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.
 
 
 
 
 
 

144 lines
3.9 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
// tf_bot_retreat.cpp
// Retreat towards our spawn to find another patient
// Michael Booth, May 2009
#include "cbase.h"
#include "tf_player.h"
#include "tf_gamerules.h"
#include "tf_weapon_medigun.h"
#include "bot/tf_bot.h"
#include "bot/behavior/medic/tf_bot_medic_retreat.h"
#include "nav_mesh.h"
extern ConVar tf_bot_path_lookahead_range;
extern ConVar tf_bot_medic_follow_range;
extern ConVar tf_bot_force_class;
//---------------------------------------------------------------------------------------------
ActionResult< CTFBot > CTFBotMedicRetreat::OnStart( CTFBot *me, Action< CTFBot > *priorAction )
{
CTFNavArea *homeArea = me->GetSpawnArea();
if ( homeArea == NULL )
{
return Done( "No home area!" );
}
m_path.SetMinLookAheadDistance( tf_bot_path_lookahead_range.GetFloat() );
CTFBotPathCost cost( me, FASTEST_ROUTE );
m_path.Compute( me, homeArea->GetCenter(), cost );
return Continue();
}
//---------------------------------------------------------------------------------------------
class CUsefulHealTargetFilter : public INextBotEntityFilter
{
public:
CUsefulHealTargetFilter( int team )
{
m_team = team;
}
virtual bool IsAllowed( CBaseEntity *entity ) const
{
if ( entity && entity->IsPlayer() && entity->GetTeamNumber() == m_team )
{
return !ToTFPlayer( entity )->IsPlayerClass( TF_CLASS_MEDIC ) && !ToTFPlayer( entity )->IsPlayerClass( TF_CLASS_SNIPER );
}
return false;
}
int m_team;
};
//---------------------------------------------------------------------------------------------
ActionResult< CTFBot > CTFBotMedicRetreat::Update( CTFBot *me, float interval )
{
// equip the syringegun and defend ourselves!
CTFWeaponBase *myWeapon = me->m_Shared.GetActiveTFWeapon();
if ( myWeapon )
{
if ( myWeapon->GetWeaponID() != TF_WEAPON_SYRINGEGUN_MEDIC )
{
CBaseCombatWeapon *syringeGun = me->Weapon_GetSlot( TF_WPN_TYPE_PRIMARY );
if ( syringeGun )
{
me->Weapon_Switch( syringeGun );
}
}
}
m_path.Update( me );
// look around to try to spot a friend to heal
if ( m_lookAroundTimer.IsElapsed() )
{
m_lookAroundTimer.Start( RandomFloat( 0.33f, 1.0f ) );
QAngle angle;
angle.x = 0.0f;
angle.y = RandomFloat( -180.0f, 180.0f );
angle.z = 0.0f;
Vector forward;
AngleVectors( angle, &forward );
me->GetBodyInterface()->AimHeadTowards( me->EyePosition() + forward, IBody::IMPORTANT, 0.1f, NULL, "Looking for someone to heal" );
}
// if we see a friend, heal them
CUsefulHealTargetFilter filter( me->GetTeamNumber() );
const CKnownEntity *known = me->GetVisionInterface()->GetClosestKnown( filter );
if ( known )
{
return Done( "I know of a teammate" );
}
return Continue();
}
//---------------------------------------------------------------------------------------------
ActionResult< CTFBot > CTFBotMedicRetreat::OnResume( CTFBot *me, Action< CTFBot > *interruptingAction )
{
CTFBotPathCost cost( me, FASTEST_ROUTE );
m_path.Compute( me, me->GetSpawnArea()->GetCenter(), cost );
return Continue();
}
//---------------------------------------------------------------------------------------------
EventDesiredResult< CTFBot > CTFBotMedicRetreat::OnStuck( CTFBot *me )
{
CTFBotPathCost cost( me, FASTEST_ROUTE );
m_path.Compute( me, me->GetSpawnArea()->GetCenter(), cost );
return TryContinue();
}
//---------------------------------------------------------------------------------------------
EventDesiredResult< CTFBot > CTFBotMedicRetreat::OnMoveToFailure( CTFBot *me, const Path *path, MoveToFailureType reason )
{
CTFBotPathCost cost( me, FASTEST_ROUTE );
m_path.Compute( me, me->GetSpawnArea()->GetCenter(), cost );
return TryContinue();
}
//---------------------------------------------------------------------------------------------
QueryResultType CTFBotMedicRetreat::ShouldAttack( const INextBot *me, const CKnownEntity *them ) const
{
// defend ourselves!
return ANSWER_YES;
}