Fix ai_enemy_memory_fixes issues in npc_combine_s and npc_strider

This commit is contained in:
ALLEN-PC\acj30 2025-01-11 22:35:21 -06:00
parent 970887d706
commit 01ad9584c7
5 changed files with 41 additions and 1 deletions

View File

@ -46,7 +46,7 @@ extern ConVar ai_use_think_optimizations;
ConVar ai_simulate_task_overtime( "ai_simulate_task_overtime", "0" ); ConVar ai_simulate_task_overtime( "ai_simulate_task_overtime", "0" );
#ifdef MAPBASE #ifdef MAPBASE
ConVar ai_enemy_memory_fixes( "ai_enemy_memory_fixes", "1", FCVAR_NONE, "Toggles Mapbase fixes for certain NPC AI not using enemy memory when it should." ); ConVar ai_enemy_memory_fixes( "ai_enemy_memory_fixes", "0", FCVAR_NONE, "Toggles Mapbase fixes for certain NPC AI not using enemy memory when it should." );
#endif #endif
#define MAX_TASKS_RUN 10 #define MAX_TASKS_RUN 10

View File

@ -2551,6 +2551,24 @@ int CNPC_Combine::TranslateSchedule( int scheduleType )
} }
} }
#ifdef MAPBASE
extern ConVar ai_enemy_memory_fixes;
// SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE uses TASK_GET_PATH_TO_ENEMY_LKP_LOS, a task with a mistake
// detailed in CAI_BaseNPC::StartTask and fixed by ai_enemy_memory_fixes.
//
// However, SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE only stops being used once the NPC has LOS to its target.
// Since the fixed task now uses the enemy's last known position instead of the enemy's actual position,
// this schedule risks getting stuck in a loop.
//
// This code makes the soldier run up directly to the last known position if it's visible, allowing the AI
// to mark the enemy as eluded.
if ( ai_enemy_memory_fixes.GetBool() && FVisible( GetEnemyLKP() ) )
{
return SCHED_COMBINE_PRESS_ATTACK;
}
#endif
return SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE; return SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE;
} }
break; break;

View File

@ -69,6 +69,7 @@ public:
int RangeAttack2Conditions( float flDot, float flDist ); // For innate grenade attack int RangeAttack2Conditions( float flDot, float flDist ); // For innate grenade attack
int MeleeAttack1Conditions( float flDot, float flDist ); // For kick/punch int MeleeAttack1Conditions( float flDot, float flDist ); // For kick/punch
bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ) { return BaseClass::FVisible( vecTarget, traceMask, ppBlocker ); }
virtual bool IsCurTaskContinuousMove(); virtual bool IsCurTaskContinuousMove();
virtual float GetJumpGravity() const { return 1.8f; } virtual float GetJumpGravity() const { return 1.8f; }

View File

@ -1511,6 +1511,26 @@ int CNPC_Strider::TranslateSchedule( int scheduleType )
return SCHED_COMBAT_PATROL; return SCHED_COMBAT_PATROL;
} }
} }
else
{
#ifdef MAPBASE
extern ConVar ai_enemy_memory_fixes;
// Striders convert TASK_GET_PATH_TO_ENEMY_LOS to TASK_GET_PATH_TO_ENEMY_LKP_LOS, a task which incorrectly
// acts identically to the former. This is detailed in CAI_BaseNPC::StartTask and fixed by ai_enemy_memory_fixes.
//
// However, SCHED_ESTABLISH_LINE_OF_FIRE only stops being used once the NPC has LOS to its target.
// Since the fixed task now uses the enemy's last known position instead of the enemy's actual position,
// this schedule risks getting stuck in a loop.
//
// This code chains back up to SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK, which is what's supposed to happen when a
// strider is eluded in this way.
if ( ai_enemy_memory_fixes.GetBool() && FVisible( GetEnemyLKP() ) )
{
return TranslateSchedule( SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK );
}
#endif
}
break; break;

View File

@ -188,6 +188,7 @@ public:
bool HasPass() { return m_PlayerFreePass.HasPass(); } bool HasPass() { return m_PlayerFreePass.HasPass(); }
bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ) { return BaseClass::FVisible( vecTarget, traceMask, ppBlocker ); }
Vector BodyTarget( const Vector &posSrc, bool bNoisy ); Vector BodyTarget( const Vector &posSrc, bool bNoisy );
bool IsValidEnemy( CBaseEntity *pTarget ); bool IsValidEnemy( CBaseEntity *pTarget );