diff --git a/src/game/server/NextBot/Path/NextBotPathFollow.cpp b/src/game/server/NextBot/Path/NextBotPathFollow.cpp index eff4ba5e33..7f65ca0078 100644 --- a/src/game/server/NextBot/Path/NextBotPathFollow.cpp +++ b/src/game/server/NextBot/Path/NextBotPathFollow.cpp @@ -474,6 +474,13 @@ bool PathFollower::CheckProgress( INextBot *bot ) { if ( ( pSkipToGoal->pos - myFeet ).IsLengthLessThan( m_minLookAheadRange ) ) { +#ifdef NEO + if ( pSkipToGoal->area && pSkipToGoal->area->HasAttributes( NAV_MESH_PRECISE ) ) + { + // don't skip segments or take shortcuts in a PRECISE area + break; + } +#endif // goal is too close - step to next segment const Path::Segment *nextSegment = NextSegment( pSkipToGoal ); diff --git a/src/game/server/neo/bot/behavior/neo_bot_attack.cpp b/src/game/server/neo/bot/behavior/neo_bot_attack.cpp index fa46e0c05b..f663476874 100644 --- a/src/game/server/neo/bot/behavior/neo_bot_attack.cpp +++ b/src/game/server/neo/bot/behavior/neo_bot_attack.cpp @@ -291,14 +291,17 @@ ActionResult< CNEOBot > CNEOBotAttack::Update( CNEOBot *me, float interval ) if (!m_attackCoverArea // don't slow movement to cover with strafing && isUsingCloseRangeWeapon && threat->IsVisibleRecently() && me->IsRangeLessThan( threatLastKnownPos, 1.1f * me->GetDesiredAttackRange() ) ) { - // circle around our victim - if ( me->TransientlyConsistentRandomValue( 3.0f ) < 0.5f ) + // circle around our victim, unless a sidestep could take us off a ledge + if ( !me->IsOnPreciseArea() ) { - me->PressLeftButton(); - } - else - { - me->PressRightButton(); + if ( me->TransientlyConsistentRandomValue( 3.0f ) < 0.5f ) + { + me->PressLeftButton(); + } + else + { + me->PressRightButton(); + } } } diff --git a/src/game/server/neo/bot/behavior/neo_bot_behavior.cpp b/src/game/server/neo/bot/behavior/neo_bot_behavior.cpp index 4612059324..37969a26a5 100644 --- a/src/game/server/neo/bot/behavior/neo_bot_behavior.cpp +++ b/src/game/server/neo/bot/behavior/neo_bot_behavior.cpp @@ -1236,6 +1236,10 @@ void CNEOBotMainAction::Dodge( CNEOBot *me ) if ( me->HasAttribute( CNEOBot::DISABLE_DODGE ) ) return; + // a sidestep on a ledge or beside a drop can walk the bot off it + if ( me->IsOnPreciseArea() ) + return; + // don't waste time doding if we're in a hurry if ( me->GetIntentionInterface()->ShouldHurry( me ) == ANSWER_YES ) return; diff --git a/src/game/server/neo/bot/behavior/neo_bot_tactical_monitor.cpp b/src/game/server/neo/bot/behavior/neo_bot_tactical_monitor.cpp index e0f1cfffca..bcc327e9a4 100644 --- a/src/game/server/neo/bot/behavior/neo_bot_tactical_monitor.cpp +++ b/src/game/server/neo/bot/behavior/neo_bot_tactical_monitor.cpp @@ -220,6 +220,12 @@ void CNEOBotTacticalMonitor::AvoidBumpingFriends( CNEOBot *me ) return; } + // stepping straight away from a teammate can step off a ledge + if ( me->IsOnPreciseArea() ) + { + return; + } + CUtlVector< CNEO_Player * > friendVector; CollectPlayers( &friendVector, me->GetTeamNumber(), COLLECT_ONLY_LIVING_PLAYERS ); diff --git a/src/game/server/neo/bot/neo_bot.cpp b/src/game/server/neo/bot/neo_bot.cpp index 7d0e4d4ea5..0f53be5d8c 100644 --- a/src/game/server/neo/bot/neo_bot.cpp +++ b/src/game/server/neo/bot/neo_bot.cpp @@ -2876,6 +2876,14 @@ bool CNEOBot::IsEnemy(const CBaseEntity* them) const } +// For disabling erratic movements like strafing where one wrong step could move a bot off a cliff +// Also useful for navigating areas that require precision to navigate like obstructed pathways +bool CNEOBot::IsOnPreciseArea() const +{ + const CNavArea *area = GetLastKnownArea(); + return area && area->HasAttributes( NAV_MESH_PRECISE | NAV_MESH_CLIFF ); +} + bool CNEOBot::IsBotOnLadder() const { ILocomotion* mover = GetLocomotionInterface(); diff --git a/src/game/server/neo/bot/neo_bot.h b/src/game/server/neo/bot/neo_bot.h index 4f9716b9d4..2124346bcd 100644 --- a/src/game/server/neo/bot/neo_bot.h +++ b/src/game/server/neo/bot/neo_bot.h @@ -187,6 +187,7 @@ class CNEOBot : public NextBotPlayer< CNEO_Player >, public CGameEventListener bool IsEnemy(const CBaseEntity* them) const OVERRIDE; bool IsBotOnLadder( ) const; + bool IsOnPreciseArea() const; // on a NAV_MESH_PRECISE or NAV_MESH_CLIFF area, where the path must be walked exactly CNEOBaseCombatWeapon* GetBludgeonWeapon(void);