Skip to content
Merged
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
73 changes: 72 additions & 1 deletion src/game/server/neo/bot/behavior/neo_bot_behavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ConVar neo_bot_sniper_aim_error( "neo_bot_sniper_aim_error", "0.01", FCVAR_CHEAT
ConVar neo_bot_sniper_aim_steady_rate( "neo_bot_sniper_aim_steady_rate", "10", FCVAR_CHEAT );
ConVar neo_bot_debug_sniper( "neo_bot_debug_sniper", "0", FCVAR_CHEAT );
ConVar neo_bot_fire_weapon_min_time( "neo_bot_fire_weapon_min_time", "1", FCVAR_CHEAT );
ConVar neo_bot_fire_at_breakable_weapon_min_time( "neo_bot_fire_at_breakable_weapon_min_time", "0.4", FCVAR_CHEAT, "Minimum time to fire at breakables", true, 0.0f, true, 60.0f );

ConVar neo_bot_notice_backstab_chance( "neo_bot_notice_backstab_chance", "25", FCVAR_CHEAT );
ConVar neo_bot_notice_backstab_min_range( "neo_bot_notice_backstab_min_range", "100", FCVAR_CHEAT );
Expand Down Expand Up @@ -582,10 +583,80 @@ void CNEOBotMainAction::FireWeaponAtEnemy( CNEOBot *me )

// shoot at bad guys
const CKnownEntity *threat = me->GetVisionInterface()->GetPrimaryKnownThreat();
const bool bIgnoreThreat = (threat == nullptr || !threat->GetEntity() || !threat->IsVisibleRecently());

if (me->GetNeoFlags() & NEO_FL_FREEZETIME)
{
me->GetLocomotionInterface()->m_bBreakBreakableInPath = false;
}

if (me->GetLocomotionInterface()->m_bBreakBreakableInPath)
{
if (me->GetDifficulty() >= CNEOBot::HARD && !m_bPrevBreakBreakableInPath && bIgnoreThreat)
{
auto *secondaryWep = static_cast<CNEOBaseCombatWeapon *>(me->Weapon_GetSlot(1));
if (secondaryWep != myWeapon && secondaryWep &&
((secondaryWep->Clip1() + secondaryWep->m_iPrimaryAmmoCount) > 0))
{
me->Weapon_Switch(secondaryWep);
}
}

if (myWeapon->Clip1() <= 0)
{
me->ReleaseFireButton();
me->PressReloadButton();
m_isWaitingForFullReload = true;
}

if (m_isWaitingForFullReload)
{
m_isWaitingForFullReload = (myWeapon->Clip1() < myWeapon->GetMaxClip1());
}

if (!m_isWaitingForFullReload)
{
if (me->IsContinuousFireWeapon(myWeapon))
{
me->PressFireButton(neo_bot_fire_at_breakable_weapon_min_time.GetFloat());
}
else
{
if (me->m_nButtons & IN_ATTACK)
{
me->ReleaseFireButton();
}
else
{
me->PressFireButton();
}
}
}
m_bPrevBreakBreakableInPath = true;
return;
}

// ignore non-visible threats here so we don't force a premature weapon switch if we're doing something else
if ( threat == NULL || !threat->GetEntity() || !threat->IsVisibleRecently() )
if (bIgnoreThreat)
{
return;
}

// After bIgnoreThreat so it doesn't go at a continous cycle switching weapons
if (!me->GetLocomotionInterface()->m_bBreakBreakableInPath && m_bPrevBreakBreakableInPath)
{
if (me->GetDifficulty() >= CNEOBot::HARD &&
(!myWeapon ||
(myWeapon->GetNeoWepBits() & (NEO_WEP_MILSO | NEO_WEP_TACHI | NEO_WEP_KYLA | NEO_WEP_KNIFE | NEO_WEP_THROWABLE))))
{
auto *primaryWeapon = static_cast<CNEOBaseCombatWeapon *>(me->Weapon_GetSlot(0));
if (primaryWeapon && (primaryWeapon->Clip1() + primaryWeapon->m_iPrimaryAmmoCount) > 0)
{
me->Weapon_Switch(primaryWeapon);
}
}
m_bPrevBreakBreakableInPath = false;
}

CNEOBot::LineOfFireFlags lofFlags = CNEOBot::LINE_OF_FIRE_FLAGS_DEFAULT;
auto *neoThreat = ToNEOPlayer(threat->GetEntity());
Expand Down
1 change: 1 addition & 0 deletions src/game/server/neo/bot/behavior/neo_bot_behavior.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@ class CNEOBotMainAction : public Action< CNEOBot >, public CNEOBotContextualQuer
IntervalTimer m_undergroundTimer;

CountdownTimer m_reevaluateClassTimer;
bool m_bPrevBreakBreakableInPath = false;
};
5 changes: 3 additions & 2 deletions src/game/server/neo/bot/neo_bot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ void CNEOBot::Spawn()
m_didReselectClass = false;
m_isLookingAroundForEnemies = true;
m_attentionFocusEntity = NULL;
GetLocomotionInterface()->m_bBreakBreakableInPath = false;

