Botpack
Class Domination

source: e:\games\UnrealTournament\Botpack\Classes\Domination.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Info
         |
         +--Engine.GameInfo
            |
            +--Botpack.TournamentGameInfo
               |
               +--Botpack.DeathMatchPlus
                  |
                  +--Botpack.TeamGamePlus
                     |
                     +--Botpack.Domination
Direct Known Subclasses:TrainingDOM

class Domination
extends Botpack.TeamGamePlus

//============================================================================= // Domination. //=============================================================================
Variables
 ControlPoint ControlPoints[16]
           control point list used for AI
 int DomScoreEvent
           used to track when to dump out periodic stat information
 bool bDumbDown
           reduce efficiency of bot team AI
 bool bNeutralPoints


Function Summary
 void CalcEndStats()
 bool CanTranslocate(Bot aBot)
 void ClearControl(Pawn Other)
 void EndGame(string Reason)
 bool FindSpecialAttractionFor(Bot aBot)
 void InitRatedGame(LadderInventory LadderObj, PlayerPawn LadderPlayer)
 void Logout(Pawn Exiting)
 void PostBeginPlay()
 bool RestartPlayer(Pawn aPlayer)
 void ScoreKill(Pawn Killer, Pawn Other)
 void SetBotOrders(Bot NewBot)
 Actor SetDefenseFor(Bot aBot)
 bool SetEndCams(string Reason)
 void Timer()



Source Code


