Jump to content
madrussian

Quick Native FSM question(s)

Recommended Posts

 

I’m quite inspired by LAMBS game-altering capabilities lately, and have become aware of the power of Native FSMs, which I’d like to harness for an upcoming Lambs (optional) compatible addon. Quick questions for y’all:

 

Spoiler

Btw- I read through this:

https://community.bistudio.com/wiki/FSM#Example

^ Unless I missed something, it didn't quite address my issues.

 

So I’ve created a test FSM, specifically a Native (not Scripted) fsm to run on the AIs.

 

Question #1:  In BIS FSM editor, to save as “.fsm”, apparently we first have to select a compile config (via FsmAttributes -> Compile config). There are several choices (many of which are obviously incorrect). My guess (for Native FSMs) would be “entityFSM.cfg”. Is this correct, and if so do other compile configs apply to Native FSMs (to get/process engine feed on AI) as well?

 

Quote

animatedBriefing.cfg

campaignFSM.cfg

campaignFSMA3.cfg

campaignFSMhsim.cfg

classFSMcompile.cfg

entityFSM.cfg

fsm2sqf.cfg

fsm2sqfCall.cfg

FSMConfig.cfg

globalSwitchFSM.cfg

identityCompile.cfg

jvmFSM.cfg

missionTask.cfg

ORBAT.cfg

radioProtocol_config.cfg

radioProtocol_stringtable.cfg

radioProtocol_voiceActing.cfg

radioProtocol_voiceActingOO.cfg

rscMenu.cfg

scriptedFSM.cfg

 

Question #2:  My test addon looks like this:

 

Quote

class CfgPatches
{
    class BUB_DangerFSM
    {
        name="BUB DangerFSM";
        author="MadRussian";
        units[]={};
        weapons[]={};
        requiredVersion=0.1;
        requiredAddons[]=
        {
            "cba_main"
        };
    };
};
class CfgVehicles
{
    class CAManBase;
    class Civilian;
    class SoldierWB: CAManBase
    {
        fsmDanger="\BUB_DangerFSM\Danger.fsm";
    };
    class SoldierEB: CAManBase
    {
        fsmDanger="\BUB_DangerFSM\Danger.fsm";
    };
    class SoldierGB: CAManBase
    {
        fsmDanger="\BUB_DangerFSM\Danger.fsm";
    };
    class Civilian_F: Civilian
    {
        fsmDanger="\BUB_DangerFSM\Danger.fsm";
    };
};
class cfgMods
{
    author="MadRussian";
};

 

Upon firing up the game I sneak up on an enemy AI and shoot him, and get this error:

 

Quote

FSM ‘BUB_DangerFSM\Danger.fsm’ cannot be loaded.

 

^ So good news and bad.  Seems it's trying to run my danger fsm, but my fsmDanger paths are messed up (or similar).  I double check, and my addon folder "BUB_DangerFSM" does indeed contain my "Danger.fsm" file.  (Thinking briefly perhaps I used the wrong compile config?)

 

At this point, I look to Lambs to see how it’s done.  In Lambs “cfgvehicles.hpp”, I see this for fsmDanger paths:

 

Quote

