Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 80 additions & 41 deletions src/game/server/neo/bot/behavior/neo_bot_ctg_carrier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include "bot/neo_bot_path_compute.h"
#include "nav_mesh.h"
#include "neo_gamerules.h"
#include "neo_ghost_cap_point.h"
#include "debugoverlay_shared.h"
#include "weapon_ghost.h"

Expand Down Expand Up @@ -361,7 +360,7 @@ ActionResult< CNEOBot > CNEOBotCtgCarrier::OnStart( CNEOBot *me, Action< CNEOBot
m_teammates.RemoveAll();
CollectPlayers( me, &m_teammates );

m_closestCapturePoint = GetNearestCapPoint( me );
m_closestCapturePoint = NEORules()->GetNearestGhostCapPoint( me->GetTeamNumber(), me->GetAbsOrigin() );

UpdateFollowPath( me, m_teammates );
return Continue();
Expand Down Expand Up @@ -419,44 +418,6 @@ ActionResult< CNEOBot > CNEOBotCtgCarrier::Update( CNEOBot *me, float interval )
}


//---------------------------------------------------------------------------------------------
Vector CNEOBotCtgCarrier::GetNearestCapPoint( const CNEOBot *me ) const
{
if ( !me )
return CNEO_Player::VECTOR_INVALID_WAYPOINT;

const int iMyTeam = me->GetTeamNumber();

if ( NEORules()->m_pGhostCaps.Count() > 0 )
{
Vector bestPos = CNEO_Player::VECTOR_INVALID_WAYPOINT;
float flNearestCapDistSq = FLT_MAX;
for( int i=0; i<NEORules()->m_pGhostCaps.Count(); ++i )
{
CNEOGhostCapturePoint *pCapPoint = dynamic_cast<CNEOGhostCapturePoint*>( UTIL_EntityByIndex( NEORules()->m_pGhostCaps[i] ) );
if (!pCapPoint || !pCapPoint->GetActive())
{
continue;
}

int iCapTeam = pCapPoint->owningTeamAlternate();
if ( iCapTeam == iMyTeam || iCapTeam == TEAM_ANY )
{
float distanceToCap = me->GetAbsOrigin().DistToSqr( pCapPoint->GetAbsOrigin() );
if ( distanceToCap < flNearestCapDistSq )
{
flNearestCapDistSq = distanceToCap;
bestPos = pCapPoint->GetAbsOrigin();
}
}
}
return bestPos;
}

return CNEO_Player::VECTOR_INVALID_WAYPOINT;
}


//---------------------------------------------------------------------------------------------
void CNEOBotCtgCarrier::UpdateFollowPath( CNEOBot *me, const CUtlVector<CNEO_Player*> &teammates )
{
Expand Down Expand Up @@ -649,14 +610,92 @@ void CNEOBotCtgCarrier::UpdateFollowPath( CNEOBot *me, const CUtlVector<CNEO_Pla
}
}

//---------------------------------------------------------------------------------------------
bool CNEOBotCtgCarrier::HasCleanRunToCap( const CNEOBot *me ) const
{
if ( !me->IsCarryingGhost() )
{
return false;
}

if ( m_closestCapturePoint == CNEO_Player::VECTOR_INVALID_WAYPOINT )
{
return false;
}

const float flMyDistToGoalSq = me->GetAbsOrigin().DistToSqr( m_closestCapturePoint );

CUtlVector< CKnownEntity > knownVector;
me->GetVisionInterface()->CollectKnownEntities( &knownVector );

for ( int i = 0; i < knownVector.Count(); ++i )
{
CBaseEntity *pKnown = knownVector[i].GetEntity();
if ( !pKnown || !pKnown->IsPlayer() || !pKnown->IsAlive() )
{
continue;
}

if ( pKnown->GetTeamNumber() == me->GetTeamNumber() )
{
continue;
}

if ( pKnown->GetAbsOrigin().DistToSqr( m_closestCapturePoint ) <= flMyDistToGoalSq )
{
// A known enemy is at least as close to the cap as we are.
return false;
}
}

return true;
}

