Skip to content

Commit

Permalink
Airway/Breathing/Vitals - Adds Oxygen Mask for High Altitude Operatio…
Browse files Browse the repository at this point in the history
…ns (#646)

**When merged this pull request will:**
- Adds O2 masks to support high altitude operations
- Adds helicopter/plane O2 support for pilots and crew

### IMPORTANT

- [Development Guidelines](https://ace3.acemod.org/wiki/development/)
are read, understood and applied.
- Title of this PR uses our standard template `Component -
Add|Fix|Improve|Change|Make|Remove {changes}`.

---------

Co-authored-by: MiszczuZPolski <[email protected]>
  • Loading branch information
mazinskihenry and MiszczuZPolski authored Dec 3, 2024
1 parent c2bf560 commit dd2b1f5
Show file tree
Hide file tree
Showing 20 changed files with 434 additions and 7 deletions.
6 changes: 3 additions & 3 deletions addons/airway/ACE_Medical_Treatment_Actions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ACE_Medical_Treatment_Actions {
medicRequired = QGVAR(medLvl_Larynxtubus);
treatmentTime = QGVAR(Larynxtubus_time);
items[] = {"kat_larynx"};
condition = QUOTE(!([_patient] call ACEFUNC(common,isAwake)) && (missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]) && !(_patient getVariable [ARR_2(QQGVAR(airway_item),'')] == 'Larynxtubus') && !(_patient getVariable [ARR_2(QQGVAR(airway_item),'')] == 'Guedeltubus'));
condition = QUOTE(!([_patient] call ACEFUNC(common,isAwake)) && (missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]) && !(_patient getVariable [ARR_2(QQGVAR(airway_item),'')] == 'Larynxtubus') && !(_patient getVariable [ARR_2(QQGVAR(airway_item),'')] == 'Guedeltubus') && !([_patient] call FUNC(checkMask)));
callbackSuccess = QUOTE([ARR_3(_medic,_patient,(_patient getVariable [ARR_2(QQGVAR(occluded),false)]))] call FUNC(handleRecoveryPosition); [ARR_6(_medic,_patient,_bodyPart,_className,objNull,_usedItem)] call FUNC(treatmentAdvanced_airway););
callbackFailure = "";
callbackProgress = "";
Expand Down Expand Up @@ -57,7 +57,7 @@ class ACE_Medical_Treatment_Actions {
displayName = CSTRING(AccuvacTreatment_displayName);
treatmentTime = QGVAR(Accuvac_time);
items[] = {"kat_accuvac"};
condition = QUOTE(!([_patient] call ACEFUNC(common,isAwake)) && (missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]) && !(_patient getVariable [ARR_2(QQGVAR(recovery),false)]) && !(_patient getVariable [ARR_2(QQGVAR(airway_item),'')] == 'Larynxtubus'));
condition = QUOTE(!([_patient] call ACEFUNC(common,isAwake)) && (missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]) && !(_patient getVariable [ARR_2(QQGVAR(recovery),false)]) && !(_patient getVariable [ARR_2(QQGVAR(airway_item),'')] == 'Larynxtubus') && !([_patient] call FUNC(checkMask)));
icon = QPATHTOF(ui\accuvac.paa);
consumeItem = 0;
medicRequired = QGVAR(medLvl_Accuvac);
Expand Down Expand Up @@ -140,7 +140,7 @@ class ACE_Medical_Treatment_Actions {
allowedSelections[] = {"Head"};
allowSelfTreatment = 0;
callbackSuccess = QFUNC(checkAirway);
condition = QUOTE(!([_patient] call ACEFUNC(common,isAwake)) && (missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]));
condition = QUOTE(!([_patient] call ACEFUNC(common,isAwake)) && (missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]) && !([_patient] call FUNC(checkMask)));
animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback";
animationPatientUnconsciousExcludeOn[] = {"ainjppnemstpsnonwrfldnon", "kat_recoveryposition"};
};
Expand Down
1 change: 1 addition & 0 deletions addons/airway/XEH_PREP.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
PREP(checkAirway);
PREP(checkRecovery);
PREP(checkMask);
PREP(fullHealLocal);
PREP(gui_updateBodyImage);
PREP(gui_updateInjuryListGeneral);
Expand Down
24 changes: 24 additions & 0 deletions addons/airway/functions/fnc_checkMask.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "..\script_component.hpp"
/*
* Author: Mazinski
* Checks if patient has mask on
*
* Arguments:
* 0: Unit <OBJECT>
*
* Return Value:
* None
*
* Example:
* [player] call kat_airway_fnc_checkMask;
*
* Public: No
*/

params ["_patient"];

if ((goggles _patient in (missionNamespace getVariable [QEGVAR(chemical,availGasmaskList), []])) || (goggles _patient in (missionNamespace getVariable [QEGVAR(breathing,availOxyMaskList), []]))) exitWith {
true
};

false
11 changes: 10 additions & 1 deletion addons/breathing/ACE_Medical_Treatment_Actions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ class ACE_Medical_Treatment_Actions {
medicRequired = QGVAR(medLvl_NasalCannula);
treatmentTime = QGVAR(NasalCannula_time);
items[] = {"kat_nasal"};
condition = QUOTE((missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]) && !((_patient getVariable [ARR_2(QQGVAR(etco2Monitor),[])] findIf {_x == 'NasalCannula'}) > -1));
condition = QUOTE((missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]) && !((_patient getVariable [ARR_2(QQGVAR(etco2Monitor),[])] findIf {_x == 'NasalCannula'}) > -1) && !([_patient] call EFUNC(airway,checkMask)));
callbackSuccess = QFUNC(treatmentAdvanced_nasalCannula);
callbackFailure = "";
callbackProgress = "";
Expand All @@ -305,4 +305,13 @@ class ACE_Medical_Treatment_Actions {
condition = QUOTE((missionNamespace getVariable [ARR_2(QQGVAR(enable),true)]) && ((_patient getVariable [ARR_2(QQGVAR(etco2Monitor),[])] findIf {_x == 'NasalCannula'}) > -1));
callbackSuccess = QFUNC(treatmentAdvanced_removeNasalCannula);
};
class RemoveOxyMask : NasalCannula {
displayName = CSTRING(Remove_OxyMask);
displayNameProgress = ECSTRING(airway,action_removing);
medicRequired = 0;
treatmentTime = 5;
items[] = {};
condition = QUOTE(_patient call EFUNC(airway,checkMask));
callbackSuccess = QFUNC(removeOxygenMask);
};
};
18 changes: 18 additions & 0 deletions addons/breathing/CfgMagazines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,22 @@ class CfgMagazines {
ACE_isMedicalItem = 1;
ACE_asItem = 1;
};
class kat_personal_oxygen: CA_Magazine {
scope = 2;
scopeCurator = 2;
scopeArsenal = 2;
author = "Mazinski";
displayName = CSTRING(PersonalOxygen_Display);
descriptionShort = CSTRING(PersonalOxygen_Desc_Short);
picture = QPATHTOF(ui\oxygenTank.paa);

ammo = "";
count = 60;
initSpeed = 0;
tracersEvery = 0;
lastRoundsTracer = 0;
mass = 3;
ACE_isMedicalItem = 1;
ACE_asItem = 1;
};
};
45 changes: 45 additions & 0 deletions addons/breathing/CfgVehicles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,24 @@ class CfgVehicles {
condition = QUOTE((GVAR(locationProvideOxygen) in [ARR_2(2,3)]) && 'kat_oxygenTank_300_Empty' in (items _player) && _player call ACEFUNC(medical_treatment,isInMedicalFacility));
statement = QUOTE([ARR_3(_player,'kat_oxygenTank_300',GVAR(PortableOxygenTank_RefillTime)*2)] call FUNC(refillOxygenTank));
};
class Attach_PersonalOxygen {
displayName = CSTRING(AttachPersonalOxygenTank);
condition = QUOTE(([ARR_2(_player,'kat_personal_oxygen')] call ACEFUNC(common,hasMagazine)) && (_player call EFUNC(airway,checkMask)));
statement = QUOTE(_player call FUNC(attachPersonalOxygen));
showDisabled = 0;
exceptions[] = {"isNotSwimming", "isNotOnLadder"};
icon = QPATHTOF(ui\oxygenTank_ui.paa);
};
class Detach_PersonalOxygen: Attach_PersonalOxygen {
displayName = CSTRING(RemovePersonalOxygenTank);
condition = QUOTE(_player getVariable [ARR_2(QQGVAR(oxygenMaskActive),false)]);
statement = QUOTE(_player call FUNC(detachPersonalOxygen));
};
class Check_PersonalOxygen: Attach_PersonalOxygen {
displayName = CSTRING(CheckPersonalOxygenTank);
condition = QUOTE(_player getVariable [ARR_2(QQGVAR(oxygenMaskActive),false)]);
statement = QUOTE(_player call FUNC(checkPersonalOxygen));
};
};
};
};
Expand All @@ -152,4 +170,31 @@ class CfgVehicles {
};
};
};

class Air;
class Helicopter: Air {
class ACE_SelfActions {
class KAT_AttachOxygenVehicle {
displayName = CSTRING(AttachOxygenVehicle);
condition = QUOTE((_player call FUNC(checkAircraftOxygen)) && (_player call EFUNC(airway,checkMask)));
statement = QUOTE(_player call FUNC(attachVehicleOxygen));
insertChildren = "";
exceptions[] = {};
icon = QACEPATHTOF(medical_gui,ui\cross.paa);
};
};
};