class CfgVehicles {
    class CAManBase;
    class Civilian;
    class SoldierWB: CAManBase {
        fsmDanger = QUOTE(PATHTOF2_SYS(PREFIX,COMPONENT,scripts\lambs_danger.fsm));
    };
    class SoldierEB: CAManBase {
        fsmDanger = QUOTE(PATHTOF2_SYS(PREFIX,COMPONENT,scripts\lambs_danger.fsm));
    };
    class SoldierGB: CAManBase {
        fsmDanger = QUOTE(PATHTOF2_SYS(PREFIX,COMPONENT,scripts\lambs_danger.fsm));
    };
    class Civilian_F: Civilian {
        fsmDanger = QUOTE(PATHTOF2_SYS(PREFIX,COMPONENT,scripts\lambs_dangerCivilian.fsm));
    };

 

...

 

Seems “PATHTOF2_SYS” is the key (to resolve my issue), but I search Lambs (directory structure) for this snippet and only these 4 instances (all in this single file "cfgvehicles.hpp") come up.

 

Fast forward… Tried a few things, fairly stuck now, can someone help?  Specifically, how to get the path working.

 

Thanks! :smile_o:

Share this post


Link to post
Share on other sites

UPDATE:

 

OK, got the path working!  Removed the leading '\' on each fixed the issue:

 

Quote

class CfgVehicles
{
    class CAManBase;
    class Civilian;
    class SoldierWB: CAManBase
    {
        fsmDanger="BUB_DangerFSM\DangerSimple.fsm";
    };
    class SoldierEB: CAManBase
    {
        fsmDanger="BUB_DangerFSM\DangerSimple.fsm";
    };
    class SoldierGB: CAManBase
    {
        fsmDanger="BUB_DangerFSM\DangerSimple.fsm";
    };
    class Civilian_F: Civilian
    {
        fsmDanger="BUB_DangerFSM\DangerSimple.fsm";
    };
};

 

But now getting an error when my FSM fires.

 

My FSM is pretty simple so far (5 items):  Start State -> True Condition -> State -> True Condition -> End State

 

In State item, I have a simple hint command:

hint "Danger!";

Otherwise all items are empty.  OK, when I shoot an AI and my FSM fires, I get this error:

 

Quote

 

File BUB_DangerFSM\DangerSimple.fsm, line 57: '/DangerSimple/States/__2/Init.hint: "" encountered instead of '='

 

 

I'm thinking the error might be due to saving my FSM using the wrong compile config.  I compiled using "entityFSM.cfg", but probably it was suppose to be one of the others?  Here they are (again):

 

Quote

animatedBriefing.cfg

campaignFSM.cfg

campaignFSMA3.cfg

campaignFSMhsim.cfg

classFSMcompile.cfg

entityFSM.cfg

fsm2sqf.cfg

fsm2sqfCall.cfg

FSMConfig.cfg

globalSwitchFSM.cfg

identityCompile.cfg

jvmFSM.cfg

missionTask.cfg

ORBAT.cfg

radioProtocol_config.cfg

radioProtocol_stringtable.cfg

radioProtocol_voiceActing.cfg

radioProtocol_voiceActingOO.cfg

rscMenu.cfg

scriptedFSM.cfg

 

 

So which one should be used for Native FSM?

 

Thanks again!

 

  • Like 1

Share this post


Link to post
Share on other sites

I've always used scriptedFSM for the few I've done.  Don't know what the differences in any of the others would be.  Not that knowledgable.

  • Like 1

Share this post


Link to post
Share on other sites

OK, just tried that and worked great so far.  Thanks!

 

Going to see if I can get all these events(?) to generate:

 

Quote

comment "0  DCEnemyDetected";
comment "1  DCFire";
comment "2  DCHit";
comment "3  DCEnemyNear";
comment "4  DCExplosion";
comment "5  DCDeadBodyGroup";
comment "6  DCDeadBody";
comment "7  DCScream";
comment "8  DCCanFire";
comment "9  DCBulletClose";

 

This seems so powerful and apparently goes way beyond the normal set of addEventHandler events.

 

Share this post


Link to post
Share on other sites

There is also this page with more information and also talks about different compile configs.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

I just had a major lightbulb go on!  Seems like many of us could use a passthrough FSM, that runs the vanilla FSM but first passes the danger info via BIS_fnc_callScriptedEventHandler for all desired units.  Something like:

_unit setVariable ["FSM_WatchFeed"];

And then one for Lambs as well (for when running Lambs), something like:

_unit setVariable ["LAMBS_FSM_WatchFeed"];

Then we can track:

params ["_affectedUnit","_dangerCause", "_dangerPos", "_dangerUntil", "_dangerCausedBy"];

... and possibly _queue too, all via BIS_fnc_addScriptedEventHandler.

 

But again only on desired units, to keep performance up to snuff.

 

I really need this capability for my upcoming Building Utilities, because I'm using forced movement via playAction through buildings (technique learned from master @johnnyboy).  Specifically I need to detect various danger events so I can stop my building unit and let him shoot back.  (DCCanFire, DCBulletClose, and DCExplosion will be particularly useful.)  Anyhow, I don't need/wish to create a whole danger FSM, just need the danger events from a passthrough FSM.  I will likely (have to) try my hand at this for vanilla.  Otherwise, if something like this exists already, please point me in the right direction, and I'll buy you 🍕.  It's a real shame that BIS didn't allow for changing the Native FSM on-the-fly.

 

Btw- Curious how many of you have messed around with these danger events?

 

Here are some quick observations (from my limited testing so far):

  • DCCanFire is super handy.  If I pop back and forth from around a corner (in and out of view of the unit), this fires quite reliably.  Before discovering DCCanFire, I was about to write all this same functionality using lineIntersectsSurfaces, knowsabout, etc.  How dreadful that would have been to reinvent the wheel (not to mention how costly in terms of performance impact).
  • DCBulletClose (bullet flying through the air, passing by unit) is also a big winner!  Would be highly unreliable and taxing to do via script (via fired EH, and tracking projectile, measuring distances from units, etc).
  • Conventional explosions fire DCExplosion (as expected), but if you shoot the ground right next to the target unit, DCExplosion will fire then too.  Odd, but quite useful.
  • I can't seem to get DCDeadBodyGroup or DCDeadBody to fire, even killing off a slew of same-side units (via setDamage 1), and then having my intended unit walk around the corner.  These events don't fire, and he doesn't seem to discover them.

Overall, seems like anything that would make these danger events accessible to the scripting masses (like passthrough FSM), would be mighty fine. 😄

 

