rott/kf_sources/Engine/Classes/GameReplicationInfo.uc
2026-07-14 20:27:09 +07:00

346 lines
11 KiB
Ucode

//=============================================================================
// GameReplicationInfo.
//=============================================================================
class GameReplicationInfo extends ReplicationInfo
native nativereplication exportstructs;
var string GameName; // Assigned by GameInfo.
var string GameClass; // Assigned by GameInfo.
var bool bTeamGame; // Assigned by GameInfo.
var bool bStopCountDown;
var bool bMatchHasBegun;
var bool bTeamSymbolsUpdated;
var bool bNoTeamSkins;
var bool bForceTeamSkins;
var bool bForceNoPlayerLights;
var bool bAllowPlayerLights;
var bool bFastWeaponSwitching;
var bool bNoTeamChanges;
var int RemainingTime, ElapsedTime, RemainingMinute;
var float SecondCount;
var int GoalScore;
var int TimeLimit;
var int MaxLives;
var int MinNetPlayers;
var float WeaponBerserk;
var TeamInfo Teams[2];
var() globalconfig string ServerName; // Name of the server, i.e.: Bob's Server.
var() globalconfig string ShortName; // Abbreviated name of server, i.e.: B's Serv (stupid example)
var() globalconfig string AdminName; // Name of the server admin.
var() globalconfig string AdminEmail; // Email address of the server admin.
var() globalconfig int ServerRegion; // Region of the game server.
var() globalconfig string MessageOfTheDay;
var() deprecated string MOTDLine1, MOTDLine2, MOTDLine3, MOTDLine4;
var Actor Winner; // set by gameinfo when game ends
var VoiceChatReplicationInfo VoiceReplicationInfo;
var() texture TeamSymbols[2];
var() array<PlayerReplicationInfo> PRIArray;
// mc - localized PlayInfo descriptions & extra info
const PROPNUM = 4;
var localized string GRIPropsDisplayText[PROPNUM];
var localized string GRIPropDescText[PROPNUM];
var vector FlagPos; // replicated 2D position of one object
var EFlagState FlagState[2];
var PlayerReplicationInfo FlagHolder[2]; // hack to work around flag holder replication FIXME remove when break net compatibility
var PlayerReplicationInfo FlagTarget; // used by Bombing Run (targeted player)
// stats
var int MatchID;
var int BotDifficulty; // for bPlayersVsBots
// Red Orchestra replication. Moved here to take advantage of native replication
// if _RO_
// Round system
var int RoundStartTime; // Time that the current round state started
var int PreStartTime; // Waiting period for players to join and settle
var int RoundDuration; // Length of a round
var int LastReinforcementTime[2]; // Time when reinforcements are allowed for both sides
var int ReinforcementInterval[2]; // Interval between reinforcement waves
var byte bReinforcementsComing[2]; // Set to 1 if reinforcements are on the way
var int ElapsedQuarterMinute; // Hack to sync the client time that works alright
var byte SpawnCount[2];
var int RoundLimit; // Number of rounds required to win the map
// Artillery system
var int LastArtyStrikeTime[2]; // Last time an artillery strike was called
var byte bArtilleryAvailable[2]; // Set to 1 if an artillery strike is available
var int ArtilleryStrikeLimit[2]; // Number of strikes available for this team
var int TotalStrikes[2]; // Total strikes that this team has called
var byte AlliesRoleCount[10]; // Total number of players with this role
var byte AxisRoleCount[10]; // Total number of players with this role
var byte AlliesRoleBotCount[10]; // Total number of bots with this role
var byte AxisRoleBotCount[10]; // Total number of bots with this role
var byte NationIndex[2];
// Map
var string UnitName[2]; // Tells the client what units are involved in the battle
var Material UnitInsignia[2];
var Material MapImage;
var vector NorthEastBounds; // This is the saved location of the Northeast corner of the map bounds
var vector SouthWestBounds; // This is the saved location of the Southwest corner of the map bounds
var int OverheadOffset; // The offset that the real map is relative to the overhead map
var bool bPlayerMustReady; // This game uses "ready to start" code
var byte MaxPlayers; // Maximum amount of players allowed in the game(Read from GameInfo's MaxPlayers setting)
// end _RO_
replication
{
reliable if ( bNetDirty && (Role == ROLE_Authority) )
bStopCountDown, Winner, Teams, FlagPos, FlagState, bMatchHasBegun, MatchID, FlagTarget;
reliable if ( !bNetInitial && bNetDirty && (Role == ROLE_Authority) )
RemainingMinute;
reliable if ( bNetInitial && (Role==ROLE_Authority) )
GameName, GameClass, bTeamGame, bNoTeamSkins, bForceTeamSkins, bForceNoPlayerLights, WeaponBerserk, bAllowPlayerLights, bFastWeaponSwitching,
RemainingTime, ElapsedTime, MessageOfTheDay, ServerName, ShortName, AdminName,
AdminEmail, ServerRegion, GoalScore, MaxLives, TimeLimit, TeamSymbols,
VoiceReplicationInfo, MinNetPlayers, bNoTeamChanges,BotDifficulty;
// if _RO_
reliable if (bNetDirty && (Role == ROLE_Authority))
RoundStartTime, LastReinforcementTime, bReinforcementsComing, ElapsedQuarterMinute, SpawnCount, LastArtyStrikeTime,
bArtilleryAvailable, TotalStrikes, AlliesRoleCount, AxisRoleCount, AlliesRoleBotCount, AxisRoleBotCount, MaxPlayers;
reliable if (bNetInitial && (Role == ROLE_Authority))
PreStartTime, RoundDuration, ReinforcementInterval, UnitName, MapImage, UnitInsignia, NationIndex, OverheadOffset,
ArtilleryStrikeLimit, bPlayerMustReady, NorthEastBounds, SouthWestBounds, RoundLimit;
// end _RO_
}
simulated function PostNetBeginPlay()
{
local PlayerReplicationInfo PRI;
Level.GRI = self;
if ( VoiceReplicationInfo == None )
foreach DynamicActors(class'VoiceChatReplicationInfo', VoiceReplicationInfo)
break;
ForEach DynamicActors(class'PlayerReplicationInfo',PRI)
AddPRI(PRI);
if ( Level.NetMode == NM_Client )
TeamSymbolNotify();
}
simulated function TeamSymbolNotify()
{
local Actor A;
if ( TeamSymbols[0] == None )
return;
bTeamSymbolsUpdated = true;
ForEach AllActors(class'Actor', A)
A.SetGRI(self);
}
simulated function UpdatePrecacheMaterials()
{
Level.AddPrecacheMaterial(TeamSymbols[0]);
Level.AddPrecacheMaterial(TeamSymbols[1]);
}
simulated function PostBeginPlay()
{
super.PostBeginPlay();
MessageOfTheDay = repl(MessageOfTheDay, chr(160),' ');
if( Level.NetMode == NM_Client )
{
// clear variables so we don't display our own values if the server has them left blank
ServerName = "";
AdminName = "";
AdminEmail = "";
MessageOfTheDay = "";
}
SecondCount = Level.TimeSeconds;
SetTimer(Level.TimeDilation, true);
}
/* Reset()
reset actor to initial state - used when restarting level without reloading.
*/
function Reset()
{
Super.Reset();
Winner = None;
}
simulated function Timer()
{
local int i;
local PlayerReplicationInfo OldHolder[2];
local Controller C;
if ( Level.NetMode == NM_Client )
{
ElapsedTime++;
if ( RemainingMinute != 0 )
{
RemainingTime = RemainingMinute;
RemainingMinute = 0;
}
if ( (RemainingTime > 0) && !bStopCountDown )
RemainingTime--;
if ( !bTeamSymbolsUpdated )
TeamSymbolNotify();
SetTimer(Level.TimeDilation, true);
}
else if ( Level.NetMode != NM_Standalone )
{
OldHolder[0] = FlagHolder[0];
OldHolder[1] = FlagHolder[1];
FlagHolder[0] = None;
FlagHolder[1] = None;
for ( i=0; i<PRIArray.length; i++ )
if ( (PRIArray[i].HasFlag != None) && (PRIArray[i].Team != None) )
FlagHolder[PRIArray[i].Team.TeamIndex] = PRIArray[i];
for ( i=0; i<2; i++ )
if ( OldHolder[i] != FlagHolder[i] )
{
for ( C=Level.ControllerList; C!=None; C=C.NextController )
if ( PlayerController(C) != None )
PlayerController(C).ClientUpdateFlagHolder(FlagHolder[i],i);
}
}
}
simulated function PlayerReplicationInfo FindPlayerByID( int PlayerID )
{
local int i;
for( i=0; i<PRIArray.Length; i++ )
{
if( PRIArray[i].PlayerID == PlayerID )
return PRIArray[i];
}
return None;
}
simulated function AddPRI(PlayerReplicationInfo PRI)
{
local byte NewVoiceID;
local int i;
if ( Level.NetMode == NM_ListenServer || Level.NetMode == NM_DedicatedServer )
{
for (i = 0; i < PRIArray.Length; i++)
{
if ( PRIArray[i].VoiceID == NewVoiceID )
{
i = -1;
NewVoiceID++;
continue;
}
}
if ( NewVoiceID >= 32 )
NewVoiceID = 0;
PRI.VoiceID = NewVoiceID;
}
PRIArray[PRIArray.Length] = PRI;
}
simulated function RemovePRI(PlayerReplicationInfo PRI)
{
local int i;
for (i=0; i<PRIArray.Length; i++)
{
if (PRIArray[i] == PRI)
{
PRIArray.Remove(i,1);
return;
}
}
log("GameReplicationInfo::RemovePRI() pri="$PRI$" not found.", 'Error');
}
simulated function GetPRIArray(out array<PlayerReplicationInfo> pris)
{
local int i;
local int num;
pris.Remove(0, pris.Length);
for (i=0; i<PRIArray.Length; i++)
{
if (PRIArray[i] != None)
pris[num++] = PRIArray[i];
}
}
static function FillPlayInfo(PlayInfo PlayInfo)
{
local int i;
Super.FillPlayInfo(PlayInfo); // Always begin with calling parent
PlayInfo.AddSetting(default.ServerGroup, "ServerName", default.GRIPropsDisplayText[i++], 255, 1, "Text", "60",,True);
PlayInfo.AddSetting(default.ServerGroup, "AdminName", default.GRIPropsDisplayText[i++], 255, 1, "Text", "40",,True,True);
PlayInfo.AddSetting(default.ServerGroup, "AdminEmail", default.GRIPropsDisplayText[i++], 255, 1, "Text", "60",,True,True);
PlayInfo.AddSetting(default.ServerGroup, "MessageOfTheDay", default.GRIPropsDisplayText[i++], 251, 1, "Custom","255;;GUI2K4.MOTDConfigPage",,True,True);
}
static event string GetDescriptionText(string PropName)
{
switch (PropName)
{
case "ServerName": return default.GRIPropDescText[0];
case "AdminName": return default.GRIPropDescText[1];
case "AdminEmail": return default.GRIPropDescText[2];
case "MessageOfTheDay": return default.GRIPropDescText[3];
}
return Super.GetDescriptionText(PropName);
}
defaultproperties
{
FlagState[0]=FLAG_Home
FlagState[1]=FLAG_Home
bStopCountDown=true
RemoteRole=ROLE_SimulatedProxy
bAlwaysRelevant=True
ServerName="Killing Floor Server"
ShortName="Server"
MessageOfTheDay=""
AdminEmail="Non-disclosed"
GRIPropsDisplayText(0)="Server Name"
GRIPropsDisplayText(1)="Admin Name"
GRIPropsDisplayText(2)="Admin E-Mail"
GRIPropsDisplayText(3)="MOTD"
GRIPropDescText(0)="Server name shown on server browser."
GRIPropDescText(1)="Server administrator's name"
GRIPropDescText(2)="Server administrator's email address."
GRIPropDescText(3)="Message of the Day"
WeaponBerserk=+1.0
BotDifficulty=-1
}