From d451da60c67eb209d726f99658c689e8dba496ba Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Sun, 3 Sep 2023 22:35:58 -0600 Subject: [PATCH 01/24] spo2 initial --- .../functions/fnc_mainLoop.sqf | 20 +++-- .../medical_engine/script_macros_medical.hpp | 3 + addons/medical_vitals/CfgVehicles.hpp | 6 ++ addons/medical_vitals/XEH_PREP.hpp | 1 + addons/medical_vitals/config.cpp | 1 + .../functions/fnc_handleUnitVitals.sqf | 3 + .../functions/fnc_updateHeartRate.sqf | 6 +- .../functions/fnc_updateOxygen.sqf | 77 +++++++++++++++++++ addons/medical_vitals/script_component.hpp | 2 + addons/weather/XEH_PREP.hpp | 2 +- .../functions/fnc_calculateOxygenDensity.sqf | 20 +++++ 11 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 addons/medical_vitals/CfgVehicles.hpp create mode 100644 addons/medical_vitals/functions/fnc_updateOxygen.sqf create mode 100644 addons/weather/functions/fnc_calculateOxygenDensity.sqf diff --git a/addons/advanced_fatigue/functions/fnc_mainLoop.sqf b/addons/advanced_fatigue/functions/fnc_mainLoop.sqf index f831bb67f36..b908e4f19df 100644 --- a/addons/advanced_fatigue/functions/fnc_mainLoop.sqf +++ b/addons/advanced_fatigue/functions/fnc_mainLoop.sqf @@ -23,6 +23,12 @@ if (!alive ACE_player) exitWith { _staminaBarContainer ctrlCommit 1; }; +private _oxygen = if (missionNamespace getVariable ["ace_medical", false]) then { + (ACE_player getVariable [QEGVAR(medical,spo2), 90]) / 100 +} else { + 0.9 +}; + private _currentWork = REE; private _currentSpeed = (vectorMagnitude (velocity ACE_player)) min 6; @@ -42,8 +48,8 @@ GVAR(muscleDamage) = (GVAR(muscleDamage) + (_currentWork / GVAR(peakPower)) ^ 3. private _muscleIntegritySqrt = sqrt (1 - GVAR(muscleDamage)); // Calculate available power -private _ae1PathwayPowerFatigued = GVAR(ae1PathwayPower) * sqrt (GVAR(ae1Reserve) / AE1_MAXRESERVE) * OXYGEN * _muscleIntegritySqrt; -private _ae2PathwayPowerFatigued = GVAR(ae2PathwayPower) * sqrt (GVAR(ae2Reserve) / AE2_MAXRESERVE) * OXYGEN * _muscleIntegritySqrt; +private _ae1PathwayPowerFatigued = GVAR(ae1PathwayPower) * sqrt (GVAR(ae1Reserve) / AE1_MAXRESERVE) * _oxygen * _muscleIntegritySqrt; +private _ae2PathwayPowerFatigued = GVAR(ae2PathwayPower) * sqrt (GVAR(ae2Reserve) / AE2_MAXRESERVE) * _oxygen * _muscleIntegritySqrt; // Calculate how much power is consumed from each reserve private _ae1Power = _currentWork min _ae1PathwayPowerFatigued; @@ -58,8 +64,8 @@ GVAR(anReserve) = GVAR(anReserve) - _anPower / WATTSPERATP; GVAR(anFatigue) = GVAR(anFatigue) + _anPower * (0.057 / GVAR(peakPower)) * 1.1; // Aerobic ATP reserve recovery -GVAR(ae1Reserve) = ((GVAR(ae1Reserve) + OXYGEN * 6.60 * (GVAR(ae1PathwayPower) - _ae1Power) / GVAR(ae1PathwayPower) * GVAR(recoveryFactor)) min AE1_MAXRESERVE) max 0; -GVAR(ae2Reserve) = ((GVAR(ae2Reserve) + OXYGEN * 5.83 * (GVAR(ae2PathwayPower) - _ae2Power) / GVAR(ae2PathwayPower) * GVAR(recoveryFactor)) min AE2_MAXRESERVE) max 0; +GVAR(ae1Reserve) = ((GVAR(ae1Reserve) + _oxygen * 6.60 * (GVAR(ae1PathwayPower) - _ae1Power) / GVAR(ae1PathwayPower) * GVAR(recoveryFactor)) min AE1_MAXRESERVE) max 0; +GVAR(ae2Reserve) = ((GVAR(ae2Reserve) + _oxygen * 5.83 * (GVAR(ae2PathwayPower) - _ae2Power) / GVAR(ae2PathwayPower) * GVAR(recoveryFactor)) min AE2_MAXRESERVE) max 0; // Anaerobic ATP reserver and fatigue recovery GVAR(anReserve) = ((GVAR(anReserve) @@ -70,9 +76,9 @@ GVAR(anFatigue) = ((GVAR(anFatigue) - (_ae1PathwayPowerFatigued + _ae2PathwayPowerFatigued - _ae1Power - _ae2Power) * (0.057 / GVAR(peakPower)) * GVAR(anFatigue) ^ 2 * GVAR(recoveryFactor) ) min 1) max 0; -private _aeReservePercentage = (GVAR(ae1Reserve) / AE1_MAXRESERVE + GVAR(ae2Reserve) / AE2_MAXRESERVE) / 2; -private _anReservePercentage = GVAR(anReserve) / AN_MAXRESERVE; -private _perceivedFatigue = 1 - (_anReservePercentage min _aeReservePercentage); +GVAR(aeReservePercentage) = (GVAR(ae1Reserve) / AE1_MAXRESERVE + GVAR(ae2Reserve) / AE2_MAXRESERVE) / 2; +GVAR(anReservePercentage) = GVAR(anReserve) / AN_MAXRESERVE; +private _perceivedFatigue = 1 - (GVAR(anReservePercentage) min GVAR(aeReservePercentage)); [ACE_player, _perceivedFatigue, _currentSpeed, GVAR(anReserve) == 0] call FUNC(handleEffects); diff --git a/addons/medical_engine/script_macros_medical.hpp b/addons/medical_engine/script_macros_medical.hpp index 2924d83b132..df80c8c7102 100644 --- a/addons/medical_engine/script_macros_medical.hpp +++ b/addons/medical_engine/script_macros_medical.hpp @@ -42,6 +42,7 @@ #define GET_ARRAY(config,default) (if (isArray (config)) then {getArray (config)} else {default}) #define DEFAULT_HEART_RATE 80 +#define DEFAULT_SPO2 97 #define DEFAULT_PERIPH_RES 100 // --- blood @@ -141,6 +142,7 @@ #define VAR_WOUND_BLEEDING QEGVAR(medical,woundBleeding) #define VAR_CRDC_ARRST QEGVAR(medical,inCardiacArrest) #define VAR_HEART_RATE QEGVAR(medical,heartRate) +#define VAR_SPO2 QEGVAR(medical,spo2) #define VAR_PAIN QEGVAR(medical,pain) #define VAR_PAIN_SUPP QEGVAR(medical,painSuppress) #define VAR_PERIPH_RES QEGVAR(medical,peripheralResistance) @@ -163,6 +165,7 @@ #define GET_BLOOD_VOLUME(unit) (unit getVariable [VAR_BLOOD_VOL, DEFAULT_BLOOD_VOLUME]) #define GET_WOUND_BLEEDING(unit) (unit getVariable [VAR_WOUND_BLEEDING, 0]) #define GET_HEART_RATE(unit) (unit getVariable [VAR_HEART_RATE, DEFAULT_HEART_RATE]) +#define GET_SPO2(unit) (unit getVariable [VAR_SPO2, DEFAULT_SPO2]) #define GET_HEMORRHAGE(unit) (unit getVariable [VAR_HEMORRHAGE, 0]) #define GET_PAIN(unit) (unit getVariable [VAR_PAIN, 0]) #define GET_PAIN_SUPPRESS(unit) (unit getVariable [VAR_PAIN_SUPP, 0]) diff --git a/addons/medical_vitals/CfgVehicles.hpp b/addons/medical_vitals/CfgVehicles.hpp new file mode 100644 index 00000000000..85bd94c1b9f --- /dev/null +++ b/addons/medical_vitals/CfgVehicles.hpp @@ -0,0 +1,6 @@ +class CfgWeapons { + class H_HelmetB; + class H_PilotHelmetFighter_B: H_HelmetB { + GVAR(oxygenSupply) = QUOTE(vehicle _this isKindOf 'Plane' || vehicle _this isKindOf 'Helicopter'); + }; +}; diff --git a/addons/medical_vitals/XEH_PREP.hpp b/addons/medical_vitals/XEH_PREP.hpp index 8f8c4277518..bb6fd48b62b 100644 --- a/addons/medical_vitals/XEH_PREP.hpp +++ b/addons/medical_vitals/XEH_PREP.hpp @@ -1,4 +1,5 @@ PREP(handleUnitVitals); PREP(updateHeartRate); +PREP(updateOxygen); PREP(updatePainSuppress); PREP(updatePeripheralResistance); diff --git a/addons/medical_vitals/config.cpp b/addons/medical_vitals/config.cpp index 91995242c9c..8f4cff8e8ab 100644 --- a/addons/medical_vitals/config.cpp +++ b/addons/medical_vitals/config.cpp @@ -15,3 +15,4 @@ class CfgPatches { }; #include "CfgEventHandlers.hpp" +#include "CfgVehicles.hpp" diff --git a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf index 5c6e0982691..3f9c9507d89 100644 --- a/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf +++ b/addons/medical_vitals/functions/fnc_handleUnitVitals.sqf @@ -31,6 +31,9 @@ if (_syncValues) then { _unit setVariable [QGVAR(lastMomentValuesSynced), CBA_missionTime]; }; +// Update SPO2 intake and usage since last update +[_unit, _deltaT, _syncValues] call FUNC(updateOxygen); + private _bloodVolume = GET_BLOOD_VOLUME(_unit) + ([_unit, _deltaT, _syncValues] call EFUNC(medical_status,getBloodVolumeChange)); _bloodVolume = 0 max _bloodVolume min DEFAULT_BLOOD_VOLUME; diff --git a/addons/medical_vitals/functions/fnc_updateHeartRate.sqf b/addons/medical_vitals/functions/fnc_updateHeartRate.sqf index 4da8519077f..e39449b7b31 100644 --- a/addons/medical_vitals/functions/fnc_updateHeartRate.sqf +++ b/addons/medical_vitals/functions/fnc_updateHeartRate.sqf @@ -37,6 +37,7 @@ if IN_CRDC_ARRST(_unit) then { if (_bloodVolume > BLOOD_VOLUME_CLASS_4_HEMORRHAGE) then { GET_BLOOD_PRESSURE(_unit) params ["_bloodPressureL", "_bloodPressureH"]; private _meanBP = (2/3) * _bloodPressureH + (1/3) * _bloodPressureL; + private _spo2 = GET_SPO2(_unit); private _painLevel = GET_PAIN_PERCEIVED(_unit); private _targetBP = 107; @@ -51,8 +52,11 @@ if IN_CRDC_ARRST(_unit) then { if (_painLevel > 0.2) then { _targetHR = _targetHR max (80 + 50 * _painLevel); }; + // Increase HR to compensate for low blood oxygen + // Increase HR to compensate for higher oxygen demand (e.g. running, recovering from sprint) + private _oxygenDemand = _unit getVariable [QGVAR(oxygenDemand), 0]; + _targetHR = _targetHR + ((97 - _spo2) * 2) + (_oxygenDemand * -1000); _targetHR = (_targetHR + _hrTargetAdjustment) max 0; - _hrChange = round(_targetHR - _heartRate) / 2; } else { _hrChange = -round(_heartRate / 10); diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf new file mode 100644 index 00000000000..fd36a99c710 --- /dev/null +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -0,0 +1,77 @@ +#include "script_component.hpp" +/* + * Author: Brett Mayson + * Update the oxygen levels + * + * Arguments: + * 0: The Unit + * 1: Time since last update + * 2: Sync value? + * + * ReturnValue: + * Current SPO2 + * + * Example: + * [player, 1, false] call ace_medical_vitals_fnc_updateOxygen + * + * Public: No + */ + +params ["_unit", "_deltaT", "_syncValue"]; + +private _current = GET_SPO2(_unit); +private _heartRate = GET_HEART_RATE(_unit); + +private _altitude = (getPosASL _unit) select 2; +private _po2 = if (missionNamespace getVariable ["ace_weather", false]) then { + private _temperature = _altitude call EFUNC(weather,calculateTemperatureAtHeight); + private _pressure = _altitude call EFUNC(weather,calculateBarometricPressure); + systemChat format ["Pressure: %1, Temperatue: %2", _pressure, _temperature]; + [_temperature, _pressure, EGVAR(weather,currentHumidity)] call EFUNC(weather,calculateOxygenDensity) +} else { + // Rough approximation of the partial pressure of oxygen in the air + 0.25725 * (_altitude / 1000 + 1) +}; + +private _oxygenSaturation = (0.255 min _po2) / 0.255; + +// Check gear for oxygen supply +[goggles _unit, headgear _unit] findIf { + if (_x != "") then { + private _condition = getText (configFile >> "CfgWeapons" >> _x >> QGVAR(oxygenSupply)); + if (_condition != "" && {ace_player call compile _condition}) then { + _oxygenSaturation = 1; + _po2 = 0.255; + true + } else { + false + } + } else { + false + } +}; + +// Base oxygen consumption rate +private _negativeChange = BASE_OXYGEN_USE; + +// Fatigue will demand more oxygen +if (missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]) then { + _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.5); +}; + +private _capture = 1 max ((_po2 / 0.255) ^ (-_po2 * 0.2)); +private _positiveChange = _heartRate * 0.00368 * _oxygenSaturation * _capture; + +private _breathingEffectiveness = 1; + +private _rateOfChange = _negativeChange + (_positiveChange * _breathingEffectiveness); + +// We want to compensate even further when spo2 is dropping +if (_rateOfChange < 0) then { _negativeChange + _rateOfChange } else {0} + +private _spo2 = _current + (_rateOfChange * _deltaT); +_spo2 = _spo2 max 0; +_spo2 = _spo2 min 100; + +_unit setVariable [QGVAR(oxygenDemand), _negativeChange - BASE_OXYGEN_USE]; +_unit setVariable [VAR_SPO2, _spo2, _syncValue]; diff --git a/addons/medical_vitals/script_component.hpp b/addons/medical_vitals/script_component.hpp index 3bfb4bcc269..1064ebc52cc 100644 --- a/addons/medical_vitals/script_component.hpp +++ b/addons/medical_vitals/script_component.hpp @@ -16,3 +16,5 @@ #include "\z\ace\addons\medical_engine\script_macros_medical.hpp" #include "\z\ace\addons\main\script_macros.hpp" + +#define BASE_OXYGEN_USE -0.25 diff --git a/addons/weather/XEH_PREP.hpp b/addons/weather/XEH_PREP.hpp index 5f17905849b..220a18ef3c5 100644 --- a/addons/weather/XEH_PREP.hpp +++ b/addons/weather/XEH_PREP.hpp @@ -1,9 +1,9 @@ - PREP(calculateAirDensity); PREP(calculateBarometricPressure); PREP(calculateDensityAltitude); PREP(calculateDewPoint); PREP(calculateHeatIndex); +PREP(calculateOxygenDensity); PREP(calculateRoughnessLength); PREP(calculateSpeedOfSound); PREP(calculateTemperatureAtHeight); diff --git a/addons/weather/functions/fnc_calculateOxygenDensity.sqf b/addons/weather/functions/fnc_calculateOxygenDensity.sqf new file mode 100644 index 00000000000..e7ec4c1971a --- /dev/null +++ b/addons/weather/functions/fnc_calculateOxygenDensity.sqf @@ -0,0 +1,20 @@ +#include "script_component.hpp" +/* + * Author: Brett Mayson + * Calculates the oxygen density + * + * Arguments: + * 0: temperature - degrees celsius + * 1: pressure - hPa + * 2: relativeHumidity - value between 0.0 and 1.0 + * + * Return Value: + * density of oxygen - kg * m^(-3) + * + * Example: + * [0, 1020] call ace_weather_fnc_calculateOxygenDensity + * + * Public: No + */ + +(_this call FUNC(calculateAirDensity)) * 0.21 From 93b3f9aba390be8efbb61ef45472900156cc49dc Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Sun, 3 Sep 2023 22:45:31 -0600 Subject: [PATCH 02/24] remove missed systemChat --- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index fd36a99c710..8c39bfae283 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -26,7 +26,6 @@ private _altitude = (getPosASL _unit) select 2; private _po2 = if (missionNamespace getVariable ["ace_weather", false]) then { private _temperature = _altitude call EFUNC(weather,calculateTemperatureAtHeight); private _pressure = _altitude call EFUNC(weather,calculateBarometricPressure); - systemChat format ["Pressure: %1, Temperatue: %2", _pressure, _temperature]; [_temperature, _pressure, EGVAR(weather,currentHumidity)] call EFUNC(weather,calculateOxygenDensity) } else { // Rough approximation of the partial pressure of oxygen in the air From 1f4a0adb873deaccc9101b7ba84b34b3869077e2 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Sun, 3 Sep 2023 22:51:29 -0600 Subject: [PATCH 03/24] some minor cleanup --- .../medical_vitals/functions/fnc_updateOxygen.sqf | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index 8c39bfae283..b3072c6a256 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -19,6 +19,8 @@ params ["_unit", "_deltaT", "_syncValue"]; +#define IDEAL_PPO2 0.255 + private _current = GET_SPO2(_unit); private _heartRate = GET_HEART_RATE(_unit); @@ -32,7 +34,7 @@ private _po2 = if (missionNamespace getVariable ["ace_weather", false]) then { 0.25725 * (_altitude / 1000 + 1) }; -private _oxygenSaturation = (0.255 min _po2) / 0.255; +private _oxygenSaturation = (IDEAL_PPO2 min _po2) / IDEAL_PPO2; // Check gear for oxygen supply [goggles _unit, headgear _unit] findIf { @@ -40,7 +42,7 @@ private _oxygenSaturation = (0.255 min _po2) / 0.255; private _condition = getText (configFile >> "CfgWeapons" >> _x >> QGVAR(oxygenSupply)); if (_condition != "" && {ace_player call compile _condition}) then { _oxygenSaturation = 1; - _po2 = 0.255; + _po2 = IDEAL_PPO2; true } else { false @@ -58,7 +60,10 @@ if (missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]) then _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.5); }; -private _capture = 1 max ((_po2 / 0.255) ^ (-_po2 * 0.2)); +// Effectiveness of capturing oxygen +// increases slightly as po2 starts lowering +// but falls off quickly as po2 drops further +private _capture = 1 max ((_po2 / IDEAL_PPO2) ^ (-_po2 * 0.2)); private _positiveChange = _heartRate * 0.00368 * _oxygenSaturation * _capture; private _breathingEffectiveness = 1; @@ -66,7 +71,9 @@ private _breathingEffectiveness = 1; private _rateOfChange = _negativeChange + (_positiveChange * _breathingEffectiveness); // We want to compensate even further when spo2 is dropping -if (_rateOfChange < 0) then { _negativeChange + _rateOfChange } else {0} +if (_rateOfChange < 0) then { + _negativeChange + _rateOfChange +}; private _spo2 = _current + (_rateOfChange * _deltaT); _spo2 = _spo2 max 0; From c064ae08456bebfe8d377930180a5cdcdf480f71 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Thu, 7 Sep 2023 19:21:39 -0600 Subject: [PATCH 04/24] review suggestions, effectiveness changes --- .hemtt/project.toml | 7 +++++++ .../functions/fnc_mainLoop.sqf | 6 +----- .../functions/fnc_updateOxygen.sqf | 19 +++++++++++-------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/.hemtt/project.toml b/.hemtt/project.toml index a8e50e494d7..8ae4f2a35b0 100644 --- a/.hemtt/project.toml +++ b/.hemtt/project.toml @@ -44,3 +44,10 @@ workshop = [ dlc = [ "S.O.G. Prairie Fire", ] + +[hemtt.launch.cup] +workshop = [ + "450814997", # CBA_A3's Workshop ID + "583496184", # CUP Terrains - Core + "583544987", # CUP Terrains - Maps +] diff --git a/addons/advanced_fatigue/functions/fnc_mainLoop.sqf b/addons/advanced_fatigue/functions/fnc_mainLoop.sqf index b908e4f19df..3d7b7570a87 100644 --- a/addons/advanced_fatigue/functions/fnc_mainLoop.sqf +++ b/addons/advanced_fatigue/functions/fnc_mainLoop.sqf @@ -23,11 +23,7 @@ if (!alive ACE_player) exitWith { _staminaBarContainer ctrlCommit 1; }; -private _oxygen = if (missionNamespace getVariable ["ace_medical", false]) then { - (ACE_player getVariable [QEGVAR(medical,spo2), 90]) / 100 -} else { - 0.9 -}; +private _oxygen = (ACE_player getVariable [QEGVAR(medical,spo2), 90]) / 100; private _currentWork = REE; private _currentSpeed = (vectorMagnitude (velocity ACE_player)) min 6; diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index b3072c6a256..3c062d00290 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -24,7 +24,7 @@ params ["_unit", "_deltaT", "_syncValue"]; private _current = GET_SPO2(_unit); private _heartRate = GET_HEART_RATE(_unit); -private _altitude = (getPosASL _unit) select 2; +private _altitude = EGVAR(common,mapAltitude) + ((getPosASL _unit) select 2); private _po2 = if (missionNamespace getVariable ["ace_weather", false]) then { private _temperature = _altitude call EFUNC(weather,calculateTemperatureAtHeight); private _pressure = _altitude call EFUNC(weather,calculateBarometricPressure); @@ -39,8 +39,13 @@ private _oxygenSaturation = (IDEAL_PPO2 min _po2) / IDEAL_PPO2; // Check gear for oxygen supply [goggles _unit, headgear _unit] findIf { if (_x != "") then { - private _condition = getText (configFile >> "CfgWeapons" >> _x >> QGVAR(oxygenSupply)); - if (_condition != "" && {ace_player call compile _condition}) then { + if (isNil QGVAR(oxygenSupplyConditionCache)) then { + GVAR(oxygenSupplyConditionCache) = createHashmap; + }; + private _condition = GVAR(oxygenSupplyConditionCache) getOrDefaultCall [_x, { + compile getText (configFile >> "CfgWeapons" >> _x >> QGVAR(oxygenSupply)) + }, true]; + if (_condition isNotEqualTo {} && {ACE_player call _condition}) then { _oxygenSaturation = 1; _po2 = IDEAL_PPO2; true @@ -56,14 +61,14 @@ private _oxygenSaturation = (IDEAL_PPO2 min _po2) / IDEAL_PPO2; private _negativeChange = BASE_OXYGEN_USE; // Fatigue will demand more oxygen -if (missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]) then { +if (_unit == player && {missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]}) then { _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.5); }; // Effectiveness of capturing oxygen // increases slightly as po2 starts lowering // but falls off quickly as po2 drops further -private _capture = 1 max ((_po2 / IDEAL_PPO2) ^ (-_po2 * 0.2)); +private _capture = 1 max ((_po2 / IDEAL_PPO2) ^ (-_po2 * 3)); private _positiveChange = _heartRate * 0.00368 * _oxygenSaturation * _capture; private _breathingEffectiveness = 1; @@ -75,9 +80,7 @@ if (_rateOfChange < 0) then { _negativeChange + _rateOfChange }; -private _spo2 = _current + (_rateOfChange * _deltaT); -_spo2 = _spo2 max 0; -_spo2 = _spo2 min 100; +private _spo2 = (_current + (_rateOfChange * _deltaT)) max 0 min 100; _unit setVariable [QGVAR(oxygenDemand), _negativeChange - BASE_OXYGEN_USE]; _unit setVariable [VAR_SPO2, _spo2, _syncValue]; From 3bb589e4ea8d25061eebb07c506c05194a914a95 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Thu, 7 Sep 2023 19:23:02 -0600 Subject: [PATCH 05/24] cleanup --- .hemtt/project.toml | 7 ------- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 5 ----- 2 files changed, 12 deletions(-) diff --git a/.hemtt/project.toml b/.hemtt/project.toml index 8ae4f2a35b0..a8e50e494d7 100644 --- a/.hemtt/project.toml +++ b/.hemtt/project.toml @@ -44,10 +44,3 @@ workshop = [ dlc = [ "S.O.G. Prairie Fire", ] - -[hemtt.launch.cup] -workshop = [ - "450814997", # CBA_A3's Workshop ID - "583496184", # CUP Terrains - Core - "583544987", # CUP Terrains - Maps -] diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index 3c062d00290..b2dcfb869eb 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -75,11 +75,6 @@ private _breathingEffectiveness = 1; private _rateOfChange = _negativeChange + (_positiveChange * _breathingEffectiveness); -// We want to compensate even further when spo2 is dropping -if (_rateOfChange < 0) then { - _negativeChange + _rateOfChange -}; - private _spo2 = (_current + (_rateOfChange * _deltaT)) max 0 min 100; _unit setVariable [QGVAR(oxygenDemand), _negativeChange - BASE_OXYGEN_USE]; From 83054a351cfa61bfe3f5f1f933966d0c16f336cf Mon Sep 17 00:00:00 2001 From: Grim <69561145+LinkIsGrim@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:54:46 -0400 Subject: [PATCH 06/24] fatigue compatibility with RC units Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com> --- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index b2dcfb869eb..3e1e52aed9c 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -61,7 +61,7 @@ private _oxygenSaturation = (IDEAL_PPO2 min _po2) / IDEAL_PPO2; private _negativeChange = BASE_OXYGEN_USE; // Fatigue will demand more oxygen -if (_unit == player && {missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]}) then { +if (_unit == ACE_player && {missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]}) then { _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.5); }; From e79e6b31306bc11cf461d3340f26103f3c226d8c Mon Sep 17 00:00:00 2001 From: Grim <69561145+LinkIsGrim@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:55:48 -0400 Subject: [PATCH 07/24] Rename CfgVehicles.hpp to CfgWeapons.hpp --- addons/medical_vitals/{CfgVehicles.hpp => CfgWeapons.hpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename addons/medical_vitals/{CfgVehicles.hpp => CfgWeapons.hpp} (100%) diff --git a/addons/medical_vitals/CfgVehicles.hpp b/addons/medical_vitals/CfgWeapons.hpp similarity index 100% rename from addons/medical_vitals/CfgVehicles.hpp rename to addons/medical_vitals/CfgWeapons.hpp From c901cab9f82ab2ecfbb0c0b15a1fb05b38f07786 Mon Sep 17 00:00:00 2001 From: Grim <69561145+LinkIsGrim@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:56:19 -0400 Subject: [PATCH 08/24] CfgWeapons --- addons/medical_vitals/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_vitals/config.cpp b/addons/medical_vitals/config.cpp index 3eefccc2b92..6e33cfef436 100644 --- a/addons/medical_vitals/config.cpp +++ b/addons/medical_vitals/config.cpp @@ -22,6 +22,6 @@ class CfgPatches { }; #include "CfgEventHandlers.hpp" -#include "CfgVehicles.hpp" +#include "CfgWeapons.hpp" #endif From f898a0c28f7b42df92bbda7e5675c315257ad1d5 Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Thu, 26 Oct 2023 14:00:02 -0400 Subject: [PATCH 09/24] fix script_component --- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 2 +- addons/weather/functions/fnc_calculateOxygenDensity.sqf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index 3e1e52aed9c..f2650bdd0cb 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -1,4 +1,4 @@ -#include "script_component.hpp" +#include "..\script_component.hpp" /* * Author: Brett Mayson * Update the oxygen levels diff --git a/addons/weather/functions/fnc_calculateOxygenDensity.sqf b/addons/weather/functions/fnc_calculateOxygenDensity.sqf index e7ec4c1971a..70d92db61c2 100644 --- a/addons/weather/functions/fnc_calculateOxygenDensity.sqf +++ b/addons/weather/functions/fnc_calculateOxygenDensity.sqf @@ -1,4 +1,4 @@ -#include "script_component.hpp" +#include "..\script_component.hpp" /* * Author: Brett Mayson * Calculates the oxygen density From 46580590fe7267e8ee87ea93a0119cf3df3d09ee Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Thu, 26 Oct 2023 14:02:54 -0400 Subject: [PATCH 10/24] switch to weather enabled setting --- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index f2650bdd0cb..da2d579a716 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -25,7 +25,7 @@ private _current = GET_SPO2(_unit); private _heartRate = GET_HEART_RATE(_unit); private _altitude = EGVAR(common,mapAltitude) + ((getPosASL _unit) select 2); -private _po2 = if (missionNamespace getVariable ["ace_weather", false]) then { +private _po2 = if (missionNamespace getVariable [QEGVAR(weather,enabled), false]) then { private _temperature = _altitude call EFUNC(weather,calculateTemperatureAtHeight); private _pressure = _altitude call EFUNC(weather,calculateBarometricPressure); [_temperature, _pressure, EGVAR(weather,currentHumidity)] call EFUNC(weather,calculateOxygenDensity) From db8d2ccff8f47477c7ce74eafe7fa0d9d6802064 Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Thu, 26 Oct 2023 14:42:01 -0400 Subject: [PATCH 11/24] move condition cache to preStart, add vest support --- addons/medical_vitals/CfgWeapons.hpp | 4 ++++ addons/medical_vitals/XEH_PREP.hpp | 1 + addons/medical_vitals/XEH_preInit.sqf | 2 ++ addons/medical_vitals/XEH_preStart.sqf | 6 +++++ .../functions/fnc_scanConfig.sqf | 23 ++++++++++++++++++ .../functions/fnc_updateOxygen.sqf | 24 ++++++------------- 6 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 addons/medical_vitals/functions/fnc_scanConfig.sqf diff --git a/addons/medical_vitals/CfgWeapons.hpp b/addons/medical_vitals/CfgWeapons.hpp index 85bd94c1b9f..5c6e4c9fd8e 100644 --- a/addons/medical_vitals/CfgWeapons.hpp +++ b/addons/medical_vitals/CfgWeapons.hpp @@ -3,4 +3,8 @@ class CfgWeapons { class H_PilotHelmetFighter_B: H_HelmetB { GVAR(oxygenSupply) = QUOTE(vehicle _this isKindOf 'Plane' || vehicle _this isKindOf 'Helicopter'); }; + class Vest_Camo_Base; + class V_RebreatherB: Vest_Camo_Base { + GVAR(oxygenSupply) = QUOTE(eyePos _this select 2 < 0); // will only work for sea-level water + }; }; diff --git a/addons/medical_vitals/XEH_PREP.hpp b/addons/medical_vitals/XEH_PREP.hpp index bb6fd48b62b..02f1cc5f899 100644 --- a/addons/medical_vitals/XEH_PREP.hpp +++ b/addons/medical_vitals/XEH_PREP.hpp @@ -1,4 +1,5 @@ PREP(handleUnitVitals); +PREP(scanConfig); PREP(updateHeartRate); PREP(updateOxygen); PREP(updatePainSuppress); diff --git a/addons/medical_vitals/XEH_preInit.sqf b/addons/medical_vitals/XEH_preInit.sqf index b47cf6628db..8006c63f76f 100644 --- a/addons/medical_vitals/XEH_preInit.sqf +++ b/addons/medical_vitals/XEH_preInit.sqf @@ -6,4 +6,6 @@ PREP_RECOMPILE_START; #include "XEH_PREP.hpp" PREP_RECOMPILE_END; +GVAR(oxygenSupplyConditionCache) = uiNamespace getVariable QGVAR(oxygenSupplyConditionCache); + ADDON = true; diff --git a/addons/medical_vitals/XEH_preStart.sqf b/addons/medical_vitals/XEH_preStart.sqf index 022888575ed..78dd8ad0e3f 100644 --- a/addons/medical_vitals/XEH_preStart.sqf +++ b/addons/medical_vitals/XEH_preStart.sqf @@ -1,3 +1,9 @@ #include "script_component.hpp" #include "XEH_PREP.hpp" + +GVAR(oxygenSupplyConditionCache) = createHashMap; + +call FUNC(scanConfig); + +GVAR(oxygenSupplyConditionCache) = compileFinal GVAR(oxygenSupplyConditionCache); diff --git a/addons/medical_vitals/functions/fnc_scanConfig.sqf b/addons/medical_vitals/functions/fnc_scanConfig.sqf new file mode 100644 index 00000000000..377b2353152 --- /dev/null +++ b/addons/medical_vitals/functions/fnc_scanConfig.sqf @@ -0,0 +1,23 @@ +#include "..\script_component.hpp" +/* + * Author: LinkIsGrim + * Cache a hashmap of all oxygen-providing items for SpO2 simulation + * + * Arguments: + * None + * + * Return Value: + * None + * + * Public: No +*/ + +private _filter = toString {getText (_x >> QGVAR(oxygenSupply)) != ""}; + +{ + private _cfgRoot = configFile >> _x; + { + private _condition = compile getText (_x >> QGVAR(oxygenSupply)); + GVAR(oxygenSupplyConditionCache) set [configName _x, _condition]; + } forEach (_filter configClasses _cfgRoot); +} forEach ["CfgWeapons", "CfgGoggles"]; diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index da2d579a716..5a403601f89 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -37,23 +37,13 @@ private _po2 = if (missionNamespace getVariable [QEGVAR(weather,enabled), false] private _oxygenSaturation = (IDEAL_PPO2 min _po2) / IDEAL_PPO2; // Check gear for oxygen supply -[goggles _unit, headgear _unit] findIf { - if (_x != "") then { - if (isNil QGVAR(oxygenSupplyConditionCache)) then { - GVAR(oxygenSupplyConditionCache) = createHashmap; - }; - private _condition = GVAR(oxygenSupplyConditionCache) getOrDefaultCall [_x, { - compile getText (configFile >> "CfgWeapons" >> _x >> QGVAR(oxygenSupply)) - }, true]; - if (_condition isNotEqualTo {} && {ACE_player call _condition}) then { - _oxygenSaturation = 1; - _po2 = IDEAL_PPO2; - true - } else { - false - } - } else { - false +[goggles _unit, headgear _unit, vest _unit] findIf { + _x in GVAR(oxygenSupplyConditionCache) && + {ACE_player call (GVAR(oxygenSupplyConditionCache) get _x)} && + { // Will only run this if other conditions are met due to lazy eval + _oxygenSaturation = 1; + _po2 = IDEAL_PPO2; + true } }; From 0ab9abc292abbd3f844f3e133f35f441f78d2a02 Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Thu, 26 Oct 2023 15:07:26 -0400 Subject: [PATCH 12/24] add setting to disable --- addons/medical_vitals/XEH_preInit.sqf | 2 ++ .../medical_vitals/functions/fnc_updateOxygen.sqf | 2 ++ addons/medical_vitals/initSettings.sqf | 8 ++++++++ addons/medical_vitals/stringtable.xml | 15 +++++++++++++++ 4 files changed, 27 insertions(+) create mode 100644 addons/medical_vitals/initSettings.sqf create mode 100644 addons/medical_vitals/stringtable.xml diff --git a/addons/medical_vitals/XEH_preInit.sqf b/addons/medical_vitals/XEH_preInit.sqf index 8006c63f76f..5b6de04384a 100644 --- a/addons/medical_vitals/XEH_preInit.sqf +++ b/addons/medical_vitals/XEH_preInit.sqf @@ -6,6 +6,8 @@ PREP_RECOMPILE_START; #include "XEH_PREP.hpp" PREP_RECOMPILE_END; +#include "initSettings.sqf" + GVAR(oxygenSupplyConditionCache) = uiNamespace getVariable QGVAR(oxygenSupplyConditionCache); ADDON = true; diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index 5a403601f89..a80d362bafb 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -19,6 +19,8 @@ params ["_unit", "_deltaT", "_syncValue"]; +if (!GVAR(simulateSpO2)) exitWith {}; + #define IDEAL_PPO2 0.255 private _current = GET_SPO2(_unit); diff --git a/addons/medical_vitals/initSettings.sqf b/addons/medical_vitals/initSettings.sqf new file mode 100644 index 00000000000..2da3d113341 --- /dev/null +++ b/addons/medical_vitals/initSettings.sqf @@ -0,0 +1,8 @@ +[ + QGVAR(simulateSpO2), + "CHECKBOX", + [LSTRING(simulateSpO2_DisplayName), LSTRING(simulateSpO2_Description)], + [ELSTRING(medical,Category), LSTRING(SubCategory)], + true, + true +] call CBA_fnc_addSetting; diff --git a/addons/medical_vitals/stringtable.xml b/addons/medical_vitals/stringtable.xml new file mode 100644 index 00000000000..f1d7f3fa5bc --- /dev/null +++ b/addons/medical_vitals/stringtable.xml @@ -0,0 +1,15 @@ + + + + + Vitals + Vitais + + + Enable SpO2 Simulation + + + Enables oxygen saturation simulation, providing variable heart rate and oxygen demand based on physical activity and altitude. Required for Airway Management. + + + From f4802ae9d4156b9f897005556552314bcd6f4d30 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Tue, 21 Nov 2023 11:35:22 -0600 Subject: [PATCH 13/24] Update addons/medical_vitals/initSettings.sqf Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com> --- addons/medical_vitals/initSettings.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_vitals/initSettings.sqf b/addons/medical_vitals/initSettings.sqf index 2da3d113341..7d13b3c1246 100644 --- a/addons/medical_vitals/initSettings.sqf +++ b/addons/medical_vitals/initSettings.sqf @@ -4,5 +4,5 @@ [LSTRING(simulateSpO2_DisplayName), LSTRING(simulateSpO2_Description)], [ELSTRING(medical,Category), LSTRING(SubCategory)], true, - true + 1 ] call CBA_fnc_addSetting; From 5fedf375e08053bb97b4b816fd5ea7d8846bae42 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Thu, 28 Dec 2023 15:12:35 -0600 Subject: [PATCH 14/24] Update addons/medical_vitals/functions/fnc_updateOxygen.sqf Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com> --- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index a80d362bafb..2cdea489081 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -19,7 +19,10 @@ params ["_unit", "_deltaT", "_syncValue"]; -if (!GVAR(simulateSpO2)) exitWith {}; +if (!GVAR(simulateSpO2)) exitWith { + _unit setVariable [QGVAR(oxygenDemand), 0]; + _unit setVariable [VAR_SPO2, DEFAULT_SPO2, _syncValue]; +}; #define IDEAL_PPO2 0.255 From 328f8afd4f84e2169996e8679e57276cbb6a8a09 Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Tue, 2 Jan 2024 10:14:03 -0300 Subject: [PATCH 15/24] move default value reset to setting change --- addons/medical_vitals/XEH_preInit.sqf | 2 +- .../medical_vitals/functions/fnc_updateOxygen.sqf | 5 +---- addons/medical_vitals/initSettings.inc.sqf | 15 +++++++++++++++ addons/medical_vitals/initSettings.sqf | 8 -------- 4 files changed, 17 insertions(+), 13 deletions(-) create mode 100644 addons/medical_vitals/initSettings.inc.sqf delete mode 100644 addons/medical_vitals/initSettings.sqf diff --git a/addons/medical_vitals/XEH_preInit.sqf b/addons/medical_vitals/XEH_preInit.sqf index 5b6de04384a..8cc49805e92 100644 --- a/addons/medical_vitals/XEH_preInit.sqf +++ b/addons/medical_vitals/XEH_preInit.sqf @@ -6,7 +6,7 @@ PREP_RECOMPILE_START; #include "XEH_PREP.hpp" PREP_RECOMPILE_END; -#include "initSettings.sqf" +#include "initSettings.inc.sqf" GVAR(oxygenSupplyConditionCache) = uiNamespace getVariable QGVAR(oxygenSupplyConditionCache); diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index 2cdea489081..8e7b9481075 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -19,10 +19,7 @@ params ["_unit", "_deltaT", "_syncValue"]; -if (!GVAR(simulateSpO2)) exitWith { - _unit setVariable [QGVAR(oxygenDemand), 0]; - _unit setVariable [VAR_SPO2, DEFAULT_SPO2, _syncValue]; -}; +if (!GVAR(simulateSpO2)) exitWith {}; // changing back to default is handled in initSettings.inc.sqf #define IDEAL_PPO2 0.255 diff --git a/addons/medical_vitals/initSettings.inc.sqf b/addons/medical_vitals/initSettings.inc.sqf new file mode 100644 index 00000000000..fb317e9b7eb --- /dev/null +++ b/addons/medical_vitals/initSettings.inc.sqf @@ -0,0 +1,15 @@ +[ + QGVAR(simulateSpO2), + "CHECKBOX", + [LSTRING(simulateSpO2_DisplayName), LSTRING(simulateSpO2_Description)], + [ELSTRING(medical,Category), LSTRING(SubCategory)], + true, + 1, + { + if (_this select 1) exitWith {}; // skip if true + { + _x setVariable [QGVAR(oxygenDemand), 0, true]; + _x setVariable [VAR_SPO2, DEFAULT_SPO2, true]; + } forEach (allUnits select {local _x}) + } // reset oxygen demand on setting change +] call CBA_fnc_addSetting; diff --git a/addons/medical_vitals/initSettings.sqf b/addons/medical_vitals/initSettings.sqf deleted file mode 100644 index 7d13b3c1246..00000000000 --- a/addons/medical_vitals/initSettings.sqf +++ /dev/null @@ -1,8 +0,0 @@ -[ - QGVAR(simulateSpO2), - "CHECKBOX", - [LSTRING(simulateSpO2_DisplayName), LSTRING(simulateSpO2_Description)], - [ELSTRING(medical,Category), LSTRING(SubCategory)], - true, - 1 -] call CBA_fnc_addSetting; From 570ac7a6d80c94d85a416fdf676e0bce3652a8f3 Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Tue, 2 Jan 2024 10:35:10 -0300 Subject: [PATCH 16/24] fix setting --- addons/medical_vitals/initSettings.inc.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_vitals/initSettings.inc.sqf b/addons/medical_vitals/initSettings.inc.sqf index fb317e9b7eb..c328b88f5a3 100644 --- a/addons/medical_vitals/initSettings.inc.sqf +++ b/addons/medical_vitals/initSettings.inc.sqf @@ -6,7 +6,7 @@ true, 1, { - if (_this select 1) exitWith {}; // skip if true + if (_this) exitWith {}; // skip if true { _x setVariable [QGVAR(oxygenDemand), 0, true]; _x setVariable [VAR_SPO2, DEFAULT_SPO2, true]; From 22a4c91c55444b45823799c50336b6bddadc9bb9 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Tue, 2 Jan 2024 09:25:57 -0600 Subject: [PATCH 17/24] Update addons/medical_vitals/functions/fnc_updateOxygen.sqf Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com> --- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index 8e7b9481075..0f7b7ed5b2c 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -52,9 +52,11 @@ private _oxygenSaturation = (IDEAL_PPO2 min _po2) / IDEAL_PPO2; // Base oxygen consumption rate private _negativeChange = BASE_OXYGEN_USE; -// Fatigue will demand more oxygen +// Fatigue & exercise will demand more oxygen +// Assuming a trained male in midst of peak exercise will have a peak heart rate of ~180 BPM +// Ref: https://academic.oup.com/bjaed/article-pdf/4/6/185/894114/mkh050.pdf table 2, though we don't take stroke volume change into account if (_unit == ACE_player && {missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]}) then { - _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.5); + _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.5) - ((1 - EGVAR(advanced_fatigue,anReservePercentage)) * 0.15); }; // Effectiveness of capturing oxygen From ff6f63c3f7ff5bd6abf3dcbd92ccab0b47bd282f Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Mon, 15 Jan 2024 22:21:16 -0300 Subject: [PATCH 18/24] fix respawn, full heal --- addons/medical_engine/script_macros_medical.hpp | 1 + addons/medical_status/functions/fnc_initUnit.sqf | 4 +++- addons/medical_treatment/functions/fnc_fullHealLocal.sqf | 2 ++ addons/medical_vitals/functions/fnc_updateHeartRate.sqf | 2 +- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 2 +- addons/medical_vitals/initSettings.inc.sqf | 2 +- 6 files changed, 9 insertions(+), 4 deletions(-) diff --git a/addons/medical_engine/script_macros_medical.hpp b/addons/medical_engine/script_macros_medical.hpp index c145f2ac3fa..e6a57c9419d 100644 --- a/addons/medical_engine/script_macros_medical.hpp +++ b/addons/medical_engine/script_macros_medical.hpp @@ -155,6 +155,7 @@ #define VAR_CRDC_ARRST QEGVAR(medical,inCardiacArrest) #define VAR_HEART_RATE QEGVAR(medical,heartRate) #define VAR_SPO2 QEGVAR(medical,spo2) +#define VAR_OXYGENDEMAND QEGVAR(medical,oxygenDemand) #define VAR_PAIN QEGVAR(medical,pain) #define VAR_PAIN_SUPP QEGVAR(medical,painSuppress) #define VAR_PERIPH_RES QEGVAR(medical,peripheralResistance) diff --git a/addons/medical_status/functions/fnc_initUnit.sqf b/addons/medical_status/functions/fnc_initUnit.sqf index 786f2be9500..b93b3e56832 100644 --- a/addons/medical_status/functions/fnc_initUnit.sqf +++ b/addons/medical_status/functions/fnc_initUnit.sqf @@ -32,13 +32,15 @@ if (damage _unit > 0) then { if (_isRespawn) then { TRACE_1("reseting all vars on respawn",_isRespawn); // note: state is handled by ace_medical_statemachine_fnc_resetStateDefault - // - Blood and heart ---------------------------------------------------------- + // - Vitals ------------------------------------------------------------------ _unit setVariable [VAR_BLOOD_VOL, DEFAULT_BLOOD_VOLUME, true]; _unit setVariable [VAR_HEART_RATE, DEFAULT_HEART_RATE, true]; _unit setVariable [VAR_BLOOD_PRESS, [80, 120], true]; _unit setVariable [VAR_PERIPH_RES, DEFAULT_PERIPH_RES, true]; _unit setVariable [VAR_CRDC_ARRST, false, true]; _unit setVariable [VAR_HEMORRHAGE, 0, true]; + _unit setVariable [VAR_SPO2, DEFAULT_SPO2, true]; + _unit setVariable [VAR_OXYGENDEMAND, 0, true]; // - Pain --------------------------------------------------------------------- _unit setVariable [VAR_PAIN, 0, true]; diff --git a/addons/medical_treatment/functions/fnc_fullHealLocal.sqf b/addons/medical_treatment/functions/fnc_fullHealLocal.sqf index e845e043042..76d22b77d6d 100644 --- a/addons/medical_treatment/functions/fnc_fullHealLocal.sqf +++ b/addons/medical_treatment/functions/fnc_fullHealLocal.sqf @@ -63,6 +63,8 @@ _patient setVariable [VAR_FRACTURES, DEFAULT_FRACTURE_VALUES, true]; _patient setVariable [VAR_HEART_RATE, DEFAULT_HEART_RATE, true]; _patient setVariable [VAR_BLOOD_PRESS, [80, 120], true]; _patient setVariable [VAR_PERIPH_RES, DEFAULT_PERIPH_RES, true]; +_patient setVariable [VAR_SPO2, DEFAULT_SPO2, true]; +_patient setVariable [VAR_OXYGENDEMAND, 0, true]; // IVs _patient setVariable [QEGVAR(medical,ivBags), nil, true]; diff --git a/addons/medical_vitals/functions/fnc_updateHeartRate.sqf b/addons/medical_vitals/functions/fnc_updateHeartRate.sqf index 2d73a5a810a..7383d897195 100644 --- a/addons/medical_vitals/functions/fnc_updateHeartRate.sqf +++ b/addons/medical_vitals/functions/fnc_updateHeartRate.sqf @@ -54,7 +54,7 @@ if IN_CRDC_ARRST(_unit) then { }; // Increase HR to compensate for low blood oxygen // Increase HR to compensate for higher oxygen demand (e.g. running, recovering from sprint) - private _oxygenDemand = _unit getVariable [QGVAR(oxygenDemand), 0]; + private _oxygenDemand = _unit getVariable [VAR_OXYGENDEMAND, 0]; _targetHR = _targetHR + ((97 - _spo2) * 2) + (_oxygenDemand * -1000); _targetHR = (_targetHR + _hrTargetAdjustment) max 0; _hrChange = round(_targetHR - _heartRate) / 2; diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index 0f7b7ed5b2c..a0a2d24c139 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -71,5 +71,5 @@ private _rateOfChange = _negativeChange + (_positiveChange * _breathingEffective private _spo2 = (_current + (_rateOfChange * _deltaT)) max 0 min 100; -_unit setVariable [QGVAR(oxygenDemand), _negativeChange - BASE_OXYGEN_USE]; +_unit setVariable [VAR_OXYGEN_DEMAND, _negativeChange - BASE_OXYGEN_USE]; _unit setVariable [VAR_SPO2, _spo2, _syncValue]; diff --git a/addons/medical_vitals/initSettings.inc.sqf b/addons/medical_vitals/initSettings.inc.sqf index c328b88f5a3..6ee0138b2d8 100644 --- a/addons/medical_vitals/initSettings.inc.sqf +++ b/addons/medical_vitals/initSettings.inc.sqf @@ -8,7 +8,7 @@ { if (_this) exitWith {}; // skip if true { - _x setVariable [QGVAR(oxygenDemand), 0, true]; + _x setVariable [VAR_OXYGENDEMAND, 0, true]; _x setVariable [VAR_SPO2, DEFAULT_SPO2, true]; } forEach (allUnits select {local _x}) } // reset oxygen demand on setting change From 80da6f6c70849837e5cc6fd6b627af00cf451ed6 Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Mon, 15 Jan 2024 22:22:19 -0300 Subject: [PATCH 19/24] edit macro name --- addons/medical_engine/script_macros_medical.hpp | 2 +- addons/medical_status/functions/fnc_initUnit.sqf | 2 +- addons/medical_treatment/functions/fnc_fullHealLocal.sqf | 2 +- addons/medical_vitals/functions/fnc_updateHeartRate.sqf | 2 +- addons/medical_vitals/initSettings.inc.sqf | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/medical_engine/script_macros_medical.hpp b/addons/medical_engine/script_macros_medical.hpp index e6a57c9419d..2b2f5504542 100644 --- a/addons/medical_engine/script_macros_medical.hpp +++ b/addons/medical_engine/script_macros_medical.hpp @@ -155,7 +155,7 @@ #define VAR_CRDC_ARRST QEGVAR(medical,inCardiacArrest) #define VAR_HEART_RATE QEGVAR(medical,heartRate) #define VAR_SPO2 QEGVAR(medical,spo2) -#define VAR_OXYGENDEMAND QEGVAR(medical,oxygenDemand) +#define VAR_OXYGEN_DEMAND QEGVAR(medical,oxygenDemand) #define VAR_PAIN QEGVAR(medical,pain) #define VAR_PAIN_SUPP QEGVAR(medical,painSuppress) #define VAR_PERIPH_RES QEGVAR(medical,peripheralResistance) diff --git a/addons/medical_status/functions/fnc_initUnit.sqf b/addons/medical_status/functions/fnc_initUnit.sqf index b93b3e56832..278163d90b9 100644 --- a/addons/medical_status/functions/fnc_initUnit.sqf +++ b/addons/medical_status/functions/fnc_initUnit.sqf @@ -40,7 +40,7 @@ if (_isRespawn) then { _unit setVariable [VAR_CRDC_ARRST, false, true]; _unit setVariable [VAR_HEMORRHAGE, 0, true]; _unit setVariable [VAR_SPO2, DEFAULT_SPO2, true]; - _unit setVariable [VAR_OXYGENDEMAND, 0, true]; + _unit setVariable [VAR_OXYGEN_DEMAND, 0, true]; // - Pain --------------------------------------------------------------------- _unit setVariable [VAR_PAIN, 0, true]; diff --git a/addons/medical_treatment/functions/fnc_fullHealLocal.sqf b/addons/medical_treatment/functions/fnc_fullHealLocal.sqf index 76d22b77d6d..7772db0a6ba 100644 --- a/addons/medical_treatment/functions/fnc_fullHealLocal.sqf +++ b/addons/medical_treatment/functions/fnc_fullHealLocal.sqf @@ -64,7 +64,7 @@ _patient setVariable [VAR_HEART_RATE, DEFAULT_HEART_RATE, true]; _patient setVariable [VAR_BLOOD_PRESS, [80, 120], true]; _patient setVariable [VAR_PERIPH_RES, DEFAULT_PERIPH_RES, true]; _patient setVariable [VAR_SPO2, DEFAULT_SPO2, true]; -_patient setVariable [VAR_OXYGENDEMAND, 0, true]; +_patient setVariable [VAR_OXYGEN_DEMAND, 0, true]; // IVs _patient setVariable [QEGVAR(medical,ivBags), nil, true]; diff --git a/addons/medical_vitals/functions/fnc_updateHeartRate.sqf b/addons/medical_vitals/functions/fnc_updateHeartRate.sqf index 7383d897195..187a8ffe58e 100644 --- a/addons/medical_vitals/functions/fnc_updateHeartRate.sqf +++ b/addons/medical_vitals/functions/fnc_updateHeartRate.sqf @@ -54,7 +54,7 @@ if IN_CRDC_ARRST(_unit) then { }; // Increase HR to compensate for low blood oxygen // Increase HR to compensate for higher oxygen demand (e.g. running, recovering from sprint) - private _oxygenDemand = _unit getVariable [VAR_OXYGENDEMAND, 0]; + private _oxygenDemand = _unit getVariable [VAR_OXYGEN_DEMAND, 0]; _targetHR = _targetHR + ((97 - _spo2) * 2) + (_oxygenDemand * -1000); _targetHR = (_targetHR + _hrTargetAdjustment) max 0; _hrChange = round(_targetHR - _heartRate) / 2; diff --git a/addons/medical_vitals/initSettings.inc.sqf b/addons/medical_vitals/initSettings.inc.sqf index 6ee0138b2d8..db762d2c522 100644 --- a/addons/medical_vitals/initSettings.inc.sqf +++ b/addons/medical_vitals/initSettings.inc.sqf @@ -8,7 +8,7 @@ { if (_this) exitWith {}; // skip if true { - _x setVariable [VAR_OXYGENDEMAND, 0, true]; + _x setVariable [VAR_OXYGEN_DEMAND, 0, true]; _x setVariable [VAR_SPO2, DEFAULT_SPO2, true]; } forEach (allUnits select {local _x}) } // reset oxygen demand on setting change From f0d8fc4f4cd0aba12c04ce1d4a35df0a35ca3f9b Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Mon, 15 Jan 2024 22:24:54 -0300 Subject: [PATCH 20/24] OCD extra whitespace --- addons/medical_engine/script_macros_medical.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_engine/script_macros_medical.hpp b/addons/medical_engine/script_macros_medical.hpp index 2b2f5504542..5fecd36413a 100644 --- a/addons/medical_engine/script_macros_medical.hpp +++ b/addons/medical_engine/script_macros_medical.hpp @@ -155,7 +155,7 @@ #define VAR_CRDC_ARRST QEGVAR(medical,inCardiacArrest) #define VAR_HEART_RATE QEGVAR(medical,heartRate) #define VAR_SPO2 QEGVAR(medical,spo2) -#define VAR_OXYGEN_DEMAND QEGVAR(medical,oxygenDemand) +#define VAR_OXYGEN_DEMAND QEGVAR(medical,oxygenDemand) #define VAR_PAIN QEGVAR(medical,pain) #define VAR_PAIN_SUPP QEGVAR(medical,painSuppress) #define VAR_PERIPH_RES QEGVAR(medical,peripheralResistance) From c76e2b490d7d47d219d14dbc333f4f26ce746feb Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Mon, 15 Jan 2024 23:02:47 -0300 Subject: [PATCH 21/24] reduce aerobic fatigue effect (max oxygen demand from fatigue is now 2x baseline) --- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index a0a2d24c139..0c9d0686aaf 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -56,7 +56,7 @@ private _negativeChange = BASE_OXYGEN_USE; // Assuming a trained male in midst of peak exercise will have a peak heart rate of ~180 BPM // Ref: https://academic.oup.com/bjaed/article-pdf/4/6/185/894114/mkh050.pdf table 2, though we don't take stroke volume change into account if (_unit == ACE_player && {missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]}) then { - _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.5) - ((1 - EGVAR(advanced_fatigue,anReservePercentage)) * 0.15); + _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.1) - ((1 - EGVAR(advanced_fatigue,anReservePercentage)) * 0.15); }; // Effectiveness of capturing oxygen From 75a6edfc5649612f84593b36c09a4fc23c8ba882 Mon Sep 17 00:00:00 2001 From: BrettMayson Date: Thu, 25 Jan 2024 19:27:57 -0600 Subject: [PATCH 22/24] Update addons/medical_vitals/functions/fnc_updateOxygen.sqf Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com> --- addons/medical_vitals/functions/fnc_updateOxygen.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_vitals/functions/fnc_updateOxygen.sqf b/addons/medical_vitals/functions/fnc_updateOxygen.sqf index 0c9d0686aaf..f2c0f68f715 100644 --- a/addons/medical_vitals/functions/fnc_updateOxygen.sqf +++ b/addons/medical_vitals/functions/fnc_updateOxygen.sqf @@ -56,7 +56,7 @@ private _negativeChange = BASE_OXYGEN_USE; // Assuming a trained male in midst of peak exercise will have a peak heart rate of ~180 BPM // Ref: https://academic.oup.com/bjaed/article-pdf/4/6/185/894114/mkh050.pdf table 2, though we don't take stroke volume change into account if (_unit == ACE_player && {missionNamespace getVariable [QEGVAR(advanced_fatigue,enabled), false]}) then { - _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.1) - ((1 - EGVAR(advanced_fatigue,anReservePercentage)) * 0.15); + _negativeChange = _negativeChange - ((1 - EGVAR(advanced_fatigue,aeReservePercentage)) * 0.1) - ((1 - EGVAR(advanced_fatigue,anReservePercentage)) * 0.05); }; // Effectiveness of capturing oxygen From f6a0baa7af170574b04c417a7e095411531af49a Mon Sep 17 00:00:00 2001 From: LinkIsGrim Date: Mon, 5 Feb 2024 19:24:04 -0300 Subject: [PATCH 23/24] use AF's o2sat value if SPO2 simulation is disabled --- addons/advanced_fatigue/XEH_postInit.sqf | 2 +- addons/advanced_fatigue/XEH_preInit.sqf | 1 + addons/advanced_fatigue/functions/fnc_mainLoop.sqf | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/advanced_fatigue/XEH_postInit.sqf b/addons/advanced_fatigue/XEH_postInit.sqf index 57b57dcf22d..db4a9d9c5e1 100644 --- a/addons/advanced_fatigue/XEH_postInit.sqf +++ b/addons/advanced_fatigue/XEH_postInit.sqf @@ -60,7 +60,7 @@ if (!hasInterface) exitWith {}; }, true] call CBA_fnc_addPlayerEventHandler; // - Duty factors ------------------------------------------------------------- - if (["ace_medical"] call EFUNC(common,isModLoaded)) then { + if (GVAR(medicalLoaded)) then { [QEGVAR(medical,pain), { // 0->1.0, 0.5->1.05, 1->1.1 linearConversion [0, 1, (_this getVariable [QEGVAR(medical,pain), 0]), 1, 1.1, true]; }] call FUNC(addDutyFactor); diff --git a/addons/advanced_fatigue/XEH_preInit.sqf b/addons/advanced_fatigue/XEH_preInit.sqf index 643b7b0be00..9f58e44fdf2 100644 --- a/addons/advanced_fatigue/XEH_preInit.sqf +++ b/addons/advanced_fatigue/XEH_preInit.sqf @@ -13,5 +13,6 @@ GVAR(dutyList) = createHashMap; GVAR(setAnimExclusions) = []; GVAR(inertia) = 0; GVAR(inertiaCache) = createHashMap; +GVAR(medicalLoaded) = ["ace_medical"] call EFUNC(common,isModLoaded); ADDON = true; diff --git a/addons/advanced_fatigue/functions/fnc_mainLoop.sqf b/addons/advanced_fatigue/functions/fnc_mainLoop.sqf index 075b4bde83a..da469b6d218 100644 --- a/addons/advanced_fatigue/functions/fnc_mainLoop.sqf +++ b/addons/advanced_fatigue/functions/fnc_mainLoop.sqf @@ -23,7 +23,11 @@ if (!alive ACE_player) exitWith { _staminaBarContainer ctrlCommit 1; }; -private _oxygen = (ACE_player getVariable [QEGVAR(medical,spo2), 90]) / 100; + +private _oxygen = 0.9; // Default AF oxygen saturation +if (GVAR(medicalLoaded) && {EGVAR(medical_vitals,simulateSpo2)}) then { + _oxygen = (ACE_player getVariable [QEGVAR(medical,spo2), 97]) / 100; +}; private _currentWork = REE; private _currentSpeed = (vectorMagnitude (velocity ACE_player)) min 6; From 4bdc4103a4bad8884ac43a31b758d16e1da2b0fa Mon Sep 17 00:00:00 2001 From: Grim <69561145+LinkIsGrim@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:39:17 -0300 Subject: [PATCH 24/24] Update addons/weather/functions/fnc_calculateOxygenDensity.sqf Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com> --- addons/weather/functions/fnc_calculateOxygenDensity.sqf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/weather/functions/fnc_calculateOxygenDensity.sqf b/addons/weather/functions/fnc_calculateOxygenDensity.sqf index 70d92db61c2..542b4b2f108 100644 --- a/addons/weather/functions/fnc_calculateOxygenDensity.sqf +++ b/addons/weather/functions/fnc_calculateOxygenDensity.sqf @@ -4,12 +4,12 @@ * Calculates the oxygen density * * Arguments: - * 0: temperature - degrees celsius - * 1: pressure - hPa - * 2: relativeHumidity - value between 0.0 and 1.0 + * 0: Temperature - °C + * 1: Pressure - hPa + * 2: Relative humidity - value between 0.0 and 1.0 * * Return Value: - * density of oxygen - kg * m^(-3) + * Density of oxygen - kg * m^(-3) * * Example: * [0, 1020] call ace_weather_fnc_calculateOxygenDensity