mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Medical Engine - Remove ACE_HDBracket hitpoint (#9732)
* Medical Engine - Remove ACE_HDBracket hitpoint * skip context 4 * move checks to vars * skip uav/logic entities * add check for arm/leg hitpoints * Update addons/medical_engine/functions/fnc_handleDamage.sqf Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com> * don't skip context 2 * clearer custom hitpoint array name * reenable compile cache * remove debug mode * lazy eval * whitespace * update comment * Update fnc_handleDamage.sqf header * Update addons/medical_engine/functions/fnc_handleDamage.sqf Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com> * Update addons/medical_engine/XEH_postInit.sqf Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com> * update hitpoint test * missing " * Update addons/medical/dev/test_hitpointConfigs.sqf Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com> --------- Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com> Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com>
This commit is contained in:
parent
c862c47617
commit
a85074a797
@ -21,23 +21,16 @@ INFO_1("Checking uniforms for correct medical hitpoints [%1 units]",count _units
|
||||
private _testPass = true;
|
||||
{
|
||||
private _typeOf = configName _x;
|
||||
private _hitpoints = (configProperties [_x >> "HitPoints", "isClass _x", true]) apply {configName _x};
|
||||
private _hitpoints = (configProperties [_x >> "HitPoints", "isClass _x", true]) apply {toLowerANSI configName _x};
|
||||
private _expectedHitPoints = ["hitleftarm","hitrightarm","hitleftleg","hitrightleg","hithead","hitbody"];
|
||||
private _missingHitPoints = _expectedHitPoints select {!(_x in _hitpoints)};
|
||||
if (_missingHitPoints isNotEqualTo []) then {
|
||||
WARNING_3("%1 missing ace hitpoints: %2 - class hitpoints: %3",_typeOf,_missingHitPoints,_hitpoints);
|
||||
_testPass = false;
|
||||
};
|
||||
|
||||
// _typeOf createUnit [position player, group player, "z = this"];
|
||||
// deleteVehicle z;
|
||||
|
||||
private _lastHitpoint = (_hitpoints param [(count _hitpoints) - 1, "#array"]);
|
||||
if (_lastHitpoint != "ACE_HDBracket") then {
|
||||
WARNING_2("%1 has bad last hitpoint: %2",_typeOf,_hitpoints);
|
||||
_testPass = false;
|
||||
};
|
||||
|
||||
if (((_hitpoints findIf {_x == "HitLeftArm"}) == -1) || {(_hitpoints findIf {_x == "HitRightArm"}) == -1}
|
||||
|| {(_hitpoints findIf {_x == "HitLeftLeg"}) == -1} || {(_hitpoints findIf {_x == "HitRightLeg"}) == -1}
|
||||
|| {(_hitpoints findIf {_x == "HitHead"}) == -1} || {(_hitpoints findIf {_x == "HitBody"}) == -1}) then {
|
||||
WARNING_2("%1 missing ace hitpoints: %2",_typeOf,_hitpoints);
|
||||
_testPass = false;
|
||||
};
|
||||
} forEach _units;
|
||||
|
||||
_testPass
|
||||
|
@ -6,27 +6,23 @@
|
||||
[_new] call FUNC(updateDamageEffects); // Run on new controlled unit to update QGVAR(aimFracture)
|
||||
}, true] call CBA_fnc_addPlayerEventHandler;
|
||||
|
||||
|
||||
["CAManBase", "init", {
|
||||
params ["_unit"];
|
||||
|
||||
// Check if last hit point is our dummy.
|
||||
private _allHitPoints = getAllHitPointsDamage _unit param [0, []];
|
||||
reverse _allHitPoints;
|
||||
while {(_allHitPoints param [0, ""]) select [0,1] == "#"} do { WARNING_1("Ignoring Reflector hitpoint %1",_allHitPoints deleteAt 0); };
|
||||
if (unitIsUAV _unit) exitWith {TRACE_1("ignore UAV AI",typeOf _unit);};
|
||||
if (getNumber (configOf _unit >> "isPlayableLogic") == 1) exitWith {TRACE_1("ignore logic unit",typeOf _unit);};
|
||||
|
||||
if (_allHitPoints param [0, ""] != "ACE_HDBracket") then {
|
||||
if (unitIsUAV _unit) exitWith {TRACE_1("ignore UAV AI",typeOf _unit);};
|
||||
if (getNumber ((configOf _unit) >> "isPlayableLogic") == 1) exitWith {TRACE_1("ignore logic unit",typeOf _unit)};
|
||||
private _allHitPoints = getAllHitPointsDamage _unit param [0, []];
|
||||
if ((GVAR(customHitpoints) arrayIntersect _allHitPoints) isNotEqualTo GVAR(customHitpoints)) exitWith {
|
||||
ERROR_1("Bad hitpoints for unit type ""%1""",typeOf _unit);
|
||||
} else {
|
||||
// Calling this function inside curly brackets allows the usage of
|
||||
// "exitWith", which would be broken with "HandleDamage" otherwise.
|
||||
_unit setVariable [
|
||||
QEGVAR(medical,HandleDamageEHID),
|
||||
_unit addEventHandler ["HandleDamage", {_this call FUNC(handleDamage)}]
|
||||
];
|
||||
};
|
||||
|
||||
// Calling this function inside curly brackets allows the usage of
|
||||
// "exitWith", which would be broken with "HandleDamage" otherwise.
|
||||
_unit setVariable [
|
||||
QEGVAR(medical,HandleDamageEHID),
|
||||
_unit addEventHandler ["HandleDamage", {_this call FUNC(handleDamage)}]
|
||||
];
|
||||
}, nil, [IGNORE_BASE_UAVPILOTS], true] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
@ -88,7 +84,7 @@
|
||||
};
|
||||
}] call CBA_fnc_addEventHandler;
|
||||
|
||||
["CAManBase", "deleted", {
|
||||
["CAManBase", "Deleted", {
|
||||
params ["_unit"];
|
||||
TRACE_3("unit deleted",_unit,objectParent _unit,local _unit);
|
||||
if ((!isNull objectParent _unit) && {local objectParent _unit}) then {
|
||||
|
@ -46,6 +46,8 @@ GVAR(animations) setVariable [QUNCON_ANIM(faceDown), [QUNCON_ANIM(1),QUNCON_ANIM
|
||||
GVAR(animations) setVariable [QUNCON_ANIM(faceLeft), [QUNCON_ANIM(7),QUNCON_ANIM(8),QUNCON_ANIM(1_1),QUNCON_ANIM(7_1),QUNCON_ANIM(8_1)]];
|
||||
GVAR(animations) setVariable [QUNCON_ANIM(faceRight), [QUNCON_ANIM(5),QUNCON_ANIM(6),QUNCON_ANIM(10),QUNCON_ANIM(5_1),QUNCON_ANIM(6_1)]];
|
||||
|
||||
GVAR(customHitpoints) = ["hitleftarm", "hitrightarm", "hitleftleg", "hitrightleg"];
|
||||
|
||||
private _fnc_fixStatic = {
|
||||
params ["_vehicle"];
|
||||
private _type = typeOf _vehicle;
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: commy2, kymckay
|
||||
* Author: commy2, kymckay, LinkIsGrim
|
||||
* HandleDamage EH where wound events are raised based on incoming damage.
|
||||
* Be aware that for each source of damage, the EH can fire multiple times (once for each hitpoint).
|
||||
* We store these incoming damages and compare them on our final hitpoint: "ace_hdbracket".
|
||||
* We store these incoming damages and compare them on last iteration of the event (_context == 2).
|
||||
*
|
||||
* Arguments:
|
||||
* Handle damage EH
|
||||
@ -13,15 +13,16 @@
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
params ["_unit", "_selection", "_damage", "_shooter", "_ammo", "_hitPointIndex", "_instigator", "_hitpoint"];
|
||||
params ["_unit", "_selection", "_damage", "_shooter", "_ammo", "_hitPointIndex", "_instigator", "_hitpoint", "_directHit", "_context"];
|
||||
|
||||
// HD sometimes triggers for remote units - ignore.
|
||||
if !(local _unit) exitWith {nil};
|
||||
|
||||
// Get missing meta info
|
||||
private _oldDamage = 0;
|
||||
private _structuralDamage = _context == 0;
|
||||
|
||||
if (_hitPoint isEqualTo "") then {
|
||||
if (_structuralDamage) then {
|
||||
_hitPoint = "#structural";
|
||||
_oldDamage = damage _unit;
|
||||
} else {
|
||||
@ -33,26 +34,29 @@ if !(isDamageAllowed _unit && {_unit getVariable [QEGVAR(medical,allowDamage), t
|
||||
|
||||
private _newDamage = _damage - _oldDamage;
|
||||
|
||||
// Happens occasionally for vehiclehit events (see line 80 onwards)
|
||||
// Just exit early to save some frametime
|
||||
if (_newDamage == 0 && {_hitpoint isNotEqualTo "ace_hdbracket"}) exitWith {_oldDamage};
|
||||
// _newDamage == 0 happens occasionally for vehiclehit events (see line 80 onwards), just exit early to save some frametime
|
||||
// context 4 is engine "bleeding". For us, it's just a duplicate event for #structural which we can ignore without any issues
|
||||
if (_context != 2 && {_context == 4 || _newDamage == 0}) exitWith {
|
||||
TRACE_4("Skipping engine bleeding or zero damage",_ammo,_newDamage,_directHit,_context);
|
||||
_oldDamage
|
||||
};
|
||||
|
||||
// Get scaled armor value of hitpoint and calculate damage before armor
|
||||
// We scale using passThrough to handle explosive-resistant armor properly (#9063)
|
||||
// We need realDamage to determine which limb was hit correctly
|
||||
[_unit, _hitpoint] call FUNC(getHitpointArmor) params ["_armor", "_armorScaled"];
|
||||
private _realDamage = _newDamage * _armor;
|
||||
if (_hitPoint isNotEqualTo "#structural") then {
|
||||
if (!_structuralDamage) then {
|
||||
private _armorCoef = _armor/_armorScaled;
|
||||
private _damageCoef = linearConversion [0, 1, GVAR(damagePassThroughEffect), 1, _armorCoef];
|
||||
_newDamage = _newDamage * _damageCoef;
|
||||
};
|
||||
TRACE_4("Received hit",_hitpoint,_ammo,_newDamage,_realDamage);
|
||||
TRACE_6("Received hit",_hitpoint,_ammo,_newDamage,_realDamage,_directHit,_context);
|
||||
|
||||
// Drowning doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs
|
||||
// Damage occurs in consistent increments
|
||||
if (
|
||||
_hitPoint isEqualTo "#structural" &&
|
||||
_structuralDamage &&
|
||||
{getOxygenRemaining _unit <= 0.5} &&
|
||||
{_damage isEqualTo (_oldDamage + 0.005)}
|
||||
) exitWith {
|
||||
@ -64,14 +68,14 @@ if (
|
||||
|
||||
// Faster than (vehicle _unit), also handles dead units
|
||||
private _vehicle = objectParent _unit;
|
||||
private _inVehicle = !isNull _vehicle;
|
||||
private _environmentDamage = _ammo == "";
|
||||
|
||||
// Crashing a vehicle doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs
|
||||
// It does fire the EH multiple times, but this seems to scale with the intensity of the crash
|
||||
if (
|
||||
EGVAR(medical,enableVehicleCrashes) &&
|
||||
{_hitPoint isEqualTo "#structural"} &&
|
||||
{_ammo isEqualTo ""} &&
|
||||
{!isNull _vehicle} &&
|
||||
{_environmentDamage && _inVehicle && _structuralDamage} &&
|
||||
{vectorMagnitude (velocity _vehicle) > 5}
|
||||
// todo: no way to detect if stationary and another vehicle hits you
|
||||
) exitWith {
|
||||
@ -83,11 +87,8 @@ if (
|
||||
|
||||
// Receiving explosive damage inside a vehicle doesn't trigger for each hitpoint
|
||||
// This is the case for mines, explosives, artillery, and catasthrophic vehicle explosions
|
||||
// Triggers twice, but that doesn't matter as damage is low
|
||||
if (
|
||||
_hitPoint isEqualTo "#structural" &&
|
||||
{!isNull _vehicle} &&
|
||||
{_ammo isNotEqualTo ""} &&
|
||||
(!_environmentDamage && _inVehicle && _structuralDamage) &&
|
||||
{
|
||||
private _ammoCfg = configFile >> "CfgAmmo" >> _ammo;
|
||||
GET_NUMBER(_ammoCfg >> "explosive",0) > 0 ||
|
||||
@ -104,9 +105,13 @@ if (
|
||||
0
|
||||
};
|
||||
|
||||
// This hitpoint is set to trigger last, evaluate all the stored damage values
|
||||
// to determine where wounds are applied
|
||||
if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
|
||||
// Damages are stored for last iteration of the HandleDamage event (_context == 2)
|
||||
_unit setVariable [format [QGVAR($%1), _hitPoint], [_realDamage, _newDamage]];
|
||||
|
||||
// Ref https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#HandleDamage
|
||||
// Context 2 means this is the last iteration of HandleDamage, so figure out which hitpoint took the most real damage and send wound event
|
||||
// Don't exit, as the last iteration can be one of the hitpoints that we need to keep _oldDamage for
|
||||
if (_context == 2) then {
|
||||
_unit setVariable [QEGVAR(medical,lastDamageSource), _shooter];
|
||||
_unit setVariable [QEGVAR(medical,lastInstigator), _instigator];
|
||||
|
||||
@ -157,7 +162,7 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
|
||||
|
||||
// Environmental damage sources all have empty ammo string
|
||||
// No explicit source given, we infer from differences between them
|
||||
if (_ammo isEqualTo "") then {
|
||||
if (_environmentDamage) then {
|
||||
// Any collision with terrain/vehicle/object has a shooter
|
||||
// Check this first because burning can happen at any velocity
|
||||
if !(isNull _shooter) then {
|
||||
@ -199,16 +204,9 @@ if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
|
||||
QGVAR($HitLeftArm),QGVAR($HitRightArm),QGVAR($HitLeftLeg),QGVAR($HitRightLeg),
|
||||
QGVAR($#structural)
|
||||
];
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
// Damages are stored for "ace_hdbracket" event triggered last
|
||||
_unit setVariable [format [QGVAR($%1), _hitPoint], [_realDamage, _newDamage]];
|
||||
|
||||
// Engine damage to these hitpoints controls blood visuals, limping, weapon sway
|
||||
// Handled in fnc_damageBodyPart, persist here
|
||||
if (_hitPoint in ["hithead", "hitbody", "hithands", "hitlegs"]) exitWith {_oldDamage};
|
||||
|
||||
// We store our own damage values so engine damage is unnecessary
|
||||
0
|
||||
// For all other hitpoints, we store our own damage values, so engine damage is unnecessary
|
||||
[0, _oldDamage] select (_hitPoint in ["hithead", "hitbody", "hithands", "hitlegs"])
|
||||
|
@ -47,15 +47,4 @@
|
||||
};\
|
||||
class HitRightLeg: HitLeftLeg {\
|
||||
name = "leg_r";\
|
||||
};\
|
||||
class ACE_HDBracket {\
|
||||
armor = 1;\
|
||||
material = -1;\
|
||||
name = "head";\
|
||||
passThrough = 0;\
|
||||
radius = 1;\
|
||||
explosionShielding = 1;\
|
||||
visual = "";\
|
||||
minimalHit = 0;\
|
||||
depends = "HitHead";\
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user