Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Medical Vitals - Extract update logic to separate functions #10566

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions addons/medical_engine/script_macros_medical.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@

#define DEFAULT_TOURNIQUET_VALUES [0,0,0,0,0,0]

// Time until a tourniquet starts causing pain
#define TOURNIQUET_MIN_TIME_FOR_PAIN 120

// How much pain a tourniquet will cause per second after TOURNIQUET_MIN_TIME_FOR_PAIN
#define TOURNIQUET_PAIN_PER_SECOND 0.001

#define DEFAULT_FRACTURE_VALUES [0,0,0,0,0,0]

// Triage colors, for consistency across UIs and functions
Expand Down
1 change: 0 additions & 1 deletion addons/medical_status/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ PREP(adjustPainLevel);
PREP(getAllMedicationCount);
PREP(getBloodLoss);
PREP(getBloodPressure);
PREP(getBloodVolumeChange);
PREP(getCardiacOutput);
PREP(getMedicationCount);
PREP(handleKilled);
Expand Down
53 changes: 0 additions & 53 deletions addons/medical_status/functions/fnc_getBloodVolumeChange.sqf

This file was deleted.

24 changes: 13 additions & 11 deletions addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,26 @@ private _bodyPartBleeding = [0,0,0,0,0,0];
{
private _partIndex = ALL_BODY_PARTS find _x;
if (_tourniquets select _partIndex == 0) then {
private _partBleeding = 0;
{
_x params ["", "_amountOf", "_bleeeding"];
_bodyPartBleeding set [_partIndex, (_bodyPartBleeding select _partIndex) + (_amountOf * _bleeeding)];
_partBleeding = _partBleeding + (_amountOf * _bleeding);
} forEach _y;
_bodyPartBleeding set [_partIndex, _partBleeding];
};
} forEach GET_OPEN_WOUNDS(_unit);

if (_bodyPartBleeding isEqualTo [0,0,0,0,0,0]) then {
if (selectMax _bodyPartBleeding == 0) exitWith {
TRACE_1("updateWoundBloodLoss-none",_unit);
_unit setVariable [VAR_WOUND_BLEEDING, 0, true];
} else {
_bodyPartBleeding params ["_headBleeding", "_bodyBleeding", "_leftArmBleeding", "_rightArmBleeding", "_leftLegBleeding", "_rightLegBleeding"];
private _bodyBleedingRate = ((_headBleeding min 0.9) + (_bodyBleeding min 1.0)) min 1.0;
private _limbBleedingRate = ((_leftArmBleeding min 0.3) + (_rightArmBleeding min 0.3) + (_leftLegBleeding min 0.5) + (_rightLegBleeding min 0.5)) min 1.0;
};

// limb bleeding is scaled down based on the amount of body bleeding
_limbBleedingRate = _limbBleedingRate * (1 - _bodyBleedingRate);
_bodyPartBleeding params ["_headBleeding", "_bodyBleeding", "_leftArmBleeding", "_rightArmBleeding", "_leftLegBleeding", "_rightLegBleeding"];
private _bodyBleedingRate = ((_headBleeding min 0.9) + (_bodyBleeding min 1.0)) min 1.0;
private _limbBleedingRate = ((_leftArmBleeding min 0.3) + (_rightArmBleeding min 0.3) + (_leftLegBleeding min 0.5) + (_rightLegBleeding min 0.5)) min 1.0;

TRACE_3("updateWoundBloodLoss-bleeding",_unit,_bodyBleedingRate,_limbBleedingRate);
_unit setVariable [VAR_WOUND_BLEEDING, _bodyBleedingRate + _limbBleedingRate, true];
};
// limb bleeding is scaled down based on the amount of body bleeding
_limbBleedingRate = _limbBleedingRate * (1 - _bodyBleedingRate);

TRACE_3("updateWoundBloodLoss-bleeding",_unit,_bodyBleedingRate,_limbBleedingRate);
_unit setVariable [VAR_WOUND_BLEEDING, _bodyBleedingRate + _limbBleedingRate, true];
6 changes: 6 additions & 0 deletions addons/medical_vitals/XEH_PREP.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
PREP(consumeIVs);
PREP(consumeMedications);
PREP(handleUnitVitals);
PREP(scanConfig);
PREP(updateBloodPressure);
PREP(updateBloodVolume);
PREP(updateHeartRate);
PREP(updateOxygen);
PREP(updatePain);
PREP(updatePainSuppress);
PREP(updatePeripheralResistance);
PREP(updateState);
1 change: 1 addition & 0 deletions addons/medical_vitals/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ PREP_RECOMPILE_END;
#include "initSettings.inc.sqf"

GVAR(oxygenSupplyConditionCache) = uiNamespace getVariable QGVAR(oxygenSupplyConditionCache);
GVAR(deferredEvents) = createHashMap;

ADDON = true;
60 changes: 60 additions & 0 deletions addons/medical_vitals/functions/fnc_consumeIVs.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "..\script_component.hpp"
/*
* Author: Glowbal, LinkIsGrim
* Calculates fluid intake and consumes unit's IVs.
*
* Arguments:
* 0: The Unit <OBJECT>
* 1: Time since last update <NUMBER>
* 2: Global Sync Values (IVs) <BOOL>
*
* Return Value:
* Blood volume change (liters per second) <NUMBER>
*
* Example:
* [player, 1, true] call ace_medical_vitals_fnc_consumeIVs
*
* Public: No
*/

