OK, here's the process I used, per your advice:
1. Create a custom PRI
Code: Select all
class EXU2BIPRI extends PlayerReplicationInfo;
var bool bCurrentlyAlive;
var int KillCount;
var int TeamKillCount;
var int DeathCount;
var int SuicideCount;
replication
{
reliable if( Role==ROLE_Authority )
bCurrentlyAlive, KillCount, TeamKillCount, DeathCount, SuicideCount;
}
2. Implement custom PRI in GameInfo's Basemutator
Code: Select all
class EXU2CoopSettings extends EXU2GlobalSettings; // EXU2GlobalSettings is the standard BaseMutator for EXU2Game (primary GameInfo), of which EXU2CoopGame is a subclass
// Basemutator for EXU2 Coop games. Added the PRI switcheroo here; thanks gopostal for the advice!
simulated function bool AlwaysKeep( actor Other )
{
if( PlayerPawn(Other)!=None )
{
PlayerPawn(Other).PlayerReplicationInfoClass = class'EXU2BIPRI';
return True;
}
if( NextMutator!=None )
return NextMutator.AlwaysKeep(Other);
return False;
}
3. Implement checks in the GameInfo. In EXU2CoopGame, for example, I have a check in Login to mark new players as alive:
This is within the if( NewPlayer!=None ) block AND in the RestartPlayer() if( foundStart ) block
Code: Select all
if( EXU2BIPRI(NewPlayer.PlayerReplicationInfo)!=None )
EXU2BIPRI(NewPlayer.PlayerReplicationInfo).bCurrentlyAlive = True; // This defaults to false and thus must be actively set to True when a player is guaranteed to be alive (i.e. at initial login or at player restart) to ensure correct status on scoreboard
This is in Killed(), just after the call to Super.Killed
Code: Select all
if( PlayerPawn(Other)!=None && EXU2BIPRI(PlayerPawn(Other).PlayerReplicationInfo)!=None )
{
EXU2BIPRI(PlayerPawn(Other).PlayerReplicationInfo).bCurrentlyAlive = False;
EXU2BIPRI(PlayerPawn(Other).PlayerReplicationInfo).DeathCount++;
if( Killer==PlayerPawn(Other) || Killer==None )
EXU2BIPRI(PlayerPawn(Other).PlayerReplicationInfo).SuicideCount++;
}
And this is in ScoreKill() since I calculate TeamKill point devaluation there already
Code: Select all
if( PlayerPawn(Other)!=None )
{
PointValue = -2500; // PAY THE IRON PRICE
if( EXU2BIPRI(PlayerPawn(Killer).PlayerReplicationInfo)!=None )
EXU2BIPRI(PlayerPawn(Killer).PlayerReplicationInfo).TeamKillCount++;
}
And a bit below that, the kill count
Code: Select all
if( Other.IsA('EXUScriptedPawn') && class'EXUStaticFuncs'.static.bHasPawnTag(EXUScriptedPawn(Other), 'DontScore') )
PointValue = 0;
else
{
if( EXU2BIPRI(PlayerPawn(Killer).PlayerReplicationInfo)!=None )
EXU2BIPRI(PlayerPawn(Killer).PlayerReplicationInfo).KillCount++; // This IS replicated and useful
Killer.KillCount++; // This apparently is not even useful since it isn't replicated from what I can tell
}
4. Implement display of values on Scoreboard
You have your variables (among others): var Deaths[16], Suicides[16], Kills[16], TeamKills[16];
Your scoreboard loop for each player (this is actually probably really poorly optimized; I copied it almost verbatim from Unreal's coop scoreboard as a base because I was too lazy / inexperienced to write one from scratch):
Code: Select all
foreach AllActors( class'PlayerReplicationInfo', PRI )
{
if( !PRI.bIsSpectator )
{
PlayerNames[PlayerCount] = PRI.PlayerName;
TeamNames[PlayerCount] = PRI.TeamName;
Scores[PlayerCount] = PRI.Score;
Teams[PlayerCount] = PRI.Team;
Pings[PlayerCount] = PRI.Ping;
if( EXU2BIPRI(PRI)!=None )
{
Deaths[PlayerCount] = EXU2BIPRI(PRI).DeathCount;
Suicides[PlayerCount] = EXU2BIPRI(PRI).SuicideCount;
Kills[PlayerCount] = EXU2BIPRI(PRI).KillCount;
TeamKills[PlayerCount] = EXU2BIPRI(PRI).TeamKillCount;
}
if( EXU2BIPRI(PRI)!=None && !EXU2BIPRI(PRI).bCurrentlyAlive )
L = "A Corpse and/or Corpse Pieces";
else if( PRI.PlayerLocation!=None )
L = PRI.PlayerLocation.LocationName;
else if( PRI.PlayerZone!=None )
L = PRI.PlayerZone.ZoneName;
else
L = "Wandering the Hellscape";
PlayerLocations[PlayerCount] = L;
PlayerCount++;
}
}
And that's about it. Everything else that uses those variables is handled in the scoreboard in ways you'd expect (i.e. ways you can see by example or come up with on your own). Having a custom PRI is way more handy than I expected!