Don't bother trying to synch the 'timer' call with the netupdate frequency because depending on network conditions the net updates may not actually occur at a regular interval (think of the netupdatefrequency and NetPriority as more of desired values...). Make sure 'bNetNotify' is true for the LRI to call the PostNetRecieve function (and that PostNetRecieve is simulated).
Good question about the pawn going relevant and un-relevant. Although I've tested my mod in network games, I'm not sure I would have picked up on whether that variable was being replicated properly. [EDIT] Now looking through the base actor code again, I don't think that the owner variable would be replicated to non-owning clients at all which means you will probably have to replciate it as another variable (and maybe reassign it once in a while on the server just to make sure that the clients will be updated).
Here is some sample code where I used an LRI for storing pawn location information (for radars to be used by clients) and to store loadout information. My custom HUDOverlay code does not really care about whether the pawn owner exists or not since on the client it just uses the PawnLocX, PawnLocY values to draw the radar markers (unless the pawn!=none (IE: is net relevant), in which case it uses the pawn's actual locations):
Code:
class YarmPawnRepInfo extends LinkedReplicationInfo;
var string PrimaryWeap, SecondWeap, InventoryOne, InventoryTwo;
var byte PrimPos, SecPos, Inv1Pos, Inv2Pos, PawnByte;
var int PawnLocX, PawnLocY; // this is to be used by the Radar, so that clients can see other enemies on the radar
var byte RotByte;//the rotation of this player
var Pawn myPawn;
var int CamoIdx, TeamCamoSetIdx;
var class<ym_CamoDataSet> CamoSetClass; // added 27Apr09 to allow camo set selection without needing another pawn subclass
var(ym_Camo) enum ECamoMode{ //important - order in decreasing importance
CAMO_None, // Don't apply custom camo skins
CAMO_Default, // use the camo assigned to the pawn type
CAMO_Team, // all team members share the same camo
CAMO_Custom // each player has an individual camo selection
} CamoMode;
replication
{
reliable if(bNetInitial && Role==ROLE_Authority)
CamoSetClass;
reliable if ( bNetDirty && (Role == Role_Authority))
PrimPos, SecPos, Inv1Pos, Inv2Pos, PawnByte, CamoIdx, CamoMode, TeamCamoSetIdx;// added team camo stuff here so that the admin can change this on the fly
reliable if ( bNetDirty && (Role == Role_Authority))
PawnLocX, PawnLocY, RotByte, myPawn;
// owning client sends to server
reliable if (Role < Role_Authority)
SetGear, SetGearByte, SetCamoIdx;
}
event PostBeginPlay()
{
if ( Role < ROLE_Authority )
return;
Timer();
SetTimer(2.0 + FRand(), true); //this helps the replication info from all "popping" and then having to replicate at the same time
}
simulated function SetGear(string Primary, string Secondary, string Inv1, string Inv2, string PawnName)
{
PrimaryWeap=Primary;
SecondWeap=Secondary;
InventoryOne=Inv1;
InventoryTwo=Inv2;
NetUpdateTime = Level.TimeSeconds - 1;
//TDPawnClassName=PawnName;
//bUpdate=true;
}
simulated function SetGearByte(byte Primary, byte Secondary, byte Inv1, byte Inv2, byte PawnName)
{
PrimaryWeap=class'mute_YarmWeapons'.default.Weapon1ClassNames[int(Primary)].path;
PrimPos=Primary;
SecondWeap=class'mute_YarmWeapons'.default.Weapon1ClassNames[int(Secondary)].path;
SecPos=Secondary;
//InventoryOne=Inventory1[Inv1];
Inv1Pos=Inv1;
//InventoryTwo=Inventory2[Inv2];
Inv2Pos=Inv2;
//log("TDPCI:TDPawnClassName = "$TDPawnClassName);
PawnByte=PawnName;
//bUpdate=true;
//if(Role < Role_Authority) ServerGearByte(
NetUpdateTime = Level.TimeSeconds - 1;
}
simulated function SetCamoIdx(int Idx){
if(CamoMode == CAMO_Custom) CamoIdx = Idx;
NetUpdateTime = Level.TimeSeconds - 1;
}
// oooh so bad for a network
simulated function string GetGear(int info)
{
local string item;
if (info == 0) item=PrimaryWeap;
else if (info == 1) item=SecondWeap;
else if (info == 2) item=InventoryOne;
else item=InventoryTwo;
return item;
}
// Prep some information for the client's radar etc.
function Timer(){
local yarmPawn cdp;
// update info for the radar
if ( Owner != None && yarmPawn(controller(Owner).Pawn) !=none ){
cdp = yarmPawn(controller(Owner).Pawn);
PawnLocX = cdp.Location.X;
PawnLocY = cdp.Location.Y;
RotByte = cdp.rotation.yaw / 256;
if(myPawn==none) myPawn=cdp;
}
SetTimer(1.5 + FRand(), true);
}
defaultproperties
{
NetUpdateFrequency=1
CamoSetClass=class'ym_CamoDataSet'
}
And some code (located in my mutator's 'CheckReplacement' function) for spawning the LRI. NOTE: this code does not check for other LRIs in the LRI chain from the PRI so it could break other mutator's functionality...
Code:
local PlayerReplicationInfo PRI;
local yarmPawnRepInfo YPRI;
...
// Add custom player replication info and make it first in the list
// see this thread-> http://forums.beyondunreal.com/showthread.php?t=168306&highlight=player+replication+info
if ( Other == PlayerReplicationInfo(Other) ){
PRI = PlayerReplicationInfo(Other);
if ( PRI.Owner != None && yarmPawnRepInfo(PRI.CustomReplicationInfo) == none ){
YPRI = PRI.Spawn(class'yarmPawnRepInfo', PRI.Owner);
YPRI.NextReplicationInfo = PRI.CustomReplicationInfo;
PRI.CustomReplicationInfo = YPRI;
switch( iCamoUniformMode ){
case 2:
YPRI.CamoMode = CAMO_Custom; break;
case 1:
YPRI.CamoMode = CAMO_Team; break;
Default:
YPRI.CamoMode = CAMO_Default; break;
}
if(AIController(PRI.Owner) != None && iCamoUniformMode==2){ //PRI.bBot // This will not show up until after the bots have died at least once since the PlayerReplicationInfo is spawned after the pawn!!!
//log("Set Random Camo Skin for bot "$PRI);
YPRI.CamoIdx = Rand(YPRI.CamoSetClass.default.CamoDatas.Length);
//log("Set Random Camo Skin for bot "$PRI@YPRI.CamoIdx@"from"@YPRI.CamoSetClass.default.CamoDatas.Length@"camos");
}else if(iCamoUniformMode==1 && Level.Game.bTeamGame ){ // forced team skins in a team game
if(TeamSkinSet < 0) TeamSkinSet = Rand(YPRI.CamoSetClass.default.CamoTeamDatas.Length);
YPRI.TeamCamoSetIdx = TeamSkinSet;
}
}
return true;
}
...
Bookmarks