UnrealShare
Class DeathMatchGame

source: e:\games\UnrealTournament\UnrealShare\Classes\DeathMatchGame.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Info
         |
         +--Engine.GameInfo
            |
            +--UnrealShare.UnrealGameInfo
               |
               +--UnrealShare.DeathMatchGame
Direct Known Subclasses:DarkMatch, KingOfTheHill, TeamGame

class DeathMatchGame
extends UnrealShare.UnrealGameInfo

//============================================================================= // DeathMatchGame. //=============================================================================
Variables
 class BotConfigType
           time limit in minutes
 int FragLimit
 string GlobalNameChange
           time limit in minutes
 int InitialBots
           time limit in minutes
 string NoNameChange
           time limit in minutes
 int NumBots
           time limit in minutes
 int TimeLimit
           time limit in minutes
 string TimeMessage[16]
           time limit in minutes
 bool bChangeLevels
           time limit in minutes
 bool bHardCoreMode
           time limit in minutes
 bool bMegaSpeed
           time limit in minutes
 bool bMultiPlayerBots
           time limit in minutes


Function Summary
 void AcceptInventory(Pawn PlayerPawn)
     
/* AcceptInventory()
Examine the passed player's inventory, and accept or discard each item
* AcceptInventory needs to gracefully handle the case of some inventory
being accepted but other inventory not being accepted (such as the default
weapon).  There are several things that can go wrong: A weapon's
AmmoType not being accepted but the weapon being accepted -- the weapon
should be killed off. Or the player's selected inventory item, active
weapon, etc. not being accepted, leaving the player weaponless or leaving
the HUD inventory rendering messed up (AcceptInventory should pick another
applicable weapon/item as current).
*/
 bool AddBot()
 bool CanSpectate(Pawn Viewer, Actor ViewTarget)
 void ChangeName(Pawn Other, string S, bool bNameChange)
 void EndGame(string Reason)
 NavigationPoint FindPlayerStart(Pawn Player, optional byte, optional string)
     
/* FindPlayerStart()
returns the 'best' player start for this player to start from.
Re-implement for each game type
*/
 int GetIntOption(string Options, string ParseString, int CurrentValue)
 string GetRules()
     
//------------------------------------------------------------------------------
// Game Querying.
 bool IsRelevant(Actor Other)
 void Killed(Pawn killer, Pawn Other, name damageType)
     
// Monitor killed messages for fraglimit
 void LogGameParameters(StatLog StatLog)
 void Logout(Pawn Exiting)
 float PlaySpawnEffect(Inventory Inv)
 float PlayerJumpZScaling()
 void PostBeginPlay()
 int ReduceDamage(int Damage, name DamageType, Pawn injured, Pawn instigatedBy)
 void RestartGame()
 void SetGameSpeed(Float T)
     
//
// Set gameplay speed.
//
 bool ShouldRespawn(Actor Other)
 void Timer()



Source Code


