Added initial rewrite of CMS vitals script for medium and advanced medical.

This commit is contained in:
Glowbal 2015-02-07 23:55:48 +01:00
parent 26527489d6
commit aadb289962
6 changed files with 361 additions and 0 deletions

View File

@ -0,0 +1,42 @@
/**
* fn_getBloodLoss.sqf
* @Descr: Calculate the total blood loss of a unit.
* @Author: Glowbal
*
* @Arguments: [unit OBJECT]
* @Return: NUMBER Total blood loss of unit
* @PublicAPI: true
*/
#include "script_component.hpp"
#define BLOODLOSS_SMALL_WOUNDS 0.025
#define BLOODLOSS_MEDIUM_WOUNDS 0.05
#define BLOODLOSS_LARGE_WOUNDS 0.1
/**
* The default cardiac output when all stats are set to normal is 5.25.
*/
#define DEFAULT_CARDIAC_OUTPUT 5.25
private ["_totalBloodLoss","_tourniquets","_openWounds", "_value", "_cardiacOutput"];
// TODO Only use this calculation if medium or higher, otherwise use vanilla calculations (for basic medical).
_totalBloodLoss = 0;
_tourniquets = _this getvariable [QGVAR(tourniquets), [0,0,0,0,0,0]];
_openWounds = _this getvariable [QGVAR(openWounds), []];
//_cardiacOutput = [_this] call FUNC(getCardiacOutput);
{
if ((_tourniquets select (_x select 2)) < 1) then {
_totalBloodLoss = _totalBloodLoss + ([BLOODLOSS_SMALL_WOUNDS, BLOODLOSS_MEDIUM_WOUNDS, BLOODLOSS_LARGE_WOUNDS] select (_x select 1));
// (((BLOODLOSS_SMALL_WOUNDS * (_x select 0))) + ((BLOODLOSS_MEDIUM_WOUNDS * (_x select 1))) + ((BLOODLOSS_LARGE_WOUNDS * (_x select 2))) * (_cardiacOutput / DEFAULT_CARDIAC_OUTPUT));
};
}foreach _openWounds;
// cap the blood loss to be no greater as the current cardiac output
//(_totalBloodLoss min _cardiacOutput);
_totalBloodLoss;

View File

@ -0,0 +1,31 @@
/**
* fn_getBloodPressure.sqf
* @Descr: Calculate the current blood pressure of a unit.
* @Author: Glowbal
*
* @Arguments: [unit OBJECT (The unit to get the blood pressure from.)]
* @Return: ARRAY Blood Pressure. Format [low NUMBER, high NUMBER]
* @PublicAPI: true
*/
#include "script_component.hpp"
/*
Value is taken because with cardic output and resistance at default values, it will put blood pressure High at 120.
*/
#define MODIFIER_BP_HIGH 0.229
/*
Value is taken because with cardic output and resistance at default values, it will put blood pressure Low at 80.
*/
#define MODIFIER_BP_LOW 0.1524
private ["_unit", "_bloodPressureLow", "_bloodPressureHigh", "_cardiacOutput", "_resistance"];
_unit = _this select 0;
_cardiacOutput = [_unit] call FUNC(getCardiacOutput);
_resistance = _unit getvariable [QGVAR(peripheralResistance), 100];
_bloodPressureHigh = (_cardiacOutput * MODIFIER_BP_HIGH) * _resistance;
_bloodPressureLow = (_cardiacOutput * MODIFIER_BP_LOW) * _resistance;
[_bloodPressureLow, _bloodPressureHigh];

View File

@ -0,0 +1,54 @@
/**
* fn_getBloodVolumeChange.sqf
* @Descr: Calculates the blood volume change and decreases the IVs given to the unit.
* @Author: Glowbal
*
* @Arguments: []
* @Return: NUMBER Bloodvolume change
* @PublicAPI: false
*/
#include "script_component.hpp"
/*
IV Change per second calculation:
250ml should take 60 seconds to fill. 250/60 = 4.166.
*/
#define IV_CHANGE_PER_SECOND -4.166
/*
Blood Change per second calculation for IVs:
250ml should take 60 seconds to fill in. Total blood volume is 7000ml = 100%.
7000/100 = 70 = 1%
250 / 70 = 3.571428571%
3.571428571 / 60 = 0.0595% per second.
*/
#define BLOOD_CHANGE_PER_SECOND 0.0595
private ["_unit","_bloodVolume","_bloodVolumeChange", "_ivVolume"];
_unit = _this select 0;
_bloodVolume = _unit getvariable [QGVAR(bloodVolume), 100];
_bloodVolumeChange = -(_unit call FUNC(getBloodLoss));
if (_bloodVolume < 100.0) then {
if ((_unit getvariable [QGVAR(salineIVVolume), 0]) > 0) then {
_bloodVolumeChange = _bloodVolumeChange + BLOOD_CHANGE_PER_SECOND;
_ivVolume = (_unit getvariable [QGVAR(salineIVVolume), 0]) + IV_CHANGE_PER_SECOND;
_unit setvariable [QGVAR(salineIVVolume),_ivVolume];
};
if ((_unit getvariable [QGVAR(plasmaIVVolume), 0]) > 0) then {
_bloodVolumeChange = _bloodVolumeChange + BLOOD_CHANGE_PER_SECOND;
_ivVolume = (_unit getvariable [QGVAR(plasmaIVVolume), 0]) + IV_CHANGE_PER_SECOND;
_unit setvariable [QGVAR(plasmaIVVolume),_ivVolume];
};
if ((_unit getvariable [QGVAR(bloodIVVolume), 0]) > 0) then {
_bloodVolumeChange = _bloodVolumeChange + BLOOD_CHANGE_PER_SECOND;
_ivVolume = (_unit getvariable [QGVAR(bloodIVVolume), 0]) + IV_CHANGE_PER_SECOND;
_unit setvariable [QGVAR(bloodIVVolume),_ivVolume];
};
};
_bloodVolumeChange;

