Merge pull request #2876 from acemod/medicalTranslateHP

Medical Fixes
This commit is contained in:
Thomas Kooi 2015-11-28 20:58:08 +01:00
commit 5282e95668
13 changed files with 158 additions and 48 deletions

View File

@ -429,9 +429,9 @@ class CfgVehicles {
};
};
#define ARM_LEG_ARMOR_DEFAULT 3
#define ARM_LEG_ARMOR_BETTER 5
#define ARM_LEG_ARMOR_CSAT 4
#define ARM_LEG_ARMOR_DEFAULT 1
#define ARM_LEG_ARMOR_BETTER 1
#define ARM_LEG_ARMOR_CSAT 1
#define ADD_ACE_HITPOINTS(ARM_ARMOR,LEG_ARMOR) \
class HitLeftArm { \

View File

@ -12,6 +12,7 @@ PREP(actionPlaceInBodyBag);
PREP(actionRemoveTourniquet);
PREP(actionLoadUnit);
PREP(actionUnloadUnit);
PREP(addDamageToUnit);
PREP(addHeartRateAdjustment);
PREP(addToInjuredCollection);
PREP(addToLog);

View File

@ -0,0 +1,63 @@
/*
* Author: PabstMirror
* Manually Apply Damage to a unit (can cause lethal damage)
* NOTE: because of caching, this will not have instant effects (~3 frame delay)
*
* Arguments:
* 0: The Unit <OBJECT>
* 1: Damage to Add <NUMBER>
* 2: Selection ("head", "body", "hand_l", "hand_r", "leg_l", "leg_r") <STRING>
* 3: Projectile Type <STRING>
*
* Return Value:
* HandleDamage's return <NUMBER>
*
* Example:
* [player, 0.8, "leg_r", "bullet"] call ace_medical_fnc_addDamageToUnit
* [cursorTarget, 1, "body", "stab"] call ace_medical_fnc_addDamageToUnit
*
* Public: Yes
*/
#define DEBUG_MODE_FULL
#define DEBUG_TESTRESULTS
#include "script_component.hpp"
params [["_unit", objNull, [objNull]], ["_damageToAdd", -1, [0]], ["_selection", "", [""]], ["_typeOfDamage", "", [""]]];
TRACE_4("params",_unit,_damageToAdd,_selection,_typeOfDamage);
_selection = toLower _selection;
if ((isNull _unit) || {!local _unit} || {!alive _unit}) exitWith {ACE_LOGERROR_1("addDamageToUnit - badUnit %1", _this); -1};
if (_damageToAdd < 0) exitWith {ACE_LOGERROR_1("addDamageToUnit - bad damage %1", _this); -1};
if (!(_selection in GVAR(SELECTIONS))) exitWith {ACE_LOGERROR_1("addDamageToUnit - bad selection %1", _this); -1};
//Get the hitpoint and the index
private _hitpoint = [_unit, _selection, true] call ace_medical_fnc_translateSelections;
(getAllHitPointsDamage _unit) params [["_allHitPoints", []]];
private _hitpointIndex = -1;
{ //case insensitive find
if (_x == _hitpoint) exitWith {_hitpointIndex = _forEachIndex;};
} forEach _allHitPoints;
if (_hitpointIndex < 0) exitWith {ACE_LOGERROR_1("addDamageToUnit - bad hitpointIndex %1", _this); -1};
private _currentDamage = _unit getHitIndex _hitpointIndex;
#ifdef DEBUG_TESTRESULTS
private _checkAtFrame = diag_frameno + 5;
private _partNumber = [_selection] call FUNC(selectionNameToNumber);
private _startDmg = (_unit getVariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0]]) select _partNumber;
private _debugCode = {
params ["", "_unit", "_startDmg", "_damageToAdd", "_partNumber"];
private _endDmg = (_unit getVariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0]]) select _partNumber;
if ((!alive _unit) || {_endDmg > _startDmg}) then {
ACE_LOGINFO_6("addDamageToUnit - PASSED - [unit:%1, partNo:%2, addDmg:%3] results:[alive:%4 old:%5 new:%6]", _unit, _partNumber, _damageToAdd, alive _unit, _startDmg, _endDmg);
} else {
ACE_LOGERROR_6("addDamageToUnit - FAILED - [unit:%1, partNo:%2, addDmg:%3] results:[alive:%4 old:%5 new:%6]", _unit, _partNumber, _damageToAdd, alive _unit, _startDmg, _endDmg);
};
};
[{diag_frameno > (_this select 0)}, _debugCode, [_checkAtFrame, _unit, _startDmg, _damageToAdd, _partNumber]] call EFUNC(common,waitUntilAndExecute);
#endif
private _return = [_unit, _selection, (_currentDamage + _damageToAdd), _unit, _typeOfDamage, _hitpointIndex] call FUNC(handleDamage);
TRACE_1("handleDamage called",_return);
_return

