From 4a63b9749d1386ec172097b85e333c18f80693f1 Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:03:20 -0300 Subject: [PATCH 01/11] Medical Vitals - Extract iv/medication consumption & state update --- addons/medical_status/XEH_PREP.hpp | 1 - .../functions/fnc_getBloodVolumeChange.sqf | 53 ------- addons/medical_vitals/XEH_PREP.hpp | 2 + addons/medical_vitals/XEH_preInit.sqf | 1 + .../functions/fnc_consumeIVs.sqf | 60 ++++++++ .../functions/fnc_consumeMedications.sqf | 61 +++++++++ .../functions/fnc_handleUnitVitals.sqf | 129 +++--------------- .../functions/fnc_updateBloodPressure.sqf | 4 + .../functions/fnc_updateHeartRate.sqf | 6 +- .../functions/fnc_updateState.sqf | 75 ++++++++++ 10 files changed, 224 insertions(+), 168 deletions(-) delete mode 100644 addons/medical_status/functions/fnc_getBloodVolumeChange.sqf create mode 100644 addons/medical_vitals/functions/fnc_consumeIVs.sqf create mode 100644 addons/medical_vitals/functions/fnc_consumeMedications.sqf create mode 100644 addons/medical_vitals/functions/fnc_updateBloodPressure.sqf create mode 100644 addons/medical_vitals/functions/fnc_updateState.sqf diff --git a/addons/medical_status/XEH_PREP.hpp b/addons/medical_status/XEH_PREP.hpp index 967332da2e2..215b45b1432 100644 --- a/addons/medical_status/XEH_PREP.hpp +++ b/addons/medical_status/XEH_PREP.hpp @@ -4,7 +4,6 @@ PREP(adjustPainLevel); PREP(getAllMedicationCount); PREP(getBloodLoss); PREP(getBloodPressure); -PREP(getBloodVolumeChange); PREP(getCardiacOutput); PREP(getMedicationCount); PREP(handleKilled); diff --git a/addons/medical_status/functions/fnc_getBloodVolumeChange.sqf b/addons/medical_status/functions/fnc_getBloodVolumeChange.sqf deleted file mode 100644 index 88e85d2c963..00000000000 --- a/addons/medical_status/functions/fnc_getBloodVolumeChange.sqf +++ /dev/null @@ -1,53 +0,0 @@ -#include "..\script_component.hpp" -/* - * Author: Glowbal - * Calculates the blood volume change and decreases the IVs given to the unit. - * - * Arguments: - * 0: The Unit - * 1: Time since last update - * 2: Global Sync Values (bloodbags) - * - * Return Value: - * Blood volume change (liters per second) - * - * Example: - * [player, 1, true] call ace_medical_status_fnc_getBloodVolumeChange - * - * Public: No - */ - -params ["_unit", "_deltaT", "_syncValues"]; - -private _bloodVolumeChange = -_deltaT * GET_BLOOD_LOSS(_unit); - -if (!isNil {_unit getVariable QEGVAR(medical,ivBags)}) then { - private _bloodBags = _unit getVariable [QEGVAR(medical,ivBags), []]; - private _tourniquets = GET_TOURNIQUETS(_unit); - - _bloodBags = _bloodBags apply { - _x params ["_bagVolumeRemaining", "_type", "_bodyPart", "_classname", "_rateCoef"]; - - if (_tourniquets select _bodyPart == 0) then { - private _bagChange = (_deltaT * EGVAR(medical,ivFlowRate) * IV_CHANGE_PER_SECOND * _rateCoef) min _bagVolumeRemaining; // absolute value of the change in miliLiters - _bagVolumeRemaining = _bagVolumeRemaining - _bagChange; - _bloodVolumeChange = _bloodVolumeChange + (_bagChange / 1000); - }; - - if (_bagVolumeRemaining < 0.01) then { - [] - } else { - [_bagVolumeRemaining, _type, _bodyPart, _classname, _rateCoef] - }; - }; - - _bloodBags = _bloodBags - [[]]; // remove empty bags - - if (_bloodBags isEqualTo []) then { - _unit setVariable [QEGVAR(medical,ivBags), nil, true]; // no bags left - clear variable (always globaly sync this) - } else { - _unit setVariable [QEGVAR(medical,ivBags), _bloodBags, _syncValues]; - }; -}; - -_bloodVolumeChange diff --git a/addons/medical_vitals/XEH_PREP.hpp b/addons/medical_vitals/XEH_PREP.hpp index 02f1cc5f899..f8a1439b341 100644 --- a/addons/medical_vitals/XEH_PREP.hpp +++ b/addons/medical_vitals/XEH_PREP.hpp @@ -1,3 +1,5 @@ +PREP(consumeIVs); +PREP(consumeMedications); PREP(handleUnitVitals); PREP(scanConfig); PREP(updateHeartRate); diff --git a/addons/medical_vitals/XEH_preInit.sqf b/addons/medical_vitals/XEH_preInit.sqf index 8cc49805e92..9de7918c29d 100644 --- a/addons/medical_vitals/XEH_preInit.sqf +++ b/addons/medical_vitals/XEH_preInit.sqf @@ -9,5 +9,6 @@ PREP_RECOMPILE_END; #include "initSettings.inc.sqf" GVAR(oxygenSupplyConditionCache) = uiNamespace getVariable QGVAR(oxygenSupplyConditionCache); +GVAR(deferredEvents) = createHashMap; ADDON = true; diff --git a/addons/medical_vitals/functions/fnc_consumeIVs.sqf b/addons/medical_vitals/functions/fnc_consumeIVs.sqf new file mode 100644 index 00000000000..a675fd4a736 --- /dev/null +++ b/addons/medical_vitals/functions/fnc_consumeIVs.sqf @@ -0,0 +1,60 @@ +#include "..\script_component.hpp" +/* + * Author: Glowbal, LinkIsGrim + * Calculates fluid intake and consumes unit's IVs. + * + * Arguments: + * 0: The Unit + * 1: Time since last update + * 2: Global Sync Values (IVs) + * + * Return Value: + * Blood volume change (liters per second) + * + * Example: + * [player, 1, true] call ace_medical_vitals_fnc_consumeIVs + * + * Public: No + */ + +params ["_unit", "_deltaT", "_syncValues"]; + +private _ivBags = _unit getVariable [QEGVAR(medical,ivBags), []]; + +if (_ivBags isEqualTo []) exitWith {0}; + +private _tourniquets = GET_TOURNIQUETS(_unit); +private _bloodVolumeChange = 0; +private _consumedIVs = []; + +{ + _x params ["_bagVolumeRemaining", "_type", "_bodyPartIndex", "_classname", "_rateCoef"]; + + if (_tourniquets select _bodyPartIndex > 0) then { + continue + }; + + private _bagChange = (_deltaT * EGVAR(medical,ivFlowRate) * IV_CHANGE_PER_SECOND * _rateCoef) min _bagVolumeRemaining; // absolute value of the change in miliLiters + _bagVolumeRemaining = _bagVolumeRemaining - _bagChange; + _consumedIVs pushBack [_type, _classname, _bagChange]; + + if (_type in ["Blood", "Plasma", "Saline"]) then { + _bloodVolumeChange = _bloodVolumeChange + (_bagChange / 1000); + }; + + if (_bagVolumeRemaining >= 0.01) then { + _x set [0, _bagVolumeRemaining]; + } else { + _ivBags deleteAt _forEachIndex; + }; +} forEachReversed _ivBags; + +(GVAR(deferredEvents) getOrDefault [_unit, [], true]) pushBack ([QEGVAR(medical,consumedIVs), [_unit, _consumedIVs]]); + +if (_ivBags isEqualTo []) then { + _unit setVariable [QEGVAR(medical,ivBags), nil, true]; +} else { + _unit setVariable [QEGVAR(medical,ivBags), _ivBags, _syncValues]; +}; + +_bloodVolumeChange // return diff --git a/addons/medical_vitals/functions/fnc_consumeMedications.sqf b/addons/medical_vitals/functions/fnc_consumeMedications.sqf new file mode 100644 index 00000000000..e4ca785dc8b --- /dev/null +++ b/addons/medical_vitals/functions/fnc_consumeMedications.sqf @@ -0,0 +1,61 @@ +#include "..\script_component.hpp" +/* + * Author: Glowbal, LinkIsGrim + * Consumes unit's medications and update relevant vitals + * + * Arguments: + * 0: The Unit + * 1: Time since last update + * 2: Global Sync Values (medications) + * + * Return Value: + * Values should be synced + * + * Example: + * [player, 1, true] call ace_medical_vitals_fnc_consumeMedications + * + * Public: No + */ + +params ["_unit", "_deltaT", "_syncValues"]; + +private _medications = _unit getVariable [VAR_MEDICATIONS, []]; + +if (_medications isEqualTo []) exitWith { + [0, 0, 0, false] +}; + +private _hrTargetAdjustment = 0; +private _painSupressAdjustment = 0; +private _peripheralResistanceAdjustment = 0; +private _consumedMedications = []; + +{ + _x params ["_medication", "_timeAdded", "_timeTillMaxEffect", "_maxTimeInSystem", "_hrAdjust", "_painAdjust", "_flowAdjust"]; + + private _timeInSystem = CBA_missionTime - _timeAdded; + if (_timeInSystem >= _maxTimeInSystem) then { + _syncValues = true; + _adjustments deleteAt _forEachIndex; + } else { + private _effectRatio = (((_timeInSystem / _timeTillMaxEffect) ^ 2) min 1) * (_maxTimeInSystem - _timeInSystem) / _maxTimeInSystem; + + _consumedMedications pushBack [_medication, _effectRatio]; + + if (_hrAdjust != 0) then { _hrTargetAdjustment = _hrTargetAdjustment + _hrAdjust * _effectRatio; }; + if (_painAdjust != 0) then { _painSupressAdjustment = _painSupressAdjustment + _painAdjust * _effectRatio; }; + if (_flowAdjust != 0) then { _peripheralResistanceAdjustment = _peripheralResistanceAdjustment + _flowAdjust * _effectRatio; }; + }; +} forEachReversed _medications; + +(GVAR(deferredEvents) getOrDefault [_unit, [], true]) pushBack ([QEGVAR(medical,consumeMedications), [_unit, _consumedMedications]]); + +if (_syncValues) then { + _unit setVariable [VAR_MEDICATIONS, _medications, true] +}; + +[_unit, _hrTargetAdjustment, _deltaT, _syncValues] call FUNC(updateHeartRate); +[_unit, _painSupressAdjustment, _deltaT, _syncValues] call FUNC(updatePainSuppress); +[_unit, _peripheralResistanceAdjustment, _deltaT, _syncValues] call FUNC(updatePeripheralResistance); + +_syncValues // return diff --git a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf index 77aec7fd621..254d1ab91a0 100644 --- a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf +++ b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf @@ -34,32 +34,15 @@ if (_syncValues) then { // Update SPO2 intake and usage since last update [_unit, _deltaT, _syncValues] call FUNC(updateOxygen); -private _bloodVolume = GET_BLOOD_VOLUME(_unit) + ([_unit, _deltaT, _syncValues] call EFUNC(medical_status,getBloodVolumeChange)); +private _bleeding = -_deltaT * GET_BLOOD_LOSS(_unit); +private _ivChange = [_unit, _deltaT, _syncValues] call FUNC(consumeIVs); + +private _bloodVolume = GET_BLOOD_VOLUME(_unit) + _bleeding + _ivChange; _bloodVolume = 0 max _bloodVolume min DEFAULT_BLOOD_VOLUME; // @todo: replace this and the rest of the setVariable with EFUNC(common,setApproximateVariablePublic) _unit setVariable [VAR_BLOOD_VOL, _bloodVolume, _syncValues]; -// Set variables for synchronizing information across the net -private _hemorrhage = switch (true) do { - case (_bloodVolume < BLOOD_VOLUME_CLASS_4_HEMORRHAGE): { 4 }; - case (_bloodVolume < BLOOD_VOLUME_CLASS_3_HEMORRHAGE): { 3 }; - case (_bloodVolume < BLOOD_VOLUME_CLASS_2_HEMORRHAGE): { 2 }; - case (_bloodVolume < BLOOD_VOLUME_CLASS_1_HEMORRHAGE): { 1 }; - default {0}; -}; - -if (_hemorrhage != GET_HEMORRHAGE(_unit)) then { - _unit setVariable [VAR_HEMORRHAGE, _hemorrhage, true]; -}; - -private _woundBloodLoss = GET_WOUND_BLEEDING(_unit); - -private _inPain = GET_PAIN_PERCEIVED(_unit) > 0; -if (_inPain isNotEqualTo IS_IN_PAIN(_unit)) then { - _unit setVariable [VAR_IN_PAIN, _inPain, true]; -}; - // Handle pain due tourniquets, that have been applied more than 120 s ago private _tourniquetPain = 0; private _tourniquets = GET_TOURNIQUETS(_unit); @@ -72,103 +55,27 @@ if (_tourniquetPain > 0) then { [_unit, _tourniquetPain] call EFUNC(medical_status,adjustPainLevel); }; -// Get Medication Adjustments: -private _hrTargetAdjustment = 0; -private _painSupressAdjustment = 0; -private _peripheralResistanceAdjustment = 0; -private _adjustments = _unit getVariable [VAR_MEDICATIONS,[]]; - -if (_adjustments isNotEqualTo []) then { - private _deleted = false; - { - _x params ["_medication", "_timeAdded", "_timeTillMaxEffect", "_maxTimeInSystem", "_hrAdjust", "_painAdjust", "_flowAdjust"]; - private _timeInSystem = CBA_missionTime - _timeAdded; - if (_timeInSystem >= _maxTimeInSystem) then { - _deleted = true; - _adjustments deleteAt _forEachIndex; - } else { - private _effectRatio = (((_timeInSystem / _timeTillMaxEffect) ^ 2) min 1) * (_maxTimeInSystem - _timeInSystem) / _maxTimeInSystem; - if (_hrAdjust != 0) then { _hrTargetAdjustment = _hrTargetAdjustment + _hrAdjust * _effectRatio; }; - if (_painAdjust != 0) then { _painSupressAdjustment = _painSupressAdjustment + _painAdjust * _effectRatio; }; - if (_flowAdjust != 0) then { _peripheralResistanceAdjustment = _peripheralResistanceAdjustment + _flowAdjust * _effectRatio; }; - }; - } forEachReversed _adjustments; - - if (_deleted) then { - _unit setVariable [VAR_MEDICATIONS, _adjustments, true]; - _syncValues = true; - }; -}; +// Consume medications +_syncValues = [_unit, _deltaT, _syncValues] call FUNC(consumeMedications); -private _heartRate = [_unit, _hrTargetAdjustment, _deltaT, _syncValues] call FUNC(updateHeartRate); -[_unit, _painSupressAdjustment, _deltaT, _syncValues] call FUNC(updatePainSuppress); -[_unit, _peripheralResistanceAdjustment, _deltaT, _syncValues] call FUNC(updatePeripheralResistance); +// Update blood presure +[_unit, _syncValues] call FUNC(updateBloodPressure); -private _bloodPressure = GET_BLOOD_PRESSURE(_unit); -_unit setVariable [VAR_BLOOD_PRESS, _bloodPressure, _syncValues]; +// Consume IVs +[_unit, _deltaT] call FUNC(consumeIVs); -_bloodPressure params ["_bloodPressureL", "_bloodPressureH"]; +// Update statemachine and status variables +_unit call FUNC(updateState); -// Statements are ordered by most lethal first. -switch (true) do { - case (_bloodVolume < BLOOD_VOLUME_FATAL): { - TRACE_3("BloodVolume Fatal",_unit,BLOOD_VOLUME_FATAL,_bloodVolume); - [QEGVAR(medical,Bleedout), _unit] call CBA_fnc_localEvent; - }; - case (IN_CRDC_ARRST(_unit)): {}; // if in cardiac arrest just break now to avoid throwing unneeded events - case (_hemorrhage == 4): { - TRACE_3("Class IV Hemorrhage",_unit,_hemorrhage,_bloodVolume); - [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; - }; - case (_heartRate < 20 || {_heartRate > 220}): { - TRACE_2("heartRate Fatal",_unit,_heartRate); - [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; - }; - case (_bloodPressureH < 50 && {_bloodPressureL < 40} && {_heartRate < 40}): { - TRACE_4("bloodPressure (H & L) + heartRate Fatal",_unit,_bloodPressureH,_bloodPressureL,_heartRate); - [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; - }; - case (_bloodPressureL >= 190): { - TRACE_2("bloodPressure L above limits",_unit,_bloodPressureL); - [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; - }; - case (_heartRate < 30): { // With a heart rate below 30 but bigger than 20 there is a chance to enter the cardiac arrest state - private _nextCheck = _unit getVariable [QGVAR(nextCheckCriticalHeartRate), CBA_missionTime]; - private _enterCardiacArrest = false; - if (CBA_missionTime >= _nextCheck) then { - _enterCardiacArrest = random 1 < (0.4 + 0.6*(30 - _heartRate)/10); // Variable chance of getting into cardiac arrest. - _unit setVariable [QGVAR(nextCheckCriticalHeartRate), CBA_missionTime + 5]; - }; - if (_enterCardiacArrest) then { - TRACE_2("Heart rate critical. Cardiac arrest",_unit,_heartRate); - [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; - } else { - TRACE_2("Heart rate critical. Critical vitals",_unit,_heartRate); - [QEGVAR(medical,CriticalVitals), _unit] call CBA_fnc_localEvent; - }; - }; - case (_woundBloodLoss > BLOOD_LOSS_KNOCK_OUT_THRESHOLD): { - [QEGVAR(medical,CriticalVitals), _unit] call CBA_fnc_localEvent; - }; - case (_woundBloodLoss > 0): { - [QEGVAR(medical,LoweredVitals), _unit] call CBA_fnc_localEvent; - }; - case (_inPain): { - [QEGVAR(medical,LoweredVitals), _unit] call CBA_fnc_localEvent; - }; -}; +END_COUNTER(Vitals); -#ifdef DEBUG_MODE_FULL -private _cardiacOutput = [_unit] call EFUNC(medical_status,getCardiacOutput); -if (!isPlayer _unit) then { - private _painLevel = _unit getVariable [VAR_PAIN, 0]; - hintSilent format["blood volume: %1, blood loss: [%2, %3]\nhr: %4, bp: %5, pain: %6", round(_bloodVolume * 100) / 100, round(_woundBloodLoss * 1000) / 1000, round((_woundBloodLoss / (0.001 max _cardiacOutput)) * 100) / 100, round(_heartRate), _bloodPressure, round(_painLevel * 100) / 100]; -}; -#endif +//placed outside the counter as 3rd-party code may be called from these events +{ + _x call CBA_fnc_localEvent; +} forEach (GVAR(deferredEvents) getOrDefault [_unit, []]); -END_COUNTER(Vitals); +GVAR(deferredEvents) deleteAt _unit; -//placed outside the counter as 3rd-party code may be called from this event [QEGVAR(medical,handleUnitVitals), [_unit, _deltaT]] call CBA_fnc_localEvent; true diff --git a/addons/medical_vitals/functions/fnc_updateBloodPressure.sqf b/addons/medical_vitals/functions/fnc_updateBloodPressure.sqf new file mode 100644 index 00000000000..84997b993db --- /dev/null +++ b/addons/medical_vitals/functions/fnc_updateBloodPressure.sqf @@ -0,0 +1,4 @@ +params ["_unit", "_syncValues"]; + +private _bloodPressure = GET_BLOOD_PRESSURE(_unit); +_unit setVariable [VAR_BLOOD_PRESS, _bloodPressure, _syncValues]; diff --git a/addons/medical_vitals/functions/fnc_updateHeartRate.sqf b/addons/medical_vitals/functions/fnc_updateHeartRate.sqf index 0390a9ad076..cd68f2bfc25 100644 --- a/addons/medical_vitals/functions/fnc_updateHeartRate.sqf +++ b/addons/medical_vitals/functions/fnc_updateHeartRate.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: Glowbal - * Update the heart rate + * Update unit's heart rate * * Arguments: * 0: The Unit @@ -9,8 +9,8 @@ * 2: Time since last update * 3: Sync value? * - * ReturnValue: - * Current Heart Rate + * Return Value: + * None * * Example: * [player, 0, 1, false] call ace_medical_vitals_fnc_updateHeartRate diff --git a/addons/medical_vitals/functions/fnc_updateState.sqf b/addons/medical_vitals/functions/fnc_updateState.sqf new file mode 100644 index 00000000000..2dffd41106d --- /dev/null +++ b/addons/medical_vitals/functions/fnc_updateState.sqf @@ -0,0 +1,75 @@ +params ["_unit", "_syncValues"]; + +private _bloodVolume = GET_BLOOD_VOLUME(_unit); +// Set variables for synchronizing information across the net + +private _hemorrhage = switch (true) do { + case (_bloodVolume < BLOOD_VOLUME_CLASS_4_HEMORRHAGE): { 4 }; + case (_bloodVolume < BLOOD_VOLUME_CLASS_3_HEMORRHAGE): { 3 }; + case (_bloodVolume < BLOOD_VOLUME_CLASS_2_HEMORRHAGE): { 2 }; + case (_bloodVolume < BLOOD_VOLUME_CLASS_1_HEMORRHAGE): { 1 }; + default {0}; +}; + +if (_hemorrhage != GET_HEMORRHAGE(_unit)) then { + _unit setVariable [VAR_HEMORRHAGE, _hemorrhage, true]; +}; + +private _inPain = GET_PAIN_PERCEIVED(_unit) > 0; +if (_inPain isNotEqualTo IS_IN_PAIN(_unit)) then { + _unit setVariable [VAR_IN_PAIN, _inPain, true]; +}; + +private _heartRate = GET_HEART_RATE(_unit); +private _bloodPressure = _unit getVariable [VAR_BLOOD_PRESS, [80, 120]]; + +_bloodPressure params ["_bloodPressureL", "_bloodPressureH"]; + +// Statements are ordered by most lethal first. +switch (true) do { + case (_bloodVolume < BLOOD_VOLUME_FATAL): { + TRACE_3("BloodVolume Fatal",_unit,BLOOD_VOLUME_FATAL,_bloodVolume); + [QEGVAR(medical,Bleedout), _unit] call CBA_fnc_localEvent; + }; + case (IN_CRDC_ARRST(_unit)): {}; // if in cardiac arrest just break now to avoid throwing unneeded events + case (_hemorrhage == 4): { + TRACE_3("Class IV Hemorrhage",_unit,_hemorrhage,_bloodVolume); + [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; + }; + case (_heartRate < 20 || {_heartRate > 220}): { + TRACE_2("heartRate Fatal",_unit,_heartRate); + [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; + }; + case (_bloodPressureH < 50 && {_bloodPressureL < 40} && {_heartRate < 40}): { + TRACE_4("bloodPressure (H & L) + heartRate Fatal",_unit,_bloodPressureH,_bloodPressureL,_heartRate); + [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; + }; + case (_bloodPressureL >= 190): { + TRACE_2("bloodPressure L above limits",_unit,_bloodPressureL); + [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; + }; + case (_heartRate < 30): { // With a heart rate below 30 but bigger than 20 there is a chance to enter the cardiac arrest state + private _nextCheck = _unit getVariable [QGVAR(nextCheckCriticalHeartRate), CBA_missionTime]; + private _enterCardiacArrest = false; + if (CBA_missionTime >= _nextCheck) then { + _enterCardiacArrest = random 1 < (0.4 + 0.6*(30 - _heartRate)/10); // Variable chance of getting into cardiac arrest. + _unit setVariable [QGVAR(nextCheckCriticalHeartRate), CBA_missionTime + 5]; + }; + if (_enterCardiacArrest) then { + TRACE_2("Heart rate critical. Cardiac arrest",_unit,_heartRate); + [QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent; + } else { + TRACE_2("Heart rate critical. Critical vitals",_unit,_heartRate); + [QEGVAR(medical,CriticalVitals), _unit] call CBA_fnc_localEvent; + }; + }; + case (_woundBloodLoss > BLOOD_LOSS_KNOCK_OUT_THRESHOLD): { + [QEGVAR(medical,CriticalVitals), _unit] call CBA_fnc_localEvent; + }; + case (_woundBloodLoss > 0): { + [QEGVAR(medical,LoweredVitals), _unit] call CBA_fnc_localEvent; + }; + case (_inPain): { + [QEGVAR(medical,LoweredVitals), _unit] call CBA_fnc_localEvent; + }; +}; From dee674b3d7edddc658cacd763f9fc0a8b63211a1 Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:09:54 -0300 Subject: [PATCH 02/11] headers/includes --- .../functions/fnc_updateBloodPressure.sqf | 18 ++++++++++++++++++ .../functions/fnc_updateState.sqf | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/addons/medical_vitals/functions/fnc_updateBloodPressure.sqf b/addons/medical_vitals/functions/fnc_updateBloodPressure.sqf index 84997b993db..7df1cdf4173 100644 --- a/addons/medical_vitals/functions/fnc_updateBloodPressure.sqf +++ b/addons/medical_vitals/functions/fnc_updateBloodPressure.sqf @@ -1,3 +1,21 @@ +#include "..\script_component.hpp" +/* + * Author: LinkIsGrim + * Update unit blood pressure + * + * Arguments: + * 0: The Unit + * 1: Sync value? + * + * Return Value: + * None + * + * Example: + * [player, false] call ace_medical_vitals_fnc_updateBloodPressure + * + * Public: No + */ + params ["_unit", "_syncValues"]; private _bloodPressure = GET_BLOOD_PRESSURE(_unit); diff --git a/addons/medical_vitals/functions/fnc_updateState.sqf b/addons/medical_vitals/functions/fnc_updateState.sqf index 2dffd41106d..d63cf8e5885 100644 --- a/addons/medical_vitals/functions/fnc_updateState.sqf +++ b/addons/medical_vitals/functions/fnc_updateState.sqf @@ -1,3 +1,21 @@ +#include "..\script_component.hpp" +/* + * Author: LinkIsGrim + * Update unit state and status variables + * + * Arguments: + * 0: The Unit + * 1: Sync value? + * + * Return Value: + * None + * + * Example: + * [player, false] call ace_medical_vitals_fnc_updateState + * + * Public: No + */ + params ["_unit", "_syncValues"]; private _bloodVolume = GET_BLOOD_VOLUME(_unit); From d248f18b4e7ff61a753d84bb9cf9d05e0f38cec8 Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Tue, 17 Dec 2024 19:13:51 -0300 Subject: [PATCH 03/11] PREP --- addons/medical_vitals/XEH_PREP.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/medical_vitals/XEH_PREP.hpp b/addons/medical_vitals/XEH_PREP.hpp index f8a1439b341..88a78c9eaad 100644 --- a/addons/medical_vitals/XEH_PREP.hpp +++ b/addons/medical_vitals/XEH_PREP.hpp @@ -2,7 +2,9 @@ PREP(consumeIVs); PREP(consumeMedications); PREP(handleUnitVitals); PREP(scanConfig); +PREP(updateBloodPressure); PREP(updateHeartRate); PREP(updateOxygen); PREP(updatePainSuppress); PREP(updatePeripheralResistance); +PREP(updateState); From a2cae4ef1c1227b4c96d16c1c9c0b8fdcb4b8add Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Wed, 18 Dec 2024 13:02:32 -0300 Subject: [PATCH 04/11] fix undefined variables --- addons/medical_vitals/functions/fnc_consumeMedications.sqf | 2 +- addons/medical_vitals/functions/fnc_updateState.sqf | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/medical_vitals/functions/fnc_consumeMedications.sqf b/addons/medical_vitals/functions/fnc_consumeMedications.sqf index e4ca785dc8b..f9bd5d8071e 100644 --- a/addons/medical_vitals/functions/fnc_consumeMedications.sqf +++ b/addons/medical_vitals/functions/fnc_consumeMedications.sqf @@ -36,7 +36,7 @@ private _consumedMedications = []; private _timeInSystem = CBA_missionTime - _timeAdded; if (_timeInSystem >= _maxTimeInSystem) then { _syncValues = true; - _adjustments deleteAt _forEachIndex; + _medications deleteAt _forEachIndex; } else { private _effectRatio = (((_timeInSystem / _timeTillMaxEffect) ^ 2) min 1) * (_maxTimeInSystem - _timeInSystem) / _maxTimeInSystem; diff --git a/addons/medical_vitals/functions/fnc_updateState.sqf b/addons/medical_vitals/functions/fnc_updateState.sqf index d63cf8e5885..063b9d77617 100644 --- a/addons/medical_vitals/functions/fnc_updateState.sqf +++ b/addons/medical_vitals/functions/fnc_updateState.sqf @@ -39,6 +39,7 @@ if (_inPain isNotEqualTo IS_IN_PAIN(_unit)) then { }; private _heartRate = GET_HEART_RATE(_unit); +private _woundBloodLoss = GET_WOUND_BLEEDING(_unit); private _bloodPressure = _unit getVariable [VAR_BLOOD_PRESS, [80, 120]]; _bloodPressure params ["_bloodPressureL", "_bloodPressureH"]; From 84b8b76336e81808a2c7d607c01d5d90886742c7 Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Wed, 18 Dec 2024 13:22:01 -0300 Subject: [PATCH 05/11] fix double IV consumption, missing arg --- addons/medical_vitals/functions/fnc_handleUnitVitals.sqf | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf index 254d1ab91a0..0423f8e464b 100644 --- a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf +++ b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf @@ -61,11 +61,8 @@ _syncValues = [_unit, _deltaT, _syncValues] call FUNC(consumeMedications); // Update blood presure [_unit, _syncValues] call FUNC(updateBloodPressure); -// Consume IVs -[_unit, _deltaT] call FUNC(consumeIVs); - // Update statemachine and status variables -_unit call FUNC(updateState); +[_unit, _syncValues] call FUNC(updateState); END_COUNTER(Vitals); From 2a16a5d7e78361635fb012ccea9accd48f9aa7e9 Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Wed, 18 Dec 2024 13:41:58 -0300 Subject: [PATCH 06/11] extract blood volume and pain update --- .../medical_engine/script_macros_medical.hpp | 6 ++++ addons/medical_vitals/XEH_PREP.hpp | 2 ++ .../functions/fnc_handleUnitVitals.sqf | 23 +++----------- .../functions/fnc_updateBloodVolume.sqf | 29 ++++++++++++++++++ .../functions/fnc_updatePain.sqf | 30 +++++++++++++++++++ 5 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 addons/medical_vitals/functions/fnc_updateBloodVolume.sqf create mode 100644 addons/medical_vitals/functions/fnc_updatePain.sqf diff --git a/addons/medical_engine/script_macros_medical.hpp b/addons/medical_engine/script_macros_medical.hpp index 167765c5767..e74282d00d9 100644 --- a/addons/medical_engine/script_macros_medical.hpp +++ b/addons/medical_engine/script_macros_medical.hpp @@ -132,6 +132,12 @@ #define DEFAULT_TOURNIQUET_VALUES [0,0,0,0,0,0] +// Time until a tourniquet starts causing pain +#define TOURNIQUET_MIN_TIME_FOR_PAIN 120 + +// How much pain a tourniquet will cause per second after TOURNIQUET_MIN_TIME_FOR_PAIN +#define TOURNIQUET_PAIN_PER_SECOND 0.001 + #define DEFAULT_FRACTURE_VALUES [0,0,0,0,0,0] // Triage colors, for consistency across UIs and functions diff --git a/addons/medical_vitals/XEH_PREP.hpp b/addons/medical_vitals/XEH_PREP.hpp index 88a78c9eaad..944b3ac881d 100644 --- a/addons/medical_vitals/XEH_PREP.hpp +++ b/addons/medical_vitals/XEH_PREP.hpp @@ -3,8 +3,10 @@ PREP(consumeMedications); PREP(handleUnitVitals); PREP(scanConfig); PREP(updateBloodPressure); +PREP(updateBloodVolume); PREP(updateHeartRate); PREP(updateOxygen); +PREP(updatePain); PREP(updatePainSuppress); PREP(updatePeripheralResistance); PREP(updateState); diff --git a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf index 0423f8e464b..e5ec75318dd 100644 --- a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf +++ b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf @@ -34,26 +34,11 @@ if (_syncValues) then { // Update SPO2 intake and usage since last update [_unit, _deltaT, _syncValues] call FUNC(updateOxygen); -private _bleeding = -_deltaT * GET_BLOOD_LOSS(_unit); -private _ivChange = [_unit, _deltaT, _syncValues] call FUNC(consumeIVs); +// Update blood volume +[_unit, _deltaT, _syncValues] call FUNC(updateBloodVolume); -private _bloodVolume = GET_BLOOD_VOLUME(_unit) + _bleeding + _ivChange; -_bloodVolume = 0 max _bloodVolume min DEFAULT_BLOOD_VOLUME; - -// @todo: replace this and the rest of the setVariable with EFUNC(common,setApproximateVariablePublic) -_unit setVariable [VAR_BLOOD_VOL, _bloodVolume, _syncValues]; - -// Handle pain due tourniquets, that have been applied more than 120 s ago -private _tourniquetPain = 0; -private _tourniquets = GET_TOURNIQUETS(_unit); -{ - if (_x > 0 && {CBA_missionTime - _x > 120}) then { - _tourniquetPain = _tourniquetPain max (CBA_missionTime - _x - 120) * 0.001; - }; -} forEach _tourniquets; -if (_tourniquetPain > 0) then { - [_unit, _tourniquetPain] call EFUNC(medical_status,adjustPainLevel); -}; +// Update pain (currently only tourniquets) +[_unit, _syncValues] call FUNC(updatePain); // Consume medications _syncValues = [_unit, _deltaT, _syncValues] call FUNC(consumeMedications); diff --git a/addons/medical_vitals/functions/fnc_updateBloodVolume.sqf b/addons/medical_vitals/functions/fnc_updateBloodVolume.sqf new file mode 100644 index 00000000000..071aef140bd --- /dev/null +++ b/addons/medical_vitals/functions/fnc_updateBloodVolume.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: LinkIsGrim + * Update unit blood volume + * + * Arguments: + * 0: The Unit + * 1: Time since last update + * 2: Sync value? + * + * Return Value: + * None + * + * Example: + * [player, 5, false] call ace_medical_vitals_fnc_updateBloodVolume + * + * Public: No + */ + +params ["_unit", "_deltaT", "_syncValues"]; + +private _bleeding = -_deltaT * GET_BLOOD_LOSS(_unit); +private _ivChange = [_unit, _deltaT, _syncValues] call FUNC(consumeIVs); + +private _bloodVolume = GET_BLOOD_VOLUME(_unit) + _bleeding + _ivChange; +_bloodVolume = 0 max _bloodVolume min DEFAULT_BLOOD_VOLUME; + +// @todo: replace this and the rest of the setVariable with EFUNC(common,setApproximateVariablePublic) +_unit setVariable [VAR_BLOOD_VOL, _bloodVolume, _syncValues]; diff --git a/addons/medical_vitals/functions/fnc_updatePain.sqf b/addons/medical_vitals/functions/fnc_updatePain.sqf new file mode 100644 index 00000000000..b854198aac8 --- /dev/null +++ b/addons/medical_vitals/functions/fnc_updatePain.sqf @@ -0,0 +1,30 @@ +#include "..\script_component.hpp" +/* + * Author: LinkIsGrim + * Update unit pain + * + * Arguments: + * 0: The Unit + * 1: Sync value? + * + * Return Value: + * None + * + * Example: + * [player, false] call ace_medical_vitals_fnc_updatePain + * + * Public: No + */ + +params ["_unit", "_syncValues"]; + +// Handle pain due tourniquets, that have been applied more than 120 s ago +private _tourniquets = GET_TOURNIQUETS(_unit); + +private _oldestTourniquetTime = selectMin _tourniquets; +if (_oldestTourniquetTime == 0) exitWith {}; + +private _tourniquetPainSeconds = CBA_missionTime - _oldestTourniquetTime - TOURNIQUET_MIN_TIME_FOR_PAIN; +if (_tourniquetPainSeconds <= 0) exitWith {}; + +[_unit, _tourniquetPainSeconds * TOURNIQUET_PAIN_PER_SECOND] call EFUNC(medical_status,adjustPainLevel); From 302a83cddc53f9d8635f6cceb43182d3553631d0 Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Wed, 18 Dec 2024 13:45:00 -0300 Subject: [PATCH 07/11] fix tourniquet logic --- addons/medical_vitals/functions/fnc_updatePain.sqf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/medical_vitals/functions/fnc_updatePain.sqf b/addons/medical_vitals/functions/fnc_updatePain.sqf index b854198aac8..433a62c6083 100644 --- a/addons/medical_vitals/functions/fnc_updatePain.sqf +++ b/addons/medical_vitals/functions/fnc_updatePain.sqf @@ -19,11 +19,10 @@ params ["_unit", "_syncValues"]; // Handle pain due tourniquets, that have been applied more than 120 s ago -private _tourniquets = GET_TOURNIQUETS(_unit); +private _activeTourniquets = GET_TOURNIQUETS(_unit) - [0]; +if (_activeTourniquets isEqualTo []) exitWith {}; private _oldestTourniquetTime = selectMin _tourniquets; -if (_oldestTourniquetTime == 0) exitWith {}; - private _tourniquetPainSeconds = CBA_missionTime - _oldestTourniquetTime - TOURNIQUET_MIN_TIME_FOR_PAIN; if (_tourniquetPainSeconds <= 0) exitWith {}; From 8cea4893a02cb8131cd8c8b9f05f8b4e2f1c08e6 Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Wed, 18 Dec 2024 17:44:23 -0300 Subject: [PATCH 08/11] refactor updateWoundBloodLoss --- .../functions/fnc_updateWoundBloodLoss.sqf | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf b/addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf index 86963496422..e5b140bce68 100644 --- a/addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf +++ b/addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf @@ -23,24 +23,26 @@ private _bodyPartBleeding = [0,0,0,0,0,0]; { private _partIndex = ALL_BODY_PARTS find _x; if (_tourniquets select _partIndex == 0) then { + private _partBleeding = 0; { _x params ["", "_amountOf", "_bleeeding"]; - _bodyPartBleeding set [_partIndex, (_bodyPartBleeding select _partIndex) + (_amountOf * _bleeeding)]; + _partBleeding = _partBleeding + (_amountOf * _bleeding); } forEach _y; + _bodyPartBleeding set [_partIndex, _partBleeding]; }; } forEach GET_OPEN_WOUNDS(_unit); -if (_bodyPartBleeding isEqualTo [0,0,0,0,0,0]) then { +if (selectMax _bodyPartBleeding == 0) exitWith { TRACE_1("updateWoundBloodLoss-none",_unit); _unit setVariable [VAR_WOUND_BLEEDING, 0, true]; -} else { - _bodyPartBleeding params ["_headBleeding", "_bodyBleeding", "_leftArmBleeding", "_rightArmBleeding", "_leftLegBleeding", "_rightLegBleeding"]; - private _bodyBleedingRate = ((_headBleeding min 0.9) + (_bodyBleeding min 1.0)) min 1.0; - private _limbBleedingRate = ((_leftArmBleeding min 0.3) + (_rightArmBleeding min 0.3) + (_leftLegBleeding min 0.5) + (_rightLegBleeding min 0.5)) min 1.0; +}; - // limb bleeding is scaled down based on the amount of body bleeding - _limbBleedingRate = _limbBleedingRate * (1 - _bodyBleedingRate); +_bodyPartBleeding params ["_headBleeding", "_bodyBleeding", "_leftArmBleeding", "_rightArmBleeding", "_leftLegBleeding", "_rightLegBleeding"]; +private _bodyBleedingRate = ((_headBleeding min 0.9) + (_bodyBleeding min 1.0)) min 1.0; +private _limbBleedingRate = ((_leftArmBleeding min 0.3) + (_rightArmBleeding min 0.3) + (_leftLegBleeding min 0.5) + (_rightLegBleeding min 0.5)) min 1.0; - TRACE_3("updateWoundBloodLoss-bleeding",_unit,_bodyBleedingRate,_limbBleedingRate); - _unit setVariable [VAR_WOUND_BLEEDING, _bodyBleedingRate + _limbBleedingRate, true]; -}; +// limb bleeding is scaled down based on the amount of body bleeding +_limbBleedingRate = _limbBleedingRate * (1 - _bodyBleedingRate); + +TRACE_3("updateWoundBloodLoss-bleeding",_unit,_bodyBleedingRate,_limbBleedingRate); +_unit setVariable [VAR_WOUND_BLEEDING, _bodyBleedingRate + _limbBleedingRate, true]; From ad79d95ebf04b056983f347255fca24bf0eadabf Mon Sep 17 00:00:00 2001 From: LinkIsGrim <69561145+LinkIsGrim@users.noreply.github.com> Date: Thu, 19 Dec 2024 17:48:37 -0300 Subject: [PATCH 09/11] add item back to IV array --- addons/medical_vitals/functions/fnc_consumeIVs.sqf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/medical_vitals/functions/fnc_consumeIVs.sqf b/addons/medical_vitals/functions/fnc_consumeIVs.sqf index a675fd4a736..7a939268e26 100644 --- a/addons/medical_vitals/functions/fnc_consumeIVs.sqf +++ b/addons/medical_vitals/functions/fnc_consumeIVs.sqf @@ -28,7 +28,7 @@ private _bloodVolumeChange = 0; private _consumedIVs = []; { - _x params ["_bagVolumeRemaining", "_type", "_bodyPartIndex", "_classname", "_rateCoef"]; + _x params ["_bagVolumeRemaining", "_type", "_bodyPartIndex", "_treatment", "_rateCoef", "_item"]; if (_tourniquets select _bodyPartIndex > 0) then { continue @@ -36,7 +36,7 @@ private _consumedIVs = []; private _bagChange = (_deltaT * EGVAR(medical,ivFlowRate) * IV_CHANGE_PER_SECOND * _rateCoef) min _bagVolumeRemaining; // absolute value of the change in miliLiters _bagVolumeRemaining = _bagVolumeRemaining - _bagChange; - _consumedIVs pushBack [_type, _classname, _bagChange]; + _consumedIVs pushBack [_type, _treatment, _bagChange]; if (_type in ["Blood", "Plasma", "Saline"]) then { _bloodVolumeChange = _bloodVolumeChange + (_bagChange / 1000); From a4c0ffde7758345d17752f1b02db0485772399b7 Mon Sep 17 00:00:00 2001 From: Grim <69561145+LinkIsGrim@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:48:47 -0300 Subject: [PATCH 10/11] Update addons/medical_vitals/functions/fnc_updatePain.sqf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jouni Järvinen --- addons/medical_vitals/functions/fnc_updatePain.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_vitals/functions/fnc_updatePain.sqf b/addons/medical_vitals/functions/fnc_updatePain.sqf index 433a62c6083..549a1b9f134 100644 --- a/addons/medical_vitals/functions/fnc_updatePain.sqf +++ b/addons/medical_vitals/functions/fnc_updatePain.sqf @@ -18,7 +18,7 @@ params ["_unit", "_syncValues"]; -// Handle pain due tourniquets, that have been applied more than 120 s ago +// Handle pain due to tourniquets, that have been applied more than 120 s ago private _activeTourniquets = GET_TOURNIQUETS(_unit) - [0]; if (_activeTourniquets isEqualTo []) exitWith {}; From 4e5748205de9fcb5fc3c72fc371e69a6c74d70d9 Mon Sep 17 00:00:00 2001 From: Grim <69561145+LinkIsGrim@users.noreply.github.com> Date: Sun, 5 Jan 2025 05:20:47 -0300 Subject: [PATCH 11/11] fix hashmap key --- addons/medical_vitals/functions/fnc_consumeIVs.sqf | 2 +- addons/medical_vitals/functions/fnc_consumeMedications.sqf | 2 +- addons/medical_vitals/functions/fnc_handleUnitVitals.sqf | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/medical_vitals/functions/fnc_consumeIVs.sqf b/addons/medical_vitals/functions/fnc_consumeIVs.sqf index 7a939268e26..b2aa85f3d9a 100644 --- a/addons/medical_vitals/functions/fnc_consumeIVs.sqf +++ b/addons/medical_vitals/functions/fnc_consumeIVs.sqf @@ -49,7 +49,7 @@ private _consumedIVs = []; }; } forEachReversed _ivBags; -(GVAR(deferredEvents) getOrDefault [_unit, [], true]) pushBack ([QEGVAR(medical,consumedIVs), [_unit, _consumedIVs]]); +(GVAR(deferredEvents) getOrDefault [hashValue _unit, [], true]) pushBack ([QEGVAR(medical,consumedIVs), [_unit, _consumedIVs]]); if (_ivBags isEqualTo []) then { _unit setVariable [QEGVAR(medical,ivBags), nil, true]; diff --git a/addons/medical_vitals/functions/fnc_consumeMedications.sqf b/addons/medical_vitals/functions/fnc_consumeMedications.sqf index f9bd5d8071e..7f756337d88 100644 --- a/addons/medical_vitals/functions/fnc_consumeMedications.sqf +++ b/addons/medical_vitals/functions/fnc_consumeMedications.sqf @@ -48,7 +48,7 @@ private _consumedMedications = []; }; } forEachReversed _medications; -(GVAR(deferredEvents) getOrDefault [_unit, [], true]) pushBack ([QEGVAR(medical,consumeMedications), [_unit, _consumedMedications]]); +(GVAR(deferredEvents) getOrDefault [hashValue _unit, [], true]) pushBack ([QEGVAR(medical,consumeMedications), [_unit, _consumedMedications]]); if (_syncValues) then { _unit setVariable [VAR_MEDICATIONS, _medications, true] diff --git a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf index e5ec75318dd..f1c1ca710d0 100644 --- a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf +++ b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf @@ -54,9 +54,9 @@ END_COUNTER(Vitals); //placed outside the counter as 3rd-party code may be called from these events { _x call CBA_fnc_localEvent; -} forEach (GVAR(deferredEvents) getOrDefault [_unit, []]); +} forEach (GVAR(deferredEvents) getOrDefault [hashValue _unit, []]); -GVAR(deferredEvents) deleteAt _unit; +GVAR(deferredEvents) deleteAt hashValue _unit; [QEGVAR(medical,handleUnitVitals), [_unit, _deltaT]] call CBA_fnc_localEvent;