mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Medical Statemachine - Improve edge case death handling (#8788)
* fix #8772 * add WARNING for dead/null units * fix macro * improve warnings * handle scripted death without warnings Co-authored-by: PabstMirror <pabstmirror@gmail.com> Co-authored-by: PabstMirror <pabstmirror@gmail.com>
This commit is contained in:
parent
90ebe08012
commit
9209fedcf7
@ -43,7 +43,7 @@ class ACE_Medical_StateMachine {
|
|||||||
};
|
};
|
||||||
class Unconscious {
|
class Unconscious {
|
||||||
onState = QFUNC(handleStateUnconscious);
|
onState = QFUNC(handleStateUnconscious);
|
||||||
onStateEntered = QUOTE([ARR_2(_this,true)] call EFUNC(medical_status,setUnconsciousState));
|
onStateEntered = QFUNC(enteredStateUnconscious);
|
||||||
class DeathAI {
|
class DeathAI {
|
||||||
targetState = "Dead";
|
targetState = "Dead";
|
||||||
condition = QUOTE(!GVAR(AIUnconsciousness) && {!isPlayer _this});
|
condition = QUOTE(!GVAR(AIUnconsciousness) && {!isPlayer _this});
|
||||||
|
@ -4,6 +4,7 @@ PREP(conditionSecondChance);
|
|||||||
PREP(enteredStateCardiacArrest);
|
PREP(enteredStateCardiacArrest);
|
||||||
PREP(enteredStateDeath);
|
PREP(enteredStateDeath);
|
||||||
PREP(enteredStateFatalInjury);
|
PREP(enteredStateFatalInjury);
|
||||||
|
PREP(enteredStateUnconscious);
|
||||||
PREP(handleStateCardiacArrest);
|
PREP(handleStateCardiacArrest);
|
||||||
PREP(handleStateDefault);
|
PREP(handleStateDefault);
|
||||||
PREP(handleStateInjured);
|
PREP(handleStateInjured);
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
params ["_unit"];
|
params ["_unit"];
|
||||||
|
if (isNull _unit || {!isNil {_unit getVariable QEGVAR(medical,causeOfDeath)}}) exitWith {
|
||||||
|
WARNING_1("enteredStateCardiacArrest: State transition on dead or null unit - %1",_unit);
|
||||||
|
};
|
||||||
|
|
||||||
// 10% possible variance in cardiac arrest time
|
// 10% possible variance in cardiac arrest time
|
||||||
private _time = GVAR(cardiacArrestTime);
|
private _time = GVAR(cardiacArrestTime);
|
||||||
|
@ -16,13 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
params ["_unit"];
|
params ["_unit"];
|
||||||
if (isNull _unit) exitWith {};
|
if (isNull _unit || {!isNil {_unit getVariable QEGVAR(medical,causeOfDeath)}}) exitWith {
|
||||||
|
if ((_unit getVariable [QEGVAR(medical,causeOfDeath), ""]) == "#scripted") exitWith {};
|
||||||
|
WARNING_1("enteredStateDeath: State transition on dead or null unit - %1",_unit);
|
||||||
|
};
|
||||||
|
|
||||||
//IGNORE_PRIVATE_WARNING ["_thisOrigin", "_thisTransition"]; // vars provided by CBA_statemachine
|
//IGNORE_PRIVATE_WARNING ["_thisOrigin", "_thisTransition"]; // vars provided by CBA_statemachine
|
||||||
TRACE_3("enteredStateDeath",_this,_thisOrigin,_thisTransition);
|
TRACE_4("enteredStateDeath",_this,_thisOrigin,_thisTransition,CBA_missionTime);
|
||||||
|
|
||||||
private _causeOfDeath = format ["%1:%2", _thisOrigin, _thisTransition];
|
private _causeOfDeath = format ["%1:%2", _thisOrigin, _thisTransition];
|
||||||
private _instigator = _unit getVariable [QEGVAR(medical,lastInstigator), objNull];
|
private _instigator = _unit getVariable [QEGVAR(medical,lastInstigator), objNull];
|
||||||
|
|
||||||
// could delay a frame here to fix the double killed EH, but we lose it being a "native" kill (scoreboard / rating)
|
|
||||||
[_unit, _causeOfDeath, _instigator] call EFUNC(medical_status,setDead);
|
[_unit, _causeOfDeath, _instigator] call EFUNC(medical_status,setDead);
|
||||||
|
@ -16,5 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
params ["_unit"];
|
params ["_unit"];
|
||||||
|
if (isNull _unit || {!isNil {_unit getVariable QEGVAR(medical,causeOfDeath)}}) exitWith {
|
||||||
|
WARNING_1("enteredStateFatalInjury: State transition on dead or null unit - %1",_unit);
|
||||||
|
};
|
||||||
|
|
||||||
[QEGVAR(medical,FatalInjuryInstantTransition), _unit] call CBA_fnc_localEvent;
|
[QEGVAR(medical,FatalInjuryInstantTransition), _unit] call CBA_fnc_localEvent;
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
#include "script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: GhostIsSpooky
|
||||||
|
* Handles a unit reaching the point of unconsciousness (calls for a status update).
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: The Unit <OBJECT>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [player] call ace_medical_statemachine_fnc_enteredStateUnconscious
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
params ["_unit"];
|
||||||
|
|
||||||
|
if (isNull _unit || {!isNil {_unit getVariable QEGVAR(medical,causeOfDeath)}}) exitWith {
|
||||||
|
WARNING_1("enteredStateUnconscious: State transition on dead or null unit - %1",_unit);
|
||||||
|
};
|
||||||
|
|
||||||
|
//IGNORE_PRIVATE_WARNING ["_thisOrigin", "_thisTransition"]; // vars provided by CBA_statemachine
|
||||||
|
TRACE_4("enteredStateUnconscious",_this,_thisOrigin,_thisTransition,CBA_missionTime);
|
||||||
|
|
||||||
|
[_unit, true] call EFUNC(medical_status,setUnconsciousState);
|
@ -18,8 +18,7 @@
|
|||||||
params ["_unit"];
|
params ["_unit"];
|
||||||
|
|
||||||
// If the unit died the loop is finished
|
// If the unit died the loop is finished
|
||||||
if (!alive _unit) exitWith {};
|
if (!alive _unit || {!local _unit}) exitWith {};
|
||||||
if (!local _unit) exitWith {};
|
|
||||||
|
|
||||||
[_unit] call EFUNC(medical_vitals,handleUnitVitals);
|
[_unit] call EFUNC(medical_vitals,handleUnitVitals);
|
||||||
|
|
||||||
@ -34,4 +33,3 @@ if (_timeDiff >= 1) then {
|
|||||||
_timeLeft = _timeLeft - _timeDiff; // negative values are fine
|
_timeLeft = _timeLeft - _timeDiff; // negative values are fine
|
||||||
_unit setVariable [QGVAR(cardiacArrestTimeLeft), _timeLeft];
|
_unit setVariable [QGVAR(cardiacArrestTimeLeft), _timeLeft];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,8 +18,7 @@
|
|||||||
params ["_unit"];
|
params ["_unit"];
|
||||||
|
|
||||||
// If the unit died the loop is finished
|
// If the unit died the loop is finished
|
||||||
if (!alive _unit) exitWith {};
|
if (!alive _unit || {!local _unit}) exitWith {};
|
||||||
if (!local _unit) exitWith {};
|
|
||||||
|
|
||||||
if ([_unit] call EFUNC(medical_vitals,handleUnitVitals)) then { // returns true when update ran
|
if ([_unit] call EFUNC(medical_vitals,handleUnitVitals)) then { // returns true when update ran
|
||||||
private _painLevel = GET_PAIN_PERCEIVED(_unit);
|
private _painLevel = GET_PAIN_PERCEIVED(_unit);
|
||||||
|
@ -18,8 +18,7 @@
|
|||||||
params ["_unit"];
|
params ["_unit"];
|
||||||
|
|
||||||
// If the unit died the loop is finished
|
// If the unit died the loop is finished
|
||||||
if (!alive _unit) exitWith {};
|
if (!alive _unit || {!local _unit}) exitWith {};
|
||||||
if (!local _unit) exitWith {};
|
|
||||||
|
|
||||||
if ([_unit] call EFUNC(medical_vitals,handleUnitVitals)) then { // returns true when update ran
|
if ([_unit] call EFUNC(medical_vitals,handleUnitVitals)) then { // returns true when update ran
|
||||||
private _painLevel = GET_PAIN_PERCEIVED(_unit);
|
private _painLevel = GET_PAIN_PERCEIVED(_unit);
|
||||||
|
@ -26,6 +26,12 @@ _unit setVariable [QEGVAR(medical,causeOfDeath), _reason, true];
|
|||||||
// Send a local event before death
|
// Send a local event before death
|
||||||
[QEGVAR(medical,death), [_unit]] call CBA_fnc_localEvent;
|
[QEGVAR(medical,death), [_unit]] call CBA_fnc_localEvent;
|
||||||
|
|
||||||
|
// Update the state machine if necessary (forced respawn, scripted death, etc)
|
||||||
|
private _unitState = [_unit, EGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
|
||||||
|
if (_unitState isNotEqualTo "Dead") then {
|
||||||
|
[_unit, EGVAR(medical,STATE_MACHINE), _unitState, "Dead"] call CBA_statemachine_fnc_manualTransition;
|
||||||
|
};
|
||||||
|
|
||||||
// (#8803) Reenable damage if disabled to prevent having live units in dead state
|
// (#8803) Reenable damage if disabled to prevent having live units in dead state
|
||||||
// Keep this after death event for compatibility with third party hooks
|
// Keep this after death event for compatibility with third party hooks
|
||||||
if !(isDamageAllowed _unit) then {
|
if !(isDamageAllowed _unit) then {
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* 1: Set unconscious <BOOL>
|
* 1: Set unconscious <BOOL>
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* Success <BOOL>
|
* None
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* [player, true] call ace_medical_status_fnc_setUnconsciousState
|
* [player, true] call ace_medical_status_fnc_setUnconsciousState
|
||||||
@ -21,7 +21,7 @@ params ["_unit", "_active"];
|
|||||||
TRACE_2("setUnconsciousState",_unit,_active);
|
TRACE_2("setUnconsciousState",_unit,_active);
|
||||||
|
|
||||||
// No change to make
|
// No change to make
|
||||||
if (_active isEqualTo IS_UNCONSCIOUS(_unit)) exitWith { TRACE_2("no change",_active,IS_UNCONSCIOUS(_unit)); };
|
if (_active isEqualTo IS_UNCONSCIOUS(_unit) || {!alive _unit}) exitWith { TRACE_2("no change",_active,IS_UNCONSCIOUS(_unit)); };
|
||||||
|
|
||||||
_unit setVariable [VAR_UNCON, _active, true];
|
_unit setVariable [VAR_UNCON, _active, true];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user