m_delayedNoticeVector.RemoveAll();

Expand Down Expand Up @@ -1770,7 +1771,7 @@ bool CNEOBot::IsLineOfFireClear(const Vector& from, const Vector& to, const Line
const auto lofMask = LineOfFireMask(flags);
UTIL_TraceLine(from, to, lofMask, &filter, &trace);

const bool bIsClear = !trace.DidHit();
const bool bIsClear = !trace.DidHit() || IsAbleToBreak(trace.m_pEnt);

if (bIsClear && !(lofMask & CONTENTS_WINDOW))
{
Expand Down Expand Up @@ -1846,7 +1847,7 @@ bool CNEOBot::IsLineOfFireClear(const Vector& from, CBaseEntity* who, const Line
const auto lofMask = LineOfFireMask(flags);
UTIL_TraceLine(from, to, lofMask, &filter, &trace);

const bool bIsClear = !trace.DidHit() || trace.m_pEnt == who;
const bool bIsClear = !trace.DidHit() || trace.m_pEnt == who || IsAbleToBreak(trace.m_pEnt);

if (bIsClear && !(lofMask & CONTENTS_WINDOW))
{
Expand Down
11 changes: 10 additions & 1 deletion src/game/server/neo/bot/neo_bot_locomotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ extern ConVar falldamage;
//-----------------------------------------------------------------------------------------
void CNEOBotLocomotion::Update( void )
{
m_bBreakBreakableInPath = false;

CNEOBot* me = ToNEOBot( GetBot()->GetEntity() );
if ( !me || me->GetNeoFlags() & NEO_FL_FREEZETIME)
{
Expand Down Expand Up @@ -103,6 +105,8 @@ bool CNEOBotLocomotion::IsAreaTraversable( const CNavArea* area ) const
//-----------------------------------------------------------------------------------------
bool CNEOBotLocomotion::IsEntityTraversable( CBaseEntity* obstacle, TraverseWhenType when ) const
{
m_bBreakBreakableInPath = false;

// assume all players are "traversable" in that they will move or can be killed
if ( obstacle && obstacle->IsPlayer() )
{
Expand Down Expand Up @@ -132,5 +136,10 @@ bool CNEOBotLocomotion::IsEntityTraversable( CBaseEntity* obstacle, TraverseWhen
}
}

return PlayerLocomotion::IsEntityTraversable( obstacle, when );
const bool bIsTraversable = PlayerLocomotion::IsEntityTraversable( obstacle, when );
if (bIsTraversable)
{
m_bBreakBreakableInPath = GetBot()->IsAbleToBreak(obstacle);
}
return bIsTraversable;
}
2 changes: 2 additions & 0 deletions src/game/server/neo/bot/neo_bot_locomotion.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class CNEOBotLocomotion : public PlayerLocomotion
virtual bool IsAreaTraversable( const CNavArea *baseArea ) const; // return true if given area can be used for navigation
virtual bool IsEntityTraversable( CBaseEntity *obstacle, TraverseWhenType when = EVENTUALLY ) const;

mutable bool m_bBreakBreakableInPath = false;

protected:
virtual void AdjustPosture( const Vector &moveGoal ) { } // never crouch to navigate
};
Expand Down