Botpack
Class LastManStanding

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

class LastManStanding
extends Botpack.DeathMatchPlus

//============================================================================= // LastManStanding. //=============================================================================
Variables
 string AltStartupMessage
 int Lives
 PlayerPawn LocalPlayer
 TotalKills, NumGhosts
 bool bHighDetailGhosts


Function Summary
 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;
*/
 void CheckEndGame()
 float GameThreatAdd(Bot aBot, Pawn Other)
 bool IsRelevant(Actor Other)
 void Killed(Pawn killer, Pawn Other, name damageType)
 void Logout(Pawn Exiting)
 void ModifyBehaviour(Bot NewBot)
 bool NeedPlayers()
 bool OneOnOne()
 bool PickupQuery(Pawn Other, Inventory item)
 bool RestartPlayer(Pawn aPlayer)
 void ScoreKill(Pawn Killer, Pawn Other)
 void Timer()



Source Code


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	}

End Source Code