From 4af8f5e9544a38facff1cd4757ab2706464fce78 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Sun, 28 Jul 2024 23:50:27 +0200 Subject: [PATCH] Give blood in CA if needed before doing CPR --- .../medical_ai/functions/fnc_healingLogic.sqf | 93 +++++++++++++++---- .../functions/fnc_playTreatmentAnim.sqf | 2 +- .../medical_ai/functions/fnc_requestMedic.sqf | 7 +- addons/medical_ai/stateMachine.inc.sqf | 9 +- 4 files changed, 84 insertions(+), 27 deletions(-) diff --git a/addons/medical_ai/functions/fnc_healingLogic.sqf b/addons/medical_ai/functions/fnc_healingLogic.sqf index a007b83e4c1..213d763b973 100644 --- a/addons/medical_ai/functions/fnc_healingLogic.sqf +++ b/addons/medical_ai/functions/fnc_healingLogic.sqf @@ -35,6 +35,23 @@ if (_finishTime > 0) exitWith { }; if ((_treatmentTarget == _target) && {(_treatmentEvent select [0, 1]) != "#"}) then { [_treatmentEvent, _treatmentArgs, _target] call CBA_fnc_targetEvent; + + // Splints are already logged on their own + switch (_treatmentEvent) do { + case QEGVAR(medical_treatment,bandageLocal): { + [_target, "activity", ELSTRING(medical_treatment,Activity_bandagedPatient), [[_healer, false, true] call EFUNC(common,getName)]] call EFUNC(medical_treatment,addToLog); + }; + case QEGVAR(medical_treatment,ivBagLocal): { + [_target, _treatmentArgs select 2] call EFUNC(medical_treatment,addToTriageCard); + [_target, "activity", ELSTRING(medical_treatment,Activity_gaveIV), [[_healer, false, true] call EFUNC(common,getName)]] call EFUNC(medical_treatment,addToLog); + }; + case QEGVAR(medical_treatment,medicationLocal): { + private _usedItem = ["ACE_epinephrine", "ACE_morphine"] select (_treatmentArgs select 2 == "Morphine"); + [_target, _usedItem] call EFUNC(medical_treatment,addToTriageCard); + [_target, "activity", ELSTRING(medical_treatment,Activity_usedItem), [[_healer, false, true] call EFUNC(common,getName), getText (configFile >> "CfgWeapons" >> _usedItem >> "displayName")]] call EFUNC(medical_treatment,addToLog); + }; + }; + #ifdef DEBUG_MODE_FULL INFO_4("%1->%2: %3 - %4",_healer,_target,_treatmentEvent,_treatmentArgs); systemChat format ["Applying [%1->%2]: %3", _healer, _treatmentTarget, _treatmentEvent]; @@ -75,9 +92,12 @@ private _treatmentEvent = "#none"; private _treatmentArgs = []; private _treatmentTime = 6; private _treatmentItem = ""; -switch (true) do { - case ((GET_WOUND_BLEEDING(_target) > 0) - && {([_healer, "@bandage"] call FUNC(itemCheck)) # 0}): { + +if (true) then { + if ( + (GET_WOUND_BLEEDING(_target) > 0) && + {([_healer, "@bandage"] call FUNC(itemCheck)) # 0} + ) exitWith { // Select first bleeding wound and bandage it private _selection = "?"; { @@ -94,13 +114,26 @@ switch (true) do { _treatmentArgs = [_target, _selection, "FieldDressing"]; _treatmentItem = "@bandage"; }; - case (IN_CRDC_ARRST(_target) && {EGVAR(medical_treatment,cprSuccessChanceMin) > 0}): { + + private _hasIV = ([_healer, "@iv"] call FUNC(itemCheck)) # 0; + private _bloodVolume = GET_BLOOD_VOLUME(_target); + + // If in cardiac arrest, first add some blood to injured if necessary, then do CPR (doing CPR when not enough blood is suboptimal if you have IVs) + // If healer has no IVs, allow AI to do CPR to keep injured alive + if ( + IN_CRDC_ARRST(_target) && + {EGVAR(medical_treatment,cprSuccessChanceMin) > 0} && + {!_hasIV || {_bloodVolume >= BLOOD_VOLUME_CLASS_3_HEMORRHAGE}} + ) exitWith { _treatmentEvent = QEGVAR(medical_treatment,cprLocal); _treatmentArgs = [_healer, _target]; _treatmentTime = 15; }; - case (_isMedic && {GET_BLOOD_VOLUME(_target) < MINIMUM_BLOOD_FOR_STABLE_VITALS} - && {([_healer, "@iv"] call FUNC(itemCheck)) # 0}): { + + private _needsIv = _bloodVolume < MINIMUM_BLOOD_FOR_STABLE_VITALS; + private _canGiveIv = _isMedic && _hasIV && _needsIv; + + if (_canGiveIv) then { // Check if patient's blood volume + remaining IV volume is enough to allow the patient to wake up private _totalIvVolume = 0; //in ml { @@ -108,33 +141,55 @@ switch (true) do { _totalIvVolume = _totalIvVolume + _volumeRemaining; } forEach (_target getVariable [QEGVAR(medical,ivBags), []]); - if (GET_BLOOD_VOLUME(_target) + (_totalIvVolume / 1000) > MINIMUM_BLOOD_FOR_STABLE_VITALS) exitWith { - _treatmentEvent = "#waitForBlood"; + // Check if the medic has to wait, which allows for a little multitasking + if (_bloodVolume + (_totalIvVolume / 1000) >= MINIMUM_BLOOD_FOR_STABLE_VITALS) then { + _treatmentEvent = "#waitForIV"; + _canGiveIv = false; }; + }; + + if (_canGiveIv) exitWith { _treatmentEvent = QEGVAR(medical_treatment,ivBagLocal); _treatmentTime = 5; _treatmentArgs = [_target, call _fnc_findNoTourniquet, "SalineIV"]; _treatmentItem = "@iv"; }; - case (((_fractures select 4) == 1) - && {([_healer, "splint"] call FUNC(itemCheck)) # 0}): { + + if ( + ((_fractures select 4) == 1) && + {([_healer, "splint"] call FUNC(itemCheck)) # 0} + ) exitWith { _treatmentEvent = QEGVAR(medical_treatment,splintLocal); _treatmentTime = 6; _treatmentArgs = [_healer, _target, "leftleg"]; _treatmentItem = "splint"; }; - case (((_fractures select 5) == 1) - && {([_healer, "splint"] call FUNC(itemCheck)) # 0}): { + + if ( + ((_fractures select 5) == 1) && + {([_healer, "splint"] call FUNC(itemCheck)) # 0} + ) exitWith { _treatmentEvent = QEGVAR(medical_treatment,splintLocal); _treatmentTime = 6; _treatmentArgs = [_healer, _target, "rightleg"]; _treatmentItem = "splint"; }; - case ((count (_target getVariable [VAR_MEDICATIONS, []])) >= 6): { + + // Wait until the injured has enough blood before administering drugs + if (_needsIv) then { + _treatmentEvent = "#waitForIV" + }; + + if (_treatmentEvent == "#waitForIV") exitWith {}; + + if ((count (_target getVariable [VAR_MEDICATIONS, []])) >= 6) exitWith { _treatmentEvent = "#tooManyMeds"; }; - case ((IS_UNCONSCIOUS(_target) || {_heartRate <= 50}) - && {([_healer, "epinephrine"] call FUNC(itemCheck)) # 0}): { + + if ( + ((IS_UNCONSCIOUS(_target) && {_heartRate < 160}) || {_heartRate <= 50}) && + {([_healer, "epinephrine"] call FUNC(itemCheck)) # 0} + ) exitWith { if (CBA_missionTime < (_target getVariable [QGVAR(nextEpinephrine), -1])) exitWith { _treatmentEvent = "#waitForEpinephrineToTakeEffect"; }; @@ -147,8 +202,11 @@ switch (true) do { _treatmentArgs = [_target, call _fnc_findNoTourniquet, "Epinephrine"]; _treatmentItem = "epinephrine"; }; - case (((GET_PAIN_PERCEIVED(_target) > 0.25) || {_heartRate >= 180}) - && {([_healer, "morphine"] call FUNC(itemCheck)) # 0}): { + + if ( + (((GET_PAIN_PERCEIVED(_target) > 0.25) && {_heartRate > 40}) || {_heartRate >= 180}) && + {([_healer, "morphine"] call FUNC(itemCheck)) # 0} + ) exitWith { if (CBA_missionTime < (_target getVariable [QGVAR(nextMorphine), -1])) exitWith { _treatmentEvent = "#waitForMorphineToTakeEffect"; }; @@ -169,6 +227,7 @@ _healer setVariable [QGVAR(currentTreatment), [CBA_missionTime + _treatmentTime, if ((_treatmentEvent select [0,1]) != "#") then { private _treatmentClassname = _treatmentArgs select 2; if (_treatmentEvent == QEGVAR(medical_treatment,splintLocal)) then { _treatmentClassname = "Splint" }; + if (_treatmentEvent == QEGVAR(medical_treatment,cprLocal)) then { _treatmentClassname = "CPR" }; [_healer, _treatmentClassname, (_healer == _target)] call FUNC(playTreatmentAnim); }; diff --git a/addons/medical_ai/functions/fnc_playTreatmentAnim.sqf b/addons/medical_ai/functions/fnc_playTreatmentAnim.sqf index cb142f02880..9b663f65b22 100644 --- a/addons/medical_ai/functions/fnc_playTreatmentAnim.sqf +++ b/addons/medical_ai/functions/fnc_playTreatmentAnim.sqf @@ -12,7 +12,7 @@ * None * * Example: - * [cursorObject, true, true] call ace_medical_ai_fnc_playTreatmentAnim + * [cursorObject, "Splint", true] call ace_medical_ai_fnc_playTreatmentAnim * * Public: No */ diff --git a/addons/medical_ai/functions/fnc_requestMedic.sqf b/addons/medical_ai/functions/fnc_requestMedic.sqf index 0ea2584fbf2..758fa80a1fd 100644 --- a/addons/medical_ai/functions/fnc_requestMedic.sqf +++ b/addons/medical_ai/functions/fnc_requestMedic.sqf @@ -17,8 +17,11 @@ private _assignedMedic = _this getVariable QGVAR(assignedMedic); private _healQueue = _assignedMedic getVariable [QGVAR(healQueue), []]; -_healQueue pushBack _this; -_assignedMedic setVariable [QGVAR(healQueue), _healQueue]; + +// Only update if it was actually changed +if (_healQueue pushBackUnique _this != -1) then { + _assignedMedic setVariable [QGVAR(healQueue), _healQueue]; +}; #ifdef DEBUG_MODE_FULL systemChat format ["%1 requested %2 for medical treatment", _this, _assignedMedic]; diff --git a/addons/medical_ai/stateMachine.inc.sqf b/addons/medical_ai/stateMachine.inc.sqf index 03483f49815..73b82f98a9c 100644 --- a/addons/medical_ai/stateMachine.inc.sqf +++ b/addons/medical_ai/stateMachine.inc.sqf @@ -17,13 +17,8 @@ GVAR(stateMachine) = [{call EFUNC(common,getLocalUnits)}, true] call CBA_statema #endif }, {}, {}, "Safe"] call CBA_statemachine_fnc_addState; -[GVAR(stateMachine), LINKFUNC(healSelf), {}, { - _this setVariable [QGVAR(treatmentOverAt), nil]; -}, "HealSelf"] call CBA_statemachine_fnc_addState; - -[GVAR(stateMachine), LINKFUNC(healUnit), {}, { - _this setVariable [QGVAR(treatmentOverAt), nil]; -}, "HealUnit"] call CBA_statemachine_fnc_addState; +[GVAR(stateMachine), LINKFUNC(healSelf), {}, {}, "HealSelf"] call CBA_statemachine_fnc_addState; +[GVAR(stateMachine), LINKFUNC(healUnit), {}, {}, "HealUnit"] call CBA_statemachine_fnc_addState; // Add Transistions [statemachine, originalState, targetState, condition, onTransition, name] [GVAR(stateMachine), "Initial", "Injured", LINKFUNC(isInjured), {}, "Injured"] call CBA_statemachine_fnc_addTransition;