00001	//=============================================================================
00002	// Domination.
00003	//=============================================================================
00004	class Domination extends TeamGamePlus
00005		config;
00006	
00007	var bool bNeutralPoints;
00008	var config bool bDumbDown;			// reduce efficiency of bot team AI
00009	var ControlPoint ControlPoints[16]; // control point list used for AI
00010										// (so game could have more than 16, but bots will only understand first 16
00011	var int DomScoreEvent;				// used to track when to dump out periodic stat information
00012	
00013	function PostBeginPlay()
00014	{
00015		local NavigationPoint N;
00016		local int TempTotal;
00017	
00018		Super.PostBeginPlay();
00019	
00020		for ( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
00021			if ( N.IsA('ControlPoint') )
00022			{
00023				ControlPoints[TempTotal] = ControlPoint(N);
00024				TempTotal++;
00025			}
00026	}
00027	
00028	function ScoreKill(pawn Killer, pawn Other)
00029	{
00030		Super.ScoreKill(Killer, Other);
00031	
00032		if ( Other.bIsPlayer && (Killer != None) && Killer.bIsPlayer 
00033			&& (Killer != Other) && (Killer.PlayerReplicationInfo.Team == Other.PlayerReplicationInfo.Team)
00034			&& (FriendlyFireScale > 0) )
00035				Killer.PlayerReplicationInfo.Score -= 1;
00036	}
00037	
00038	function InitRatedGame(LadderInventory LadderObj, PlayerPawn LadderPlayer)
00039	{
00040		bDumbDown = True;
00041		Super.InitRatedGame(LadderObj, LadderPlayer);
00042	}
00043	
00044	function bool SetEndCams(string Reason)
00045	{
00046		local TeamInfo BestTeam;
00047		local ControlPoint Best;
00048		local Pawn P;
00049		local int i,j, nbest, n;
00050		local PlayerPawn player;
00051	
00052		// find winner
00053		BestTeam = Teams[0];
00054		for ( i=1; i<MaxTeams; i++ )
00055		{
00056			if ( int(Teams[i].Score) > int(BestTeam.Score) )
00057				BestTeam = Teams[i];
00058			else if ( int(Teams[i].Score) == int(BestTeam.Score) )
00059			{
00060				n = 0;
00061				nbest = 0;
00062				// check who has more points currently
00063				for ( j=0; j<16; j++ )
00064					if ( ControlPoints[j] != None )
00065					{
00066						if ( ControlPoints[j].ControllingTeam == BestTeam )
00067							nbest++;
00068						else if ( ControlPoints[j].ControllingTeam == Teams[i] )
00069							n++;
00070					}
00071	
00072				if ( n > nbest )
00073					BestTeam = Teams[i];
00074			}
00075		}
00076	
00077		GameReplicationInfo.GameEndedComments = TeamPrefix@BestTeam.TeamName@GameEndedMessage;
00078	
00079		ForEach AllActors(class'ControlPoint', Best)
00080			if ( Best.ControllingTeam == BestTeam )
00081				break;
00082	
00083		EndTime = Level.TimeSeconds + 3.0;
00084		for ( P=Level.PawnList; P!=None; P=P.nextPawn )
00085		{
00086			player = PlayerPawn(P);
00087			P.GotoState('GameEnded');
00088			if ( Player != None )
00089			{
00090				player.bBehindView = true;
00091				player.ViewTarget = Best;
00092				if (!bTutorialGame)
00093					PlayWinMessage(Player, (Player.PlayerReplicationInfo.Team == BestTeam.TeamIndex));
00094				player.ClientGameEnded();
00095			}
00096		}
00097		CalcEndStats();
00098		return true;
00099	}
00100	
00101	function CalcEndStats()
00102	{
00103		EndStatsClass.Default.TotalGames++;
00104		EndStatsClass.Static.StaticSaveConfig();
00105	}
00106	
00107	function Timer()
00108	{
00109		local NavigationPoint N;
00110		local ControlPoint CP;
00111		local int i;
00112		local float c;
00113		local PlayerReplicationInfo PRI;
00114	
00115		if ( !bGameEnded )
00116		{
00117			c = 0.2;
00118			if ( TimeLimit > 0 )
00119			{
00120				if ( RemainingTime < 0.25 * TimeLimit )
00121				{
00122					if ( RemainingTime < 0.1 * TimeLimit )
00123						c = 0.8;
00124					else
00125						c = 0.4;
00126				}
00127			}
00128	
00129			if ( !bRequireReady || (CountDown <= 0) )
00130				for ( N=Level.NavigationPointList; N!=None; N=N.nextNavigationPoint )
00131				{
00132					CP = ControlPoint(N);
00133					if ( (CP != None) && (CP.ControllingTeam != None) && CP.bScoreReady )
00134					{
00135						CP.ControllingTeam.Score += c;
00136						CP.Controller.PlayerReplicationInfo.Score += c;
00137					}
00138				}
00139			DomScoreEvent++;
00140			if (DomScoreEvent >= 5)
00141			{
00142				DomScoreEvent = 0;
00143				for (i=0; i<4; i++)
00144				{
00145					if (Teams[i].Score > 0)
00146					{
00147						if (Level.Game.WorldLog != None)
00148							Level.Game.WorldLog.LogSpecialEvent("dom_score_update", i, Teams[i].Score);
00149						if (Level.Game.LocalLog != None)
00150							Level.Game.LocalLog.LogSpecialEvent("dom_score_update", i, Teams[i].Score);
00151					}
00152				}
00153				for (i=0; i<32; i++)
00154				{
00155					PRI = GameReplicationInfo.PRIArray[i];
00156					if (PRI != None)
00157					{
00158						if (Level.Game.WorldLog != None)
00159							Level.Game.WorldLog.LogSpecialEvent("dom_playerscore_update", PRI.PlayerID, int(PRI.Score));
00160						if (Level.Game.LocalLog != None)
00161							Level.Game.LocalLog.LogSpecialEvent("dom_playerscore_update", PRI.PlayerID, int(PRI.Score));				
00162					}
00163				}
00164			}
00165			if ( GoalTeamScore > 0 )
00166				for ( i=0; i<4; i++ )
00167					if ( Teams[i].Score >= GoalTeamScore )
00168						EndGame("teamscorelimit");
00169		}
00170		Super.Timer();
00171	}
00172	
00173	function bool CanTranslocate(Bot aBot)
00174	{
00175		if ( aBot.bNovice && (aBot.Skill < 2) )
00176			return false;
00177		return Super.CanTranslocate(aBot);
00178	} 
00179	
00180	function ClearControl(Pawn Other)
00181	{
00182		local NavigationPoint N;
00183		local Pawn P, Pick;
00184		local int Num;
00185	
00186		// find a teammate
00187		if ( !Other.bIsPlayer || (Other.PlayerReplicationInfo.Team == 255) )
00188			return;
00189	
00190		for ( P=Level.PawnList; P!=None; P=P.NextPawn )
00191			if ( P.bIsPlayer && (P != Other) && (P.PlayerReplicationInfo.Team == Other.PlayerReplicationInfo.Team) )
00192			{
00193				Num++;
00194				if ( (Pick == None) || (Rand(Num) == 1) )
00195					Pick = P;
00196			}
00197		for ( N=Level.NavigationPointList; N!=None; N=N.nextNavigationPoint )
00198			if ( N.IsA('ControlPoint') && (ControlPoint(N).ControllingTeam != None) )
00199			{
00200				if ( ControlPoint(N).Controller == Other )
00201				{
00202					ControlPoint(N).Controller = Pick;
00203					ControlPoint(N).UpdateStatus();
00204				}
00205			}
00206	}
00207	
00208	function Logout( pawn Exiting )
00209	{
00210		ClearControl(Exiting);
00211		Super.Logout(Exiting);
00212	}
00213	
00214	function bool RestartPlayer( pawn aPlayer )	
00215	{
00216		local Bot B;
00217	
00218		B = Bot(aPlayer);
00219		if ( (B != None) && (B.Orders == 'Defend') )
00220			B.SetOrders('Freelance', None);
00221	
00222		return Super.RestartPlayer(aPlayer);
00223	}
00224	
00225	function Actor SetDefenseFor(Bot aBot)
00226	{
00227		local Actor Result;
00228		local int i, j;
00229		local NavigationPoint N;
00230	
00231		if ( ControlPoint(aBot.OrderObject) != None )
00232			return aBot.OrderObject;
00233	
00234		while ( (i<16) && (ControlPoints[i] != None) )
00235		{
00236			if ( (ControlPoints[i].ControllingTeam != None)
00237				&& (ControlPoints[i].ControllingTeam.TeamIndex == aBot.PlayerReplicationInfo.Team) )
00238			{
00239				j++;
00240				if ( (Result == None) || ( FRand() < 1.0/float(j)) )
00241					Result = N;
00242			}	
00243			i++;
00244		}
00245	
00246		return Result;		
00247	}
00248	
00249	function bool FindSpecialAttractionFor(Bot aBot)
00250	{
00251		local float bestweight, newweight;
00252		local ControlPoint Best, Near;
00253		local int i, count, maxdist, t;
00254		local bool bOrdered, bFound, bBehind;
00255	
00256		if ( aBot.LastAttractCheck == Level.TimeSeconds )
00257			return false;
00258		aBot.LastAttractCheck = Level.TimeSeconds;
00259	
00260		if ( aBot.Orders == 'Defend' )
00261		{
00262			if ( (aBot.OrderObject == None) || !aBot.OrderObject.IsA('ControlPoint') )
00263				aBot.Orders = 'FreeLance';
00264			else if ( (ControlPoint(aBot.OrderObject).ControllingTeam == None)
00265						|| (ControlPoint(aBot.OrderObject).ControllingTeam.TeamIndex != aBot.PlayerReplicationInfo.Team) )
00266			{
00267				if ( VSize(aBot.OrderObject.Location - aBot.Location) < 20 )
00268				{
00269					aBot.OrderObject.Touch(aBot);
00270					return false;
00271				}
00272				else if ( aBot.ActorReachable(aBot.OrderObject) )
00273				{
00274					bFound = true;
00275					aBot.MoveTarget = aBot.OrderObject;
00276				}
00277				else
00278				{
00279					aBot.MoveTarget = aBot.FindPathToward(aBot.OrderObject);
00280					bFound = ( aBot.MoveTarget != None );
00281				}
00282				if ( bFound )
00283				{
00284					if ( aBot.Enemy != None )
00285						aBot.bReadyToAttack = true;
00286					SetAttractionStateFor(aBot);
00287					return true;
00288				}
00289				return false;
00290			}
00291			else
00292				return false;					
00293		}
00294		// also "no movetarget"	in fallback		
00295		bOrdered = (aBot.Orders == 'Follow') || (aBot.Orders == 'Hold');
00296		if ( !bOrdered && bDumbdown && aBot.bDumbdown && !bNeutralPoints )
00297		{
00298			// dumbdown bot if its team isn't too far behind
00299			for ( i=0; i< MaxTeams; i++ )
00300				if ( Teams[i].score > Teams[aBot.PlayerReplicationInfo.Team].score + 20 )
00301					bBehind = true;
00302			bOrdered = !bBehind;
00303		}
00304					
00305		if ( bOrdered || (aBot.Enemy != None) || (aBot.Weapon == None) 
00306			|| (aBot.Weapon.AIRating < 0.5) || (aBot.Health < 70) )
00307		{
00308			if ( bOrdered )
00309				MaxDist = 1200;
00310			else
00311				MaxDist = 1700;
00312			// change nearby enemy or neutral controlpoint
00313			i = 0;
00314			bNeutralPoints = false;
00315			while ( (i<16) && (ControlPoints[i] != None) )
00316			{
00317				if ( ((ControlPoints[i].ControllingTeam == None) 
00318					|| (ControlPoints[i].ControllingTeam.TeamIndex != aBot.PlayerReplicationInfo.Team))
00319					&& (VSize(aBot.Location - ControlPoints[i].Location) < MaxDist)
00320					&& aBot.LineOfSightTo(ControlPoints[i]) )
00321				{
00322					if ( ControlPoints[i].ControllingTeam == None )
00323					{
00324						bNeutralPoints = true;
00325						if ( bOrdered && (aBot.Orders != 'Follow') && (aBot.Orders != 'Hold') )
00326						{
00327							aBot.bDumbDown = false; 
00328							bOrdered = false;
00329						}
00330					}
00331										
00332					if ( VSize(ControlPoints[i].Location - aBot.Location) < 20 )
00333					{
00334						ControlPoints[i].Touch(aBot);
00335						return false;
00336					}
00337					else if ( aBot.ActorReachable(ControlPoints[i]) )
00338					{
00339						bFound = true;
00340						aBot.MoveTarget = ControlPoints[i];
00341					}
00342					else if ( !bOrdered )
00343					{
00344						aBot.OrderObject = ControlPoints[i];
00345						BotReplicationInfo(aBot.PlayerReplicationInfo).OrderObject = None;
00346						aBot.MoveTarget = aBot.FindPathToward(ControlPoints[i]);
00347						bFound = ( aBot.MoveTarget != None );
00348					}
00349					if ( bFound )
00350					{
00351						if ( aBot.Enemy != None )
00352							aBot.bReadyToAttack = true;
00353						SetAttractionStateFor(aBot);
00354						return true;
00355					}
00356				}	
00357				i++;
00358			}
00359			if ( bOrdered || (aBot.Enemy == None) )
00360				return false;
00361	
00362			i = 0;
00363			while ( (i<16) && (ControlPoints[i] != None) )
00364			{
00365				if ( (ControlPoints[i].ControllingTeam == None) 
00366					|| (ControlPoints[i].ControllingTeam.TeamIndex != aBot.PlayerReplicationInfo.Team) )
00367					Count--;
00368				else
00369					Count++;
00370				i++;
00371			}
00372			if ( Count > 0 )
00373				return false; // already have an advantage in control points
00374		}
00375	
00376		//log("Find Special Attraction for"@aBot@"in state"@aBot.GetStateName());
00377	
00378		Best = ControlPoint(aBot.OrderObject);
00379		if ( (Best == None)
00380			|| ((Best.ControllingTeam != None)
00381				&& (Best.ControllingTeam.TeamIndex == aBot.PlayerReplicationInfo.Team)))
00382		{
00383			bestweight = 10000000;
00384			while ( (i<16) && (ControlPoints[i] != None) )
00385			{
00386				if ( ControlPoints[i].ControllingTeam == None )
00387					newweight = VSize(ControlPoints[i].location - aBot.location) * 0.1;
00388				else if ( (ControlPoints[i].ControllingTeam.TeamIndex != aBot.PlayerReplicationInfo.Team) )
00389				{
00390					newweight = VSize(ControlPoints[i].location - aBot.location) + 2 * Abs(ControlPoints[i].Location.Z - aBot.Location.Z);
00391					newweight *= (0.8 + 0.4 * FRand());
00392				}
00393				else 
00394					newweight = 90000000;
00395	
00396				if ( newweight < bestweight )
00397				{
00398					bestweight = newweight;
00399					Best = ControlPoints[i];
00400				}
00401				i++;
00402			}
00403		}
00404	
00405		if ( Best != None )
00406		{
00407			BotReplicationInfo(aBot.PlayerReplicationInfo).OrderObject = None;
00408			aBot.OrderObject = Best;
00409			if ( VSize(Best.Location - aBot.Location) < 20 )
00410			{
00411				aBot.OrderObject = None;
00412				Best.Touch(aBot);
00413				return false;
00414			}
00415			else if ( aBot.ActorReachable(Best) )
00416				aBot.MoveTarget = Best;
00417			else
00418				aBot.MoveTarget = aBot.FindPathToward(Best);
00419	
00420			if ( aBot.MoveTarget != None )
00421			{
00422				if ( aBot.bVerbose )
00423					log(aBot$" moving toward "$Best$" using "$aBot.MoveTarget);
00424				SetAttractionStateFor(aBot);
00425				return true;
00426			}
00427			else 
00428			{
00429				if ( FRand() < 0.3 )
00430					aBot.OrderObject = None;
00431				if ( aBot.bVerbose )
00432					log(aBot@"no path to"@Best.PointName);
00433			}
00434				
00435		}
00436		else if ( aBot.bVerbose )
00437			log(aBot@"found no best control point");
00438		return false;
00439	}
00440	
00441	function SetBotOrders(Bot NewBot)
00442	{
00443		local Pawn P, L;
00444		local int num, total;
00445		local Bot B;
00446	
00447		// only follow players, if there are any
00448		if ( NumSupportingPlayer == 0 ) 
00449		{
00450			For ( P=Level.PawnList; P!=None; P= P.NextPawn )
00451				if ( P.IsA('PlayerPawn') && (P.PlayerReplicationInfo.Team == NewBot.PlayerReplicationInfo.Team)
00452					&& !P.IsA('Spectator') )
00453			{
00454				num++;
00455				if ( (L == None) || (FRand() < 1.0/float(num)) )
00456					L = P;
00457			}
00458	
00459			if ( L != None )
00460			{
00461				NumSupportingPlayer++;
00462				NewBot.SetOrders('Follow',L,true);
00463				return;
00464			}
00465		}
00466		num = 0;
00467		For ( P=Level.PawnList; P!=None; P= P.NextPawn )
00468			if ( P.bIsPlayer && (P.PlayerReplicationInfo.Team == NewBot.PlayerReplicationInfo.Team) )
00469			{
00470				total++;
00471				if ( (P != NewBot) && P.IsA('Bot') )	
00472				{
00473					B = Bot(P);
00474					if ( B.Orders == 'FreeLance' )
00475					{
00476						num++;
00477						if ( (L == None) || (FRand() < 1.0/float(num)) )
00478							L = P;
00479					}
00480					else if ( (B.Orders == 'Follow') && (B.OrderObject == L) )
00481						L = None;
00482				}
00483			}
00484					
00485		if ( (L != None) && (total > 3) && (FRand() < (float(num) - 2.0)/(float(total) - 2.5)) )
00486		{
00487			NewBot.SetOrders('Follow',L,true);
00488			return;
00489		}
00490		NewBot.SetOrders('Freelance', None,true);
00491	}				 
00492	
00493	function EndGame( string Reason )
00494	{
00495		local int i;
00496		local PlayerReplicationInfo PRI;
00497	
00498		for (i=0; i<4; i++)
00499		{
00500			if (Teams[i].Score > 0)
00501			{
00502				if (Level.Game.WorldLog != None)
00503					Level.Game.WorldLog.LogSpecialEvent("dom_score_update", i, Teams[i].Score);
00504				if (Level.Game.LocalLog != None)
00505					Level.Game.LocalLog.LogSpecialEvent("dom_score_update", i, Teams[i].Score);
00506			}
00507		}
00508		for (i=0; i<32; i++)
00509		{
00510			PRI = GameReplicationInfo.PRIArray[i];
00511			if (PRI != None)
00512			{
00513				if (Level.Game.WorldLog != None)
00514					Level.Game.WorldLog.LogSpecialEvent("dom_playerscore_update", PRI.PlayerID, int(PRI.Score));
00515				if (Level.Game.LocalLog != None)
00516					Level.Game.LocalLog.LogSpecialEvent("dom_playerscore_update", PRI.PlayerID, int(PRI.Score));				
00517			}
00518		}
00519	
00520		Super.EndGame( Reason );
00521	}
00522	
00523	defaultproperties
00524	{
00525	     bScoreTeamKills=False
00526	     GoalTeamScore=100.000000
00527	     bUseTranslocator=True
00528	     bRatedTranslocator=True
00529	     StartUpMessage="Capture and hold control points to win."
00530	     gamegoal="points wins the match!"
00531	     MaxCommanders=0
00532	     LadderTypeIndex=3
00533	     bCoopWeaponMode=True
00534	     ScoreBoardType=Class'Botpack.DominationScoreboard'
00535	     HUDType=Class'Botpack.ChallengeDominationHUD'
00536	     MapListType=Class'Botpack.DOMMapList'
00537	     MapPrefix="DOM"
00538	     BeaconName="DOM"
00539	     GameName="Domination"
00540	}

End Source Code