Medical - Increase severity of falling damage and Improve non-selectionSpecific wounds (#7214)

* Medical - Increase severity of falling damage

* Improve non-selectionSpecific wounds

* Use macros for hitpoint indexes
This commit is contained in:
PabstMirror 2019-10-08 10:44:49 -05:00 committed by GitHub
parent f4dbe5229e
commit a71879ccea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 23 deletions

View File

@ -47,7 +47,6 @@ class ACE_Medical_Injuries {
}; };
// Also called tears, these are separating wounds that produce ragged edges. They are produced by a tremendous force against the body, either from an internal source as in childbirth, or from an external source like a punch. // Also called tears, these are separating wounds that produce ragged edges. They are produced by a tremendous force against the body, either from an internal source as in childbirth, or from an external source like a punch.
class Laceration { class Laceration {
selections[] = {"All"};
causes[] = {"vehiclecrash", "collision", "punch"}; causes[] = {"vehiclecrash", "collision", "punch"};
bleeding = 0.05; bleeding = 0.05;
pain = 0.2; pain = 0.2;
@ -94,11 +93,11 @@ class ACE_Medical_Injuries {
selectionSpecific = 0; selectionSpecific = 0;
}; };
class vehiclecrash { class vehiclecrash {
thresholds[] = {{0.5, 5}, {0.3, 2}, {0.05, 1}}; thresholds[] = {{1.5, 3}, {1, 2}, {0.05, 1}}; // prevent subdividing wounds past FRACTURE_DAMAGE_THRESHOLD to ensure limp/fractue is triggered
selectionSpecific = 0; selectionSpecific = 0;
}; };
class collision { class collision {
thresholds[] = {{0.5, 5}, {0.3, 2}, {0.05, 1}}; thresholds[] = {{1.5, 3}, {1, 2}, {0.05, 1}}; // prevent subdividing wounds past FRACTURE_DAMAGE_THRESHOLD to ensure limp/fractue is triggered
selectionSpecific = 0; selectionSpecific = 0;
}; };
class backblast { class backblast {
@ -114,8 +113,8 @@ class ACE_Medical_Injuries {
selectionSpecific = 1; selectionSpecific = 1;
}; };
class falling { class falling {
thresholds[] = {{0.6, 4}, {0.35, 2}, {0.1, 1}}; thresholds[] = {{1.5, 3}, {1, 2}, {0.05, 1}}; // prevent subdividing wounds past FRACTURE_DAMAGE_THRESHOLD to ensure limp/fractue is triggered
selectionSpecific = 1; selectionSpecific = 0;
}; };
class ropeburn { class ropeburn {
thresholds[] = {{0.1, 1}}; thresholds[] = {{0.1, 1}};

View File

@ -26,10 +26,10 @@ addMissionEventHandler ["Loaded",{
// }; // };
[QEGVAR(medical,woundReceived), { [QEGVAR(medical,woundReceived), {
params ["_unit", "_woundedHitPoint", "_receivedDamage", "", "_ammo"]; params ["_unit", "_woundedHitPoint", "_receivedDamage", "", "_ammo", "_damageSelectionArray"];
private _typeOfDamage = _ammo call FUNC(getTypeOfDamage); private _typeOfDamage = _ammo call FUNC(getTypeOfDamage);
[_unit, _woundedHitPoint, _receivedDamage, _typeOfDamage] call FUNC(woundsHandlerActive); [_unit, _woundedHitPoint, _receivedDamage, _typeOfDamage, _damageSelectionArray] call FUNC(woundsHandlerActive);
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;
ADDON = true; ADDON = true;

View File

@ -76,6 +76,7 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
GVAR(allDamageTypesData) setVariable [_className, [_thresholds, _selectionSpecific > 0, _woundTypes]]; GVAR(allDamageTypesData) setVariable [_className, [_thresholds, _selectionSpecific > 0, _woundTypes]];
/*
// extension loading // extension loading
private _minDamageThresholds = (_thresholds apply {str (_x select 0)}) joinString ":"; private _minDamageThresholds = (_thresholds apply {str (_x select 0)}) joinString ":";
private _amountThresholds = (_thresholds apply {str (_x select 1)}) joinString ":"; private _amountThresholds = (_thresholds apply {str (_x select 1)}) joinString ":";
@ -93,8 +94,10 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
// private _extensionRes = "ace_medical" callExtension _extensionArgs; // private _extensionRes = "ace_medical" callExtension _extensionArgs;
// TRACE_1("",_extensionRes); // TRACE_1("",_extensionRes);
*/
} forEach configProperties [_damageTypesConfig, "isClass _x"]; } forEach configProperties [_damageTypesConfig, "isClass _x"];
/*
// extension loading // extension loading
{ {
_x params ["_classID", "_selections", "_bleedingRate", "_pain", "_damageExtrema", "_causes", "_displayName"]; _x params ["_classID", "_selections", "_bleedingRate", "_pain", "_damageExtrema", "_causes", "_displayName"];
@ -128,3 +131,4 @@ private _selectionSpecificDefault = getNumber (_damageTypesConfig >> "selectionS
} forEach GVAR(woundsData); } forEach GVAR(woundsData);
// "ace_medical" callExtension "ConfigComplete"; // "ace_medical" callExtension "ConfigComplete";
*/

View File

@ -8,18 +8,19 @@
* 1: Name Of Body Part <STRING> * 1: Name Of Body Part <STRING>
* 2: Amount Of Damage <NUMBER> * 2: Amount Of Damage <NUMBER>
* 3: Type of the damage done <STRING> * 3: Type of the damage done <STRING>
* 4: Weighted array of damaged selections <ARRAY>
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* [player, "Body", 0.5, "bullet"] call ace_medical_damage_fnc_woundsHandlerSQF * [player, "Body", 0.5, "bullet", [1, 1]] call ace_medical_damage_fnc_woundsHandlerSQF
* *
* Public: No * Public: No
*/ */
params ["_unit", "_bodyPart", "_damage", "_typeOfDamage"]; params ["_unit", "_bodyPart", "_damage", "_typeOfDamage", "_damageSelectionArray"];
TRACE_4("woundsHandlerSQF",_unit,_bodyPart,_damage,_typeOfDamage); TRACE_5("woundsHandlerSQF",_unit,_bodyPart,_damage,_typeOfDamage,_damageSelectionArray);
// Convert the selectionName to a number and ensure it is a valid selection. // Convert the selectionName to a number and ensure it is a valid selection.
private _bodyPartN = ALL_BODY_PARTS find toLower _bodyPart; private _bodyPartN = ALL_BODY_PARTS find toLower _bodyPart;
@ -47,7 +48,7 @@ private _allPossibleInjuries = [];
// Check if the damage is higher as the min damage for the specific injury // Check if the damage is higher as the min damage for the specific injury
if (_damage >= _minDamage && {_damage <= _maxDamage || _maxDamage < 0}) then { if (_damage >= _minDamage && {_damage <= _maxDamage || _maxDamage < 0}) then {
// Check if the injury can be applied to the given selection name // 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! // 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 // 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 { if (_minDamage > _highestPossibleDamage) then {
@ -57,7 +58,7 @@ private _allPossibleInjuries = [];
// Store the valid possible injury for the damage type, damage amount and selection // Store the valid possible injury for the damage type, damage amount and selection
_allPossibleInjuries pushBack _x; _allPossibleInjuries pushBack _x;
}; // };
}; };
} forEach _woundTypes; } forEach _woundTypes;
@ -87,7 +88,7 @@ private _bodyPartVisParams = [_unit, false, false, false, false]; // params arra
_oldInjury params ["_woundClassIDToAdd", "", "_injuryBleedingRate", "_injuryPain", "", "", "", "_causeLimping", "_causeFracture"]; _oldInjury params ["_woundClassIDToAdd", "", "_injuryBleedingRate", "_injuryPain", "", "", "", "_causeLimping", "_causeFracture"];
private _bodyPartNToAdd = [floor random 6, _bodyPartN] select _isSelectionSpecific; // 6 == count ALL_BODY_PARTS private _bodyPartNToAdd = if (_isSelectionSpecific) then {_bodyPartN} else {selectRandomWeighted _damageSelectionArray};
_bodyPartDamage set [_bodyPartNToAdd, (_bodyPartDamage select _bodyPartNToAdd) + _woundDamage]; _bodyPartDamage set [_bodyPartNToAdd, (_bodyPartDamage select _bodyPartNToAdd) + _woundDamage];
_bodyPartVisParams set [[1,2,3,3,4,4] select _bodyPartNToAdd, true]; // Mark the body part index needs updating _bodyPartVisParams set [[1,2,3,3,4,4] select _bodyPartNToAdd, true]; // Mark the body part index needs updating

View File

@ -80,6 +80,12 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
]; ];
TRACE_2("incoming",_allDamages,_damageStructural); TRACE_2("incoming",_allDamages,_damageStructural);
// represents all incoming damage for selecting a non-selectionSpecific wound location, (used for selectRandomWeighted [value1,weight1,value2....])
private _damageSelectionArray = [
HITPOINT_INDEX_HEAD, _damageHead, HITPOINT_INDEX_BODY, _damageBody, HITPOINT_INDEX_LARM, _damageLeftArm,
HITPOINT_INDEX_RARM, _damageRightArm, HITPOINT_INDEX_LLEG, _damageLeftLeg, HITPOINT_INDEX_RLEG, _damageRightLeg
];
_allDamages sort false; _allDamages sort false;
(_allDamages select 0) params ["_receivedDamage", "", "_woundedHitPoint"]; (_allDamages select 0) params ["_receivedDamage", "", "_woundedHitPoint"];
if (_damageHead >= HEAD_DAMAGE_THRESHOLD) then { if (_damageHead >= HEAD_DAMAGE_THRESHOLD) then {
@ -92,6 +98,7 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
if (_receivedDamage == 0) then { if (_receivedDamage == 0) then {
_receivedDamage = _damageStructural; _receivedDamage = _damageStructural;
_woundedHitPoint = "Body"; _woundedHitPoint = "Body";
_damageSelectionArray = [1, 1]; // sum of weights would be 0
}; };
// Environmental damage sources all have empty ammo string // Environmental damage sources all have empty ammo string
@ -100,7 +107,7 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
// Any collision with terrain/vehicle/object has a shooter // Any collision with terrain/vehicle/object has a shooter
// Check this first because burning can happen at any velocity // Check this first because burning can happen at any velocity
if !(isNull _shooter) then { if !(isNull _shooter) then {
_ammo = "#collision"; _ammo = "#collision"; // non-selectionSpecific so only _damageSelectionArray matters
/* /*
If shooter != unit then they hit unit, otherwise it could be: If shooter != unit then they hit unit, otherwise it could be:
@ -110,10 +117,11 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
Assume fall damage for downward velocity because it's most common Assume fall damage for downward velocity because it's most common
*/ */
if (_shooter == _unit && {(velocity _unit select 2) < -2}) then { if (_shooter == _unit && {(velocity _unit select 2) < -2}) then {
_woundedHitPoint = selectRandom ["RightLeg", "LeftLeg"]; _ammo = "#falling"; // non-selectionSpecific so only _damageSelectionArray matters
_damageSelectionArray = [4, 1, 5, 1]; // selectRandom ["RightLeg", "LeftLeg"];
TRACE_5("Fall",_unit,_shooter,_instigator,_damage,_receivedDamage); TRACE_5("Fall",_unit,_shooter,_instigator,_damage,_receivedDamage);
} else { } else {
_woundedHitPoint = selectRandom ["RightArm", "LeftArm", "RightLeg", "LeftLeg"]; _damageSelectionArray = [2, 1, 3, 1, 4, 1, 5, 1]; // selectRandom ["RightArm", "LeftArm", "RightLeg", "LeftLeg"];
TRACE_5("Collision",_unit,_shooter,_instigator,_damage,_receivedDamage); TRACE_5("Collision",_unit,_shooter,_instigator,_damage,_receivedDamage);
}; };
@ -122,12 +130,16 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
// Higher momentum results in higher chance for head to be hit for more lethality // Higher momentum results in higher chance for head to be hit for more lethality
if (_receivedDamage > 0.35) then { if (_receivedDamage > 0.35) then {
private _headHitWeight = (_receivedDamage / 2) min 1; private _headHitWeight = (_receivedDamage / 2) min 1;
_woundedHitPoint = selectRandomWeighted ["Body", (1 - _headHitWeight), "Head", _headHitWeight]; if (_recievedDamage < 0.6) then {
_damageSelectionArray append [0, (1 - _headHitWeight), 1, _headHitWeight];
} else {
_damageSelectionArray = [0, (1 - _headHitWeight), 1, _headHitWeight];
}
}; };
} else { } else {
// Anything else is almost guaranteed to be fire damage // Anything else is almost guaranteed to be fire damage
_woundedHitPoint = selectRandom ["LeftLeg", "RightLeg", "Body"]; _damageSelectionArray = [1, 1, 4, 1, 5, 1]; // selectRandom ["Body", "LeftLeg", "RightLeg"];
_ammo = "#unknown"; _ammo = "#unknown"; // non-selectionSpecific so only _damageSelectionArray matters
// Fire damage can occur as lots of minor damage events // Fire damage can occur as lots of minor damage events
// Combine these until significant enough to wound // Combine these until significant enough to wound
@ -145,8 +157,8 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
// No wounds for minor damage // No wounds for minor damage
if (_receivedDamage > 1E-3) then { if (_receivedDamage > 1E-3) then {
[QEGVAR(medical,woundReceived), [_unit, _woundedHitPoint, _receivedDamage, _shooter, _ammo]] call CBA_fnc_localEvent; TRACE_3("received",_receivedDamage,_woundedHitPoint,_damageSelectionArray);
TRACE_2("received",_receivedDamage,_woundedHitPoint); [QEGVAR(medical,woundReceived), [_unit, _woundedHitPoint, _receivedDamage, _shooter, _ammo, _damageSelectionArray]] call CBA_fnc_localEvent;
}; };
// Clear stored damages otherwise they will influence future damage events // Clear stored damages otherwise they will influence future damage events
@ -169,7 +181,7 @@ if (
{getOxygenRemaining _unit <= 0.5} && {getOxygenRemaining _unit <= 0.5} &&
{_damage isEqualTo (_oldDamage + 0.005)} {_damage isEqualTo (_oldDamage + 0.005)}
) exitWith { ) exitWith {
[QEGVAR(medical,woundReceived), [_unit, "Body", _newDamage, _unit, "#drowning"]] call CBA_fnc_localEvent; [QEGVAR(medical,woundReceived), [_unit, "Body", _newDamage, _unit, "#drowning", [HITPOINT_INDEX_BODY, 1]]] call CBA_fnc_localEvent;
TRACE_5("Drowning",_unit,_shooter,_instigator,_damage,_newDamage); TRACE_5("Drowning",_unit,_shooter,_instigator,_damage,_newDamage);
0 0
@ -185,7 +197,11 @@ if (
{vectorMagnitude (velocity _vehicle) > 5} {vectorMagnitude (velocity _vehicle) > 5}
// todo: no way to detect if stationary and another vehicle hits you // todo: no way to detect if stationary and another vehicle hits you
) exitWith { ) exitWith {
[QEGVAR(medical,woundReceived), [_unit, "Body", _newDamage, _unit, "#vehiclecrash"]] call CBA_fnc_localEvent; private _damageSelectionArray = [
HITPOINT_INDEX_HEAD, 1, HITPOINT_INDEX_BODY, 1, HITPOINT_INDEX_LARM, 1,
HITPOINT_INDEX_RARM, 1, HITPOINT_INDEX_LLEG, 1, HITPOINT_INDEX_RLEG, 1
];
[QEGVAR(medical,woundReceived), [_unit, "Body", _newDamage, _unit, "#vehiclecrash", _damageSelectionArray]] call CBA_fnc_localEvent;
TRACE_5("Crash",_unit,_shooter,_instigator,_damage,_newDamage); TRACE_5("Crash",_unit,_shooter,_instigator,_damage,_newDamage);
0 0

View File

@ -6,6 +6,13 @@
#define ALL_SELECTIONS ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"] #define ALL_SELECTIONS ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"]
#define ALL_HITPOINTS ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"] #define ALL_HITPOINTS ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"]
#define HITPOINT_INDEX_HEAD 0
#define HITPOINT_INDEX_BODY 1
#define HITPOINT_INDEX_LARM 2
#define HITPOINT_INDEX_RARM 3
#define HITPOINT_INDEX_LLEG 4
#define HITPOINT_INDEX_RLEG 5
// Damage threshold above which fatal organ damage can occur // Damage threshold above which fatal organ damage can occur
#define HEAD_DAMAGE_THRESHOLD 1 #define HEAD_DAMAGE_THRESHOLD 1
#define ORGAN_DAMAGE_THRESHOLD 0.6 #define ORGAN_DAMAGE_THRESHOLD 0.6