You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
6.3 KiB
235 lines
6.3 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#include "cbase.h" |
|
#include "serverbenchmark_tf.h" |
|
#include "tf_shareddefs.h" |
|
#include "tf_bot_temp.h" |
|
#include "entity_tfstart.h" |
|
#include "tf_player.h" |
|
|
|
|
|
static ConVar sv_benchmark_freeroam( "sv_benchmark_freeroam", "0", 0, "Allow the local player to move freely in the benchmark. Only used for debugging. Don't use for real benchmarks because it will make the timing inconsistent." ); |
|
|
|
|
|
class CTFServerBenchmark : public CServerBenchmarkHook |
|
{ |
|
public: |
|
virtual void StartBenchmark() |
|
{ |
|
ConVarRef cvBotFlipout( "bot_flipout" ); |
|
cvBotFlipout.SetValue( 3 ); |
|
|
|
extern ConVar bot_forceattack_down; |
|
bot_forceattack_down.SetValue( true ); |
|
|
|
extern ConVar mp_teams_unbalance_limit; |
|
mp_teams_unbalance_limit.SetValue( (int)0 ); |
|
|
|
m_nBotsCreated = 0; |
|
m_bSetupLocalPlayer = false; |
|
} |
|
|
|
virtual void GetPhysicsModelNames( CUtlVector<char*> &modelNames ) |
|
{ |
|
modelNames.AddToTail( "models/props_farm/wooden_barrel.mdl" ); |
|
modelNames.AddToTail( "models/props_gameplay/orange_cone001.mdl" ); |
|
} |
|
|
|
virtual CBaseEntity* GetBlueSpawnPoint( bool bBest ) |
|
{ |
|
CUtlVector<CTFTeamSpawn*> spawns; |
|
for ( int i=0; i<ITFTeamSpawnAutoList::AutoList().Count(); ++i ) |
|
{ |
|
CTFTeamSpawn *pTFSpawn = static_cast< CTFTeamSpawn* >( ITFTeamSpawnAutoList::AutoList()[i] ); |
|
if ( !pTFSpawn->IsDisabled() && pTFSpawn->GetTeamNumber() == TF_TEAM_BLUE ) |
|
spawns.AddToTail( pTFSpawn ); |
|
} |
|
|
|
// If we're not looking for the BEST one, return a random one. |
|
if ( !bBest ) |
|
{ |
|
if ( spawns.Count() == 0 ) |
|
return NULL; |
|
|
|
return spawns[ g_pServerBenchmark->RandomInt( 0, spawns.Count()-1 ) ]; |
|
} |
|
|
|
float flBestSpawn = 0; |
|
CTFTeamSpawn *pBestSpawn = NULL; |
|
for ( int i=0; i < spawns.Count(); i++ ) |
|
{ |
|
Vector vForward; |
|
AngleVectors( spawns[i]->GetLocalAngles(), &vForward ); |
|
|
|
float flCurSpawn = 0; |
|
for ( int j=0; j < spawns.Count(); j++ ) |
|
{ |
|
if ( j == i ) |
|
continue; |
|
|
|
Vector vTo = spawns[j]->GetAbsOrigin() - spawns[i]->GetAbsOrigin(); |
|
VectorNormalize( vTo ); |
|
|
|
flCurSpawn += vForward.Dot( vTo ); |
|
} |
|
|
|
if ( flCurSpawn > flBestSpawn ) |
|
{ |
|
flBestSpawn = flCurSpawn; |
|
pBestSpawn = spawns[i]; |
|
} |
|
} |
|
|
|
return pBestSpawn; |
|
} |
|
|
|
virtual void UpdateBenchmark() |
|
{ |
|
if ( m_nBotsCreated == 0 ) |
|
{ |
|
return; |
|
} |
|
|
|
RandomSeed( 0 ); |
|
|
|
// Put the player at a blue spawn point. |
|
if ( !engine->IsDedicatedServer() ) |
|
{ |
|
CTFPlayer *pLocalPlayer = dynamic_cast< CTFPlayer* >( UTIL_GetListenServerHost() ); |
|
if ( pLocalPlayer ) |
|
{ |
|
if ( !m_bSetupLocalPlayer ) |
|
{ |
|
m_bSetupLocalPlayer = true; |
|
|
|
pLocalPlayer->ChangeTeam( TEAM_SPECTATOR ); |
|
pLocalPlayer->SetDesiredPlayerClassIndex( TF_CLASS_SNIPER ); |
|
pLocalPlayer->ForceRespawn(); |
|
|
|
// Now pick whatever blue spawn point has the most other spawn points in front of it. |
|
CBaseEntity *pBestSpawn = GetBlueSpawnPoint( true ); |
|
if ( !pBestSpawn ) |
|
Error( "Can't find spawn position for local player." ); |
|
|
|
m_vLocalPlayerOrigin = pBestSpawn->GetLocalOrigin() + Vector(0,0,80); |
|
m_vLocalPlayerEyeAngles = pBestSpawn->GetLocalAngles(); |
|
} |
|
|
|
((CBasePlayer*)pLocalPlayer)->SetObserverMode( OBS_MODE_ROAMING ); |
|
|
|
// Lock the player in place for a little bit, then let them go free when we have some bots. |
|
if ( !sv_benchmark_freeroam.GetBool() || m_nBotsCreated < 2 ) |
|
{ |
|
pLocalPlayer->Teleport( &m_vLocalPlayerOrigin, &m_vLocalPlayerEyeAngles, NULL ); |
|
pLocalPlayer->SetObserverTarget( NULL ); |
|
|
|
if ( !sv_benchmark_freeroam.GetBool() ) |
|
pLocalPlayer->AddFlag( FL_FROZEN ); |
|
} |
|
} |
|
} |
|
|
|
RespawnDeadPlayers(); |
|
MoveRedPlayersToBlueArea(); |
|
AddSentries(); |
|
} |
|
|
|
void RespawnDeadPlayers() |
|
{ |
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); |
|
if ( pPlayer && pPlayer->IsDead() && !g_pServerBenchmark->IsLocalBenchmarkPlayer( pPlayer ) ) |
|
{ |
|
pPlayer->ForceRespawn(); |
|
} |
|
} |
|
} |
|
|
|
void AddSentries() |
|
{ |
|
const char *pSentryClassName = "obj_sentrygun"; |
|
|
|
for ( int iTeamIteration=0; iTeamIteration < 2; iTeamIteration++ ) |
|
{ |
|
int iTeam = (iTeamIteration == 0) ? TF_TEAM_BLUE : TF_TEAM_RED; |
|
|
|
// Get the current # of sentries. |
|
int nSentries = 0; |
|
CBaseEntity *pSpot = gEntList.FindEntityByClassname( NULL, pSentryClassName ); |
|
while( pSpot ) |
|
{ |
|
if ( pSpot->GetTeamNumber() == iTeam ) |
|
++nSentries; |
|
|
|
pSpot = gEntList.FindEntityByClassname( pSpot, pSentryClassName ); |
|
} |
|
|
|
// Make new ones if necessary. |
|
if ( nSentries < 2 ) |
|
{ |
|
// Find an engineer.. |
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CTFPlayer *pPlayer = dynamic_cast< CTFPlayer* >( UTIL_PlayerByIndex( i ) ); |
|
if ( pPlayer && pPlayer->GetTeamNumber() == iTeam && pPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_ENGINEER ) |
|
{ |
|
pPlayer->StartBuildingObjectOfType( OBJ_SENTRYGUN ); |
|
if ( pPlayer->GetActiveWeapon() ) |
|
pPlayer->GetActiveWeapon()->PrimaryAttack(); |
|
|
|
break; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void MoveRedPlayersToBlueArea() |
|
{ |
|
for ( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); |
|
if ( pPlayer && pPlayer->GetTeamNumber() == TF_TEAM_RED ) |
|
{ |
|
// If too far from the spawns, then teleport into the blue area. |
|
CBaseEntity *pSpawn = GetBlueSpawnPoint( false ); |
|
if ( pPlayer->GetAbsOrigin().DistTo( pSpawn->GetAbsOrigin() ) > 2000 ) |
|
{ |
|
pPlayer->Teleport( &pSpawn->GetAbsOrigin(), NULL, NULL ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
virtual CBasePlayer* CreateBot() |
|
{ |
|
int iTeam = (g_pServerBenchmark->RandomInt( 0, 1 ) == 1) ? TF_TEAM_BLUE : TF_TEAM_RED; |
|
if ( m_nBotsCreated == 0 ) |
|
iTeam = TF_TEAM_BLUE; |
|
|
|
int iClass = g_pServerBenchmark->RandomInt( TF_FIRST_NORMAL_CLASS, ( TF_LAST_NORMAL_CLASS - 1 ) ); //( TF_LAST_NORMAL_CLASS - 1 ) to exclude the new civilian class |
|
if ( m_nBotsCreated < 4 ) |
|
iClass = TF_CLASS_ENGINEER; // Make engineers first so they'll build sentries. |
|
|
|
CBasePlayer *pPlayer = BotPutInServer( false, false, iTeam, iClass, NULL ); |
|
if ( !pPlayer ) |
|
Error( "Server benchmark: Can't create bot." ); |
|
|
|
++m_nBotsCreated; |
|
return pPlayer; |
|
} |
|
|
|
private: |
|
int m_nBotsCreated; |
|
bool m_bSetupLocalPlayer; |
|
|
|
Vector m_vLocalPlayerOrigin; |
|
QAngle m_vLocalPlayerEyeAngles; |
|
}; |
|
|
|
static CTFServerBenchmark g_TFServerBenchmark;
|
|
|