  • Like 2

Share this post


Link to post
Share on other sites

That is essentially how LAMBS danger works 🙂  Most if it is built on stuff documented by .kju and others in Arma2 days-- but extrapolated to Arma3. 

If you are running LAMBS danger you can track these variables by getting  
<unit> getVariable ["lambs_danger_FSMDangerCauseData",[]];


Which outputs
[_dangerCause, _dangerPos, _dangerUntil, _dangerCausedBy]]

--- 
I have experimented quite a bit with the different types of events, and there are some intricacies to them. I unfortunately do not have time to write it out right now (dinner is calling!). The next evolution of LAMBS danger.fsm is, as I envision it, to read these variables and feed them into an even more nuanced brain than LAMBS danger.fsm currently runs-- while also rewriting (or somehow enhancing) the existing  engine based formation.fsm. 

DCDeadBodyGroup and DCDeadBody absolutely do fire. It is only that their priority is very low and therefore will rarely come to the fore. You can experiment with  LAMBS where it is possible to configure the priorities on the fly: 
 

// FSM priorities
GVAR(fsmPriorities) = [
    3,      // DCEnemyDetected
    1,      // DCFire
    6,      // DCHit
    5,      // DCEnemyNear
    3,      // DCExplosion
    1,      // DCDeadBodyGroup
    1,      // DCDeadBody
    2,      // DCScream
    4,      // DCCanFire
    3       // DCBulletClose
];

// GVAR(fsmPriorities) translates into the variable 'lambs_danger_fsmPriorities'. 


edit: 

For your use you could do this: Read "lambs_danger_FSMDangerCauseData", or extend the codebase with an eventhandler.  Then continuously set  "lambs_danger_forceMove" to true on the unit  to override other manoeuvre schemes. 🙂

The latter variable is a first-run attempt at getting a more agile combatant. But like I said, it will require an ever deeper delving into A3 AI methinks. 

  • Like 1
  • Thanks 2

Share this post


Link to post
Share on other sites

Great explanations nKenny. 🙂

 

I do wish my Building Utilities system to work both with and without Lambs.  Thus perhaps the need for a more general solution (for when not running Lambs).  For this I'm thinking simply a (lightweight) copy of vanilla danger FSM with the passthrough functionality.  Or... I could just require Lambs and spell out how to disable Lambs (during which time Lambs running for the passthrough-only)... for when folks would want that.

 

As for when Lambs intended to be running (which of course is most of the time!):

 

1 hour ago, nkenny said:

For your use you could do this: Read "lambs_danger_FSMDangerCauseData", or extend the codebase with an eventhandler.  Then continuously set  "lambs_danger_forceMove" to true on the unit  to override other manoeuvre schemes. 🙂

 

This sounds promising & very doable.  I'd really like to get this working with EHs and not looping polling scripts though.  By "extend the codebase with an eventhandler", are you talking about BIS devs adding those missing EHs to the game?  Or (can anyone think of) some way I can access "lambs_danger_FSMDangerCauseData" (unit) variable via an EH?  Like similar to addPublicVariableEventHandler, but for getVariable/setVariable variables set on units?  If not...

 

@nkenny What do you think about adding extremely simplified passthough to Lambs so we can detect these danger causes as actual events (via BIS_fnc_addScriptedEventHandler)?  Again this would only apply to flagged units, via:

_unit setVariable ["lambs_fireDangerEvents", true];

or something like that.  Seems to me performance impact would be quite minimal, as it's one quick var check.  If unit flagged, lambs fires a danger event via BIS_fnc_callScriptedEventHandler.  (Obviously if no units are flagged, no scripted events are fired.)  Would help me tremendously (and I think many others).

 

Anyhow, regardless these are exciting A3 times.  Thanks again for Lambs and all your hard work, for which we all benefit so much.  Also, everyone please stay safe (and keep your loved ones safe too), with this virus rampaging about. 🙏 

 

  • Like 2

Share this post


Link to post
Share on other sites

 

Hi all, so I've got some time on my hands and would like to try my hand at a quick passthrough version of the vanilla FSMs.  I took a quick look in the config at "B_Soldier_F" (and a bunch of other man types), and unfortunately don't see fsm file paths:

 

