ACE3/addons/medical_vitals/functions/fnc_updateOxygen.sqf
BrettMayson 1649422cbd
Medical Vitals - Add SPO2 (#9360)
Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com>
Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
Co-authored-by: LinkIsGrim <salluci.lovi@gmail.com>
2024-02-07 17:50:18 -03:00

76 lines
2.7 KiB
Plaintext

#include "..\script_component.hpp"
/*
* Author: Brett Mayson
* Update the oxygen levels
*
* Arguments:
* 0: The Unit <OBJECT>
* 1: Time since last update <NUMBER>
* 2: Sync value? <BOOL>
*
* ReturnValue:
* Current SPO2 <NUMBER>
*
* Example:
* [player, 1, false] call ace_medical_vitals_fnc_updateOxygen
*
* Public: No
*/
params ["_unit", "_deltaT", "_syncValue"];
if (!GVAR(simulateSpO2)) exitWith {}; // changing back to default is handled in initSettings.inc.sqf
#define IDEAL_PPO2 0.255
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 [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)
} else {
// Rough approximation of the partial pressure of oxygen in the air
0.25725 * (_altitude / 1000 + 1)
};
private _oxygenSaturation = (IDEAL_PPO2 min _po2) / IDEAL_PPO2;
// Check gear for oxygen supply
[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
}
};
// Base oxygen consumption rate
private _negativeChange = BASE_OXYGEN_USE;
// 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.1) - ((1 - EGVAR(advanced_fatigue,anReservePercentage)) * 0.05);
};
// 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 * 3));
private _positiveChange = _heartRate * 0.00368 * _oxygenSaturation * _capture;
private _breathingEffectiveness = 1;
private _rateOfChange = _negativeChange + (_positiveChange * _breathingEffectiveness);
private _spo2 = (_current + (_rateOfChange * _deltaT)) max 0 min 100;
_unit setVariable [VAR_OXYGEN_DEMAND, _negativeChange - BASE_OXYGEN_USE];
_unit setVariable [VAR_SPO2, _spo2, _syncValue];