mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Add initial medical state component
This commit is contained in:
parent
3aa88c80bf
commit
2d330e36e0
89
addons/medical_state/ACE_Medical_StateMachine.hpp
Normal file
89
addons/medical_state/ACE_Medical_StateMachine.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
class ACE_Medical_StateMachine {
|
||||
class Default {
|
||||
onState = QUOTE(DFUNC(handleDefaultState));
|
||||
onStateEntered = "";
|
||||
onStateLeaving = "";
|
||||
class Injury {
|
||||
targetState = "Injured";
|
||||
events[] = {'TakenInjury'};
|
||||
};
|
||||
class CriticalInjuryOrVitals {
|
||||
targetState = "Unconscious";
|
||||
events[] = {'InjuryCritical', 'CriticalVitals'};
|
||||
};
|
||||
class FatalInjuryOrVitals {
|
||||
targetState = "Dead";
|
||||
events[] = {'FatalVitals', 'InjuryFatal'};
|
||||
};
|
||||
};
|
||||
class Injured {
|
||||
onState = QUOTE(DFUNC(handleInjuredState));
|
||||
onStateEntered = "";
|
||||
onStateLeaving = "";
|
||||
|
||||
class FullHeal {
|
||||
targetState = "Default";
|
||||
events[] = {'FullHeal'};
|
||||
};
|
||||
class LastWoundTreated {
|
||||
targetState = "Default";
|
||||
events[] = {'LastWoundTreated'};
|
||||
};
|
||||
class CriticalInjuryOrVitals {
|
||||
targetState = "Unconscious";
|
||||
events[] = {'InjuryCritical', 'CriticalVitals'};
|
||||
};
|
||||
class FatalInjuryOrVitals {
|
||||
targetState = "Dead";
|
||||
events[] = {'FatalVitals', 'InjuryFatal'};
|
||||
};
|
||||
};
|
||||
class Unconscious {
|
||||
onState = QUOTE(DFUNC(handleUnconciousState));
|
||||
onStateEntered = QUOTE(DFUNC(enteredUnconscious)); // set unconscious animation & state
|
||||
onStateLeaving = QUOTE(DFUNC(leavingUnconscious)); // leave unconscious animation & state
|
||||
class WakeUpFromKnockDown {
|
||||
targetState = "Injured";
|
||||
condition = QUOTE(_unit call FUNC(hasStableVitals));
|
||||
events[] = {'MinUnconsciousTimer'};
|
||||
};
|
||||
class WakeUpStable {
|
||||
targetState = "Injured";
|
||||
condition = "unitUnconsciousTimer >= MinUnconsciousTimer";
|
||||
events[] = {'VitalsWentStable'};
|
||||
};
|
||||
class FatalTransitions {
|
||||
targetState = "Dead";
|
||||
events[] = {'InjuryFatal', 'FatalVitals', 'UnconsciousTimerRanOut'};
|
||||
};
|
||||
};
|
||||
class Dead {
|
||||
onStateEntered = "(_this select 0) setDamage 1"; // killing a unit also exits the state machine for this unit
|
||||
};
|
||||
class Revive {
|
||||
onState = QUOTE(DFUNC(handleReviveState));
|
||||
onStateEntered = QUOTE(DFUNC(enteredRevive)); // set unconscious animation & state
|
||||
onStateLeaving = QUOTE(DFUNC(leavingRevive)); // leave unconscious animation & state
|
||||
class FullHeal {
|
||||
targetState = "Default";
|
||||
events[] = {'fullyHealed'};
|
||||
onTransition = "";
|
||||
};
|
||||
class Revived {
|
||||
targetState = "Injured";
|
||||
events[] = {'Revived'};
|
||||
onTransition = "";
|
||||
};
|
||||
class TimerRanOut {
|
||||
targetState = "Dead";
|
||||
condition = "timerValue >= maxReviveTime";
|
||||
events[] = {'ReviveTimer'};
|
||||
onTransition = "";
|
||||
};
|
||||
class FatalTransitions {
|
||||
targetState = "Dead";
|
||||
condition = "killOnFatalDamageInRevive && inReviveState >= 10";
|
||||
events[] = {'FatalInjury'};
|
||||
};
|
||||
};
|
||||
};
|
53
addons/medical_state/functions/fnc_createStateMachine.sqf
Normal file
53
addons/medical_state/functions/fnc_createStateMachine.sqf
Normal file
@ -0,0 +1,53 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_stateMachineConfig"];
|
||||
|
||||
private _getCode = {
|
||||
params ["_config", "_attribute"];
|
||||
private _value = getText (_config >> _attribute);
|
||||
if (_value == "") {_value = "true"};
|
||||
compile _value;
|
||||
};
|
||||
|
||||
private _states = [];
|
||||
{
|
||||
private _stateName = configName _x;
|
||||
private _onState = [_x, "onState"] call _getCode;
|
||||
private _onEntry = [_x, "onEntry"] call _getCode;
|
||||
private _onExit = [_x, "onExit"] call _getCode;
|
||||
|
||||
// Collect all the transitions for the state
|
||||
private _transitions = [];
|
||||
{
|
||||
private _transitionName = configName _x;
|
||||
private _targetState = getText (_x >> "targetState");
|
||||
private _events = getArray (_x >> "events");
|
||||
private _condition = [_x, "condition"] call _getCode;
|
||||
private _onTransition = [_x, "onTransition"] call _getCode;
|
||||
|
||||
_transitions pushBack [_transitionName, _condition, _events, _onTransition, _targetState];
|
||||
} forEach ("true" configClasses _x);
|
||||
_states pushBack [_stateName, _onState, _onEntry, _onExit, _transitions];
|
||||
} forEach ("true" configClasses _stateMachineConfig);
|
||||
|
||||
// Helper method for finding the desired state when linking (See below)
|
||||
private _getState = {
|
||||
params ["_stateName"];
|
||||
private _state = ["Invalid", {}, {}, {}, []];
|
||||
{
|
||||
if (_stateName == (_x select 0)) exitWith {_state = _x};
|
||||
} forEach _states;
|
||||
_state;
|
||||
};
|
||||
|
||||
// Now we have collected all the states, link them in transitions so we do not have to look them up on state transitions
|
||||
{
|
||||
_x params ["", "", "", "", "_transitions"];
|
||||
{
|
||||
_x params ["", "", "", "", "_targetState"];
|
||||
private _state = [_targetState] call _getState;
|
||||
_x set [4, _state];
|
||||
} forEach _transitions;
|
||||
} forEach _states;
|
||||
|
||||
_states;
|
33
addons/medical_state/functions/fnc_handleStateEvent.sqf
Normal file
33
addons/medical_state/functions/fnc_handleStateEvent.sqf
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
params ["_unit", "_event", "_args"];
|
||||
|
||||
private _unitState = _unit getvariable [QGVAR(state), [CBA_missionTime, DEFAULT_STATE]];
|
||||
_unitState params ["_lastTime", "_state"];
|
||||
_state params ["_name", "_handler", "_onEntry", "_onExit", "_transitions"];
|
||||
|
||||
{
|
||||
_x params ["_transitionName", "_condition", "_events", "_onTransition", "_targetState"];
|
||||
|
||||
if (_condition && {_event in _events}) exitWith {
|
||||
_targetState params ["_targetStateName", "_targetStateHandler", "_targetStateOnEntry", "_targetStateOnExit", "_targetStateTansitions"];
|
||||
|
||||
// Handle state leaving
|
||||
[_unit, _event, _args] call {
|
||||
params ["_unit", "_event", "_args"];
|
||||
[_unit, _event, _args] call _onExit;
|
||||
[_unit, _event, _args] call _onTransition;
|
||||
};
|
||||
|
||||
// Switch the state
|
||||
_unitState set [1, _targetState];
|
||||
_unit setvariable [QGVAR(state), _unitState];
|
||||
|
||||
// Enter the state
|
||||
[_unit, _event, _args] call {
|
||||
params ["_unit", "_event", "_args"];
|
||||
[_unit, _event, _args] call _targetStateOnEntry;
|
||||
};
|
||||
};
|
||||
} forEach _transitions;
|
44
addons/medical_state/functions/fnc_stateMachine.sqf
Normal file
44
addons/medical_state/functions/fnc_stateMachine.sqf
Normal file
@ -0,0 +1,44 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
// Delay between state runs
|
||||
#define DELAY 10
|
||||
#define DEFAULT_STATE [0, "Default", {}, {}, {}, []];
|
||||
|
||||
GVAR(monitoredUnitsList) = [];
|
||||
GVAR(monitoredUnitsListIsSorted) = false;
|
||||
|
||||
[{
|
||||
params ["_args", "_pfhId"];
|
||||
|
||||
if (!GVAR(monitoredUnitsListIsSorted)) then {
|
||||
GVAR(monitoredUnitsList) sort true;
|
||||
GVAR(monitoredUnitsListIsSorted) = true;
|
||||
};
|
||||
|
||||
private _delete = false;
|
||||
private _exit = false;
|
||||
{
|
||||
_x params ["_unit"];
|
||||
|
||||
if (!isNull _unit && alive _unit) {
|
||||
private _unitState = _unit getvariable [QGVAR(state), [CBA_missionTime, DEFAULT_STATE]];
|
||||
_unitState params ["_lastTime", "_state"];
|
||||
|
||||
if ((_lastTime + DELAY) > CBA_missionTime) exitWith {_exit = true;};
|
||||
_state params ["_name", "_handler", "_onEntry", "_onExit", "_transitions"];
|
||||
_unitState set [0, CBA_missionTime];
|
||||
|
||||
_unit setvariable [QGVAR(state), _unitState];
|
||||
|
||||
[_unit, _name] call _handler;
|
||||
} else {
|
||||
_delete = true;
|
||||
GVAR(monitoredUnitsList) set [_forEachIndex, objNull];
|
||||
};
|
||||
if (_exit) exitwith {};
|
||||
} forEach GVAR(monitoredUnitsList);
|
||||
|
||||
if (_delete) then {
|
||||
GVAR(monitoredUnitsList) = GVAR(monitoredUnitsList) - [objNull];
|
||||
};
|
||||
}, 0, []] call CBA_fnc_addPerFrameHandler;
|
Loading…
Reference in New Issue
Block a user