diff --git a/src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.cpp b/src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.cpp index a30d954344..7e85892070 100644 --- a/src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.cpp +++ b/src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.cpp @@ -227,6 +227,82 @@ QueryResultType CNEOBotSeekAndDestroy::ShouldHurry( const INextBot *me ) const return ANSWER_UNDEFINED; } + +//--------------------------------------------------------------------------------------------- +// Should I slow down to let my teammates catch up? +QueryResultType CNEOBotSeekAndDestroy::ShouldWalk( const CNEOBot *me, const QueryResultType qShouldAimQuery ) const +{ + // ShouldAim query shorts cuts ShouldWalk to ANSWER_YES as aiming and running blocks each other + if (qShouldAimQuery == ANSWER_YES) + { + return ANSWER_YES; + } + + const CKnownEntity* threat = me->GetVisionInterface()->GetPrimaryKnownThreat(); + if (threat != NULL) + { + // I need to decide how to deal with a threat + return ANSWER_UNDEFINED; + } + + if (NEORules()->GetGameType() == NEO_GAME_TYPE_CTG) + { + if (NEORules()->GhostExists()) + { + // For comparing my distance to the ghost compared to my teammates + const Vector &vGhostPos = NEORules()->GetGhostPos(); + float flMySqDistToGhost = (me->GetAbsOrigin() - vGhostPos).LengthSqr(); + int iAliveTeammates = 0; + + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + + if (!pPlayer || !pPlayer->IsAlive() || pPlayer->GetTeamNumber() != me->GetTeamNumber() || pPlayer == me->GetEntity()) + { + continue; + } + + iAliveTeammates++; + + const CNEO_Player *pNeoPlayer = ToNEOPlayer(pPlayer); + if (pNeoPlayer && pNeoPlayer->IsCarryingGhost()) + { + // Maybe I can catch up to my team's ghost carrier + return ANSWER_UNDEFINED; + } + + // Check if this teammate is closer to the ghost + float flTeammateSqDistToGhost = (pPlayer->GetAbsOrigin() - vGhostPos).LengthSqr(); + if (flTeammateSqDistToGhost < flMySqDistToGhost) + { + // Maybe I can catch up to my teammate up ahead + return ANSWER_UNDEFINED; + } + } + + if (iAliveTeammates == 0) + { + // I'm the sole survivor, don't need to wait for anyone + return ANSWER_UNDEFINED; + } + + // I should slow down to let my teammates catch up + return ANSWER_YES; + } + } + + return ANSWER_UNDEFINED; +} + + +//--------------------------------------------------------------------------------------------- +QueryResultType CNEOBotSeekAndDestroy::ShouldAim(const CNEOBot* me, const bool bWepHasClip) const +{ + return ANSWER_UNDEFINED; +} + + class CNextSpawnFilter : public IEntityFindFilter { public: diff --git a/src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.h b/src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.h index 39950bfa70..9731d0148c 100644 --- a/src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.h +++ b/src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.h @@ -1,12 +1,12 @@ #pragma once #include "Path/NextBotChasePath.h" - +#include "bot/neo_bot_contextual_query_interface.h" // // Roam around the map attacking enemies // -class CNEOBotSeekAndDestroy : public Action< CNEOBot > +class CNEOBotSeekAndDestroy : public Action< CNEOBot >, public CNEOBotContextualQueryInterface { public: CNEOBotSeekAndDestroy( float duration = -1.0f ); @@ -22,6 +22,8 @@ class CNEOBotSeekAndDestroy : public Action< CNEOBot > virtual QueryResultType ShouldRetreat( const INextBot *me ) const; // is it time to retreat? virtual QueryResultType ShouldHurry( const INextBot *me ) const; // are we in a hurry? + virtual QueryResultType ShouldWalk( const CNEOBot *me, const QueryResultType qShouldAimQuery ) const override; // are we to walk? + virtual QueryResultType ShouldAim(const CNEOBot *me, const bool bWepHasClip) const override; virtual EventDesiredResult< CNEOBot > OnTerritoryCaptured( CNEOBot *me, int territoryID ); virtual EventDesiredResult< CNEOBot > OnTerritoryLost( CNEOBot *me, int territoryID ); diff --git a/src/game/server/neo/bot/neo_bot.cpp b/src/game/server/neo/bot/neo_bot.cpp index 8390df1cf8..068272bd99 100644 --- a/src/game/server/neo/bot/neo_bot.cpp +++ b/src/game/server/neo/bot/neo_bot.cpp @@ -2657,24 +2657,29 @@ QueryResultType CNEOBotBehavior::ShouldWalk(const CNEOBot *me, const QueryResult { QueryResultType result = ANSWER_UNDEFINED; - auto *neoAction = static_cast(m_action); - if ( neoAction ) + Action *action = m_action; + if ( action ) { // find innermost child action - CNEOBotMainAction *action; - for( action = neoAction; action->m_child; action = static_cast(action->m_child) ) - ; + while( action->GetActiveChildAction() ) + { + action = action->GetActiveChildAction(); + } // work our way through our containers while( action && result == ANSWER_UNDEFINED ) { - CNEOBotMainAction *containingAction = static_cast(action->m_parent); + Action *containingAction = action->GetParentAction(); // work our way up the stack while( action && result == ANSWER_UNDEFINED ) { - result = action->ShouldWalk(me, qShouldAimQuery); - action = static_cast(action->GetActionBuriedUnderMe()); + auto *query = dynamic_cast(action); + if (query) + { + result = query->ShouldWalk(me, qShouldAimQuery); + } + action = action->GetActionBuriedUnderMe(); } action = containingAction; @@ -2693,24 +2698,29 @@ QueryResultType CNEOBotBehavior::ShouldAim(const CNEOBot *me, const bool bWepHas { QueryResultType result = ANSWER_UNDEFINED; - auto *neoAction = static_cast(m_action); - if ( neoAction ) + Action *action = m_action; + if ( action ) { // find innermost child action - CNEOBotMainAction *action; - for( action = neoAction; action->m_child; action = static_cast(action->m_child) ) - ; + while( action->GetActiveChildAction() ) + { + action = action->GetActiveChildAction(); + } // work our way through our containers while( action && result == ANSWER_UNDEFINED ) { - CNEOBotMainAction *containingAction = static_cast(action->m_parent); + Action *containingAction = action->GetParentAction(); // work our way up the stack while( action && result == ANSWER_UNDEFINED ) { - result = action->ShouldAim(me, bWepHasClip); - action = static_cast(action->GetActionBuriedUnderMe()); + auto *query = dynamic_cast(action); + if (query) + { + result = query->ShouldAim(me, bWepHasClip); + } + action = action->GetActionBuriedUnderMe(); } action = containingAction;