diff --git a/addons/medical/ACE_Settings.hpp b/addons/medical/ACE_Settings.hpp index c2b32b84fa..550651b58f 100644 --- a/addons/medical/ACE_Settings.hpp +++ b/addons/medical/ACE_Settings.hpp @@ -57,24 +57,20 @@ class ACE_Settings { typeName = "BOOL"; value = 1; }; - - // Use those for handleIncapacitation? class GVAR(playerDamageThreshold) { category = CSTRING(Category_Medical); displayName = CSTRING(MedicalSettings_playerDamageThreshold_DisplayName); description = CSTRING(MedicalSettings_playerDamageThreshold_Description); typeName = "SCALAR"; - value = 1; + value = 1.05; }; class GVAR(AIDamageThreshold) { category = CSTRING(Category_Medical); displayName = CSTRING(MedicalSettings_AIDamageThreshold_DisplayName); description = CSTRING(MedicalSettings_AIDamageThreshold_Description); typeName = "SCALAR"; - value = 1; + value = 1.05; }; - - class GVAR(enableUnconsciousnessAI) { category = CSTRING(Category_Medical); displayName = CSTRING(MedicalSettings_enableUnconsciousnessAI_DisplayName); diff --git a/addons/medical/functions/fnc_displayPatientInformation.sqf b/addons/medical/functions/fnc_displayPatientInformation.sqf index 87d223a0ba..a21d4a6127 100644 --- a/addons/medical/functions/fnc_displayPatientInformation.sqf +++ b/addons/medical/functions/fnc_displayPatientInformation.sqf @@ -78,13 +78,12 @@ if (_show == 1) then { private _selectionTourniquet = _target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]]; private _selectionBloodLoss = [0, 0, 0, 0, 0, 0]; - private _selectionDamage = [0, 0, 0, 0, 0, 0]; + private _selectionDamage = _target getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; private _allInjuryTexts = []; { - _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"]; + _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding"]; _selectionBloodLoss set [_bodyPartN, (_selectionBloodLoss select _bodyPartN) + (20 * (_bleeding * _amountOf))]; - _selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage]; if (_selectionN == _bodyPartN) then { // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] if (_amountOf > 0) then { @@ -101,8 +100,7 @@ if (_show == 1) then { } forEach (_target getVariable [QEGVAR(medical,openWounds), []]); { - _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"]; - _selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage]; + _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding"]; if (_selectionN == _bodyPartN) then { // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] if (_amountOf > 0) then { @@ -119,8 +117,7 @@ if (_show == 1) then { } forEach (_target getVariable [QEGVAR(medical,bandagedWounds), []]); { - _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"]; - _selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage]; + _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding"]; if (_selectionN == _bodyPartN) then { // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] if (_amountOf > 0) then { diff --git a/addons/medical/functions/fnc_handleIncapacitation.sqf b/addons/medical/functions/fnc_handleIncapacitation.sqf index f4d136a5ec..d8e302cf6d 100644 --- a/addons/medical/functions/fnc_handleIncapacitation.sqf +++ b/addons/medical/functions/fnc_handleIncapacitation.sqf @@ -15,28 +15,28 @@ params ["_unit"]; private _painLevel = [_unit] call FUNC(getPainLevel); -private _headDamage = 0; -private _bodyDamage = 0; +private _bodyPartDamage = _unit getVariable [QGVAR(bodyPartDamage), [0,0,0,0,0,0]]; +_bodyPartDamage params ["_headDamage", "_bodyDamage", "_leftArmDamage", "_rightArmDamage", "_leftLegDamage", "_rightLegDamage"]; + +// Exclude non penetrating body damage { - _x params ["", "", "_bodyPart", "", "", "_damage"]; - switch (_bodyPart) do { - case 0: { - _headDamage = _headDamage + _damage; - }; - case 1: { - if (_damage > PENETRATION_THRESHOLD) then { - _bodyDamage = _bodyDamage + _damage; - }; - }; + _x params ["", "", "_bodyPartN", "", "", "_damage"]; + if (_bodyPartN == 1 && {_damage < PENETRATION_THRESHOLD}) then { + _bodyDamage = _bodyDamage - _damage; }; } forEach (_unit getVariable [QGVAR(openWounds), []]); -// todo: use an ace settings for the thresholds -if (_headDamage > 0.50) then { +private _damageThreshold = if (isPlayer _unit) then { + GVAR(playerDamageThreshold) +} else { + GVAR(AIDamageThreshold) +}; + +if (_headDamage > _damageThreshold / 2) then { [QGVAR(CriticalInjury), _unit] call CBA_fnc_localEvent; }; -if (_bodyDamage > 1.05) then { +if (_bodyDamage > _damageThreshold) then { [QGVAR(CriticalInjury), _unit] call CBA_fnc_localEvent; }; diff --git a/addons/medical/functions/fnc_init.sqf b/addons/medical/functions/fnc_init.sqf index f428a7b210..a5ebd01d2c 100644 --- a/addons/medical/functions/fnc_init.sqf +++ b/addons/medical/functions/fnc_init.sqf @@ -47,7 +47,10 @@ _unit setVariable [QGVAR(triageCard), [], true]; _unit setVariable [QGVAR(ivBags), nil, true]; // damage storage +_unit setVariable [QGVAR(bodyPartDamage), [0,0,0,0,0,0], true]; +#ifdef DEBUG_TESTRESULTS _unit setVariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0], true]; +#endif // generic medical admin _unit setVariable [QGVAR(inCardiacArrest), false, true]; diff --git a/addons/medical/script_macros_medical.hpp b/addons/medical/script_macros_medical.hpp index 37d07bda06..87af11df85 100644 --- a/addons/medical/script_macros_medical.hpp +++ b/addons/medical/script_macros_medical.hpp @@ -35,12 +35,17 @@ // --- pain #define PAIN_UNCONSCIOUS 0.5 -// duration in seconds to stay knocked out due to pain -#define PAIN_KNOCK_OUT_DURATION (5 + random 10) - // Pain reduction per second #define PAIN_REDUCTION_SPEED 0.001 // Chance to wake up when vitals are stable (checked once every SPONTANEOUS_WAKE_UP_INTERVAL seconds) #define SPONTANEOUS_WAKE_UP_CHANCE 0.2 #define SPONTANEOUS_WAKE_UP_INTERVAL 15 + +#define LETHAL_HEAD_DAMAGE_THRESHOLD 1.0 + +// Minimum leg damage required for limping +#define LIMPING_DAMAGE_THRESHOLD 0.30 + +// Minimum body part damage required for blood effect on uniform +#define VISUAL_BODY_DAMAGE_THRESHOLD 0.35 diff --git a/addons/medical_damage/functions/fnc_woundsHandler.sqf b/addons/medical_damage/functions/fnc_woundsHandler.sqf index f1dfb6eb03..2696498cab 100644 --- a/addons/medical_damage/functions/fnc_woundsHandler.sqf +++ b/addons/medical_damage/functions/fnc_woundsHandler.sqf @@ -38,9 +38,12 @@ call compile _extensionOutput; // todo: Make the pain and bleeding calculations part of the extension again private _painLevel = 0; +private _bodyPartDamage = _unit getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; { _x params ["", "_woundClassIDToAdd", "_bodyPartNToAdd", "", "_bleeding"]; + _bodyPartDamage set [_bodyPartNToAdd, (_bodyPartDamage select _bodyPartNToAdd) + _damage]; + // The higher the nastiness likelihood the higher the change to get a painful and bloody wound private _nastinessLikelihood = if (_damage > 1) then { (_damage ^ 0.33) @@ -49,26 +52,26 @@ private _painLevel = 0; }; private _bloodiness = 0.01 + 0.99 * (1 - random[0, 1, 0.9]) ^ (1 / _nastinessLikelihood); private _painfullness = 0.05 + 0.95 * (1 - random[0, 1, 0.5]) ^ (1 / _nastinessLikelihood); - + _bleeding = _bleeding * _bloodiness; - + _x set [4, _bleeding]; _x set [5, _damage]; - + private _pain = ((GVAR(woundsData) select _woundClassIDToAdd) select 3) * _painfullness; _painLevel = _painLevel max _pain; - + #ifdef DEBUG_MODE_FULL systemChat format["%1, damage: %2, peneration: %3, bleeding: %4, pain: %5", _bodyPart, round(_damage * 100) / 100, _damage > PENETRATION_THRESHOLD, round(_bleeding * 1000) / 1000, round(_pain * 1000) / 1000]; #endif - if (_bodyPartNToAdd == 0 && {_damage > 1}) then { + if (_bodyPartNToAdd == 0 && {_damage > LETHAL_HEAD_DAMAGE_THRESHOLD}) then { [QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent; }; // todo `forceWalk` based on leg damage private _causeLimping = (GVAR(woundsData) select _woundClassIDToAdd) select 7; - if (_causeLimping == 1 && {_damage > 0.3} && {_bodyPartNToAdd > 3}) then { + if (_causeLimping == 1 && {_damage > LIMPING_DAMAGE_THRESHOLD} && {_bodyPartNToAdd > 3}) then { [_unit, true] call EFUNC(medical_engine,setLimping); }; @@ -76,6 +79,7 @@ private _painLevel = 0; } forEach _woundsCreated; _unit setVariable [QEGVAR(medical,openWounds), _openWounds, true]; +_unit setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true]; [_unit, _bodyPart] call EFUNC(medical_engine,updateBodyPartVisuals); diff --git a/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf b/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf index 13b8b98c59..334cbf04eb 100644 --- a/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf +++ b/addons/medical_damage/functions/fnc_woundsHandlerSQF.sqf @@ -73,8 +73,8 @@ private _openWounds = _unit getVariable [QEGVAR(medical,openWounds), []]; private _woundID = _unit getVariable [QGVAR(lastUniqueWoundID), 1]; private _painLevel = 0; +private _bodyPartDamage = _unit getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; private _woundsCreated = []; - { if (_x select 0 <= _damage) exitWith { for "_i" from 0 to ((_x select 1)-1) do { @@ -89,6 +89,8 @@ private _woundsCreated = []; private _bodyPartNToAdd = [floor random 6, _bodyPartN] select _isSelectionSpecific; // 6 == count ALL_BODY_PARTS + _bodyPartDamage set [_bodyPartNToAdd, (_bodyPartDamage select _bodyPartNToAdd) + _damage]; + // Create a new injury. Format [ID, classID, bodypart, percentage treated, bleeding rate] _injury = [_woundID, _woundClassIDToAdd, _bodyPartNToAdd, 1, _injuryBleedingRate]; @@ -113,13 +115,13 @@ private _woundsCreated = []; systemChat format["%1, damage: %2, peneration: %3, bleeding: %4, pain: %5", _bodyPart, round(_damage * 100) / 100, _damage > PENETRATION_THRESHOLD, round(_bleeding * 1000) / 1000, round(_pain * 1000) / 1000]; #endif - if (_bodyPartNToAdd == 0 && {_damage > 1}) then { + if (_bodyPartNToAdd == 0 && {_damage > LETHAL_HEAD_DAMAGE_THRESHOLD}) then { [QEGVAR(medical,FatalInjury), _unit] call CBA_fnc_localEvent; }; // todo `forceWalk` based on leg damage private _causeLimping = (GVAR(woundsData) select _woundClassIDToAdd) select 7; - if (_causeLimping == 1 && {_damage > 0.3} && {_bodyPartNToAdd > 3}) then { + if (_causeLimping == 1 && {_damage > LIMPING_DAMAGE_THRESHOLD} && {_bodyPartNToAdd > 3}) then { [_unit, true] call EFUNC(medical_engine,setLimping); }; @@ -136,6 +138,7 @@ private _woundsCreated = []; } forEach _thresholds; _unit setVariable [QEGVAR(medical,openWounds), _openWounds, true]; +_unit setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true]; [_unit, _bodyPart] call EFUNC(medical_engine,updateBodyPartVisuals); diff --git a/addons/medical_engine/functions/fnc_updateBodyPartVisuals.sqf b/addons/medical_engine/functions/fnc_updateBodyPartVisuals.sqf index 5168072115..d7479ae758 100644 --- a/addons/medical_engine/functions/fnc_updateBodyPartVisuals.sqf +++ b/addons/medical_engine/functions/fnc_updateBodyPartVisuals.sqf @@ -43,23 +43,13 @@ switch (toLower _bodyPart) do { }; }; -private _openWounds = _unit getVariable QEGVAR(medical,openWounds); +private _bodyPartDamage = _unit getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; private _damageOnAffectedBodyParts = 0; - { - private _damageOnBodyPart = 0; private _partIndex = ALL_BODY_PARTS find toLower _x; - - { - _x params ["", "", "_bodyPartN", "", "_bleeding", "_damage"]; - - if (_bodyPartN isEqualTo _partIndex) then { - _damageOnBodyPart = _damageOnBodyPart + _damage; - }; - } forEach _openWounds; - + private _damageOnBodyPart = _bodyPartDamage select _partIndex; // report maximum of both legs or arms _damageOnAffectedBodyParts = _damageOnAffectedBodyParts max _damageOnBodyPart; } forEach _affectedBodyParts; -[_unit, _bodyPart, _damageOnAffectedBodyParts > 0.35] call FUNC(damageBodyPart); +[_unit, _bodyPart, _damageOnAffectedBodyParts > VISUAL_BODY_DAMAGE_THRESHOLD] call FUNC(damageBodyPart); diff --git a/addons/medical_menu/functions/fnc_updateUIInfo.sqf b/addons/medical_menu/functions/fnc_updateUIInfo.sqf index a2457b828a..0f0924251e 100644 --- a/addons/medical_menu/functions/fnc_updateUIInfo.sqf +++ b/addons/medical_menu/functions/fnc_updateUIInfo.sqf @@ -56,13 +56,12 @@ if (_totalIvVolume >= 1) then { private _selectionTourniquet = _target getVariable [QEGVAR(medical,tourniquets), [0,0,0,0,0,0]]; private _selectionBloodLoss = [0, 0, 0, 0, 0, 0]; -private _selectionDamage = [0, 0, 0, 0, 0, 0]; +private _selectionDamage = _target getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; private _allInjuryTexts = []; { - _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"]; + _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding"]; _selectionBloodLoss set [_bodyPartN, (_selectionBloodLoss select _bodyPartN) + (20 * (_bleeding * _amountOf))]; - _selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage]; if (_selectionN == _bodyPartN) then { // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] if (_amountOf > 0) then { @@ -79,8 +78,7 @@ private _allInjuryTexts = []; } forEach (_target getVariable [QEGVAR(medical,openWounds), []]); { - _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"]; - _selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage]; + _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding"]; if (_selectionN == _bodyPartN) then { // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] if (_amountOf > 0) then { @@ -97,8 +95,7 @@ private _allInjuryTexts = []; } forEach (_target getVariable [QEGVAR(medical,bandagedWounds), []]); { - _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding", "_damage"]; - _selectionDamage set [_bodyPartN, (_selectionDamage select _bodyPartN) + _damage]; + _x params ["", "_woundClassID", "_bodyPartN", "_amountOf", "_bleeding"]; if (_selectionN == _bodyPartN) then { // Collect the text to be displayed for this injury [ Select injury class type definition - select the classname DisplayName (6th), amount of injuries for this] if (_amountOf > 0) then { diff --git a/addons/medical_treatment/ACE_Medical_Treatment_Actions.hpp b/addons/medical_treatment/ACE_Medical_Treatment_Actions.hpp index 7da243de98..0a8c365e8b 100644 --- a/addons/medical_treatment/ACE_Medical_Treatment_Actions.hpp +++ b/addons/medical_treatment/ACE_Medical_Treatment_Actions.hpp @@ -75,7 +75,7 @@ class GVAR(Actions) { displayNameProgress = ECSTRING(medical,Applying_Tourniquet); allowedSelections[] = {"LeftArm", "RightArm", "LeftLeg", "RightLeg"}; items[] = {"ACE_tourniquet"}; - treatmentTime = 6; + treatmentTime = 7; callbackSuccess = QFUNC(treatmentTourniquet); condition = QUOTE(EGVAR(medical,advancedBandages) && {!([ARR_2(_target,_bodyPart)] call EFUNC(medical,hasTourniquetAppliedTo))}); litter[] = {}; diff --git a/addons/medical_treatment/functions/fnc_treatmentFullHealLocal.sqf b/addons/medical_treatment/functions/fnc_treatmentFullHealLocal.sqf index aaafa6bc55..c023b64b2e 100644 --- a/addons/medical_treatment/functions/fnc_treatmentFullHealLocal.sqf +++ b/addons/medical_treatment/functions/fnc_treatmentFullHealLocal.sqf @@ -34,35 +34,24 @@ if (_partialHeal) then { private _partialHealCounter = _target getVariable [QGVAR(partialHealCounter), 0]; _partialHealCounter = _partialHealCounter + 1; _target setVariable [QGVAR(partialHealCounter), _partialHealCounter, true]; - + private _effectiveness = (0 max EGVAR(medical,fieldEffectiveness_PAK) min 1) ^ _partialHealCounter; private _persistentDamage = 1 - _effectiveness; - - private _openWounds = _target getVariable [QEGVAR(medical,openWounds), []]; - { - _x params ["", "", "", "", "_bleeding", "_damage"]; - _x set [5, _damage min _persistentDamage]; - } forEach _openWounds; - _target setVariable [QEGVAR(medical,openWounds), _openWounds, true]; - - private _bandagedWounds = _target getVariable [QEGVAR(medical,bandagedWounds), []]; - { - _x params ["", "", "", "", "_bleeding", "_damage"]; - _x set [5, _damage min _persistentDamage]; - } forEach _bandagedWounds; - _target setVariable [QEGVAR(medical,bandagedWounds), _bandagedWounds, true]; - - private _stitchedWounds = _target getVariable [QEGVAR(medical,stitchedWounds), []]; - { - _x params ["", "", "", "", "_bleeding", "_damage"]; - _x set [5, _damage min _persistentDamage]; - } forEach _stitchedWounds; - _target setVariable [QEGVAR(medical,stitchedWounds), _stitchedWounds, true]; - - // todo: only reset limping if leg damage was reduced enough - [_unit, false] call EFUNC(medical_engine,setLimping); - - _target setDamage ((damage _target) min _persistentDamage); + + private _bodyPartDamage = _target getVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0]]; + _bodyPartDamage = _bodyPartDamage apply { + (_x min _persistentDamage) + }; + _target setVariable [QEGVAR(medical,bodyPartDamage), _bodyPartDamage, true]; + + if ((_bodyPartDamage select 4) < 0.3 && {(_bodyPartDamage select 5) < 0.3}) then { + [_unit, false] call EFUNC(medical_engine,setLimping); + }; + + // wounds and injuries + _target setVariable [QEGVAR(medical,openWounds), [], true]; + _target setVariable [QEGVAR(medical,bandagedWounds), [], true]; + _target setVariable [QEGVAR(medical,stitchedWounds), [], true]; } else { _target setVariable [QEGVAR(medical,pain), 0, true]; _target setVariable [QEGVAR(medical,bloodVolume), DEFAULT_BLOOD_VOLUME, true]; @@ -86,7 +75,10 @@ if (_partialHeal) then { _target setVariable [QEGVAR(medical,ivBags), nil, true]; // damage storage + _target setVariable [QEGVAR(medical,bodyPartDamage), [0,0,0,0,0,0], true]; +#ifdef DEBUG_TESTRESULTS _target setVariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0], true]; +#endif // generic medical admin _target setVariable [QEGVAR(medical,inCardiacArrest), false, true]; @@ -106,11 +98,11 @@ if (_partialHeal) then { } forEach _allUsedMedication; [_unit, false] call EFUNC(medical_engine,setLimping); - - // Resetting damage - _target setDamage 0; }; +// Resetting damage +_target setDamage 0; + [QEGVAR(medical,FullHeal), _target] call CBA_fnc_localEvent; [_target, "activity", ELSTRING(medical,Activity_fullHeal), [[_caller, false, true] call EFUNC(common,getName)]] call FUNC(addToLog); diff --git a/addons/medical_treatment/functions/fnc_treatmentFullHealTreatmentTime.sqf b/addons/medical_treatment/functions/fnc_treatmentFullHealTreatmentTime.sqf index a1f8159139..a65a6361de 100644 --- a/addons/medical_treatment/functions/fnc_treatmentFullHealTreatmentTime.sqf +++ b/addons/medical_treatment/functions/fnc_treatmentFullHealTreatmentTime.sqf @@ -21,6 +21,6 @@ private _totalDamage = 0; { _totalDamage = _totalDamage + _x; -} forEach (_unit getVariable [QEGVAR(medical,bodyPartStatus), []]); +} forEach (_unit getVariable [QEGVAR(medical,bodyPartDamage), []]); -10 max (_totalDamage * 10) min 120 +10 max (_totalDamage * 10) min 180