AI State
An AI's Mind is in a certain State all the time. It's the State class which does the actual thinking each frame, it pushes the Tasks to the Subsystems, it interprets the incoming stimuli, it decides which States the Mind will be switch to.
Note: States are the only instances which are allowed to actually switch the Mind's State (Tasks are not allowed to do it, nor is the Mind or the AI class itself allowed to).
There are a few so-called Backbone States, corresponding to the AI's alert indices:
- Alert Index 0: IdleState
- Alert Index 1: SuspiciousState
- Alert Index 2: SearchingState
- Alert Index 3: AgitatedSearchingState
- Alert Index 4: CombatState
The Backbone States form some kind of "ladder" and follow this pattern:
- When the AI's alert level exceeds a given threshold (e.g. from thres_3 to thresh_combat), the Backbone State switches to the next higher State (e.g. from AgitatedSearchingState to CombatState). This happens via a PushState command, so that the AgitatedSearchingState still stays within the Mind's StateQueue.
- When the AI's alert level falls below the threshold for the current State, it is terminated via an EndState call.
These two rules ensure that the Mind is always in the correct State according to the AI's alert index.
Example: Let's assume the AI is in SearchingState and encounters the player (visually). The alert index is increased immediately above thresh_combat which causes the SearchingState (in its role as Backbone State) to Push the next higher State (in this case this is AgitatedSearchingState). The AgitatedSearchingState peforms another check and as the alertlevel is higher than thresh_combat it passes the torch and pushes the CombatState into the StateQueue. Let's further assume that the player manages to escape and the AI's alert level is slowly decreasing again. As soon as it falls below thresh_combat, the CombatState recognises itself not being appropriate anymore and calls EndState(). This lets the Mind fall back into the AgitatedSearchingState (which is still in the Mind's StateQueue). A further decrease of the Alert Level causes the AgitatedSearchingState to end itself and to fall back to SearchingState. This goes on until the bottom of the StateQueue is reached, which is always occupied by the IdleState.
The important part is that the Backbone States always use PushState to go upwards and EndState to go downwards.
It's of course not a problem, if the CombatState decides to some other State like FleeState or LostTrackOfEnemyState, as long as the BackBone stays intact. It's ok for the CombatState to use either SwitchState, PushState to jump to (say) FleeState. The important thing is that the FleeState must not directly push another Backbone State (like IdleState), as this would disrupt the StateQueue. If the FleeState wants to go back into IdleState, it's enough to set the AI alert level and call EndState. The BackBone States will take care of switching by subsequently calling EndState until the corresponding State is reached.
Things to remember:
- Only States are allowed to switch States
- Only Backbone States are allowed to switch to one of the five Backbone States (via PushState/EndState).
- The Backbone States always take care that the right State is selected when the Alert Index is changing.
- States are responsible for handling the incoming stimuli and pushing the right Tasks into their Subsystems.
Implementation Notes
A State must...
- ...have a unique name string identifier (depicted in the header, e.g. STATE_COMBAT).
- ...implement the abstract State interface
- ...provide a static CreateInstance() method.
- ...register itself with the StateLibrary using a StateRegistrar helper class.
- ...define a default constructor without arguments
- ...be save-able and restore-able via the Save/Restore methods it has to implement (no reference/raw pointer members, etc., see Saving and Loading)
Optional: A State can...
- ...implement the method OnSubsystemTaskFinished to get notified about finished Subsystem Tasks.
- ...override one of the various OnVisualStimX() methods to implement behaviour different to the default.
- ...override the OnAICommMessage() to handle the incoming messages differently than the base class.