Skip to content
Draft
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
3 changes: 1 addition & 2 deletions src/game/server/neo/bot/behavior/neo_bot_jgr_juggernaut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#include "neo_player.h"
#include "neo_gamerules.h"
#include "bot/neo_bot.h"
#include "bot/neo_bot_path_compute.h"
#include "bot/behavior/neo_bot_jgr_juggernaut.h"
#include "bot/behavior/neo_bot_retreat_to_cover.h"
#include "weapon_balc.h"
Expand Down Expand Up @@ -70,7 +69,7 @@ void CNEOBotJgrJuggernaut::RecomputeSeekPath( CNEOBot *me )
m_vGoalPos = pTargetSpawn->GetAbsOrigin();
m_bGoingToTargetEntity = false;

if (CNEOBotPathCompute(me, m_path, m_vGoalPos, DEFAULT_ROUTE) && m_path.IsValid() && m_path.GetResult() == Path::COMPLETE_PATH)
if (TryPathToRoamGoal(me, m_vGoalPos))
{
return;
}
Expand Down
14 changes: 14 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_retreat_to_cover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,20 @@ ActionResult< CNEOBot > CNEOBotRetreatToCover::Update( CNEOBot *me, float interv
if ( !m_path.IsValid() )
{
CNEOBotPathCompute( me, m_path, m_coverArea->GetCenter(), RETREAT_ROUTE );

// Cover is chosen where the retreat starts; after a drop off a ledge no route
// may reach it any more, so choose again from here
if ( !CNEOBotPathReachesGoal( m_path ) )
{
CNavArea *pUnreachableArea = m_coverArea;
m_coverArea = FindCoverArea( me );
if ( m_coverArea == NULL || m_coverArea == pUnreachableArea )
{
return Done( "My cover is out of reach, and there is no other cover available!" );
}

CNEOBotPathCompute( me, m_path, m_coverArea->GetCenter(), RETREAT_ROUTE );
}
}

m_path.Update( me );
Expand Down
19 changes: 14 additions & 5 deletions src/game/server/neo/bot/behavior/neo_bot_seek_and_destroy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ bool CNEOBotSeekAndDestroy::TryPathToCombatSound( CNEOBot *me )
m_combatSoundCommitTimer.Start( sv_neo_bot_seek_and_destroy_combat_sound_commit_time.GetFloat() );
}

if ( CNEOBotPathCompute( me, m_path, m_vCombatSoundSpot, DEFAULT_ROUTE )
&& m_path.IsValid() && m_path.GetResult() == Path::COMPLETE_PATH )
if ( TryPathToRoamGoal( me, m_vCombatSoundSpot ) )
{
m_vGoalPos = m_vCombatSoundSpot;
m_bGoingToTargetEntity = false;
Expand All @@ -128,6 +127,15 @@ bool CNEOBotSeekAndDestroy::TryPathToCombatSound( CNEOBot *me )
}


//---------------------------------------------------------------------------------------------
// Roam goals are picked at random, so skip one that no route reaches instead of walking at it. A refused
// attempt stays in m_path: the wander loop's last resort keeps it.
bool CNEOBotSeekAndDestroy::TryPathToRoamGoal( CNEOBot *me, const Vector &vGoal )
{
return CNEOBotPathCompute( me, m_path, vGoal, DEFAULT_ROUTE ) && CNEOBotPathReachesGoal( m_path );
}


//---------------------------------------------------------------------------------------------
CNEOBotSeekAndDestroy::CNEOBotSeekAndDestroy( float duration )
{
Expand Down Expand Up @@ -592,7 +600,7 @@ void CNEOBotSeekAndDestroy::RecomputeSeekPath( CNEOBot *me )
m_hTargetEntity = pSpawns[RandomInt( 0, pSpawns.Size() - 1 )];
m_bGoingToTargetEntity = true;
m_vGoalPos = m_hTargetEntity->WorldSpaceCenter();
if ( CNEOBotPathCompute( me, m_path, m_vGoalPos, DEFAULT_ROUTE ) && m_path.IsValid() && m_path.GetResult() == Path::COMPLETE_PATH )
if ( TryPathToRoamGoal( me, m_vGoalPos ) )
return;
}
}
Expand All @@ -604,11 +612,12 @@ void CNEOBotSeekAndDestroy::RecomputeSeekPath( CNEOBot *me )

Vector vWanderPoint = TheNavAreas[RandomInt( 0, TheNavAreas.Size() - 1 )]->GetCenter();
m_vGoalPos = vWanderPoint;
if ( CNEOBotPathCompute( me, m_path, vWanderPoint, DEFAULT_ROUTE ) )
if ( TryPathToRoamGoal( me, vWanderPoint ) )
return;
}

m_path.Invalidate();
// No wander point has a route either (a pocket, or hazards all round): keep the last one's partial or
// straight-line path rather than stand still
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class CNEOBotSeekAndDestroy : public Action< CNEOBot >
virtual void RecomputeSeekPath( CNEOBot *me );

bool TryPathToCombatSound( CNEOBot *me );
bool TryPathToRoamGoal( CNEOBot *me, const Vector &vGoal );
virtual bool IsSeekGoalAnObjective() const { return false; }

PathFollower m_path;
Expand Down
18 changes: 18 additions & 0 deletions src/game/server/neo/bot/neo_bot_path_compute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,24 @@ bool CNEOBotPathCompute(CNEOBot* bot, PathFollower& path, const Vector& goal, Ro
return false;
}

// When no route reaches the goal and the search got no nearer to it than the bot's own area,
// Path::Compute falls back to a straight line labeled COMPLETE_PATH: two segments in two areas
bool CNEOBotPathReachesGoal(const PathFollower& path)
{
if (!path.IsValid() || path.GetResult() != Path::COMPLETE_PATH)
{
return false;
}

const Path::Segment* pFirst = path.FirstSegment();
const Path::Segment* pLast = path.LastSegment();

// A goal inside the bot's own area also gives a two-segment path,
// so where the areas nearest the bot and the goal differ (stacked or overlapping areas) it reads as the fallback
const bool bStraightLineFallback = (path.NextSegment(pFirst) == pLast) && (pFirst->area != pLast->area);
return !bStraightLineFallback;
}

bool CNEOBotPathUpdateChase(CNEOBot* bot, ChasePath& path, CBaseEntity* subject, RouteType route, Vector* pPredictedSubjectPos)
{
CNEOBotPathCost cost_with_reservations(bot, route);
Expand Down
4 changes: 4 additions & 0 deletions src/game/server/neo/bot/neo_bot_path_compute.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ bool CNEOBotPathCompute
bool requireGoalArea = false
);

// True if the path reaches its goal: complete, and not the straight-line fallback
// Path::Compute builds when no route reaches the goal
bool CNEOBotPathReachesGoal(const PathFollower& path);

bool CNEOBotPathUpdateChase
(
CNEOBot *bot,
Expand Down
Loading