From 6e42a10d4751a231b0b5bbc886e98b89b7cce839 Mon Sep 17 00:00:00 2001 From: Glowbal Date: Sun, 17 Jan 2016 12:28:08 +0100 Subject: [PATCH] Add selectionDamage implementation --- addons/medical/XEH_postInit.sqf | 4 +- .../medical/functions/fnc_handleDamageNew.sqf | 33 ++++++-- .../functions/fnc_handleSelectionDamage.sqf | 75 +++++++++++++++++-- 3 files changed, 98 insertions(+), 14 deletions(-) diff --git a/addons/medical/XEH_postInit.sqf b/addons/medical/XEH_postInit.sqf index 41778361a2..95df32b8cd 100644 --- a/addons/medical/XEH_postInit.sqf +++ b/addons/medical/XEH_postInit.sqf @@ -3,8 +3,8 @@ #include "script_component.hpp" ["medical_selectionDamage", {_this call FUNC(handleSelectionDamage)}] call EFUNC(common,addEventhandler); -["medical_fallDamage", {_this call FUNC(handleFallDamage)}] call EFUNC(common,addEventhandler); -["medical_drowningDamage", {_this call FUNC(handleDrowningDamage)}] call EFUNC(common,addEventhandler); +["medical_fallDamage", {_this call FUNC(handleFallDamage)}] call EFUNC(common,addEventhandler); +["medical_drowningDamage", {_this call FUNC(handleDrowningDamage)}] call EFUNC(common,addEventhandler); ["medical_collisionDamage", {_this call FUNC(handleCollisionDamage)}] call EFUNC(common,addEventhandler); GVAR(heartBeatSounds_Fast) = ["ACE_heartbeat_fast_1", "ACE_heartbeat_fast_2", "ACE_heartbeat_fast_3"]; diff --git a/addons/medical/functions/fnc_handleDamageNew.sqf b/addons/medical/functions/fnc_handleDamageNew.sqf index 143c70dddb..63278c6751 100644 --- a/addons/medical/functions/fnc_handleDamageNew.sqf +++ b/addons/medical/functions/fnc_handleDamageNew.sqf @@ -42,10 +42,21 @@ if !(_unit getVariable [QGVAR(allowDamage), true]) exitWith { }; }; +// If damage is in dummy hitpoints, "hands" and "legs", don't change anything +if (_selection == "hands") exitWith {_unit getHit "hands"}; +if (_selection == "legs") exitWith {_unit getHit "legs"}; +if (_selection == "arms") exitWith {_unit getHit "arms"}; + +// Deal with the new hitpoint and selection names introduced with Arma v1.50 and later. +// This will convert new selection names into selection names that the medical system understands +// TODO This should be cleaned up when we revisit the medical system at a later stage +// and instead we should deal with the new hitpoints directly +_selection = [_unit, _selection, _hitPointIndex] call FUNC(translateSelections); diag_log text str _selection; diag_log text str _damage; +// systemChat format["_selection %1 _damage %2", _selection, _damage]; private ["_damageReturn", "_newDamage", "_index"]; @@ -62,13 +73,13 @@ if (_selection == "") then { // handle damage always tries to start and end with the same structural damage call. Use that to find and set the final damage. discard everything the game discards too. // this correctly handles: bullets, explosions, fire if (_damage == _cachedStructuralDamage) then { - private "_cachedNewHitpointDamages"; - _cachedNewHitpointDamages = _unit getVariable [QGVAR(cachedNewHitpointDamages), [0,0,0,0,0,0]]; + private _cachedNewHitpointDamages = _unit getVariable [QGVAR(cachedNewHitpointDamages), [0,0,0,0,0,0]]; + private _cachedNewHitpointProjectiles = _unit getVariable [QGVAR(cachedNewHitpointProjectiles), ["", "", "", "", "", ""]]; // this is the only point damage actually counts. all additional vitality functions should use these values. { if (_x > 0) then { - ["medical_selectionDamage", [_unit, GVAR(Selections) select _forEachIndex, _x, _projectile]] call EFUNC(common,localEvent); + ["medical_selectionDamage", [_unit, GVAR(Selections) select _forEachIndex, _x, _cachedNewHitpointProjectiles select _forEachIndex]] call EFUNC(common,localEvent); }; } forEach _cachedNewHitpointDamages; } else { @@ -126,6 +137,7 @@ if (_selection == "") then { // reset everything, get ready for the next bullet _unit setVariable [QGVAR(cachedNewHitpointDamages), [0,0,0,0,0,0]]; + _unit setVariable [QGVAR(cachedNewHitpointProjectiles), ["", "", "", "", "", ""]]; _unit setVariable [QGVAR(cachedStructuralDamageNew), _damage]; } else { @@ -137,8 +149,8 @@ if (_selection == "") then { // a selection we care for was hit. now save the new damage to apply it by a later structural damage call if (_index != -1) then { - private "_cachedNewHitpointDamages"; - _cachedNewHitpointDamages = _unit getVariable [QGVAR(cachedNewHitpointDamages), [0,0,0,0,0,0]]; + private _cachedNewHitpointDamages = _unit getVariable [QGVAR(cachedNewHitpointDamages), [0,0,0,0,0,0]]; + private _cachedNewHitpointProjectiles = _unit getVariable [QGVAR(cachedNewHitpointProjectiles), ["", "", "", "", "", ""]]; // prevents multiple selections from being hit by one bullet due to hitpoint radius system { @@ -150,12 +162,19 @@ if (_selection == "") then { // overwrite minor damage in secondary selections if (_x > 0) then { _cachedNewHitpointDamages set [_forEachIndex, 0]; + _cachedNewHitpointProjectiles set [_forEachIndex, ""]; }; } forEach _cachedNewHitpointDamages; - // apply these by the next matching hd call with selection "". If that one is not matching, this gets discarded - _cachedNewHitpointDamages set [_index, _newDamage]; + if (_cachedNewHitpointDamages select _index < _newDamage) then { + // apply these by the next matching hd call with selection "". If that one is not matching, this gets discarded + _cachedNewHitpointDamages set [_index, _newDamage]; + _cachedNewHitpointProjectiles set [_index, _projectile]; + } else { + diag_log format["PREVENTED OVERWRITE: %1", [_newDamage, _projectile, _selection]]; + }; _unit setVariable [QGVAR(cachedNewHitpointDamages), _cachedNewHitpointDamages]; + _unit setVariable [QGVAR(cachedNewHitpointProjectiles), _cachedNewHitpointProjectiles]; }; // use this to detect collision damage. diff --git a/addons/medical/functions/fnc_handleSelectionDamage.sqf b/addons/medical/functions/fnc_handleSelectionDamage.sqf index 27c8debe63..247589ae03 100644 --- a/addons/medical/functions/fnc_handleSelectionDamage.sqf +++ b/addons/medical/functions/fnc_handleSelectionDamage.sqf @@ -1,11 +1,76 @@ -// by commy2 +/* + * Author: Glowbal, Commy2 & KoffeinFlummi + * Sets the hitpoint damage for an unit to the correct values + * + * Arguments: + * 0: Unit for which the hitpoint damage will be sorted out + * 1: Selection name + * 2: new damage + * 3: projectile + * + * Return Value: + * None + * + * Public: No + */ + #include "script_component.hpp" params ["_unit", "_selection", "_newDamage", "_projectile"]; -private "_totalDamage"; -_totalDamage = (_unit getHit _selection) + _newDamage; +// private _totalDamage = (_unit getHit _selection) + _newDamage; +systemChat format["handleSelectionDamage: %1", _this]; -_unit setHit [_selection, _totalDamage]; +private _part = [_selection] call FUNC(selectionNameToNumber); +if (_part < 0) exitwith {systemchat format["Selection name part is below 0"]}; -systemChat format ["selection: %1", _this]; +// Store the new damage values in our damageBodyParts store +private _damageBodyParts = _unit getVariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0]]; +_damageBodyParts set [_part, (_damageBodyParts select _part) + _newDamage]; +_unit setVariable [QGVAR(bodyPartStatus), _damageBodyParts]; + +// our unconscious calculation for selection damages +if (alive _unit && {!(_unit getVariable ["ACE_isUnconscious", false])}) then { + // If it reaches this, we can assume that the hit did not kill this unit, as this function is called some time after the damage has been passed. + if ([_unit, _part, if (_part > 1) then {_newDamage * 1.3} else {_newDamage * 2}] call FUNC(determineIfFatal)) then { + [_unit, true, 0.5+random(10)] call FUNC(setUnconscious); + }; +}; + +if (GVAR(level) > 1) then { // advanced medical is enabled + systemChat format["LEVEL OF MEDICAL SYSTEM IS ADVANCED"]; + _typeOfDamage = [_projectile] call FUNC(getTypeOfDamage); // Get the exact type of damage + [_unit, _selection, _newDamage, _projectile, _typeOfDamage] call FUNC(handleDamage_assignWounds); + + // TODO Disabled until implemented fully + //if (GVAR(enableAirway)) then { + // [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_airway); + //}; + //if (GVAR(enableFractures)) then { + // [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_fractures); + //}; + //if (GVAR(enableInternalBleeding)) then { + // [_unit,_selectionName,_newDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_internalInjuries); + //}; +} else { + systemChat format["LEVEL OF MEDICAL SYSTEM IS BASIC"]; + // New pain values + _pain = _unit getVariable [QGVAR(pain), 0]; + _pain = _pain + (_newDamage / 4) * (1 - (_unit getVariable [QGVAR(morphine), 0])); + _unit setVariable [QGVAR(pain), _pain min 1, true]; +}; + +// Store the hitpoint values so blood ends up on the unit textures +_unit setVariable [QGVAR(bodyPartStatus), _damageBodyParts, true]; +TRACE_2("ACE_DEBUG: HandleSelectionDamage Broadcast value here", _unit, _unit getVariable QGVAR(bodyPartStatus)); + +EXPLODE_6_PVT(_damageBodyParts,_headDamage,_torsoDamage,_handsDamageR,_handsDamageL,_legsDamageR,_legsDamageL); +_unit setHitPointDamage ["hitHead", _headDamage min 0.95]; +_unit setHitPointDamage ["hitBody", _torsoDamage min 0.95]; +_unit setHitPointDamage ["hitHands", (_handsDamageR + _handsDamageL) min 0.95]; +_unit setHitPointDamage ["hitLegs", (_legsDamageR + _legsDamageL) min 0.95]; + +{ + private _hitPointName = [_unit, _x, true] call FUNC(translateSelections); + _unit setHitPointDamage [_hitPointName, (_damageBodyParts select _foreachIndex) min 0.95]; +}foreach GVAR(SELECTIONS);