00001	//=============================================================================
00002	// DeathMatchGame.
00003	//=============================================================================
00004	class DeathMatchGame extends UnrealGameInfo;
00005	
00006	var() globalconfig int	FragLimit; 
00007	var() globalconfig int	TimeLimit; // time limit in minutes
00008	var() globalconfig bool	bMultiPlayerBots;
00009	var() globalconfig bool bChangeLevels;
00010	var() globalconfig bool bHardCoreMode;
00011	var() globalconfig bool bMegaSpeed;
00012	
00013	var		bool	bDontRestart;
00014	var		bool	bGameEnded;
00015	var		bool	bAlreadyChanged;
00016	var	  int RemainingTime;
00017	
00018	// Bot related info
00019	var   int			NumBots;
00020	var	  int			RemainingBots;
00021	var() globalconfig int	InitialBots;
00022	var		BotInfo		BotConfig;
00023	var localized string GlobalNameChange;
00024	var localized string NoNameChange;
00025	var localized string TimeMessage[16];
00026	var class<BotInfo> BotConfigType;
00027	
00028	function PostBeginPlay()
00029	{
00030		local string NextPlayerClass;
00031		local int i;
00032	
00033		BotConfig = spawn(BotConfigType);
00034		RemainingTime = 60 * TimeLimit;
00035		if ( (Level.NetMode == NM_Standalone) || bMultiPlayerBots )
00036			RemainingBots = InitialBots;
00037		Super.PostBeginPlay();
00038	
00039		// load all player classes
00040		NextPlayerClass = GetNextInt("UnrealiPlayer", 0); 
00041		while ( NextPlayerClass != "" )
00042		{
00043			DynamicLoadObject(NextPlayerClass, class'Class');
00044			i++;
00045			NextPlayerClass = GetNextInt("UnrealiPlayer", i); 
00046		}
00047	}
00048	
00049	function int GetIntOption( string Options, string ParseString, int CurrentValue)
00050	{
00051		if ( !bTeamGame && (ParseString ~= "Team") )
00052			return 255;
00053	
00054		return Super.GetIntOption(Options, ParseString, CurrentValue);
00055	}
00056	
00057	function bool IsRelevant(actor Other) 
00058	{
00059		if ( bMegaSpeed && Other.IsA('Pawn') && Pawn(Other).bIsPlayer )
00060		{
00061			Pawn(Other).GroundSpeed *= 1.5;
00062			Pawn(Other).WaterSpeed *= 1.5;
00063			Pawn(Other).AirSpeed *= 1.5;
00064			Pawn(Other).Acceleration *= 1.5;
00065		}
00066		return Super.IsRelevant(Other);
00067	}
00068	
00069	function LogGameParameters(StatLog StatLog)
00070	{
00071		if (StatLog == None)
00072			return;
00073		
00074		Super.LogGameParameters(StatLog);
00075	
00076		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"FragLimit"$Chr(9)$FragLimit);
00077		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"TimeLimit"$Chr(9)$TimeLimit);
00078		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"MultiPlayerBots"$Chr(9)$bMultiPlayerBots);
00079		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"HardCore"$Chr(9)$bHardCoreMode);
00080		StatLog.LogEventString(StatLog.GetTimeStamp()$Chr(9)$"game"$Chr(9)$"MegaSpeed"$Chr(9)$bMegaSpeed);
00081	}
00082	
00083	function float PlayerJumpZScaling()
00084	{
00085		if ( bHardCoreMode )
00086			return 1.1;
00087		else
00088			return 1.0;
00089	}
00090	
00091	//
00092	// Set gameplay speed.
00093	//
00094	function SetGameSpeed( Float T )
00095	{
00096		GameSpeed = FMax(T, 0.1);
00097		if ( bHardCoreMode )
00098			Level.TimeDilation = 1.1 * GameSpeed;
00099		else
00100			Level.TimeDilation = GameSpeed;
00101	}
00102	
00103	event InitGame( string Options, out string Error )
00104	{
00105		local string InOpt;
00106	
00107		Super.InitGame(Options, Error);
00108	
00109		SetGameSpeed(GameSpeed);
00110		FragLimit = GetIntOption( Options, "FragLimit", FragLimit );
00111		TimeLimit = GetIntOption( Options, "TimeLimit", TimeLimit );
00112	
00113		InOpt = ParseOption( Options, "CoopWeaponMode");
00114		if ( InOpt != "" )
00115		{
00116			log("CoopWeaponMode "$bool(InOpt));
00117			bCoopWeaponMode = bool(InOpt);
00118		}
00119	}
00120	
00121	//------------------------------------------------------------------------------
00122	// Game Querying.
00123	
00124	function string GetRules()
00125	{
00126		local string ResultSet;
00127		ResultSet = Super.GetRules();
00128	
00129		// Timelimit.
00130		ResultSet = "\\timelimit\\"$TimeLimit;
00131			
00132		// Fraglimit
00133		ResultSet = ResultSet$"\\fraglimit\\"$FragLimit;
00134			
00135		// Bots in Multiplay?
00136		if( bMultiplayerBots )
00137			Resultset = ResultSet$"\\MultiplayerBots\\"$true;
00138		else
00139			Resultset = ResultSet$"\\MultiplayerBots\\"$false;
00140	
00141		// Change levels?
00142		if( bChangeLevels )
00143			Resultset = ResultSet$"\\ChangeLevels\\"$true;
00144		else
00145			Resultset = ResultSet$"\\ChangeLevels\\"$false;
00146	
00147		return ResultSet;
00148	}
00149	
00150	function int ReduceDamage(int Damage, name DamageType, pawn injured, pawn instigatedBy)
00151	{
00152		if (injured.Region.Zone.bNeutralZone)
00153			return 0;
00154	
00155		if ( instigatedBy == None)
00156			return Damage;
00157	
00158		if ( bHardCoreMode )
00159			Damage *= 1.5;
00160	
00161		//skill level modification
00162		if ( (instigatedBy.Skill < 1.5) && instigatedBy.IsA('Bots') && injured.IsA('PlayerPawn') )
00163			Damage = Damage * (0.7 + 0.15 * instigatedBy.skill);
00164	
00165		return (Damage * instigatedBy.DamageScaling);
00166	}
00167	
00168	function float PlaySpawnEffect(inventory Inv)
00169	{
00170		spawn( class 'ReSpawn',,, Inv.Location );
00171		return 0.3;
00172	}
00173	
00174	function RestartGame()
00175	{
00176		local string NextMap;
00177		local MapList myList;
00178	
00179		// multipurpose don't restart variable
00180		if ( bDontRestart )
00181			return;
00182	
00183		log("Restart Game");
00184	
00185		// these server travels should all be relative to the current URL
00186		if ( bChangeLevels && !bAlreadyChanged && (MapListType != None) )
00187		{
00188			// open a the nextmap actor for this game type and get the next map
00189			bAlreadyChanged = true;
00190			myList = spawn(MapListType);
00191			NextMap = myList.GetNextMap();
00192			myList.Destroy();
00193			if ( NextMap == "" )
00194				NextMap = GetMapName(MapPrefix, NextMap,1);
00195			if ( NextMap != "" )
00196			{
00197				log("Changing to "$NextMap);
00198				Level.ServerTravel(NextMap, false);
00199				return;
00200			}
00201		}
00202	
00203		Level.ServerTravel("?Restart" , false);
00204	}
00205	
00206	event playerpawn Login
00207	(
00208		string Portal,
00209		string Options,
00210		out string Error,
00211		class<playerpawn> SpawnClass
00212	)
00213	{
00214		local playerpawn NewPlayer;
00215	
00216		NewPlayer = Super.Login(Portal, Options, Error, SpawnClass );
00217		if ( NewPlayer != None )
00218		{
00219			if ( Left(NewPlayer.PlayerReplicationInfo.PlayerName, 6) == DefaultPlayerName )
00220				ChangeName( NewPlayer, (DefaultPlayerName$NumPlayers), false );
00221			NewPlayer.bAutoActivate = true;
00222		}
00223	
00224		return NewPlayer;
00225	}
00226	
00227	function bool AddBot()
00228	{
00229		local NavigationPoint StartSpot;
00230		local bots NewBot;
00231		local int BotN;
00232	
00233		Difficulty = BotConfig.Difficulty;
00234		BotN = BotConfig.ChooseBotInfo();
00235		
00236		// Find a start spot.
00237		StartSpot = FindPlayerStart(None, 255);
00238		if( StartSpot == None )
00239		{
00240			log("Could not find starting spot for Bot");
00241			return false;
00242		}
00243	
00244		// Try to spawn the player.
00245		NewBot = Spawn(BotConfig.GetBotClass(BotN),,,StartSpot.Location,StartSpot.Rotation);
00246	
00247		if ( NewBot == None )
00248			return false;
00249	
00250		if ( (bHumansOnly || Level.bHumansOnly) && !NewBot.bIsHuman )
00251		{
00252			NewBot.Destroy();
00253			log("Failed to spawn bot");
00254			return false;
00255		}
00256	
00257		StartSpot.PlayTeleportEffect(NewBot, true);
00258	
00259		// Init player's information.
00260		BotConfig.Individualize(NewBot, BotN, NumBots);
00261		NewBot.ViewRotation = StartSpot.Rotation;
00262	
00263		// broadcast a welcome message.
00264		BroadcastMessage( NewBot.PlayerReplicationInfo.PlayerName$EnteredMessage, true );
00265	
00266		AddDefaultInventory( NewBot );
00267		NumBots++;
00268	
00269		NewBot.PlayerReplicationInfo.bIsABot = True;
00270	
00271		// Set the player's ID.
00272		NewBot.PlayerReplicationInfo.PlayerID = CurrentID++;
00273	
00274		// Log it.
00275		if (LocalLog != None)
00276			LocalLog.LogPlayerConnect(NewBot);
00277		if (WorldLog != None)
00278			WorldLog.LogPlayerConnect(NewBot);
00279	
00280		return true;
00281	}
00282	
00283	function Logout(pawn Exiting)
00284	{
00285		Super.Logout(Exiting);
00286		if ( Exiting.IsA('Bots') )
00287			NumBots--;
00288	}
00289		
00290	function Timer()
00291	{
00292		Super.Timer();
00293	
00294		if ( (RemainingBots > 0) && AddBot() )
00295			RemainingBots--;
00296	
00297		if ( bGameEnded )
00298		{
00299			RemainingTime--;
00300			if ( RemainingTime < -7 )
00301				RestartGame();
00302		}
00303		else if ( TimeLimit > 0 )
00304		{
00305			RemainingTime--;
00306			switch (RemainingTime)
00307			{
00308				case 300:
00309					BroadcastMessage(TimeMessage[0], True, 'CriticalEvent');
00310					break;
00311				case 240:
00312					BroadcastMessage(TimeMessage[1], True, 'CriticalEvent');
00313					break;
00314				case 180:
00315					BroadcastMessage(TimeMessage[2], True, 'CriticalEvent');
00316					break;
00317				case 120:
00318					BroadcastMessage(TimeMessage[3], True, 'CriticalEvent');
00319					break;
00320				case 60:
00321					BroadcastMessage(TimeMessage[4], True, 'CriticalEvent');
00322					break;
00323				case 30:
00324					BroadcastMessage(TimeMessage[5], True, 'CriticalEvent');
00325					break;
00326				case 10:
00327					BroadcastMessage(TimeMessage[6], True, 'CriticalEvent');
00328					break;
00329				case 5:
00330					BroadcastMessage(TimeMessage[7], True, 'CriticalEvent');
00331					break;
00332				case 4:
00333					BroadcastMessage(TimeMessage[8], True, 'CriticalEvent');
00334					break;
00335				case 3:
00336					BroadcastMessage(TimeMessage[9], True, 'CriticalEvent');
00337					break;
00338				case 2:
00339					BroadcastMessage(TimeMessage[10], True, 'CriticalEvent');
00340					break;
00341				case 1:
00342					BroadcastMessage(TimeMessage[11], True, 'CriticalEvent');
00343					break;
00344				case 0:
00345					BroadcastMessage(TimeMessage[12], True, 'CriticalEvent');
00346					break;
00347			}
00348			if ( RemainingTime <= 0 )
00349				EndGame("timelimit");
00350		}
00351	}
00352	
00353	/* FindPlayerStart()
00354	returns the 'best' player start for this player to start from.
00355	Re-implement for each game type
00356	*/
00357	function NavigationPoint FindPlayerStart( Pawn Player, optional byte InTeam, optional string incomingName )
00358	{
00359		local PlayerStart Dest, Candidate[4], Best;
00360		local float Score[4], BestScore, NextDist;
00361		local pawn OtherPlayer;
00362		local int i, num;
00363		local Teleporter Tel;
00364		local NavigationPoint N;
00365	
00366		if( incomingName!="" )
00367			foreach AllActors( class 'Teleporter', Tel )
00368				if( string(Tel.Tag)~=incomingName )
00369					return Tel;
00370	
00371		num = 0;
00372		//choose candidates	
00373		N = Level.NavigationPointList;
00374		While ( N != None )
00375		{
00376			if ( N.IsA('PlayerStart') && !N.Region.Zone.bWaterZone )
00377			{
00378				if (num<4)
00379					Candidate[num] = PlayerStart(N);
00380				else if (Rand(num) < 4)
00381					Candidate[Rand(4)] = PlayerStart(N);
00382				num++;
00383			}
00384			N = N.nextNavigationPoint;
00385		}
00386	
00387		if (num == 0 )
00388			foreach AllActors( class 'PlayerStart', Dest )
00389			{
00390				if (num<4)
00391					Candidate[num] = Dest;
00392				else if (Rand(num) < 4)
00393					Candidate[Rand(4)] = Dest;
00394				num++;
00395			}
00396	
00397		if (num>4) num = 4;
00398		else if (num == 0)
00399			return None;
00400			
00401		//assess candidates
00402		for (i=0;i<num;i++)
00403			Score[i] = 4000 * FRand(); //randomize
00404			
00405		for ( OtherPlayer=Level.PawnList; OtherPlayer!=None; OtherPlayer=OtherPlayer.NextPawn)	
00406			if ( OtherPlayer.bIsPlayer && (OtherPlayer.Health > 0) )
00407				for (i=0;i<num;i++)
00408					if ( OtherPlayer.Region.Zone == Candidate[i].Region.Zone )
00409					{
00410						NextDist = VSize(OtherPlayer.Location - Candidate[i].Location);
00411						if (NextDist < OtherPlayer.CollisionRadius + OtherPlayer.CollisionHeight)
00412							Score[i] -= 1000000.0;
00413						else if ( (NextDist < 2000) && OtherPlayer.LineOfSightTo(Candidate[i]) )
00414							Score[i] -= 10000.0;
00415					}
00416		
00417		BestScore = Score[0];
00418		Best = Candidate[0];
00419		for (i=1;i<num;i++)
00420			if (Score[i] > BestScore)
00421			{
00422				BestScore = Score[i];
00423				Best = Candidate[i];
00424			}
00425	
00426		return Best;
00427	}
00428	
00429	/* AcceptInventory()
00430	Examine the passed player's inventory, and accept or discard each item
00431	* AcceptInventory needs to gracefully handle the case of some inventory
00432	being accepted but other inventory not being accepted (such as the default
00433	weapon).  There are several things that can go wrong: A weapon's
00434	AmmoType not being accepted but the weapon being accepted -- the weapon
00435	should be killed off. Or the player's selected inventory item, active
00436	weapon, etc. not being accepted, leaving the player weaponless or leaving
00437	the HUD inventory rendering messed up (AcceptInventory should pick another
00438	applicable weapon/item as current).
00439	*/
00440	function AcceptInventory(pawn PlayerPawn)
00441	{
00442		//deathmatch accepts no inventory
00443		local inventory Inv;
00444		for( Inv=PlayerPawn.Inventory; Inv!=None; Inv=Inv.Inventory )
00445			Inv.Destroy();
00446		PlayerPawn.Weapon = None;
00447		PlayerPawn.SelectedItem = None;
00448		AddDefaultInventory( PlayerPawn );
00449	}
00450	
00451	function ChangeName( Pawn Other, coerce string S, bool bNameChange )
00452	{
00453		local pawn APlayer;
00454	
00455		if ( S == "" )
00456			return;
00457	
00458		if (Other.PlayerReplicationInfo.PlayerName~=S)
00459			return;
00460		
00461		APlayer = Level.PawnList;
00462		
00463		While ( APlayer != None )
00464		{	
00465			if ( APlayer.bIsPlayer && (APlayer.PlayerReplicationInfo.PlayerName~=S) )
00466			{
00467				Other.ClientMessage(S$NoNameChange);
00468				return;
00469			}
00470			APlayer = APlayer.NextPawn;
00471		}
00472	
00473		if (bNameChange)
00474			BroadcastMessage(Other.PlayerReplicationInfo.PlayerName$GlobalNameChange$S, false);
00475				
00476		Other.PlayerReplicationInfo.PlayerName = S;
00477	
00478		if (LocalLog != None)
00479			LocalLog.LogNameChange(Other);
00480		if (WorldLog != None)
00481			WorldLog.LogNameChange(Other);
00482	}
00483	
00484	function bool ShouldRespawn(Actor Other)
00485	{
00486		return ( (Inventory(Other) != None) && (Inventory(Other).ReSpawnTime!=0.0) );
00487	}
00488	
00489	function bool CanSpectate( pawn Viewer, actor ViewTarget )
00490	{
00491		return ( (Level.NetMode == NM_Standalone) || (Spectator(Viewer) != None) );
00492	}
00493	
00494	// Monitor killed messages for fraglimit
00495	function Killed(pawn killer, pawn Other, name damageType)
00496	{
00497		Super.Killed(killer, Other, damageType);
00498		if ( (killer == None) || (Other == None) )
00499			return;
00500		if ( !bTeamGame && (FragLimit > 0) && (killer.PlayerReplicationInfo.Score >= FragLimit) )
00501			EndGame("fraglimit");
00502	
00503		if ( BotConfig.bAdjustSkill && (killer.IsA('PlayerPawn') || Other.IsA('PlayerPawn')) )
00504		{
00505			if ( killer.IsA('Bots') )
00506				Bots(killer).AdjustSkill(true);
00507			if ( Other.IsA('Bots') )
00508				Bots(Other).AdjustSkill(false);
00509		}
00510	}	
00511	
00512	function EndGame( string Reason )
00513	{
00514		local actor A;
00515		local pawn aPawn;
00516	
00517		Super.EndGame(Reason);
00518	
00519		bGameEnded = true;
00520		aPawn = Level.PawnList;
00521		RemainingTime = -1; // use timer to force restart
00522	}
00523	
00524	defaultproperties
00525	{
00526	     bChangeLevels=True
00527	     bHardCoreMode=True
00528	     InitialBots=4
00529	     GlobalNameChange=" changed name to "
00530	     NoNameChange=" is already in use"
00531	     TimeMessage(0)="5 minutes left in the game!"
00532	     TimeMessage(1)="4 minutes left in the game!"
00533	     TimeMessage(2)="3 minutes left in the game!"
00534	     TimeMessage(3)="2 minutes left in the game!"
00535	     TimeMessage(4)="1 minute left in the game!"
00536	     TimeMessage(5)="30 seconds left!"
00537	     TimeMessage(6)="10 seconds left!"
00538	     TimeMessage(7)="5 seconds and counting..."
00539	     TimeMessage(8)="4..."
00540	     TimeMessage(9)="3..."
00541	     TimeMessage(10)="2..."
00542	     TimeMessage(11)="1..."
00543	     TimeMessage(12)="Time Up!"
00544	     BotConfigType=Class'UnrealShare.BotInfo'
00545	     bNoMonsters=True
00546	     bRestartLevel=False
00547	     bPauseable=False
00548	     bDeathMatch=True
00549	     ScoreBoardType=Class'UnrealShare.UnrealScoreBoard'
00550	     GameMenuType=Class'UnrealShare.UnrealDMGameOptionsMenu'
00551	     MapListType=Class'UnrealShare.DMmaplist'
00552	     MapPrefix="DM"
00553	     BeaconName="DM"
00554	     GameName="DeathMatch"
00555	}

End Source Code