Medical AI - Adjust healing logic for rewrite (#6902)

* Medical AI - Adjust healing logic for rewrite

- move state machine from config to sqf
- move all healing logic to seperate func
- attempt to handle healing for new system

* prioritize unitReady medics

* move setting to subcategory under medical

* Use faster GET_WOUND_BLEEDING

* Update fnc_healingLogic.sqf

* Update for wound array changes

* Update treatment events changes

* Fractures/splint

* formating / use GET_OPEN_WOUNDS

* Use non-localized medical category
This commit is contained in:
PabstMirror 2019-07-03 09:59:28 -05:00 committed by GitHub
parent aa41fffdb7
commit 05e4f74e73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 247 additions and 236 deletions

View File

@ -23,7 +23,11 @@
if (!isNull cursorTarget && {cursorTarget isKindOf "CAManBase"}) then {
private _targetState = [cursorTarget, EGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
drawIcon3D ["", [0.6, 0, 0, 1], cursorTarget modelToWorldVisual (cursorTarget selectionPosition "pelvis"), 0, 0, 0, format ["State: %1", _targetState], 2, 40 * pixelH, "RobotoCondensed"];
private _targetStateAI = "";
if (!isNil QEGVAR(medical_ai,stateMachine)) then {
_targetStateAI = [cursorTarget, EGVAR(medical_ai,stateMachine)] call CBA_statemachine_fnc_getCurrentState;
};
drawIcon3D ["", [0.6, 0, 0, 1], cursorTarget modelToWorldVisual (cursorTarget selectionPosition "pelvis"), 0, 0, 0, format ["State: %1 / %2", _targetState,_targetStateAI], 2, 40 * pixelH, "RobotoCondensed"];
};
}, 0 ,[]] call CBA_fnc_addPerFrameHandler;
}, []] call CBA_fnc_waitUntilAndExecute;

View File

@ -1,86 +0,0 @@
class GVAR(stateMachine) {
list = QUOTE(call EFUNC(common,getLocalUnits));
skipNull = 1;
class Initial {
class Injured {
targetState = "Injured";
condition = QFUNC(isInjured);
};
class HealUnit {
targetState = "HealUnit";
condition = QUOTE((call FUNC(isSafe)) && {call FUNC(wasRequested)});
};
};
class Injured {
#ifdef DEBUG_MODE_FULL
onState = "systemChat format [""%1 is injured"", _this]";
#endif
class InSafety {
targetState = "Safe";
condition = QFUNC(isSafe);
};
};
class Safe {
#ifdef DEBUG_MODE_FULL
onState = "systemChat format [""%1 is injured, but safe"", _this]";
#endif
class RequestMedic {
targetState = "HealSelf";
condition = QFUNC(canRequestMedic);
onTransition = QFUNC(requestMedic);
};
class HealSelf {
targetState = "HealSelf";
condition = "true";
};
};
class HealSelf {
onState = QFUNC(healSelf);
onStateLeaving = QUOTE(_this setVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),nil)]);
class Initial {
// Go back to initial state when done healing
targetState = "Initial";
condition = QUOTE( \
!(call FUNC(isInjured)) \
&& {_this getVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),CBA_missionTime)] <= CBA_missionTime} \
);
};
class Injured {
// Stop treating when it's no more safe
targetState = "Injured";
condition = QUOTE( \
!(call FUNC(isSafe)) \
&& {_this getVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),CBA_missionTime)] <= CBA_missionTime} \
);
};
};
class HealUnit {
onState = QFUNC(healUnit);
onStateLeaving = QUOTE(_this setVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),nil)]);
class Initial {
// Go back to initial state when done healing or it's no more safe to treat
targetState = "Initial";
condition = QUOTE( \
!((call FUNC(wasRequested)) && {call FUNC(isSafe)}) \
&& {_this getVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),CBA_missionTime)] <= CBA_missionTime} \
);
};
class Injured {
// Treating yourself has priority
targetState = "Injured";
condition = QUOTE( \
(call FUNC(isInjured)) \
&& {_this getVariable [ARR_2(QUOTE(QGVAR(treatmentOverAt)),CBA_missionTime)] <= CBA_missionTime} \
);
};
};
};