View File

@ -0,0 +1,25 @@
/**
* fn_getCardiacOutput.sqf
* @Descr: Get the cardiac output from the Heart, based on current Heart Rate and Blood Volume.
* @Author: Glowbal
*
* @Arguments: [unit OBJECT]
* @Return: NUMBER Current cardiac output.
* @PublicAPI: true
*/
#include "script_component.hpp"
/*
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 time interval of one minute. CO may be measured in many ways, for example dm3/min (1 dm3 equals 1 litre).
Source: http://en.wikipedia.org/wiki/Cardiac_output
*/
// to limit the amount of complex calculations necessary, we take a set modifier to calculate Stroke Volume.
#define MODIFIER_CARDIAC_OUTPUT 19.04761
private "_unit";
_unit = _this select 0;
((_unit getvariable [QGVAR(bloodVolume), 100])/MODIFIER_CARDIAC_OUTPUT) + ((_unit getvariable [QGVAR(heartRate), 80])/80-1);

View File

@ -0,0 +1,82 @@
/**
* fn_getHeartRateChange.sqf
* @Descr: N/A
* @Author: Glowbal
*
* @Arguments: []
* @Return: void
* @PublicAPI: false
*/
#include "script_component.hpp"
#define HEART_RATE_MODIFIER 0.02
private ["_unit", "_heartRate", "_hrIncrease", "_bloodLoss", "_time", "_values", "_adjustment", "_adjustments", "_additionalIncrease", "_change", "_callBack", "_bloodVolume"];
_unit = _this select 0;
_hrIncrease = 0;
if (!(_unit getvariable [QGVAR(inCardiacArrest),false])) then {
_heartRate = _unit getvariable [QGVAR(heartRate), 80];
_bloodLoss = _unit call FUNC(getBloodLoss);
_adjustment = _unit getvariable [QGVAR(heartRateAdjustments), []];
{
_values = (_x select 0);
if (abs _values > 0) then {
_time = (_x select 1);
_callBack = _x select 2;
if (_time <= 0) then {
_time = 1;
};
_change = (_values / _time);
_hrIncrease = _hrIncrease + _change;
if ( (_time - 1) < 0) then {
_time = 0;
_adjustment set [_foreachIndex, ObjNull];
[_unit] call _callBack;
} else {
_time = _time - 1;
_adjustment set [_foreachIndex, [_values - _change, _time]];
};
} else {
_adjustment set [_foreachIndex, ObjNull];
};
}foreach _adjustment;
_adjustment = _adjustment - [ObjNull];
_unit setvariable [QGVAR(heartRateAdjustments), _adjustment];
_bloodVolume = _unit getvariable [QGVAR(bloodVolume), 100];
if (_bloodVolume > 75) then {
if (_bloodLoss >0.0) then {
if (_bloodLoss <0.5) then {
if (_heartRate < 126) then {
_hrIncrease = _hrIncrease + 0.05;
};
} else {
if (_bloodLoss < 1) then {
if (_heartRate < 161) then {
_hrIncrease = _hrIncrease + 0.1;
};
} else {
if (_heartRate < 220) then {
_hrIncrease = _hrIncrease + 0.15;
};
};
};
} else {
// Stabalize it
if (_heartRate < (60 + round(random(10)))) then {
_hrIncrease = _hrIncrease + HEART_RATE_MODIFIER;
} else {
if (_heartRate > (77 + round(random(10)))) then {
_hrIncrease = _hrIncrease - HEART_RATE_MODIFIER;
};
};
};
} else {
_hrIncrease = _hrIncrease - HEART_RATE_MODIFIER;
};
};
_hrIncrease

