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
2 changes: 2 additions & 0 deletions src/game/client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1623,6 +1623,8 @@ target_sources_grouped(
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_ghost_cap_point.h
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_juggernaut.cpp
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_juggernaut.h
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_penetration_resistance.cpp
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_penetration_resistance.h
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_shared.cpp
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_shared.h
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_spawnpoint.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/game/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,8 @@ target_sources_grouped(
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_ghost_cap_point.h
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_juggernaut.cpp
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_juggernaut.h
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_penetration_resistance.cpp
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_penetration_resistance.h
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_shared.cpp
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_shared.h
${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_spawnpoint.cpp
Expand Down
3 changes: 1 addition & 2 deletions src/game/server/neo/bot/behavior/neo_bot_attack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ ActionResult< CNEOBot > CNEOBotAttack::OnStart( CNEOBot *me, Action< CNEOBot > *
ActionResult< CNEOBot > CNEOBotAttack::Update( CNEOBot *me, float interval )
{
const CKnownEntity *threat = me->GetVisionInterface()->GetPrimaryKnownThreat();
me->EquipBestWeaponForThreat( threat );

if ( threat == NULL || threat->IsObsolete() || !me->GetIntentionInterface()->ShouldAttack( me, threat ) )
{
Expand Down Expand Up @@ -65,7 +64,7 @@ ActionResult< CNEOBot > CNEOBotAttack::Update( CNEOBot *me, float interval )
if ( bAggressive ||
!threat->IsVisibleRecently() ||
me->IsRangeGreaterThan( threat->GetEntity()->GetAbsOrigin(), me->GetDesiredAttackRange() ) ||
!me->IsLineOfFireClear( threat->GetEntity()->EyePosition() ) )
!me->IsLineOfFireClear( threat->GetEntity()->EyePosition(), CNEOBot::LINE_OF_FIRE_FLAGS_DEFAULT ) )
{
// SUPA7 reload can be interrupted so proactively reload
if (myWeapon && (myWeapon->GetNeoWepBits() & NEO_WEP_SUPA7) && (myWeapon->Clip1() < myWeapon->GetMaxClip1()))
Expand Down
79 changes: 71 additions & 8 deletions src/game/server/neo/bot/behavior/neo_bot_behavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ bool CNEOBotMainAction::IsImmediateThreat( const CBaseCombatCharacter *subject,
return false;

// if they can't hurt me, they aren't an immediate threat
if ( !me->IsLineOfFireClear( threat->GetEntity() ) )
if ( !me->IsLineOfFireClear( threat->GetEntity(), CNEOBot::LINE_OF_FIRE_FLAGS_DEFAULT ) )
return false;

Vector to = me->GetAbsOrigin() - threat->GetLastKnownPosition();
Expand Down Expand Up @@ -587,13 +587,66 @@ void CNEOBotMainAction::FireWeaponAtEnemy( CNEOBot *me )
if ( threat == NULL || !threat->GetEntity() || !threat->IsVisibleRecently() )
return;

// don't shoot through windows/etc
if ( !me->IsLineOfFireClear( threat->GetEntity()->EyePosition() ) )
CNEOBot::LineOfFireFlags lofFlags = CNEOBot::LINE_OF_FIRE_FLAGS_DEFAULT;
auto *neoThreat = ToNEOPlayer(threat->GetEntity());

// Only hard + expert bots will attempt to wallbang at ghoster
const bool bThreatIsGhoster = neoThreat && neoThreat->IsCarryingGhost();
if (bThreatIsGhoster && me->GetDifficulty() >= CNEOBot::HARD)
{
lofFlags |= CNEOBot::LINE_OF_FIRE_FLAGS_PENETRATION;
}

// don't shoot through non-shootables, check if shootable by any non-shotguns weapons
Vector vShootablePos = threat->GetEntity()->EyePosition();
if ( !me->IsLineOfFireClear( vShootablePos, lofFlags ) )
{
if ( !me->IsLineOfFireClear( threat->GetEntity()->WorldSpaceCenter() ) )
vShootablePos = threat->GetEntity()->WorldSpaceCenter();
if ( !me->IsLineOfFireClear( vShootablePos, lofFlags ) )
{
if ( !me->IsLineOfFireClear( threat->GetEntity()->GetAbsOrigin() ) )
vShootablePos = threat->GetEntity()->GetAbsOrigin();
if ( !me->IsLineOfFireClear( vShootablePos, lofFlags ) )
{
return;
}
}
}

// Check again if shotgun from last "any" shootable pos
bool bNotPrimary = false;
bool bShotgunSituationHandled = false;
// If holding non-primary, have shotgun in primary, and sight clear for shotgun, try to switch to shotgun
// Otherwise if holding shotgun and sight not clear for shotgun, try to switch to secondary
if (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->GetNeoWepBits() & (NEO_WEP_AA13 | NEO_WEP_SUPA7)))
{
const bool bClearForShotgun = me->IsLineOfFireClear(vShootablePos, CNEOBot::LINE_OF_FIRE_FLAGS_SHOTGUN);
if (bClearForShotgun)
{
bNotPrimary = false;
me->EquipBestWeaponForThreat(threat, bNotPrimary);
myWeapon = static_cast<CNEOBaseCombatWeapon *>(me->GetActiveWeapon());
}
bShotgunSituationHandled = true;
}
}
else if (myWeapon && (myWeapon->GetNeoWepBits() & (NEO_WEP_AA13 | NEO_WEP_SUPA7)))
{
const bool bClearForShotgun = me->IsLineOfFireClear(vShootablePos, CNEOBot::LINE_OF_FIRE_FLAGS_SHOTGUN);
if (!bClearForShotgun)
{
// Try to switch over to non-shotgun weapon
bNotPrimary = true;
me->EquipBestWeaponForThreat(threat, bNotPrimary);
myWeapon = static_cast<CNEOBaseCombatWeapon *>(me->GetActiveWeapon());
// If it's still Supa7, then it should try to dodge the threat instead
if (myWeapon && (myWeapon->GetNeoWepBits() & (NEO_WEP_AA13 | NEO_WEP_SUPA7)))
{
return;
}
bShotgunSituationHandled = true;
}
}

Expand All @@ -609,6 +662,11 @@ void CNEOBotMainAction::FireWeaponAtEnemy( CNEOBot *me )
return;
}

if (!bShotgunSituationHandled)
{
me->EquipBestWeaponForThreat(threat, false);
}

float threatRange = ( threat->GetEntity()->GetAbsOrigin() - me->GetAbsOrigin() ).Length();

// actual head aiming is handled elsewhere, just check if we're on target
Expand All @@ -622,6 +680,12 @@ void CNEOBotMainAction::FireWeaponAtEnemy( CNEOBot *me )

if (bOnTarget)
{
if (bThreatIsGhoster)
{
me->GetBodyInterface()->AimHeadTowards(vShootablePos, IBody::CRITICAL, 1.0f, nullptr,
"Aiming at a visible ghoster threat");
}

if ( me->IsCombatWeapon( myWeapon ) )
{
if (myWeapon->m_iClip1 <= 0)
Expand All @@ -635,7 +699,7 @@ void CNEOBotMainAction::FireWeaponAtEnemy( CNEOBot *me )
else if (IsImmediateThreat(me->GetEntity(), threat) && !m_isWaitingForFullReload)
{
// intention is to swap to secondary if available
me->EquipBestWeaponForThreat(threat);
me->EquipBestWeaponForThreat(threat, bNotPrimary);
}
else
{
Expand Down Expand Up @@ -698,7 +762,6 @@ void CNEOBotMainAction::FireWeaponAtEnemy( CNEOBot *me )
}
}
}

}
}

Expand Down Expand Up @@ -748,7 +811,7 @@ void CNEOBotMainAction::Dodge( CNEOBot *me )
const CKnownEntity *threat = me->GetVisionInterface()->GetPrimaryKnownThreat();
if ( threat && threat->IsVisibleRecently() )
{
bool isShotClear = me->IsLineOfFireClear( threat->GetLastKnownPosition() );
bool isShotClear = me->IsLineOfFireClear( threat->GetLastKnownPosition(), CNEOBot::LINE_OF_FIRE_FLAGS_DEFAULT );

// don't dodge if they can't hit us
if ( !isShotClear )
Expand Down
13 changes: 10 additions & 3 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 @@ -65,10 +65,17 @@ ActionResult< CNEOBot > CNEOBotSeekAndDestroy::Update( CNEOBot *me, float interv

if ( threat )
{
const float engageRange = 1000.0f;
if ( me->IsRangeLessThan( threat->GetLastKnownPosition(), engageRange ) )
const auto *neoThreat = ToNEOPlayer(threat->GetEntity());
// This will just go to the ghoster RecomputeSeekPath logics instead of
// only going after it
const bool bDontSuspendForGhoster = (neoThreat && neoThreat->IsCarryingGhost());
if (!bDontSuspendForGhoster)
{
return SuspendFor( new CNEOBotAttack, "Going after an enemy" );
const float engageRange = 1000.0f;
if ( me->IsRangeLessThan( threat->GetLastKnownPosition(), engageRange ) )
{
return SuspendFor( new CNEOBotAttack, "Going after an enemy" );
}
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ ActionResult< CNEOBot > CNEOBotTacticalMonitor::Update( CNEOBot *me, float inter
}
}

const CKnownEntity* threat = me->GetVisionInterface()->GetPrimaryKnownThreat();
me->EquipBestWeaponForThreat( threat );
const CKnownEntity *threat = me->GetVisionInterface()->GetPrimaryKnownThreat();

// check if we need to get to cover
QueryResultType shouldRetreat = me->GetIntentionInterface()->ShouldRetreat( me );
Expand Down
Loading
Loading