class Plane: Air {
class ACE_SelfActions {
class KAT_AttachOxygenVehicle {
displayName = CSTRING(AttachOxygenVehicle);
condition = QUOTE((_player call FUNC(checkAircraftOxygen)) && (_player call EFUNC(airway,checkMask)));
statement = QUOTE(_player call FUNC(attachVehicleOxygen));
insertChildren = "";
exceptions[] = {};
icon = QACEPATHTOF(medical_gui,ui\cross.paa);
};
};
};
};
10 changes: 8 additions & 2 deletions addons/breathing/XEH_PREP.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
PREP(attachPersonalOxygen);
PREP(attachVehicleOxygen);
PREP(canUseBVM);
PREP(checkAircraftOxygen);
PREP(checkBreathing);
PREP(checkPersonalOxygen);
PREP(checkPulseOximeter);
PREP(detachPersonalOxygen);
PREP(fullHealLocal);
PREP(gui_updateBodyImage);
PREP(gui_updateInjuryListPart);
Expand All @@ -16,6 +21,7 @@ PREP(init);
PREP(inspectChest);
PREP(listenLungs);
PREP(refillOxygenTank);
PREP(removeOxygenMask);
PREP(treatmentAdvanced_chestSeal);
PREP(treatmentAdvanced_chestSealLocal);
PREP(treatmentAdvanced_hemopneumothorax);
Expand All @@ -24,9 +30,9 @@ PREP(treatmentAdvanced_nasalCannula);
PREP(treatmentAdvanced_nasalCannulaLocal);
PREP(treatmentAdvanced_pulseoximeter);
PREP(treatmentAdvanced_pulseoximeterLocal);
PREP(treatmentAdvanced_removePulseoximeter);
PREP(treatmentAdvanced_removeNasalCannula);
PREP(treatmentAdvanced_removeNasalCannulaLocal);
PREP(treatmentAdvanced_removePulseoximeter);
PREP(treatmentAdvanced_tensionpneumothorax);
PREP(treatmentAdvanced_tensionpneumothoraxLocal);
PREP(useBVM);
PREP(useBVM);
4 changes: 4 additions & 0 deletions addons/breathing/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@
[QACEGVAR(medical_gui,updateBodyImage), LINKFUNC(gui_updateBodyImage)] call CBA_fnc_addEventHandler;
[QACEGVAR(medical_treatment,fullHealLocalMod), LINKFUNC(fullHealLocal)] call CBA_fnc_addEventHandler;
[QACEGVAR(medical,woundReceived),LINKFUNC(handlePulmoHit)] call CBA_fnc_addEventHandler;

private _items = missionNamespace getVariable [QGVAR(availOxyMask), "'G_AirPurifyingRespirator_01_F'"];
private _array = [_items, "CfgGlasses"] call FUNC(getList);
missionNamespace setVariable [QGVAR(availOxyMaskList), _array, true];
15 changes: 15 additions & 0 deletions addons/breathing/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ PREP_RECOMPILE_END;
true
] call CBA_Settings_fnc_init;

//Adds available oxygen masks
[
QGVAR(availOxyMask),
"EDITBOX",
[LLSTRING(SETTING_AVAIL_OXYMASK), LLSTRING(SETTING_AVAIL_OXYMASK_DISC)],
[CBA_SETTINGS_CAT, ELSTRING(GUI,SubCategory_Basic)],
"'G_AirPurifyingRespirator_01_F'",
1,
{
private _array = [_this, "CfgGlasses"] call FUNC(getList);
missionNamespace setVariable [QGVAR(availOxyMaskList), _array, true];
},
true
] call CBA_Settings_fnc_init;

