Botpack
Class CTFGame

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

class CTFGame
extends Botpack.TeamGamePlus

//============================================================================= // CTFGame. //=============================================================================
Variables
 sound CaptureSound[4]
 float LastGotFlag
 float LastSeeFlagCarrier
 sound ReturnSound


Function Summary
 bool AllowTranslocation(Pawn Other, vector Dest)
     
// AllowTranslocation - return true if Other can teleport to Dest
 byte AssessBotAttitude(Bot aBot, Pawn Other)
 void CalcEndStats()
 bool CanTranslocate(Bot aBot)
     
// ShouldTranslocate - return true if abot should use translocation
 bool CheckForTranslocators(Bot aBot)
 bool CheckThisTranslocator(Bot aBot, TranslocatorTarget T)
 bool FindPathToBase(Bot aBot, FlagBase aBase)
 bool FindSpecialAttractionFor(Bot aBot)
 float GameThreatAdd(Bot aBot, Pawn Other)
 void Killed(Pawn Killer, Pawn Other, name damageType)
 void Logout(Pawn Exiting)
 void PickAmbushSpotFor(Bot aBot)
 byte PriorityObjective(Bot aBot)
 int ReduceDamage(int Damage, name DamageType, Pawn injured, Pawn instigatedBy)
 bool RestartPlayer(Pawn aPlayer)
 void ScoreFlag(Pawn Scorer, CTFFlag theFlag)
 void ScoreKill(Pawn Killer, Pawn Other)
 void SetBotOrders(Bot NewBot)
 Actor SetDefenseFor(Bot aBot)
 bool SetEndCams(string Reason)



Source Code