//---------------------------------------------------------------------------------------------
bool CNEOBotCtgCarrier::IsCapPotentiallyVisible( const CNEOBot *me ) const
{
if ( !me->IsCarryingGhost() )
{
return false;
}

if ( m_closestCapturePoint == CNEO_Player::VECTOR_INVALID_WAYPOINT )
{
return false;
}

const CNavArea *capArea = TheNavMesh->GetNearestNavArea( m_closestCapturePoint );
const CNavArea *myArea = me->GetLastKnownArea();
if ( !capArea || !myArea )
{
return false;
}

return capArea->IsPotentiallyVisible( myArea );
}

//---------------------------------------------------------------------------------------------
QueryResultType CNEOBotCtgCarrier::ShouldHurry( const INextBot *me ) const
{
const CNEOBot *meBot = static_cast<const CNEOBot *>( me );

// Within sight of the cap zone, run for it regardless of who is closing in
if ( IsCapPotentiallyVisible( meBot ) || HasCleanRunToCap( meBot ) )
{
return ANSWER_YES;
}

return ANSWER_UNDEFINED;
}

//---------------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotCtgCarrier::OnResume( CNEOBot *me, Action< CNEOBot > *interruptingAction )
{
m_teammates.RemoveAll();
CollectPlayers( me, &m_teammates );

// Re-evaluate nearest cap point on resume (in case we moved significantly while interrupted)
m_closestCapturePoint = GetNearestCapPoint( me );
m_closestCapturePoint = NEORules()->GetNearestGhostCapPoint( me->GetTeamNumber(), me->GetAbsOrigin() );

UpdateFollowPath( me, m_teammates );
return Continue();
Expand Down
5 changes: 4 additions & 1 deletion src/game/server/neo/bot/behavior/neo_bot_ctg_carrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class CNEOBotCtgCarrier : public Action< CNEOBot >
virtual EventDesiredResult< CNEOBot > OnMoveToSuccess( CNEOBot *me, const Path *path ) override;
virtual EventDesiredResult< CNEOBot > OnMoveToFailure( CNEOBot *me, const Path *path, MoveToFailureType reason ) override;

virtual QueryResultType ShouldHurry( const INextBot *me ) const override;

virtual const char *GetName( void ) const override { return "ctgGhostCarrier"; }

private:
Expand All @@ -51,7 +53,8 @@ class CNEOBotCtgCarrier : public Action< CNEOBot >
Vector m_closestCapturePoint;
CUtlVector<CNEO_Player*> m_teammates;

Vector GetNearestCapPoint( const CNEOBot *me ) const;
bool HasCleanRunToCap( const CNEOBot *me ) const;
bool IsCapPotentiallyVisible( const CNEOBot *me ) const;
void UpdateFollowPath( CNEOBot *me, const CUtlVector<CNEO_Player*> &teammates );
};