Quote

configfile >> "CfgVehicles" >> "B_Soldier_F" >> "fsmDanger" = '-';

configfile >> "CfgVehicles" >> "B_Soldier_F" >> "fsmFormation" = 'Formation';

 

Anyone know off-hand where to find the vanilla native danger and formation FSMs?  Thanks!

 

Edit:

OK, in "characters_f.pbo", I found these 7 files:

 

Quote

 

a3\characters_f\scripts\comm.fsm

a3\characters_f\scripts\danger.fsm

a3\characters_f\scripts\fe1.sqf

a3\characters_f\scripts\fe2.sqf

a3\characters_f\scripts\formationc.fsm

a3\characters_f\scripts\formationcdanger.fsm

a3\characters_f\scripts\formationentity.fsm

 

 

Hmmm... Quick questions:

  1. Anyone know why "B_Soldier_F" config entries "fsmDanger" and "fsmFormation" don't explicitly reference any of these 5 fsm files?
  2. Anyone know if any of these 5 fsm files are actually used by vanilla game?
  3. Otherwise, are the actual vanilla danger and formation fsms simply hard-coded (or otherwise located elsewhere)?

Share this post


Link to post
Share on other sites

Short answer. You can't. These FSMs have been turned into engine-level commands. There are two ways to effect these however.  Check cfgFSM to see the fsm turne dinto config-- along with a series of interesting functions which are unfortunately inaccessible to seeing or editing. The danger.fsm is fsmDanger config setting, and the formationEntity.fsm is the fsmFormation config setting. 

 

It IS possible to change the config settings however. And I have done so for LAMBS danger fsm.  In my ORK mod I have also altered fsmFormation-- which is really, really powerful. HOWEVER. The price you pay is loosing all the neat cover-to-cover bounding movement. 

 

-k

edit
1. Because of 3
2. Only for the civilian fsms! 

3. I believe they are hardcoded

  • Like 1

Share this post


Link to post
Share on other sites

Good info, many thanks. 🙂

 

So if I understand, those 5 fsm files in "a3\characters_f\scripts" (or at least "danger.fsm" and "formationentity.fsm" in there) used to be run by the engine, but have now been superseded by the "config-based fsms" located in cfgFSM... correct?

 

2 hours ago, nkenny said:

Check cfgFSM to see the fsm turne dinto config-- along with a series of interesting functions which are unfortunately inaccessible to seeing or editing.

 

Roger that, with the those functions (in particular) inaccessible to seeing or editing.  Curious though, can they be called (somehow)?

 

2 hours ago, nkenny said:

It IS possible to change the config settings however.

 

Right, via "fsmDanger" and "fsmFormation" config settings.  Would be nice to know exactly which of the "config-based fsms" are running normally, so we know explicitly what we are overriding when we change these.

 

In CfgFSMs, I see 4 entries:

  • Butterfly
  • Dragonfly
  • Formation
  • HoneyBee

Looking again at "B_Soldier_F" config:

 

Quote

configfile >> "CfgVehicles" >> "B_Soldier_F" >> "fsmDanger" = '-';

configfile >> "CfgVehicles" >> "B_Soldier_F" >> "fsmFormation" = 'Formation';

 

About how all this ties together, it would seem that vanilla "fsmFormation" is referencing CfgFSMs' "Formation" entry.

 

But I'm still having trouble making sense of what vanilla "fsmDanger" is referencing with that "-".  Butterfly, Dragonfly, or HoneyBee perhaps?  Or perhaps all of these 3 (or a combination) is running simultaneously?  Also, are we sure we're actually overriding anything when setting config entry "fsmDanger", or is it possible we are simply supplementing whats going on?

 

I realize much of what I'm asking is probably unknowable (except to specific devs), but please correct if I've got anything explicitly wrong here.  It's nice to finally get some insight on how all this fsm stuff works.  Thanks @nkenny for sharing your expertise.

 

 

Share this post


Link to post
Share on other sites

I am 100% we are overwriting when changing these values. In fact, I have a lite formation mod I'm just about to release as a showcase. Also, I've used this already in my ork AI mod enhancement. These functions cannot, to my knowledge, be easily called.  I wish they could, because they govern some pretty interesting features! 

That said, some of the values can be changed, see: 

https://github.com/nk3nny/LambsDanger/blob/master/addons/danger/CfgFSMs.hpp
That is the result of some painful experiments. ^^

 

-k 

  • Like 1

Share this post


Link to post
Share on other sites

I'm building a small project of simplified  formations and danger.fsm   I'll put them on gitHub of course. 

 

-k 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×