Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Medical Damage - Pass ammo to wound handlers #10573

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 17 additions & 19 deletions addons/medical_damage/functions/fnc_getTypeOfDamage.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,29 @@
* Type of damage <STRING>
*
* Example:
* ["bullet"] call ace_medical_damage_fnc_getTypeOfDamage
* "bullet" call ace_medical_damage_fnc_getTypeOfDamage
*
* Public: No
*/

params ["_typeOfProjectile"];

private _damageType = GVAR(damageTypeCache) get _typeOfProjectile;
GVAR(damageTypeCache) getOrDefaultCall [_typeOfProjectile, {
private _projectileConfig = configFile >> "CfgAmmo" >> _typeOfProjectile >> "ACE_damageType";

if (isNil "_damageType") then {
if (isText (configFile >> "CfgAmmo" >> _typeOfProjectile >> "ACE_damageType")) then {
_damageType = getText (configFile >> "CfgAmmo" >> _typeOfProjectile >> "ACE_damageType");
} else {
WARNING_1("Ammo type [%1] has no ACE_damageType",_typeOfProjectile);
_damageType = "unknown";
};
switch (false) do {
case (isText _projectileConfig): { // no property or wrong type
WARNING_1("Ammo type [%1] has no ACE_damageType",_typeOfProjectile);
"unknown" // return
};

// config may define an invalid damage type
if !(_damageType in GVAR(damageTypeDetails)) then {
WARNING_2("Damage type [%1] for ammo [%2] not found",_damageType,_typeOfProjectile);
_damageType = "unknown";
private _damageType = getText _projectileConfig;
case (_damageType in GVAR(damageTypeDetails)): { // config may define an invalid damage type
WARNING_2("Damage type [%1] for ammo [%2] not found",_damageType,_typeOfProjectile);
"unknown" // return
};
default {
_damageType // return
};
};

TRACE_2("getTypeOfDamage caching",_typeOfProjectile,_damageType);
GVAR(damageTypeCache) set [_typeOfProjectile, _damageType];
};

_damageType // return
}, true]
5 changes: 3 additions & 2 deletions addons/medical_damage/functions/fnc_parseWoundHandlersCfg.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ private _entries = [];

{
private _entryResult = getText _x;
private _entryName = configName _x;

if (_entryResult != "") then {
if (ADDON) then {
Expand All @@ -30,9 +31,9 @@ private _entries = [];

if (!isNil "_entryResult") then {
if (_entryResult isEqualType {}) then {
_entries pushBack _entryResult;
_entries pushBack [_entryName, _entryResult];
} else {
ERROR_2("Wound handler '%1' needs to be a function, but is of type %2.",configName _x,toLowerANSI typeName _entryResult);
ERROR_2("Wound handler '%1' needs to be a function, but is of type %2.",_entryName,toLowerANSI typeName _entryResult);
};
};
} else {
Expand Down
32 changes: 20 additions & 12 deletions addons/medical_damage/functions/fnc_woundReceived.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,26 @@ params ["_unit", "_allDamages", "_shooter", "_ammo"];

private _typeOfDamage = _ammo call FUNC(getTypeOfDamage);

if (_typeOfDamage in GVAR(damageTypeDetails)) then {
(GVAR(damageTypeDetails) get _typeOfDamage) params ["", "", "_woundHandlers"];
if !(_typeOfDamage in GVAR(damageTypeDetails)) exitWith {};

private _damageData = [_unit, _allDamages, _typeOfDamage];
(GVAR(damageTypeDetails) get _typeOfDamage) params ["", "", "_woundHandlers"];

{
_damageData = _damageData call _x;
TRACE_1("Wound handler returned",_damageData);
private _damageData = [_unit, _allDamages, _typeOfDamage, _ammo];
private _originalCount = count _damageData;

LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved
// If invalid return, exit
if (isNil "_damageData" || {!(_damageData isEqualType [])} || {(count _damageData) < 3}) exitWith {
TRACE_1("Return invalid, skipping wound handling",_damageData);
};
} forEach _woundHandlers;
};
{
_x params ["_handlerName", "_handlerCode"];
_damageData = _damageData call _handlerCode;
TRACE_2("Wound handler returned",_damageData,_handlerName);

if ((count _damageData) == (_originalCount - 1)) then {
ERROR_1("Wound handler '%1' missing latest param in return, readding. This will be deprecated in the future, check Medical Framework wiki.",_handlerName);
_damageData pushBack _ammo;
};

// If invalid return, log an error and exit
if (isNil "_damageData" || {!(_damageData isEqualType [])} || {(count _damageData) < _originalCount}) then {
ERROR_2("Return for handler '%1' invalid - '%2', skipping wound handling",_damageData,_handlerName);
break
};
} forEach _woundHandlers;
8 changes: 7 additions & 1 deletion docs/wiki/framework/medical-framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,18 +224,24 @@ Custom wound handlers should follow the same spec as the built-in handler:
| 0 | Unit that was hit | Object | Required |
| 1 | Array of damage dealt to each body part | Array | Required |
| 2 | Type of damage | String | Required |
| 3 | Ammo | String | Required |
| **R** | Parameters to be passed to the next handler in the list, e.g. `_this` or a modified copy of it. Return `[]` to prevent further handling. | Array | Required |

We recommend modifying `_this` with `set` and returning it instead of returning a copy of the array to prevent any issues with API changes. Existing parameters will not change in type, function, or format without warning, but new parameters may be added.

The damage elements are sorted in descending order according to how much damage was dealt to each body part _before armor was taken into account_, but the actual damage values are _after armor_.

Ammo can be a CfgAmmo classname (like `" B_556x45_Ball"`), empty string, or special ammo from `medical_engine`/another wound handler. Check if the passed ammo is within your expected values (like `!isNull (configFile >> "CfgAmmo" >> _ammo)` for CfgAmmo classes) before using it.

### Example
`[player, [[0.5, "Body", 1], [0.3, "Head", 0.6]], "grenade"] ace_medical_damage_fnc_woundsHandlerBase`
`[player, [[0.5, "Body", 1], [0.3, "Head", 0.6]], "grenade", "grenade_ammo"] ace_medical_damage_fnc_woundsHandlerBase`

| | Arguments | Explanation |
| ---| --------- | ----------- |
| 0 | `player` | Unit that was hit |
| 1 | `[[0.5, "Body", 1], [0.3, "Head", 0.6]]` | 0.5 damage to body (was 1 before armor), 0.3 damage to head (was 0.6 before armor) |
| 2 | `"grenade"` | type grenade (non-selection-specific) |
| 3 | `"grenade_ammo"` | ammo |

## 5. Tweaking internal variables
Some of ACE Medical's underlying behavior, primarily related to damage handling and the vitals loop, can be fine-tuned by editing `ace_medical_const_` variables, found in [script_macros_medical.hpp](https://github.com/acemod/ACE3/blob/master/addons/medical_engine/script_macros_medical.hpp).
Expand Down
Loading