Expand Down
23 changes: 23 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_ctg_enemy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,26 @@ EventDesiredResult< CNEOBot > CNEOBotCtgEnemy::OnMoveToFailure( CNEOBot *me, con
{
return TryContinue();
}

//---------------------------------------------------------------------------------------------
QueryResultType CNEOBotCtgEnemy::ShouldHurry( const INextBot *me ) const
{
const CNEOBot *meBot = static_cast<const CNEOBot *>( me );

CNEO_Player *pCarrier = ToNEOPlayer( UTIL_PlayerByIndex( NEORules()->GetGhosterPlayer() ) );
if ( !pCarrier || !pCarrier->IsAlive() || pCarrier->GetTeamNumber() == meBot->GetTeamNumber() )
{
return ANSWER_UNDEFINED;
}

const Vector vecCarrierGoal = NEORules()->GetNearestGhostCapPoint( pCarrier->GetTeamNumber(), pCarrier->GetAbsOrigin() );
if ( vecCarrierGoal == CNEO_Player::VECTOR_INVALID_WAYPOINT )
{
return ANSWER_UNDEFINED;
}

const float flCarrierToGoalSq = pCarrier->GetAbsOrigin().DistToSqr( vecCarrierGoal );
const float flMeToGoalSq = meBot->GetAbsOrigin().DistToSqr( vecCarrierGoal );

return ( flMeToGoalSq > flCarrierToGoalSq ) ? ANSWER_YES : ANSWER_UNDEFINED;
}
2 changes: 2 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_ctg_enemy.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class CNEOBotCtgEnemy : public Action< CNEOBot >
virtual EventDesiredResult< CNEOBot > OnMoveToSuccess( CNEOBot *me, const Path *path ) override;
virtual EventDesiredResult< CNEOBot > OnMoveToFailure( CNEOBot *me, const Path *path, MoveToFailureType reason ) override;

virtual QueryResultType ShouldHurry( const INextBot *me ) const override;

virtual const char *GetName( void ) const override { return "ctgEnemy"; }

private:
Expand Down
68 changes: 42 additions & 26 deletions src/game/server/neo/bot/behavior/neo_bot_ctg_escort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "bot/behavior/neo_bot_attack.h"
#include "bot/neo_bot_path_compute.h"
#include "neo_gamerules.h"
#include "neo_ghost_cap_point.h"
#include "weapons/weapon_ghost.h"

extern ConVar sv_neo_grenade_blast_radius;
Expand Down Expand Up @@ -241,6 +240,46 @@ EventDesiredResult< CNEOBot > CNEOBotCtgEscort::OnMoveToFailure( CNEOBot *me, co
return TryContinue();
}

//---------------------------------------------------------------------------------------------
// Hurry back to friendly ghost carrier if there are enemies closer to them
QueryResultType CNEOBotCtgEscort::ShouldHurry( const INextBot *me ) const
{
const CNEOBot *meBot = static_cast<const CNEOBot *>( me );

CNEO_Player *pCarrier = ToNEOPlayer( UTIL_PlayerByIndex( NEORules()->GetGhosterPlayer() ) );
if ( !pCarrier || !pCarrier->IsAlive() || pCarrier->GetTeamNumber() != meBot->GetTeamNumber() || pCarrier == meBot )
{
return ANSWER_UNDEFINED;
}

const Vector &vecCarrierPos = pCarrier->GetAbsOrigin();
const float flMyDistToCarrierSq = meBot->GetAbsOrigin().DistToSqr( vecCarrierPos );

CUtlVector< CKnownEntity > knownVector;
meBot->GetVisionInterface()->CollectKnownEntities( &knownVector );

for ( int i = 0; i < knownVector.Count(); ++i )
{
CBaseEntity *pKnown = knownVector[i].GetEntity();
if ( !pKnown || !pKnown->IsPlayer() || !pKnown->IsAlive() )
{
continue;
}

if ( pKnown->GetTeamNumber() == meBot->GetTeamNumber() )
{
continue;
}

if ( pKnown->GetAbsOrigin().DistToSqr( vecCarrierPos ) < flMyDistToCarrierSq )
{
return ANSWER_YES;
}
}

return ANSWER_UNDEFINED;
}

//---------------------------------------------------------------------------------------------
CNEOBotCtgEscort::EscortRole CNEOBotCtgEscort::UpdateRoleAssignment( CNEOBot *me, CNEO_Player *pGhostCarrier, const Vector &vecGoalPos )
{
Expand Down Expand Up @@ -324,29 +363,6 @@ CNEOBotCtgEscort::EscortRole CNEOBotCtgEscort::UpdateRoleAssignment( CNEOBot *me
//---------------------------------------------------------------------------------------------
void CNEOBotCtgEscort::UpdateGoalPosition( CNEOBot *me, CNEO_Player *pGhostCarrier )
{
m_vecGoalPos = CNEO_Player::VECTOR_INVALID_WAYPOINT;
m_bHasGoal = false;

float flNearestCapDistSq = FLT_MAX;
const int iMyTeam = me->GetTeamNumber();

for( int i=0; i<NEORules()->m_pGhostCaps.Count(); ++i )
{
CNEOGhostCapturePoint *pCapPoint = dynamic_cast<CNEOGhostCapturePoint*>( UTIL_EntityByIndex( NEORules()->m_pGhostCaps[i] ) );
if ( !pCapPoint || !pCapPoint->GetActive() )
{
continue;
}
const int iCapTeam = pCapPoint->owningTeamAlternate();
if ( iCapTeam == iMyTeam || iCapTeam == TEAM_ANY )
{
float d = pGhostCarrier->GetAbsOrigin().DistToSqr( pCapPoint->GetAbsOrigin() );
if ( d < flNearestCapDistSq )
{
flNearestCapDistSq = d;
m_vecGoalPos = pCapPoint->GetAbsOrigin();
m_bHasGoal = true;
}
}
}
m_vecGoalPos = NEORules()->GetNearestGhostCapPoint( me->GetTeamNumber(), pGhostCarrier->GetAbsOrigin() );
m_bHasGoal = ( m_vecGoalPos != CNEO_Player::VECTOR_INVALID_WAYPOINT );
}
2 changes: 2 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_ctg_escort.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class CNEOBotCtgEscort : public Action< CNEOBot >
virtual EventDesiredResult< CNEOBot > OnMoveToSuccess( CNEOBot *me, const Path *path ) override;
virtual EventDesiredResult< CNEOBot > OnMoveToFailure( CNEOBot *me, const Path *path, MoveToFailureType reason ) override;

virtual QueryResultType ShouldHurry( const INextBot *me ) const override;

virtual const char *GetName( void ) const override { return "ctgEscort"; }

private:
Expand Down
30 changes: 1 addition & 29 deletions src/game/server/neo/bot/behavior/neo_bot_ctg_lone_wolf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "bot/behavior/neo_bot_detpack_deploy.h"
#include "bot/neo_bot_path_compute.h"
#include "neo_gamerules.h"
#include "neo_ghost_cap_point.h"
#include "weapon_detpack.h"
#include "weapon_ghost.h"

Expand Down Expand Up @@ -229,33 +228,6 @@ Vector CNEOBotCtgLoneWolf::GetNearestEnemyCapPoint( CNEOBot *me ) const
}

const int iEnemyTeam = NEORules()->GetOpposingTeam( me->GetTeamNumber() );

if ( NEORules()->m_pGhostCaps.Count() > 0 )
{
const Vector* pBestPos = nullptr;
float flNearestSq = FLT_MAX;
for ( int i = 0; i < NEORules()->m_pGhostCaps.Count(); ++i )
{
CNEOGhostCapturePoint *pCapPoint = dynamic_cast<CNEOGhostCapturePoint*>( UTIL_EntityByIndex( NEORules()->m_pGhostCaps[i] ) );
if ( !pCapPoint || !pCapPoint->GetActive() )
{
continue;
}

int iCapTeam = pCapPoint->owningTeamAlternate();
if ( iCapTeam == iEnemyTeam || iCapTeam == TEAM_ANY )
{
float distSq = me->GetAbsOrigin().DistToSqr( pCapPoint->GetAbsOrigin() );
if ( distSq < flNearestSq )
{
flNearestSq = distSq;
pBestPos = &pCapPoint->GetAbsOrigin();
}
}
}
return pBestPos ? *pBestPos : CNEO_Player::VECTOR_INVALID_WAYPOINT;
}

return CNEO_Player::VECTOR_INVALID_WAYPOINT;
return NEORules()->GetNearestGhostCapPoint( iEnemyTeam, me->GetAbsOrigin() );
}

23 changes: 2 additions & 21 deletions src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "cbase.h"
#include "neo_player.h"
#include "neo_gamerules.h"
#include "neo_ghost_cap_point.h"
#include "team_control_point_master.h"
#include "bot/neo_bot.h"
#include "bot/behavior/neo_bot_attack.h"
Expand Down Expand Up @@ -161,26 +160,8 @@ ActionResult< CNEOBot > CNEOBotSeekAndDestroy::Update( CNEOBot *me, float interv
if (NEORules()->GetGameType() == NEO_GAME_TYPE_CTG)
{
// Only switch to CTG behavior if there are available capture zones this round
bool bHasAvailableCapZone = false;
const int iMyTeam = me->GetTeamNumber();

for( int i=0; i<NEORules()->m_pGhostCaps.Count(); ++i )
{
CNEOGhostCapturePoint *pCapPoint = dynamic_cast<CNEOGhostCapturePoint*>( UTIL_EntityByIndex( NEORules()->m_pGhostCaps[i] ) );
if ( !pCapPoint || !pCapPoint->GetActive() )
{
continue;
}

const int iCapTeam = pCapPoint->owningTeamAlternate();
if ( iCapTeam == iMyTeam || iCapTeam == TEAM_ANY )
{
bHasAvailableCapZone = true;
break;
}
}

if ( bHasAvailableCapZone )
const Vector vecCapPoint = NEORules()->GetNearestGhostCapPoint( me->GetTeamNumber(), me->GetAbsOrigin() );
if ( vecCapPoint != CNEO_Player::VECTOR_INVALID_WAYPOINT )
{
return SuspendFor( new CNEOBotCtgSeek, "Switching to Ghost-related Seek and Destroy" );
}
Expand Down
Loading