ACE3/addons/medical_damage/functions/fnc_parseConfigForInjuries.sqf
pterolatypus 73a7dbdc1e
Medical - Rework wound handling (#8278)
- Add stackable wound handler system for easy 3rd party extensibility and overriding of default wound handler.
- Change mapping from wound type -> damage types, to damage type -> wound types. Improves the semantics and makes configuration easier to reason about.
- Allow damage types to influence wound properties (bleed, size, etc.) with configurable variance parameters.
- Allow configuration of wound type variance per damage type. Enabling more logically driven variance for sensible but still varied end results.
- Improve handling of non-selection-specific damage events. The wound handler now receives all incoming damages and may apply damage to multiple selections (previously only ever one) if the damage type is not configured to be selection specific (with new config property `selectionSpecific`).
- Add debug script for testing explosion damage events at varied ranges.
- Add custom fire wound handler.
2022-02-17 20:03:12 +00:00

167 lines
6.1 KiB
Plaintext

#include "script_component.hpp"
/*
* Author: Glowbal, commy2
* Parse the ACE_Medical_Advanced config for all injury types.
*
* Arguments:
* None
*
* ReturnValue:
* None
*
* Example:
* [] call ace_medical_damage_fnc_parseConfigForInjuries
*
* Public: No
*/
private _injuriesConfigRoot = configFile >> "ACE_Medical_Injuries";
// --- parse wounds
GVAR(woundClassNames) = [];
GVAR(woundClassNamesComplex) = []; // index = 10 * classID + category; [will contain nils] e.g. ["aMinor", "aMed", "aLarge", nil, nil..."bMinor"]
GVAR(woundDetails) = createHashMap;
private _woundsConfig = _injuriesConfigRoot >> "wounds";
private _classID = 0;
{
private _entry = _x;
private _className = configName _entry;
private _selections = GET_ARRAY(_entry >> "selections",["All"]);
private _bleeding = GET_NUMBER(_entry >> "bleeding",0);
private _pain = GET_NUMBER(_entry >> "pain",0);
private _causeLimping = GET_NUMBER(_entry >> "causeLimping",0) == 1;
private _causeFracture = GET_NUMBER(_entry >> "causeFracture",0) == 1;
private _details = [_selections, _bleeding, _pain, _causeLimping, _causeFracture];
GVAR(woundDetails) set [_className, _details];
GVAR(woundDetails) set [_classID, _details];
GVAR(woundClassNames) pushBack _className;
{
GVAR(woundClassNamesComplex) set [10 * _classID + _forEachIndex, format ["%1%2", _className, _x]];
} forEach ["Minor", "Medium", "Large"];
_classID = _classID + 1;
} forEach configProperties [_woundsConfig, "isClass _x"];
// --- parse damage types
GVAR(damageTypeDetails) = createHashMap;
// cache for ammunition -> damageType
GVAR(damageTypeCache) = createHashMap;
// minimum lethal damage collection, mapped to damageTypes
private _damageTypesConfig = _injuriesConfigRoot >> "damageTypes";
private _thresholdsDefault = getArray (_damageTypesConfig >> "thresholds");
private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionSpecific");
private _defaultWoundHandlers = [];
if (isClass (_damageTypesConfig >> "woundHandlers")) then {
_defaultWoundHandlers = [_damageTypesConfig >> "woundHandlers"] call FUNC(parseWoundHandlersCfg);
reverse _defaultWoundHandlers;
};
TRACE_1("Found default wound handlers", count _defaultWoundHandlers);
// Collect all available damage types from the config
{
private _entry = _x;
private _className = configName _entry;
if (_className == "woundHandlers") then {continue};
GVAR(damageTypeCache) set [_className, _className];
GVAR(damageTypeCache) set ["#"+_className, _className];
private _damageTypeSubClassConfig = _damageTypesConfig >> _className;
private _thresholds = GET_ARRAY(_damageTypeSubClassConfig >> "thresholds",_thresholdsDefault);
private _selectionSpecific = GET_NUMBER(_damageTypeSubClassConfig >> "selectionSpecific",_selectionSpecificDefault);
private _woundHandlers = [];
if (isClass (_damageTypeSubClassConfig >> "woundHandlers")) then {
_woundHandlers = [_damageTypeSubClassConfig >> "woundHandlers"] call FUNC(parseWoundHandlersCfg);
reverse _woundHandlers;
TRACE_2("Damage type found wound handlers", _className, count _woundHandlers);
} else {
_woundHandlers = _defaultWoundHandlers;
TRACE_1("Damage type has no wound handlers, using default", _className);
};
/*
// extension loading
private _minDamageThresholds = (_thresholds apply {str (_x select 0)}) joinString ":";
private _amountThresholds = (_thresholds apply {str (_x select 1)}) joinString ":";
// load in the damage types into the medical extension
private _extensionArgs = format [
"addDamageType,%1,%2,%3,%4,%5",
_className,
1, //@todo remove 'minLethalDamage' from extension
_minDamageThresholds,
_amountThresholds,
_selectionSpecific
];
TRACE_1("",_extensionArgs);
// private _extensionRes = "ace_medical" callExtension _extensionArgs;
// TRACE_1("",_extensionRes);
*/
// parse config for each wound this damage type can cause
private _damageWoundDetails = [];
{
private _woundType = configName _x;
if (_woundType == "woundHandlers") then {continue};
if (_woundType in GVAR(woundDetails)) then {
private _weighting = GET_ARRAY(_x >> "weighting",ARR_2([[0,1]]));
private _dmgMulti = GET_NUMBER(_x >> "damageMultiplier", 1);
private _bleedMulti = GET_NUMBER(_x >> "bleedingMultiplier", 1);
private _sizeMulti = GET_NUMBER(_x >> "sizeMultiplier", 1);
private _painMulti = GET_NUMBER(_x >> "painMultiplier", 1);
private _fractureMulti = GET_NUMBER(_x >> "fractureMultiplier", 1);
_damageWoundDetails pushBack [_woundType, _weighting, _dmgMulti, _bleedMulti, _sizeMulti, _painMulti, _fractureMulti];
} else {
WARNING_2("Damage type %1 refers to wound %2, but it doesn't exist: skipping.",_className,configName _x);
};
} forEach configProperties [_damageTypeSubClassConfig, "isClass _x"];
GVAR(damageTypeDetails) set [_className, [_thresholds, _selectionSpecific, _woundHandlers, _damageWoundDetails]];
} forEach configProperties [_damageTypesConfig, "isClass _x"];
/*
// extension loading
{
_x params ["_classID", "_selections", "_bleedingRate", "_pain", "_damageExtrema", "_causes", "_displayName"];
_damageExtrema params ["_minDamage", "_maxDamage"];
private _className = GVAR(woundClassNames) select _forEachIndex;
if (_displayName isEqualTo "") then {
_displayName = _className;
};
private _selections = _selections joinString ":";
private _causes = _causes joinString ":";
private _extensionArgs = format [
"addInjuryType,%1,%2,%3,%4,%5,%6,%7,%8,%9",
_classID,
_className,
_selections,
_bleedingRate,
_pain,
_minDamage,
_maxDamage,
_causes,
_displayName
];
TRACE_1("",_extensionArgs);
// private _extensionRes = "ace_medical" callExtension _extensionArgs;
// TRACE_1("",_extensionRes);
} forEach GVAR(woundsData);
// "ace_medical" callExtension "ConfigComplete";
*/