Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addons/statemachine/$PBOPREFIX$
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x\kat\addons\statemachine
29 changes: 29 additions & 0 deletions addons/statemachine/CfgEventHandlers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preInit));
};
};

// class Extended_PostInit_EventHandlers {
// class ADDON {
// init = QUOTE(call COMPILE_FILE(XEH_postInit));
// };
// };

class Extended_Respawn_EventHandlers {
class CAManBase {
class ADDON {
respawn = QUOTE(call ACEFUNC(medical_statemachine,resetStateDefault));
exclude[] = {IGNORE_BASE_UAVPILOTS};
};
};
};

class Extended_Local_EventHandlers {
class CAManBase {
class ADDON {
local = QUOTE(call FUNC(localityChangedEH)); // TODO replace with kam function
exclude[] = {IGNORE_BASE_UAVPILOTS};
};
};
};
10 changes: 10 additions & 0 deletions addons/statemachine/CfgFunctions.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CfgFunctions {
class overwrite_ace_medical_statemachine {
tag = "ace_medical_statemachine";
class ace_medical_statemachine {
class localityChangedEH {
file = QPATHTOF(functions\fnc_localityChangedEH.sqf);
};
};
};
};
113 changes: 113 additions & 0 deletions addons/statemachine/Statemachine.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Overwrite for ACE_Medical_StateMachine
class KAT_StateMachine {
list = QUOTE(call ACEFUNC(common,getLocalUnits));
skipNull = 1;
class Default {
onState = QACEFUNC(medical_statemachine,handleStateDefault);
class Injury {
targetState = "Injured";
events[] = {QACEGVAR(medical,injured), QACEGVAR(medical,LoweredVitals)};
};
class CriticalInjuryOrVitals {
targetState = "Unconscious";
events[] = {QACEGVAR(medical,CriticalInjury), QACEGVAR(medical,CriticalVitals), QACEGVAR(medical,knockOut)};
};
class FatalVitals {
targetState = "CardiacArrest";
events[] = {QACEGVAR(medical,FatalVitals), QACEGVAR(medical,Bleedout)};
};
class FatalInjury {
targetState = "FatalInjury";
events[] = {QACEGVAR(medical,FatalInjury)};
};
};
class Injured {
onState = QACEFUNC(medical_statemachine,handleStateInjured);
class FullHeal {
targetState = "Default";
events[] = {QACEGVAR(medical,FullHeal)};
};
class CriticalInjuryOrVitals {
targetState = "Unconscious";
events[] = {QACEGVAR(medical,CriticalInjury), QACEGVAR(medical,CriticalVitals), QACEGVAR(medical,knockOut)};
};
class FatalVitals {
targetState = "CardiacArrest";
events[] = {QACEGVAR(medical,FatalVitals), QACEGVAR(medical,Bleedout)};
};
class FatalInjury {
targetState = "FatalInjury";
events[] = {QACEGVAR(medical,FatalInjury)};
};
};
class Unconscious {
onState = QACEFUNC(medical_statemachine,handleStateUnconscious);
onStateEntered = QACEFUNC(medical_statemachine,enteredStateUnconscious);
class DeathAI {
targetState = "Dead";
condition = QUOTE(!(_this getVariable [ARR_2(QQACEGVAR(medical_statemachine,AIUnconsciousness),ACEGVAR(medical_statemachine,AIUnconsciousness))]) && {!isPlayer _this});
};
class WakeUp {
targetState = "Injured";
condition = QACEFUNC(medical_status,hasStableVitals);
events[] = {QACEGVAR(medical,WakeUp)};
onTransition = QUOTE([ARR_2(_this,false)] call ACEFUNC(medical_status,setUnconsciousState));
};
class FatalTransitions {
targetState = "CardiacArrest";
events[] = {QACEGVAR(medical,FatalVitals), QACEGVAR(medical,Bleedout)};
};
class FatalInjury {
targetState = "FatalInjury";
events[] = {QACEGVAR(medical,FatalInjury)};
};
};
class FatalInjury {
// Transition state for handling instant death from fatal injuries
// This state raises the next transition in the same frame
onStateEntered = QACEFUNC(medical_statemachine,enteredStateFatalInjury);
class SecondChance {
events[] = {QACEGVAR(medical,FatalInjuryInstantTransition)};
targetState = "CardiacArrest";
condition = QACEFUNC(medical_statemachine,conditionSecondChance);
onTransition = QACEFUNC(medical_statemachine,transitionSecondChance);
};
class Death {
events[] = {QACEGVAR(medical,FatalInjuryInstantTransition)};
targetState = "Dead";
};
};
class CardiacArrest {
onState = QACEFUNC(medical_statemachine,handleStateCardiacArrest);
onStateEntered = QACEFUNC(medical_statemachine,enteredStateCardiacArrest);
onStateLeaving = QACEFUNC(medical_statemachine,leftStateCardiacArrest);
class DeathAI {
// If an AI unit reanimates, they will immediately die upon entering unconsciousness if AI Unconsciousness is disabled
// As a result, we immediately kill the AI unit since cardiac arrest is effectively useless for it
targetState = "Dead";
condition = QUOTE(!ACEGVAR(medical_statemachine,AIUnconsciousness) && {!isPlayer _this});
};
class Timeout {
targetState = "Dead";
condition = QACEFUNC(medical_statemachine,conditionCardiacArrestTimer);
};
class Reanimation {
targetState = "Unconscious";
events[] = {QACEGVAR(medical,CPRSucceeded)};
};
class Execution {
targetState = "Dead";
condition = QACEFUNC(medical_statemachine,conditionExecutionDeath);
events[] = {QACEGVAR(medical,FatalInjury)};
};
class Bleedout {
targetState = "Dead";
condition = QUOTE((ACEGVAR(medical_statemachine,cardiacArrestBleedoutEnabled))); // wrap to ensure cba uses this as code and not a direct variable
events[] = {QACEGVAR(medical,Bleedout)};
};
};
class Dead {
// When the unit is killed it's no longer handled by the statemachine
onStateEntered = QACEFUNC(medical_statemachine,enteredStateDeath);
};
};
1 change: 1 addition & 0 deletions addons/statemachine/XEH_PREP.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PREP(localityChangedEH);
14 changes: 14 additions & 0 deletions addons/statemachine/XEH_postInit.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "script_component.hpp"

