Medical AI - Give blood in Cardiac Arrest before doing CPR (#10154)

Give blood in CA if needed before doing CPR
This commit is contained in:
johnb432 2024-07-29 15:04:59 +02:00 committed by GitHub
parent 7e93715bcc
commit 98da279e8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 27 deletions

View File

@ -35,6 +35,23 @@ if (_finishTime > 0) exitWith {
}; };
if ((_treatmentTarget == _target) && {(_treatmentEvent select [0, 1]) != "#"}) then { if ((_treatmentTarget == _target) && {(_treatmentEvent select [0, 1]) != "#"}) then {
[_treatmentEvent, _treatmentArgs, _target] call CBA_fnc_targetEvent; [_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 #ifdef DEBUG_MODE_FULL
INFO_4("%1->%2: %3 - %4",_healer,_target,_treatmentEvent,_treatmentArgs); INFO_4("%1->%2: %3 - %4",_healer,_target,_treatmentEvent,_treatmentArgs);
systemChat format ["Applying [%1->%2]: %3", _healer, _treatmentTarget, _treatmentEvent]; systemChat format ["Applying [%1->%2]: %3", _healer, _treatmentTarget, _treatmentEvent];
@ -75,9 +92,12 @@ private _treatmentEvent = "#none";
private _treatmentArgs = []; private _treatmentArgs = [];
private _treatmentTime = 6; private _treatmentTime = 6;
private _treatmentItem = ""; private _treatmentItem = "";
switch (true) do {
case ((GET_WOUND_BLEEDING(_target) > 0) if (true) then {
&& {([_healer, "@bandage"] call FUNC(itemCheck)) # 0}): { if (
(GET_WOUND_BLEEDING(_target) > 0) &&
{([_healer, "@bandage"] call FUNC(itemCheck)) # 0}
) exitWith {
// Select first bleeding wound and bandage it // Select first bleeding wound and bandage it
private _selection = "?"; private _selection = "?";
{ {
@ -94,13 +114,26 @@ switch (true) do {
_treatmentArgs = [_target, _selection, "FieldDressing"]; _treatmentArgs = [_target, _selection, "FieldDressing"];
_treatmentItem = "@bandage"; _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); _treatmentEvent = QEGVAR(medical_treatment,cprLocal);
_treatmentArgs = [_healer, _target]; _treatmentArgs = [_healer, _target];
_treatmentTime = 15; _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 // Check if patient's blood volume + remaining IV volume is enough to allow the patient to wake up
private _totalIvVolume = 0; //in ml private _totalIvVolume = 0; //in ml
{ {
@ -108,33 +141,55 @@ switch (true) do {
_totalIvVolume = _totalIvVolume + _volumeRemaining; _totalIvVolume = _totalIvVolume + _volumeRemaining;
} forEach (_target getVariable [QEGVAR(medical,ivBags), []]); } forEach (_target getVariable [QEGVAR(medical,ivBags), []]);
if (GET_BLOOD_VOLUME(_target) + (_totalIvVolume / 1000) > MINIMUM_BLOOD_FOR_STABLE_VITALS) exitWith { // Check if the medic has to wait, which allows for a little multitasking
_treatmentEvent = "#waitForBlood"; if (_bloodVolume + (_totalIvVolume / 1000) >= MINIMUM_BLOOD_FOR_STABLE_VITALS) then {
_treatmentEvent = "#waitForIV";
_canGiveIv = false;
}; };
};
if (_canGiveIv) exitWith {
_treatmentEvent = QEGVAR(medical_treatment,ivBagLocal); _treatmentEvent = QEGVAR(medical_treatment,ivBagLocal);
_treatmentTime = 5; _treatmentTime = 5;
_treatmentArgs = [_target, call _fnc_findNoTourniquet, "SalineIV"]; _treatmentArgs = [_target, call _fnc_findNoTourniquet, "SalineIV"];
_treatmentItem = "@iv"; _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); _treatmentEvent = QEGVAR(medical_treatment,splintLocal);
_treatmentTime = 6; _treatmentTime = 6;
_treatmentArgs = [_healer, _target, "leftleg"]; _treatmentArgs = [_healer, _target, "leftleg"];
_treatmentItem = "splint"; _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); _treatmentEvent = QEGVAR(medical_treatment,splintLocal);
_treatmentTime = 6; _treatmentTime = 6;
_treatmentArgs = [_healer, _target, "rightleg"]; _treatmentArgs = [_healer, _target, "rightleg"];
_treatmentItem = "splint"; _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"; _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 { if (CBA_missionTime < (_target getVariable [QGVAR(nextEpinephrine), -1])) exitWith {
_treatmentEvent = "#waitForEpinephrineToTakeEffect"; _treatmentEvent = "#waitForEpinephrineToTakeEffect";
}; };
@ -147,8 +202,11 @@ switch (true) do {
_treatmentArgs = [_target, call _fnc_findNoTourniquet, "Epinephrine"]; _treatmentArgs = [_target, call _fnc_findNoTourniquet, "Epinephrine"];
_treatmentItem = "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 { if (CBA_missionTime < (_target getVariable [QGVAR(nextMorphine), -1])) exitWith {
_treatmentEvent = "#waitForMorphineToTakeEffect"; _treatmentEvent = "#waitForMorphineToTakeEffect";
}; };
@ -169,6 +227,7 @@ _healer setVariable [QGVAR(currentTreatment), [CBA_missionTime + _treatmentTime,
if ((_treatmentEvent select [0,1]) != "#") then { if ((_treatmentEvent select [0,1]) != "#") then {
private _treatmentClassname = _treatmentArgs select 2; private _treatmentClassname = _treatmentArgs select 2;
if (_treatmentEvent == QEGVAR(medical_treatment,splintLocal)) then { _treatmentClassname = "Splint" }; 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); [_healer, _treatmentClassname, (_healer == _target)] call FUNC(playTreatmentAnim);
}; };

View File

@ -12,7 +12,7 @@
* None * None
* *
* Example: * Example:
* [cursorObject, true, true] call ace_medical_ai_fnc_playTreatmentAnim * [cursorObject, "Splint", true] call ace_medical_ai_fnc_playTreatmentAnim
* *
* Public: No * Public: No
*/ */

View File

@ -17,8 +17,11 @@
private _assignedMedic = _this getVariable QGVAR(assignedMedic); private _assignedMedic = _this getVariable QGVAR(assignedMedic);
private _healQueue = _assignedMedic getVariable [QGVAR(healQueue), []]; 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 #ifdef DEBUG_MODE_FULL
systemChat format ["%1 requested %2 for medical treatment", _this, _assignedMedic]; systemChat format ["%1 requested %2 for medical treatment", _this, _assignedMedic];

View File

@ -17,13 +17,8 @@ GVAR(stateMachine) = [{call EFUNC(common,getLocalUnits)}, true] call CBA_statema
#endif #endif
}, {}, {}, "Safe"] call CBA_statemachine_fnc_addState; }, {}, {}, "Safe"] call CBA_statemachine_fnc_addState;
[GVAR(stateMachine), LINKFUNC(healSelf), {}, { [GVAR(stateMachine), LINKFUNC(healSelf), {}, {}, "HealSelf"] call CBA_statemachine_fnc_addState;
_this setVariable [QGVAR(treatmentOverAt), nil]; [GVAR(stateMachine), LINKFUNC(healUnit), {}, {}, "HealUnit"] call CBA_statemachine_fnc_addState;
}, "HealSelf"] call CBA_statemachine_fnc_addState;
[GVAR(stateMachine), LINKFUNC(healUnit), {}, {
_this setVariable [QGVAR(treatmentOverAt), nil];
}, "HealUnit"] call CBA_statemachine_fnc_addState;
// Add Transistions [statemachine, originalState, targetState, condition, onTransition, name] // Add Transistions [statemachine, originalState, targetState, condition, onTransition, name]
[GVAR(stateMachine), "Initial", "Injured", LINKFUNC(isInjured), {}, "Injured"] call CBA_statemachine_fnc_addTransition; [GVAR(stateMachine), "Initial", "Injured", LINKFUNC(isInjured), {}, "Injured"] call CBA_statemachine_fnc_addTransition;