Core.Object | +--Engine.Actor | +--Engine.Info | +--Engine.GameInfo | +--Botpack.TournamentGameInfo | +--Botpack.DeathMatchPlus | +--Botpack.TeamGamePlus | +--Botpack.Domination
ControlPoint
ControlPoints[16]
int
DomScoreEvent
bool
bDumbDown
bNeutralPoints
void
CalcEndStats()
CanTranslocate(Bot aBot)
ClearControl(Pawn Other)
EndGame(string Reason)
FindSpecialAttractionFor(Bot aBot)
InitRatedGame(LadderInventory LadderObj, PlayerPawn LadderPlayer)
Logout(Pawn Exiting)
PostBeginPlay()
RestartPlayer(Pawn aPlayer)
ScoreKill(Pawn Killer, Pawn Other)
SetBotOrders(Bot NewBot)
Actor
SetDefenseFor(Bot aBot)
SetEndCams(string Reason)
Timer()
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 }