00001	//=============================================================================
00002	// CTFGame.
00003	//=============================================================================
00004	class CTFGame extends TeamGamePlus
00005		config;
00006	
00007	#exec AUDIO IMPORT FILE="Sounds\CTF\RockOnDude.wav" NAME="CaptureSound" GROUP="CTF"
00008	#exec AUDIO IMPORT FILE="Sounds\CTF\ctf9.wav" NAME="CaptureSound2" GROUP="CTF"
00009	#exec AUDIO IMPORT FILE="Sounds\CTF\ctf10.wav" NAME="CaptureSound3" GROUP="CTF"
00010	#exec AUDIO IMPORT FILE="Sounds\CTF\returnf1.wav" NAME="ReturnSound" GROUP="CTF"
00011	
00012	var() sound CaptureSound[4];
00013	var() sound ReturnSound;
00014	var float LastGotFlag;
00015	var float LastSeeFlagCarrier;
00016	
00017	function Logout(pawn Exiting)
00018	{
00019		if ( Exiting.PlayerReplicationInfo.HasFlag != None )
00020			CTFFlag(Exiting.PlayerReplicationInfo.HasFlag).SendHome();	
00021		Super.Logout(Exiting);
00022	}
00023	
00024	event InitGame( string Options, out string Error )
00025	{
00026		Super.InitGame(Options, Error);
00027		if ( bRatedGame )
00028			GoalTeamScore = 5;
00029	
00030		FragLimit = 0;
00031	}
00032	
00033	function Killed( pawn Killer, pawn Other, name damageType )
00034	{
00035		local int NextTaunt, i;
00036		local bool bAutoTaunt;
00037	
00038		if ( Other.bIsPlayer && (Other.PlayerReplicationInfo.HasFlag != None) )
00039		{
00040			if ( (Killer != None) && Killer.bIsPlayer && Other.bIsPlayer && (Killer.PlayerReplicationInfo.Team != Other.PlayerReplicationInfo.Team) )
00041			{
00042				killer.PlayerReplicationInfo.Score += 4;
00043				bAutoTaunt = ((TournamentPlayer(Killer) != None) && TournamentPlayer(Killer).bAutoTaunt);
00044				if ( (Bot(Killer) != None) || bAutoTaunt )
00045				{
00046					NextTaunt = Rand(class<ChallengeVoicePack>(Killer.PlayerReplicationInfo.VoiceType).Default.NumTaunts);
00047					for ( i=0; i<4; i++ )
00048					{
00049						if ( NextTaunt == LastTaunt[i] )
00050							NextTaunt = Rand(class<ChallengeVoicePack>(Killer.PlayerReplicationInfo.VoiceType).Default.NumTaunts);
00051						if ( i > 0 )
00052							LastTaunt[i-1] = LastTaunt[i];
00053					}	
00054					LastTaunt[3] = NextTaunt;
00055					killer.SendGlobalMessage(None, 'AUTOTAUNT', NextTaunt, 5);
00056				}
00057			}
00058			CTFFlag(Other.PlayerReplicationInfo.HasFlag).Drop(0.5 * Other.Velocity);
00059		}
00060	
00061		Super.Killed(Killer, Other, damageType);
00062	}
00063	
00064	function ScoreKill(pawn Killer, pawn Other)
00065	{
00066	
00067		if( (killer == Other) || (killer == None) )
00068			Other.PlayerReplicationInfo.Score -= 1;
00069		else if ( killer != None )
00070		{
00071			killer.killCount++;
00072			if ( Killer.bIsPlayer && Other.bIsPlayer && (Killer.PlayerReplicationInfo.Team != Other.PlayerReplicationInfo.Team) )
00073				Killer.PlayerReplicationInfo.Score += 1;
00074		}
00075		if ( bAltScoring && (Killer != Other) && (killer != None) && Other.bIsPlayer )
00076			Other.PlayerReplicationInfo.Score -= 1;
00077	
00078		Other.DieCount++;
00079	
00080		BaseMutator.ScoreKill(Killer, Other);
00081	}	
00082	
00083	function bool SetEndCams(string Reason)
00084	{
00085		local TeamInfo Best;
00086		local FlagBase BestBase;
00087		local CTFFlag BestFlag;
00088		local Pawn P;
00089		local int i;
00090		local PlayerPawn Player;
00091	
00092		for ( i=0; i<MaxTeams; i++ )
00093			if ( (Best == None) || (Best.Score < Teams[i].Score) )
00094				Best = Teams[i];
00095	
00096		for ( i=0; i<MaxTeams; i++ )
00097			if ( (Best.TeamIndex != i) && (Best.Score == Teams[i].Score) )
00098			{
00099				BroadcastLocalizedMessage(DMMessageClass, 0);
00100				return false;
00101			}		
00102	
00103		// find winner
00104		ForEach AllActors(class'CTFFlag', BestFlag)
00105			if ( BestFlag.Team == Best.TeamIndex )
00106				break;
00107	
00108		BestBase = BestFlag.HomeBase;
00109		GameReplicationInfo.GameEndedComments = TeamPrefix@Best.TeamName@GameEndedMessage;
00110	
00111		EndTime = Level.TimeSeconds + 3.0;
00112		for ( P=Level.PawnList; P!=None; P=P.nextPawn )
00113		{
00114			P.GotoState('GameEnded');
00115			Player = PlayerPawn(P);
00116			if ( Player != None )
00117			{
00118				Player.bBehindView = true;
00119				Player.ViewTarget = BestBase;
00120				if (!bTutorialGame)
00121					PlayWinMessage(Player, (Player.PlayerReplicationInfo.Team == Best.TeamIndex));
00122				Player.ClientGameEnded();
00123			}
00124		}
00125		BestBase.bHidden = false;
00126		BestFlag.bHidden = true;
00127		CalcEndStats();
00128		return true;
00129	}
00130	
00131	function CalcEndStats()
00132	{
00133		EndStatsClass.Default.TotalGames++;
00134		EndStatsClass.Static.StaticSaveConfig();
00135	}
00136	
00137	function ScoreFlag(Pawn Scorer, CTFFlag theFlag)
00138	{
00139		local pawn TeamMate;
00140		local Actor A;
00141	
00142		if ( Scorer.PlayerReplicationInfo.Team == theFlag.Team )
00143		{
00144			if (Level.Game.WorldLog != None)
00145			{
00146				Level.Game.WorldLog.LogSpecialEvent("flag_returned", Scorer.PlayerReplicationInfo.PlayerID, Teams[theFlag.Team].TeamIndex);
00147			}
00148			if (Level.Game.LocalLog != None)
00149			{
00150				Level.Game.LocalLog.LogSpecialEvent("flag_returned", Scorer.PlayerReplicationInfo.PlayerID, Teams[theFlag.Team].TeamIndex);
00151			}
00152			BroadcastLocalizedMessage( class'CTFMessage', 1, Scorer.PlayerReplicationInfo, None, TheFlag );
00153			for ( TeamMate=Level.PawnList; TeamMate!=None; TeamMate=TeamMate.NextPawn )
00154			{
00155				if ( TeamMate.IsA('PlayerPawn') )
00156					PlayerPawn(TeamMate).ClientPlaySound(ReturnSound);
00157				else if ( TeamMate.IsA('Bot') )
00158					Bot(TeamMate).SetOrders(BotReplicationInfo(TeamMate.PlayerReplicationInfo).RealOrders, BotReplicationInfo(TeamMate.PlayerReplicationInfo).RealOrderGiver, true);
00159			}
00160			return;
00161		}
00162	
00163		if ( bRatedGame && Scorer.IsA('PlayerPawn') )
00164			bFulfilledSpecial = true;
00165		Scorer.PlayerReplicationInfo.Score += 7;
00166		Teams[Scorer.PlayerReplicationInfo.Team].Score += 1.0;
00167	
00168		for ( TeamMate=Level.PawnList; TeamMate!=None; TeamMate=TeamMate.NextPawn )
00169		{
00170			if ( TeamMate.IsA('PlayerPawn') )
00171				PlayerPawn(TeamMate).ClientPlaySound(CaptureSound[Scorer.PlayerReplicationInfo.Team]);
00172			else if ( TeamMate.IsA('Bot') )
00173				Bot(TeamMate).SetOrders(BotReplicationInfo(TeamMate.PlayerReplicationInfo).RealOrders, BotReplicationInfo(TeamMate.PlayerReplicationInfo).RealOrderGiver, true);
00174		}
00175	
00176		if (Level.Game.WorldLog != None)
00177		{
00178			Level.Game.WorldLog.LogSpecialEvent("flag_captured", Scorer.PlayerReplicationInfo.PlayerID, Teams[theFlag.Team].TeamIndex);
00179		}
00180		if (Level.Game.LocalLog != None)
00181		{
00182			Level.Game.LocalLog.LogSpecialEvent("flag_captured", Scorer.PlayerReplicationInfo.PlayerID, Teams[theFlag.Team].TeamIndex);
00183		}
00184		EndStatsClass.Default.TotalFlags++;
00185		BroadcastLocalizedMessage( class'CTFMessage', 0, Scorer.PlayerReplicationInfo, None, TheFlag );
00186		if ( theFlag.HomeBase.Event != '' )
00187			foreach allactors(class'Actor', A, theFlag.HomeBase.Event )
00188				A.Trigger(theFlag.HomeBase,	Scorer);
00189	
00190		if ( (bOverTime || (GoalTeamScore != 0)) && (Teams[Scorer.PlayerReplicationInfo.Team].Score >= GoalTeamScore) )
00191			EndGame("teamscorelimit");
00192		else if ( bOverTime )
00193			EndGame("timelimit");
00194	}
00195	 
00196	function Actor SetDefenseFor(Bot aBot)
00197	{
00198		return CTFReplicationInfo(GameReplicationInfo).FlagList[aBot.PlayerReplicationInfo.Team].HomeBase;
00199	}
00200	
00201	
00202	function float GameThreatAdd(Bot aBot, Pawn Other)
00203	{
00204		local CTFFlag aFlag;
00205	
00206		if ( Other.PlayerReplicationInfo.HasFlag != None )
00207			return 10;
00208		else
00209			return 0;
00210	}
00211	
00212	function bool FindPathToBase(Bot aBot, FlagBase aBase)
00213	{
00214		if ( (aBot.AlternatePath != None) 
00215			&& ((aBot.AlternatePath.team == aBase.team) || aBot.AlternatePath.bTwoWay) )
00216		{
00217			if ( aBot.ActorReachable(aBot.AlternatePath) )
00218			{
00219				aBot.MoveTarget = aBot.AlternatePath;
00220				aBot.AlternatePath = None;
00221			}
00222			else
00223			{
00224				aBot.MoveTarget = aBot.FindPathToward(aBot.AlternatePath);
00225				if ( aBot.MoveTarget == None )
00226				{
00227					aBot.AlternatePath = None;
00228					aBot.MoveTarget = aBot.FindPathToward(aBase);
00229				}
00230			}
00231		}
00232		else						
00233			aBot.MoveTarget = aBot.FindPathToward(aBase);
00234	
00235		return (aBot.bNoClearSpecial || (aBot.MoveTarget != None));
00236	}
00237	
00238	function byte AssessBotAttitude(Bot aBot, Pawn Other)
00239	{
00240		if ( aBot.PlayerReplicationInfo.Team == Other.PlayerReplicationInfo.Team )
00241			return 3; //teammate
00242		else if ( (Other.bIsPlayer && (Other.PlayerReplicationInfo.HasFlag != None)) 
00243					|| (aBot.PlayerReplicationInfo.HasFlag != None) )
00244			return 1;
00245		else 
00246			return Super.AssessBotAttitude(aBot, Other);
00247	}
00248	
00249	function bool FindSpecialAttractionFor(Bot aBot)
00250	{
00251		local CTFFlag FriendlyFlag, EnemyFlag;
00252		local bool bSeeFlag, bReachHome, bOrdered;
00253		local float Dist;
00254	
00255		if ( aBot.LastAttractCheck == Level.TimeSeconds )
00256			return false;
00257		aBot.LastAttractCheck = Level.TimeSeconds;
00258	
00259		//log(aBot@"find special attraction in state"@aBot.GetStateName()@"at"@Level.TimeSeconds);	
00260		FriendlyFlag = CTFReplicationInfo(GameReplicationInfo).FlagList[aBot.PlayerReplicationInfo.Team];
00261		
00262		if ( aBot.PlayerReplicationInfo.Team == 0 )
00263			EnemyFlag = CTFReplicationInfo(GameReplicationInfo).FlagList[1];
00264		else
00265			EnemyFlag = CTFReplicationInfo(GameReplicationInfo).FlagList[0];
00266		
00267		bOrdered = aBot.bSniping || (aBot.Orders == 'Follow') || (aBot.Orders == 'Hold');
00268	
00269		if ( !FriendlyFlag.bHome  )
00270		{
00271			bSeeFlag = aBot.LineOfSightTo(FriendlyFlag.Position());
00272			FriendlyFlag.bKnownLocation = FriendlyFlag.bKnownLocation || bSeeFlag;
00273	
00274			if ( bSeeFlag && (FriendlyFlag.Holder == None) && aBot.ActorReachable(FriendlyFlag) )
00275			{
00276				if ( Level.TimeSeconds - LastGotFlag > 6 )
00277				{	
00278					LastGotFlag = Level.TimeSeconds;
00279					aBot.SendTeamMessage(None, 'OTHER', 8, 20);
00280				}
00281				aBot.MoveTarget = FriendlyFlag;
00282				SetAttractionStateFor(aBot);
00283				return true;
00284			}
00285	
00286			if ( EnemyFlag.Holder != aBot )
00287			{
00288				if ( bSeeFlag && (FriendlyFlag.Holder != None) )
00289				{	
00290					FriendlyFlag.bKnownLocation = true;
00291					if ( Level.TimeSeconds - LastSeeFlagCarrier > 6 )
00292					{
00293						LastSeeFlagCarrier = Level.TimeSeconds;
00294						aBot.SendTeamMessage(None, 'OTHER', 12, 10);
00295					}
00296					aBot.SetEnemy(FriendlyFlag.Holder);
00297					aBot.Orders = 'Freelance';
00298					aBot.MoveTarget = FriendlyFlag.Holder;
00299					if ( aBot.IsInState('Attacking') )
00300						return false;
00301					else
00302					{
00303						aBot.GotoState('Attacking');
00304						return true;
00305					}
00306				}
00307				else if ( aBot.Orders == 'Attack' )
00308				{
00309					// break off attack only if needed
00310					if ( bSeeFlag || (EnemyFlag.Holder != None) 
00311						|| (((FriendlyFlag.Position().Region.Zone != FriendlyFlag.Homebase.Region.Zone) || (VSize(FriendlyFlag.Homebase.Location - FriendlyFlag.Position().Location) > 1000)) 
00312							&& ((aBot.Region.Zone != EnemyFlag.Region.Zone)
00313								|| (VSize(aBot.Location - EnemyFlag.Location) > 1600) || (VSize(aBot.Location - FriendlyFlag.Position().Location) < 1200))) )
00314					{
00315						FriendlyFlag.bKnownLocation = true;
00316						aBot.MoveTarget = aBot.FindPathToward(FriendlyFlag.Position());
00317						aBot.AlternatePath = None;
00318						if ( aBot.MoveTarget != None )
00319						{
00320							SetAttractionStateFor(aBot);
00321							return true;
00322						}
00323					}
00324				}
00325				else if ( (!bOrdered || ABot.OrderObject.IsA('Bot')) 
00326					&& (FriendlyFlag.bKnownLocation || (FRand() < 0.1)) ) 
00327				{
00328					FriendlyFlag.bKnownLocation = true;
00329					aBot.MoveTarget = aBot.FindPathToward(FriendlyFlag.Position());
00330					if ( aBot.MoveTarget != None )
00331					{
00332						SetAttractionStateFor(aBot);
00333						return true;
00334					}
00335				}
00336			}
00337		}
00338	
00339		if ( EnemyFlag.Holder == aBot )
00340		{
00341			aBot.bCanTranslocate = false;
00342			bReachHome = aBot.ActorReachable(FriendlyFlag.HomeBase);
00343			if ( bReachHome && !FriendlyFlag.bHome )
00344			{
00345				aBot.SendTeamMessage(None, 'OTHER', 1, 25);
00346				aBot.Orders = 'Freelance';
00347				return false;
00348			}
00349			if ( bReachHome && (VSize(aBot.Location - FriendlyFlag.Location) < 30) )
00350				FriendlyFlag.Touch(aBot);
00351			if ( aBot.Enemy != None )
00352			{
00353				if ( aBot.Health < 60 )
00354					aBot.SendTeamMessage(None, 'OTHER', 13, 25);
00355				if ( !aBot.IsInState('FallBack') )
00356				{
00357					aBot.bNoClearSpecial = true;
00358					aBot.TweenToRunning(0.1);
00359					aBot.GotoState('Fallback', 'SpecialNavig');
00360				}
00361				if ( bReachHome )
00362					aBot.MoveTarget = FriendlyFlag.HomeBase;
00363				else
00364					return FindPathToBase(aBot, FriendlyFlag.HomeBase);
00365			}
00366			else
00367			{
00368				if ( !aBot.IsInState('Roaming') )
00369				{
00370					aBot.bNoClearSpecial = true;
00371					aBot.TweenToRunning(0.1);
00372					aBot.GotoState('Roaming', 'SpecialNavig');
00373				}
00374				if ( bReachHome )
00375					aBot.MoveTarget = FriendlyFlag.HomeBase;
00376				else
00377					return FindPathToBase(aBot, FriendlyFlag.HomeBase);
00378			}		
00379			return true;
00380		}
00381	
00382		if ( EnemyFlag.Holder == None )
00383		{
00384			if ( aBot.ActorReachable(EnemyFlag) )
00385			{
00386				aBot.MoveTarget = EnemyFlag;
00387				SetAttractionStateFor(aBot);
00388				return true;
00389			}
00390			else if ( (aBot.Orders == 'Attack')
00391					 || ((aBot.Orders == 'Follow') && aBot.OrderObject.IsA('Bot')
00392						&& ((Pawn(aBot.OrderObject).Health <= 0) 
00393							 || ((EnemyFlag.Region.Zone == aBot.Region.Zone) && (VSize(EnemyFlag.Location - aBot.Location) < 2000)))) )
00394			{
00395				if ( !aBot.bKamikaze
00396					&& ( (aBot.Weapon == None) || (aBot.Weapon.AIRating < 0.4)) )
00397				{
00398					aBot.bKamikaze = ( FRand() < 0.1 );
00399					return false;
00400				}
00401	
00402				if ( (aBot.Enemy != None) 
00403					&& (aBot.Enemy.IsA('PlayerPawn') || (aBot.Enemy.IsA('Bot') && (Bot(aBot.Enemy).Orders == 'Attack')))
00404					&& (((aBot.Enemy.Region.Zone == FriendlyFlag.HomeBase.Region.Zone) && (EnemyFlag.HomeBase.Region.Zone != FriendlyFlag.HomeBase.Region.Zone)) 
00405						|| (VSize(aBot.Enemy.Location - FriendlyFlag.HomeBase.Location) < 0.6 * VSize(aBot.Location - EnemyFlag.HomeBase.Location))) )
00406					{
00407						aBot.SendTeamMessage(None, 'OTHER', 14, 15); //"Incoming!"
00408						aBot.Orders = 'Freelance';
00409						return false;
00410					}
00411	
00412				if ( EnemyFlag.bHome )
00413					FindPathToBase(aBot, EnemyFlag.HomeBase);
00414				else
00415					aBot.MoveTarget = aBot.FindPathToward(EnemyFlag);
00416				if ( aBot.MoveTarget != None )
00417				{
00418					SetAttractionStateFor(aBot);
00419					return true;
00420				}
00421				else
00422				{
00423					if ( aBot.bVerbose )
00424						log(aBot$" no path to flag");
00425					return false;
00426				}
00427			}
00428			return false;
00429		}
00430	
00431		if ( (bOrdered && !aBot.OrderObject.IsA('Bot')) || (aBot.Weapon == None) || (aBot.Weapon.AIRating < 0.4) )
00432			return false;
00433	
00434		if ( (aBot.Enemy == None) && (aBot.Orders != 'Defend') )
00435		{
00436			Dist = VSize(aBot.Location - EnemyFlag.Holder.Location);
00437			if ( (Dist > 500) || (VSize(EnemyFlag.Holder.Velocity) > 230)
00438				|| !aBot.LineOfSightTo(EnemyFlag.Holder) )
00439			{
00440				aBot.MoveTarget = aBot.FindPathToward(EnemyFlag.Holder);
00441				if ( !aBot.IsInState('Roaming') )
00442				{
00443					aBot.bNoClearSpecial = true;
00444					aBot.TweenToRunning(0.1);
00445					aBot.GotoState('Roaming', 'SpecialNavig');
00446					return true;
00447				}
00448				return (aBot.MoveTarget != None);
00449			}
00450			else
00451			{
00452				if ( !aBot.bInitLifeMessage )
00453				{
00454					aBot.bInitLifeMessage = true;
00455					aBot.SendTeamMessage(EnemyFlag.Holder.PlayerReplicationInfo, 'OTHER', 3, 10);
00456				}
00457				if ( FRand() < 0.35 )
00458					aBot.GotoState('Wandering');
00459				else
00460				{
00461					aBot.CampTime = 1.0;
00462					aBot.bCampOnlyOnce = true;
00463					aBot.GotoState('Roaming', 'Camp');
00464				}
00465				return true;
00466			}
00467		}
00468		return false;
00469	}		
00470	
00471	function bool RestartPlayer(Pawn aPlayer)
00472	{
00473		local NavigationPoint N;
00474		local int num;
00475		local float totalWeight, selection, partialWeight;
00476		local bool bResult, bPowerPlay;
00477		local bot B;
00478		local Pawn P;
00479		
00480		bResult = Super.RestartPlayer(aPlayer);
00481	
00482		B = Bot(aPlayer);
00483		if ( B == None )
00484			return bResult;
00485	
00486		B.AlternatePath = None;
00487		
00488		if ( B.bPowerPlay || (BotReplicationInfo(B.PlayerReplicationInfo).RealOrders == 'Defend') )
00489		{
00490			// if bot only team and already one defender, 50% chance of powerplay for this guy if defender
00491			if ( FRand() < 0.5 )
00492			{
00493				B.bPowerPlay = false;
00494				B.SetOrders('Defend', None, true);
00495			}
00496			else
00497			{
00498				// check for bot only team and already a valid defender
00499				for ( P=Level.PawnList; P!=None; P=P.NextPawn )
00500				{
00501					if ( P.bIsPlayer && (P.PlayerReplicationInfo.Team == B.PlayerReplicationInfo.Team) )
00502					{
00503						if ( P.IsA('PlayerPawn') )
00504						{
00505							bPowerPlay = false;
00506							break;
00507						}
00508						else if ( (P != B) && P.IsA('Bot') && (Bot(P).Orders == 'Defend') )
00509							bPowerPlay = true;
00510					}
00511				}
00512				if ( bPowerPlay )
00513				{
00514					B.bPowerPlay = true;
00515					B.SetOrders('Attack', None, true);
00516				}
00517			}
00518		}
00519	
00520		if ( BotReplicationInfo(B.PlayerReplicationInfo).RealOrders != 'Attack' )
00521			return bResult;
00522	
00523		if ( FRand() < 0.8 )
00524		{
00525			for ( N=Level.NavigationPointList; N!=None; N=N.nextNavigationPoint )
00526				if ( N.IsA('AlternatePath') && (AlternatePath(N).team != B.PlayerReplicationInfo.team)
00527					&& !AlternatePath(N).bReturnOnly )
00528					TotalWeight += AlternatePath(N).SelectionWeight;
00529			selection = FRand() * TotalWeight;
00530			for ( N=Level.NavigationPointList; N!=None; N=N.nextNavigationPoint )
00531				if ( N.IsA('AlternatePath') && (AlternatePath(N).team != B.PlayerReplicationInfo.team) )
00532				{
00533					B.AlternatePath = AlternatePath(N);
00534					PartialWeight += AlternatePath(N).SelectionWeight;
00535					if ( PartialWeight > selection )
00536						break;
00537				}
00538		}
00539		return bResult;
00540	}
00541	
00542	function SetBotOrders(Bot NewBot)
00543	{
00544		local Pawn P, L, M;
00545		local int num;
00546		local bool bAvailable;
00547	
00548		if ( CurrentOrders[NewBot.PlayerReplicationInfo.Team] == 'Freelance' )
00549			CurrentOrders[NewBot.PlayerReplicationInfo.Team] = 'Attack';
00550		else if ( CurrentOrders[NewBot.PlayerReplicationInfo.Team] == 'Defend' )
00551			CurrentOrders[NewBot.PlayerReplicationInfo.Team] = 'Freelance';
00552		else 
00553		{
00554			CurrentOrders[NewBot.PlayerReplicationInfo.Team] = 'Defend';		
00555			if ( bNoviceMode )
00556				for ( P=Level.PawnList; P!=None; P= P.NextPawn )
00557					if ( P.bIsPlayer && (P != NewBot) && (P.PlayerReplicationInfo.Team == NewBot.PlayerReplicationInfo.Team)
00558						&& P.IsA('Bot') && (BotReplicationInfo(P.PlayerReplicationInfo).RealOrders == 'Defend') && (FRand() < 0.5) )
00559						{	
00560							CurrentOrders[NewBot.PlayerReplicationInfo.Team] = 'Attack';
00561							break;
00562						}
00563		}		
00564	
00565		if ( ((CurrentOrders[NewBot.PlayerReplicationInfo.Team] == 'Attack') || (CurrentOrders[NewBot.PlayerReplicationInfo.Team] == 'Freelance'))	
00566			&& (NumSupportingPlayer == 0) )
00567		{
00568			For ( P=Level.PawnList; P!=None; P=P.NextPawn )
00569				if ( P.IsA('PlayerPawn') && (P.PlayerReplicationInfo.Team == NewBot.PlayerReplicationInfo.Team)
00570					&& !P.IsA('Spectator') )
00571			{
00572				num++;
00573				if ( (L == None) || (FRand() < 1.0/float(num)) )
00574					L = P;
00575			}
00576	
00577			if ( L != None )
00578			{
00579				NumSupportingPlayer++;
00580				NewBot.SetOrders('Follow',L, true);
00581				return;
00582			}
00583			else if ( FRand() < 0.8 )
00584			{
00585				// no players on this team - possibly support other bot
00586				num = 0;
00587				For ( P=Level.PawnList; P!=None; P=P.NextPawn )
00588					if ( P.IsA('Bot') && (P.PlayerReplicationInfo.Team == NewBot.PlayerReplicationInfo.Team) 
00589						&& (Bot(P).Orders == 'Attack') )
00590				{
00591					num++;
00592					if ( (L == None) || (FRand() < 1.0/float(num)) )
00593					{
00594						// make sure P doesn't already have a follower
00595						bAvailable = true;
00596						for ( M=Level.PawnList; M!=None; M=M.NextPawn )
00597							if ( M.IsA('Bot') && (M.PlayerReplicationInfo.Team == NewBot.PlayerReplicationInfo.Team) 
00598								&& (Bot(M).Orders == 'Follow') && (Bot(M).OrderObject == P) )
00599								bAvailable = false;
00600						if ( bAvailable )
00601							L = P;
00602					}
00603				}
00604	
00605				if ( L != None )
00606				{
00607					NewBot.SetOrders('Follow',L, true);
00608					return;
00609				}
00610			}
00611		}
00612		
00613		if ( CurrentOrders[NewBot.PlayerReplicationInfo.Team] == 'Freelance' )
00614			NewBot.SetOrders('Attack', None, true);
00615		else	
00616			NewBot.SetOrders(CurrentOrders[NewBot.PlayerReplicationInfo.Team], None, true);
00617	}
00618	
00619	// AllowTranslocation - return true if Other can teleport to Dest
00620	function bool AllowTranslocation(Pawn Other, vector Dest )
00621	{
00622		if ( Other.PlayerReplicationInfo.HasFlag != None )
00623			CTFFlag(Other.PlayerReplicationInfo.HasFlag).Drop(0.5 * Other.Velocity);
00624	
00625		return true;
00626	}
00627	
00628	// ShouldTranslocate - return true if abot should use translocation
00629	function bool CanTranslocate(Bot aBot)
00630	{
00631		if ( aBot.PlayerReplicationInfo.HasFlag != None )
00632			return false;
00633	
00634		return Super.CanTranslocate(aBot);
00635	}
00636	
00637	function int ReduceDamage(int Damage, name DamageType, pawn injured, pawn instigatedBy)
00638	{
00639		if ( (instigatedBy != None) 
00640			&& (injured.PlayerReplicationInfo.Team != instigatedBy.PlayerReplicationInfo.Team)
00641			&& injured.IsA('Bot') 
00642			&& ((injured.health < 35) || (injured.PlayerReplicationInfo.HasFlag != None)) )
00643				Bot(injured).SendTeamMessage(None, 'OTHER', 4, 15);
00644	
00645		return Super.ReduceDamage(Damage, DamageType, injured, instigatedBy);
00646	}
00647	
00648	function byte PriorityObjective(Bot aBot)
00649	{
00650		local CTFFlag FriendlyFlag;
00651	
00652		FriendlyFlag = CTFReplicationInfo(GameReplicationInfo).FlagList[aBot.PlayerReplicationInfo.Team]; 
00653	
00654		if ( aBot.PlayerReplicationInfo.HasFlag != None )
00655		{
00656			if ( (VSize(aBot.Location - FriendlyFlag.HomeBase.Location) < 2000)
00657				&& aBot.LineOfSightTo(FriendlyFlag.HomeBase) )
00658				return 255;
00659			return 2;
00660		}
00661	
00662		if ( FriendlyFlag.Holder != None )
00663			return 1;
00664	
00665		return 0;
00666	}
00667	
00668	function PickAmbushSpotFor(Bot aBot)
00669	{
00670		if ( CheckForTranslocators(aBot) )
00671		{
00672			aBot.bSpecialAmbush = true;
00673			return;
00674		}
00675		Super.PickAmbushSpotFor(aBot);
00676	}
00677	
00678	function bool CheckForTranslocators(Bot aBot)
00679	{
00680		local TranslocatorTarget T;
00681	
00682		// check for translocators near base
00683		ForEach AllActors(class'TranslocatorTarget', T)
00684			if ( CheckThisTranslocator(aBot, T) )
00685				return true;
00686	
00687		return false;
00688	}
00689	
00690	function bool CheckThisTranslocator(Bot aBot, TranslocatorTarget T)
00691	{
00692		local FlagBase F;
00693	
00694		if ( aBot.Weapon.bMeleeWeapon )
00695			return false;
00696		F = CTFReplicationInfo(GameReplicationInfo).FlagList[aBot.PlayerReplicationInfo.Team].HomeBase;
00697	
00698		if ( (T.Region.Zone == F.Region.Zone)
00699			&& (T.Instigator.PlayerReplicationInfo.Team != aBot.PlayerReplicationInfo.Team)
00700			&& !T.Disrupted()
00701			&& (VSize(T.Location - F.Location) < 1000) )
00702		{
00703			if ( (VSize(aBot.Location - T.Location) < 850)
00704					&& aBot.LineOfSightTo(T) )
00705			{
00706				aBot.AmbushSpot = None;
00707				aBot.ShootTarget(T);
00708				return true;
00709			}
00710			else
00711			{
00712				aBot.MoveTarget = aBot.FindPathToward(T);
00713				if ( aBot.MoveTarget != None )
00714				{
00715					if ( VSize(aBot.Location - aBot.MoveTarget.Location) < 1.5 * aBot.CollisionRadius )
00716					{
00717						aBot.CampTime = 3.0;
00718						aBot.GotoState('Roaming', 'Camp');
00719					}
00720					aBot.AmbushSpot = None;
00721					return true;
00722				}
00723			}
00724		}
00725		return false;
00726	}
00727	
00728	defaultproperties
00729	{
00730	     CaptureSound(0)=Sound'Botpack.CTF.CaptureSound2'
00731	     CaptureSound(1)=Sound'Botpack.CTF.CaptureSound3'
00732	     CaptureSound(2)=Sound'Botpack.CTF.CaptureSound2'
00733	     CaptureSound(3)=Sound'Botpack.CTF.CaptureSound3'
00734	     ReturnSound=Sound'Botpack.CTF.ReturnSound'
00735	     bSpawnInTeamArea=True
00736	     bScoreTeamKills=False
00737	     MaxAllowedTeams=2
00738	     GoalTeamScore=3.000000
00739	     CurrentOrders(0)=Freelance
00740	     CurrentOrders(1)=Freelance
00741	     CurrentOrders(2)=Freelance
00742	     CurrentOrders(3)=Freelance
00743	     bUseTranslocator=True
00744	     bRatedTranslocator=True
00745	     StartUpMessage=""
00746	     gamegoal="captures wins the match!"
00747	     MaxCommanders=0
00748	     LadderTypeIndex=2
00749	     bCoopWeaponMode=True
00750	     ScoreBoardType=Class'Botpack.UnrealCTFScoreboard'
00751	     HUDType=Class'Botpack.ChallengeCTFHUD'
00752	     MapListType=Class'Botpack.CTFMapList'
00753	     MapPrefix="CTF"
00754	     BeaconName="CTF"
00755	     GameName="Capture the Flag"
00756	     GameReplicationInfoClass=Class'Botpack.CTFReplicationInfo'
00757	}

End Source Code