Engine
Class GameInfo

source: e:\games\UnrealTournament\Engine\Classes\GameInfo.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Info
         |
         +--Engine.GameInfo
Direct Known Subclasses:TournamentGameInfo, MovieInfo, UnrealGameInfo

class GameInfo
extends Engine.Info

//============================================================================= // GameInfo. // // default game info is normal single player // //=============================================================================
Variables
 string AdminPassword
           Password to receive bAdmin privileges.
 float AutoAim
           How much autoaiming to do (1 = none, 0 = always).
 Mutator BaseMutator
           Identifying string used for finding LAN servers.
 string BeaconName
           Identifying string used for finding LAN servers.
 string BotMenuType
           Type of bot menu to display.
 int CurrentID
           Identifying string used for finding LAN servers.
 class DMMessageClass
           Identifying string used for finding LAN servers.
 Mutator DamageMutator
           linked list of mutators which affect damage
 class DeathMessageClass
           Identifying string used for finding LAN servers.
 class DefaultPlayerClass
           Scale applied to game rate.
 string DefaultPlayerName
           Identifying string used for finding LAN servers.
 name DefaultPlayerState
           linked list of mutators which get localized message queries
 class DefaultWeapon
           Default weapon given to player at start.
 int DemoBuild
           Does this gametype log?
 int DemoHasTuts
           Does this gametype log?
 byte Difficulty
           0=easy, 1=medium, 2=hard, 3=very hard.
 string EnabledMutators
           Does this gametype log?
 string EnteredMessage
           Identifying string used for finding LAN servers.
 string FailedPlaceMessage
           Identifying string used for finding LAN servers.
 string FailedSpawnMessage
           Identifying string used for finding LAN servers.
 string FailedTeamMessage
           Identifying string used for finding LAN servers.
 class GameMenuType
           Type of oldstyle game options menu to display.
 string GameName
           Identifying string used for finding LAN servers.
 string GameOptionsMenuType
           Type of options dropdown to display.
 string GamePassword
           Password to enter game.
 GameReplicationInfo GameReplicationInfo
           linked list of mutators which get localized message queries
 class GameReplicationInfoClass
           linked list of mutators which get localized message queries
 float GameSpeed
           Scale applied to game rate.
 string GameUMenuType
           Type of Game dropdown to display.
 class HUDType
           HUD class this game uses.
 string IPPolicies[50]
           Identifying string used for finding LAN servers.
 string LeftMessage
           Identifying string used for finding LAN servers.
 StatLog LocalLog
           linked list of mutators which get localized message queries
 string LocalLogFileName
           Does this gametype log?
 class MapListType
           Maplist this game uses.
 string MapPrefix
           Prefix characters for names of maps for this game type.
 int MaxPlayers
           Identifying string used for finding LAN servers.
 int MaxSpectators
           Maximum number of spectators.
 Mutator MessageMutator
           linked list of mutators which get localized message queries
 string MultiplayerUMenuType
           Type of Multiplayer dropdown to display.
 class MutatorClass
           Identifying string used for finding LAN servers.
 string NameChangedMessage
           Identifying string used for finding LAN servers.
 int NumPlayers
           Identifying string used for finding LAN servers.
 string RulesMenuType
           Type of rules menu to display.
 class ScoreBoardType
           Type of scoreboard this game uses.
 KillGoals, SecretGoals
           Special game goals.
 string ServerLogName
           linked list of mutators which get localized message queries
 string SettingsMenuType
           Type of settings menu to display.
 string SpecialDamageString
           Identifying string used for finding LAN servers.
 float StartTime
           Scale applied to game rate.
 class StatLogClass
           Does this gametype log?
 string SwitchLevelMessage
           Identifying string used for finding LAN servers.
 class WaterZoneType
           linked list of mutators which get localized message queries
 StatLog WorldLog
           linked list of mutators which get localized message queries
 string WorldLogFileName
           Does this gametype log?
 bool bAllowFOV
           Allows FOV changes in net games
 bool bAlternateMode
           This game is some type of deathmatch (where players can respawn during gameplay)
 bool bBatchLocal
           linked list of mutators which get localized message queries
 bool bClassicDeathmessages
           Weapon deathmessages if false.
 bool bCoopWeaponMode
           Whether or not weapons stay when picked up.
 bool bDeathMatch
           This game is some type of deathmatch (where players can respawn during gameplay)
 bool bExternalBatcher
           This game is some type of deathmatch (where players can respawn during gameplay)
 bool bHumansOnly
           Whether non human player models are allowed.
 bool bLocalLog
           linked list of mutators which get localized message queries
 bool bLoggingGame
           Does this gametype log?
 bool bLowGore
           Whether or not to reduce gore.
 bool bMuteSpectators
           Whether spectators are allowed to speak.
 bool bNoCheating
           Disallows cheating. Hehe.
 bool bNoMonsters
           Whether monsters are allowed in this play mode.
 bool bPauseable
           Whether the level is pauseable.
 bool bRestartLevel
           Whether non human player models are allowed.
 bool bTeamGame
           This is a teamgame.
 bool bWorldLog
           linked list of mutators which get localized message queries


Function Summary
 bool AddBot()
     
//
// Add bot to game.
//
 void AddDefaultInventory(Pawn PlayerPawn)
     
//
// Spawn any default inventory for the player.
//
 void AdminLogin(PlayerPawn P, string Password)
     
//------------------------------------------------------------------------------
// Admin
 void AdminLogout(PlayerPawn P)
 bool AllowsBroadcast(Actor broadcaster, int Len)
     
//
// Whether players are allowed to broadcast messages now.
//
 bool AtCapacity(string Options)
 void BroadcastRegularDeathMessage(Pawn Killer, Pawn Other, name damageType)
 bool CanSpectate(Pawn Viewer, Actor ViewTarget)
     
//
// Return whether Viewer is allowed to spectate from the
// point of view of ViewTarget.
//
 void ChangeName(Pawn Other, string S, bool bNameChange)
     
//
// Try to change a player's name.
//	
 bool ChangeTeam(Pawn Other, int N)
     
//
// Return whether a team change is allowed.
//
 bool CheckIPPolicy(string Address)
 string CreatureKillMessage(name damageType, Pawn Other)
     
//
// Generate a killed by creature message.
//
 void DiscardInventory(Pawn Other)
     
//
// Discard a player's inventory after he dies.
//
 void EndGame(string Reason)
     
//
// End of game.
//
 NavigationPoint FindPlayerStart(Pawn Player, optional byte, optional string)
     
//
// Return the 'best' player start for this player to start from.
// Re-implement for each game type.
//
 bool ForceAddBot()
 string GetInfo()
     
//------------------------------------------------------------------------------
// Game Querying.
 int GetIntOption(string Options, string ParseString, int CurrentValue)
 void GetKeyValue(string Pair, out string, out string)
     
//
// Break up a key=value pair into its key and value.
//
 string GetNetworkNumber()
 string GetRules()
 int GetServerPort()
     
// Return the server's port number.
 bool GrabOption(out string, out string)
     
//
// Grab the next option from a string.
//
 bool HasOption(string Options, string InKey)
     
//
// See if an option was specified in the options string.
//
 void InitGameReplicationInfo()
     
//------------------------------------------------------------------------------
// Replication
 void InitLogging()
 bool IsRelevant(Actor Other)
     
//
// Return whether an actor should be destroyed in
// this type of game.
//	
 string KillMessage(name damageType, Pawn Other)
     
//
// Default death message.
//
 void Killed(Pawn Killer, Pawn Other, name damageType)
     
//------------------------------------------------------------------------------
// Level death message functions.
 void LogGameParameters(StatLog StatLog)
     
//------------------------------------------------------------------------------
// Stat Logging.
 void Logout(Pawn Exiting)
     
//
// Pawn exits.
//
 string ParseKillMessage(string KillerName, string VictimName, string WeaponName, string DeathMessage)
     
// %k = Owner's PlayerName (Killer)
// %o = Other's PlayerName (Victim)
// %w = Owner's Weapon ItemName
 string ParseOption(string Options, string InKey)
     
//
// Find an option in the options string and return it.
//
 bool PickupQuery(Pawn Other, Inventory item)
     
//
// Called when pawn has a chance to pick Item up (i.e. when 
// the pawn touches a weapon pickup). Should return true if 
// he wants to pick it up, false if he does not want it.
//
 float PlaySpawnEffect(Inventory Inv)
     
//
// Play an inventory respawn effect.
//
 void PlayTeleportEffect(Actor Incoming, bool bOut, bool bSound)
     
//
// Play a teleporting special effect.
//
 float PlayerJumpZScaling()
     
// Return the player jumpZ scaling for this gametype
 string PlayerKillMessage(name damageType, PlayerReplicationInfo Other)
     
//
// Generate a player killled message.
//
 void PostBeginPlay()
 void PreBeginPlay()
     
