mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 06:36:54 +00:00
236 lines
6.3 KiB
C++
236 lines
6.3 KiB
C++
//========= 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;
|