AI FSM – Arma 2: Operation Arrowhead

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Added some details)
(Added info for danger.fsm)
Line 79: Line 79:
=== danger.fsm ===
=== danger.fsm ===


Seems to be an event hook to make AI react to various danger events.


Right now only few events are used to initiate actions:
==== Cause 0 "ENEMY DETECTED" ====
'''Signal enemy''' via gesture.
==== Cause 8 "CAN FIRE" ====
'''Stop to fire''' makes the unit no longer move to return fire more effectively.
If the threat is dead or after 4 to 8 seconds delay the unit moves on.
==== Next cause ====
The FSM can get multiple events supplied by the engine.
'''Assumption''': The FSM is meant to loop through all of them, yet it seems the looping is broken or disabled intentionally. See the technical details section below for more details.


=== formationC.fsm ===
=== formationC.fsm ===
Line 97: Line 113:
=== comm.fsm ===
=== comm.fsm ===


*Assumption*: Not at all. Seems like a test version and the actual system is integrated into the engine nowadays.
'''Assumption''': Not at all. Seems like a test version and the actual system is integrated into the engine nowadays.


=== danger.fsm ===
=== danger.fsm ===


 
Unknown. Was yet to log an occurrence for non Civilian infantry.


=== formationC.fsm ===
=== formationC.fsm ===
Line 124: Line 140:
=== danger.fsm ===
=== danger.fsm ===


==== Danger causes ====
The FSM contains this description block:
DEFINE_ENUM_BEG(DangerCause)
(0) DCEnemyDetected, // the first enemy detected
(1) DCFire, // fire visible
(2) DCHit, // vehicle hit
(3) DCEnemyNear, // enemy very close to me
(4) DCExplosion, // explosion detected
(5) DCDeadBodyGroup, // dead soldier from my group found
(6) DCDeadBody, // other dead soldier found
(7) DCScream // hit soldier screaming
DEFINE_ENUM_END(DangerCause)
The index numbers in brackets are added for easier viewing only in this article.
It seems that later an '''ninth (index 8) event''' was added: '''DCCanFire'''.
It looks like an event when the unit has a target in sight and is able to fire it's weapon.
==== Engine parameters ====
The FSM gets supplied by the engine the following parameters:
* _this: References the unit.
* _dangerCause: An integer to specify the "first" danger event type. '''Assumption''': First could be most recent or oldest or with the highest priority.
* _queue: An array that contains multiple danger events and their details. One queue element contains:
** The danger cause (integer).
** A position. '''Assumption''': It could be the danger target position.
** A float. '''Assumption''': It looks like the timeout timestamp. It always has +5 seconds or less to the event call time.
** An unit. '''Assumption''': Most likely the unit the threat is coming from. Can be <NULL-object>.
//Note this data was retrieved assigning the FSM to civilian units as it never triggered so far for non Civilian units.
diag_log["danger.FSM",time,_this,_dangerCause,_queue];
"danger.FSM",0.05,C 1-1-A:8,3,[[3,[1665.17,1686.23,1.31488],5.60283,O 1-1-A:5],[3,[1665.17,1686.23,1.31488],5.79803,O 1-1-A:5]]
==== FSM Init ====
It seems only the highest priority event is handled:
// Retrieve the highest priority event from the _queue
private ["_priors","_priorCur"];
_priors = [3, 4, 5, 1, 4, 1, 1, 2, 2];
if (_dangerCause>0) then {_priorCur = _priors select _dangerCause}
else {_priorCur=-1};
{
  private ["_cause"];
  _cause = _x select 0;
  if ((_priors select _cause)>_priorCur) then
  {
    _dangerCause = _cause;
    _dangerPos = _x select 1;
    _dangerUntil = _x select 2;
    _dangerCausedBy = _x select 3;
  }
} forEach _queue;
_queue = [];
Danger cause events ordered by priority. Highest comes first:
(2) DCHit, 5
(1) DCFire, 4
(4) DCExplosion, 4
(0) DCEnemyDetected, 3
(7) DCScream 2
(8) DCCanFire 2
(3) DCEnemyNear, 1
(5) DCDeadBodyGroup, 1
(6) DCDeadBody, 1
==== Queue ====
After handling an event the FSM gets into the 'Check queue' state.
In the condition 'Next cause', it checks 'count _queue>0' and returns to the init state if true; otherwise exits.
The strange thing is that the _queue gets emptied in the init state.
So either the _queue can get refiled while the FSM is processed, or it will always exit.


'''TODO''': Log the value of _queue once in the state to determine how it works.


=== formationC.fsm ===
=== formationC.fsm ===

Revision as of 08:10, 15 May 2011

AI FSM

Summary page to gather community knowledge about the exposed AI FSM and the modification possibilities.

NOTE: None of the information on this page is guaranteed to be correct. The information is from research, testing and guesswork. The content of the page is WORK IN PROGRESS. You are most welcome to contribute yourself!

What are they about

It seems they expose certain areas of the AI behavior outside the core engine. This means the community can modify some parts of the AI behavior this one. That said in the config space a lot of values permitted tweaking AI as well, yet on a different level.

The available FSM are about:

  • Behavior while in formation.
  • Behavior while in danger/from danger events.

TODO: Needs more research, testing and specific information.

