Skip to content
Merged
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
59 changes: 46 additions & 13 deletions src/game/server/neo/bot/neo_bot_path_obstacles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,26 @@ static void GetLineBounds( const CUtlVector< Vector > &line, float range, Vector
}


//----------------------------------------------------------------------------------------------------------------
// Return true if the body, walking the line up to the end of the given leg, meets the entity before anything else,
// passing through players, who move
static bool IsMetFirst( INextBot *bot, const BodyBox_t &body, const CUtlVector< Vector > &line, int lastLeg, CBaseEntity *entity )
{
CTraceFilterNoNPCsOrPlayer filter( bot->GetEntity(), COLLISION_GROUP_NONE );
for ( int leg = 0; leg <= lastLeg; ++leg )
{
trace_t result;
UTIL_TraceHull( line[ leg ], line[ leg + 1 ], body.mins, body.maxs, MASK_PLAYERSOLID, &filter, &result );
if ( result.DidHit() )
{
return result.m_pEnt == entity;
}
}

return false;
}


//----------------------------------------------------------------------------------------------------------------
// The breakable the body meets first walking the line, within PATH_OBSTACLE_BREAKABLE_RANGE,
// when nothing else stands in front of it
Expand Down Expand Up @@ -130,25 +150,32 @@ static CBaseEntity *FindBreakableInWay( INextBot *bot, const BodyBox_t &body, co
}

// what the body meets first on the way may be a crate, a door or a wall in front of the breakable:
// keep the breakable only if the body reaches it first, passing through players, who move
CTraceFilterNoNPCsOrPlayer filter( bot->GetEntity(), COLLISION_GROUP_NONE );
for ( int leg = 0; leg <= nearestLeg; ++leg )
// keep the breakable only if the body reaches it first
if ( IsMetFirst( bot, body, line, nearestLeg, nearest ) )
{
trace_t result;
UTIL_TraceHull( line[ leg ], line[ leg + 1 ], body.mins, body.maxs, MASK_PLAYERSOLID, &filter, &result );
if ( result.DidHit() )
{
return ( result.m_pEnt == nearest ) ? nearest : NULL;
}
return nearest;
}

return NULL;
// or reaches it crouched, since a vent cover in a crawl gap sits under a lintel the standing body meets first
BodyBox_t crouched = body;
crouched.maxs.z = bot->GetBodyInterface()->GetCrouchHullHeight();
return IsMetFirst( bot, crouched, line, nearestLeg, nearest ) ? nearest : NULL;
}

//----------------------------------------------------------------------------------------------------------------
// Where the path ahead ends: at the first segment not walked on the ground,
// or at the ledge of a drop, which is walked at the height of the floor above before the fall
enum PathAheadEnd_t
{
PATH_AHEAD_TO_GROUND_END,
PATH_AHEAD_TO_DROP_LEDGE,
};

//----------------------------------------------------------------------------------------------------------------
// The path ahead as a line from the bot's feet, over walked segments only, up to the range,
// and, given a list for them, the segment each point of the line belongs to
static void GetPathAhead( const PathFollower &path, const Vector &feet, float range, CUtlVector< Vector > *line, CUtlVector< const Path::Segment * > *segments = NULL )
static void GetPathAhead( const PathFollower &path, const Vector &feet, float range, CUtlVector< Vector > *line,
CUtlVector< const Path::Segment * > *segments = NULL, PathAheadEnd_t end = PATH_AHEAD_TO_GROUND_END )
{
line->AddToTail( feet );
if ( segments )
Expand All @@ -159,7 +186,8 @@ static void GetPathAhead( const PathFollower &path, const Vector &feet, float ra
float length = 0.0f;
for ( const Path::Segment *seg = path.GetCurrentGoal(); seg && length < range; seg = path.NextSegment( seg ) )
{
if ( seg->ladder || seg->type != Path::ON_GROUND )
const bool isDropLedge = ( end == PATH_AHEAD_TO_DROP_LEDGE && seg->type == Path::DROP_DOWN );
if ( seg->ladder || ( seg->type != Path::ON_GROUND && !isDropLedge ) )
{
break;
}
Expand All @@ -179,6 +207,10 @@ static void GetPathAhead( const PathFollower &path, const Vector &feet, float ra

length += legLength;
line->AddToTail( seg->pos );
if ( isDropLedge )
{
break;
}
}
}

Expand Down Expand Up @@ -358,7 +390,8 @@ void CNEOBotPathObstacles::LookForBreakable( INextBot *bot, const PathFollower &
m_breakable = NULL;

CUtlVector< Vector > line;
GetPathAhead( path, bot->GetLocomotionInterface()->GetFeet(), PATH_OBSTACLE_BREAKABLE_RANGE, &line );
// a vent cover can block the way to a drop's ledge, such as out of a crawl duct
GetPathAhead( path, bot->GetLocomotionInterface()->GetFeet(), PATH_OBSTACLE_BREAKABLE_RANGE, &line, NULL, PATH_AHEAD_TO_DROP_LEDGE );
if ( line.Count() < 2 )
{
return;
Expand Down
Loading