mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Medical AI - AI will remove tourniquets (#10166)
* Medical AI - AI will remove tourniquets * Medical AI - Improve tourniquet removal (for #10166) (#10178) * Fixes & tweaks - Have AI remove tourniquets ASAP - Fixed bug where AI would not remove tourniquet, because it didn't have any bandages - Allowed for more multitasking * Allow healer to administer morphine if out of bandages * Remove TODO comment * Allow AI to remove tourniquets from limbs with no open wounds * Update addons/medical_ai/functions/fnc_healingLogic.sqf --------- Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com>
This commit is contained in:
parent
96f81f1c9b
commit
0b4029b12f
@ -16,9 +16,6 @@
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
// TODO: Add AI tourniquet behaviour
|
||||
// For now, AI handle player or otherwise scripted tourniquets only
|
||||
|
||||
params ["_healer", "_target"];
|
||||
(_healer getVariable [QGVAR(currentTreatment), [-1]]) params ["_finishTime", "_treatmentTarget", "_treatmentEvent", "_treatmentArgs", "_treatmentItem"];
|
||||
|
||||
@ -87,34 +84,40 @@ if (_finishTime > 0) exitWith {
|
||||
};
|
||||
};
|
||||
|
||||
// Find a suitable limb (no tourniquets) for injecting and giving IVs
|
||||
private _fnc_findNoTourniquet = {
|
||||
private _bodyPart = "";
|
||||
// Bandage a limb up, then remove the tourniquet on it
|
||||
private _fnc_removeTourniquet = {
|
||||
params [["_removeAllTourniquets", false]];
|
||||
|
||||
// If all limbs have tourniquets, find the least damaged limb and try to bandage it
|
||||
if ((_tourniquets select [2]) find 0 == -1) then {
|
||||
// If no bandages available, wait
|
||||
if !(([_healer, "@bandage"] call FUNC(itemCheck)) # 0) exitWith {
|
||||
_treatmentEvent = "#waitForNonTourniquetedLimb"; // TODO: Medic can move onto another patient/should be flagged as out of supplies
|
||||
};
|
||||
// Ignore head & torso if not removing all tourniquets (= administering drugs/IVs)
|
||||
private _offset = [2, 0] select _removeAllTourniquets;
|
||||
|
||||
// Bandage the least bleeding body part
|
||||
private _bodyPartBleeding = [0, 0, 0, 0];
|
||||
private _bodyPartBleeding = [];
|
||||
_bodyPartBleeding resize [[4, 6] select _removeAllTourniquets, -1];
|
||||
|
||||
{
|
||||
// Ignore head and torso
|
||||
private _partIndex = (ALL_BODY_PARTS find _x) - 2;
|
||||
// Ignore head and torso, if only looking for place to administer drugs/IVs
|
||||
private _partIndex = (ALL_BODY_PARTS find _x) - _offset;
|
||||
|
||||
if (_partIndex >= 0) then {
|
||||
if (_partIndex >= 0 && {_tourniquets select _partIndex != 0}) then {
|
||||
{
|
||||
_x params ["", "_amountOf", "_bleeding"];
|
||||
_bodyPartBleeding set [_partIndex, (_bodyPartBleeding select _partIndex) + (_amountOf * _bleeding)];
|
||||
|
||||
// max 0, to set the baseline to 0, as body parts with no wounds are marked with -1
|
||||
_bodyPartBleeding set [_partIndex, ((_bodyPartBleeding select _partIndex) max 0) + (_amountOf * _bleeding)];
|
||||
} forEach _y;
|
||||
};
|
||||
} forEach GET_OPEN_WOUNDS(_target);
|
||||
|
||||
private _minBodyPartBleeding = selectMin _bodyPartBleeding;
|
||||
private _selection = ALL_BODY_PARTS select ((_bodyPartBleeding find _minBodyPartBleeding) + 2);
|
||||
// If there are no open wounds, check if there are tourniquets on limbs with no open wounds (stitched or fully healed),
|
||||
// as we know there have to be tourniquets at this point
|
||||
if (_bodyPartBleeding findIf {_x != -1} == -1) then {
|
||||
_bodyPartBleeding set [_tourniquets findIf {_x != 0}, 0];
|
||||
};
|
||||
|
||||
// Ignore body parts that don't have open wounds (-1)
|
||||
private _minBodyPartBleeding = selectMin (_bodyPartBleeding select {_x != -1});
|
||||
private _selection = ALL_BODY_PARTS select ((_bodyPartBleeding find _minBodyPartBleeding) + _offset);
|
||||
|
||||
// If not bleeding anymore, remove the tourniquet
|
||||
if (_minBodyPartBleeding == 0) exitWith {
|
||||
@ -123,11 +126,26 @@ private _fnc_findNoTourniquet = {
|
||||
_treatmentArgs = [_healer, _target, _selection];
|
||||
};
|
||||
|
||||
// If no bandages available, wait
|
||||
// If check is done at the start of the scope, it will miss the edge case where the unit ran out of bandages just as they finished bandaging tourniqueted body part
|
||||
if !(([_healer, "@bandage"] call FUNC(itemCheck)) # 0) exitWith {
|
||||
_treatmentEvent = "#waitForBandages"; // TODO: Medic can move onto another patient/should be flagged as out of supplies
|
||||
};
|
||||
|
||||
// Otherwise keep bandaging
|
||||
_treatmentEvent = QEGVAR(medical_treatment,bandageLocal);
|
||||
_treatmentTime = 5;
|
||||
_treatmentArgs = [_target, _selection, "FieldDressing"];
|
||||
_treatmentItem = "@bandage";
|
||||
};
|
||||
|
||||
// Find a suitable limb (no tourniquets) for adminstering drugs/IVs
|
||||
private _fnc_findNoTourniquet = {
|
||||
private _bodyPart = "";
|
||||
|
||||
// If all limbs have tourniquets, find the least damaged limb and try to bandage it
|
||||
if ((_tourniquets select [2]) find 0 == -1) then {
|
||||
call _fnc_removeTourniquet;
|
||||
} else {
|
||||
// Select a random non-tourniqueted limb otherwise
|
||||
private _bodyParts = ["leftarm", "rightarm", "leftleg", "rightleg"];
|
||||
@ -270,7 +288,7 @@ if (true) then {
|
||||
|
||||
// Wait until the injured has enough blood before administering drugs
|
||||
// (_needsIV && !_canGiveIV), but _canGiveIV is false here, otherwise IV would be given
|
||||
if (_needsIV || {_treatmentEvent == "#waitForIV"}) exitWith {
|
||||
if (_needsIV || {_doCPR && {_treatmentEvent == "#waitForIV"}}) exitWith {
|
||||
// If injured is in cardiac arrest and the healer is doing nothing else, start CPR
|
||||
if (_doCPR) exitWith {
|
||||
_treatmentEvent = QEGVAR(medical_treatment,cprLocal); // TODO: Medic remains in this loop until injured is given enough IVs or dies
|
||||
@ -284,23 +302,30 @@ if (true) then {
|
||||
};
|
||||
};
|
||||
|
||||
if ((count (_target getVariable [VAR_MEDICATIONS, []])) >= 6) exitWith {
|
||||
// These checks are not exitWith, so that the medic can try to bandage up tourniqueted body parts
|
||||
if ((count (_target getVariable [VAR_MEDICATIONS, []])) >= 6) then {
|
||||
_treatmentEvent = "#tooManyMeds"; // TODO: Medic can move onto another patient
|
||||
};
|
||||
|
||||
private _heartRate = GET_HEART_RATE(_target);
|
||||
private _canGiveEpinephrine = !(_treatmentEvent in ["#tooManyMeds", "#waitForIV"]) &&
|
||||
{IS_UNCONSCIOUS(_target) || {_heartRate <= 50}} &&
|
||||
{([_healer, "epinephrine"] call FUNC(itemCheck)) # 0};
|
||||
|
||||
if (
|
||||
(IS_UNCONSCIOUS(_target) || {_heartRate <= 50}) &&
|
||||
{([_healer, "epinephrine"] call FUNC(itemCheck)) # 0}
|
||||
) exitWith {
|
||||
if (CBA_missionTime < (_target getVariable [QGVAR(nextEpinephrine), -1])) exitWith {
|
||||
// This allows for some multitasking
|
||||
if (_canGiveEpinephrine) then {
|
||||
if (CBA_missionTime < (_target getVariable [QGVAR(nextEpinephrine), -1])) then {
|
||||
_treatmentEvent = "#waitForEpinephrineToTakeEffect";
|
||||
};
|
||||
if (_heartRate > 180) exitWith {
|
||||
_treatmentEvent = "#waitForSlowerHeart"; // TODO: Medic can move onto another patient, after X amount of time of high HR
|
||||
_canGiveEpinephrine = false;
|
||||
};
|
||||
|
||||
if (_heartRate > 180) then {
|
||||
_treatmentEvent = "#waitForSlowerHeart"; // TODO: Medic can move onto another patient, after X amount of time of high HR
|
||||
_canGiveEpinephrine = false;
|
||||
};
|
||||
};
|
||||
|
||||
if (_canGiveEpinephrine) exitWith {
|
||||
// If all limbs are tourniqueted, bandage the one with the least amount of wounds, so that the tourniquet can be removed
|
||||
_bodyPart = call _fnc_findNoTourniquet;
|
||||
|
||||
@ -313,8 +338,18 @@ if (true) then {
|
||||
_treatmentItem = "epinephrine";
|
||||
};
|
||||
|
||||
// Remove all remaining tourniquets by bandaging all body parts
|
||||
if (_tourniquets isNotEqualTo DEFAULT_TOURNIQUET_VALUES) then {
|
||||
true call _fnc_removeTourniquet;
|
||||
};
|
||||
|
||||
// If the healer can bandage or remove tourniquets, do that
|
||||
if (_treatmentEvent in [QEGVAR(medical_treatment,bandageLocal), QGVAR(tourniquetRemove)]) exitWith {};
|
||||
|
||||
// Otherwise, if the healer is either done or out of bandages, continue
|
||||
if (
|
||||
((GET_PAIN_PERCEIVED(_target) > 0.25) || {_heartRate >= 180}) &&
|
||||
!(_treatmentEvent in ["#tooManyMeds", "#waitForIV"]) &&
|
||||
{(GET_PAIN_PERCEIVED(_target) > 0.25) || {_heartRate >= 180}} &&
|
||||
{([_healer, "morphine"] call FUNC(itemCheck)) # 0}
|
||||
) exitWith {
|
||||
if (CBA_missionTime < (_target getVariable [QGVAR(nextMorphine), -1])) exitWith {
|
||||
|
@ -24,3 +24,4 @@ if !(alive _this) exitWith {false};
|
||||
private _fractures = GET_FRACTURES(_this);
|
||||
((_fractures select 4) == 1) || {(_fractures select 5) == 1}
|
||||
}
|
||||
|| { GET_TOURNIQUETS(_this) isNotEqualTo DEFAULT_TOURNIQUET_VALUES }
|
||||
|
Loading…
Reference in New Issue
Block a user