-
Notifications
You must be signed in to change notification settings - Fork 140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NPC memory fixes and NPC VScript expansions #337
NPC memory fixes and NPC VScript expansions #337
Conversation
6db2932
to
290d9fb
Compare
290d9fb
to
85cc7f2
Compare
85cc7f2
to
970887d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few comments of things I wanted to get clarification on. I couldn't find any issues that I can tell.
@@ -740,6 +744,25 @@ void CAI_Squad::UpdateEnemyMemory( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy, c | |||
|
|||
//------------------------------------------------------------------------------ | |||
|
|||
#ifdef MAPBASE | |||
void CAI_Squad::MarkEnemyAsEluded( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is gated by a convar, there isn't really any concern about it affecting normal gameplay. But I have to wonder what happens if one NPC in a squad can't see the enemy and another can. Isn't it possible an NPC could be marked as eluded while still being visible by another squad member?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's visible to another squad member, then the squad member will broadcast that to others in the squad and update the enemy's last known position. The eluded code only runs when the NPC is at the enemy's last known position and the enemy is nowhere to be found. I'm reasonably certain those two situations can't happen at once
void ScriptSetSquadData( int iSlot, const char *data ); | ||
const char *ScriptGetSquadData( int iSlot ); | ||
void ScriptSetSquadData( int iSlot, int data ); | ||
int ScriptGetSquadData( int iSlot ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the intended purpose of this return type being changed from char* to int?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was one of the points in the PR description:
The VScript functions for squad data now use integers instead of strings, as even though squad data supposedly accepts any parameter, only integers are capable of save/restore. Since these functions were very obscure (and only partially functional), this is unlikely to break existing scripts.
// With this change, these NPCs will establish LOS according to enemy memory instead of where the enemy | ||
// actually is. This may make the NPCs more consistent and fair, but their AI and levels built around it | ||
// may have been designed around this bug, so this is currently being tied to a cvar. | ||
Vector vecEnemy = ( task != TASK_GET_PATH_TO_ENEMY_LKP_LOS || !ai_enemy_memory_fixes.GetBool() ) ? GetEnemy()->GetAbsOrigin() : GetEnemyLKP(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to reread the comment a couple of times before I understood this. Just to be absolutely clear: There is no chance that TASK_GET_PATH_TO_ENEMY_LKP could use this code? Is it worth preserving the original case just to be sure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is within a switch statement case that is used by TASK_GET_PATH_TO_ENEMY_LOS
, TASK_GET_FLANK_RADIUS_PATH_TO_ENEMY_LOS
, TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS
, and TASK_GET_PATH_TO_ENEMY_LKP_LOS
. The case for TASK_GET_PATH_TO_ENEMY_LKP
is farther above and does not fall back into this code.
if (i == m_SensedObjects.InvalidIndex()) | ||
return; | ||
|
||
pEntity->RemoveFlag( FL_OBJECT ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does removing this flag from the entity do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It prevents the entity from being sensed anymore. FL_OBJECT
's purpose is to mark non-player, non-NPC entities that should be seen by NPC senses.
beeb68a
to
01ad958
Compare
I've discovered that these changes caused a regression in Combine soldiers and striders. I'm going to explain exactly what went wrong, but tl;dr, I had to add two new cases in The issue with Combine soldiers
While This PR fixed the issue with that task, so now I added a new case for soldiers to use Other NPCsAfter identifying and fixing the issue with Combine soldiers, I searched for every other case of After testing both
To fix this, I added a similar case where striders would use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After looking through the PR and talking about it yesterday, I think it looks good to me.
This pull request contains several fixes or enhancements for NPC enemy memory as well as a large number of new VScript hooks and functions variously related to enemy memory, sensing, and general scheduling.
There are a lot of closely related changes in this pull request which are difficult to clearly separate, but these are the highlights that can be itemized:
CAI_BaseNPC
for sensing, NPC memory, and general task/schedule behavior.GetTaskID
VScript function not returning correctly scoped ID (ai_basenpc.cpp:944
)MarkEnemyAsEluded
can now broadcast to the entire squad ifai_squad_broadcast_elusion
is set to 1.TASK_GET_PATH_TO_ENEMY_LKP_LOS
now correctly uses the enemy's last known position. An oversight in the code previously caused it to use the enemy's actual position instead, making NPCs who use the task accidentally cheat. This fix can be disabled withai_enemy_memory_fixes
if the fixed behavior is undesirable.SensedObjectsManager
VScript singleton gives the ability to add unique objects (e.g. physics props) to the sensed object list, allowing NPCs to see them in the same way they would see players and other NPCs.New VScript functions on(addendum: this requires E:Z2 code and it wasn't as related as the other changes anyway, so I will include it in a separate PR)CBaseCombatCharacter
for glow effects.OnTakeDamage
,ModifyOrAppendCriteria
, andCanBeSeenBy
VScript hooks forCBaseEntity
. Also exposedRemoveContext
, which was oddly missing.FireBullets
VScript hook using incorrect parameters.FreeSound
VScript function forCSoundEnt
.These changes were all made for the development of Progenitors, a currently unreleased mod with an emphasis on stealth mechanics that run almost entirely on VScript, although I was planning on committing these upstream from the start.
Due to the volume of changes and some uncertainty regarding save/restore compatibility, I would wait until v8.0 before merging this.
PR Checklist
develop
branch OR targets another branch with a specific goal in mind