diff --git a/addons/medical/dev/watchVariable.sqf b/addons/medical/dev/watchVariable.sqf index 94ff6b4c29..dbda8636a0 100644 --- a/addons/medical/dev/watchVariable.sqf +++ b/addons/medical/dev/watchVariable.sqf @@ -95,24 +95,33 @@ GVAR(dev_watchVariableRunning) = true; _return pushBack "------- Open Wounds: -------"; private _wounds = GET_OPEN_WOUNDS(_unit); { - _x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"]; - _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; + private _bodyPart = _x; + { + _x params ["_xClassID", "_xAmountOf", "_xBleeding", "_xDamage"]; + _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", _bodyPart, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; + } forEach _y; } forEach _wounds; // Bandaged Wounds: _return pushBack "------- Bandaged Wounds: -------"; private _wounds = GET_BANDAGED_WOUNDS(_unit); { - _x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"]; - _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; + private _bodyPart = _x; + { + _x params ["_xClassID", "_xAmountOf", "_xBleeding", "_xDamage"]; + _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", _bodyPart, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; + } forEach _y; } forEach _wounds; // Stitched Wounds: _return pushBack "------- Stitched Wounds: -------"; private _wounds = GET_STITCHED_WOUNDS(_unit); { - _x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "_xBleeding", "_xDamage"]; - _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", ALL_SELECTIONS select _xBodyPartN, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; + private _bodyPart = _x; + { + _x params ["_xClassID", "_xAmountOf", "_xBleeding", "_xDamage"]; + _return pushBack format ["%1: [%2] [x%3] [Bld: %4] [Dmg: %5]", _bodyPart, _xClassID, _xAmountOf toFixed 1, _xBleeding toFixed 4, _xDamage toFixed 2]; + } forEach _y; } forEach _wounds; // IVs: diff --git a/addons/medical/functions/fnc_deserializeState.sqf b/addons/medical/functions/fnc_deserializeState.sqf index 938c18e8fa..2002abf59e 100644 --- a/addons/medical/functions/fnc_deserializeState.sqf +++ b/addons/medical/functions/fnc_deserializeState.sqf @@ -35,6 +35,22 @@ if !(_unit getVariable [QGVAR(initialized), false]) exitWith { private _state = [_json] call CBA_fnc_parseJSON; +// Migration from old array wounding storage serialized in old versions (<= 3.16.0) +{ + if ((_state getVariable [_x, createHashMap]) isEqualType []) then { + private _migratedWounds = createHashMap; + + { + _x params ["_class", "_bodyPartIndex", "_amountOf", "_bleeding", "_damage"]; + + private _partWounds = _migratedWounds getOrDefault [ALL_BODY_PARTS select _bodyPartIndex, [], true]; + _partWounds pushBack [_class, _amountOf, _bleeding, _damage]; + } forEach (_state getVariable _x); + + _state setVariable [_x, _migratedWounds]; + }; +} forEach [VAR_OPEN_WOUNDS, VAR_BANDAGED_WOUNDS, VAR_STITCHED_WOUNDS]; + // Set medical variables { _x params ["_var", "_default"]; @@ -57,9 +73,9 @@ private _state = [_json] call CBA_fnc_parseJSON; [VAR_PAIN, 0], [VAR_IN_PAIN, false], [VAR_PAIN_SUPP, 0], - [VAR_OPEN_WOUNDS, []], - [VAR_BANDAGED_WOUNDS, []], - [VAR_STITCHED_WOUNDS, []], + [VAR_OPEN_WOUNDS, createHashMap], + [VAR_BANDAGED_WOUNDS, createHashMap], + [VAR_STITCHED_WOUNDS, createHashMap], [VAR_FRACTURES, DEFAULT_FRACTURE_VALUES], // State transition should handle this // [VAR_UNCON, false], diff --git a/addons/medical/functions/fnc_serializeState.sqf b/addons/medical/functions/fnc_serializeState.sqf index 31f1dccad4..9eb4bde5bc 100644 --- a/addons/medical/functions/fnc_serializeState.sqf +++ b/addons/medical/functions/fnc_serializeState.sqf @@ -33,9 +33,9 @@ private _state = [] call CBA_fnc_createNamespace; [VAR_PAIN, 0], [VAR_IN_PAIN, false], [VAR_PAIN_SUPP, 0], - [VAR_OPEN_WOUNDS, []], - [VAR_BANDAGED_WOUNDS, []], - [VAR_STITCHED_WOUNDS, []], + [VAR_OPEN_WOUNDS, createHashMap], + [VAR_BANDAGED_WOUNDS, createHashMap], + [VAR_STITCHED_WOUNDS, createHashMap], [VAR_FRACTURES, DEFAULT_FRACTURE_VALUES], // State transition should handle this // [VAR_UNCON, false], diff --git a/addons/medical_ai/functions/fnc_healingLogic.sqf b/addons/medical_ai/functions/fnc_healingLogic.sqf index a07b08db8b..b05c07f176 100644 --- a/addons/medical_ai/functions/fnc_healingLogic.sqf +++ b/addons/medical_ai/functions/fnc_healingLogic.sqf @@ -44,12 +44,14 @@ private _treatmentTime = 6; switch (true) do { case (GET_WOUND_BLEEDING(_target) > 0): { // Select first bleeding wound and bandage it - private _openWounds = GET_OPEN_WOUNDS(_target); private _selection = "?"; { - _x params ["", "_index", "_amount", "_percentage"]; - if ((_amount * _percentage) > 0) exitWith { _selection = ALL_BODY_PARTS select _index; }; - } forEach _openWounds; + private _foundBleeding = _y findIf { + _x params ["", "_amount", "_percentage"]; + (_amount * _percentage) > 0 + }; + if (_foundBleeding != -1) exitWith { _selection = _x; }; + } forEach GET_OPEN_WOUNDS(_target); _treatmentEvent = QEGVAR(medical_treatment,bandageLocal); _treatmentTime = 5; _treatmentArgs = [_target, _selection, "FieldDressing"]; diff --git a/addons/medical_damage/functions/fnc_handleIncapacitation.sqf b/addons/medical_damage/functions/fnc_handleIncapacitation.sqf index 4e87e749df..80014b2959 100644 --- a/addons/medical_damage/functions/fnc_handleIncapacitation.sqf +++ b/addons/medical_damage/functions/fnc_handleIncapacitation.sqf @@ -24,11 +24,11 @@ _bodyPartDamage params ["_headDamage", "_bodyDamage", "_leftArmDamage", "_rightA // Exclude non penetrating body damage { - _x params ["", "_bodyPartN", "_amountOf", "", "_damage"]; - if (_bodyPartN == 1 && {_damage < PENETRATION_THRESHOLD}) then { + _x params ["", "_amountOf", "", "_damage"]; + if (_damage < PENETRATION_THRESHOLD) then { _bodyDamage = _bodyDamage - (_amountOf * _damage); }; -} forEach GET_OPEN_WOUNDS(_unit); +} forEach (GET_OPEN_WOUNDS(_unit) getOrDefault ["body", []]); private _damageThreshold = GET_DAMAGE_THRESHOLD(_unit); diff --git a/addons/medical_damage/functions/fnc_woundsHandlerBase.sqf b/addons/medical_damage/functions/fnc_woundsHandlerBase.sqf index e0b0a2a32b..1d60983492 100644 --- a/addons/medical_damage/functions/fnc_woundsHandlerBase.sqf +++ b/addons/medical_damage/functions/fnc_woundsHandlerBase.sqf @@ -41,12 +41,13 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra // process wounds separately for each body part hit { // forEach _allDamages _x params ["_damage", "_bodyPart"]; + _bodyPart = toLower _bodyPart; // silently ignore structural damage if (_bodyPart == "#structural") then {continue}; // Convert the selectionName to a number and ensure it is a valid selection. - private _bodyPartNToAdd = ALL_BODY_PARTS find toLower _bodyPart; + private _bodyPartNToAdd = ALL_BODY_PARTS find _bodyPart; if (_bodyPartNToAdd < 0) then { ERROR_1("invalid body part %1",_bodyPart); continue @@ -84,7 +85,7 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra }; GVAR(woundDetails) get _woundTypeToAdd params ["","_injuryBleedingRate","_injuryPain","_causeLimping","_causeFracture"]; private _woundClassIDToAdd = GVAR(woundClassNames) find _woundTypeToAdd; - + // Add a bit of random variance to wounds private _woundDamage = _dmgPerWound * _dmgMultiplier * random [0.9, 1, 1.1]; @@ -99,7 +100,7 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra // Config specifies bleeding and pain for worst possible wound // Worse wound correlates to higher damage, damage is not capped at 1 private _woundSize = linearConversion [0.1, _worstDamage, _woundDamage * _sizeMultiplier, LARGE_WOUND_THRESHOLD^3, 1, true]; - + private _pain = _woundSize * _painMultiplier * _injuryPain; _painLevel = _painLevel + _pain; @@ -112,10 +113,10 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra private _classComplex = 10 * _woundClassIDToAdd + _category; - // Create a new injury. Format [0:classComplex, 1:bodypart, 2:amountOf, 3:bleedingRate, 4:woundDamage] - private _injury = [_classComplex, _bodyPartNToAdd, 1, _bleeding, _woundDamage]; + // Create a new injury. Format [0:classComplex, 1:amountOf, 2:bleedingRate, 3:woundDamage] + private _injury = [_classComplex, 1, _bleeding, _woundDamage]; - if (_bodyPartNToAdd == 0 || {_bodyPartNToAdd == 1 && {_woundDamage > PENETRATION_THRESHOLD}}) then { + if (_bodyPart isEqualTo "head" || {_bodyPart isEqualTo "body" && {_woundDamage > PENETRATION_THRESHOLD}}) then { _criticalDamage = true; }; if ([_unit, _bodyPartNToAdd, _bodyPartDamage, _woundDamage] call FUNC(determineIfFatal)) then { @@ -158,28 +159,28 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra // if possible merge into existing wounds private _createNewWound = true; + private _existingWounds = _openWounds getOrDefault [_bodyPart, [], true]; { - _x params ["_classID", "_bodyPartN", "_oldAmountOf", "_oldBleeding", "_oldDamage"]; + _x params ["_classID", "_oldAmountOf", "_oldBleeding", "_oldDamage"]; if ( (_classComplex == _classID) && - {_bodyPartNToAdd == _bodyPartN} && - {(_bodyPartNToAdd != 1) || {(_woundDamage < PENETRATION_THRESHOLD) isEqualTo (_oldDamage < PENETRATION_THRESHOLD)}} && // penetrating body damage is handled differently + {(_bodyPart isNotEqualTo "body") || {(_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]; + _x set [1, _newAmountOf]; private _newBleeding = (_oldAmountOf * _oldBleeding + _bleeding) / _newAmountOf; - _x set [3, _newBleeding]; + _x set [2, _newBleeding]; private _newDamage = (_oldAmountOf * _oldDamage + _woundDamage) / _newAmountOf; - _x set [4, _newDamage]; + _x set [3, _newDamage]; _createNewWound = false; }; - } forEach _openWounds; + } forEach _existingWounds; if (_createNewWound) then { TRACE_1("adding new wound",_injury); - _openWounds pushBack _injury; + _existingWounds pushBack _injury; }; _createdWounds = true; }; diff --git a/addons/medical_engine/functions/fnc_updateDamageEffects.sqf b/addons/medical_engine/functions/fnc_updateDamageEffects.sqf index 10d62f2141..757a2945b2 100644 --- a/addons/medical_engine/functions/fnc_updateDamageEffects.sqf +++ b/addons/medical_engine/functions/fnc_updateDamageEffects.sqf @@ -48,18 +48,31 @@ if (EGVAR(medical,fractures) > 0) then { }; if (!_isLimping && {EGVAR(medical,limping) > 0}) then { - private _woundsToCheck = GET_OPEN_WOUNDS(_unit); + private _openWounds = GET_OPEN_WOUNDS(_unit); + + // Want a copy of combined arrays to prevent wound mixing + private _legWounds = (_openWounds getOrDefault ["leftleg", []]) + + (_openWounds getOrDefault ["rightleg", []]); + if (EGVAR(medical,limping) == 2) then { - _woundsToCheck = _woundsToCheck + GET_BANDAGED_WOUNDS(_unit); // do not append + private _bandagedWounds = GET_BANDAGED_WOUNDS(_unit); + _legWounds = _legWounds + + (_bandagedWounds getOrDefault ["leftleg", []]) + + (_bandagedWounds getOrDefault ["rightleg", []]); }; + { - _x params ["_xClassID", "_xBodyPartN", "_xAmountOf", "", "_xDamage"]; - if ((_xBodyPartN > 3) && {_xAmountOf > 0} && {_xDamage > LIMPING_DAMAGE_THRESHOLD} && { - (EGVAR(medical_damage,woundDetails) get (_xClassID / 10)) select 3}) exitWith { // select _causeLimping from woundDetails + _x params ["_xClassID", "_xAmountOf", "", "_xDamage"]; + if ( + (_xAmountOf > 0) + && {_xDamage > LIMPING_DAMAGE_THRESHOLD} + // select _causeLimping from woundDetails + && {(EGVAR(medical_damage,woundDetails) get (_xClassID / 10)) select 3} + ) exitWith { TRACE_1("limping because of wound",_x); _isLimping = true; }; - } forEach _woundsToCheck; + } forEach _legWounds; }; _unit setVariable [QEGVAR(medical,isLimping), _isLimping, true]; diff --git a/addons/medical_engine/script_macros_medical.hpp b/addons/medical_engine/script_macros_medical.hpp index 618810414a..962c8d6219 100644 --- a/addons/medical_engine/script_macros_medical.hpp +++ b/addons/medical_engine/script_macros_medical.hpp @@ -99,8 +99,8 @@ #define VISUAL_BODY_DAMAGE_THRESHOLD 0.35 // Empty wound data, used for some default return values -// [classID, bodypartIndex, amountOf, bloodloss, damage] -#define EMPTY_WOUND [-1, -1, 0, 0, 0] +// [classID, amountOf, bloodloss, damage] +#define EMPTY_WOUND [-1, 0, 0, 0] // Base time to bandage each wound category #define BANDAGE_TIME_S 4 @@ -173,9 +173,9 @@ #define IS_BLEEDING(unit) (GET_WOUND_BLEEDING(unit) > 0) #define IS_IN_PAIN(unit) (unit getVariable [VAR_IN_PAIN, false]) #define IS_UNCONSCIOUS(unit) (unit getVariable [VAR_UNCON, false]) -#define GET_OPEN_WOUNDS(unit) (unit getVariable [VAR_OPEN_WOUNDS, []]) -#define GET_BANDAGED_WOUNDS(unit) (unit getVariable [VAR_BANDAGED_WOUNDS, []]) -#define GET_STITCHED_WOUNDS(unit) (unit getVariable [VAR_STITCHED_WOUNDS, []]) +#define GET_OPEN_WOUNDS(unit) (unit getVariable [VAR_OPEN_WOUNDS, createHashMap]) +#define GET_BANDAGED_WOUNDS(unit) (unit getVariable [VAR_BANDAGED_WOUNDS, createHashMap]) +#define GET_STITCHED_WOUNDS(unit) (unit getVariable [VAR_STITCHED_WOUNDS, createHashMap]) #define GET_DAMAGE_THRESHOLD(unit) (unit getVariable [QEGVAR(medical,damageThreshold), [EGVAR(medical,AIDamageThreshold),EGVAR(medical,playerDamageThreshold)] select (isPlayer unit)]) // The following function calls are defined here just for consistency diff --git a/addons/medical_gui/InteractionBodyParts.hpp b/addons/medical_gui/InteractionBodyParts.hpp index b06e24c2e7..928ec330ed 100644 --- a/addons/medical_gui/InteractionBodyParts.hpp +++ b/addons/medical_gui/InteractionBodyParts.hpp @@ -5,7 +5,7 @@ class ACE_Head { exceptions[] = {"isNotInside", "isNotSitting"}; ACTION_CONDITION statement = QUOTE([ARR_2(_target,0)] call FUNC(displayPatientInformation)); - modifierFunction = QUOTE([ARR_3(_target,0,_this select 3)] call FUNC(modifyAction)); + modifierFunction = QUOTE([ARR_3(_target,""head"",_this select 3)] call FUNC(modifyAction)); runOnHover = 1; }; class ACE_Torso { @@ -15,7 +15,7 @@ class ACE_Torso { exceptions[] = {"isNotInside", "isNotSitting"}; ACTION_CONDITION statement = QUOTE([ARR_2(_target,1)] call FUNC(displayPatientInformation)); - modifierFunction = QUOTE([ARR_3(_target,1,_this select 3)] call FUNC(modifyAction)); + modifierFunction = QUOTE([ARR_3(_target,""body"",_this select 3)] call FUNC(modifyAction)); runOnHover = 1; class TriageCard { displayName = CSTRING(Actions_TriageCard); @@ -32,7 +32,7 @@ class ACE_ArmLeft { exceptions[] = {"isNotInside", "isNotSitting"}; ACTION_CONDITION statement = QUOTE([ARR_2(_target,2)] call FUNC(displayPatientInformation)); - modifierFunction = QUOTE([ARR_3(_target,2,_this select 3)] call FUNC(modifyAction)); + modifierFunction = QUOTE([ARR_3(_target,""leftarm"",_this select 3)] call FUNC(modifyAction)); runOnHover = 1; }; class ACE_ArmRight { @@ -42,7 +42,7 @@ class ACE_ArmRight { exceptions[] = {"isNotInside", "isNotSitting"}; ACTION_CONDITION statement = QUOTE([ARR_2(_target,3)] call FUNC(displayPatientInformation)); - modifierFunction = QUOTE([ARR_3(_target,3,_this select 3)] call FUNC(modifyAction)); + modifierFunction = QUOTE([ARR_3(_target,""rightarm"",_this select 3)] call FUNC(modifyAction)); runOnHover = 1; }; class ACE_LegLeft { @@ -52,7 +52,7 @@ class ACE_LegLeft { exceptions[] = {"isNotInside", "isNotSitting"}; ACTION_CONDITION statement = QUOTE([ARR_2(_target,4)] call FUNC(displayPatientInformation)); - modifierFunction = QUOTE([ARR_3(_target,4,_this select 3)] call FUNC(modifyAction)); + modifierFunction = QUOTE([ARR_3(_target,""leftleg"",_this select 3)] call FUNC(modifyAction)); runOnHover = 1; }; class ACE_LegRight { @@ -62,6 +62,6 @@ class ACE_LegRight { exceptions[] = {"isNotInside", "isNotSitting"}; ACTION_CONDITION statement = QUOTE([ARR_2(_target,5)] call FUNC(displayPatientInformation)); - modifierFunction = QUOTE([ARR_3(_target,5,_this select 3)] call FUNC(modifyAction)); + modifierFunction = QUOTE([ARR_3(_target,""rightleg"",_this select 3)] call FUNC(modifyAction)); runOnHover = 1; }; diff --git a/addons/medical_gui/functions/fnc_modifyAction.sqf b/addons/medical_gui/functions/fnc_modifyAction.sqf index 422c73a475..f3f11b04ba 100644 --- a/addons/medical_gui/functions/fnc_modifyAction.sqf +++ b/addons/medical_gui/functions/fnc_modifyAction.sqf @@ -5,32 +5,30 @@ * * Arguments: * 0: Unit - * 1: Body part index + * 1: Body part * 2: Action data * * Return Value: * None * * Example: - * [_target, 0, _actionData] call ace_medical_gui_fnc_modifyAction + * [_target, "head", _actionData] call ace_medical_gui_fnc_modifyAction * * Public: No */ #define COLOR_SCALE ["#ffffff", "#fff1a1", "#ffe075", "#ffcb55", "#ffb73c", "#ffa127", "#ff8815", "#ff6d05", "#ff4b00", "#ff0000"] -params ["_target", "_partIndex", "_actionData"]; +params ["_target", "_bodyPart", "_actionData"]; +private _partIndex = ALL_BODY_PARTS find _bodyPart; private _bloodLossOnBodyPart = 0; // Add all bleeding from wounds on selection { - _x params ["", "_bodyPartN", "_amountOf", "_bleeding"]; - - if (_bodyPartN == _partIndex) then { - _bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _bleeding); - }; -} forEach GET_OPEN_WOUNDS(_target); + _x params ["", "_amountOf", "_bleeding"]; + _bloodLossOnBodyPart = _bloodLossOnBodyPart + (_amountOf * _bleeding); +} forEach (GET_OPEN_WOUNDS(_target) getOrDefault [_bodyPart, []]); private _frBL = 0 max (_bloodLossOnBodyPart / BLOOD_LOSS_RED_THRESHOLD) min 1; private _colorInt = ceil (_frBL * (BLOOD_LOSS_TOTAL_COLORS - 1)); // ceil because any bleeding more than zero shouldn't be white diff --git a/addons/medical_gui/functions/fnc_updateBodyImage.sqf b/addons/medical_gui/functions/fnc_updateBodyImage.sqf index 3a1f756f79..51a15945d3 100644 --- a/addons/medical_gui/functions/fnc_updateBodyImage.sqf +++ b/addons/medical_gui/functions/fnc_updateBodyImage.sqf @@ -25,8 +25,11 @@ private _bodyPartDamage = _target getVariable [QEGVAR(medical,bodyPartDamage), [ private _bodyPartBloodLoss = [0, 0, 0, 0, 0, 0]; { - _x params ["", "_bodyPartN", "_amountOf", "_bleeding"]; - _bodyPartBloodLoss set [_bodyPartN, (_bodyPartBloodLoss select _bodyPartN) + (_bleeding * _amountOf)]; + private _partIndex = ALL_BODY_PARTS find _x; + { + _x params ["", "_amountOf", "_bleeding"]; + _bodyPartBloodLoss set [_partIndex, (_bodyPartBloodLoss select _partIndex) + (_bleeding * _amountOf)]; + } forEach _y; } forEach GET_OPEN_WOUNDS(_target); { diff --git a/addons/medical_gui/functions/fnc_updateInjuryList.sqf b/addons/medical_gui/functions/fnc_updateInjuryList.sqf index 2d06e4b1d8..b0bf76fe45 100644 --- a/addons/medical_gui/functions/fnc_updateInjuryList.sqf +++ b/addons/medical_gui/functions/fnc_updateInjuryList.sqf @@ -110,9 +110,9 @@ private _fnc_processWounds = { params ["_wounds", "_format", "_color"]; { - _x params ["_woundClassID", "_bodyPartN", "_amountOf"]; + _x params ["_woundClassID", "_amountOf"]; - if (_selectionN == _bodyPartN && {_amountOf > 0}) then { + if (_amountOf > 0) then { private _classIndex = _woundClassID / 10; private _category = _woundClassID % 10; @@ -128,7 +128,7 @@ private _fnc_processWounds = { _woundEntries pushBack [format [_format, _woundDescription], _color]; }; - } forEach _wounds; + } forEach (_wounds getOrDefault [ALL_BODY_PARTS select _selectionN, []]); }; [GET_OPEN_WOUNDS(_target), "%1", [1, 1, 1, 1]] call _fnc_processWounds; diff --git a/addons/medical_status/functions/fnc_initUnit.sqf b/addons/medical_status/functions/fnc_initUnit.sqf index 56ab8498cd..bb0f748d3b 100644 --- a/addons/medical_status/functions/fnc_initUnit.sqf +++ b/addons/medical_status/functions/fnc_initUnit.sqf @@ -46,9 +46,9 @@ if (_isRespawn) then { _unit setVariable [VAR_PAIN_SUPP, 0, true]; // - Wounds ------------------------------------------------------------------- - _unit setVariable [VAR_OPEN_WOUNDS, [], true]; - _unit setVariable [VAR_BANDAGED_WOUNDS, [], true]; - _unit setVariable [VAR_STITCHED_WOUNDS, [], true]; + _unit setVariable [VAR_OPEN_WOUNDS, createHashMap, true]; + _unit setVariable [VAR_BANDAGED_WOUNDS, createHashMap, true]; + _unit setVariable [VAR_STITCHED_WOUNDS, createHashMap, true]; _unit setVariable [QEGVAR(medical,isLimping), false, true]; _unit setVariable [VAR_FRACTURES, DEFAULT_FRACTURE_VALUES, true]; diff --git a/addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf b/addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf index fe38aabadc..cf83b0719c 100644 --- a/addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf +++ b/addons/medical_status/functions/fnc_updateWoundBloodLoss.sqf @@ -21,9 +21,12 @@ params ["_unit"]; private _tourniquets = GET_TOURNIQUETS(_unit); private _bodyPartBleeding = [0,0,0,0,0,0]; { - _x params ["", "_bodyPart", "_amountOf", "_bleeeding"]; - if (_tourniquets select _bodyPart == 0) then { - _bodyPartBleeding set [_bodyPart, (_bodyPartBleeding select _bodyPart) + (_amountOf * _bleeeding)]; + private _partIndex = ALL_BODY_PARTS find _x; + if (_tourniquets select _partIndex == 0) then { + { + _x params ["", "_amountOf", "_bleeeding"]; + _bodyPartBleeding set [_partIndex, (_bodyPartBleeding select _partIndex) + (_amountOf * _bleeeding)]; + } forEach _y; }; } forEach GET_OPEN_WOUNDS(_unit); diff --git a/addons/medical_treatment/functions/fnc_bandageLocal.sqf b/addons/medical_treatment/functions/fnc_bandageLocal.sqf index d02ab8f749..74d2641766 100644 --- a/addons/medical_treatment/functions/fnc_bandageLocal.sqf +++ b/addons/medical_treatment/functions/fnc_bandageLocal.sqf @@ -19,27 +19,26 @@ params ["_patient", "_bodyPart", "_bandage"]; TRACE_3("bandageLocal",_patient,_bodyPart,_bandage); - -private _partIndex = ALL_BODY_PARTS find toLower _bodyPart; -if (_partIndex < 0) exitWith {}; +_bodyPart = toLower _bodyPart; private _openWounds = GET_OPEN_WOUNDS(_patient); -if (_openWounds isEqualTo []) exitWith {}; +private _woundsOnPart = _openWounds getOrDefault [_bodyPart, []]; +if (_woundsOnPart isEqualTo []) exitWith {}; // Figure out which injury for this bodypart is the best choice to bandage // TODO also use up the remainder on left over injuries -private _targetWound = [_patient, _bandage, _partIndex] call FUNC(findMostEffectiveWound); +private _targetWound = [_patient, _bandage, _bodyPart] call FUNC(findMostEffectiveWound); _targetWound params ["_wound", "_woundIndex", "_effectiveness"]; // Everything is patched up on this body part already if (_effectiveness == -1) exitWith {}; // Find the impact this bandage has and reduce the amount this injury is present -private _amountOf = _wound select 2; +private _amountOf = _wound select 1; private _impact = _effectiveness min _amountOf; _amountOf = _amountOf - _impact; -_wound set [2, _amountOf]; -_openWounds set [_woundIndex, _wound]; +_wound set [1, _amountOf]; +_woundsOnPart set [_woundIndex, _wound]; _patient setVariable [VAR_OPEN_WOUNDS, _openWounds, true]; @@ -47,20 +46,28 @@ _patient setVariable [VAR_OPEN_WOUNDS, _openWounds, true]; // Handle the reopening of bandaged wounds if (_impact > 0 && {GVAR(advancedBandages) == 2}) then { - [_patient, _impact, _partIndex, _woundIndex, _wound, _bandage] call FUNC(handleBandageOpening); + [_patient, _impact, _bodyPart, _woundIndex, _wound, _bandage] call FUNC(handleBandageOpening); }; // Check if we fixed limping from this treatment -if (EGVAR(medical,limping) == 1 && {_partIndex > 3} && {_amountOf <= 0} && {_patient getVariable [QEGVAR(medical,isLimping), false]}) then { +if ( + EGVAR(medical,limping) == 1 + && {_bodyPart isEqualTo "leftleg" || _bodyPart isEqualTo "rightleg"} + && {_amountOf <= 0} + && {_patient getVariable [QEGVAR(medical,isLimping), false]} +) then { [_patient] call EFUNC(medical_engine,updateDamageEffects); }; if (GVAR(clearTrauma) == 2) then { - TRACE_2("clearTrauma - clearing trauma after bandage",_partIndex,_openWounds); - private _treatedDamageOf = (_wound select 4) * _impact; + TRACE_2("clearTrauma - clearing trauma after bandage",_bodyPart,_openWounds); + private _partIndex = ALL_BODY_PARTS find _bodyPart; + private _treatedDamageOf = (_wound select 3) * _impact; private _bodyPartDamage = _patient getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; private _newDam = (_bodyPartDamage select _partIndex) - _treatedDamageOf; - if (_newDam < 0.05) then { // Prevent obscenely small damage from lack of floating precision + + // Prevent obscenely small damage from lack of floating precision + if (_newDam < 0.05) then { _bodyPartDamage set [_partIndex, 0]; } else { _bodyPartDamage set [_partIndex, _newDam]; @@ -68,16 +75,17 @@ if (GVAR(clearTrauma) == 2) then { _patient setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true]; TRACE_2("clearTrauma - healed damage",_partIndex,_treatedDamageOf); - switch (_partIndex) do { - case 0: { [_patient, true, false, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; - case 1: { [_patient, false, true, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; - case 2; - case 3: { [_patient, false, false, true, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + switch (_bodyPart) do { + case "head": { [_patient, true, false, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + case "body": { [_patient, false, true, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + case "leftarm"; + case "rightarm": { [_patient, false, false, true, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; default { [_patient, false, false, false, true] call EFUNC(medical_engine,updateBodyPartVisuals); }; }; }; -if (_amountOf <= 0) then { // Reset treatment condition cache for nearby players if we stopped all bleeding +// Reset treatment condition cache for nearby players if we stopped all bleeding +if (_amountOf <= 0) then { private _nearPlayers = (_patient nearEntities ["CAManBase", 6]) select {_x call EFUNC(common,isPlayer)}; TRACE_1("clearConditionCaches: bandage",_nearPlayers); [QEGVAR(interact_menu,clearConditionCaches), [], _nearPlayers] call CBA_fnc_targetEvent; diff --git a/addons/medical_treatment/functions/fnc_canBandage.sqf b/addons/medical_treatment/functions/fnc_canBandage.sqf index c564272583..2308fa937c 100644 --- a/addons/medical_treatment/functions/fnc_canBandage.sqf +++ b/addons/medical_treatment/functions/fnc_canBandage.sqf @@ -1,6 +1,6 @@ #include "script_component.hpp" /* - * Author: SilentSpike + * Author: kymckay * Prevents bandage actions from showing if selected body part isn't bleeding. * Toggles between showing all or only basic bandage action for advanced setting. * @@ -20,6 +20,7 @@ */ params ["_medic", "_patient", "_bodyPart", "_bandage"]; +_bodyPart = toLower _bodyPart; // If patient is swimming, don't allow bandage actions. if (_patient call EFUNC(common,isSwimming)) exitWith {false}; @@ -27,16 +28,15 @@ if (_patient call EFUNC(common,isSwimming)) exitWith {false}; // Bandage type and bandage setting XNOR to show only active actions if ((_bandage == "BasicBandage") isEqualTo (GVAR(advancedBandages) != 0)) exitWith {false}; -private _index = ALL_BODY_PARTS find toLower _bodyPart; private _canBandage = false; { - _x params ["", "_bodyPartN", "_amountOf", "_bleeding"]; + _x params ["", "_amountOf", "_bleeding"]; // If any single wound on the bodypart is bleeding bandaging can go ahead - if (_bodyPartN == _index && {_amountOf * _bleeding > 0}) exitWith { + if (_amountOf * _bleeding > 0) exitWith { _canBandage = true; }; -} forEach GET_OPEN_WOUNDS(_patient); +} forEach ((GET_OPEN_WOUNDS(_patient)) getOrDefault [_bodyPart, []]); _canBandage diff --git a/addons/medical_treatment/functions/fnc_canStitch.sqf b/addons/medical_treatment/functions/fnc_canStitch.sqf index 995a018e04..08dd3dd70d 100644 --- a/addons/medical_treatment/functions/fnc_canStitch.sqf +++ b/addons/medical_treatment/functions/fnc_canStitch.sqf @@ -20,4 +20,4 @@ params ["_medic", "_patient"]; if ((GVAR(consumeSurgicalKit) == 2) && {!([_medic, _patient, ["ACE_suture"]] call FUNC(hasItem))}) exitWith {false}; -(_patient call FUNC(getStitchableWounds) isNotEqualTo []) +count (_patient call FUNC(getStitchableWounds)) > 0 diff --git a/addons/medical_treatment/functions/fnc_createLitter.sqf b/addons/medical_treatment/functions/fnc_createLitter.sqf index 93b7e7397e..19e457c65f 100644 --- a/addons/medical_treatment/functions/fnc_createLitter.sqf +++ b/addons/medical_treatment/functions/fnc_createLitter.sqf @@ -28,10 +28,9 @@ if (vehicle _medic != _medic || {vehicle _patient != _patient}) exitWith {}; // Determine if treated body part is bleeding private _index = ALL_BODY_PARTS find toLower _bodyPart; -private _isBleeding = GET_OPEN_WOUNDS(_patient) findIf { - _x params ["", "_bodyPartN", "_amountOf", "_bleeding"]; - - _bodyPartN == _index && {_amountOf * _bleeding > 0} +private _isBleeding = (GET_OPEN_WOUNDS(_patient) get _bodyPart) findIf { + _x params ["", "_amountOf", "_bleeding"]; + _amountOf * _bleeding > 0 } != -1; // Get litter config for the treatment diff --git a/addons/medical_treatment/functions/fnc_findMostEffectiveWound.sqf b/addons/medical_treatment/functions/fnc_findMostEffectiveWound.sqf index a7a133c2e4..7f7e4a1848 100644 --- a/addons/medical_treatment/functions/fnc_findMostEffectiveWound.sqf +++ b/addons/medical_treatment/functions/fnc_findMostEffectiveWound.sqf @@ -1,12 +1,12 @@ #include "script_component.hpp" /* - * Author: SilentSpike + * Author: kymckay * Finds the wound most effective to bandage on the given bodypart of the patient for the given bandage type. * * Arguments: * 0: Patient * 1: Treatment classname - * 2: Body part index + * 2: Body part * * Return Value: * [Wound, Index, Effectiveness] @@ -14,7 +14,7 @@ * Public: No */ -params ["_patient", "_bandage", "_partIndex"]; +params ["_patient", "_bandage", "_bodyPart"]; // Get the default effectiveness for the used bandage private _config = configFile >> QUOTE(ADDON) >> "Bandaging"; @@ -29,7 +29,7 @@ if (isClass (_config >> _bandage)) then { }; // Iterate over open wounds to find the most effective target -private _openWounds = GET_OPEN_WOUNDS(_patient); +private _openWounds = GET_OPEN_WOUNDS(_patient) getOrDefault [_bodyPart, []]; if (_openWounds isEqualTo []) exitWith { [EMPTY_WOUND, -1, -1] }; private _wound = EMPTY_WOUND; @@ -37,36 +37,33 @@ private _woundIndex = -1; private _effectivenessFound = -1; { - _x params ["_classID", "_partIndexN", "_amountOf", "_bleeding", "_damage"]; + _x params ["_classID", "_amountOf", "_bleeding", "_damage"]; - // Ignore wounds on other bodyparts - if (_partIndexN == _partIndex) then { - private _woundEffectiveness = _effectiveness; + private _woundEffectiveness = _effectiveness; - // Select the classname from the wound classname storage - private _className = EGVAR(medical_damage,woundClassNamesComplex) select _classID; + // Select the classname from the wound classname storage + private _className = EGVAR(medical_damage,woundClassNamesComplex) select _classID; - // Get the effectiveness of the bandage on this wound type - if (isClass (_config >> _className)) then { - private _woundTreatmentConfig = _config >> _className; + // Get the effectiveness of the bandage on this wound type + if (isClass (_config >> _className)) then { + private _woundTreatmentConfig = _config >> _className; - if (isNumber (_woundTreatmentConfig >> "effectiveness")) then { - _woundEffectiveness = getNumber (_woundTreatmentConfig >> "effectiveness"); - }; - } else { - // Basic medical bandage just has a base level config (same effectivenes for all wound types) - if (_bandage != "BasicBandage") then { - WARNING_2("No config for wound type [%1] config base [%2]",_className,_config); - }; + if (isNumber (_woundTreatmentConfig >> "effectiveness")) then { + _woundEffectiveness = getNumber (_woundTreatmentConfig >> "effectiveness"); }; - - // Track most effective found so far - if (_woundEffectiveness * _amountOf * _bleeding > _effectivenessFound * (_wound select 2) * (_wound select 3)) then { - _effectivenessFound = _woundEffectiveness; - _woundIndex = _forEachIndex; - _wound = _x; + } else { + // Basic medical bandage just has a base level config (same effectivenes for all wound types) + if (_bandage != "BasicBandage") then { + WARNING_2("No config for wound type [%1] config base [%2]",_className,_config); }; }; + + // Track most effective found so far + if (_woundEffectiveness * _amountOf * _bleeding > _effectivenessFound * (_wound select 1) * (_wound select 2)) then { + _effectivenessFound = _woundEffectiveness; + _woundIndex = _forEachIndex; + _wound = _x; + }; } forEach _openWounds; [_wound, _woundIndex, _effectivenessFound] diff --git a/addons/medical_treatment/functions/fnc_fullHealLocal.sqf b/addons/medical_treatment/functions/fnc_fullHealLocal.sqf index 3484811a32..7a0516ed94 100644 --- a/addons/medical_treatment/functions/fnc_fullHealLocal.sqf +++ b/addons/medical_treatment/functions/fnc_fullHealLocal.sqf @@ -50,9 +50,9 @@ _patient setVariable [VAR_TOURNIQUET, DEFAULT_TOURNIQUET_VALUES, true]; _patient setVariable [QGVAR(occludedMedications), nil, true]; // Wounds and Injuries -_patient setVariable [VAR_OPEN_WOUNDS, [], true]; -_patient setVariable [VAR_BANDAGED_WOUNDS, [], true]; -_patient setVariable [VAR_STITCHED_WOUNDS, [], true]; +_patient setVariable [VAR_OPEN_WOUNDS, createHashMap, true]; +_patient setVariable [VAR_BANDAGED_WOUNDS, createHashMap, true]; +_patient setVariable [VAR_STITCHED_WOUNDS, createHashMap, true]; _patient setVariable [QEGVAR(medical,isLimping), false, true]; _patient setVariable [VAR_FRACTURES, DEFAULT_FRACTURE_VALUES, true]; diff --git a/addons/medical_treatment/functions/fnc_getBandageTime.sqf b/addons/medical_treatment/functions/fnc_getBandageTime.sqf index 8a6248e3b5..44ad2a9744 100644 --- a/addons/medical_treatment/functions/fnc_getBandageTime.sqf +++ b/addons/medical_treatment/functions/fnc_getBandageTime.sqf @@ -1,6 +1,6 @@ #include "script_component.hpp" /* - * Author: SilentSpike + * Author: kymckay * Calculates the time to bandage a wound based on it's size, the patient and the medic. * * Arguments: @@ -18,19 +18,19 @@ * Public: No */ -params ["_medic", "_patient", "_bodypart", "_bandage"]; +params ["_medic", "_patient", "_bodyPart", "_bandage"]; private _partIndex = ALL_BODY_PARTS find toLower _bodyPart; if (_partIndex < 0) exitWith { ERROR_1("invalid partIndex - %1",_this); 0 }; -private _targetWound = [_patient, _bandage, _partIndex] call FUNC(findMostEffectiveWound); +private _targetWound = [_patient, _bandage, _bodyPart] call FUNC(findMostEffectiveWound); _targetWound params ["_wound", "_woundIndex", "_effectiveness"]; TRACE_3("findMostEffectiveWound",_wound,_woundIndex,_effectiveness); // Everything is patched up on this body part already if (_wound isEqualTo EMPTY_WOUND) exitWith {0}; -_wound params ["_classID", "", "_amountOf", "_bloodloss", "_damage"]; +_wound params ["_classID", "_amountOf", "_bloodloss", "_damage"]; private _category = (_classID % 10); // Base bandage time is based on wound size and remaining percentage diff --git a/addons/medical_treatment/functions/fnc_getStitchTime.sqf b/addons/medical_treatment/functions/fnc_getStitchTime.sqf index 12c770eb95..3d965eed78 100644 --- a/addons/medical_treatment/functions/fnc_getStitchTime.sqf +++ b/addons/medical_treatment/functions/fnc_getStitchTime.sqf @@ -1,6 +1,6 @@ #include "script_component.hpp" /* - * Author: mharis001 + * Author: kymckay * Calculates the Surgical Kit treatment time based on the amount of stitchable wounds. * * Arguments: @@ -18,4 +18,11 @@ params ["", "_patient"]; -count (_patient call FUNC(getStitchableWounds)) * GVAR(woundStitchTime) + +private _stitchableTotal = 0; + +{ + _stitchableTotal = _stitchableTotal + count _y; +} forEach (_patient call FUNC(getStitchableWounds)); + +_stitchableTotal * GVAR(woundStitchTime) diff --git a/addons/medical_treatment/functions/fnc_getStitchableWounds.sqf b/addons/medical_treatment/functions/fnc_getStitchableWounds.sqf index a46d878409..e06e12ffa1 100644 --- a/addons/medical_treatment/functions/fnc_getStitchableWounds.sqf +++ b/addons/medical_treatment/functions/fnc_getStitchableWounds.sqf @@ -1,14 +1,14 @@ #include "script_component.hpp" /* - * Author: mharis001 - * Returns a list of all the stitchable wounds that the given unit has. + * Author: kymckay + * Returns a hashmap of the stitchable wounds that the given unit has on each body part. * A stitchable wound is a bandaged wound on a body part that does not have any bleeding wounds. * * Arguments: * 0: Unit * * Return Value: - * Stitchable Wounds + * Stitchable Wounds * * Example: * [player] call ace_medical_treatment_fnc_getStitchableWounds @@ -18,16 +18,25 @@ params ["_unit"]; -private _bleedingBodyParts = GET_OPEN_WOUNDS(_unit) select { - _x params ["", "", "_amountOf", "_bleedingRate"]; +// First determine which body parts have a bleeding wound +private _bleedingBodyParts = createHashMap; +{ + private _isBleeding = _y findIf { + _x params ["", "_amountOf", "_bleedingRate"]; + _amountOf > 0 && {_bleedingRate > 0} + } != -1; - _amountOf > 0 && {_bleedingRate > 0} -} apply { - _x select 1 -}; + if (_isBleeding) then { + _bleedingBodyParts set [_x, true]; + }; +} forEach GET_OPEN_WOUNDS(_unit); -GET_BANDAGED_WOUNDS(_unit) select { - _x params ["", "_bodyPartN"]; +// Any bandaged wound on a body part not bleeding is stitchable +private _stitchableWounds = createHashMap; +{ + if (!(_x in _bleedingBodyParts) && {_y isNotEqualTo []}) then { + _stitchableWounds set [_x, _y]; + }; +} forEach GET_BANDAGED_WOUNDS(_unit); - !(_bodyPartN in _bleedingBodyParts) -} +_stitchableWounds diff --git a/addons/medical_treatment/functions/fnc_handleBandageOpening.sqf b/addons/medical_treatment/functions/fnc_handleBandageOpening.sqf index 31affbb311..b6191072bd 100644 --- a/addons/medical_treatment/functions/fnc_handleBandageOpening.sqf +++ b/addons/medical_treatment/functions/fnc_handleBandageOpening.sqf @@ -6,7 +6,7 @@ * Arguments: * 0: The target * 1: The impact - * 2: Selection part number + * 2: Body part * 3: Injury index * 4: Injury * 5: Used Bandage type @@ -20,7 +20,7 @@ params ["_target", "_impact", "_part", "_injuryIndex", "_injury", "_bandage"]; TRACE_6("handleBandageOpening",_target,_impact,_part,_injuryIndex,_injury,_bandage); -_injury params ["_classID", "_bodyPartN"]; +_injury params ["_classID"]; private _className = EGVAR(medical_damage,woundClassNamesComplex) select _classID; private _reopeningChance = DEFAULT_BANDAGE_REOPENING_CHANCE; @@ -61,19 +61,19 @@ TRACE_5("configs",_bandage,_className,_reopeningChance,_reopeningMinDelay,_reope private _bandagedWounds = GET_BANDAGED_WOUNDS(_target); private _exist = false; { - _x params ["_id", "_partN", "_amountOf"]; - if (_id == _classID && {_partN == _bodyPartN}) exitWith { - _x set [2, _amountOf + _impact]; - TRACE_2("adding to existing bandagedWound",_id,_partN); + _x params ["_id", "_amountOf"]; + if (_id == _classID) exitWith { + _x set [1, _amountOf + _impact]; + TRACE_2("adding to existing bandagedWound",_id,_part); _exist = true; }; -} forEach _bandagedWounds; +} forEach (_bandagedWounds getOrDefault [_part, []]); if (!_exist) then { - TRACE_2("adding new bandagedWound",_classID,_bodyPartN); + TRACE_2("adding new bandagedWound",_classID,_part); private _bandagedInjury = +_injury; - _bandagedInjury set [2, _impact]; - _bandagedWounds pushBack _bandagedInjury; + _bandagedInjury set [1, _impact]; + (_bandagedWounds getOrDefault [_part, [], true]) pushBack _bandagedInjury; }; _target setVariable [VAR_BANDAGED_WOUNDS, _bandagedWounds, true]; @@ -92,42 +92,45 @@ if (random 1 <= _reopeningChance * GVAR(woundReopenChance)) then { TRACE_5("reopen delay finished",_target,_impact,_part,_injuryIndex,_injury); private _openWounds = GET_OPEN_WOUNDS(_target); - if (count _openWounds - 1 < _injuryIndex) exitWith { TRACE_2("index bounds",_injuryIndex,count _openWounds); }; + private _woundsOnPart = _openWounds getOrDefault [_part, []]; + if (count _woundsOnPart - 1 < _injuryIndex) exitWith { TRACE_2("index bounds",_injuryIndex,count _woundsOnPart); }; - _injury params ["_classID", "_bodyPartN"]; + _injury params ["_classID"]; - private _selectedInjury = _openWounds select _injuryIndex; - _selectedInjury params ["_selClassID", "_selBodyPart", "_selAmmount"]; - if ((_selClassID == _classID) && {_selBodyPart == _bodyPartN}) then { // matching the IDs + private _selectedInjury = _woundsOnPart select _injuryIndex; + _selectedInjury params ["_selClassID", "_selAmmount"]; + if (_selClassID == _classID) then { // matching the IDs private _bandagedWounds = GET_BANDAGED_WOUNDS(_target); private _exist = false; { - _x params ["_id", "_partN", "_amountOf"]; - if ((_id == _classID) && {_partN == _bodyPartN}) exitWith { + _x params ["_id", "_amountOf"]; + if (_id == _classID) exitWith { TRACE_2("bandagedWound exists",_id,_classID); - _x set [2, 0 max (_amountOf - _impact)]; + _x set [1, 0 max (_amountOf - _impact)]; _exist = true; }; - } forEach _bandagedWounds; + } forEach (_bandagedWounds getOrDefault [_part, []]); if (_exist) then { TRACE_2("Reopening Wound",_bandagedWounds,_openWounds); - _selectedInjury set [2, _selAmmount + _impact]; + _selectedInjury set [1, _selAmmount + _impact]; _target setVariable [VAR_BANDAGED_WOUNDS, _bandagedWounds, true]; _target setVariable [VAR_OPEN_WOUNDS, _openWounds, true]; [_target] call EFUNC(medical_status,updateWoundBloodLoss); + private _partIndex = ALL_BODY_PARTS find _part; + // Re-add trauma and damage visuals if (GVAR(clearTrauma) == 2) then { private _injuryDamage = (_selectedInjury select 4) * _impact; private _bodyPartDamage = _target getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; - private _newDam = (_bodyPartDamage select _selBodyPart) + _injuryDamage; - _bodyPartDamage set [_selBodyPart, _newDam]; + private _newDam = (_bodyPartDamage select _partIndex) + _injuryDamage; + _bodyPartDamage set [_partIndex, _newDam]; _target setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true]; - switch (_selBodyPart) do { + switch (_partIndex) do { case 0: { [_target, true, false, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; case 1: { [_target, false, true, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; case 2; @@ -137,12 +140,12 @@ if (random 1 <= _reopeningChance * GVAR(woundReopenChance)) then { }; // Check if we gained limping from this wound re-opening - if ((EGVAR(medical,limping) == 1) && {_bodyPartN > 3}) then { + if ((EGVAR(medical,limping) == 1) && {_partIndex > 3}) then { [_target] call EFUNC(medical_engine,updateDamageEffects); }; }; } else { - TRACE_3("no match",_selectedInjury,_classID,_bodyPartN); + TRACE_3("no match",_selectedInjury,_classID,_part); }; }, [_target, _impact, _part, _injuryIndex, +_injury], _delay] call CBA_fnc_waitAndExecute; }; diff --git a/addons/medical_treatment/functions/fnc_surgicalKitProgress.sqf b/addons/medical_treatment/functions/fnc_surgicalKitProgress.sqf index 1a19066a43..ee16205099 100644 --- a/addons/medical_treatment/functions/fnc_surgicalKitProgress.sqf +++ b/addons/medical_treatment/functions/fnc_surgicalKitProgress.sqf @@ -25,44 +25,46 @@ _args params ["_medic", "_patient"]; private _stitchableWounds = _patient call FUNC(getStitchableWounds); // Stop treatment if there are no wounds that can be stitched remaining -if (_stitchableWounds isEqualTo []) exitWith {false}; +if (_stitchableWounds isEqualTo createHashMap) exitWith {false}; // Not enough time has elapsed to stitch a wound -if (_totalTime - _elapsedTime > (count _stitchableWounds - 1) * GVAR(woundStitchTime)) exitWith {true}; +if (_totalTime - _elapsedTime > ([_patient, _patient] call FUNC(getStitchTime)) - GVAR(woundStitchTime)) exitWith {true}; private _bandagedWounds = GET_BANDAGED_WOUNDS(_patient); private _stitchedWounds = GET_STITCHED_WOUNDS(_patient); // Remove the first stitchable wound from the bandaged wounds -private _treatedWound = _bandagedWounds deleteAt (_bandagedWounds find (_stitchableWounds select 0)); -_treatedWound params ["_treatedID", "_treatedBodyPartN", "_treatedAmountOf", "", "_treatedDamageOf"]; +private _bodyPart = (keys _stitchableWounds) select 0; +private _bandagedWoundsOnPart = _bandagedWounds get _bodyPart; +private _treatedWound = _bandagedWoundsOnPart deleteAt (count _bandagedWoundsOnPart - 1); +_treatedWound params ["_treatedID", "_treatedAmountOf", "", "_treatedDamageOf"]; // Check if we need to add a new stitched wound or increase the amount of an existing one -private _woundIndex = _stitchedWounds findIf { - _x params ["_classID", "_bodyPartN"]; - - _classID == _treatedID && {_bodyPartN == _treatedBodyPartN} +private _woundIndex = (_stitchedWounds getOrDefault [_bodyPart, []]) findIf { + _x params ["_classID"]; + _classID == _treatedID }; if (_woundIndex == -1) then { - _stitchedWounds pushBack _treatedWound; + (_stitchedWounds getOrDefault [_bodyPart, [], true]) pushBack _treatedWound; } else { - private _wound = _stitchedWounds select _woundIndex; - _wound set [2, (_wound select 2) + _treatedAmountOf]; + private _wound = (_stitchedWounds get _bodyPart) select _woundIndex; + _wound set [1, (_wound select 1) + _treatedAmountOf]; }; if (GVAR(clearTrauma) == 1) then { - TRACE_2("clearTrauma - clearing trauma after stitching",_partIndex,_treatedWound); + private _partIndex = ALL_BODY_PARTS find _bodyPart; + TRACE_2("clearTrauma - clearing trauma after stitching",_bodyPart,_treatedWound); private _bodyPartDamage = _patient getVariable [QEGVAR(medical,bodyPartDamage), []]; - _bodyPartDamage set [_treatedBodyPartN, (_bodyPartDamage select _treatedBodyPartN) - _treatedDamageOf]; + _bodyPartDamage set [_partIndex, (_bodyPartDamage select _partIndex) - _treatedDamageOf]; _patient setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true]; - TRACE_2("clearTrauma - healed damage",_partIndex,_treatedDamageOf); + TRACE_2("clearTrauma - healed damage",_bodyPart,_treatedDamageOf); - switch (_treatedBodyPartN) do { - case 0: { [_patient, true, false, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; - case 1: { [_patient, false, true, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; - case 2; - case 3: { [_patient, false, false, true, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + switch (_bodyPart) do { + case "head": { [_patient, true, false, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + case "body": { [_patient, false, true, false, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; + case "leftarm"; + case "rightarm": { [_patient, false, false, true, false] call EFUNC(medical_engine,updateBodyPartVisuals); }; default { [_patient, false, false, false, true] call EFUNC(medical_engine,updateBodyPartVisuals); }; }; }; @@ -71,15 +73,19 @@ _patient setVariable [VAR_BANDAGED_WOUNDS, _bandagedWounds, true]; _patient setVariable [VAR_STITCHED_WOUNDS, _stitchedWounds, true]; // Check if we fixed limping by stitching this wound (only for leg wounds) -if (EGVAR(medical,limping) == 2 && {_patient getVariable [QEGVAR(medical,isLimping), false]} && {_treatedBodyPartN > 3}) then { - TRACE_3("Updating damage effects",_patient,_treatedBodyPartN,local _patient); +if ( + EGVAR(medical,limping) == 2 + && {_patient getVariable [QEGVAR(medical,isLimping), false]} + && {_bodyPart isEqualTo "leftleg" || _bodyPart isEqualTo "rightleg"} +) then { + TRACE_3("Updating damage effects",_patient,_bodyPart,local _patient); [QEGVAR(medical_engine,updateDamageEffects), _patient, _patient] call CBA_fnc_targetEvent; }; // Consume a suture for the next wound if one exists, stop stitching if none are left if (GVAR(consumeSurgicalKit) == 2) then { // Don't consume a suture if there are no more wounds to stitch - if (count _stitchableWounds == 1) exitWith {false}; + if (count (values _stitchableWounds) isEqualTo 1) exitWith {false}; ([_medic, _patient, ["ACE_suture"]] call FUNC(useItem)) params ["_user"]; !isNull _user } else {