mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Medical - Rework CPR and Bleeding in cardiac arrest (#7060)
* Medical - Rework CPR and Bleeding in cardiac arrest * remove cprCreatesPulse, add cprSuccessChance * hide cpr for basic diagnose * Update addons/medical_statemachine/functions/fnc_enteredStateCardiacArrest.sqf Co-Authored-By: SilentSpike <silentspike100+Github@gmail.com>
This commit is contained in:
parent
56cb638aff
commit
de13ab0f47
@ -19,12 +19,16 @@
|
||||
_return pushBack "";
|
||||
|
||||
// State:
|
||||
private _hasStableVitals = [_unit] call EFUNC(medical_status,hasStableVitals);
|
||||
private _targetState = [_unit, EGVAR(medical,STATE_MACHINE)] call CBA_statemachine_fnc_getCurrentState;
|
||||
if (!local _unit) then {_targetState = "NotLocal";};
|
||||
private _color = switch (_targetState) do {case "Default": {"33FF33"}; case "Injured": {"FF3333"}; case "Unconscious": {"FF8833"}; case "CardiacArrest": {"FF33AA"}; default {"555555"}};
|
||||
private _unconcFlag = if IS_UNCONSCIOUS(_unit) then {"[<t color='#FFFFFF'>U</t>]"} else {""};
|
||||
_return pushBack format ["<t color='#%1'>State: %2</t> [StableVitals: %3] %4", _color, _targetState, _hasStableVitals, _unconcFlag];
|
||||
_return pushBack format ["<t color='#%1'>State: %2</t>", _color, _targetState];
|
||||
private _hasStableVitals = ["N", "Y"] select ([_unit] call EFUNC(medical_status,hasStableVitals));
|
||||
private _hasStableCondition = ["N", "Y"] select ([_unit] call EFUNC(medical_status,isInStableCondition));
|
||||
private _unconcFlag = if IS_UNCONSCIOUS(_unit) then {"[<t color='#BBFFBB'>U</t>]"} else {""};
|
||||
private _timeLeft = _unit getVariable [QEGVAR(medical_statemachine,cardiacArrestTimeLeft), -1];
|
||||
private _cardiactArrestFlag = if IN_CRDC_ARRST(_unit) then {format ["[<t color='#BBBBFF'>CA</t> %1]", _timeLeft toFixed 1]} else {""};
|
||||
_return pushBack format ["[StableVitals: %1] [StableCon: %2] %3 %4", _hasStableVitals, _hasStableCondition, _unconcFlag, _cardiactArrestFlag];
|
||||
|
||||
// Blood:
|
||||
private _bloodVolume = GET_BLOOD_VOLUME(_unit);
|
||||
|
@ -18,5 +18,6 @@
|
||||
if (EGVAR(interact_menu,menuBackground) == 1) then {[QGVAR(id), false] call EFUNC(common,blurScreen)};
|
||||
if (EGVAR(interact_menu,menuBackground) == 2) then {(uiNamespace getVariable [QEGVAR(interact_menu,menuBackground), displayNull]) closeDisplay 0};
|
||||
|
||||
GVAR(pendingReopen) = false;
|
||||
GVAR(menuPFH) call CBA_fnc_removePerFrameHandler;
|
||||
GVAR(menuPFH) = -1;
|
||||
|
@ -86,6 +86,7 @@ class ACE_Medical_StateMachine {
|
||||
};
|
||||
};
|
||||
class CardiacArrest {
|
||||
onState = QFUNC(handleStateCardiacArrest);
|
||||
onStateEntered = QFUNC(enteredStateCardiacArrest);
|
||||
onStateLeaving = QFUNC(leftStateCardiacArrest);
|
||||
class DeathAI {
|
||||
|
@ -3,6 +3,7 @@ PREP(conditionExecutionDeath);
|
||||
PREP(enteredStateCardiacArrest);
|
||||
PREP(enteredStateDeath);
|
||||
PREP(enteredStateFatalInjury);
|
||||
PREP(handleStateCardiacArrest);
|
||||
PREP(handleStateDefault);
|
||||
PREP(handleStateInjured);
|
||||
PREP(handleStateUnconscious);
|
||||
|
@ -17,7 +17,4 @@
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
private _startTime = _unit getVariable [QGVAR(cardiacArrestStart), CBA_missionTime];
|
||||
private _lifeTime = _unit getVariable [QGVAR(cardiacArrestTime), GVAR(cardiacArrestTime)];
|
||||
|
||||
(CBA_missionTime - _startTime) > _lifeTime
|
||||
(_unit getVariable [QGVAR(cardiacArrestTimeLeft), -1]) <= 0
|
||||
|
@ -20,10 +20,12 @@ params ["_unit"];
|
||||
|
||||
// 10% possible variance in cardiac arrest time
|
||||
private _time = GVAR(cardiacArrestTime);
|
||||
_time = _time + random [_time*-0.1, 0, _time*0.1];
|
||||
_time = _time + _time * random [-0.1, 0, 0.1];
|
||||
|
||||
_unit setVariable [QGVAR(cardiacArrestTime), _time];
|
||||
_unit setVariable [QGVAR(cardiacArrestStart), CBA_missionTime];
|
||||
_unit setVariable [QGVAR(cardiacArrestTimeLeft), _time];
|
||||
_unit setVariable [QGVAR(cardiacArrestTimeLastUpdate), CBA_missionTime];
|
||||
|
||||
TRACE_3("enteredStateCardiacArrest",_unit,_time,CBA_missionTime);
|
||||
|
||||
// Update the unit status to reflect cardiac arrest
|
||||
[_unit, true] call EFUNC(medical_status,setCardiacArrest);
|
||||
|
@ -0,0 +1,37 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: BaerMitUmlaut
|
||||
* Handles the unconscious state
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [player] call ace_medical_statemachine_fnc_handleStateCardiacArrest
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
// If the unit died the loop is finished
|
||||
if (!alive _unit) exitWith {};
|
||||
if (!local _unit) exitWith {};
|
||||
|
||||
[_unit] call EFUNC(medical_vitals,handleUnitVitals);
|
||||
|
||||
private _timeDiff = CBA_missionTime - (_unit getVariable [QGVAR(cardiacArrestTimeLastUpdate), 0]);
|
||||
if (_timeDiff >= 1) then {
|
||||
_timeDiff = _timeDiff min 10;
|
||||
_unit setVariable [QGVAR(cardiacArrestTimeLastUpdate), CBA_missionTime];
|
||||
private _recieveingCPR = alive (_unit getVariable [QEGVAR(medical,CPR_provider), objNull]);
|
||||
private _timeLeft = _unit getVariable [QGVAR(cardiacArrestTimeLeft), -1];
|
||||
TRACE_3("cardiac arrest life tick",_unit,_recieveingCPR,_timeDiff);
|
||||
if (_recieveingCPR) then { _timeDiff = _timeDiff * 0.5; }; // if being cpr'ed, then time decrease is reduced
|
||||
_timeLeft = _timeLeft - _timeDiff; // negative values are fine
|
||||
_unit setVariable [QGVAR(cardiacArrestTimeLeft), _timeLeft];
|
||||
};
|
||||
|
@ -17,11 +17,9 @@
|
||||
*/
|
||||
|
||||
params ["_unit"];
|
||||
TRACE_1("leftStateCardiacArrest",_unit);
|
||||
|
||||
_unit setVariable [QGVAR(cardiacArrestTime), nil];
|
||||
_unit setVariable [QEGVAR(medical,cardiacArrestStart), nil];
|
||||
|
||||
// Temporary fix for vitals loop on cardiac arrest exit
|
||||
_unit setVariable [QGVAR(lastTimeUpdated), CBA_missionTime];
|
||||
_unit setVariable [QGVAR(cardiacArrestTimeLeft), nil];
|
||||
_unit setVariable [QGVAR(cardiacArrestTimeLastUpdate), nil];
|
||||
|
||||
[_unit, false] call EFUNC(medical_status,setCardiacArrest);
|
||||
|
@ -22,4 +22,5 @@ if (_woundBleeding == 0) exitWith {0};
|
||||
|
||||
private _cardiacOutput = [_unit] call FUNC(getCardiacOutput);
|
||||
|
||||
(_woundBleeding * _cardiacOutput * EGVAR(medical,bleedingCoefficient))
|
||||
// even if heart stops blood will still flow slowly (gravity)
|
||||
(_woundBleeding * (_cardiacOutput max 0.05) * EGVAR(medical,bleedingCoefficient))
|
||||
|
@ -7,7 +7,7 @@
|
||||
* 0: The Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* Current cardiac output (litre per second) <NUMBER>
|
||||
* Current cardiac output (liter per second) <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* [player] call ace_medical_status_fnc_getCardiacOutput
|
||||
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
Cardiac output (Q or or CO ) is the volume of blood being pumped by the heart, in particular by a left or right ventricle in the CBA_missionTime interval of one second. CO may be measured in many ways, for example dm3/min (1 dm3 equals 1 litre).
|
||||
Cardiac output (Q or or CO ) is the volume of blood being pumped by the heart, in particular by a left or right ventricle in the CBA_missionTime interval of one second. CO may be measured in many ways, for example dm3/min (1 dm3 equals 1 liter).
|
||||
Source: http://en.wikipedia.org/wiki/Cardiac_output
|
||||
*/
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
params ["_unit", "_active"];
|
||||
TRACE_2("setCardiacArrest",_unit,_active);
|
||||
|
||||
// No change to make
|
||||
if (_active isEqualTo IN_CRDC_ARRST(_unit)) exitWith {};
|
||||
|
@ -269,7 +269,7 @@ class GVAR(actions) {
|
||||
treatmentTime = 15;
|
||||
items[] = {};
|
||||
condition = QFUNC(canCPR);
|
||||
callbackSuccess = QFUNC(cpr);
|
||||
callbackSuccess = QFUNC(cprSuccess);
|
||||
callbackFailure = QFUNC(cprFailure);
|
||||
callbackProgress = QFUNC(cprProgress);
|
||||
callbackStart = QFUNC(cprStart);
|
||||
|
@ -2,9 +2,6 @@ class ACE_Settings {
|
||||
class EGVAR(medical,allowLitterCreation) {
|
||||
movedToSqf = 1;
|
||||
};
|
||||
class EGVAR(medical,CPRcreatesPulse) {
|
||||
movedToSqf = 1;
|
||||
};
|
||||
class EGVAR(medical,litterCleanUpDelay) {
|
||||
movedToSqf = 1;
|
||||
};
|
||||
|
@ -4,7 +4,6 @@ PREP(addToTriageCard);
|
||||
PREP(bandage);
|
||||
PREP(bandageLocal);
|
||||
PREP(bodyCleanupLoop);
|
||||
PREP(calculateBlood);
|
||||
PREP(canBandage);
|
||||
PREP(canCPR);
|
||||
PREP(canSplint);
|
||||
@ -17,7 +16,7 @@ PREP(checkItems);
|
||||
PREP(checkPulse);
|
||||
PREP(checkPulseLocal);
|
||||
PREP(checkResponse);
|
||||
PREP(cpr);
|
||||
PREP(cprSuccess);
|
||||
PREP(cprFailure);
|
||||
PREP(cprLocal);
|
||||
PREP(cprProgress);
|
||||
|
@ -1,29 +0,0 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: Zakant
|
||||
* Calculate the blood lost and blood volume for a unit. Used from CPR to simulate a heart rate while in cardiac arrest.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params["_unit"];
|
||||
|
||||
// We will just simulate blood flow for now!
|
||||
private _lastTimeUpdated = _unit getVariable [QEGVAR(medical,lastTimeUpdated), CBA_missionTime];
|
||||
private _deltaT = CBA_missionTime - _lastTimeUpdated;
|
||||
|
||||
private _lastTimeValuesSynced = _unit getVariable [QEGVAR(medical,lastMomentValuesSynced), 0];
|
||||
private _syncValues = (CBA_missionTime - _lastTimeValuesSynced) >= (10 + floor(random(10)));
|
||||
|
||||
_unit setVariable [QEGVAR(medical,lastTimeUpdated), CBA_missionTime];
|
||||
if (_deltaT != 0) then {
|
||||
private _change = ([_unit, _deltaT, _syncValues] call EFUNC(medical_status,getBloodVolumeChange));
|
||||
private _bloodVolume = 0 max (GET_BLOOD_VOLUME(_unit) + _change) min DEFAULT_BLOOD_VOLUME;
|
||||
_unit setVariable [VAR_BLOOD_VOL, _bloodVolume, _syncValues];
|
||||
};
|
@ -18,4 +18,6 @@
|
||||
|
||||
params ["", "_patient"];
|
||||
|
||||
!(_patient call EFUNC(common,isAwake)) && {!(_patient getVariable [QGVAR(isReceivingCPR), false])}
|
||||
!(_patient call EFUNC(common,isAwake))
|
||||
&& {(GVAR(advancedDiagnose)) || {IN_CRDC_ARRST(_patient)}} // if basic diagnose, then only show action if appropriate (they can't tell difference between uncon/ca)
|
||||
&& {isNull (_patient getVariable [QEGVAR(medical,CPR_provider), objNull])}
|
||||
|
@ -16,13 +16,7 @@
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["", "_patient"];
|
||||
params ["_medic", "_patient"];
|
||||
TRACE_2("cprFailure",_medic,_patient);
|
||||
|
||||
if (!(_patient call EFUNC(common,isAwake)) || {IN_CRDC_ARRST(_patient)}) then {
|
||||
_patient setVariable [VAR_HEART_RATE, 0, true];
|
||||
};
|
||||
|
||||
// Patient is no longer receiving CPR
|
||||
_patient setVariable [QGVAR(isReceivingCPR), false, true];
|
||||
|
||||
_patient call FUNC(calculateBlood);
|
||||
_patient setVariable [QEGVAR(medical,CPR_provider), objNull, true];
|
||||
|
@ -17,9 +17,14 @@
|
||||
*/
|
||||
|
||||
params ["_medic", "_patient"];
|
||||
TRACE_2("cprLocal",_medic,_patient);
|
||||
|
||||
[_patient, "activity", LSTRING(Activity_CPR), [[_medic, false, true] call EFUNC(common,getName)]] call FUNC(addToLog);
|
||||
|
||||
if (random 1 >= 0.6) then {
|
||||
if ((random 1) < GVAR(cprSuccessChance)) then {
|
||||
TRACE_1("CPR random success",GVAR(cprSuccessChance));
|
||||
[QEGVAR(medical,CPRSucceeded), _patient] call CBA_fnc_localEvent;
|
||||
} else {
|
||||
TRACE_1("CPR random fail",GVAR(cprSuccessChance));
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Arguments <ARRAY>
|
||||
* 0: Medic (not used) <OBJECT>
|
||||
* 0: Medic <OBJECT>
|
||||
* 1: Patient <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
@ -18,12 +18,10 @@
|
||||
*/
|
||||
|
||||
params ["_args"];
|
||||
_args params ["", "_patient"];
|
||||
_args params ["_medic", "_patient"];
|
||||
|
||||
// Cancel CPR is patient wakes up
|
||||
if (_patient getVariable EFUNC(common,isAwake) || {!IN_CRDC_ARRST(_patient)}) exitWith {false};
|
||||
// Cancel CPR if patient wakes up
|
||||
|
||||
// Calculate blood volume, if there is no pulse nothing happens
|
||||
_patient call FUNC(calculateBlood);
|
||||
|
||||
true
|
||||
!(_patient call EFUNC(common,isAwake))
|
||||
&& {(GVAR(advancedDiagnose)) || {IN_CRDC_ARRST(_patient)}} // if basic diagnose, then only show action if appropriate (they can't tell difference between uncon/ca)
|
||||
&& {_medic == (_patient getVariable [QEGVAR(medical,CPR_provider), objNull])}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Handles starting the CPR treatment.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Medic (not used) <OBJECT>
|
||||
* 0: Medic <OBJECT>
|
||||
* 1: Patient <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
@ -16,14 +16,7 @@
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["", "_patient"];
|
||||
params ["_medic", "_patient"];
|
||||
TRACE_2("cprStart",_medic,_patient);
|
||||
|
||||
// Prevent others from performing CPR
|
||||
_patient setVariable [QGVAR(isReceivingCPR), true, true];
|
||||
|
||||
// Create a random pulse based on setting
|
||||
if (GVAR(cprCreatesPulse) && {GET_HEART_RATE(_patient) == 0}) then {
|
||||
_patient setVariable [VAR_HEART_RATE, round random [25, 30, 35], true];
|
||||
};
|
||||
|
||||
_patient setVariable [QEGVAR(medical,lastTimeUpdated), CBA_missionTime, true];
|
||||
_patient setVariable [QEGVAR(medical,CPR_provider), _medic, true];
|
||||
|
@ -11,17 +11,19 @@
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [player, cursorObject] call ace_medical_treatment_fnc_cpr
|
||||
* [player, cursorObject] call ace_medical_treatment_fnc_cprSuccess
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_medic", "_patient"];
|
||||
TRACE_2("cprSuccess",_medic,_patient);
|
||||
|
||||
_patient setVariable [QGVAR(isReceivingCPR), false, true];
|
||||
_patient setVariable [VAR_HEART_RATE, 0, true];
|
||||
_patient call FUNC(calculateBlood);
|
||||
_patient setVariable [QEGVAR(medical,CPR_provider), objNull, true];
|
||||
|
||||
if (alive _patient && {IN_CRDC_ARRST(_patient)}) then {
|
||||
TRACE_1("sending cprLocal event",_patient);
|
||||
[QGVAR(cprLocal), [_medic, _patient], _patient] call CBA_fnc_targetEvent;
|
||||
} else {
|
||||
TRACE_1("not alive or in cardiac arrest",_patient);
|
||||
};
|
@ -38,15 +38,6 @@
|
||||
true
|
||||
] call CBA_settings_fnc_init;
|
||||
|
||||
[
|
||||
QGVAR(cprCreatesPulse),
|
||||
"CHECKBOX",
|
||||
[LSTRING(CPRCreatesPulse_DisplayName), LSTRING(CPRCreatesPulse_Description)],
|
||||
[ELSTRING(medical,Category), LSTRING(SubCategory_Treatment)],
|
||||
true,
|
||||
true
|
||||
] call CBA_settings_fnc_init;
|
||||
|
||||
// todo: should this setting differentiate between medical vehicles and facilities?
|
||||
[
|
||||
QGVAR(locationsBoostTraining),
|
||||
@ -165,6 +156,15 @@
|
||||
true
|
||||
] call CBA_settings_fnc_init;
|
||||
|
||||
[
|
||||
QGVAR(cprSuccessChance),
|
||||
"SLIDER",
|
||||
[LSTRING(cprSuccessChance_DisplayName), LSTRING(cprSuccessChance_Description)],
|
||||
[ELSTRING(medical,Category), LSTRING(SubCategory_Treatment)],
|
||||
[0, 1, 0.4, 2],
|
||||
true
|
||||
] call CBA_settings_fnc_init;
|
||||
|
||||
[
|
||||
QGVAR(allowLitterCreation),
|
||||
"CHECKBOX",
|
||||
|
@ -44,15 +44,6 @@
|
||||
<English>Enables extended, more in-depth medication handling. Also, enables the use of Adenosine and Atropine.</English>
|
||||
<Russian>Устанавливает расширенное использование лекарств</Russian>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_Treatment_CPRCreatesPulse_DisplayName">
|
||||
<English>CPR Creates Pulse</English>
|
||||
<German>HLW erzeugt einen Puls</German>
|
||||
<Japanese>心肺蘇生による脈</Japanese>
|
||||
<Russian>СЛР создаст пульс</Russian>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_Treatment_CPRCreatesPulse_Description">
|
||||
<English>Controls whether performing CPR creates a pulse for the patient.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_Treatment_LocationsBoostTraining_DisplayName">
|
||||
<English>Locations Boost Training</English>
|
||||
<Czech>Místa pro vylepšení zkušeností</Czech>
|
||||
@ -1939,6 +1930,12 @@
|
||||
<Chinesesimp>进行心肺复苏术中...</Chinesesimp>
|
||||
<Chinese>進行心肺復甦術中...</Chinese>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_Treatment_cprSuccessChance_DisplayName">
|
||||
<English>CPR Success Chance</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_Treatment_cprSuccessChance_Description">
|
||||
<English>Probability that cpr will be successful in restoring heart rhythm.</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Medical_Treatment_Actions_Blood4_1000">
|
||||
<English>Give Blood IV (1000ml)</English>
|
||||
<German>Bluttransfusion IV (1000ml)</German>
|
||||
|
@ -113,6 +113,7 @@ switch (true) do {
|
||||
TRACE_3("BloodVolume Fatal",_unit,BLOOD_VOLUME_FATAL,_bloodVolume);
|
||||
[QEGVAR(medical,Bleedout), _unit] call CBA_fnc_localEvent;
|
||||
};
|
||||
case (IN_CRDC_ARRST(_unit)): {}; // if in cardiac arrest just break now to avoid throwing unneeded events
|
||||
case (_hemorrhage == 4): {
|
||||
TRACE_3("Class IV Hemorrhage",_unit,_hemorrhage,_bloodVolume);
|
||||
[QEGVAR(medical,FatalVitals), _unit] call CBA_fnc_localEvent;
|
||||
|
@ -22,7 +22,15 @@ params ["_unit", "_hrTargetAdjustment", "_deltaT", "_syncValue"];
|
||||
|
||||
private _heartRate = GET_HEART_RATE(_unit);
|
||||
|
||||
if !IN_CRDC_ARRST(_unit) then {
|
||||
if IN_CRDC_ARRST(_unit) then {
|
||||
if (alive (_unit getVariable [QEGVAR(medical,CPR_provider), objNull])) then {
|
||||
if (_heartRate == 0) then { _syncValue = true }; // always sync on large change
|
||||
_heartRate = random [25, 30, 35];
|
||||
} else {
|
||||
if (_heartRate != 0) then { _syncValue = true }; // always sync on large change
|
||||
_heartRate = 0
|
||||
};
|
||||
} else {
|
||||
private _hrChange = 0;
|
||||
private _targetHR = 0;
|
||||
private _bloodVolume = GET_BLOOD_VOLUME(_unit);
|
||||
|
Loading…
Reference in New Issue
Block a user