//------------------------------------------------------------------------------
// Engine notifications.
 void ProcessServerTravel(string URL, bool bItems)
     
//
// Optional handling of ServerTravel for network games.
//
 int ReduceDamage(int Damage, name DamageType, Pawn injured, Pawn instigatedBy)
     
//
// Use reduce damage for teamplay modifications, etc.
//
 void RegisterDamageMutator(Mutator M)
 void RegisterMessageMutator(Mutator M)
 void ResetGame()
 void RestartGame()
     
//
// Restart the game.
//
 bool RestartPlayer(Pawn aPlayer)
     
//
// Restart a player.
//
 void ScoreEvent(name EventName, Actor EventActor, Pawn InstigatedBy)
     
//
// Award a score to an actor.
//
 void ScoreKill(Pawn Killer, Pawn Other)
 void SendPlayer(PlayerPawn aPlayer, string URL)
     
//
// Send a player to a URL.
//
 bool SetEndCams(string Reason)
 void SetGameSpeed(Float T)
     
//
// Set gameplay speed.
//
 bool SetPause(BOOL bPause, PlayerPawn P)
 bool ShouldRespawn(Actor Other)
     
//
// Return whether an item should respawn.
//
 void StartPlayer(PlayerPawn Other)
     
//
// Start a player.
//
 void Timer()



Source Code