params ["_unit", "_deltaT", "_syncValues"];

private _ivBags = _unit getVariable [QEGVAR(medical,ivBags), []];

if (_ivBags isEqualTo []) exitWith {0};

private _tourniquets = GET_TOURNIQUETS(_unit);
private _bloodVolumeChange = 0;
private _consumedIVs = [];

{
_x params ["_bagVolumeRemaining", "_type", "_bodyPartIndex", "_treatment", "_rateCoef", "_item"];

if (_tourniquets select _bodyPartIndex > 0) then {
continue
};

private _bagChange = (_deltaT * EGVAR(medical,ivFlowRate) * IV_CHANGE_PER_SECOND * _rateCoef) min _bagVolumeRemaining; // absolute value of the change in miliLiters
_bagVolumeRemaining = _bagVolumeRemaining - _bagChange;
_consumedIVs pushBack [_type, _treatment, _bagChange];

if (_type in ["Blood", "Plasma", "Saline"]) then {
_bloodVolumeChange = _bloodVolumeChange + (_bagChange / 1000);
};

if (_bagVolumeRemaining >= 0.01) then {
_x set [0, _bagVolumeRemaining];
} else {
_ivBags deleteAt _forEachIndex;
};
} forEachReversed _ivBags;

(GVAR(deferredEvents) getOrDefault [_unit, [], true]) pushBack ([QEGVAR(medical,consumedIVs), [_unit, _consumedIVs]]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key can't be an object, you need to use hashValue first.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally not a huge fan of having a global hashmap for this kind of thing:

  1. If the unit is deleted, you need to handle the removal from the hashmap.
  2. If the unit switches locality, this can't handle it. Idk how important that is though.

Why not use an object variable instead? Handles 1) and no longer requires hashValue _unit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hashmap is slightly faster (might not be with hashvalue), that was the only incentive. If we don't have to worry about keeping 3rd-party code out of the counter, I'd rather just raise the events outright.
locality change and deletion won't (shouldn't) happen mid-execution, deferred events are still executed on the same frame, so it'll be either before or after handleUnitVitals is executed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather just raise the events outright

Do that then, makes more sense.

LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved

if (_ivBags isEqualTo []) then {
_unit setVariable [QEGVAR(medical,ivBags), nil, true];
} else {
_unit setVariable [QEGVAR(medical,ivBags), _ivBags, _syncValues];
};

_bloodVolumeChange // return
61 changes: 61 additions & 0 deletions addons/medical_vitals/functions/fnc_consumeMedications.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "..\script_component.hpp"
/*
* Author: Glowbal, LinkIsGrim
* Consumes unit's medications and update relevant vitals
*
* Arguments:
* 0: The Unit <OBJECT>
* 1: Time since last update <NUMBER>
* 2: Global Sync Values (medications) <BOOL>
*
* Return Value:
* Values should be synced <BOOL>
*
* Example:
* [player, 1, true] call ace_medical_vitals_fnc_consumeMedications
*
* Public: No
*/

params ["_unit", "_deltaT", "_syncValues"];

private _medications = _unit getVariable [VAR_MEDICATIONS, []];

if (_medications isEqualTo []) exitWith {
[0, 0, 0, false]
};

private _hrTargetAdjustment = 0;
private _painSupressAdjustment = 0;
private _peripheralResistanceAdjustment = 0;
private _consumedMedications = [];

{
_x params ["_medication", "_timeAdded", "_timeTillMaxEffect", "_maxTimeInSystem", "_hrAdjust", "_painAdjust", "_flowAdjust"];

private _timeInSystem = CBA_missionTime - _timeAdded;
if (_timeInSystem >= _maxTimeInSystem) then {
_syncValues = true;
_medications deleteAt _forEachIndex;
} else {
private _effectRatio = (((_timeInSystem / _timeTillMaxEffect) ^ 2) min 1) * (_maxTimeInSystem - _timeInSystem) / _maxTimeInSystem;

_consumedMedications pushBack [_medication, _effectRatio];

if (_hrAdjust != 0) then { _hrTargetAdjustment = _hrTargetAdjustment + _hrAdjust * _effectRatio; };
if (_painAdjust != 0) then { _painSupressAdjustment = _painSupressAdjustment + _painAdjust * _effectRatio; };
if (_flowAdjust != 0) then { _peripheralResistanceAdjustment = _peripheralResistanceAdjustment + _flowAdjust * _effectRatio; };
};
} forEachReversed _medications;

(GVAR(deferredEvents) getOrDefault [_unit, [], true]) pushBack ([QEGVAR(medical,consumeMedications), [_unit, _consumedMedications]]);
LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved

if (_syncValues) then {
_unit setVariable [VAR_MEDICATIONS, _medications, true]
};

[_unit, _hrTargetAdjustment, _deltaT, _syncValues] call FUNC(updateHeartRate);
[_unit, _painSupressAdjustment, _deltaT, _syncValues] call FUNC(updatePainSuppress);
[_unit, _peripheralResistanceAdjustment, _deltaT, _syncValues] call FUNC(updatePeripheralResistance);

_syncValues // return
Loading
Loading