// ["ace_killed", { // global event
// params ["_unit"];

// // Prevent second ragdoll of uncon units when they're killed
// if (
// IS_UNCONSCIOUS(_unit) && !isAwake _unit // uncon and not ragdolling
// && {isPlayer _unit || {_unit getVariable [QGVAR(AIUnconsciousness), GVAR(AIUnconsciousness)]}}
// ) then {
// _unit enableSimulation false;
// [{_this enableSimulation true}, _unit, 2] call CBA_fnc_waitAndExecute;
// };
// }] call CBA_fnc_addEventHandler;
14 changes: 14 additions & 0 deletions addons/statemachine/XEH_preInit.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "script_component.hpp"

ADDON = false;

PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;

#define CBA_SETTINGS_CAT "KAT - ADV Medical: Advanced States"

// Overwrite ace statemachine
ACEGVAR(medical,STATE_MACHINE) = (configFile >> "KAT_StateMachine") call CBA_statemachine_fnc_createFromConfig;

ADDON = true;
22 changes: 22 additions & 0 deletions addons/statemachine/config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "script_component.hpp"

class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {
"ace_medical_vitals",
"ace_medical_statemachine"
};
author = "apo_tle";
authors[] = {"Glowbal", "KoffeinFlummi","apo_tle"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
};

#include "Statemachine.hpp"
#include "CfgEventHandlers.hpp"
#include "CfgFunctions.hpp"
56 changes: 56 additions & 0 deletions addons/statemachine/functions/fnc_localityChangedEH.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "..\script_component.hpp"
/*
* Author: PabstMirror
* Modified: apo_tle
* Handles locality switch. Will also be called at unit init.
* Because state machine state is local only, when a unit transfers locality we need to manually transition to it's current state
*
* Arguments:
* 0: Unit <OBJECT>
* 1: isLocal <BOOL>
*
* Return Value:
* None
*
* Example:
* [player, true] call ace_medical_statemachine_fnc_localityChangedEH
*
* Public: No
*/

params ["_unit", "_isLocal"];
TRACE_2("localityChangedEH",_unit,_isLocal);

if (!alive _unit) exitWith {};

if (_isLocal) then {
private _currentState = [_unit, ACEGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
TRACE_1("local",_currentState);

switch (true) do {
case (IN_CRDC_ARRST(_unit)): {
if (_currentState == "CardiacArrest") exitWith {};
_unit setVariable [VAR_CRDC_ARRST, false]; // force reset vars so setCardiacArrestState can run (enteredStateCardiacArrest will also be called)
_unit setVariable [VAR_UNCON, false];
TRACE_1("manually changing state to CardiacArrest",_currentState);
[_unit, ACEGVAR(medical,STATE_MACHINE), _currentState, "CardiacArrest", {}, "LocalityChange"] call CBA_statemachine_fnc_manualTransition;
};
case (IS_UNCONSCIOUS(_unit)): {
if (_currentState == "Unconscious") exitWith {};
_unit setVariable [VAR_UNCON, false]; // force reset var so ace_medical_status_fnc_setUnconsciousState can run
TRACE_1("manually changing state to Unconscious",_currentState);
[_unit, ACEGVAR(medical,STATE_MACHINE), _currentState, "Unconscious", {}, "LocalityChange"] call CBA_statemachine_fnc_manualTransition;
};
case (IS_BLEEDING(_unit) || {IS_IN_PAIN(_unit)}): {
if (_currentState == "Injured") exitWith {};
TRACE_1("manually changing state to Injured",_currentState);
[_unit, ACEGVAR(medical,STATE_MACHINE), _currentState, "Injured", {}, "LocalityChange"] call CBA_statemachine_fnc_manualTransition;
};
default {
// If locality transfers back and forth, we could be in an old state and should transfer back to default
if (_currentState == "Default") exitWith {};
TRACE_1("manually changing state to Default",_currentState);
[_unit, ACEGVAR(medical,STATE_MACHINE), _currentState, "Default", {}, "LocalityChange"] call CBA_statemachine_fnc_manualTransition;
};
};
}
17 changes: 17 additions & 0 deletions addons/statemachine/script_component.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#define COMPONENT statemachine
#define COMPONENT_BEAUTIFIED KAT - STATEMACHINE
#include "\x\kat\addons\main\script_mod.hpp"

// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS

#ifdef DEBUG_ENABLED_STATEMACHINE
#define DEBUG_MODE_FULL
#endif

#ifdef DEBUG_SETTINGS_STATEMACHINE
#define DEBUG_SETTINGS DEBUG_SETTINGS_STATEMACHINE
#endif

#include "\x\kat\addons\main\script_macros.hpp"
5 changes: 5 additions & 0 deletions addons/statemachine/stringtable.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="KAT">
<Package name="Statemachine">
</Package>
</Project>
Loading