Skip to content
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

State Machine - Add Condition Check Frequency #1282

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

PiZZAD0X
Copy link

@PiZZAD0X PiZZAD0X commented Jan 12, 2020

When merged this pull request will:

  • Add an optional parameter to a state machine transition that limits the frequency of a condition check.
  • Add an optional config entry condFrequency for determining transition frequency .
  • Add conditionPrecondition parsing in the FSM Editor compile config.
  • Add new optional param that follow existing params for backwards compatibility.
  • Add a default transition frequency of 0 to produce old behaviour for existing script based state machines.

Aim and Intent:

  • Add a shorthand for timed frequency checks for transition conditions which acts as a limit on intensive condition checks as well as a minimum wait timer between entering a state and evaluating a transition condition. Maximum time to condition check is not guaranteed and dependent on the amount of list items in the state machine and fps.

Screenshot_753
Screenshot_754

@bux
Copy link
Contributor

bux commented Jan 12, 2020

why not conditionFrequency?

@PabstMirror
Copy link
Contributor

I think it would make more sense to compile these checks into _condition.
This would prevent it adding any overhead when not using this feature.

We would only have to modify createFromConfig and not touch any other sqf.

private _condFrequency = getNumber (_x >> "condFrequency");
private _condition = getText (x >> "condition");

if (_condFrequency <= 0) then {
    // do GET_FUNCTION
    if (isNil _condition) then { 
        _condition = compile _condition; 
    } else {
        _condition = missionNamespace getVariable _condition;
    };
} else {
    if (isNil _condition) then { 
        _condition = compile format ["
        (CBA_missionTime >= (_current getVariable ['cba_statemachine_nextCheck' + str _id, -1])) 
        && {%1} 
        && {_current setVariable ['cba_statemachine_nextCheck' + str _id, CBA_missionTime + %2]; true}
        ", _condition, _condFrequency];
    } else {
        _condition = compile format ["
        (CBA_missionTime >= (_current getVariable ['cba_statemachine_nextCheck' + str _id, -1])) 
        && %1
        && {_current setVariable ['cba_statemachine_nextCheck' + str _id, CBA_missionTime + %2]; true}
        ", _condition, _condFrequency];
    };
};

@PiZZAD0X
Copy link
Author

If a var determining the next check is set on a condition evaluation, it would not take into account a state transition via a condition that is lacking the condFrequency time check and resulting setVariable. To result in a wait one needs to check the time that the SM entered any state and compare it to current mission time, which is not guaranteed with this unless every transition has a positive condFrequency value. You would also need to deal with manual and event transitions if one wanted to rely on this feature as a minimum time to state transition.

@commy2
Copy link
Contributor

commy2 commented Jan 12, 2020

Just script your own delay into the already existing condition block.
I withdraw myself from this. Baer should decide.

@PiZZAD0X
Copy link
Author

I can see the value in not adding overhead, but as of now there is only limited use of the state machine with most people opting for FSMs or even iterating through with their own PFH/stacked onEach. A few shorthands like this and the FSM editor config should make utilizing the state machine much more accessible.

@commy2
Copy link
Contributor

commy2 commented Jan 12, 2020

Never said "overhead".
Low usage is no sufficient argument for the addition of a feature.

@PiZZAD0X
Copy link
Author

I think low usage is an argument in this case. Low usage of the state machine is a pity, and the most common cause I hear people say for avoiding the state machine is that they are simply much more familiar with FSM and they are not willing to port over/rewrite their AI in the state machine format. By adding shorthands and having the FSM editor compile config you can make the state machine much more attractive to work with.

@PiZZAD0X
Copy link
Author

@BaerMitUmlaut

@Best2nd
Copy link

Best2nd commented Jan 17, 2020

Man, it would be great to have the timer on the statemachine. Can we make this a thing, please?

@BaerMitUmlaut
Copy link
Contributor

  • Condition frequency is a very misleading name
  • People who didn't show the will to learn the CBA state machine system maybe shouldn't
  • The performance argument is very weird to me, instead of fixing your code you now get long frames, you're just moving a problem around

@PiZZAD0X
Copy link
Author

  • I couldn't care less about the particular var name, we could name it whatever we want.
  • I disagree, there are very few people that use the statemachine and this, like the FSM editor compile config, makes the system more accessible and easier to develop with. Being accessible and utilized when the system is a better alternative to using FSMs is a good thing.
  • There is a clear use scenario for staggering intensive checks as well as an effective wait timer, people do it all the time through FSMs and in a couple cases with the statemachine. This is the equivalent of a shorthand for setting a var with time in a state and evaluating that in the condition.

@BaerMitUmlaut
Copy link
Contributor

I'd prefer if it was compiled into code. If you're concerned about it not resetting without additional code, you could do that like this:

if (CBA_missionTime >= _lastCheck + _condFrequency && {_current setVariable [..., nil]; true})

@PiZZAD0X
Copy link
Author

There wouldn't be a concern over readability if it was compiled into the condition? It would also need to set/evaluate vars before the condition check and would probably require a true && {code for evaluating timer} && {condition}

@PiZZAD0X
Copy link
Author

if (_conditionFrequency > 0) then {
    _condition = compile format [QUOTE( \
        true && \
        { \
            private _return = false; \
            if ((_current getVariable [ARR_2((QQGVAR(lastCheckedState) + str _id), '')]) isEqualTo _thisState) then { \
                private _lastCheckedTime = _current getVariable [ARR_2((QQGVAR(lastCheckedTime) + str _id), CBA_MissionTime)]; \
                if (CBA_MissionTime >= (_lastCheckedTime + %2)) then { \
                    _current setVariable [ARR_2((QQGVAR(lastCheckedTime) + str _id), CBA_MissionTime)]; \
                    _return = true; \
                } else { \
                    _return = false; \
                }; \
            } else { \
                _current setVariable [ARR_2((QQGVAR(lastCheckedState) + str _id), _thisState)]; \
                _current setVariable [ARR_2((QQGVAR(lastCheckedTime) + str _id), CBA_MissionTime)]; \
                _return = false; \
            }; \
            _return \
        } && \
        %1 \
    ), _condition, _conditionFrequency];
};

Any suggestions?

- cfgName to `conditionFrequency`
@jonpas jonpas added the Feature label Jul 23, 2021
@jonpas jonpas changed the title State Machine Condition Check Frequency State Machine - Add Condition Check Frequency Jul 23, 2021
@jonpas
Copy link
Member

jonpas commented Jul 23, 2021

@BaerMitUmlaut ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants