From 04278149619bd31775cd87986b93dbdc5fd9dfd5 Mon Sep 17 00:00:00 2001 From: BaerMitUmlaut Date: Mon, 7 Nov 2016 22:21:07 +0100 Subject: [PATCH] Started transition to CBA state machine, removed revive in favour of extended cardiac arrest --- addons/medical/ACE_Medical_StateMachine.hpp | 88 +++++++++++-------- addons/medical/XEH_postInit.sqf | 3 - addons/medical/XEH_preInit.sqf | 20 ++++- .../fnc_conditionCardiacArrestDeath.sqf | 18 ++++ .../functions/fnc_enteredReviveState.sqf | 24 ----- .../fnc_enteredStateCardiacArrest.sqf | 16 ++++ .../functions/fnc_handleStateRevive.sqf | 55 ------------ .../fnc_leavingStateCardiacArrest.sqf | 16 ++++ 8 files changed, 118 insertions(+), 122 deletions(-) create mode 100644 addons/medical/functions/fnc_conditionCardiacArrestDeath.sqf delete mode 100644 addons/medical/functions/fnc_enteredReviveState.sqf create mode 100644 addons/medical/functions/fnc_enteredStateCardiacArrest.sqf delete mode 100644 addons/medical/functions/fnc_handleStateRevive.sqf create mode 100644 addons/medical/functions/fnc_leavingStateCardiacArrest.sqf diff --git a/addons/medical/ACE_Medical_StateMachine.hpp b/addons/medical/ACE_Medical_StateMachine.hpp index 8b6126a0d8..94df783f63 100644 --- a/addons/medical/ACE_Medical_StateMachine.hpp +++ b/addons/medical/ACE_Medical_StateMachine.hpp @@ -3,78 +3,88 @@ class ACE_Medical_StateMachine { onState = QUOTE(DFUNC(handleStateDefault)); class Injury { targetState = "Injured"; - events[] = {"TakenInjury"}; + events[] = {QGVAR(TakenInjury)}; }; class CriticalInjuryOrVitals { targetState = "Unconscious"; - events[] = {"InjuryCritical", "CriticalVitals"}; + events[] = {QGVAR(InjuryCritical), QGVAR(CriticalVitals)}; }; - class FatalInjuryOrVitals { - targetState = "Dead"; - events[] = {"FatalVitals", "InjuryFatal"}; + class FatalInjury { + targetState = "FatalInjury"; + events[] = {QGVAR(InjuryFatal)}; }; }; class Injured { onState = QUOTE(DFUNC(handleStateInjured)); class FullHeal { targetState = "Default"; - events[] = {"FullHeal"}; + events[] = {QGVAR(FullHeal)}; }; class LastWoundTreated { targetState = "Default"; - events[] = {"LastWoundTreated"}; + events[] = {QGVAR(LastWoundTreated)}; }; class CriticalInjuryOrVitals { targetState = "Unconscious"; - events[] = {"InjuryCritical", "CriticalVitals"}; + events[] = {QGVAR(InjuryCritical), QGVAR(CriticalVitals)}; }; - class FatalInjuryOrVitals { - targetState = "Dead"; - events[] = {"FatalVitals", "InjuryFatal"}; + class FatalVitals { + targetState = "CardiacArrest"; + events[] = {QGVAR(FatalVitals)}; + }; + class FatalInjury { + targetState = "FatalInjury"; + events[] = {QGVAR(InjuryFatal)}; }; }; class Unconscious { onState = QUOTE(DFUNC(handleStateUnconscious)); onStateEntered = QUOTE(DFUNC(enteredUnconsciousState)); - onStateLeaving = "_unit setVariable ['ACE_isUnconscious', false, true];"; + onStateLeaving = "_this setVariable ['ACE_isUnconscious', false, true];"; class WakeUpFromKnockDown { targetState = "Injured"; - condition = QUOTE(_unit call FUNC(hasStableVitals)); - events[] = {"MinUnconsciousTimer"}; + condition = QUOTE(_this call FUNC(hasStableVitals)); + events[] = {QGVAR(MinUnconsciousTimer)}; }; class WakeUpStable { targetState = "Injured"; condition = "unitUnconsciousTimer >= MinUnconsciousTimer"; - events[] = {"VitalsWentStable"}; + events[] = {QGVAR(VitalsWentStable)}; }; class FatalTransitions { + targetState = "CardiacArrest"; + events[] = {QGVAR(FatalVitals), QGVAR(UnconsciousTimerRanOut)}; + }; + class FatalInjury { + targetState = "FatalInjury"; + events[] = {QGVAR(InjuryFatal)}; + }; + }; + class FatalInjury { + // Transition state for handling instant death + onStateEntered = QUOTE(DFUNC(enteredStateFatalInjury)); + class InstantDeathPrevented { + targetState = "CardiacArrest"; + condition = QUOTE(DFUNC(conditionPreventInstantDeath)); + }; + class InstantDeath { targetState = "Dead"; - events[] = {"InjuryFatal", "FatalVitals", "UnconsciousTimerRanOut"}; + condition = "true"; + }; + }; + class CardiacArrest { + onStateEntered = QUOTE(DFUNC(enteredStateCardiacArrest)); + onStateLeaving = '_this setVariable [QGVAR(cardiacArrestStart), nil]'; + class Death { + targetState = "Dead"; + condition = QUOTE(DFUNC(conditionCardiacArrestDeath)); + }; + class Reanimated { + targetState = "Unconscious"; + events[] = {QGVAR(CPRSucceeded)}; }; }; class Dead { - onStateEntered = "(_this select 0) setDamage 1"; // killing a unit also exits the state machine for this unit - }; - class Revive { - onState = QUOTE(DFUNC(handleStateRevive)); - onStateEntered = QUOTE(DFUNC(enteredRevive)); // set unconscious animation & state - onStateLeaving = QUOTE(DFUNC(leavingRevive)); // leave unconscious animation & state - class FullHeal { - targetState = "Default"; - events[] = {"fullyHealed"}; - }; - class Revived { - targetState = "Injured"; - events[] = {"Revived"}; - }; - class TimerRanOut { - targetState = "Dead"; - events[] = {"ReviveTimer", "NoLives"}; - }; - class FatalTransitions { - targetState = "Dead"; - condition = QGVAR(killOnFatalDamageInRevive); - events[] = {"FatalInjury"}; - }; + onStateEntered = "_this setDamage 1"; // killing a unit also exits the state machine for this unit }; }; diff --git a/addons/medical/XEH_postInit.sqf b/addons/medical/XEH_postInit.sqf index 434086bf4b..3f9b0c2df8 100644 --- a/addons/medical/XEH_postInit.sqf +++ b/addons/medical/XEH_postInit.sqf @@ -1,12 +1,9 @@ - #include "script_component.hpp" GVAR(heartBeatSounds_Fast) = ["ACE_heartbeat_fast_1", "ACE_heartbeat_fast_2", "ACE_heartbeat_fast_3"]; GVAR(heartBeatSounds_Normal) = ["ACE_heartbeat_norm_1", "ACE_heartbeat_norm_2"]; GVAR(heartBeatSounds_Slow) = ["ACE_heartbeat_slow_1", "ACE_heartbeat_slow_2"]; -call FUNC(stateMachine); - //Handle Deleting Bodies and creating litter on Server: if (isServer) then { ["ace_placedInBodyBag", FUNC(serverRemoveBody)] call CBA_fnc_addEventHandler; diff --git a/addons/medical/XEH_preInit.sqf b/addons/medical/XEH_preInit.sqf index b590114b13..2f8b13e377 100644 --- a/addons/medical/XEH_preInit.sqf +++ b/addons/medical/XEH_preInit.sqf @@ -7,7 +7,7 @@ ADDON = false; GVAR(HITPOINTS) = ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"]; GVAR(SELECTIONS) = ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"]; -GVAR(STATE_MACHINE) = (configFile >> "ACE_Medical_StateMachine") call FUNC(createStateMachine); +GVAR(STATE_MACHINE) = (configFile >> "ACE_Medical_StateMachine") call CBA_statemachine_fnc_createFromConfig; // @todo, ACE_Settings [ @@ -37,4 +37,22 @@ GVAR(STATE_MACHINE) = (configFile >> "ACE_Medical_StateMachine") call FUNC(creat true ] call CBA_Settings_fnc_init; +[ + QGVAR(enableInstantDeath), + "CHECKBOX", + ["Enable Instant Death", "Enables units instantly dying without entering cardiac arrest first."], //@todo + "ACE Medical", // @todo + true, + true +] call CBA_Settings_fnc_init; + +[ + QGVAR(maximumCardiacArrestTime), + "SLIDER", + ["Maximum Cardiac Arrest Time", "Sets the maximum amount of time a unit can stay in cardiac arrest."], //@todo + "ACE Medical", // @todo + [0, 30, 2, 0], + true +] call CBA_Settings_fnc_init; + ADDON = true; diff --git a/addons/medical/functions/fnc_conditionCardiacArrestDeath.sqf b/addons/medical/functions/fnc_conditionCardiacArrestDeath.sqf new file mode 100644 index 0000000000..fd7348f4bc --- /dev/null +++ b/addons/medical/functions/fnc_conditionCardiacArrestDeath.sqf @@ -0,0 +1,18 @@ +/* + * Author: BaerMitUmlaut + * Handles a unit entering cardiac arrest. + * + * Arguments: + * 0: The Unit + * + * Return Value: + * None + * + * Public: No + */ +#include "script_component.hpp" +params ["_unit"]; + +private _startTime = _unit getVariable [QGVAR(cardiacArrestStart), CBA_missionTime]; + +(CBA_missionTime - _startTime) > (GVAR(maximumCardiacArrestTime) * 60) diff --git a/addons/medical/functions/fnc_enteredReviveState.sqf b/addons/medical/functions/fnc_enteredReviveState.sqf deleted file mode 100644 index 4368cf5985..0000000000 --- a/addons/medical/functions/fnc_enteredReviveState.sqf +++ /dev/null @@ -1,24 +0,0 @@ - - -#include "script_component.hpp" - -params ["_unit"]; - -private _reviveVal = _unit getVariable [QGVAR(enableRevive), GVAR(enableRevive)]; -if (_reviveVal == 1 && {[_unit] call EFUNC(common,isPlayer)} || _reviveVal == 2) then { - if (_unit getVariable [QGVAR(inReviveState), false]) exitWith { - // Error, already in revive state - false; - }; - - private _lifesLeft = _unit getVariable [QGVAR(amountOfReviveLives), GVAR(amountOfReviveLives)]; - if (GVAR(amountOfReviveLives) > 0 && _lifesLeft == 0) exitWith { - [_unit, "NoLives", []] call FUNC(stateEvent); - }; - - _unit setVariable [QGVAR(inReviveState), true, true]; - _unit setVariable [QGVAR(reviveStartTime), CBA_missionTime]; - [_unit, true] call FUNC(setUnconscious); -} else { - [_unit, "NoLives", []] call FUNC(stateEvent); -}; diff --git a/addons/medical/functions/fnc_enteredStateCardiacArrest.sqf b/addons/medical/functions/fnc_enteredStateCardiacArrest.sqf new file mode 100644 index 0000000000..73f94a8471 --- /dev/null +++ b/addons/medical/functions/fnc_enteredStateCardiacArrest.sqf @@ -0,0 +1,16 @@ +/* + * Author: BaerMitUmlaut + * Handles a unit entering cardiac arrest. + * + * Arguments: + * 0: The Unit + * + * Return Value: + * None + * + * Public: No + */ +#include "script_component.hpp" +params ["_unit"]; + +_unit setVariable [QGVAR(cardiacArrestStart), CBA_missionTime]; diff --git a/addons/medical/functions/fnc_handleStateRevive.sqf b/addons/medical/functions/fnc_handleStateRevive.sqf deleted file mode 100644 index e5251c93e5..0000000000 --- a/addons/medical/functions/fnc_handleStateRevive.sqf +++ /dev/null @@ -1,55 +0,0 @@ - -#include "script_component.hpp" - -params ["_unit", "_stateName", "_lastTime"]; - -// If the unit died the loop is finished -if (!alive _unit) exitWith {}; - -// If locality changed, broadcast the last medical state and finish the local loop -if (!local _unit) exitWith { - if (GVAR(level) >= 2) then { - _unit setVariable [QGVAR(heartRate), _unit getVariable [QGVAR(heartRate), 80], true]; - _unit setVariable [QGVAR(bloodPressure), _unit getVariable [QGVAR(bloodPressure), [80, 120]], true]; - }; - _unit setVariable [QGVAR(bloodVolume), _unit getVariable [QGVAR(bloodVolume), DEFAULT_BLOOD_VOLUME], true]; -}; - -private _startTime = _unit getVariable [QGVAR(reviveStartTime), 0]; - -// If we are in revive state in a blown up vehicle, try to unload so that people can access the body -if ((alive _unit) && {(vehicle _unit) != _unit} && {!alive (vehicle _unit)}) then { - TRACE_2("Unloading", _unit, vehicle _unit); - [_unit] call EFUNC(common,unloadPerson); -}; - -// Revive timer ran out -if (GVAR(maxReviveTime) > 0 && {CBA_missionTime - _startTime > GVAR(maxReviveTime)}) exitWith { - [_unit, "ReviveTimer", []] call FUNC(stateEvent); - _unit setVariable [QGVAR(inReviveState), nil, true]; - _unit setVariable [QGVAR(reviveStartTime), nil]; -}; - -// If the unit was taken out from revive state, exit the loop -if !(_unit getVariable [QGVAR(inReviveState), false]) exitWith { - // Revived without dieing, so in case we have lifes, remove one. - if (GVAR(amountOfReviveLives) > 0) then { - _lifesLeft = _unit getVariable [QGVAR(amountOfReviveLives), GVAR(amountOfReviveLives)]; - _unit setVariable [QGVAR(amountOfReviveLives), _lifesLeft - 1, true]; - }; - _unit setVariable [QGVAR(reviveStartTime), nil]; -}; - -// Remove heartbeat -if (GVAR(level) >= 2) then { - if (_unit getVariable [QGVAR(heartRate), 60] > 0) then { - _unit setVariable [QGVAR(heartRate), 0]; - }; -}; - -[_unit, CBA_missionTime - _lastTime] call FUNC(handleUnitVitals); - -private _pain = _unit getVariable [QGVAR(pain), 0]; -if (_pain > (_unit getVariable [QGVAR(painSuppress), 0])) then { - [_unit, "moan", PAIN_TO_MOAN(_pain)] call EFUNC(medical_engine,playInjuredSound); -}; diff --git a/addons/medical/functions/fnc_leavingStateCardiacArrest.sqf b/addons/medical/functions/fnc_leavingStateCardiacArrest.sqf new file mode 100644 index 0000000000..8ec63de5d9 --- /dev/null +++ b/addons/medical/functions/fnc_leavingStateCardiacArrest.sqf @@ -0,0 +1,16 @@ +/* + * Author: BaerMitUmlaut + * Handles a unit entering cardiac arrest. + * + * Arguments: + * 0: The Unit + * + * Return Value: + * None + * + * Public: No + */ +#include "script_component.hpp" +params ["_unit"]; + +_unit setVariable [QGVAR(cardiacArrestStart), nil];