View File

@ -1,4 +1,5 @@
PREP(canRequestMedic);
PREP(healingLogic);
PREP(healSelf);
PREP(healUnit);
PREP(isInjured);

View File

@ -1,35 +1,14 @@
#include "script_component.hpp"
/*["ace_settingsInitialized", {
["ace_settingsInitialized", {
TRACE_1("settingsInitialized", GVAR(enabledFor));
if (GVAR(enabledFor) == 0) exitWith {}; // 0: disabled
if ((GVAR(enabledFor) == 1) && {!isServer} && {hasInterface}) exitWith {}; // 1: Don't Run on non-hc Clients
// Only run for AI that does not have to deal with advanced medical
if (EGVAR(medical,enableFor) == 1 || {hasInterface}) exitWith {};
["ace_firedNonPlayer", {
_unit setVariable [QGVAR(lastFired), CBA_missionTime];
}] call CBA_fnc_addEventHandler;
if (hasInterface) then {
["ace_unconscious", {
params ["_unit", "_unconscious"];
if (!_unconscious || {_unit != ACE_player}) exitWith {};
#include "stateMachine.sqf"
}] call CBA_fnc_addEventHandler;
private _medic = objNull;
{
if ((!isPlayer _x) && {[_x] call EFUNC(medical_treatment,isMedic)}) exitWith {
_medic = _x;
};
} forEach (units _unit);
if (isNull _medic) exitWith {};
private _healQueue = _medic getVariable [QGVAR(healQueue), []];
_healQueue pushBack _unit;
_medic setVariable [QGVAR(healQueue), _healQueue];
}] call CBA_fnc_addEventHandler;
};
GVAR(statemachine) = [configFile >> "ACE_Medical_AI_StateMachine"] call CBA_statemachine_fnc_createFromConfig;
}] call CBA_fnc_addEventHandler;*/

View File

@ -16,4 +16,3 @@ class CfgPatches {
#include "ACE_Settings.hpp"
#include "CfgEventHandlers.hpp"
#include "StateMachine.hpp"

View File

@ -10,7 +10,7 @@
* Can request medic <BOOL>
*
* Example:
* call ACE_medical_ai_fnc_canRequestMedic
* player call ACE_medical_ai_fnc_canRequestMedic
*
* Public: No
*/
@ -21,10 +21,14 @@
if ([_this] call EFUNC(medical_treatment,isMedic) || {vehicle _this != _this}) exitWith {false};
// Search for a medic, prioritize unitReady
private _medic = objNull;
{
if ([_x] call EFUNC(medical_treatment,isMedic) && {!([_x] call EFUNC(common,isPlayer))}) exitWith {
_this setVariable [QGVAR(assignedMedic), _x];
true
};
false
if ([_x] call EFUNC(medical_treatment,isMedic) && {!([_x] call EFUNC(common,isPlayer))} && {
_medic = _x;
(unitReady _medic)
}) exitWith {};
} forEach (units _this);
_this setVariable [QGVAR(assignedMedic), _medic];
!isNull _medic

View File

@ -18,41 +18,8 @@
// Player will have to do this manually of course
if ([_this] call EFUNC(common,isPlayer)) exitWith {};
// Can't heal self when unconscious
if IS_UNCONSCIOUS(_this) exitWith {};
// Check if we're still treating
if ((_this getVariable [QGVAR(treatmentOverAt), CBA_missionTime]) > CBA_missionTime) exitWith {};
private _needsBandaging = GET_BLOOD_LOSS(_this) > 0;
private _needsMorphine = GET_PAIN(_this) > 0.2;
switch (true) do {
case _needsBandaging: {
// Select first wound and bandage it
private _openWounds = _this getVariable [QEGVAR(medical,openWounds), []];
private _partIndex = {
_x params ["", "", "_index", "_amount", "_percentage"];
if (_amount * _percentage > 0) exitWith {
_index
};
} forEach _openWounds;
private _selection = ALL_BODY_PARTS select _partIndex;
[_this, "BasicBandage", _selection] call EFUNC(medical_treatment,treatmentBandageLocal);
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is bandaging selection %2", _this, _selection];
#endif
// Play animation
[_this, true, true] call FUNC(playTreatmentAnim);
_this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 5];
};
case _needsMorphine: {
[_this, "Morphine", 2] call EFUNC(medical_treatment,treatmentMedicationLocal);
[_this, false, true] call FUNC(playTreatmentAnim);
_this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 2];
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is giving himself morphine", _this];
#endif
};
if IS_UNCONSCIOUS(_this) exitWith {
_this setVariable [QGVAR(currentTreatment), nil];
};
[_this, _this] call FUNC(healingLogic);

