mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
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:
parent
aa41fffdb7
commit
05e4f74e73
@ -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;
|
||||
|
@ -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} \
|
||||
);
|
||||
};
|
||||
};
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
PREP(canRequestMedic);
|
||||
PREP(healingLogic);
|
||||
PREP(healSelf);
|
||||
PREP(healUnit);
|
||||
PREP(isInjured);
|
||||
|
@ -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;*/
|
||||
|
@ -16,4 +16,3 @@ class CfgPatches {
|
||||
|
||||
#include "ACE_Settings.hpp"
|
||||
#include "CfgEventHandlers.hpp"
|
||||
#include "StateMachine.hpp"
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
117
addons/medical_ai/functions/fnc_healingLogic.sqf
Normal file
117
addons/medical_ai/functions/fnc_healingLogic.sqf
Normal 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
|
@ -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}
|
||||
}
|
||||
|
@ -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"};
|
||||
|
@ -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;
|
||||
|
67
addons/medical_ai/stateMachine.sqf
Normal file
67
addons/medical_ai/stateMachine.sqf
Normal 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;
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user