//Enable Check Breathing medical action
[
QGVAR(enableCheckBreathing),
Expand Down
84 changes: 84 additions & 0 deletions addons/breathing/functions/fnc_attachPersonalOxygen.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "..\script_component.hpp"
/*
* Author: Mazinski
* Attaches personal oxygen tank to player
* Main function
*
* Arguments:
* 0: Patient <OBJECT>
*
* Return Value:
* None
*
* Example:
* [player] call kat_breathing_fnc_attachPersonalOxygen;
*
* Public: No
*/

params ["_patient"];

if ((_patient getVariable [QGVAR(oxygenMaskActive), false])) exitWith {
[LSTRING(PersonalOxygen_Affirm), 1.5, _patient] call ACEFUNC(common,displayTextStructured);
};

_patient setVariable [QGVAR(oxygenMaskActive), true, true];

private _availableTanks = (magazinesAmmo [_patient, false]) select {(_x select 0) isEqualTo "kat_personal_oxygen"};
private _largestTank = 0;

{
if (_x select 1 > ((_availableTanks select _largestTank) select 1)) then {
_largestTank = _y;
};
} forEach _availableTanks;

private _largestTankValue = (_availableTanks select _largestTank) select 1;

_availableTanks deleteAt _largestTank;
_patient removeMagazines "kat_personal_oxygen";

{ _patient addMagazine _x; } forEach _availableTanks;

_patient setVariable [QGVAR(oxygenMaskStatus), [(_largestTankValue + 1), 1], true];

[{
_this params ["_args", "_pfhID"];
_args params ["_patient"];

if !((_patient call EFUNC(airway,checkMask))) exitWith {
_patient call FUNC(detachPersonalOxygen);
_pfhID call CBA_fnc_removePerFrameHandler;
};

}, 5, [
_patient
]] call CBA_fnc_addPerFrameHandler;

[{
_this params ["_args", "_pfhID"];
_args params ["_patient"];

if !(alive _patient) exitWith {
_pfhID call CBA_fnc_removePerFrameHandler;
};

if !(_patient setVariable [QGVAR(oxygenMaskActive), true]) exitWith {
_pfhID call CBA_fnc_removePerFrameHandler;
};

private _maskStatus = _patient getVariable [QGVAR(oxygenMaskStatus), [0,0]];

if ((_maskStatus select 0) == 0) exitWith {
[LLSTRING(PersonalOxygen_Empty), 1.5, _patient] call ACEFUNC(common,displayTextStructured);
_pfhID call CBA_fnc_removePerFrameHandler;
};

if ((_maskStatus select 1) == 0) exitWith {
_pfhID call CBA_fnc_removePerFrameHandler;
};

_patient setVariable [QGVAR(oxygenMaskStatus), [((_maskStatus select 0) - 1), _pfhID]];
}, 60, [
_patient
]] call CBA_fnc_addPerFrameHandler;
47 changes: 47 additions & 0 deletions addons/breathing/functions/fnc_attachVehicleOxygen.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "..\script_component.hpp"
/*
* Author: Mazinski
* Attaches vehicle oxygen to player
* Main function
*
* Arguments:
* 0: Patient <OBJECT>
*
* Return Value:
* None
*
* Example:
* [player] call kat_breathing_fnc_attachVehicleOxygen;
*
* Public: No
*/

params ["_patient"];

if (_patient getVariable [QGVAR(oxygenMaskActive), false]) exitWith {
[LSTRING(PersonalOxygen_Affirm), 1.5, _patient] call ACEFUNC(common,displayTextStructured);
};

_patient setVariable [QGVAR(oxygenMaskActive), true, true];

[{
_this params ["_args", "_pfhID"];
_args params ["_patient"];

if !(alive _patient) exitWith {
_patient setVariable [QGVAR(oxygenMaskActive), false, true];
_pfhID call CBA_fnc_removePerFrameHandler;
};

if (isNull objectParent _patient) exitWith {
_patient setVariable [QGVAR(oxygenMaskActive), false, true];
_pfhID call CBA_fnc_removePerFrameHandler;
};

if !((_patient call EFUNC(airway,checkMask))) exitWith {
_patient setVariable [QGVAR(oxygenMaskActive), false, true];
_pfhID call CBA_fnc_removePerFrameHandler;
};
}, 10, [
_patient
]] call CBA_fnc_addPerFrameHandler;
2 changes: 1 addition & 1 deletion addons/breathing/functions/fnc_canUseBVM.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@

params ["_patient"];

!(_patient call ACEFUNC(common,isAwake)) && !(_patient getVariable [QGVAR(BVMInUse), false] && {["",_patient] call ACEFUNC(medical_treatment,canCPR)});
!(_patient call ACEFUNC(common,isAwake)) && !(_patient getVariable [QGVAR(BVMInUse), false] && {["",_patient] call ACEFUNC(medical_treatment,canCPR)} && !(_patient getVariable [QGVAR(oxygenMaskActive), false]));
31 changes: 31 additions & 0 deletions addons/breathing/functions/fnc_checkAircraftOxygen.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "..\script_component.hpp"
/*
* Author: Mazinski
* Checks status of attached oxygen
* Main function
*
* Arguments:
* 0: Patient <OBJECT>
*
* Return Value:
* None
*
* Example:
* [player] call kat_breathing_fnc_checkAircraftOxygen;
*
* Public: No
*/

params ["_patient"];

if (isNull objectParent _patient) exitWith {
false
};

private _playerPosition = assignedVehicleRole _patient;

if ((_playerPosition select 0) isEqualTo "cargo") exitWith {
false
};

true
Loading

0 comments on commit dd2b1f5

Please sign in to comment.