View File

@ -14,11 +14,12 @@
*
* Public: No
*/
// Player will have to do this manually of course
if ([_this] call EFUNC(common,isPlayer)) exitWith {};
// Can't heal other units when unconscious
if IS_UNCONSCIOUS(_this) exitWith {};
// Check if we're still treating
if ((_this getVariable [QGVAR(treatmentOverAt), CBA_missionTime]) > CBA_missionTime) exitWith {};
if IS_UNCONSCIOUS(_this) exitWith {
_this setVariable [QGVAR(currentTreatment), nil];
};
// Find next unit to treat
private _healQueue = _this getVariable [QGVAR(healQueue), []];
@ -26,74 +27,34 @@ private _target = _healQueue select 0;
// If unit died or was healed, be lazy and wait for the next tick
if (isNull _target || {!alive _target} || {!(_target call FUNC(isInjured))}) exitWith {
_this forceSpeed -1;
_target forceSpeed -1;
_healQueue deleteAt 0;
_this getVariable [QGVAR(healQueue), _healQueue];
_this forceSpeed -1;
_this setVariable [QGVAR(healQueue), _healQueue];
// return to formation instead of going where the injured unit was if it healed itself in the mean time
_this doFollow leader _this;
_this setVariable [QGVAR(movingToInjured), false];
_this setVariable [QGVAR(nextMoveOrder), nil];
_this setVariable [QGVAR(currentTreatment), nil];
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 finished healing %2", _this, _target];
systemChat format ["%1 finished healing %2", _this, _target];
#endif
};
// Move to target...
if (_this distance _target > 2) exitWith {
if !(_this getVariable [QGVAR(movingToInjured), false]) then {
_this setVariable [QGVAR(movingToInjured), true];
if (_this distance _target > 2.5) exitWith {
_this setVariable [QGVAR(currentTreatment), nil];
if (CBA_missionTime >= (_this getVariable [QGVAR(nextMoveOrder), CBA_missionTime])) then {
_this setVariable [QGVAR(nextMoveOrder), CBA_missionTime + 10];
_this doMove getPosATL _target;
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 moving to %2", _this, _target];
#endif
};
};
_this setVariable [QGVAR(movingToInjured), false];
// ...and make sure medic and target don't move
_this forceSpeed 0;
_target forceSpeed 0;
private _needsBandaging = GET_BLOOD_LOSS(_target) > 0;
private _needsMorphine = GET_PAIN(_target) > 0.2;
private _needsEpinephrine = IS_UNCONSCIOUS(_target);
switch (true) do {
case _needsBandaging: {
// Select first wound and bandage it
private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []];
private _partIndex = {
_x params ["", "", "_index", "_amount", "_percentage"];
if (_amount * _percentage > 0) exitWith {
_index
};
} forEach _openWounds;
private _selection = ALL_BODY_PARTS select _partIndex;
[_target, "BasicBandage", _selection] call EFUNC(medical_treatment,treatmentBandageLocal);
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is bandaging selection %2 on %3", _this, _selection, _target];
#endif
// Play animation
[_this, true, false] call FUNC(playTreatmentAnim);
_this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 5];
};
case _needsMorphine: {
[_this, "Morphine", 2] call EFUNC(medical_treatment,treatmentMedicationLocal);
[_this, false, false] call FUNC(playTreatmentAnim);
_this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 2];
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is giving %2 morphine", _this, _target];
#endif
};
//ToDo - Figure out how to connect to new medical
// case _needsEpinephrine: {
// [_this, _target] call EFUNC(medical,treatmentBasic_epipen);
// [_this, false, false] call FUNC(playTreatmentAnim);
// _this setVariable [QGVAR(treatmentOverAt), CBA_missionTime + 2];
// #ifdef DEBUG_MODE_FULL
// systemChat format ["%1 is using an epipen on %2", _this, _target];
// #endif
// };
};
[_this, _target] call FUNC(healingLogic);