View File

@ -0,0 +1,127 @@
/**
* fn_handleUnitVitals.sqf
* @Descr: Updates the vitals. Is expected to be called every second.
* @Author: Glowbal
*
* @Arguments: [unit OBJECT]
* @Return: void
* @PublicAPI: false
*/
#include "script_component.hpp"
private ["_unit", "_heartRate","_bloodPressure","_bloodVolume","_painStatus"];
_unit = _this select 0;
_bloodVolume = (_unit getvariable [QGVAR(bloodVolume), 0]) + ([_unit] call FUNC(getBloodVolumeChange));
if (_bloodVolume <= 0) then {
_bloodVolume = 0;
};
_unit setvariable [QGVAR(bloodVolume), _bloodVolume];
// Set variables for synchronizing information across the net
if (_bloodVolume < 90) then {
if !(_unit getvariable [QGVAR(hasLostBlood), false]) then {
_unit setvariable [QGVAR(hasLostBlood), true, true];
};
} else {
if (_unit getvariable [QGVAR(hasLostBlood),false]) then {
_unit setvariable [QGVAR(hasLostBlood), false, true];
};
};
if ((_unit call FUNC(getBloodLoss)) > 0) then {
if !(_unit getvariable [QGVAR(isBleeding), false]) then {
_unit setvariable [QGVAR(isBleeding), true, true];
};
} else {
if (_unit getvariable [QGVAR(isBleeding), false]) then {
_unit setvariable [QGVAR(isBleeding), false, true];
};
};
_painStatus = _unit getvariable [QGVAR(amountOfPain), 0];
if (_painStatus > 0) then {
if !(_unit getvariable [QGVAR(hasPain), false]) then {
_unit setvariable [QGVAR(hasPain), true, true];
};
} else {
if (_unit getvariable [QGVAR(hasPain), false]) then {
_unit setvariable [QGVAR(hasPain), false, true];
};
};
if (_bloodVolume < 30) exitwith {
// [_unit] call FUNC(setDead);
};
if ([_unit] call EFUNC(common,isAwake)) then {
if (_bloodVolume < 60) then {
if (random(1) > 0.9) then {
//[_unit] call FUNC(setUnconsciousState);
};
};
};
// handle advanced medical, with vitals
if ((missionNamespace getvariable[QGVAR(setting_AdvancedLevel), 0]) > 0) exitwith {
// Set the vitals
_heartRate = (_unit getvariable [QGVAR(heartRate), 0]) + ([_unit] call FUNC(getHeartRateChange));
_unit setvariable [QGVAR(heartRate), _heartRate];
_bloodPressure = [_unit] call FUNC(getBloodPressure);
_unit setvariable [QGVAR(bloodPressure), _bloodPressure];
// Handle airway
if (GVAR(setting_allowAirwayInjuries)) then {
_airwayStatus = _unit getvariable [QGVAR(airwayStatus), 100];
if (((_unit getvariable [QGVAR(airwayOccluded), false]) || (_unit getvariable [QGVAR(airwayCollapsed), false])) && !((_unit getvariable [QGVAR(airwaySecured), false]))) then {
if (_airwayStatus >= 0.5) then {
_unit setvariable [QGVAR(airwayStatus), _airwayStatus - 0.5];
};
} else {
if !((_unit getvariable [QGVAR(airwayOccluded), false]) || (_unit getvariable [QGVAR(airwayCollapsed), false])) then {
if (_airwayStatus <= 98.5) then {
_unit setvariable [QGVAR(airwayStatus), _airwayStatus + 1.5];
};
};
};
};
// Check vitals for medical status
// TODO check for in revive state instead of variable
// TODO Implement cardiac arrest.
/* _bloodPressureL = _bloodPressure select 0;
_bloodPressureH = _bloodPressure select 1;
if (!(_unit getvariable [QGVAR(inCardiacArrest),false])) then {
if (_heartRate < 10 || _bloodPressureH < 30 || _bloodVolume < 20) then {
[_unit] call FUNC(setUnconsciousState); // safety check to ensure unconsciousness for units if they are not dead already.
};
if (_bloodPressureH > 260) then {
if (random(1) > 0.7) then {
[_unit] call FUNC(setCardiacArrest);
};
};
if (_bloodPressureL < 40 && _heartRate > 190) then {
if (random(1) > 0.7) then {
[_unit] call FUNC(setCardiacArrest);
};
};
if (_bloodPressureH > 145 && _heartRate > 150) then {
if (random(1) > 0.7) then {
[_unit] call FUNC(setCardiacArrest);
};
};
if (_heartRate > 200) then {
[_unit] call FUNC(setCardiacArrest);
};
if (_heartRate < 20) then {
[_unit] call FUNC(setCardiacArrest);
};
};*/
};