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
2 changes: 1 addition & 1 deletion src/game/server/neo/bot/behavior/neo_bot_attack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,10 @@ ActionResult< CNEOBot > CNEOBotAttack::Update( CNEOBot *me, float interval )
// Consider throwing a grenade
if ( !m_grenadeThrowCooldownTimer.HasStarted() || m_grenadeThrowCooldownTimer.IsElapsed() )
{
m_grenadeThrowCooldownTimer.Start( sv_neo_bot_grenade_throw_cooldown.GetFloat() );
Action<CNEOBot> *pGrenadeBehavior = CNEOBotGrenadeDispatch::ChooseGrenadeThrowBehavior( me, threat );
if ( pGrenadeBehavior )
{
m_grenadeThrowCooldownTimer.Start( sv_neo_bot_grenade_throw_cooldown.GetFloat() );
return SuspendFor( pGrenadeBehavior, "Throwing grenade before chasing threat!" );
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_grenade_dispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ Action< CNEOBot > *CNEOBotGrenadeDispatch::ChooseGrenadeThrowBehavior( const CNE
}
}

// Don't commit to a throw when there's nowhere to throw from yet
if ( me->FindVisibleThrowPointNear( threat->GetLastKnownPosition() ) == vec3_invalid )
{
return nullptr;
}

return new CNEOBotGrenadeThrowFrag( pFragGrenade, threat );
}

Expand Down
65 changes: 2 additions & 63 deletions src/game/server/neo/bot/behavior/neo_bot_grenade_throw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include "weapon_grenade.h"
#include "weapon_smokegrenade.h"
#include "nav_mesh.h"
#include "nav_pathfind.h"
#include "bot/neo_bot_path_compute.h"

extern ConVar sv_neo_bot_grenade_frag_safety_range_multiplier;
Expand Down Expand Up @@ -44,68 +43,6 @@ CNEOBotGrenadeThrow::CNEOBotGrenadeThrow( CNEOBaseCombatWeapon *pWeapon, const C
}
}

//---------------------------------------------------------------------------------------------
// Used to anticipate the emergence point from cover ahead of a path
// Is calculated in reverse of path to find the farthest point from bot
// (assuming "familiar" position is closer to the bot than the "obscured" position)
const Vector& CNEOBotGrenadeThrow::FindEmergencePointAlongPath( const CNEOBot *me, const Vector &familiarPos, const Vector &obscuredPos )
{
CNavArea *familiarArea = TheNavMesh->GetNavArea( familiarPos );
if ( !familiarArea )
{
return vec3_invalid;
}

CNavArea *obscuredArea = TheNavMesh->GetNavArea( obscuredPos );
if ( !obscuredArea )
{
return vec3_invalid;
}

ShortestPathCost cost;
const Vector& vecGoal = obscuredPos;
if ( NavAreaBuildPath( familiarArea, obscuredArea, &vecGoal, cost ) )
{
// search backwards from obscured position to find the first point visible to me
for ( CNavArea *area = obscuredArea; area; area = area->GetParent() )
{
// DEBUG: Draw emergence path
// Color: Yellow (255, 255, 0) to distinguish path analysis
if ( sv_neo_bot_grenade_debug_behavior.GetBool() )
{
if ( area->GetParent() )
{
NDebugOverlay::HorzArrow( area->GetCenter(), area->GetParent()->GetCenter(), 2.0f, 255, 255, 0, 255, true, 2.0f );
}
else
{
NDebugOverlay::Cross3D( area->GetCenter(), 16.0f, 255, 255, 0, true, 2.0f );
}
}

const Vector& vecTest = area->GetCenter();

if ( me->IsLineOfFireClear( vecTest, CNEOBot::LINE_OF_FIRE_FLAGS_SHOTGUN ) )
{
// DEBUG: Draw emergence point
if ( sv_neo_bot_grenade_debug_behavior.GetBool() )
{
NDebugOverlay::Box( vecTest, Vector(-16,-16,-16), Vector(16,16,16), 255, 255, 0, 50, 2.0f );
}
return vecTest;
}

if ( area == familiarArea )
{
return vec3_invalid;
}
}
}

return vec3_invalid;
}