View File

@ -0,0 +1,117 @@
#include "script_component.hpp"
/*
* Author: BaerMitUmlaut, PabstMirror
* Applies healing to target
*
* Arguments:
* 0: Healer <OBJECT>
* 1: Target <OBJECT>
*
* Return Value:
* Nothing
*
* Example:
* [a, b] call ACE_medical_ai_fnc_healingLogic
*
* Public: No
*/
params ["_healer", "_target"];
(_healer getVariable [QGVAR(currentTreatment), [-1]]) params ["_finishTime", "_treatmentTarget", "_treatmentEvent", "_treatmentArgs"];
// Treatment in progress, check if finished and apply
if (_finishTime > 0) exitWith {
if (CBA_missionTime >= _finishTime) then {
TRACE_4("treatment finished",_finishTime,_treatmentTarget,_treatmentEvent,_treatmentArgs);
_healer setVariable [QGVAR(currentTreatment), nil];
if ((_treatmentTarget == _target) && {(_treatmentEvent select [0, 1]) != "#"}) then {
[_treatmentEvent, _treatmentArgs, _target] call CBA_fnc_targetEvent;
#ifdef DEBUG_MODE_FULL
INFO_4("%1->%2: %3 - %4",_healer,_target,_treatmentEvent,_treatmentArgs);
systemChat format ["Applying [%1->%2]: %3", _healer, _treatmentTarget, _treatmentEvent];
#endif
};
};
};
private _isMedic = [_healer] call EFUNC(medical_treatment,isMedic);
private _heartRate = GET_HEART_RATE(_target);
private _fractures = GET_FRACTURES(_target);
private _treatmentEvent = "#none";
private _treatmentArgs = [];
private _treatmentTime = 6;
switch (true) do {
case (GET_WOUND_BLEEDING(_target) > 0): {
// Select first bleeding wound and bandage it
private _openWounds = GET_OPEN_WOUNDS(_target);
private _selection = "?";
{
_x params ["", "_index", "_amount", "_percentage"];
if ((_amount * _percentage) > 0) exitWith { _selection = ALL_BODY_PARTS select _index; };
} forEach _openWounds;
_treatmentEvent = QEGVAR(medical_treatment,bandageLocal);
_treatmentTime = 5;
_treatmentArgs = [_target, _selection, "FieldDressing"];
};
case (_isMedic && {GET_BLOOD_VOLUME(_target) < BLOOD_VOLUME_CLASS_2_HEMORRHAGE}): {
private _bloodBags = _target getVariable [QEGVAR(medical,ivBags), []];
if ((count _bloodBags) >= 2) exitWith {
_treatmentEvent = "#waitForBlood";
};
_treatmentEvent = QEGVAR(medical_treatment,ivBagLocal);
_treatmentTime = 5;
_treatmentArgs = [_target, selectRandom ["leftarm", "rightarm", "leftleg", "rightleg"], "SalineIV"];
};
case ((count (_target getVariable [VAR_MEDICATIONS, []])) >= 6): {
_treatmentEvent = "#tooManyMeds";
};
case ((_fractures select 4) == 1): {
_treatmentEvent = QEGVAR(medical_treatment,splintLocal);
_treatmentTime = 6;
_treatmentArgs = [_healer, _target, "leftleg"];
};
case ((_fractures select 5) == 1): {
_treatmentEvent = QEGVAR(medical_treatment,splintLocal);
_treatmentTime = 6;
_treatmentArgs = [_healer, _target, "rightleg"];
};
case (IS_UNCONSCIOUS(_target) || {_heartRate <= 50}): {
if (CBA_missionTime < (_target getVariable [QGVAR(nextEpinephrine), -1])) exitWith {
_treatmentEvent = "#waitForEpinephrineToTakeEffect";
};
if (_heartRate > 180) exitWith {
_treatmentEvent = "#waitForSlowerHeart";
};
_target setVariable [QGVAR(nextEpinephrine), CBA_missionTime + 10];
_treatmentEvent = QEGVAR(medical_treatment,medicationLocal);
_treatmentTime = 2.5;
_treatmentArgs = [_target, selectRandom ["leftarm", "rightarm", "leftleg", "rightleg"], "Epinephrine"];
};
case ((GET_PAIN_PERCEIVED(_target) > 0.25) || {_heartRate >= 180}): {
if (CBA_missionTime < (_target getVariable [QGVAR(nextMorphine), -1])) exitWith {
_treatmentEvent = "#waitForMorphineToTakeEffect";
};
if (_heartRate < 60) exitWith {
_treatmentEvent = "#waitForFasterHeart";
};
_target setVariable [QGVAR(nextMorphine), CBA_missionTime + 30];
_treatmentEvent = QEGVAR(medical_treatment,medicationLocal);
_treatmentTime = 2.5;
_treatmentArgs = [_target, selectRandom ["leftarm", "rightarm", "leftleg", "rightleg"], "Morphine"];
};
};
_healer setVariable [QGVAR(currentTreatment), [CBA_missionTime + _treatmentTime, _target, _treatmentEvent, _treatmentArgs]];
// Play animation
if ((_treatmentEvent select [0,1]) != "#") then {
private _treatmentClassname = _treatmentArgs select 2;
if (_treatmentEvent == QEGVAR(medical_treatment,splintLocal)) then { _treatmentClassname = "Splint" };
[_healer, _treatmentClassname, (_healer == _target)] call FUNC(playTreatmentAnim);
};
#ifdef DEBUG_MODE_FULL
TRACE_4("treatment started",_treatmentTime,_target,_treatmentEvent,_treatmentArgs);
systemChat format ["Treatment [%1->%2]: %3", _healer, _target, _treatmentEvent];
#endif

