Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.
 
 
 
 
 
 

194 lines
5.4 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
// tf_bot_engineer_build_sentrygun.cpp
// Engineer building his Sentry gun
// Michael Booth, May 2010
#include "cbase.h"
#include "nav_mesh.h"
#include "tf_player.h"
#include "tf_obj.h"
#include "tf_obj_sentrygun.h"
#include "tf_obj_dispenser.h"
#include "tf_gamerules.h"
#include "tf_weapon_builder.h"
#include "bot/tf_bot.h"
#include "bot/behavior/engineer/tf_bot_engineer_move_to_build.h"
#include "bot/behavior/engineer/tf_bot_engineer_build_sentrygun.h"
#include "bot/behavior/tf_bot_get_ammo.h"
#include "bot/map_entities/tf_bot_hint_sentrygun.h"
extern ConVar tf_bot_path_lookahead_range;
//---------------------------------------------------------------------------------------------
CTFBotEngineerBuildSentryGun::CTFBotEngineerBuildSentryGun( void )
{
m_sentryBuildHint = NULL;
}
//---------------------------------------------------------------------------------------------
CTFBotEngineerBuildSentryGun::CTFBotEngineerBuildSentryGun( CTFBotHintSentrygun *sentryBuildHint )
{
m_sentryBuildHint = sentryBuildHint;
}
//---------------------------------------------------------------------------------------------
ActionResult< CTFBot > CTFBotEngineerBuildSentryGun::OnStart( CTFBot *me, Action< CTFBot > *priorAction )
{
m_sentryTriesLeft = 5;
m_giveUpTimer.Invalidate();
m_searchTimer.Invalidate();
m_wanderWay = 1;
m_needToAimSentry = true;
m_sentryBuildLocation = ( m_sentryBuildHint == NULL ) ? me->GetAbsOrigin() : m_sentryBuildHint->GetAbsOrigin();
return Continue();
}
//---------------------------------------------------------------------------------------------
ActionResult< CTFBot > CTFBotEngineerBuildSentryGun::Update( CTFBot *me, float interval )
{
if ( me->GetTimeSinceLastInjury() < 1.0f )
{
return Done( "Ouch! I'm under attack" );
}
CObjectSentrygun *mySentry = (CObjectSentrygun *)me->GetObjectOfType( OBJ_SENTRYGUN );
if ( mySentry )
{
return Done( "Sentry built" );
}
// collect metal as we move to our build location
if ( me->CanBuild( OBJ_SENTRYGUN ) == CB_NEED_RESOURCES )
{
if ( m_getAmmoTimer.IsElapsed() && CTFBotGetAmmo::IsPossible( me ) )
{
// need more metal - get some
m_getAmmoTimer.Start( 1.0f );
return SuspendFor( new CTFBotGetAmmo, "Need more metal to build my Sentry" );
}
}
// various interruptions could mean we're away from our build location - move to it
if ( me->IsRangeGreaterThan( m_sentryBuildLocation, 25.0f ) )
{
if ( m_repathTimer.IsElapsed() )
{
m_repathTimer.Start( RandomFloat( 1.0f, 2.0f ) );
CTFBotPathCost cost( me, FASTEST_ROUTE );
m_path.Compute( me, m_sentryBuildLocation, cost );
}
m_path.Update( me );
if ( !m_path.IsValid() )
{
return Done( "Path failed" );
}
return Continue();
}
// we are at our build location
if ( m_sentryTriesLeft <= 0 )
{
// couldn't build here
return Done( "Couldn't find a place to build" );
}
// attempt to build a Sentry here
if ( m_sentryBuildHint != NULL )
{
// directly create a sentry gun at the precise position and orientation desired
CObjectSentrygun *mySentry = (CObjectSentrygun *)CreateEntityByName( "obj_sentrygun" );
if ( mySentry )
{
m_sentryBuildHint->IncrementUseCount();
mySentry->SetAbsOrigin( m_sentryBuildHint->GetAbsOrigin() );
mySentry->SetAbsAngles( QAngle( 0, m_sentryBuildHint->GetAbsAngles().y, 0 ) );
mySentry->Spawn();
mySentry->StartPlacement( me );
mySentry->StartBuilding( me );
}
}
else
{
// no precise build location - go through the normal build process
CTFWeaponBuilder *builder = dynamic_cast< CTFWeaponBuilder * >( me->GetActiveTFWeapon() );
if ( !builder || builder->GetType() != OBJ_SENTRYGUN || builder->m_hObjectBeingBuilt == NULL )
{
// at home position, build a sentry (switch to the sentry builder "gun")
me->StartBuildingObjectOfType( OBJ_SENTRYGUN );
return Continue();
}
// orient sentry towards where enemies enter this region
if ( m_needToAimSentry )
{
CTFNavArea *myArea = (CTFNavArea *)me->GetLastKnownArea();
if ( myArea )
{
CUtlVector< CTFNavArea * > invasionVector;
myArea->GetEnemyInvasionAreaVector( me->GetTeamNumber() );
if ( invasionVector.Count() > 0 )
{
// orient sentry towards where enemies enter this region
int which = RandomInt( 0, invasionVector.Count()-1 );
me->GetBodyInterface()->AimHeadTowards( invasionVector[ which ]->GetCenter(), IBody::CRITICAL, 1.0f, NULL, "Sentry build orientation" );
m_needToAimSentry = false;
}
}
}
if ( me->GetBodyInterface()->IsHeadSteady() )
{
if ( builder->IsValidPlacement() )
{
// build the sentry
me->PressFireButton();
}
else
{
// move around a bit to find valid spot
if ( m_searchTimer.IsElapsed() )
{
m_wanderWay = RandomInt( 0, 3 );
m_needToAimSentry = true;
m_searchTimer.Start( RandomFloat( 0.1f, 0.25f ) );
--m_sentryTriesLeft;
}
switch( m_wanderWay )
{
case 0: me->PressForwardButton(); break;
case 1: me->PressBackwardButton(); break;
case 2: me->PressRightButton(); break;
case 3: me->PressLeftButton(); break;
}
}
}
}
return Continue();
}
//---------------------------------------------------------------------------------------------
ActionResult< CTFBot > CTFBotEngineerBuildSentryGun::OnResume( CTFBot *me, Action< CTFBot > *interruptingAction )
{
m_path.Invalidate();
m_repathTimer.Invalidate();
return Continue();
}