//---------------------------------------------------------------------------------------------
class CFindVantagePointTargetPos : public ISearchSurroundingAreasFunctor
{
Expand Down Expand Up @@ -524,6 +461,8 @@ ActionResult< CNEOBot > CNEOBotGrenadeThrow::Update( CNEOBot *me, float interval
// and want to bypass the weapon's internal scheduled throw to ensure it happens NOW.
if ( bAimOnTarget )
{
OnThrowReleased( me );

// Play first person throw animation
pWep->SendWeaponAnim( ACT_VM_THROW );

Expand Down
3 changes: 1 addition & 2 deletions src/game/server/neo/bot/behavior/neo_bot_grenade_throw.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ class CNEOBotGrenadeThrow : public Action< CNEOBot >

CNavArea *FindVantageArea( CNEOBot *me );

static const Vector& FindEmergencePointAlongPath( const CNEOBot *me, const Vector &familiarPos, const Vector &obscuredPos );

virtual ThrowTargetResult UpdateGrenadeTargeting( CNEOBot *me, CNEOBaseCombatWeapon *pWeapon ) = 0;
virtual void OnThrowReleased( CNEOBot *me ) { }

};

Expand Down
15 changes: 7 additions & 8 deletions src/game/server/neo/bot/behavior/neo_bot_grenade_throw_frag.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
#include "cbase.h"
#include "bot/neo_bot.h"
#include "bot/neo_bot_path_compute.h"
#include "bot/neo_bot_path_reservation.h"
#include "bot/behavior/neo_bot_grenade_throw_frag.h"
#include "neo_gamerules.h"
#include "neo_player.h"
#include "weapon_neobasecombatweapon.h"

#include "nav_mesh.h"
#include "nav_pathfind.h"

extern ConVar sv_neo_grenade_blast_radius;
extern ConVar sv_neo_grenade_fuse_timer;
Expand Down Expand Up @@ -69,11 +67,9 @@ CNEOBotGrenadeThrow::ThrowTargetResult CNEOBotGrenadeThrowFrag::UpdateGrenadeTar
{
// Last known location in view, but don't see threat
// Infer where the threat could have gone
// CHEAT: calculate a path from the last known position to the actual threat position
// and throw at the furthest visible point along that path
if ( me->IsLineOfSightClear( m_vecThreatLastKnownPos ) && m_scanTimer.IsElapsed() )
if ( m_scanTimer.IsElapsed() )
{
const Vector& vecThrowTarget = FindEmergencePointAlongPath( me, m_vecThreatLastKnownPos, m_hThreatGrenadeTarget->GetAbsOrigin() );
const Vector vecThrowTarget = me->FindVisibleThrowPointNear( m_vecThreatLastKnownPos );

if ( vecThrowTarget != vec3_invalid )
{
Expand Down Expand Up @@ -108,6 +104,11 @@ CNEOBotGrenadeThrow::ThrowTargetResult CNEOBotGrenadeThrowFrag::UpdateGrenadeTar
return THROW_TARGET_CANCEL; // risk of friendly fire
}

return THROW_TARGET_READY;
}

void CNEOBotGrenadeThrowFrag::OnThrowReleased( CNEOBot *me )
{
// Register explosive hazard at the target position
// so the throwing bot's team can avoid the trajectory and landing areas
CNavArea *area = TheNavMesh->GetNearestNavArea(m_vecTarget);
Expand All @@ -116,8 +117,6 @@ CNEOBotGrenadeThrow::ThrowTargetResult CNEOBotGrenadeThrowFrag::UpdateGrenadeTar
int team = me->GetTeamNumber();
CNEOBotPathReservations()->AddFragHazard(area->GetID(), gpGlobals->curtime + sv_neo_grenade_fuse_timer.GetFloat(), team);
}

return THROW_TARGET_READY;
}

float CNEOBotGrenadeThrowFrag::GetFragSafetyRadius()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class CNEOBotGrenadeThrowFrag : public CNEOBotGrenadeThrow

protected:
virtual ThrowTargetResult UpdateGrenadeTargeting( CNEOBot *me, CNEOBaseCombatWeapon *pWeapon ) override;
virtual void OnThrowReleased( CNEOBot *me ) override;
};

#endif // NEO_BOT_GRENADE_THROW_FRAG_H
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
#include "neo_player.h"
#include "bot/neo_bot.h"
#include "bot/behavior/neo_bot_grenade_throw_smoke.h"
#include "bot/neo_bot_path_compute.h"
#include "weapon_neobasecombatweapon.h"

#include "nav_pathfind.h"

CNEOBotGrenadeThrowSmoke::CNEOBotGrenadeThrowSmoke( CNEOBaseCombatWeapon *pWeapon, const CKnownEntity *threat )
: CNEOBotGrenadeThrow( pWeapon, threat )
{
Expand All @@ -29,7 +26,7 @@ CNEOBotGrenadeThrow::ThrowTargetResult CNEOBotGrenadeThrowSmoke::UpdateGrenadeTa

if (m_vecTarget == vec3_invalid)
{
const Vector& vecThrowTarget = FindEmergencePointAlongPath(me, me->GetAbsOrigin(), m_vecThreatLastKnownPos);
const Vector vecThrowTarget = me->FindVisibleThrowPointNear( m_vecThreatLastKnownPos );

if (vecThrowTarget != vec3_invalid)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ ActionResult< CNEOBot > CNEOBotRetreatToCover::Update( CNEOBot *me, float interv
if ( ( !m_grenadeThrowCooldownTimer.HasStarted() || m_grenadeThrowCooldownTimer.IsElapsed() ) &&
threat && threat->GetEntity() && !me->IsLineOfFireClear( threat->GetEntity()->EyePosition(), CNEOBot::LINE_OF_FIRE_FLAGS_DEFAULT ) )
{
m_grenadeThrowCooldownTimer.Start( sv_neo_bot_grenade_throw_cooldown.GetFloat() );
Action<CNEOBot> *pGrenadeBehavior = CNEOBotGrenadeDispatch::ChooseGrenadeThrowBehavior( me, threat );
if ( pGrenadeBehavior )
{
m_grenadeThrowCooldownTimer.Start( sv_neo_bot_grenade_throw_cooldown.GetFloat() );
return SuspendFor( pGrenadeBehavior, "Throwing grenade while taking cover!" );
}
}
Expand Down
52 changes: 49 additions & 3 deletions src/game/server/neo/bot/neo_bot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1148,10 +1148,10 @@ void CNEOBot::OnWeaponFired(CBaseCombatCharacter* whoFired, CBaseCombatWeapon* w


//-----------------------------------------------------------------------------------------------------
class CFindClosestPotentiallyVisibleAreaToPos
class CNEOFindClosestPotentiallyVisibleAreaToPos
{
public:
CFindClosestPotentiallyVisibleAreaToPos(const Vector& pos)
CNEOFindClosestPotentiallyVisibleAreaToPos(const Vector& pos)
{
m_pos = pos;
m_closeArea = NULL;
Expand Down Expand Up @@ -1181,6 +1181,34 @@ class CFindClosestPotentiallyVisibleAreaToPos
};


//-----------------------------------------------------------------------------------------------------
Vector CNEOBot::FindVisibleThrowPointNear( const Vector &vecPos ) const
{
CNavArea *myArea = GetLastKnownArea();
if ( !myArea )
{
return vec3_invalid;
}

CNEOFindClosestPotentiallyVisibleAreaToPos find( vecPos );
myArea->ForAllPotentiallyVisibleAreas( find );
if ( !find.m_closeArea )
{
return vec3_invalid;
}

Vector vecPoint;
find.m_closeArea->GetClosestPointOnArea( vecPos, &vecPoint );
if ( IsThrowLineClear( vecPoint ) )
{
return vecPoint;
}

const Vector &vecCenter = find.m_closeArea->GetCenter();
return IsThrowLineClear( vecCenter ) ? vecCenter : vec3_invalid;
}


//-----------------------------------------------------------------------------------------------------
// Update our view to watch where members of the given team will be coming from
void CNEOBot::UpdateLookingAroundForIncomingPlayers(bool lookForEnemies)
Expand Down Expand Up @@ -1255,7 +1283,7 @@ void CNEOBot::UpdateLookingAroundForEnemies(void)
if (myArea)
{
const CNavArea* closeArea = NULL;
CFindClosestPotentiallyVisibleAreaToPos find(known->GetLastKnownPosition());
CNEOFindClosestPotentiallyVisibleAreaToPos find(known->GetLastKnownPosition());
myArea->ForAllPotentiallyVisibleAreas(find);

closeArea = find.m_closeArea;
Expand Down Expand Up @@ -2035,6 +2063,24 @@ bool CNEOBot::IsLineOfFireClear(const Vector& where, const LineOfFireFlags flags
}


//-----------------------------------------------------------------------------------------------------
// Return true if a thrown object (like a grenade) has a completely unobstructed physical line to the target.
// Unlike IsLineOfFireClear, this requires !trace.DidHit() and will NOT treat breakable entities (like glass) as clear.
bool CNEOBot::IsThrowLineClear(const Vector& from, const Vector& to) const
{
trace_t trace;
NextBotTraceFilterIgnoreActors filter(NULL, COLLISION_GROUP_NONE);
Comment thread
Rainyan marked this conversation as resolved.
UTIL_TraceLine(from, to, MASK_SHOT, &filter, &trace);
return !trace.DidHit();
}

//-----------------------------------------------------------------------------------------------------
bool CNEOBot::IsThrowLineClear(const Vector& where) const
{
return IsThrowLineClear(const_cast<CNEOBot*>(this)->EyePosition(), where);
}


//-----------------------------------------------------------------------------------------------------
// Return whether there is a friendly player blocking the line of fire
bool CNEOBot::IsLineOfFireClearOfFriendlies(const Vector& from, CBaseEntity* who) const
Expand Down
4 changes: 4 additions & 0 deletions src/game/server/neo/bot/neo_bot.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ class CNEOBot : public NextBotPlayer< CNEO_Player >, public CGameEventListener
bool IsLineOfFireClearOfFriendlies(const Vector& from, const Vector& to) const;
void RepathIfFriendlyBlockingLineOfFire();

Vector FindVisibleThrowPointNear( const Vector &vecPos ) const;
bool IsThrowLineClear(const Vector& where) const;
bool IsThrowLineClear(const Vector& from, const Vector& to) const;

bool IsEntityBetweenTargetAndSelf(CBaseEntity* other, CBaseEntity* target); // return true if "other" is positioned inbetween us and "target"

CNEO_Player* GetClosestHumanLookingAtMe(int team = TEAM_ANY); // return the nearest human player on the given team who is looking directly at me
Expand Down