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.
248 lines
7.1 KiB
248 lines
7.1 KiB
4 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
// tf_bot_defend_point_block_capture.h
|
||
|
// Move to and defend current point from capture
|
||
|
// Michael Booth, February 2009
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "nav_mesh/tf_nav_mesh.h"
|
||
|
#include "tf_player.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
#include "trigger_area_capture.h"
|
||
|
#include "bot/tf_bot.h"
|
||
|
#include "bot/behavior/scenario/capture_point/tf_bot_defend_point_block_capture.h"
|
||
|
#include "bot/behavior/medic/tf_bot_medic_heal.h"
|
||
|
#include "bot/behavior/tf_bot_attack.h"
|
||
|
#include "bot/behavior/demoman/tf_bot_prepare_stickybomb_trap.h"
|
||
|
|
||
|
|
||
|
extern ConVar tf_bot_path_lookahead_range;
|
||
|
|
||
|
ConVar tf_bot_defend_owned_point_percent( "tf_bot_defend_owned_point_percent", "0.5", FCVAR_CHEAT, "Stay on the contested point we own until enemy cap percent falls below this" );
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
ActionResult< CTFBot > CTFBotDefendPointBlockCapture::OnStart( CTFBot *me, Action< CTFBot > *priorAction )
|
||
|
{
|
||
|
m_path.SetMinLookAheadDistance( me->GetDesiredPathLookAheadRange() );
|
||
|
|
||
|
m_point = me->GetMyControlPoint();
|
||
|
if ( m_point == NULL )
|
||
|
{
|
||
|
return Done( "Point is NULL" );
|
||
|
}
|
||
|
|
||
|
m_defenseArea = static_cast< CTFNavArea * >( TheTFNavMesh()->GetNearestNavArea( m_point->GetAbsOrigin() ) );
|
||
|
if ( m_defenseArea == NULL )
|
||
|
{
|
||
|
return Done( "Can't find nav area on point" );
|
||
|
}
|
||
|
|
||
|
return Continue();
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
bool CTFBotDefendPointBlockCapture::IsPointSafe( CTFBot *me )
|
||
|
{
|
||
|
// if a point was just captured, defend this point for awhile
|
||
|
if ( me->WasPointJustLost() )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ( m_point == NULL )
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ( m_point->GetTeamCapPercentage( me->GetTeamNumber() ) < tf_bot_defend_owned_point_percent.GetFloat() )
|
||
|
{
|
||
|
// we're not in complete control of this point yet
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// is point is being contested, or was just being contested, its not safe
|
||
|
if ( m_point->HasBeenContested() && ( gpGlobals->curtime - m_point->LastContestedAt() ) < 5.0f )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// if we still see a near threat, stay put
|
||
|
const CKnownEntity *knownThreat = me->GetVisionInterface()->GetPrimaryKnownThreat();
|
||
|
if ( knownThreat )
|
||
|
{
|
||
|
const float dangerRange = 500.0f;
|
||
|
if ( ( knownThreat->GetLastKnownPosition() - m_point->GetAbsOrigin() ).IsLengthLessThan( dangerRange ) )
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
ActionResult< CTFBot > CTFBotDefendPointBlockCapture::Update( CTFBot *me, float interval )
|
||
|
{
|
||
|
// if point is safe, we can move back to our defense positions
|
||
|
if ( IsPointSafe( me ) )
|
||
|
{
|
||
|
return Done( "Point is safe again" );
|
||
|
}
|
||
|
|
||
|
if ( me->IsPlayerClass( TF_CLASS_MEDIC ) )
|
||
|
{
|
||
|
// medics look ridiculous rushing to the point - they need to heal
|
||
|
return SuspendFor( new CTFBotMedicHeal );
|
||
|
}
|
||
|
|
||
|
const CKnownEntity *threat = me->GetVisionInterface()->GetPrimaryKnownThreat();
|
||
|
me->EquipBestWeaponForThreat( threat );
|
||
|
|
||
|
Extent pointExtent;
|
||
|
pointExtent.Init( m_point );
|
||
|
|
||
|
bool isStandingOnThePoint = pointExtent.Contains( me->GetAbsOrigin() );
|
||
|
|
||
|
const CUtlVector< CTFNavArea * > *controlPointAreas = TheTFNavMesh()->GetControlPointAreas( m_point->GetPointIndex() );
|
||
|
if ( controlPointAreas )
|
||
|
{
|
||
|
for( int i=0; i<controlPointAreas->Count(); ++i )
|
||
|
{
|
||
|
if ( me->GetLastKnownArea() && me->GetLastKnownArea()->GetID() == controlPointAreas->Element(i)->GetID() )
|
||
|
{
|
||
|
isStandingOnThePoint = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( isStandingOnThePoint && CTFBotPrepareStickybombTrap::IsPossible( me ) )
|
||
|
{
|
||
|
return SuspendFor( new CTFBotPrepareStickybombTrap, "Placing stickies for defense" );
|
||
|
}
|
||
|
|
||
|
if ( controlPointAreas )
|
||
|
{
|
||
|
// move to a random spot on this control point
|
||
|
if ( m_repathTimer.IsElapsed() )
|
||
|
{
|
||
|
m_repathTimer.Start( RandomFloat( 0.5f, 1.0f ) );
|
||
|
|
||
|
float totalArea = 0.0f;
|
||
|
int i;
|
||
|
for( i=0; i<controlPointAreas->Count(); ++i )
|
||
|
{
|
||
|
CTFNavArea *area = controlPointAreas->Element(i);
|
||
|
totalArea += area->GetSizeX() * area->GetSizeY();
|
||
|
}
|
||
|
|
||
|
float which = RandomFloat( 0.0f, totalArea - 1.0f );
|
||
|
CTFNavArea *goalArea = NULL;
|
||
|
for( i=0; i<controlPointAreas->Count(); ++i )
|
||
|
{
|
||
|
CTFNavArea *area = controlPointAreas->Element(i);
|
||
|
which -= area->GetSizeX() * area->GetSizeY();
|
||
|
if ( which <= 0.0f )
|
||
|
{
|
||
|
goalArea = area;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( goalArea )
|
||
|
{
|
||
|
CTFBotPathCost cost( me, DEFAULT_ROUTE );
|
||
|
m_path.Compute( me, goalArea->GetRandomPoint(), cost );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_path.Update( me );
|
||
|
}
|
||
|
else if ( !isStandingOnThePoint )
|
||
|
{
|
||
|
// get on the point!
|
||
|
if ( m_repathTimer.IsElapsed() )
|
||
|
{
|
||
|
m_repathTimer.Start( RandomFloat( 0.5f, 1.0f ) );
|
||
|
|
||
|
CTFBotPathCost cost( me, DEFAULT_ROUTE );
|
||
|
m_path.Compute( me, ( pointExtent.lo + pointExtent.hi )/2.0f, cost );
|
||
|
}
|
||
|
|
||
|
m_path.Update( me );
|
||
|
}
|
||
|
|
||
|
return Continue();
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
ActionResult< CTFBot > CTFBotDefendPointBlockCapture::OnResume( CTFBot *me, Action< CTFBot > *interruptingAction )
|
||
|
{
|
||
|
m_path.Invalidate();
|
||
|
|
||
|
return Continue();
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
EventDesiredResult< CTFBot > CTFBotDefendPointBlockCapture::OnStuck( CTFBot *me )
|
||
|
{
|
||
|
m_path.Invalidate();
|
||
|
me->GetLocomotionInterface()->ClearStuckStatus();
|
||
|
|
||
|
return TryContinue();
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
EventDesiredResult< CTFBot > CTFBotDefendPointBlockCapture::OnMoveToSuccess( CTFBot *me, const Path *path )
|
||
|
{
|
||
|
return TryContinue();
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
EventDesiredResult< CTFBot > CTFBotDefendPointBlockCapture::OnMoveToFailure( CTFBot *me, const Path *path, MoveToFailureType reason )
|
||
|
{
|
||
|
m_path.Invalidate();
|
||
|
return TryContinue();
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
EventDesiredResult< CTFBot > CTFBotDefendPointBlockCapture::OnTerritoryContested( CTFBot *me, int territoryID )
|
||
|
{
|
||
|
return TryToSustain();
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
EventDesiredResult< CTFBot > CTFBotDefendPointBlockCapture::OnTerritoryCaptured( CTFBot *me, int territoryID )
|
||
|
{
|
||
|
return TryContinue();
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
EventDesiredResult< CTFBot > CTFBotDefendPointBlockCapture::OnTerritoryLost( CTFBot *me, int territoryID )
|
||
|
{
|
||
|
// we lost it, fall back
|
||
|
return TryDone( RESULT_CRITICAL, "Lost the point" );
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
QueryResultType CTFBotDefendPointBlockCapture::ShouldHurry( const INextBot *me ) const
|
||
|
{
|
||
|
// hurry up and get on the point!
|
||
|
return ANSWER_YES;
|
||
|
}
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------
|
||
|
QueryResultType CTFBotDefendPointBlockCapture::ShouldRetreat( const INextBot *me ) const
|
||
|
{
|
||
|
// get on the point!
|
||
|
return ANSWER_NO;
|
||
|
}
|