AI Perception Behavior Enhancement: Difference between revisions
Ghost12332 (talk | contribs) mNo edit summary |
No edit summary |
||
(18 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
In | In [[Half-Life 2]], if an idle [[NPC]] hears a sound but doesn't see its emitter, it will only turn in the direction of the sound for a bit before returning to its previous action. | ||
With the modification below the NPC will investigate the source of the sound instead. | With the modification below the NPC will investigate the source of the sound instead. | ||
Open the | Open the '''ai_basenpc_schedule.cpp''' file and look for the function <code>SelectIdleSchedule()</code>. Look for the following code: | ||
<source lang=cpp> | |||
if ( HasCondition( COND_HEAR_DANGER ) || | |||
HasCondition( COND_HEAR_PLAYER ) || | |||
HasCondition( COND_HEAR_WORLD ) || | |||
HasCondition( COND_HEAR_BULLET_IMPACT ) || | |||
HasCondition( COND_HEAR_COMBAT ) ) | |||
{ | |||
return SCHED_ALERT_FACE_BESTSOUND; | |||
} | |||
</source> | |||
Replace this code with: | |||
<source lang=cpp> | |||
if ( HasCondition ( COND_HEAR_WORLD ) || | |||
HasCondition ( COND_HEAR_PLAYER ) ) | |||
{ | |||
return SCHED_ALERT_FACE_BESTSOUND; | |||
} | |||
</source> | |||
Look for the function <code>SelectAlertSchedule()</code>. Look for the following code: | |||
<source lang=cpp> | |||
if ( HasCondition( COND_HEAR_DANGER ) || | |||
HasCondition( COND_HEAR_PLAYER ) || | |||
HasCondition( COND_HEAR_WORLD ) || | |||
HasCondition( COND_HEAR_BULLET_IMPACT ) || | |||
HasCondition( COND_HEAR_COMBAT ) ) | |||
{ | |||
return SCHED_ALERT_FACE_BESTSOUND; | |||
} | |||
</source> | |||
Replace this code with: | |||
<source lang=cpp> | |||
if ( HasCondition ( COND_HEAR_BULLET_IMPACT ) || | |||
HasCondition ( COND_HEAR_DANGER ) || | |||
HasCondition ( COND_HEAR_COMBAT ) ) | |||
{ | |||
return SCHED_INVESTIGATE_SOUND ; | |||
} | |||
</source> | |||
Open the '''ai_default.cpp''' file and look for the schedule <code>SCHED_ALERT_FACE_BESTSOUND</code>. Look for the following code: | |||
<source lang=cpp> | |||
AI_DEFINE_SCHEDULE | |||
( | |||
SCHED_ALERT_FACE_BESTSOUND, | |||
" Tasks" | |||
" TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_FACE_SAVEPOSITION 0" | |||
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" | |||
" TASK_WAIT 1.5" | |||
" TASK_FACE_REASONABLE 0" | |||
"" | |||
" Interrupts" | |||
" COND_NEW_ENEMY" | |||
" COND_SEE_FEAR" | |||
" COND_LIGHT_DAMAGE" | |||
" COND_HEAVY_DAMAGE" | |||
" COND_PROVOKED" | |||
); | |||
</source> | |||
Replace this code with: | Replace this code with: | ||
<source lang=cpp> | |||
AI_DEFINE_SCHEDULE | |||
( | |||
SCHED_ALERT_FACE_BESTSOUND, | |||
" Tasks" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_STORE_LASTPOSITION 0" | |||
// " TASK_SET_TOLERANCE_DISTANCE 32" | |||
" TASK_GET_PATH_TO_BESTSOUND 0" | |||
" TASK_FACE_IDEAL 0" | |||
" TASK_RUN_PATH 0" | |||
" TASK_WAIT_FOR_MOVEMENT 0" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_WAIT 5" | |||
" TASK_GET_PATH_TO_LASTPOSITION 0" | |||
" TASK_WALK_PATH 0" | |||
" TASK_WAIT_FOR_MOVEMENT 0" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_CLEAR_LASTPOSITION 0" | |||
" TASK_FACE_REASONABLE 0" | |||
"" | |||
" Interrupts" | |||
" COND_NEW_ENEMY" | |||
" COND_SEE_FEAR" | |||
" COND_LIGHT_DAMAGE" | |||
" COND_HEAVY_DAMAGE" | |||
" COND_PROVOKED" | |||
" COND_HEAR_BULLET_IMPACT" | |||
" COND_HEAR_DANGER" | |||
" COND_HEAR_COMBAT" | |||
); | |||
</source> | |||
Look for the schedule <code>SCHED_INVESTIGATE_SOUND</code>. Look for the following code: | |||
<source lang=cpp> | |||
AI_DEFINE_SCHEDULE | |||
( | |||
SCHED_INVESTIGATE_SOUND, | |||
" Tasks" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_STORE_LASTPOSITION 0" | |||
// " TASK_SET_TOLERANCE_DISTANCE 32" | |||
" TASK_GET_PATH_TO_BESTSOUND 0" | |||
" TASK_FACE_IDEAL 0" | |||
" TASK_RUN_PATH 0" | |||
" TASK_WAIT_FOR_MOVEMENT 0" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_WAIT 5" | |||
" TASK_GET_PATH_TO_LASTPOSITION 0" | |||
" TASK_WALK_PATH 0" | |||
" TASK_WAIT_FOR_MOVEMENT 0" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_CLEAR_LASTPOSITION 0" | |||
" TASK_FACE_REASONABLE 0" | |||
"" | |||
" Interrupts" | |||
" COND_NEW_ENEMY" | |||
" COND_SEE_FEAR" | |||
" COND_SEE_ENEMY" | |||
" COND_LIGHT_DAMAGE" | |||
" COND_HEAVY_DAMAGE" | |||
" COND_HEAR_DANGER" | |||
); | |||
</source> | |||
Replace this code with: | |||
<source lang=cpp> | |||
AI_DEFINE_SCHEDULE | |||
( | |||
SCHED_INVESTIGATE_SOUND, | |||
" Tasks" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_STORE_LASTPOSITION 0" | |||
" TASK_GET_PATH_TO_BESTSOUND 0" | |||
" TASK_FACE_IDEAL 0" | |||
" TASK_RUN_PATH 0" | |||
" TASK_WAIT_FOR_MOVEMENT 0" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_WAIT 1.25" | |||
" TASK_SET_ROUTE_SEARCH_TIME 1" // Spend 1 seconds trying to build a path if stuck | |||
" TASK_GET_PATH_TO_RANDOM_NODE 500" | |||
" TASK_RUN_PATH 0" | |||
" TASK_WAIT_FOR_MOVEMENT 0" | |||
" TASK_WAIT 2.5" | |||
" TASK_GET_PATH_TO_LASTPOSITION 0" | |||
" TASK_WALK_PATH 0" | |||
" TASK_WAIT_FOR_MOVEMENT 0" | |||
" TASK_STOP_MOVING 0" | |||
" TASK_CLEAR_LASTPOSITION 0" | |||
" TASK_FACE_REASONABLE 0" | |||
"" | |||
" Interrupts" | |||
" COND_NEW_ENEMY" | |||
" COND_SEE_FEAR" | |||
" COND_SEE_ENEMY" | |||
" COND_LIGHT_DAMAGE" | |||
" COND_HEAVY_DAMAGE" | |||
" COND_HEAR_DANGER" | |||
" COND_HEAR_COMBAT" | |||
" COND_HEAR_PLAYER" | |||
); | |||
</source> | |||
Alternatively you could just replace these lines in the file '''ai_basenpc_schedule.cpp''' (this code will only have the AI walk to the source of the sound and have them walk back without looking for the player or the source of the sound afterwards). | |||
Open the '''ai_basenpc_schedule.cpp''' file and look for the function <code>SelectIdleSchedule()</code>. Look for the following code: | |||
<source lang=cpp> | |||
if ( HasCondition( COND_HEAR_DANGER ) || | |||
HasCondition( COND_HEAR_PLAYER ) || | |||
HasCondition( COND_HEAR_WORLD ) || | |||
HasCondition( COND_HEAR_BULLET_IMPACT ) || | |||
HasCondition( COND_HEAR_COMBAT ) ) | |||
{ | |||
return SCHED_ALERT_FACE_BESTSOUND; | |||
} | |||
</source> | |||
Replace this code with: | |||
<source lang=cpp> | |||
if ( HasCondition( COND_HEAR_DANGER ) || | |||
HasCondition( COND_HEAR_PLAYER ) || | |||
HasCondition( COND_HEAR_WORLD ) || | |||
HasCondition( COND_HEAR_BULLET_IMPACT ) || | |||
HasCondition( COND_HEAR_COMBAT ) ) | |||
{ | |||
return SCHED_INVESTIGATE_SOUND; | |||
} | |||
</source> | |||
==Conclusion== | ==Conclusion== | ||
With this code, | With this code, NPC will hear sounds and react to them according to their loudness and intensity | ||
{{Warning|This code does not have the changes required to allow AI to hear sounds from prop_physics.}} | |||
{{Warning|This code (the one with changes to "ai_basenpc_schedule.cpp" and to "ai_default.cpp") will break animations when multiple gunshots occur ! Use the simpler implementation (the one without changes to "ai_default.cpp") if your mod will have loud gun battles.}} | |||
[[Category:AI Programming]] | [[Category:AI Programming]] |
Latest revision as of 02:43, 16 December 2021
In Half-Life 2, if an idle NPC hears a sound but doesn't see its emitter, it will only turn in the direction of the sound for a bit before returning to its previous action.
With the modification below the NPC will investigate the source of the sound instead.
Open the ai_basenpc_schedule.cpp file and look for the function SelectIdleSchedule()
. Look for the following code:
if ( HasCondition( COND_HEAR_DANGER ) ||
HasCondition( COND_HEAR_PLAYER ) ||
HasCondition( COND_HEAR_WORLD ) ||
HasCondition( COND_HEAR_BULLET_IMPACT ) ||
HasCondition( COND_HEAR_COMBAT ) )
{
return SCHED_ALERT_FACE_BESTSOUND;
}
Replace this code with:
if ( HasCondition ( COND_HEAR_WORLD ) ||
HasCondition ( COND_HEAR_PLAYER ) )
{
return SCHED_ALERT_FACE_BESTSOUND;
}
Look for the function SelectAlertSchedule()
. Look for the following code:
if ( HasCondition( COND_HEAR_DANGER ) ||
HasCondition( COND_HEAR_PLAYER ) ||
HasCondition( COND_HEAR_WORLD ) ||
HasCondition( COND_HEAR_BULLET_IMPACT ) ||
HasCondition( COND_HEAR_COMBAT ) )
{
return SCHED_ALERT_FACE_BESTSOUND;
}
Replace this code with:
if ( HasCondition ( COND_HEAR_BULLET_IMPACT ) ||
HasCondition ( COND_HEAR_DANGER ) ||
HasCondition ( COND_HEAR_COMBAT ) )
{
return SCHED_INVESTIGATE_SOUND ;
}
Open the ai_default.cpp file and look for the schedule SCHED_ALERT_FACE_BESTSOUND
. Look for the following code:
AI_DEFINE_SCHEDULE
(
SCHED_ALERT_FACE_BESTSOUND,
" Tasks"
" TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0"
" TASK_STOP_MOVING 0"
" TASK_FACE_SAVEPOSITION 0"
" TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
" TASK_WAIT 1.5"
" TASK_FACE_REASONABLE 0"
""
" Interrupts"
" COND_NEW_ENEMY"
" COND_SEE_FEAR"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_PROVOKED"
);
Replace this code with:
AI_DEFINE_SCHEDULE
(
SCHED_ALERT_FACE_BESTSOUND,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_STORE_LASTPOSITION 0"
// " TASK_SET_TOLERANCE_DISTANCE 32"
" TASK_GET_PATH_TO_BESTSOUND 0"
" TASK_FACE_IDEAL 0"
" TASK_RUN_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_STOP_MOVING 0"
" TASK_WAIT 5"
" TASK_GET_PATH_TO_LASTPOSITION 0"
" TASK_WALK_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_STOP_MOVING 0"
" TASK_CLEAR_LASTPOSITION 0"
" TASK_FACE_REASONABLE 0"
""
" Interrupts"
" COND_NEW_ENEMY"
" COND_SEE_FEAR"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_PROVOKED"
" COND_HEAR_BULLET_IMPACT"
" COND_HEAR_DANGER"
" COND_HEAR_COMBAT"
);
Look for the schedule SCHED_INVESTIGATE_SOUND
. Look for the following code:
AI_DEFINE_SCHEDULE
(
SCHED_INVESTIGATE_SOUND,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_STORE_LASTPOSITION 0"
// " TASK_SET_TOLERANCE_DISTANCE 32"
" TASK_GET_PATH_TO_BESTSOUND 0"
" TASK_FACE_IDEAL 0"
" TASK_RUN_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_STOP_MOVING 0"
" TASK_WAIT 5"
" TASK_GET_PATH_TO_LASTPOSITION 0"
" TASK_WALK_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_STOP_MOVING 0"
" TASK_CLEAR_LASTPOSITION 0"
" TASK_FACE_REASONABLE 0"
""
" Interrupts"
" COND_NEW_ENEMY"
" COND_SEE_FEAR"
" COND_SEE_ENEMY"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_HEAR_DANGER"
);
Replace this code with:
AI_DEFINE_SCHEDULE
(
SCHED_INVESTIGATE_SOUND,
" Tasks"
" TASK_STOP_MOVING 0"
" TASK_STORE_LASTPOSITION 0"
" TASK_GET_PATH_TO_BESTSOUND 0"
" TASK_FACE_IDEAL 0"
" TASK_RUN_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_STOP_MOVING 0"
" TASK_WAIT 1.25"
" TASK_SET_ROUTE_SEARCH_TIME 1" // Spend 1 seconds trying to build a path if stuck
" TASK_GET_PATH_TO_RANDOM_NODE 500"
" TASK_RUN_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_WAIT 2.5"
" TASK_GET_PATH_TO_LASTPOSITION 0"
" TASK_WALK_PATH 0"
" TASK_WAIT_FOR_MOVEMENT 0"
" TASK_STOP_MOVING 0"
" TASK_CLEAR_LASTPOSITION 0"
" TASK_FACE_REASONABLE 0"
""
" Interrupts"
" COND_NEW_ENEMY"
" COND_SEE_FEAR"
" COND_SEE_ENEMY"
" COND_LIGHT_DAMAGE"
" COND_HEAVY_DAMAGE"
" COND_HEAR_DANGER"
" COND_HEAR_COMBAT"
" COND_HEAR_PLAYER"
);
Alternatively you could just replace these lines in the file ai_basenpc_schedule.cpp (this code will only have the AI walk to the source of the sound and have them walk back without looking for the player or the source of the sound afterwards).
Open the ai_basenpc_schedule.cpp file and look for the function SelectIdleSchedule()
. Look for the following code:
if ( HasCondition( COND_HEAR_DANGER ) ||
HasCondition( COND_HEAR_PLAYER ) ||
HasCondition( COND_HEAR_WORLD ) ||
HasCondition( COND_HEAR_BULLET_IMPACT ) ||
HasCondition( COND_HEAR_COMBAT ) )
{
return SCHED_ALERT_FACE_BESTSOUND;
}
Replace this code with:
if ( HasCondition( COND_HEAR_DANGER ) ||
HasCondition( COND_HEAR_PLAYER ) ||
HasCondition( COND_HEAR_WORLD ) ||
HasCondition( COND_HEAR_BULLET_IMPACT ) ||
HasCondition( COND_HEAR_COMBAT ) )
{
return SCHED_INVESTIGATE_SOUND;
}
Conclusion
With this code, NPC will hear sounds and react to them according to their loudness and intensity