00001	//=============================================================================
00002	// GameInfo.
00003	//
00004	// default game info is normal single player
00005	//
00006	//=============================================================================
00007	class GameInfo extends Info
00008		native;
00009	
00010	//-----------------------------------------------------------------------------
00011	// Variables.
00012	
00013	var int ItemGoals, KillGoals, SecretGoals;				// Special game goals.
00014	var byte  Difficulty;									// 0=easy, 1=medium, 2=hard, 3=very hard.
00015	var() config bool   		  bNoMonsters;				// Whether monsters are allowed in this play mode.
00016	var() globalconfig bool		  bMuteSpectators;			// Whether spectators are allowed to speak.
00017	var() config bool			  bHumansOnly;				// Whether non human player models are allowed.
00018	var() bool				      bRestartLevel;	
00019	var() bool				      bPauseable;				// Whether the level is pauseable.
00020	var() config bool			  bCoopWeaponMode;			// Whether or not weapons stay when picked up.
00021	var() config bool			  bClassicDeathmessages;	// Weapon deathmessages if false.
00022	var   globalconfig bool	      bLowGore;					// Whether or not to reduce gore.
00023	var	  bool				      bCanChangeSkin;			// Allow player to change skins in game.
00024	var() bool				      bTeamGame;				// This is a teamgame.
00025	var	  globalconfig bool	      bVeryLowGore;				// Greatly reduces gore.
00026	var() globalconfig bool       bNoCheating;				// Disallows cheating. Hehe.
00027	var() globalconfig bool       bAllowFOV;				// Allows FOV changes in net games
00028	var() bool					  bDeathMatch;				// This game is some type of deathmatch (where players can respawn during gameplay)
00029	var	  bool					  bGameEnded;				// set when game ends
00030	var	  bool					  bOverTime;
00031	var localized bool			  bAlternateMode;
00032	var		bool				  bCanViewOthers;
00033	var   globalconfig bool		  bExternalBatcher;
00034	
00035	var() globalconfig float	  AutoAim;					// How much autoaiming to do (1 = none, 0 = always).
00036															// (cosine of max error to correct)
00037	
00038	var() globalconfig float	  GameSpeed;				// Scale applied to game rate.
00039	var   float                   StartTime;
00040	
00041	var() class<playerpawn>       DefaultPlayerClass;
00042	var() class<weapon>           DefaultWeapon;			// Default weapon given to player at start.
00043	
00044	var() globalconfig int	      MaxSpectators;			// Maximum number of spectators.
00045	var	  int					  NumSpectators;			// Current number of spectators.
00046	
00047	var() private globalconfig string AdminPassword;	    // Password to receive bAdmin privileges.
00048	var() private globalconfig string GamePassword;		    // Password to enter game.
00049	
00050	var() class<scoreboard>		  ScoreBoardType;			// Type of scoreboard this game uses.
00051	var() class<menu>			  GameMenuType;				// Type of oldstyle game options menu to display.
00052	var() string			      BotMenuType;				// Type of bot menu to display.
00053	var() string			      RulesMenuType;			// Type of rules menu to display.
00054	var() string				  SettingsMenuType;			// Type of settings menu to display.
00055	var() string				  GameUMenuType;			// Type of Game dropdown to display.
00056	var() string				  MultiplayerUMenuType;		// Type of Multiplayer dropdown to display.
00057	var() string				  GameOptionsMenuType;		// Type of options dropdown to display.
00058	
00059	var() class<hud>			  HUDType;					// HUD class this game uses.
00060	var() class<MapList>		  MapListType;				// Maplist this game uses.
00061	var() string			      MapPrefix;				// Prefix characters for names of maps for this game type.
00062	var() string			      BeaconName;				// Identifying string used for finding LAN servers.
00063	var() string			      SpecialDamageString;
00064	var localized string	      SwitchLevelMessage;
00065	var	int					      SentText;
00066	var localized string	      DefaultPlayerName;
00067	var localized string	      LeftMessage;
00068	var localized string	      FailedSpawnMessage;
00069	var localized string	      FailedPlaceMessage;
00070	var localized string	      FailedTeamMessage;
00071	var localized string	      NameChangedMessage;
00072	var localized string	      EnteredMessage;
00073	var localized string	      GameName;
00074	var	localized string	      MaxedOutMessage;
00075	var	localized string	      WrongPassword;
00076	var	localized string          NeedPassword;
00077	var	localized string          IPBanned;
00078	
00079	var() globalconfig int		  MaxPlayers; 
00080	var   int					  NumPlayers;
00081	var   int					  CurrentID;
00082	var() globalconfig string     IPPolicies[50];
00083	
00084	// Message classes.
00085	var class<LocalMessage>		  DeathMessageClass;
00086	var class<LocalMessage>		  DMMessageClass;
00087	
00088	// Mutator (for modifying actors as they enter the game)
00089	var class<Mutator> MutatorClass;
00090	var Mutator BaseMutator;
00091	var Mutator DamageMutator;	// linked list of mutators which affect damage
00092	var Mutator MessageMutator; // linked list of mutators which get localized message queries
00093	
00094	// Default waterzone entry and exit effects
00095	var class<ZoneInfo> WaterZoneType;
00096	
00097	// What state a player should start in for this game type
00098	var name DefaultPlayerState;
00099	
00100	// ReplicationInfo
00101	var() class<GameReplicationInfo> GameReplicationInfoClass;
00102	var GameReplicationInfo GameReplicationInfo;
00103	
00104	// Server Log
00105	var globalconfig string         ServerLogName;
00106	
00107	// Statistics Logging
00108	var StatLog						LocalLog;
00109	var StatLog						WorldLog;
00110	var globalconfig bool			bLocalLog;
00111	var globalconfig bool			bWorldLog;
00112	var globalconfig bool			bBatchLocal;
00113	var bool						bLoggingGame;			// Does this gametype log?
00114	var string					    LocalLogFileName;
00115	var string					    WorldLogFileName;
00116	var class<StatLog>				StatLogClass;
00117	
00118	// Demo Information
00119	var globalconfig int DemoBuild;
00120	var globalconfig int DemoHasTuts;
00121	
00122	// Server query info
00123	var string EnabledMutators;
00124	
00125	
00126	//------------------------------------------------------------------------------
00127	// Admin
00128	
00129	function AdminLogin( PlayerPawn P, string Password )
00130	{
00131		if (AdminPassword == "")
00132			return;
00133	
00134		if (Password == AdminPassword)
00135		{
00136			P.bAdmin = True;
00137			P.PlayerReplicationInfo.bAdmin = P.bAdmin;
00138			Log("Administrator logged in.");
00139			BroadcastMessage( P.PlayerReplicationInfo.PlayerName@"became a server administrator." );
00140		}
00141	}
00142	
00143	function AdminLogout( PlayerPawn P )
00144	{
00145		local float OldScore;
00146	
00147		if (P.bAdmin)
00148		{
00149			P.bAdmin = False;
00150			P.PlayerReplicationInfo.bAdmin = P.bAdmin;
00151			if ( P.ReducedDamageType == 'All' )
00152				P.ReducedDamageType = '';
00153			P.StartWalk();
00154			OldScore = P.PlayerReplicationInfo.Score;
00155			P.Suicide();
00156			P.PlayerReplicationInfo.Score = OldScore;
00157			Log("Administrator logged out.");
00158			BroadcastMessage( P.PlayerReplicationInfo.PlayerName@"gave up administrator abilities." );
00159		}
00160	}
00161	
00162	//------------------------------------------------------------------------------
00163	// Engine notifications.
00164	
00165	function PreBeginPlay()
00166	{
00167		StartTime = 0;
00168		SetGameSpeed(GameSpeed);
00169		Level.bNoCheating = bNoCheating;
00170		Level.bAllowFOV = bAllowFOV;
00171		
00172		if (GameReplicationInfoClass != None)
00173			GameReplicationInfo = Spawn(GameReplicationInfoClass);
00174		else
00175			GameReplicationInfo = Spawn(class'GameReplicationInfo');
00176		InitGameReplicationInfo();
00177	}
00178	
00179	function PostBeginPlay()
00180	{
00181		local ZoneInfo W;
00182	
00183		if ( bAlternateMode )
00184		{
00185			bLowGore = true;
00186			bVeryLowGore = true;
00187		}
00188	
00189		if ( bVeryLowGore )
00190			bLowGore = true;
00191	
00192		if ( WaterZoneType != None )
00193		{
00194			ForEach AllActors(class'ZoneInfo', W )
00195				if ( W.bWaterZone )
00196				{
00197					if( W.EntryActor == None )
00198						W.EntryActor = WaterZoneType.Default.EntryActor;
00199					if( W.ExitActor == None )
00200						W.ExitActor = WaterZoneType.Default.ExitActor;
00201					if( W.EntrySound == None )
00202						W.EntrySound = WaterZoneType.Default.EntrySound;
00203					if( W.ExitSound == None )
00204						W.ExitSound = WaterZoneType.Default.ExitSound;
00205				}
00206		}
00207	
00208		// Setup local statistics logging.
00209		InitLogging();
00210	
00211		Super.PostBeginPlay();
00212	}
00213	
00214	function InitLogging()
00215	{
00216		local Mutator M;
00217	
00218		if (bLocalLog && bLoggingGame)
00219		{
00220			Log("Initiating local logging...");
00221			LocalLog = spawn(StatLogClass);
00222			LocalLog.bWorld = False;
00223			LocalLog.StartLog();
00224			LocalLog.LogStandardInfo();
00225			LocalLog.LogServerInfo();
00226			LocalLog.LogMapParameters();
00227			for (M = BaseMutator; M != None; M = M.NextMutator)
00228				LocalLog.LogMutator(M);
00229			LogGameParameters(LocalLog);
00230			LocalLogFileName = LocalLog.GetLogFileName();
00231		}
00232	
00233		// Setup world statistics logging.
00234		if ((Level.NetMode != NM_DedicatedServer) && (Level.NetMode != NM_ListenServer))
00235			return;
00236	
00237		if (bWorldLog && bLoggingGame)
00238		{
00239			Log("Initiating world logging...");
00240			WorldLog = spawn(StatLogClass);
00241			WorldLog.bWorld = True;
00242			WorldLog.StartLog();
00243			WorldLog.LogStandardInfo();
00244			WorldLog.LogServerInfo();
00245			WorldLog.LogMapParameters();
00246			WorldLog.InitialCheck(Self);
00247			for (M = BaseMutator; M != None; M = M.NextMutator)
00248				WorldLog.LogMutator(M);
00249			LogGameParameters(WorldLog);
00250			WorldLogFileName = WorldLog.GetLogFileName();
00251		}
00252	}
00253	
00254	function Timer()
00255	{
00256		SentText = 0;
00257	}
00258	
00259	// Called when game shutsdown.
00260	event GameEnding()
00261	{
00262		if (LocalLog != None)
00263		{
00264			LocalLog.LogGameEnd("serverquit");
00265			LocalLog.StopLog();
00266			LocalLog.Destroy();
00267			LocalLog = None;
00268		}
00269	
00270		if (WorldLog != None)
00271		{
00272			WorldLog.LogGameEnd("serverquit");
00273			WorldLog.StopLog();
00274			WorldLog.Destroy();
00275			WorldLog = None;
00276		}
00277	}
00278	
00279	//------------------------------------------------------------------------------
00280	// Replication
00281	
00282	function InitGameReplicationInfo()
00283	{
00284		GameReplicationInfo.bTeamGame = bTeamGame;
00285		GameReplicationInfo.GameName = GameName;
00286		GameReplicationInfo.GameClass = string(Class);
00287		GameReplicationInfo.bClassicDeathmessages = bClassicDeathmessages;
00288	}
00289	
00290	native function string GetNetworkNumber();
00291	
00292	//------------------------------------------------------------------------------
00293	// Game Querying.
00294	
00295	function string GetInfo()
00296	{
00297		local string ResultSet;
00298	
00299		// World logging enabled and working
00300		if ( WorldLog != None && !WorldLog.bWorldBatcherError )
00301			ResultSet = "\\worldlog\\true";
00302		else
00303			ResultSet = "\\worldlog\\false";
00304	
00305		// World logging activated
00306		if ( WorldLog != None )
00307			ResultSet = ResultSet$"\\wantworldlog\\true";
00308		else
00309			ResultSet = ResultSet$"\\wantworldlog\\false";
00310	
00311		return ResultSet;
00312	}
00313	
00314	function string GetRules()
00315	{
00316		local string ResultSet;
00317		local Mutator M;
00318		local string NextMutator, NextDesc;
00319		local int Num, i;
00320	
00321		ResultSet = "";
00322	
00323		if( EnabledMutators == "" )
00324		{
00325			for (M = BaseMutator.NextMutator; M != None; M = M.NextMutator)
00326			{
00327				Num = 0;
00328				NextMutator = "";
00329				GetNextIntDesc("Engine.Mutator", 0, NextMutator, NextDesc);
00330				while( (NextMutator != "") && (Num < 50) )
00331				{
00332					if(NextMutator ~= string(M.Class))
00333					{
00334						i = InStr(NextDesc, ",");
00335						if(i != -1)
00336							NextDesc = Left(NextDesc, i);
00337	
00338						if(EnabledMutators != "")
00339							EnabledMutators = EnabledMutators $ ", ";
00340						 EnabledMutators = EnabledMutators $ NextDesc;
00341						 break;
00342					}
00343					
00344					Num++;
00345					GetNextIntDesc("Engine.Mutator", Num, NextMutator, NextDesc);
00346				}
00347			}
00348			if(EnabledMutators != "")
00349				ResultSet = ResultSet $ "\\mutators\\"$EnabledMutators;
00350		}
00351	
00352		ResultSet = ResultSet $ "\\listenserver\\"$string(Level.NetMode==NM_ListenServer);
00353	
00354		return ResultSet;
00355	}
00356	
00357	// Return the server's port number.
00358	function int GetServerPort()
00359	{
00360		local string S;
00361		local int i;
00362	
00363		// Figure out the server's port.
00364		S = Level.GetAddressURL();
00365		i = InStr( S, ":" );
00366		assert(i>=0);
00367		return int(Mid(S,i+1));
00368	}
00369	
00370	function bool SetPause( BOOL bPause, PlayerPawn P )
00371	{
00372		if( bPauseable || P.bAdmin || Level.Netmode==NM_Standalone )
00373		{
00374			if( bPause )
00375				Level.Pauser=P.PlayerReplicationInfo.PlayerName;
00376			else
00377				Level.Pauser="";
00378			return True;
00379		}
00380		else return False;
00381	}
00382	
00383	//------------------------------------------------------------------------------
00384	// Stat Logging.
00385	
00386	function LogGameParameters(StatLog StatLog)
00387	{
00388		if (StatLog == None)
00389			return;
00390	
00391		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"GameName"$Chr(9)$GameName);
00392		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"GameClass"$Chr(9)$Class);// <-- Move to c++
00393		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"GameVersion"$Chr(9)$Level.EngineVersion);
00394		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"MinNetVersion"$Chr(9)$Level.MinNetVersion);
00395		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"NoMonsters"$Chr(9)$bNoMonsters);
00396		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"MuteSpectators"$Chr(9)$bMuteSpectators);
00397		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"HumansOnly"$Chr(9)$bHumansOnly);
00398		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"WeaponsStay"$Chr(9)$bCoopWeaponMode);
00399		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"ClassicDeathmessages"$Chr(9)$bClassicDeathmessages);
00400		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"LowGore"$Chr(9)$bLowGore);
00401		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"VeryLowGore"$Chr(9)$bVeryLowGore);
00402		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"TeamGame"$Chr(9)$bTeamGame);
00403		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"GameSpeed"$Chr(9)$int(GameSpeed*100));
00404		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"MaxSpectators"$Chr(9)$MaxSpectators);
00405		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"MaxPlayers"$Chr(9)$MaxPlayers);
00406	}
00407	
00408	//------------------------------------------------------------------------------
00409	// Game parameters.
00410	
00411	//
00412	// Set gameplay speed.
00413	//
00414	function SetGameSpeed( Float T )
00415	{
00416		GameSpeed = FMax(T, 0.1);
00417		Level.TimeDilation = GameSpeed;
00418		SetTimer(Level.TimeDilation, true);
00419	}
00420	
00421	static function ResetGame();
00422	
00423	//
00424	// Called after setting low or high detail mode.
00425	//
00426	event DetailChange()
00427	{
00428		local actor A;
00429		local zoneinfo Z;
00430		local skyzoneinfo S;
00431		if( !Level.bHighDetailMode )
00432		{
00433			foreach AllActors(class'Actor', A)
00434			{
00435				if( A.bHighDetail && !A.bGameRelevant )
00436					A.Destroy();
00437			}
00438		}
00439		foreach AllActors(class'ZoneInfo', Z)
00440			Z.LinkToSkybox();
00441	}
00442	
00443	//
00444	// Return whether an actor should be destroyed in
00445	// this type of game.
00446	//	
00447	function bool IsRelevant( actor Other )
00448	{
00449		local byte bSuperRelevant;
00450	
00451		// let the mutators mutate the actor or choose to remove it
00452		if ( BaseMutator.AlwaysKeep(Other) )
00453			return true;
00454		if ( BaseMutator.IsRelevant(Other, bSuperRelevant) )
00455		{
00456			if ( bSuperRelevant == 1 ) // mutator wants to override any logic in here
00457				return true;
00458		}
00459		else return false;
00460	
00461		if
00462		(	(Difficulty==0 && !Other.bDifficulty0 )
00463		||  (Difficulty==1 && !Other.bDifficulty1 )
00464		||  (Difficulty==2 && !Other.bDifficulty2 )
00465		||  (Difficulty==3 && !Other.bDifficulty3 )
00466		||  (!Other.bSinglePlayer && (Level.NetMode==NM_Standalone) ) 
00467		||  (!Other.bNet && ((Level.NetMode == NM_DedicatedServer) || (Level.NetMode == NM_ListenServer)) )
00468		||  (!Other.bNetSpecial  && (Level.NetMode==NM_Client)) )
00469			return False;
00470	
00471		if( bNoMonsters && (Pawn(Other) != None) && !Pawn(Other).bIsPlayer )
00472			return False;
00473	
00474		if( FRand() > Other.OddsOfAppearing )
00475			return False;
00476	
00477	    // Update the level info goal counts.
00478	    if( Other.bIsSecretGoal )
00479	       SecretGoals++;
00480	
00481	    if( Other.bIsItemGoal )
00482	       ItemGoals++;
00483	
00484	    if( Other.bIsKillGoal )
00485	       KillGoals++;
00486	
00487		return True;
00488	}
00489	
00490	//------------------------------------------------------------------------------
00491	// Player start functions
00492	
00493	//
00494	// Grab the next option from a string.
00495	//
00496	function bool GrabOption( out string Options, out string Result )
00497	{
00498		if( Left(Options,1)=="?" )
00499		{
00500			// Get result.
00501			Result = Mid(Options,1);
00502			if( InStr(Result,"?")>=0 )
00503				Result = Left( Result, InStr(Result,"?") );
00504	
00505			// Update options.
00506			Options = Mid(Options,1);
00507			if( InStr(Options,"?")>=0 )
00508				Options = Mid( Options, InStr(Options,"?") );
00509			else
00510				Options = "";
00511	
00512			return true;
00513		}
00514		else return false;
00515	}
00516	
00517	//
00518	// Break up a key=value pair into its key and value.
00519	//
00520	function GetKeyValue( string Pair, out string Key, out string Value )
00521	{
00522		if( InStr(Pair,"=")>=0 )
00523		{
00524			Key   = Left(Pair,InStr(Pair,"="));
00525			Value = Mid(Pair,InStr(Pair,"=")+1);
00526		}
00527		else
00528		{
00529			Key   = Pair;
00530			Value = "";
00531		}
00532	}
00533	
00534	//
00535	// See if an option was specified in the options string.
00536	//
00537	function bool HasOption( string Options, string InKey )
00538	{
00539		local string Pair, Key, Value;
00540		while( GrabOption( Options, Pair ) )
00541		{
00542			GetKeyValue( Pair, Key, Value );
00543			if( Key ~= InKey )
00544				return true;
00545		}
00546		return false;
00547	}
00548	
00549	//
00550	// Find an option in the options string and return it.
00551	//
00552	function string ParseOption( string Options, string InKey )
00553	{
00554		local string Pair, Key, Value;
00555		while( GrabOption( Options, Pair ) )
00556		{
00557			GetKeyValue( Pair, Key, Value );
00558			if( Key ~= InKey )
00559				return Value;
00560		}
00561		return "";
00562	}
00563	
00564	//
00565	// Initialize the game.
00566	//warning: this is called before actors' PreBeginPlay.
00567	//
00568	event InitGame( string Options, out string Error )
00569	{
00570		local string InOpt, LeftOpt;
00571		local int pos;
00572		local class<Mutator> MClass;
00573	
00574		log( "InitGame:" @ Options );
00575		MaxPlayers = Min( 32,GetIntOption( Options, "MaxPlayers", MaxPlayers ));
00576		InOpt = ParseOption( Options, "Difficulty" );
00577		if( InOpt != "" )
00578			Difficulty = int(InOpt);
00579	
00580		InOpt = ParseOption( Options, "AdminPassword");
00581		if( InOpt!="" )
00582			AdminPassword = InOpt;
00583	
00584		InOpt = ParseOption( Options, "GameSpeed");
00585		if( InOpt != "" )
00586		{
00587			log("GameSpeed"@InOpt);
00588			SetGameSpeed(float(InOpt));
00589		}
00590	
00591		BaseMutator = spawn(MutatorClass);
00592		log("Base Mutator is "$BaseMutator);
00593		InOpt = ParseOption( Options, "Mutator");
00594		if ( InOpt != "" )
00595		{
00596			log("Mutators"@InOpt);
00597			while ( InOpt != "" )
00598			{
00599				pos = InStr(InOpt,",");
00600				if ( pos > 0 )
00601				{
00602					LeftOpt = Left(InOpt, pos);
00603					InOpt = Right(InOpt, Len(InOpt) - pos - 1);
00604				}
00605				else
00606				{
00607					LeftOpt = InOpt;
00608					InOpt = "";
00609				}
00610				log("Add mutator "$LeftOpt);
00611				MClass = class<Mutator>(DynamicLoadObject(LeftOpt, class'Class'));	
00612				BaseMutator.AddMutator(Spawn(MClass));
00613			}
00614		}
00615	
00616		InOpt = ParseOption( Options, "GamePassword");
00617		if( InOpt != "" )
00618		{
00619			GamePassWord = InOpt;
00620			log( "GamePassword" @ InOpt );
00621		}
00622	
00623		InOpt = ParseOption( Options, "LocalLog");
00624		if( InOpt ~= "true" )
00625			bLocalLog = True;
00626	
00627		InOpt = ParseOption( Options, "WorldLog");
00628		if( InOpt ~= "true" )
00629			bWorldLog = True;
00630	}
00631	
00632	//
00633	// Return beacon text for serverbeacon.
00634	//
00635	event string GetBeaconText()
00636	{	
00637		return
00638			Level.ComputerName
00639		$	" "
00640		$	Left(Level.Title,24) 
00641		$	" "
00642		$	BeaconName
00643		$	" "
00644		$	NumPlayers
00645		$	"/"
00646		$	MaxPlayers;
00647	}
00648	
00649	//
00650	// Optional handling of ServerTravel for network games.
00651	//
00652	function ProcessServerTravel( string URL, bool bItems )
00653	{
00654		local playerpawn P, LocalPlayer;
00655	
00656		if (LocalLog != None)
00657		{
00658			LocalLog.LogGameEnd("mapchange");
00659			LocalLog.StopLog();
00660			LocalLog.Destroy();
00661			LocalLog = None;
00662		}
00663	
00664		if (WorldLog != None)
00665		{
00666			WorldLog.LogGameEnd("mapchange");
00667			WorldLog.StopLog();
00668			WorldLog.Destroy();
00669			WorldLog = None;
00670		}
00671	
00672		// Notify clients we're switching level and give them time to receive.
00673		// We call PreClientTravel directly on any local PlayerPawns (ie listen server)
00674		log("ProcessServerTravel:"@URL);
00675		foreach AllActors( class'PlayerPawn', P )
00676			if( NetConnection(P.Player)!=None )
00677				P.ClientTravel( URL, TRAVEL_Relative, bItems );
00678			else
00679			{	
00680				LocalPlayer = P;
00681				P.PreClientTravel();
00682			}
00683	
00684		if ( (Level.NetMode == NM_ListenServer) && (LocalPlayer != None) )
00685			Level.NextURL = Level.NextURL$"?Skin="$LocalPlayer.GetDefaultURL("Skin")
00686						 $"?Face="$LocalPlayer.GetDefaultURL("Face")
00687						 $"?Team="$LocalPlayer.GetDefaultURL("Team")
00688						 $"?Name="$LocalPlayer.GetDefaultURL("Name")
00689						 $"?Class="$LocalPlayer.GetDefaultURL("Class");
00690	
00691		// Switch immediately if not networking.
00692		if( Level.NetMode!=NM_DedicatedServer && Level.NetMode!=NM_ListenServer )
00693			Level.NextSwitchCountdown = 0.0;
00694	}
00695	
00696	function bool AtCapacity(string Options)
00697	{
00698		return ( (MaxPlayers>0) && (NumPlayers>=MaxPlayers) );
00699	}
00700	
00701	//
00702	// Accept or reject a player on the server.
00703	// Fails login if you set the Error to a non-empty string.
00704	//
00705	event PreLogin
00706	(
00707		string Options,
00708		string Address,
00709		out string Error,
00710		out string FailCode
00711	)
00712	{
00713		// Do any name or password or name validation here.
00714		local string InPassword;
00715		Error="";
00716		InPassword = ParseOption( Options, "Password" );
00717		if( (Level.NetMode != NM_Standalone) && AtCapacity(Options) )
00718		{
00719			Error=MaxedOutMessage;
00720		}
00721		else if
00722		(	GamePassword!=""
00723		&&	caps(InPassword)!=caps(GamePassword)
00724		&&	(AdminPassword=="" || caps(InPassword)!=caps(AdminPassword)) )
00725		{
00726			if( InPassword == "" )
00727			{
00728				Error = NeedPassword;
00729				FailCode = "NEEDPW";
00730			}
00731			else
00732			{
00733				Error = WrongPassword;
00734				FailCode = "WRONGPW";
00735			}
00736		}
00737	
00738		if(!CheckIPPolicy(Address))
00739			Error = IPBanned;
00740	}
00741	
00742	function bool CheckIPPolicy(string Address)
00743	{
00744		local int i, j, LastMatchingPolicy;
00745		local string Policy, Mask;
00746		local bool bAcceptAddress, bAcceptPolicy;
00747		
00748		// strip port number
00749		j = InStr(Address, ":");
00750		if(j != -1)
00751			Address = Left(Address, j);
00752	
00753		bAcceptAddress = True;
00754		for(i=0; i<50 && IPPolicies[i] != ""; i++)
00755		{
00756			j = InStr(IPPolicies[i], ",");
00757			if(j==-1)
00758				continue;
00759			Policy = Left(IPPolicies[i], j);
00760			Mask = Mid(IPPolicies[i], j+1);
00761			if(Policy ~= "ACCEPT") 
00762				bAcceptPolicy = True;
00763			else
00764			if(Policy ~= "DENY") 
00765				bAcceptPolicy = False;
00766			else
00767				continue;
00768	
00769			j = InStr(Mask, "*");
00770			if(j != -1)
00771			{
00772				if(Left(Mask, j) == Left(Address, j))
00773				{
00774					bAcceptAddress = bAcceptPolicy;
00775					LastMatchingPolicy = i;
00776				}
00777			}
00778			else
00779			{
00780				if(Mask == Address)
00781				{
00782					bAcceptAddress = bAcceptPolicy;
00783					LastMatchingPolicy = i;
00784				}
00785			}
00786		}
00787	
00788		if(!bAcceptAddress)
00789			Log("Denied connection for "$Address$" with IP policy "$IPPolicies[LastMatchingPolicy]);
00790			
00791		return bAcceptAddress;
00792	}
00793	
00794	function int GetIntOption( string Options, string ParseString, int CurrentValue)
00795	{
00796		local string InOpt;
00797	
00798		InOpt = ParseOption( Options, ParseString );
00799		if ( InOpt != "" )
00800		{
00801			log(ParseString@InOpt);
00802			return int(InOpt);
00803		}	
00804		return CurrentValue;
00805	}
00806	
00807	//
00808	// Log a player in.
00809	// Fails login if you set the Error string.
00810	// PreLogin is called before Login, but significant game time may pass before
00811	// Login is called, especially if content is downloaded.
00812	//
00813	event playerpawn Login
00814	(
00815		string Portal,
00816		string Options,
00817		out string Error,
00818		class<playerpawn> SpawnClass
00819	)
00820	{
00821		local NavigationPoint StartSpot;
00822		local PlayerPawn      NewPlayer, TestPlayer;
00823		local Pawn            PawnLink;
00824		local string          InName, InPassword, InSkin, InFace, InChecksum;
00825		local byte            InTeam;
00826	
00827		// Make sure there is capacity. (This might have changed since the PreLogin call).
00828		if ( Level.NetMode != NM_Standalone )
00829		{
00830			if ( ClassIsChildOf(SpawnClass, class'Spectator') )
00831			{
00832				if ( (NumSpectators >= MaxSpectators)
00833					&& ((Level.NetMode != NM_ListenServer) || (NumPlayers > 0)) )
00834				{
00835					Error=MaxedOutMessage;
00836					return None;
00837				}
00838			}		
00839			else if ( (MaxPlayers>0) && (NumPlayers>=MaxPlayers) )
00840			{
00841				Error=MaxedOutMessage;
00842				return None;
00843			}
00844		}
00845	
00846		BaseMutator.ModifyLogin(SpawnClass, Portal, Options);
00847	
00848		// Get URL options.
00849		InName     = Left(ParseOption ( Options, "Name"), 20);
00850		InTeam     = GetIntOption( Options, "Team", 255 ); // default to "no team"
00851		InPassword = ParseOption ( Options, "Password" );
00852		InSkin	   = ParseOption ( Options, "Skin"    );
00853		InFace     = ParseOption ( Options, "Face"    );
00854		InChecksum = ParseOption ( Options, "Checksum" );
00855	
00856		log( "Login:" @ InName );
00857		if( InPassword != "" )
00858			log( "Password"@InPassword );
00859		 
00860		// Find a start spot.
00861		StartSpot = FindPlayerStart( None, InTeam, Portal );
00862	
00863		if( StartSpot == None )
00864		{
00865			Error = FailedPlaceMessage;
00866			return None;
00867		}
00868	
00869		// Try to match up to existing unoccupied player in level,
00870		// for savegames and coop level switching.
00871		for( PawnLink=Level.PawnList; PawnLink!=None; PawnLink=PawnLink.NextPawn )
00872		{
00873			TestPlayer = PlayerPawn(PawnLink);
00874			if
00875			(	TestPlayer!=None
00876			&&	TestPlayer.Player==None 
00877			&&  TestPlayer.PlayerReplicationInfo != None
00878			&&  TestPlayer.bIsPlayer
00879			&&	TestPlayer.PlayerReplicationInfo.PlayerName != class'PlayerReplicationInfo'.default.PlayerName
00880			)
00881			{
00882				if
00883				(	(Level.NetMode==NM_Standalone)
00884				||	(TestPlayer.PlayerReplicationInfo.PlayerName~=InName && TestPlayer.Password~=InPassword) )
00885				{
00886					// Found matching unoccupied player, so use this one.
00887					NewPlayer = TestPlayer;
00888					break;
00889				}
00890			}
00891		}
00892	
00893		// In not found, spawn a new player.
00894		if( NewPlayer==None )
00895		{
00896			// Make sure this kind of player is allowed.
00897			if ( (bHumansOnly || Level.bHumansOnly) && !SpawnClass.Default.bIsHuman
00898				&& !ClassIsChildOf(SpawnClass, class'Spectator') )
00899				SpawnClass = DefaultPlayerClass;
00900	
00901			NewPlayer = Spawn(SpawnClass,,,StartSpot.Location,StartSpot.Rotation);
00902			if( NewPlayer!=None )
00903				NewPlayer.ViewRotation = StartSpot.Rotation;
00904		}
00905	
00906		// Handle spawn failure.
00907		if( NewPlayer == None )
00908		{
00909			log("Couldn't spawn player at "$StartSpot);
00910			Error = FailedSpawnMessage;
00911			return None;
00912		}
00913	
00914		NewPlayer.static.SetMultiSkin(NewPlayer, InSkin, InFace, InTeam);
00915	
00916		// Set the player's ID.
00917		NewPlayer.PlayerReplicationInfo.PlayerID = CurrentID++;
00918	
00919		// Init player's information.
00920		NewPlayer.ClientSetRotation(NewPlayer.Rotation);
00921		if( InName=="" )
00922			InName=DefaultPlayerName;
00923		if( Level.NetMode!=NM_Standalone || NewPlayer.PlayerReplicationInfo.PlayerName==DefaultPlayerName )
00924			ChangeName( NewPlayer, InName, false );
00925	
00926		// Change player's team.
00927		if ( !ChangeTeam(newPlayer, InTeam) )
00928		{
00929			Error = FailedTeamMessage;
00930			return None;
00931		}
00932	
00933		if( NewPlayer.IsA('Spectator') && (Level.NetMode == NM_DedicatedServer) )
00934			NumSpectators++;
00935	
00936		// Init player's administrative privileges
00937		NewPlayer.Password = InPassword;
00938		NewPlayer.bAdmin = AdminPassword!="" && caps(InPassword)==caps(AdminPassword);
00939		NewPlayer.PlayerReplicationInfo.bAdmin = NewPlayer.bAdmin;
00940		if( NewPlayer.bAdmin )
00941			log( "Administrator logged in!" );
00942	
00943		// Init player's replication info
00944		NewPlayer.GameReplicationInfo = GameReplicationInfo;
00945	
00946		// If we are a server, broadcast a welcome message.
00947		if( Level.NetMode==NM_DedicatedServer || Level.NetMode==NM_ListenServer )
00948			BroadcastMessage( NewPlayer.PlayerReplicationInfo.PlayerName$EnteredMessage, false );
00949	
00950		// Teleport-in effect.
00951		StartSpot.PlayTeleportEffect( NewPlayer, true );
00952	
00953		// Log it.
00954		if ( LocalLog != None )
00955			LocalLog.LogPlayerConnect(NewPlayer);
00956		if ( WorldLog != None )
00957			WorldLog.LogPlayerConnect(NewPlayer, InChecksum);
00958		NewPlayer.ReceivedSecretChecksum = !(InChecksum ~= "NoChecksum");
00959	
00960		if ( !NewPlayer.IsA('Spectator') )
00961			NumPlayers++;
00962		return newPlayer;
00963	}	
00964	
00965	//
00966	// Called after a successful login. This is the first place
00967	// it is safe to call replicated functions on the PlayerPawn.
00968	//
00969	event PostLogin( playerpawn NewPlayer )
00970	{
00971		local Pawn P;
00972		// Start player's music.
00973		NewPlayer.ClientSetMusic( Level.Song, Level.SongSection, Level.CdTrack, MTRAN_Fade );
00974		if ( Level.NetMode != NM_Standalone )
00975		{
00976			// replicate skins
00977			for ( P=Level.PawnList; P!=None; P=P.NextPawn )
00978				if ( P.bIsPlayer && (P != NewPlayer) )
00979				{
00980					if ( P.bIsMultiSkinned )
00981						NewPlayer.ClientReplicateSkins(P.MultiSkins[0], P.MultiSkins[1], P.MultiSkins[2], P.MultiSkins[3]);
00982					else
00983						NewPlayer.ClientReplicateSkins(P.Skin);	
00984						
00985					if ( (P.PlayerReplicationInfo != None) && P.PlayerReplicationInfo.bWaitingPlayer && P.IsA('PlayerPawn') )
00986					{
00987						if ( NewPlayer.bIsMultiSkinned )
00988							PlayerPawn(P).ClientReplicateSkins(NewPlayer.MultiSkins[0], NewPlayer.MultiSkins[1], NewPlayer.MultiSkins[2], NewPlayer.MultiSkins[3]);
00989						else
00990							PlayerPawn(P).ClientReplicateSkins(NewPlayer.Skin);	
00991					}						
00992				}
00993		}
00994	}
00995	
00996	//
00997	// Add bot to game.
00998	//
00999	function bool AddBot();
01000	function bool ForceAddBot();
01001	
01002	//
01003	// Pawn exits.
01004	//
01005	function Logout( pawn Exiting )
01006	{
01007		local bool bMessage;
01008	
01009		bMessage = true;
01010		if ( Exiting.IsA('PlayerPawn') )
01011		{
01012			if ( Exiting.IsA('Spectator') )
01013			{
01014				bMessage = false;
01015				if ( Level.NetMode == NM_DedicatedServer )
01016					NumSpectators--;
01017			}
01018			else
01019				NumPlayers--;
01020		}
01021		if( bMessage && (Level.NetMode==NM_DedicatedServer || Level.NetMode==NM_ListenServer) )
01022			BroadcastMessage( Exiting.PlayerReplicationInfo.PlayerName$LeftMessage, false );
01023	
01024		if ( LocalLog != None )
01025			LocalLog.LogPlayerDisconnect(Exiting);
01026		if ( WorldLog != None )
01027			WorldLog.LogPlayerDisconnect(Exiting);
01028	}
01029	
01030	//
01031	// Examine the passed player's inventory, and accept or discard each item.
01032	// AcceptInventory needs to gracefully handle the case of some inventory
01033	// being accepted but other inventory not being accepted (such as the default
01034	// weapon).  There are several things that can go wrong: A weapon's
01035	// AmmoType not being accepted but the weapon being accepted -- the weapon
01036	// should be killed off. Or the player's selected inventory item, active
01037	// weapon, etc. not being accepted, leaving the player weaponless or leaving
01038	// the HUD inventory rendering messed up (AcceptInventory should pick another
01039	// applicable weapon/item as current).
01040	//
01041	event AcceptInventory(pawn PlayerPawn)
01042	{
01043		//default accept all inventory except default weapon (spawned explicitly)
01044	
01045		local inventory inv;
01046	
01047		// Initialize the inventory.
01048		AddDefaultInventory( PlayerPawn );
01049	
01050		log( "All inventory from" @ PlayerPawn.PlayerReplicationInfo.PlayerName @ "is accepted" );
01051	}
01052	
01053	//
01054	// Spawn any default inventory for the player.
01055	//
01056	function AddDefaultInventory( pawn PlayerPawn )
01057	{
01058		local Weapon newWeapon;
01059		local class<Weapon> WeapClass;
01060	
01061		PlayerPawn.JumpZ = PlayerPawn.Default.JumpZ * PlayerJumpZScaling();
01062		 
01063		if( PlayerPawn.IsA('Spectator') )
01064			return;
01065	
01066		// Spawn default weapon.
01067		WeapClass = BaseMutator.MutatedDefaultWeapon();
01068		if( (WeapClass!=None) && (PlayerPawn.FindInventoryType(WeapClass)==None) )
01069		{
01070			newWeapon = Spawn(WeapClass,,,PlayerPawn.Location);
01071			if( newWeapon != None )
01072			{
01073				newWeapon.Instigator = PlayerPawn;
01074				newWeapon.BecomeItem();
01075				PlayerPawn.AddInventory(newWeapon);
01076				newWeapon.BringUp();
01077				newWeapon.GiveAmmo(PlayerPawn);
01078				newWeapon.SetSwitchPriority(PlayerPawn);
01079				newWeapon.WeaponSet(PlayerPawn);
01080			}
01081		}
01082		BaseMutator.ModifyPlayer(PlayerPawn);
01083	}
01084	
01085	
01086	//
01087	// Return the 'best' player start for this player to start from.
01088	// Re-implement for each game type.
01089	//
01090	function NavigationPoint FindPlayerStart( Pawn Player, optional byte InTeam, optional string incomingName )
01091	{
01092		local PlayerStart Dest;
01093		local Teleporter Tel;
01094		if( incomingName!="" )
01095			foreach AllActors( class 'Teleporter', Tel )
01096				if( string(Tel.Tag)~=incomingName )
01097					return Tel;
01098		foreach AllActors( class 'PlayerStart', Dest )
01099			if( Dest.bSinglePlayerStart && Dest.bEnabled )
01100				return Dest;
01101	
01102		// if none, check for any that aren't enabled
01103		log("WARNING: All single player starts were disabled - picking one anyway!");
01104		foreach AllActors( class 'PlayerStart', Dest )
01105			if( Dest.bSinglePlayerStart )
01106				return Dest;
01107		log( "No single player start found" );
01108		return None;
01109	}
01110	
01111	//
01112	// Restart a player.
01113	//
01114	function bool RestartPlayer( pawn aPlayer )	
01115	{
01116		local NavigationPoint startSpot;
01117		local bool foundStart;
01118	
01119		if( bRestartLevel && Level.NetMode!=NM_DedicatedServer && Level.NetMode!=NM_ListenServer )
01120			return true;
01121	
01122		startSpot = FindPlayerStart(aPlayer, 255);
01123		if( startSpot == None )
01124		{
01125			log(" Player start not found!!!");
01126			return false;
01127		}	
01128		foundStart = aPlayer.SetLocation(startSpot.Location);
01129		if( foundStart )
01130		{
01131			startSpot.PlayTeleportEffect(aPlayer, true);
01132			aPlayer.SetRotation(startSpot.Rotation);
01133			aPlayer.ViewRotation = aPlayer.Rotation;
01134			aPlayer.Acceleration = vect(0,0,0);
01135			aPlayer.Velocity = vect(0,0,0);
01136			aPlayer.Health = aPlayer.Default.Health;
01137			aPlayer.SetCollision( true, true, true );
01138			aPlayer.ClientSetLocation( startSpot.Location, startSpot.Rotation );
01139			aPlayer.bHidden = false;
01140			aPlayer.DamageScaling = aPlayer.Default.DamageScaling;
01141			aPlayer.SoundDampening = aPlayer.Default.SoundDampening;
01142			AddDefaultInventory(aPlayer);
01143		}
01144		else
01145			log(startspot$" Player start not useable!!!");
01146		return foundStart;
01147	}
01148	
01149	//
01150	// Start a player.
01151	//
01152	function StartPlayer(PlayerPawn Other)
01153	{
01154		if( Level.NetMode==NM_DedicatedServer || Level.NetMode==NM_ListenServer || !bRestartLevel )
01155			Other.GotoState(Other.PlayerRestartState);
01156		else
01157			Other.ClientTravel( "?restart", TRAVEL_Relative, false );
01158	}
01159	
01160	//------------------------------------------------------------------------------
01161	// Level death message functions.
01162	
01163	function Killed( pawn Killer, pawn Other, name damageType )
01164	{
01165		local String Message, KillerWeapon, OtherWeapon;
01166		local bool bSpecialDamage;
01167	
01168		if (Other.bIsPlayer)
01169		{
01170			if ( (Killer != None) && (!Killer.bIsPlayer) )
01171			{
01172				Message = Killer.KillMessage(damageType, Other);
01173				BroadcastMessage( Message, false, 'DeathMessage');
01174				if ( LocalLog != None )
01175					LocalLog.LogSuicide(Other, DamageType, None);
01176				if ( WorldLog != None )
01177					WorldLog.LogSuicide(Other, DamageType, None);
01178				return;
01179			}
01180			if ( (DamageType == 'SpecialDamage') && (SpecialDamageString != "") )
01181			{
01182				BroadcastMessage( ParseKillMessage(
01183						Killer.PlayerReplicationInfo.PlayerName,
01184						Other.PlayerReplicationInfo.PlayerName,
01185						Killer.Weapon.ItemName,
01186						SpecialDamageString
01187						),
01188					false, 'DeathMessage');
01189				bSpecialDamage = True;
01190			}
01191			Other.PlayerReplicationInfo.Deaths += 1;
01192			if ( (Killer == Other) || (Killer == None) )
01193			{
01194				// Suicide
01195				if (damageType == '')
01196				{
01197					if ( LocalLog != None )
01198						LocalLog.LogSuicide(Other, 'Unknown', Killer);
01199					if ( WorldLog != None )
01200						WorldLog.LogSuicide(Other, 'Unknown', Killer);
01201				} else {
01202					if ( LocalLog != None )
01203						LocalLog.LogSuicide(Other, damageType, Killer);
01204					if ( WorldLog != None )
01205						WorldLog.LogSuicide(Other, damageType, Killer);
01206				}
01207				if (!bSpecialDamage)
01208				{
01209					if ( damageType == 'Fell' )
01210						BroadcastLocalizedMessage(DeathMessageClass, 2, Other.PlayerReplicationInfo, None);
01211					else if ( damageType == 'Eradicated' )
01212						BroadcastLocalizedMessage(DeathMessageClass, 3, Other.PlayerReplicationInfo, None);
01213					else if ( damageType == 'Drowned' )
01214						BroadcastLocalizedMessage(DeathMessageClass, 4, Other.PlayerReplicationInfo, None);
01215					else if ( damageType == 'Burned' )
01216						BroadcastLocalizedMessage(DeathMessageClass, 5, Other.PlayerReplicationInfo, None);
01217					else if ( damageType == 'Corroded' )
01218						BroadcastLocalizedMessage(DeathMessageClass, 6, Other.PlayerReplicationInfo, None);
01219					else if ( damageType == 'Mortared' )
01220						BroadcastLocalizedMessage(DeathMessageClass, 7, Other.PlayerReplicationInfo, None);
01221					else
01222						BroadcastLocalizedMessage(DeathMessageClass, 1, Other.PlayerReplicationInfo, None);
01223				}
01224			} 
01225			else 
01226			{
01227				if ( Killer.bIsPlayer )
01228				{
01229					KillerWeapon = "None";
01230					if (Killer.Weapon != None)
01231						KillerWeapon = Killer.Weapon.ItemName;
01232					OtherWeapon = "None";
01233					if (Other.Weapon != None)
01234						OtherWeapon = Other.Weapon.ItemName;
01235					if ( Killer.PlayerReplicationInfo.Team == Other.PlayerReplicationInfo.Team )
01236					{
01237						if ( LocalLog != None )
01238							LocalLog.LogTeamKill(
01239								Killer.PlayerReplicationInfo.PlayerID,
01240								Other.PlayerReplicationInfo.PlayerID,
01241								KillerWeapon,
01242								OtherWeapon,
01243								damageType
01244							);
01245						if ( WorldLog != None )
01246							WorldLog.LogTeamKill(
01247								Killer.PlayerReplicationInfo.PlayerID,
01248								Other.PlayerReplicationInfo.PlayerID,
01249								KillerWeapon,
01250								OtherWeapon,
01251								damageType
01252							);
01253					} else {
01254						if ( LocalLog != None )
01255							LocalLog.LogKill(
01256								Killer.PlayerReplicationInfo.PlayerID,
01257								Other.PlayerReplicationInfo.PlayerID,
01258								KillerWeapon,
01259								OtherWeapon,
01260								damageType
01261							);
01262						if ( WorldLog != None )
01263							WorldLog.LogKill(
01264								Killer.PlayerReplicationInfo.PlayerID,
01265								Other.PlayerReplicationInfo.PlayerID,
01266								KillerWeapon,
01267								OtherWeapon,
01268								damageType
01269							);
01270					}
01271					if (!bSpecialDamage && (Other != None))
01272					{
01273						BroadcastRegularDeathMessage(Killer, Other, damageType);
01274					}
01275				}
01276			}
01277		}
01278		ScoreKill(Killer, Other);
01279	}
01280	
01281	function BroadcastRegularDeathMessage(pawn Killer, pawn Other, name damageType)
01282	{
01283		BroadcastLocalizedMessage(DeathMessageClass, 0, Killer.PlayerReplicationInfo, Other.PlayerReplicationInfo, Killer.Weapon.Class);
01284	}
01285	
01286	// %k = Owner's PlayerName (Killer)
01287	// %o = Other's PlayerName (Victim)
01288	// %w = Owner's Weapon ItemName
01289	static native function string ParseKillMessage( string KillerName, string VictimName, string WeaponName, string DeathMessage );
01290	
01291	function ScoreKill(pawn Killer, pawn Other)
01292	{
01293		Other.DieCount++;
01294		if( (killer == Other) || (killer == None) )
01295			Other.PlayerReplicationInfo.Score -= 1;
01296		else if ( killer != None )
01297		{
01298			killer.killCount++;
01299			if ( killer.PlayerReplicationInfo != None )
01300				killer.PlayerReplicationInfo.Score += 1;
01301		}
01302	
01303		BaseMutator.ScoreKill(Killer, Other);
01304	}
01305	
01306	//
01307	// Default death message.
01308	//
01309	static function string KillMessage( name damageType, pawn Other )
01310	{
01311		return " died.";
01312	}
01313	
01314	//-------------------------------------------------------------------------------------
01315	// Level gameplay modification.
01316	
01317	//
01318	// Return whether Viewer is allowed to spectate from the
01319	// point of view of ViewTarget.
01320	//
01321	function bool CanSpectate( pawn Viewer, actor ViewTarget )
01322	{
01323		return true;
01324	}
01325	
01326	function RegisterDamageMutator(Mutator M)
01327	{
01328		M.NextDamageMutator = DamageMutator;
01329		DamageMutator = M;
01330	}
01331	
01332	function RegisterMessageMutator(Mutator M)
01333	{
01334		M.NextMessageMutator = MessageMutator;
01335		MessageMutator = M;
01336	}
01337	
01338	//
01339	// Use reduce damage for teamplay modifications, etc.
01340	//
01341	function int ReduceDamage( int Damage, name DamageType, pawn injured, pawn instigatedBy )
01342	{
01343		if( injured.Region.Zone.bNeutralZone )
01344			return 0;	
01345		return Damage;
01346	}
01347	
01348	//
01349	// Award a score to an actor.
01350	//
01351	function ScoreEvent( name EventName, actor EventActor, pawn InstigatedBy )
01352	{
01353	}
01354	
01355	//
01356	// Return whether an item should respawn.
01357	//
01358	function bool ShouldRespawn( actor Other )
01359	{
01360		if( Level.NetMode == NM_StandAlone )
01361			return false;
01362		return Inventory(Other)!=None && Inventory(Other).ReSpawnTime!=0.0;
01363	}
01364	
01365	//
01366	// Called when pawn has a chance to pick Item up (i.e. when 
01367	// the pawn touches a weapon pickup). Should return true if 
01368	// he wants to pick it up, false if he does not want it.
01369	//
01370	function bool PickupQuery( Pawn Other, Inventory item )
01371	{
01372		local Mutator M;
01373		local byte bAllowPickup;
01374	
01375		if ( BaseMutator.HandlePickupQuery(Other, item, bAllowPickup) )
01376			return (bAllowPickup == 1);
01377	
01378		if ( Other.Inventory == None )
01379			return true;
01380		else
01381			return !Other.Inventory.HandlePickupQuery(Item);
01382	}
01383			
01384	//
01385	// Discard a player's inventory after he dies.
01386	//
01387	function DiscardInventory( Pawn Other )
01388	{
01389		local actor dropped;
01390		local inventory Inv;
01391		local weapon weap;
01392		local float speed;
01393	
01394		if( Other.DropWhenKilled != None )
01395		{
01396			dropped = Spawn(Other.DropWhenKilled,,,Other.Location);
01397			Inv = Inventory(dropped);
01398			if ( Inv != None )
01399			{ 
01400				Inv.RespawnTime = 0.0; //don't respawn
01401				Inv.BecomePickup();		
01402			}
01403			if ( dropped != None )
01404			{
01405				dropped.RemoteRole = ROLE_DumbProxy;
01406				dropped.SetPhysics(PHYS_Falling);
01407				dropped.bCollideWorld = true;
01408				dropped.Velocity = Other.Velocity + VRand() * 280;
01409			}
01410			if ( Inv != None )
01411				Inv.GotoState('PickUp', 'Dropped');
01412		}					
01413		if( (Other.Weapon!=None) && (Other.Weapon.Class!=Level.Game.BaseMutator.MutatedDefaultWeapon()) 
01414			&& Other.Weapon.bCanThrow )
01415		{
01416			speed = VSize(Other.Velocity);
01417			weap = Other.Weapon;
01418			if (speed != 0)
01419				weap.Velocity = Normal(Other.Velocity/speed + 0.5 * VRand()) * (speed + 280);
01420			else {
01421				weap.Velocity.X = 0;
01422				weap.Velocity.Y = 0;
01423				weap.Velocity.Z = 0;
01424			}
01425			Other.TossWeapon();
01426			if ( weap.PickupAmmoCount == 0 )
01427				weap.PickupAmmoCount = 1;
01428		}
01429		Other.Weapon = None;
01430		Other.SelectedItem = None;	
01431		for( Inv=Other.Inventory; Inv!=None; Inv=Inv.Inventory )
01432			Inv.Destroy();
01433	}
01434	
01435	// Return the player jumpZ scaling for this gametype
01436	function float PlayerJumpZScaling()
01437	{
01438		return 1.0;
01439	}
01440	
01441	//
01442	// Try to change a player's name.
01443	//	
01444	function ChangeName( Pawn Other, coerce string S, bool bNameChange )
01445	{
01446		if( S == "" )
01447			return;
01448		if (LocalLog != None)
01449			LocalLog.LogNameChange(Other);
01450		if (WorldLog != None)
01451			WorldLog.LogNameChange(Other);
01452		Other.PlayerReplicationInfo.PlayerName = S;
01453		if( bNameChange )
01454			Other.ClientMessage( NameChangedMessage $ Other.PlayerReplicationInfo.PlayerName );
01455	}
01456	
01457	//
01458	// Return whether a team change is allowed.
01459	//
01460	function bool ChangeTeam(Pawn Other, int N)
01461	{
01462		Other.PlayerReplicationInfo.Team = N;
01463		if (LocalLog != None)
01464			LocalLog.LogTeamChange(Other);
01465		if (WorldLog != None)
01466			WorldLog.LogTeamChange(Other);
01467		return true;
01468	}
01469	
01470	//
01471	// Play an inventory respawn effect.
01472	//
01473	function float PlaySpawnEffect( inventory Inv )
01474	{
01475		return 0.3;
01476	}
01477	
01478	//
01479	// Generate a player killled message.
01480	//
01481	static function string PlayerKillMessage( name damageType, PlayerReplicationInfo Other )
01482	{
01483		local string message;
01484	
01485		message = " was killed by ";
01486		return message;
01487	}
01488	
01489	//
01490	// Generate a killed by creature message.
01491	//
01492	static function string CreatureKillMessage( name damageType, pawn Other )
01493	{
01494		return " was killed by a ";
01495	}
01496	
01497	//
01498	// Send a player to a URL.
01499	//
01500	function SendPlayer( PlayerPawn aPlayer, string URL )
01501	{
01502		aPlayer.ClientTravel( URL, TRAVEL_Relative, true );
01503	}
01504	
01505	//
01506	// Play a teleporting special effect.
01507	//
01508	function PlayTeleportEffect( actor Incoming, bool bOut, bool bSound);
01509	
01510	//
01511	// Restart the game.
01512	//
01513	function RestartGame()
01514	{
01515		Level.ServerTravel( "?Restart", false );
01516	}
01517	
01518	//
01519	// Whether players are allowed to broadcast messages now.
01520	//
01521	function bool AllowsBroadcast( actor broadcaster, int Len )
01522	{
01523		local PlayerPawn P;
01524	
01525		P = PlayerPawn(BroadCaster);
01526		if ( P != None )
01527		{
01528			// prevent message spamming
01529			if ( (Level.TimeSeconds - P.LastMessageWindow < 20)
01530				&& (Level.TimeSeconds > 20) )
01531				return false;
01532			P.LastMessageWindow = 0.75 * P.LastMessageWindow + 0.25 * Level.TimeSeconds;
01533		}
01534		SentText += Len;
01535	
01536		return (SentText < 260);
01537	}
01538	
01539	//
01540	// End of game.
01541	//
01542	function EndGame( string Reason )
01543	{
01544		local actor A;
01545		local Mutator M;
01546	
01547		// don't end game if not really ready
01548		// mutator can set bOverTime if doesn't want game to end
01549	
01550		if ( !BaseMutator.HandleEndGame() && !SetEndCams(Reason) )
01551		{
01552			bOverTime = true;
01553			return;
01554		}
01555	
01556		bGameEnded = true;
01557		foreach AllActors(class'Actor', A, 'EndGame')
01558			A.trigger(self, none);
01559	
01560		if (LocalLog != None)
01561		{
01562			LocalLog.LogGameEnd(Reason);
01563			LocalLog.StopLog();
01564			if (bBatchLocal)
01565				LocalLog.ExecuteSilentLogBatcher();
01566			LocalLog.Destroy();
01567			LocalLog = None;
01568		}
01569		if (WorldLog != None)
01570		{
01571			WorldLog.LogGameEnd(Reason);
01572			WorldLog.StopLog();
01573			WorldLog.ExecuteWorldLogBatcher();
01574			WorldLog.Destroy();
01575			WorldLog = None;
01576		}
01577	}
01578	
01579	function bool SetEndCams(string Reason)
01580	{
01581		local pawn aPawn;
01582	
01583		for ( aPawn=Level.PawnList; aPawn!=None; aPawn=aPawn.NextPawn )
01584			if ( aPawn.bIsPlayer )
01585			{
01586				aPawn.GotoState('GameEnded');
01587				aPawn.ClientGameEnded();
01588			}	
01589	
01590		return true;
01591	}
01592	
01593	defaultproperties
01594	{
01595	     Difficulty=1
01596	     bRestartLevel=True
01597	     bPauseable=True
01598	     bCanChangeSkin=True
01599	     bNoCheating=True
01600	     bCanViewOthers=True
01601	     AutoAim=0.930000
01602	     GameSpeed=1.000000
01603	     MaxSpectators=2
01604	     BotMenuType="UMenu.UMenuBotConfigSClient"
01605	     RulesMenuType="UMenu.UMenuGameRulesSClient"
01606	     SettingsMenuType="UMenu.UMenuGameSettingsSClient"
01607	     GameUMenuType="UMenu.UMenuGameMenu"
01608	     MultiplayerUMenuType="UMenu.UMenuMultiplayerMenu"
01609	     GameOptionsMenuType="UMenu.UMenuOptionsMenu"
01610	     SwitchLevelMessage="Switching Levels"
01611	     DefaultPlayerName="Player"
01612	     LeftMessage=" left the game."
01613	     FailedSpawnMessage="Failed to spawn player actor"
01614	     FailedPlaceMessage="Could not find starting spot (level might need a 'PlayerStart' actor)"
01615	     FailedTeamMessage="Could not find team for player"
01616	     NameChangedMessage="Name changed to "
01617	     EnteredMessage=" entered the game."
01618	     GameName="Game"
01619	     MaxedOutMessage="Server is already at capacity."
01620	     WrongPassword="The password you entered is incorrect."
01621	     NeedPassword="You need to enter a password to join this game."
01622	     IPBanned="Your IP address has been banned on this server."
01623	     MaxPlayers=16
01624	     IPPolicies(0)="ACCEPT,*"
01625	     DeathMessageClass=Class'Engine.LocalMessage'
01626	     MutatorClass=Class'Engine.Mutator'
01627	     DefaultPlayerState=PlayerWalking
01628	     ServerLogName="server.log"
01629	     bLocalLog=True
01630	     bWorldLog=True
01631	     StatLogClass=Class'Engine.StatLogFile'
01632	}

End Source Code