Core.Object | +--Engine.Actor | +--Engine.Info | +--Engine.GameInfo | +--Botpack.TournamentGameInfo | +--Botpack.DeathMatchPlus | +--Botpack.LastManStanding
string
AltStartupMessage
int
Lives
PlayerPawn
LocalPlayer
TotalKills,
NumGhosts
bool
bHighDetailGhosts
void
AddDefaultInventory(Pawn PlayerPawn)
byte
AssessBotAttitude(Bot aBot, Pawn Other)
/* AssessBotAttitude returns a value that translates to an attitude 0 = ATTITUDE_Fear; 1 = return ATTITUDE_Hate; 2 = return ATTITUDE_Ignore; 3 = return ATTITUDE_Friendly; */
CheckEndGame()
float
GameThreatAdd(Bot aBot, Pawn Other)
IsRelevant(Actor Other)
Killed(Pawn killer, Pawn Other, name damageType)
Logout(Pawn Exiting)
ModifyBehaviour(Bot NewBot)
NeedPlayers()
OneOnOne()
PickupQuery(Pawn Other, Inventory item)
RestartPlayer(Pawn aPlayer)
ScoreKill(Pawn Killer, Pawn Other)
Timer()
00001 //============================================================================= 00002 // LastManStanding. 00003 //============================================================================= 00004 class LastManStanding extends DeathMatchPlus; 00005 00006 var config bool bHighDetailGhosts; 00007 var() int Lives; 00008 var int TotalKills, NumGhosts; 00009 var localized string AltStartupMessage; 00010 var PlayerPawn LocalPlayer; 00011 00012 event InitGame( string Options, out string Error ) 00013 { 00014 local string InOpt; 00015 00016 Super.InitGame(Options, Error); 00017 if ( FragLimit == 0 ) 00018 Lives = 10; 00019 else 00020 Lives = Fraglimit; 00021 } 00022 00023 function float GameThreatAdd(Bot aBot, Pawn Other) 00024 { 00025 if ( !Other.bIsPlayer ) 00026 return 0; 00027 else 00028 return 0.1 * Other.PlayerReplicationInfo.Score; 00029 } 00030 00031 event playerpawn Login 00032 ( 00033 string Portal, 00034 string Options, 00035 out string Error, 00036 class<playerpawn> SpawnClass 00037 ) 00038 { 00039 local playerpawn NewPlayer; 00040 local Pawn P; 00041 00042 // if more than 15% of the game is over, must join as spectator 00043 if ( TotalKills > 0.15 * (NumPlayers + NumBots) * Lives ) 00044 { 00045 bDisallowOverride = true; 00046 SpawnClass = class'CHSpectator'; 00047 if ( (NumSpectators >= MaxSpectators) 00048 && ((Level.NetMode != NM_ListenServer) || (NumPlayers > 0)) ) 00049 { 00050 MaxSpectators++; 00051 } 00052 } 00053 NewPlayer = Super.Login(Portal, Options, Error, SpawnClass); 00054 00055 if ( (NewPlayer != None) && !NewPlayer.IsA('Spectator') && !NewPlayer.IsA('Commander') ) 00056 NewPlayer.PlayerReplicationInfo.Score = Lives; 00057 00058 return NewPlayer; 00059 } 00060 00061 event PostLogin( playerpawn NewPlayer ) 00062 { 00063 if( NewPlayer.Player != None && Viewport(NewPlayer.Player) != None) 00064 LocalPlayer = NewPlayer; 00065 00066 if ( (TotalKills > 0.15 * (NumPlayers + NumBots) * Lives) && NewPlayer.IsA('CHSpectator') ) 00067 GameName = AltStartupMessage; 00068 Super.PostLogin(NewPlayer); 00069 GameName = Default.GameName; 00070 } 00071 00072 function Timer() 00073 { 00074 local Pawn P; 00075 00076 Super.Timer(); 00077 For ( P=Level.PawnList; P!=None; P=P.NextPawn ) 00078 if ( P.IsInState('FeigningDeath') ) 00079 P.GibbedBy(P); 00080 } 00081 00082 function bool NeedPlayers() 00083 { 00084 if ( bGameEnded || (TotalKills > 0.15 * (NumPlayers + NumBots) * Lives) ) 00085 return false; 00086 return (NumPlayers + NumBots < MinPlayers); 00087 } 00088 00089 function bool IsRelevant(actor Other) 00090 { 00091 local Mutator M; 00092 local bool bArenaMutator; 00093 00094 for (M = BaseMutator; M != None; M = M.NextMutator) 00095 { 00096 if (M.IsA('Arena')) 00097 bArenaMutator = True; 00098 } 00099 00100 if ( bArenaMutator ) 00101 { 00102 if ( Other.IsA('Inventory') && (Inventory(Other).MyMarker != None) && !Other.IsA('UT_Jumpboots') && !Other.IsA('Ammo')) 00103 { 00104 Inventory(Other).MyMarker.markedItem = None; 00105 return false; 00106 } 00107 } else { 00108 if ( Other.IsA('Inventory') && (Inventory(Other).MyMarker != None) && !Other.IsA('UT_Jumpboots')) 00109 { 00110 Inventory(Other).MyMarker.markedItem = None; 00111 return false; 00112 } 00113 } 00114 00115 return Super.IsRelevant(Other); 00116 } 00117 00118 function bool RestartPlayer( pawn aPlayer ) 00119 { 00120 local NavigationPoint startSpot; 00121 local bool foundStart; 00122 local Pawn P; 00123 00124 if( bRestartLevel && Level.NetMode!=NM_DedicatedServer && Level.NetMode!=NM_ListenServer ) 00125 return true; 00126 00127 if ( aPlayer.PlayerReplicationInfo.Score < 1 ) 00128 { 00129 BroadcastLocalizedMessage(class'LMSOutMessage', 0, aPlayer.PlayerReplicationInfo); 00130 For ( P=Level.PawnList; P!=None; P=P.NextPawn ) 00131 if ( P.bIsPlayer && (P.PlayerReplicationInfo.Score >= 1) ) 00132 P.PlayerReplicationInfo.Score += 0.00001; 00133 if ( aPlayer.IsA('Bot') ) 00134 { 00135 aPlayer.PlayerReplicationInfo.bIsSpectator = true; 00136 aPlayer.PlayerReplicationInfo.bWaitingPlayer = true; 00137 aPlayer.GotoState('GameEnded'); 00138 return false; // bots don't respawn when ghosts 00139 } 00140 } 00141 00142 startSpot = FindPlayerStart(None, 255); 00143 if( startSpot == None ) 00144 return false; 00145 00146 foundStart = aPlayer.SetLocation(startSpot.Location); 00147 if( foundStart ) 00148 { 00149 startSpot.PlayTeleportEffect(aPlayer, true); 00150 aPlayer.SetRotation(startSpot.Rotation); 00151 aPlayer.ViewRotation = aPlayer.Rotation; 00152 aPlayer.Acceleration = vect(0,0,0); 00153 aPlayer.Velocity = vect(0,0,0); 00154 aPlayer.Health = aPlayer.Default.Health; 00155 aPlayer.ClientSetRotation( startSpot.Rotation ); 00156 aPlayer.bHidden = false; 00157 aPlayer.SoundDampening = aPlayer.Default.SoundDampening; 00158 if ( aPlayer.PlayerReplicationInfo.Score < 1 ) 00159 { 00160 // This guy is a ghost. Add a visual effect. 00161 if ( bHighDetailGhosts ) 00162 { 00163 aPlayer.Style = STY_Translucent; 00164 aPlayer.ScaleGlow = 0.5; 00165 } 00166 else 00167 aPlayer.bHidden = true; 00168 aPlayer.PlayerRestartState = 'PlayerSpectating'; 00169 } 00170 else 00171 { 00172 aPlayer.SetCollision( true, true, true ); 00173 AddDefaultInventory(aPlayer); 00174 } 00175 } 00176 return foundStart; 00177 } 00178 00179 function Logout( pawn Exiting ) 00180 { 00181 Super.Logout(Exiting); 00182 00183 // Don't run endgame if it's the local player leaving 00184 // - stats saveconfig messes up saved defaults 00185 if( LocalPlayer == None || Exiting != LocalPlayer ) 00186 CheckEndGame(); 00187 } 00188 00189 function Killed( pawn killer, pawn Other, name damageType ) 00190 { 00191 local int OldFragLimit; 00192 00193 OldFragLimit = FragLimit; 00194 FragLimit = 0; 00195 00196 if ( Other.bIsPlayer ) 00197 TotalKills++; 00198 00199 Super.Killed(Killer, Other, damageType); 00200 00201 FragLimit = OldFragLimit; 00202 00203 CheckEndGame(); 00204 } 00205 00206 function CheckEndGame() 00207 { 00208 local Pawn PawnLink; 00209 local int StillPlaying; 00210 local bool bStillHuman; 00211 local bot B, D; 00212 00213 if ( bGameEnded ) 00214 return; 00215 00216 // Check to see if everyone is a ghost. 00217 NumGhosts = 0; 00218 for ( PawnLink=Level.PawnList; PawnLink!=None; PawnLink=PawnLink.nextPawn ) 00219 if ( PawnLink.bIsPlayer ) 00220 { 00221 if ( PawnLink.PlayerReplicationInfo.Score < 1 ) 00222 NumGhosts++; 00223 else 00224 { 00225 if ( PawnLink.IsA('PlayerPawn') ) 00226 bStillHuman = true; 00227 StillPlaying++; 00228 } 00229 } 00230 00231 // End the game if there is only one man standing. 00232 if ( StillPlaying < 2 ) 00233 EndGame("lastmanstanding"); 00234 else if ( !bStillHuman ) 00235 { 00236 // no humans left - get bots to be more aggressive and finish up 00237 for ( PawnLink=Level.PawnList; PawnLink!=None; PawnLink=PawnLink.NextPawn ) 00238 { 00239 B = Bot(PawnLink); 00240 if ( B != None ) 00241 { 00242 B.CampingRate = 0; 00243 B.Aggressiveness += 5.0; 00244 if ( D == None ) 00245 D = B; 00246 else if ( B.Enemy == None ) 00247 B.SetEnemy(D); 00248 } 00249 } 00250 } 00251 } 00252 00253 function ScoreKill(pawn Killer, pawn Other) 00254 { 00255 Other.DieCount++; 00256 if (Other.PlayerReplicationInfo.Score > 0) 00257 Other.PlayerReplicationInfo.Score -= 1; 00258 if( (killer != Other) && (killer != None) ) 00259 killer.killCount++; 00260 BaseMutator.ScoreKill(Killer, Other); 00261 } 00262 00263 function bool PickupQuery( Pawn Other, Inventory item ) 00264 { 00265 if ( Other.PlayerReplicationInfo.Score < 1 ) 00266 return false; 00267 00268 return Super.PickupQuery( Other, item ); 00269 } 00270 00271 /* 00272 AssessBotAttitude returns a value that translates to an attitude 00273 0 = ATTITUDE_Fear; 00274 1 = return ATTITUDE_Hate; 00275 2 = return ATTITUDE_Ignore; 00276 3 = return ATTITUDE_Friendly; 00277 */ 00278 function byte AssessBotAttitude(Bot aBot, Pawn Other) 00279 { 00280 local float Adjust; 00281 00282 if ( aBot.bNovice ) 00283 Adjust = -0.2; 00284 else 00285 Adjust = -0.2 - 0.1 * aBot.Skill; 00286 if ( Other.bIsPlayer && (Other.PlayerReplicationInfo.Score < 1) ) 00287 return 2; //bots ignore ghosts 00288 else if ( aBot.bKamikaze ) 00289 return 1; 00290 else if ( Other.IsA('TeamCannon') 00291 || (aBot.RelativeStrength(Other) > aBot.Aggressiveness - Adjust) ) 00292 return 0; 00293 else 00294 return 1; 00295 } 00296 00297 function AddDefaultInventory( pawn PlayerPawn ) 00298 { 00299 local Weapon weap; 00300 local int i; 00301 local inventory Inv; 00302 local float F; 00303 00304 if ( PlayerPawn.IsA('Spectator') || (bRequireReady && (CountDown > 0)) ) 00305 return; 00306 Super.AddDefaultInventory(PlayerPawn); 00307 00308 GiveWeapon(PlayerPawn, "Botpack.ShockRifle"); 00309 GiveWeapon(PlayerPawn, "Botpack.UT_BioRifle"); 00310 GiveWeapon(PlayerPawn, "Botpack.Ripper"); 00311 GiveWeapon(PlayerPawn, "Botpack.UT_FlakCannon"); 00312 00313 if ( PlayerPawn.IsA('PlayerPawn') ) 00314 { 00315 GiveWeapon(PlayerPawn, "Botpack.SniperRifle"); 00316 GiveWeapon(PlayerPawn, "Botpack.PulseGun"); 00317 GiveWeapon(PlayerPawn, "Botpack.Minigun2"); 00318 GiveWeapon(PlayerPawn, "Botpack.UT_Eightball"); 00319 PlayerPawn.SwitchToBestWeapon(); 00320 } 00321 else 00322 { 00323 // randomize order for bots so they don't always use the same weapon 00324 F = FRand(); 00325 if ( F < 0.7 ) 00326 { 00327 GiveWeapon(PlayerPawn, "Botpack.SniperRifle"); 00328 GiveWeapon(PlayerPawn, "Botpack.PulseGun"); 00329 if ( F < 0.4 ) 00330 { 00331 GiveWeapon(PlayerPawn, "Botpack.Minigun2"); 00332 GiveWeapon(PlayerPawn, "Botpack.UT_Eightball"); 00333 } 00334 else 00335 { 00336 GiveWeapon(PlayerPawn, "Botpack.UT_Eightball"); 00337 GiveWeapon(PlayerPawn, "Botpack.Minigun2"); 00338 } 00339 } 00340 else 00341 { 00342 GiveWeapon(PlayerPawn, "Botpack.Minigun2"); 00343 GiveWeapon(PlayerPawn, "Botpack.UT_Eightball"); 00344 if ( F < 0.88 ) 00345 { 00346 GiveWeapon(PlayerPawn, "Botpack.SniperRifle"); 00347 GiveWeapon(PlayerPawn, "Botpack.PulseGun"); 00348 } 00349 else 00350 { 00351 GiveWeapon(PlayerPawn, "Botpack.PulseGun"); 00352 GiveWeapon(PlayerPawn, "Botpack.SniperRifle"); 00353 } 00354 } 00355 } 00356 00357 for ( inv=PlayerPawn.inventory; inv!=None; inv=inv.inventory ) 00358 { 00359 weap = Weapon(inv); 00360 if ( (weap != None) && (weap.AmmoType != None) ) 00361 weap.AmmoType.AmmoAmount = weap.AmmoType.MaxAmmo; 00362 } 00363 00364 inv = Spawn(class'Armor2'); 00365 if( inv != None ) 00366 { 00367 inv.bHeldItem = true; 00368 inv.RespawnTime = 0.0; 00369 inv.GiveTo(PlayerPawn); 00370 } 00371 } 00372 00373 function ModifyBehaviour(Bot NewBot) 00374 { 00375 // Set the Bot's Lives 00376 NewBot.PlayerReplicationInfo.Score = Lives; 00377 00378 NewBot.CampingRate += FRand(); 00379 } 00380 00381 function bool OneOnOne() 00382 { 00383 return ( NumPlayers + NumBots - NumGhosts == 2 ); 00384 } 00385 00386 defaultproperties 00387 { 00388 bAlwaysForceRespawn=True 00389 StartUpMessage="Last Man Standing. How long can you live?" 00390 ScoreBoardType=Class'Botpack.LMSScoreboard' 00391 RulesMenuType="UTMenu.UTLMSRulesSC" 00392 BeaconName="LMS" 00393 GameName="Last Man Standing" 00394 }