View File

@ -17,8 +17,10 @@
if !(alive _this) exitWith {false};
private _bloodLoss = GET_BLOOD_LOSS(_this);
private _pain = GET_PAIN_PERCEIVED(_this);
private _unconscious = IS_UNCONSCIOUS(_this);
(_bloodLoss > 0) || {_pain > 0.2} || _unconscious
(GET_WOUND_BLEEDING(_this) > 0)
|| {GET_PAIN_PERCEIVED(_this) > 0.25}
|| {IS_UNCONSCIOUS(_this)}
|| {
private _fractures = GET_FRACTURES(_this);
((_fractures select 4) == 1) || {(_fractures select 5) == 1}
}

View File

@ -5,7 +5,7 @@
*
* Arguments:
* 0: Unit <OBJECT>
* 1: Is bandage <BOOL>
* 1: Treatment name <STRING>
* 2: Is self treatment <BOOL>
*
* Return Value:
@ -16,16 +16,11 @@
*
* Public: No
*/
params ["_unit", "_isBandage", "_isSelfTreatment"];
params ["_unit", "_actionName", "_isSelfTreatment"];
TRACE_3("playTreatmentAnim",_unit,_actionName,_isSelfTreatment);
if (vehicle _unit != _unit) exitWith {};
private _animConfig = if (_isBandage) then {
configFile >> "ACE_Medical_Actions" >> "Basic" >> "BasicBandage";
} else {
configFile >> "ACE_Medical_Actions" >> "Basic" >> "Morphine";
};
private _configProperty = "animationMedic";
if (_isSelfTreatment) then {
_configProperty = _configProperty + "Self";
@ -34,7 +29,9 @@ if (stance _unit == "PRONE") then {
_configProperty = _configProperty + "Prone";
};
private _anim = getText (_animConfig >> _configProperty);
private _anim = getText (configFile >> QEGVAR(medical_treatment,Actions) >> _actionName >> _configProperty);
if (_anim == "") exitWith { WARNING_2("no anim [%1, %2]",_actionName,_configProperty); };
private _wpn = switch (true) do {
case ((currentWeapon _unit) == ""): {"non"};
case ((currentWeapon _unit) == (primaryWeapon _unit)): {"rfl"};

View File

@ -1,12 +1,17 @@
// CBA Settings [ADDON: ace_medical_ai]:
private _categoryArray = [ELSTRING(medical,Category), "STR_TEAM_SWITCH_AI"];
[
QGVAR(enabledFor),
"LIST",
QGVAR(enabledFor), "LIST",
[LLSTRING(enableFor_title), LLSTRING(enableFor_desc)],
LLSTRING(settingCategory),
_categoryArray,
[
[0, 1, 2],
[LELSTRING(Common,Disabled), LLSTRING(enabledFor_OnlyServerAndHC), LELSTRING(Common,Enabled)],
2
],
true
true, // isGlobal
{[QGVAR(enabledFor), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_settings_fnc_init;

View File

@ -0,0 +1,67 @@
GVAR(stateMachine) = [{call EFUNC(common,getLocalUnits)}, true] call CBA_statemachine_fnc_create;
// Add states [statemachine, onState, onStateEntered, onStateLeaving, name]
[GVAR(stateMachine), {}, {}, {}, "Initial"] call CBA_statemachine_fnc_addState;
[GVAR(stateMachine), {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is injured", _this];
#endif
}, {}, {}, "Injured"] call CBA_statemachine_fnc_addState;
[GVAR(stateMachine), {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is injured and safe", _this];
#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;
// Add Transistions [statemachine, originalState, targetState, condition, onTransition, name]
[GVAR(stateMachine), "Initial", "Injured", LINKFUNC(isInjured), {}, "Injured"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "Initial", "HealUnit", {(call FUNC(isSafe)) && FUNC(wasRequested)}, {}, "HealUnit"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "Injured", "Safe", LINKFUNC(isSafe), {}, "InSafety"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "Safe", "HealSelf", LINKFUNC(canRequestMedic), LINKFUNC(requestMedic), "RequestMedic"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "Safe", "HealSelf", {true}, {}, "HealSelf"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "HealSelf", "Initial", { // Go back to initial state when done healing
!(call FUNC(isInjured)) && {isNil {_this getVariable QGVAR(currentTreatment)}}
}, {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 finished healing themself", _this];
#endif
}, "Initial"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "HealSelf", "Injured", { // Stop treating when it's no more safe
!(call FUNC(isSafe)) && {isNil {_this getVariable QGVAR(currentTreatment)}}
}, {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 is no longer safe", _this];
#endif
}, "Injured"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "HealUnit", "Initial", { // Go back to initial state when done healing or it's no more safe to treat
!((call FUNC(wasRequested)) && FUNC(isSafe)) && {isNil {_this getVariable QGVAR(currentTreatment)}}
}, {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 finished healing someone", _this];
#endif
}, "Initial"] call CBA_statemachine_fnc_addTransition;
[GVAR(stateMachine), "HealUnit", "Injured", { // Treating yourself has priority
(call FUNC(isInjured)) && {isNil {_this getVariable QGVAR(currentTreatment)}}
}, {
#ifdef DEBUG_MODE_FULL
systemChat format ["%1 was injured while healing someone", _this];
#endif
}, "Injured"] call CBA_statemachine_fnc_addTransition;

View File

@ -1,12 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="medical_ai">
<Key ID="STR_ACE_medical_ai_settingCategory">
<English>ACE Medical - AI</English>
<Japanese>ACE 医療 - AI</Japanese>
<Russian>ACE Медицина - ИИ</Russian>
<German>ACE Sanitäts - KI</German>
</Key>
<Key ID="STR_ACE_medical_ai_enableFor_title">
<English>Medic AI</English>
<German>Sanitäts KI</German>