View File

@ -133,10 +133,10 @@ if (_show) then {
} else {
_damaged = [true, true, true, true, true, true];
{
_selectionBloodLoss set [_forEachIndex, _target getHitPointDamage _x];
if (_target getHitPointDamage _x > 0 && {_forEachIndex == _selectionN}) then {
_pointDamage = _target getHitPointDamage _x;
private _hitPoint = [_target, _x, true] call FUNC(translateSelections);
_selectionBloodLoss set [_forEachIndex, _target getHitPointDamage _hitPoint];
if (_target getHitPointDamage _hitPoint > 0 && {_forEachIndex == _selectionN}) then {
_pointDamage = _target getHitPointDamage _hitPoint;
_severity = switch (true) do {
case (_pointDamage > 0.5): {localize LSTRING(HeavilyWounded)};
case (_pointDamage > 0.1): {localize LSTRING(LightlyWounded)};
@ -152,7 +152,7 @@ if (_show) then {
] select _forEachIndex);
_allInjuryTexts pushBack [format ["%1 %2", _severity, toLower _part], [1,1,1,1]];
};
} forEach ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"];
} forEach GVAR(SELECTIONS);
};
// Handle the body image coloring

View File

@ -8,6 +8,7 @@
* 2: Amount Of Damage <NUMBER>
* 3: Shooter <OBJECT>
* 4: Projectile <OBJECT/STRING>
* 5: HitPointIndex (-1 for structural) <NUMBER>
*
* Return Value:
* Damage To Be Inflicted <NUMBER>
@ -38,6 +39,7 @@ TRACE_3("ACE_DEBUG: HandleDamage",_selection,_damage,_unit);
// 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
@ -46,8 +48,8 @@ if (_selection == "legs") exitWith {_unit getHit "legs"};
_selection = [_unit, _selection, _hitPointIndex] call FUNC(translateSelections);
_this set [1, _selection]; // ensure that the parameters are set correctly
// If the damage is being weird, we just tell it to fuck off. Ignore: "hands", "legs", "?"
if (_selection != "" && {!(_selection in GVAR(SELECTIONS))}) exitWith {0}; //@todo "neck", "pelvis", "spine1", "spine2", "spine3"
// If the damage is being weird, we just tell it to fuck off. Ignore: "hands", "legs", "arms"
if (_selection != "" && {!(_selection in GVAR(SELECTIONS))}) exitWith {0};
// Exit if we disable damage temporarily
if !(_unit getVariable [QGVAR(allowDamage), true]) exitWith {
@ -85,7 +87,7 @@ if ((_minLethalDamage <= _newDamage) && {[_unit, [_selection] call FUNC(selectio
if ((_unit getVariable [QGVAR(preventInstaDeath), GVAR(preventInstaDeath)])) exitwith {
_damageReturn = 0.9;
};
if ([_unit] call FUNC(setDead)) then {
if ([_unit, false, true] call FUNC(setDead)) then {
_damageReturn = 1;
} else {
_damageReturn = _damageReturn min 0.89;
@ -110,7 +112,7 @@ if (_unit getVariable [QGVAR(preventInstaDeath), GVAR(preventInstaDeath)]) exitW
if (_damageReturn >= 0.9 && {_selection in ["", "head", "body"]}) exitWith {
if (_unit getvariable ["ACE_isUnconscious", false]) exitwith {
[_unit] call FUNC(setDead);
[_unit, false, true] call FUNC(setDead);
0.89;
};
if (_delayedUnconsicous) then {
@ -131,7 +133,7 @@ if (((_unit getVariable [QGVAR(enableRevive), GVAR(enableRevive)]) > 0) && {_dam
if (vehicle _unit != _unit and {damage (vehicle _unit) >= 1}) then {
[_unit] call EFUNC(common,unloadPerson);
};
[_unit] call FUNC(setDead);
[_unit, false, true] call FUNC(setDead);
0.89;
};

View File

@ -24,6 +24,7 @@ TRACE_4("ACE_DEBUG: HandleDamage BASIC",_unit, _damageBodyParts,_cache_params,_c
{
_x params ["_unit","_selectionName","_amountOfDamage","_sourceOfDamage","_typeOfProjectile","_typeOfDamage"];
TRACE_6("_x",_unit,_selectionName,_amountOfDamage,_sourceOfDamage,_typeOfProjectile,_typeOfDamage);
if !(isNull _sourceOfDamage && {_typeOfProjectile == ""} && {vehicle _unit == _unit} && {(_selectionName == "head" || isBurning _unit)}) then {
_part = [_selectionName] call FUNC(selectionNameToNumber);
if (_part < 0) exitwith {};
@ -56,5 +57,6 @@ _target setHitPointDamage ["hitHands", (_handsDamageR + _handsDamageL) min 0.95]
_target setHitPointDamage ["hitLegs", (_legsDamageR + _legsDamageL) min 0.95];
{
_target setHitPointDamage [_x, (_damageBodyParts select _foreachIndex) min 0.95];
}foreach GVAR(HITPOINTS);
private _hitPointName = [_target, _x, true] call FUNC(translateSelections);
_target setHitPointDamage [_hitPointName, (_damageBodyParts select _foreachIndex) min 0.95];
}foreach GVAR(SELECTIONS);

View File

@ -8,29 +8,25 @@
* 2: Amount Of Damage <NUMBER>
* 3: Shooter <OBJECT>
* 4: Projectile <STRING>
* 5: Current damage to be returned <NUMBER>
* 5: HitPointIndex (-1 for structural) <NUMBER>
*
* Return Value:
* <nil>
*
* Public: No
*/
#include "script_component.hpp"
private ["_hitSelections", "_hitPoints", "_impactVelocity", "_newDamage", "_cache_hitpoints", "_cache_projectiles", "_cache_params", "_cache_damages"];
params ["_unit", "_selectionName", "_damage", "_source", "_projectile"];
TRACE_8("ACE_DEBUG: HandleDamage_Caching Called",_unit, _selectionName, _damage, _source, _projectile,GVAR(SELECTIONS),GVAR(HITPOINTS),damage _unit);
params ["_unit", "_selectionName", "_damage", "_source", "_projectile", "_hitPointIndex"];
_hitSelections = GVAR(SELECTIONS);
_hitPoints = GVAR(HITPOINTS);
// Calculate change in damage.
// Calculate change in damage - use getHitIndex because selection is translated (hitdiaphragm->body)
_newDamage = _damage - (damage _unit);
if (_selectionName in _hitSelections) then {
_newDamage = _damage - (_unit getHitPointDamage (_hitPoints select (_hitSelections find _selectionName)));
};
if (_hitPointIndex >= 0) then {_newDamage = _damage - (_unit getHitIndex _hitPointIndex)};
//_damage = _damage + _newDamage;
TRACE_7("ACE_DEBUG: HandleDamage_Caching Called",_unit, _selectionName, _damage, _source, _projectile,_hitPointIndex,_newDamage);
// Check for vehicle crash
if (vehicle _unit != _unit && {!(vehicle _unit isKindOf "StaticWeapon")} && {isNull _source} && {_projectile == ""} && {_selectionName == ""}) then {
@ -45,8 +41,14 @@ if (vehicle _unit != _unit && {!(vehicle _unit isKindOf "StaticWeapon")} && {isN
// Handle falling damage
_impactVelocity = (velocity _unit) select 2;
if (_impactVelocity < -5 && {vehicle _unit == _unit}) then {
TRACE_1("Starting isFalling", time);
_unit setVariable [QGVAR(isFalling), true];
_unit setVariable [QGVAR(impactVelocity), _impactVelocity];
} else {
if ((_unit getVariable [QGVAR(isFalling), false]) && {diag_frameno > (_unit getVariable [QGVAR(frameNo_damageCaching), -3]) + 2}) then {
TRACE_1("Ending isFalling", time);
_unit setVariable [QGVAR(isFalling), false];
};
};
if (_unit getVariable [QGVAR(isFalling), false]) then {
if !(_selectionName in ["", "leg_l", "leg_r"]) then {
@ -119,10 +121,10 @@ if (_selectionName != "") then {
private ["_hitPoint", "_restore"];
// Restore the damage before the previous damage was processed
_hitPoint = _cache_hitpoints select _index;
_restore = ((_unit getHitPointDamage _hitPoint) - _otherDamage) max 0;
_unit setHitPointDamage [_hitPoint, _restore];
_restore = ((_unit getHitIndex _hitPoint) - _otherDamage) max 0;
_unit setHitIndex [_hitPoint, _restore];
_cache_hitpoints set [_index, (_hitPoints select (_hitSelections find _selectionName))];
_cache_hitpoints set [_index, _hitPointIndex];
_cache_damages set [_index, _newDamage];
_cache_params set[_index, _this];
@ -139,7 +141,7 @@ if (_selectionName != "") then {
// This is an unhandled projectile
_cache_projectiles pushBack _projectile;
_cache_hitpoints pushBack (_hitPoints select (_hitSelections find _selectionName));
_cache_hitpoints pushBack _hitPointIndex;
_cache_damages pushBack _newDamage;
_cache_params pushBack _this;

View File

@ -4,19 +4,21 @@
*
* Arguments:
* 0: The unit that will be killed <OBJECT>
* 1: Force Dead (ignore revive setting) <BOOL>
* 1: Delay setDamage for a frame <BOOL>
*
* ReturnValue:
* None
* Did he died? <BOOL>
*
* Public: yes
*/
#include "script_component.hpp"
private ["_unit", "_force", "_reviveVal", "_lifesLeft"];
params ["_unit", ["_force", false]];
private ["_reviveVal", "_lifesLeft"];
params ["_unit", ["_force", false], ["_delaySetDamage", false]];
if (!alive _unit) exitwith{true};
if ((!alive _unit) || {_unit getVariable ["ACE_isDead", false]}) exitWith {true};
if (!local _unit) exitwith {
[[_unit, _force], QUOTE(DFUNC(setDead)), _unit, false] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
false;
@ -78,5 +80,13 @@ if (isPLayer _unit) then {
["medical_onSetDead", [_unit]] call EFUNC(common,localEvent);
[_unit, 1] call FUNC(setStructuralDamage);
//Delay a frame before killing the unit via scripted damage
//to avoid triggering the "Killed" Event twice (and having the wrong killer)
if (!_delaySetDamage) then {
[_unit, 1] call FUNC(setStructuralDamage);
} else {
[FUNC(setStructuralDamage), [_unit, 1]] call EFUNC(common,execNextFrame);
};
true;

View File

@ -6,15 +6,18 @@
* Arguments:
* 0: Unit <OBJECT>
* 1: selection name <STRING>
* 2: HitPoint Index <SCALAR>
* 2: HitPoint Index/True to get hitpoint <SCALAR><BOOL>
*
* Return Value:
* translated selection name <STRING>
* translated selection/hitpoint name <STRING>
*
* Example:
* [bob, "pelvis", 4] call ace_medical_fnc_translateSelections
* Returns "body"
*
* [bob, "body", true] call ace_medical_fnc_translateSelections
* Returns "HitBody"
*
* Public: No
*/
#include "script_component.hpp"
@ -35,6 +38,36 @@
params ["_unit", "_selection", "_hitPointIndex"];
if (_selection == "") exitWith {""};
//Get Selection from standard selection ["head","body","hand_l","hand_r","leg_l","leg_r"]
if (_hitPointIndex isEqualTo true) exitWith {
private _returnHitPoint = GVAR(HITPOINTS) select (GVAR(SELECTIONS) find _selection);
//If the selection is a valid hitpoint just return it:
if (!isNil {_unit getHitPointDamage _returnHitPoint}) exitWith {
_returnHitPoint;
};
//Those VR fuckers have weird limb hitpoints
private _hitPoints = switch (_selection) do {
case ("hand_l"): {L_ARM_HITPOINTS};
case ("hand_r"): {R_ARM_HITPOINTS};
case ("leg_l"): {L_LEG_HITPOINTS};
case ("leg_r"): {R_LEG_HITPOINTS};
case ("head"): {HEAD_HITPOINTS};
case ("body"): {TORSO_HITPOINTS};
default {[]};
};
{
if (!isNil {_unit getHitPointDamage _x}) exitWith {
_returnHitPoint = _x;
};
} forEach _hitPoints;
_returnHitPoint
};
//Get Selection from Selection/HitIndex:
if (_selection in HEAD_SELECTIONS) exitWith {"head"};
if (_selection in TORSO_SELECTIONS) exitWith {"body"};

View File

@ -44,7 +44,8 @@ _target setHitPointDamage ["hitHands", (_handsDamageR + _handsDamageL) min 0.95]
_target setHitPointDamage ["hitLegs", (_legsDamageR + _legsDamageL) min 0.95];
{
_target setHitPointDamage [_x, (_damageBodyParts select _foreachIndex) min 0.95];
}foreach GVAR(HITPOINTS);
private _hitPointName = [_target, _x, true] call FUNC(translateSelections);
_target setHitPointDamage [_hitPointName, (_damageBodyParts select _foreachIndex) min 0.95];
}foreach GVAR(SELECTIONS);
true;

View File

@ -66,14 +66,10 @@ if (isNil _callback) then {
};
//Get current damage before treatment (for litter)
_previousDamage = switch (toLower _selectionName) do {
case ("head"): {_target getHitPointDamage "HitHead"};
case ("body"): {_target getHitPointDamage "HitBody"};
case ("hand_l"): {_target getHitPointDamage "HitLeftArm"};
case ("hand_r"): {_target getHitPointDamage "HitRightArm"};
case ("leg_l"): {_target getHitPointDamage "HitLeftLeg"};
case ("leg_r"): {_target getHitPointDamage "HitRightLeg"};
default {damage _target};
_previousDamage = if (_selectionName in GVAR(SELECTIONS)) then {
_target getHitPointDamage ([_target, _selectionName, true] call FUNC(translateSelections));
} else {
damage _target;
};
_args call _callback;

View File

@ -62,7 +62,7 @@ if (_distance < _backblastRange) then {
[_damage * 100] call BIS_fnc_bloodEffect;
if (isClass (configFile >> "CfgPatches" >> "ACE_Medical") && {([_firer] call EFUNC(medical,hasMedicalEnabled))}) then {
[_firer, "body", ((_firer getvariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0]]) select 1) + _damage, _firer, "backblast", 0] call EFUNC(medical,handleDamage);
[_firer, _damage, "body", "backblast"] call EFUNC(medical,addDamageToUnit);
} else {
_firer setDamage (damage _firer + _damage);
};

View File

@ -56,7 +56,7 @@ TRACE_4("Parameters:",_overpressureAngle,_overpressureRange,_overpressureDamage,
if (_x == ACE_player) then {[_damage * 100] call BIS_fnc_bloodEffect};
if (isClass (configFile >> "CfgPatches" >> "ACE_Medical") && {([_x] call EFUNC(medical,hasMedicalEnabled))}) then {
[_x, "body", ((_x getvariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0]]) select 1) + _damage, _firer, "backblast", 0] call EFUNC(medical,handleDamage);
[_x, _damage, "body", "backblast"] call EFUNC(medical,addDamageToUnit);
} else {
_x setDamage (damage _x + _damage);
};