What are they NOT about

  • Micro AI
  • Low(est) level AI behavior system

TODO: Clarify and add more details.

Where to find them

ca\characters\scripts

Where are they used

comm.fsm

No reference.

danger.fsm

class CAManBase: Man
 fsmDanger = "Ca\characters\scripts\danger.fsm";

formationC.fsm

class Civilian: CAManBase
 fsmFormation = "ca\characters\scripts\formationC.fsm";

formationCDanger.fsm

class Civilian: CAManBase
 fsmDanger = "ca\characters\scripts\formationCDanger.fsm";

formationEntity.fsm

No reference. However it is the equivalent to the config definition of:

class CAManBase: Man
 fsmFormation = "Formation";

Formation itself is also defined, for unknown reasons, in the config space rather as FSM file.

class CfgFSMs - class Formation

How to edit them

Get the FSM_Editor part of the BI Tools 2 suite. It allows you to open, study and modify the FSM files.

What do they do

comm.fsm

Makes an unit unit communicate his action:

  • "Reloading! Cover me!"
  • "Running!"
  • "Covering!"

danger.fsm

Seems to be an event hook to make AI react to various danger events.

Right now only few events are used to initiate actions:

Cause 0 "ENEMY DETECTED"

Signal enemy via gesture.

Cause 8 "CAN FIRE"

Stop to fire makes the unit no longer move to return fire more effectively. If the threat is dead or after 4 to 8 seconds delay the unit moves on.

Next cause

The FSM can get multiple events supplied by the engine. Assumption: The FSM is meant to loop through all of them, yet it seems the looping is broken or disabled intentionally. See the technical details section below for more details.

formationC.fsm

formationCDanger.fsm

formationEntity.fsm

When are they run

comm.fsm

Assumption: Not at all. Seems like a test version and the actual system is integrated into the engine nowadays.

danger.fsm

Unknown. Was yet to log an occurrence for non Civilian infantry.

formationC.fsm

formationCDanger.fsm

formationEntity.fsm

Technical details

comm.fsm

  • _who = _this select 0;
  • _state = _this select 1;

danger.fsm

Danger causes

The FSM contains this description block:

DEFINE_ENUM_BEG(DangerCause)
(0) DCEnemyDetected,	// the first enemy detected
(1) DCFire,		// fire visible
(2) DCHit,		// vehicle hit
(3) DCEnemyNear,	// enemy very close to me
(4) DCExplosion,	// explosion detected
(5) DCDeadBodyGroup,	// dead soldier from my group found
(6) DCDeadBody,		// other dead soldier found
(7) DCScream		// hit soldier screaming
DEFINE_ENUM_END(DangerCause)

The index numbers in brackets are added for easier viewing only in this article. It seems that later an ninth (index 8) event was added: DCCanFire. It looks like an event when the unit has a target in sight and is able to fire it's weapon.

Engine parameters

The FSM gets supplied by the engine the following parameters:

  • _this: References the unit.
  • _dangerCause: An integer to specify the "first" danger event type. Assumption: First could be most recent or oldest or with the highest priority.
  • _queue: An array that contains multiple danger events and their details. One queue element contains:
    • The danger cause (integer).
    • A position. Assumption: It could be the danger target position.
    • A float. Assumption: It looks like the timeout timestamp. It always has +5 seconds or less to the event call time.
    • An unit. Assumption: Most likely the unit the threat is coming from. Can be <NULL-object>.
//Note this data was retrieved assigning the FSM to civilian units as it never triggered so far for non Civilian units.
diag_log["danger.FSM",time,_this,_dangerCause,_queue];
"danger.FSM",0.05,C 1-1-A:8,3,[[3,[1665.17,1686.23,1.31488],5.60283,O 1-1-A:5],[3,[1665.17,1686.23,1.31488],5.79803,O 1-1-A:5]]

FSM Init

It seems only the highest priority event is handled:

// Retrieve the highest priority event from the _queue
private ["_priors","_priorCur"];

_priors = [3, 4, 5, 1, 4, 1, 1, 2, 2];

if (_dangerCause>0) then {_priorCur = _priors select _dangerCause}
else {_priorCur=-1};

{
  private ["_cause"];
  _cause = _x select 0;
  if ((_priors select _cause)>_priorCur) then
  {
    _dangerCause = _cause;
    _dangerPos = _x select 1;
    _dangerUntil = _x select 2;
    _dangerCausedBy = _x select 3;
  }
} forEach _queue;
_queue = [];

Danger cause events ordered by priority. Highest comes first:

(2) DCHit,		5
(1) DCFire,		4
(4) DCExplosion,	4
(0) DCEnemyDetected,	3
(7) DCScream		2
(8) DCCanFire		2
(3) DCEnemyNear,	1
(5) DCDeadBodyGroup,	1
(6) DCDeadBody,		1

Queue

After handling an event the FSM gets into the 'Check queue' state. In the condition 'Next cause', it checks 'count _queue>0' and returns to the init state if true; otherwise exits.

The strange thing is that the _queue gets emptied in the init state. So either the _queue can get refiled while the FSM is processed, or it will always exit.

TODO: Log the value of _queue once in the state to determine how it works.

formationC.fsm

formationCDanger.fsm

formationEntity.fsm