ACE3/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf

209 lines
9.6 KiB
Plaintext
Raw Normal View History

#include "script_component.hpp"
/*
* Author: Glowbal, commy2
* Handling of the open wounds & injuries upon the handleDamage eventhandler.
*
* Arguments:
* 0: Unit That Was Hit <OBJECT>
* 1: Name Of Body Part <STRING>
* 2: Amount Of Damage <NUMBER>
* 3: Type of the damage done <STRING>
* 4: Weighted array of damaged selections <ARRAY>
*
* Return Value:
* None
*
2019-03-30 16:07:54 +00:00
* Example:
* [player, "Body", 0.5, "bullet", [1, 1]] call ace_medical_damage_fnc_woundsHandlerSQF
2019-03-30 16:07:54 +00:00
*
* Public: No
*/
params ["_unit", "_bodyPart", "_damage", "_typeOfDamage", "_damageSelectionArray"];
TRACE_5("woundsHandlerSQF",_unit,_bodyPart,_damage,_typeOfDamage,_damageSelectionArray);
// Convert the selectionName to a number and ensure it is a valid selection.
private _bodyPartN = ALL_BODY_PARTS find toLower _bodyPart;
if (_bodyPartN < 0) exitWith { ERROR_1("invalid body part %1",_bodyPart); };
if ((_typeOfDamage isEqualTo "") || {isNil {GVAR(allDamageTypesData) getVariable _typeOfDamage}}) then {
WARNING_1("damage type [%1] not found",_typeOfDamage);
_typeOfDamage = "unknown";
};
// Get the damage type information. Format: [typeDamage thresholds, selectionSpecific, woundTypes]
// WoundTypes are the available wounds for this damage type. Format [[classID, selections, bleedingRate, pain], ..]
private _damageTypeInfo = [GVAR(allDamageTypesData) getVariable _typeOfDamage] param [0, [[], false, []]];
_damageTypeInfo params ["_thresholds", "_isSelectionSpecific", "_woundTypes"];
// find the available injuries for this damage type and damage amount
private _highestPossibleSpot = -1;
private _highestPossibleDamage = -1;
private _allPossibleInjuries = [];
{
_x params ["", "_selections", "", "", "_damageExtrema"];
_damageExtrema params ["_minDamage", "_maxDamage"];
// Check if the damage is higher as the min damage for the specific injury
if (_damage >= _minDamage && {_damage <= _maxDamage || _maxDamage < 0}) then {
// Check if the injury can be applied to the given selection name
// if ("All" in _selections || {_bodyPart in _selections}) then { // @todo, this is case sensitive! [we have no injuries that use this, disabled for now]
// Find the wound which has the highest minimal damage, so we can use this later on for adding the correct injuries
if (_minDamage > _highestPossibleDamage) then {
_highestPossibleSpot = _forEachIndex;
_highestPossibleDamage = _minDamage;
};
// Store the valid possible injury for the damage type, damage amount and selection
_allPossibleInjuries pushBack _x;
// };
};
} forEach _woundTypes;
// No possible wounds available for this damage type or damage amount.
if (_highestPossibleSpot < 0) exitWith { TRACE_2("no wounds possible",_damage,_highestPossibleSpot); };
// Administration for open wounds and ids
2019-06-22 18:36:27 +00:00
private _openWounds = GET_OPEN_WOUNDS(_unit);
private _updateDamageEffects = false;
private _painLevel = 0;
private _critialDamage = false;
2016-12-08 10:38:43 +00:00
private _bodyPartDamage = _unit getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]];
2017-06-08 18:50:38 +00:00
private _bodyPartVisParams = [_unit, false, false, false, false]; // params array for EFUNC(medical_engine,updateBodyPartVisuals);
{
_x params ["_thresholdMinDam", "_thresholdWoundCount"];
Medical - Fix severity of wound bleeding and adjust cardiac output calculations (#7010) * Fix severity of wound bleeding I'm simplifying the nastiness calculations so that the wound config specifies the worst wound and we scale it between 25% to 100% based on the wound damage and number of wounds recieved. Similarly I've updated the wound configs to more reasonable maximum bleeding values based on the fact that they're percentages of cardiac output being bled. * Limit variance of pain modifier This is to avoid unexpectedly high pain for small wounds or unexpectedly small pain for large wounds * Make more wounds increase chance for nastiness Rather than guarantee * Adjust worst damage scaling This handles torso wounds better as they're typically around 0.3-0.6 for 6.5mm shots which makes them roughly medium sized. * Fix cardiac output calculation Previously the calculation didn't make sense as it wasn't outputting a value in l/s. This method of calculation makes more logical sense and provides a point of reference for what the bleeding values actually represent (percentage of the blood being pumped that is lost - which now has an actual volumetric value). * Fix blood pressure after change to cardiac output * Fix heartrate skyrocketing between 5l and 4l blood Pretty sure someone accidnentally got these conditions the wrong way around. This way blood pressure will first drop and then heart rate will later go up to compensate. * Fix comment typo Co-Authored-By: PabstMirror <pabstmirror@gmail.com>
2019-06-10 16:23:21 +00:00
if (_damage > _thresholdMinDam) exitWith {
private _woundDamage = _damage / (_thresholdWoundCount max 1); // If the damage creates multiple wounds
for "_i" from 1 to _thresholdWoundCount do {
Medical - Fix severity of wound bleeding and adjust cardiac output calculations (#7010) * Fix severity of wound bleeding I'm simplifying the nastiness calculations so that the wound config specifies the worst wound and we scale it between 25% to 100% based on the wound damage and number of wounds recieved. Similarly I've updated the wound configs to more reasonable maximum bleeding values based on the fact that they're percentages of cardiac output being bled. * Limit variance of pain modifier This is to avoid unexpectedly high pain for small wounds or unexpectedly small pain for large wounds * Make more wounds increase chance for nastiness Rather than guarantee * Adjust worst damage scaling This handles torso wounds better as they're typically around 0.3-0.6 for 6.5mm shots which makes them roughly medium sized. * Fix cardiac output calculation Previously the calculation didn't make sense as it wasn't outputting a value in l/s. This method of calculation makes more logical sense and provides a point of reference for what the bleeding values actually represent (percentage of the blood being pumped that is lost - which now has an actual volumetric value). * Fix blood pressure after change to cardiac output * Fix heartrate skyrocketing between 5l and 4l blood Pretty sure someone accidnentally got these conditions the wrong way around. This way blood pressure will first drop and then heart rate will later go up to compensate. * Fix comment typo Co-Authored-By: PabstMirror <pabstmirror@gmail.com>
2019-06-10 16:23:21 +00:00
// Find the injury we are going to add. Format [ classID, allowedSelections, bleedingRate, injuryPain]
private _oldInjury = if (random 1 < 0.15) then {
_woundTypes select _highestPossibleSpot
} else {
selectRandom _allPossibleInjuries
};
_oldInjury params ["_woundClassIDToAdd", "", "_injuryBleedingRate", "_injuryPain", "", "", "", "_causeLimping", "_causeFracture"];
private _bodyPartNToAdd = if (_isSelectionSpecific) then {_bodyPartN} else {selectRandomWeighted _damageSelectionArray};
2018-05-10 16:44:02 +00:00
_bodyPartDamage set [_bodyPartNToAdd, (_bodyPartDamage select _bodyPartNToAdd) + _woundDamage];
2017-06-08 18:50:38 +00:00
_bodyPartVisParams set [[1,2,3,3,4,4] select _bodyPartNToAdd, true]; // Mark the body part index needs updating
2018-05-10 16:44:02 +00:00
Medical - Fix severity of wound bleeding and adjust cardiac output calculations (#7010) * Fix severity of wound bleeding I'm simplifying the nastiness calculations so that the wound config specifies the worst wound and we scale it between 25% to 100% based on the wound damage and number of wounds recieved. Similarly I've updated the wound configs to more reasonable maximum bleeding values based on the fact that they're percentages of cardiac output being bled. * Limit variance of pain modifier This is to avoid unexpectedly high pain for small wounds or unexpectedly small pain for large wounds * Make more wounds increase chance for nastiness Rather than guarantee * Adjust worst damage scaling This handles torso wounds better as they're typically around 0.3-0.6 for 6.5mm shots which makes them roughly medium sized. * Fix cardiac output calculation Previously the calculation didn't make sense as it wasn't outputting a value in l/s. This method of calculation makes more logical sense and provides a point of reference for what the bleeding values actually represent (percentage of the blood being pumped that is lost - which now has an actual volumetric value). * Fix blood pressure after change to cardiac output * Fix heartrate skyrocketing between 5l and 4l blood Pretty sure someone accidnentally got these conditions the wrong way around. This way blood pressure will first drop and then heart rate will later go up to compensate. * Fix comment typo Co-Authored-By: PabstMirror <pabstmirror@gmail.com>
2019-06-10 16:23:21 +00:00
// Damage to limbs/head is scaled higher than torso by engine
// Anything above this value is guaranteed worst wound possible
private _worstDamage = [2, 1, 4, 4, 4, 4] select _bodyPartNToAdd;
Medical - Fix severity of wound bleeding and adjust cardiac output calculations (#7010) * Fix severity of wound bleeding I'm simplifying the nastiness calculations so that the wound config specifies the worst wound and we scale it between 25% to 100% based on the wound damage and number of wounds recieved. Similarly I've updated the wound configs to more reasonable maximum bleeding values based on the fact that they're percentages of cardiac output being bled. * Limit variance of pain modifier This is to avoid unexpectedly high pain for small wounds or unexpectedly small pain for large wounds * Make more wounds increase chance for nastiness Rather than guarantee * Adjust worst damage scaling This handles torso wounds better as they're typically around 0.3-0.6 for 6.5mm shots which makes them roughly medium sized. * Fix cardiac output calculation Previously the calculation didn't make sense as it wasn't outputting a value in l/s. This method of calculation makes more logical sense and provides a point of reference for what the bleeding values actually represent (percentage of the blood being pumped that is lost - which now has an actual volumetric value). * Fix blood pressure after change to cardiac output * Fix heartrate skyrocketing between 5l and 4l blood Pretty sure someone accidnentally got these conditions the wrong way around. This way blood pressure will first drop and then heart rate will later go up to compensate. * Fix comment typo Co-Authored-By: PabstMirror <pabstmirror@gmail.com>
2019-06-10 16:23:21 +00:00
// More wounds means more likely to get nasty wound
private _countModifier = 1 + random(_i - 1);
// Config specifies bleeding and pain for worst possible wound
// Worse wound correlates to higher damage, damage is not capped at 1
private _bleedModifier = linearConversion [0.1, _worstDamage, _woundDamage * _countModifier, 0.25, 1, true];
private _painModifier = (_bleedModifier * random [0.7, 1, 1.3]) min 1; // Pain isn't directly scaled to bleeding
private _bleeding = _injuryBleedingRate * _bleedModifier;
private _pain = _injuryPain * _painModifier;
_painLevel = _painLevel + _pain;
Medical - Fix severity of wound bleeding and adjust cardiac output calculations (#7010) * Fix severity of wound bleeding I'm simplifying the nastiness calculations so that the wound config specifies the worst wound and we scale it between 25% to 100% based on the wound damage and number of wounds recieved. Similarly I've updated the wound configs to more reasonable maximum bleeding values based on the fact that they're percentages of cardiac output being bled. * Limit variance of pain modifier This is to avoid unexpectedly high pain for small wounds or unexpectedly small pain for large wounds * Make more wounds increase chance for nastiness Rather than guarantee * Adjust worst damage scaling This handles torso wounds better as they're typically around 0.3-0.6 for 6.5mm shots which makes them roughly medium sized. * Fix cardiac output calculation Previously the calculation didn't make sense as it wasn't outputting a value in l/s. This method of calculation makes more logical sense and provides a point of reference for what the bleeding values actually represent (percentage of the blood being pumped that is lost - which now has an actual volumetric value). * Fix blood pressure after change to cardiac output * Fix heartrate skyrocketing between 5l and 4l blood Pretty sure someone accidnentally got these conditions the wrong way around. This way blood pressure will first drop and then heart rate will later go up to compensate. * Fix comment typo Co-Authored-By: PabstMirror <pabstmirror@gmail.com>
2019-06-10 16:23:21 +00:00
// wound category (minor [0.25-0.5], medium [0.5-0.75], large [0.75+])
private _category = floor linearConversion [0.25, 0.75, _bleedModifier, 0, 2, true];
private _classComplex = 10 * _woundClassIDToAdd + _category;
2016-12-14 17:04:56 +00:00
// Create a new injury. Format [0:classComplex, 1:bodypart, 2:amountOf, 3:bleedingRate, 4:woundDamage]
private _injury = [_classComplex, _bodyPartNToAdd, 1, _bleeding, _woundDamage];
if (_bodyPartNToAdd == 0 || {_bodyPartNToAdd == 1 && {_woundDamage > PENETRATION_THRESHOLD}}) then {
_critialDamage = true;
};
if ([_unit, _bodyPartNToAdd, _bodyPartDamage, _woundDamage] call FUNC(determineIfFatal)) then {
if (!isPlayer _unit || {random 1 < EGVAR(medical,deathChance)}) then {
TRACE_1("determineIfFatal returned true",_woundDamage);
[QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent;
};
};
#ifdef DEBUG_MODE_FULL
systemChat format["%1, damage: %2, peneration: %3, bleeding: %4, pain: %5", _bodyPart, _woundDamage toFixed 2, _woundDamage > PENETRATION_THRESHOLD, _bleeding toFixed 3, _pain toFixed 3];
#endif
switch (true) do {
case (
_causeFracture
&& {EGVAR(medical,fractures) > 0}
&& {_bodyPartNToAdd > 1}
&& {_woundDamage > FRACTURE_DAMAGE_THRESHOLD}
&& {random 1 < EGVAR(medical,fractureChance)}
): {
Medical Treatment - Modernize and Cleanup (#6933) * Modernize and cleanup medical_treatment * One line for each old public function * Fix litterCleanupDelay name * Improve adjustment calcs / wound blood loss / medications fix func descriptions Calc wound blood loss on events reorder includes so scritpmacroMed has global effect trivial optimization for getCardiacOutput Fix var Fix wounds not reopening (nil _category) Fix surgical kit inherting canBandage conditional debug hitpoints Update ACE_Medical_Treatment_Actions.hpp Use woundBleeding for IS_BLEEDING macro rework medication vars comments Reset var in init / fullHeal Update addons/medical_treatment/functions/fnc_onMedicationUsage.sqf Co-Authored-By: PabstMirror <pabstmirror@gmail.com> * Change wound data array Drop unique id and merge classId and category * Splinting and treatment and gui * Add arm fractures and aim effects * localizations and event * fix * fix merge for renamed files * Fixes and code review changes * Move medical logs clearing to treatment * More cleanup work * cleanup * Apply suggestions from code review Co-Authored-By: PabstMirror <pabstmirror@gmail.com> * formating, rename bone images * Fix args for setDead call in actionPlaceInBodyBag * Apply suggestions from code review Co-Authored-By: PabstMirror <pabstmirror@gmail.com> * disable calls to extension * Update fnc_onMedicationUsage.sqf * Medical - Skip unneeded setVars on initUnit (#6949) * Medical - Transfer state machine state on locality (#6950) * Medical - Transfer state machine state on locality * Fix feedback isUnconscious var * Exclude AI * Make UAV excludes consistant, formating * Update fnc_treatmentFullHealLocal.sqf * reset fractures on respawn * Fix merge * Add PAK time coefficient setting * Fix medication * Add ace_medical_replacementItems config array * checkItems performance improvement * Treatment - cap max animation speed (#6995) * Treatment - cap max animation speed and add lock to prevent AF from reseting anim * Update fnc_getBandageTime.sqf * Use local version of setAnimSpeedCoef * Revert "Use local version of setAnimSpeedCoef" This reverts commit 36c22a90473fd0670ab97f3a373e4ae08493ff52. * Move replacementItems compiling to preInit * Improve replacementItems compiling * Cleanup splint functions, use macros for fractures * Rename splintCondition to canSplint * Add cprCreatesPulse setting * Cleanup remaining functions * Capitalize stringtable entry names * getStitchTime function and fix treatment locations * Update addons/medical_treatment/functions/fnc_getHealTime.sqf Co-Authored-By: SilentSpike <silentspike100+Github@gmail.com>
2019-06-03 15:31:46 +00:00
private _fractures = GET_FRACTURES(_unit);
_fractures set [_bodyPartNToAdd, 1];
Medical Treatment - Modernize and Cleanup (#6933) * Modernize and cleanup medical_treatment * One line for each old public function * Fix litterCleanupDelay name * Improve adjustment calcs / wound blood loss / medications fix func descriptions Calc wound blood loss on events reorder includes so scritpmacroMed has global effect trivial optimization for getCardiacOutput Fix var Fix wounds not reopening (nil _category) Fix surgical kit inherting canBandage conditional debug hitpoints Update ACE_Medical_Treatment_Actions.hpp Use woundBleeding for IS_BLEEDING macro rework medication vars comments Reset var in init / fullHeal Update addons/medical_treatment/functions/fnc_onMedicationUsage.sqf Co-Authored-By: PabstMirror <pabstmirror@gmail.com> * Change wound data array Drop unique id and merge classId and category * Splinting and treatment and gui * Add arm fractures and aim effects * localizations and event * fix * fix merge for renamed files * Fixes and code review changes * Move medical logs clearing to treatment * More cleanup work * cleanup * Apply suggestions from code review Co-Authored-By: PabstMirror <pabstmirror@gmail.com> * formating, rename bone images * Fix args for setDead call in actionPlaceInBodyBag * Apply suggestions from code review Co-Authored-By: PabstMirror <pabstmirror@gmail.com> * disable calls to extension * Update fnc_onMedicationUsage.sqf * Medical - Skip unneeded setVars on initUnit (#6949) * Medical - Transfer state machine state on locality (#6950) * Medical - Transfer state machine state on locality * Fix feedback isUnconscious var * Exclude AI * Make UAV excludes consistant, formating * Update fnc_treatmentFullHealLocal.sqf * reset fractures on respawn * Fix merge * Add PAK time coefficient setting * Fix medication * Add ace_medical_replacementItems config array * checkItems performance improvement * Treatment - cap max animation speed (#6995) * Treatment - cap max animation speed and add lock to prevent AF from reseting anim * Update fnc_getBandageTime.sqf * Use local version of setAnimSpeedCoef * Revert "Use local version of setAnimSpeedCoef" This reverts commit 36c22a90473fd0670ab97f3a373e4ae08493ff52. * Move replacementItems compiling to preInit * Improve replacementItems compiling * Cleanup splint functions, use macros for fractures * Rename splintCondition to canSplint * Add cprCreatesPulse setting * Cleanup remaining functions * Capitalize stringtable entry names * getStitchTime function and fix treatment locations * Update addons/medical_treatment/functions/fnc_getHealTime.sqf Co-Authored-By: SilentSpike <silentspike100+Github@gmail.com>
2019-06-03 15:31:46 +00:00
_unit setVariable [VAR_FRACTURES, _fractures, true];
[QEGVAR(medical,fracture), [_unit, _bodyPartNToAdd]] call CBA_fnc_localEvent;
TRACE_1("Limb fracture",_bodyPartNToAdd);
_updateDamageEffects = true;
};
case (
_causeLimping
&& {EGVAR(medical,limping) > 0}
&& {_bodyPartNToAdd > 3}
&& {_woundDamage > LIMPING_DAMAGE_THRESHOLD}
): {
_updateDamageEffects = true;
};
};
// if possible merge into existing wounds
private _createNewWound = true;
{
_x params ["_classID", "_bodyPartN", "_oldAmountOf", "_oldBleeding", "_oldDamage"];
if (
(_classComplex == _classID) &&
{_bodyPartNToAdd == _bodyPartN} &&
{(_bodyPartNToAdd != 1) || {(_woundDamage < PENETRATION_THRESHOLD) isEqualTo (_oldDamage < PENETRATION_THRESHOLD)}} && // penetrating body damage is handled differently
{(_bodyPartNToAdd > 3) || {!_causeLimping} || {(_woundDamage <= LIMPING_DAMAGE_THRESHOLD) isEqualTo (_oldDamage <= LIMPING_DAMAGE_THRESHOLD)}} // ensure limping damage is stacked correctly
) exitWith {
TRACE_2("merging with existing wound",_injury,_x);
private _newAmountOf = _oldAmountOf + 1;
_x set [2, _newAmountOf];
private _newBleeding = (_oldAmountOf * _oldBleeding + _bleeding) / _newAmountOf;
_x set [3, _newBleeding];
private _newDamage = (_oldAmountOf * _oldDamage + _woundDamage) / _newAmountOf;
_x set [4, _newDamage];
_createNewWound = false;
};
} forEach _openWounds;
if (_createNewWound) then {
TRACE_1("adding new wound",_injury);
_openWounds pushBack _injury;
};
};
};
} forEach _thresholds;
if (_updateDamageEffects) then {
[_unit] call EFUNC(medical_engine,updateDamageEffects);
};
2019-06-22 18:36:27 +00:00
_unit setVariable [VAR_OPEN_WOUNDS, _openWounds, true];
2016-12-08 10:38:43 +00:00
_unit setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true];
[_unit] call EFUNC(medical_status,updateWoundBloodLoss);
2017-06-08 18:50:38 +00:00
_bodyPartVisParams call EFUNC(medical_engine,updateBodyPartVisuals);
[QEGVAR(medical,injured), [_unit, _painLevel]] call CBA_fnc_localEvent;
if (_critialDamage || {_painLevel > PAIN_UNCONSCIOUS}) then {
[_unit] call FUNC(handleIncapacitation);
};
2019-06-22 18:36:27 +00:00
TRACE_4("exit",_unit,_painLevel,GET_PAIN(_unit),GET_OPEN_WOUNDS(_unit));