integrate medical-engine handledamage into medical-damage component

This commit is contained in:
commy2 2016-08-27 09:39:24 +02:00
parent 2ac52fb430
commit 602d074898
9 changed files with 7 additions and 482 deletions

View File

@ -9,11 +9,3 @@ class Extended_PreInit_EventHandlers {
init = QUOTE(call COMPILE_FILE(XEH_preInit));
};
};
class Extended_Init_EventHandlers {
class CAManBase {
class ADDON {
init = QUOTE(call FUNC(install));
};
};
};

View File

@ -1,13 +1,6 @@
PREP(airwayHandler);
PREP(damageCache);
PREP(damageOrchestration);
PREP(fracturesHandler);
PREP(getTypeOfDamage);
PREP(handleDamage);
PREP(getTypeOfDamage);
PREP(internalInjuriesHandler);
PREP(setDamage);
PREP(translateSelections);
PREP(woundsHandler);
PREP(woundsHandlerSqf);
PREP(install);

View File

@ -4,8 +4,12 @@ ADDON = false;
#include "XEH_PREP.hpp"
// EGVAR(medical,SELECTIONS) = []; // TODO get all selections from medical
// EGVAR(medical,HITPOINTS) = []; // TODO get all selections from medical
// TODO EGVAR(medical,allAvailableDamageTypes) = []; // get from medical core component
[QGVAR(woundReceived), {
params ["_unit", "_woundedHitPoint", "_receivedDamage", "", "_ammo"];
private _selectionName = EGVAR(medical,SELECTIONS) param [EGVAR(medical,HITPOINTS) find _woundedHitPoint]; // @todo
private _typeOfDamage = _ammo call FUNC(getTypeOfDamage);
[_unit, _selectionName, _receivedDamage, _ammo, _typeOfDamage] call FUNC(woundsHandler); // TODO also support the sqf variant
}] call CBA_fnc_addEventHandler;
ADDON = true;

View File

@ -1,152 +0,0 @@
/*
* Author: KoffeinFlummi, Glowbal
* Cache a handleDamage call to execute it 3 frames later
*
* Arguments:
* 0: Unit That Was Hit <OBJECT>
* 1: Name Of Hit Selection <STRING>
* 2: Amount Of Damage <NUMBER>
* 3: Shooter <OBJECT>
* 4: Projectile <STRING>
* 5: HitPointIndex (-1 for structural) <NUMBER>
*
* Return Value:
* <nil>
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_selectionName", "_damage", "_source", "_projectile", "_hitPointIndex"];
private _hitSelections = EGVAR(medical,SELECTIONS);
// Calculate change in damage - use getHitIndex because selection is translated (hitdiaphragm->body)
private _newDamage = _damage - (damage _unit);
if (_hitPointIndex >= 0) then {_newDamage = _damage - (_unit getHitIndex _hitPointIndex)};
TRACE_7("ACE_DEBUG: HandleDamage_Caching Called",_unit, _selectionName, _damage, _source, _projectile,_hitPointIndex,_newDamage);
// Check for vehicle crash
private _vehicle = vehicle _unit;
if ((_vehicle != _unit) && {!(_vehicle isKindOf "StaticWeapon")} && {_source in [objNull, driver _vehicle, _vehicle]} && {_projectile == ""} && {_selectionName == ""}) then {
//if (GVAR(enableVehicleCrashes)) then {
_selectionName = selectRandom _hitSelections;
_projectile = "vehiclecrash";
_this set [1, _selectionName];
_this set [4, _projectile];
//};
};
// Handle falling damage
private _impactVelocity = (velocity _unit) select 2;
if (_impactVelocity < -5 && {_vehicle == _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 {
if (_selectionName == "body") then {
_newDamage = _newDamage * abs(_unit getVariable [QGVAR(impactVelocity), _impactVelocity]) / 50;
} else {
_newDamage = _newDamage * 0.5;
};
if (_newDamage < 0.075) then {_newDamage = 0;}; //Filter minor falling damage to non-leg hitpoints
} else {
if (_selectionName == "") then {
_selectionName = selectRandom ["leg_l", "leg_r"];
_this set [1, _selectionName];
};
_newDamage = _newDamage * 0.7;
};
_projectile = "falling";
_this set [4, "falling"];
};
// Finished with the current frame, reset variables
// Note: sometimes handleDamage spans over 2 or even 3 frames.
if (diag_frameno > (_unit getVariable [QGVAR(frameNo_damageCaching), -3]) + 2) then {
_unit setVariable [QGVAR(frameNo_damageCaching), diag_frameno];
// handle the cached damages 3 frames later
[{
private ["_args", "_params"];
params ["_args", "_idPFH"];
_args params ["_unit", "_frameno"];
if (diag_frameno >= _frameno + 2) then {
_unit setDamage 0;
private _cache_params = _unit getVariable [QGVAR(cachedHandleDamageParams), []];
private _cache_damages = _unit getVariable QGVAR(cachedDamages);
{
(_x + [_cache_damages select _forEachIndex]) call FUNC(damageOrchestration);
} forEach _cache_params;
[_unit] call FUNC(setDamage);
[_idPFH] call CBA_fnc_removePerFrameHandler;
};
}, 0, [_unit, diag_frameno] ] call CBA_fnc_addPerFrameHandler;
_unit setVariable [QGVAR(cachedProjectiles), []];
_unit setVariable [QGVAR(cachedHitPoints), []];
_unit setVariable [QGVAR(cachedDamages), []];
_unit setVariable [QGVAR(cachedHandleDamageParams), []];
};
// Caching of the damage events
if (_selectionName != "") then {
private _cache_projectiles = _unit getVariable QGVAR(cachedProjectiles);
private _index = _cache_projectiles find _projectile;
// Check if the current projectile has already been handled once
if (_index >= 0 && {_projectile != "falling"}) exitWith {
private _cache_damages = _unit getVariable QGVAR(cachedDamages);
private _otherDamage = (_cache_damages select _index); // Find the previous damage this projectile has done
// Take the highest damage of the two
if (_newDamage > _otherDamage) then {
private _cache_params = _unit getVariable QGVAR(cachedHandleDamageParams);
private _cache_hitpoints = _unit getVariable QGVAR(cachedHitPoints);
// Restore the damage before the previous damage was processed
private _hitPoint = _cache_hitpoints select _index;
private _restore = ((_unit getHitIndex _hitPoint) - _otherDamage) max 0;
_unit setHitIndex [_hitPoint, _restore];
_cache_hitpoints set [_index, _hitPointIndex];
_cache_damages set [_index, _newDamage];
_cache_params set[_index, _this];
_unit setVariable [QGVAR(cachedProjectiles), _cache_projectiles];
_unit setVariable [QGVAR(cachedHitPoints), _cache_hitpoints];
_unit setVariable [QGVAR(cachedDamages), _cache_damages];
_unit setVariable [QGVAR(cachedHandleDamageParams), _cache_params];
};
};
private _cache_hitpoints = _unit getVariable QGVAR(cachedHitPoints);
private _cache_damages = _unit getVariable QGVAR(cachedDamages);
private _cache_params = _unit getVariable QGVAR(cachedHandleDamageParams);
// This is an unhandled projectile
_cache_projectiles pushBack _projectile;
_cache_hitpoints pushBack _hitPointIndex;
_cache_damages pushBack _newDamage;
_cache_params pushBack _this;
// Store the new cached values
_unit setVariable [QGVAR(cachedProjectiles), _cache_projectiles];
_unit setVariable [QGVAR(cachedHitPoints), _cache_hitpoints];
_unit setVariable [QGVAR(cachedDamages), _cache_damages];
_unit setVariable [QGVAR(cachedHandleDamageParams), _cache_params];
};
TRACE_8("ACE_DEBUG: HandleDamage_Caching",_unit, _newDamage, _cache_params, _cache_damages, _unit getVariable QGVAR(cachedProjectiles), _unit getVariable QGVAR(cachedHitPoints), _unit getVariable QGVAR(cachedDamages), _unit getVariable QGVAR(cachedHandleDamageParams));
_newDamage

View File

@ -1,59 +0,0 @@
/*
* Author: Glowbal
* Damage orchestration
*
* Arguments:
* 0: Unit That Was Hit <OBJECT>
* 1: Name Of Hit Selection <STRING>
* 2: Amount Of Damage <NUMBER>
* 3: Shooter <OBJECT>
* 4: Projectile <STRING>
* 5: Hit part index of the hit point <NUMBER>
* 6: Current damage to be returned <NUMBER>
*
* //On 1.63 dev:
* 6: Shooter? <OBJECT>
* 7: Current damage to be returned <NUMBER>
*
* Return Value:
* None
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_selectionName", "_amountOfDamage", "_sourceOfDamage", "_typeOfProjectile", "_hitPointNumber", "_newDamage"];
//Temp fix for 1.63 handleDamage changes
if (_newDamage isEqualType objNull) then {
_newDamage = _this select 7;
};
TRACE_5("ACE_DEBUG: damageOrchestration Called",_unit, _selectionName, _amountOfDamage, _sourceOfDamage, _typeOfProjectile);
private _part = [_selectionName] call EFUNC(medical,selectionNameToNumber);
if (_part < 0) exitWith {};
private _hitPoints = ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"];
// Sorting out the damage
private _damageBodyParts = _unit getVariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0]];
_damageBodyParts set [_part, (_damageBodyParts select _part) + _newDamage];
_unit setVariable [QEGVAR(medical,bodyPartStatus), _damageBodyParts, true];
private _typeOfDamage = [_typeOfProjectile] call FUNC(getTypeOfDamage);
[_unit, _selectionName, _newDamage, _typeOfProjectile, _typeOfDamage] call FUNC(woundsHandler); // TODO also support the sqf variant
// 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);
//};
// TODO raise state events for unit

View File

@ -1,120 +0,0 @@
/*
* Author: KoffeinFlummi, Glowbal, commy2
* Main HandleDamage EH function.
*
* Arguments:
* 0: Unit That Was Hit <OBJECT>
* 1: Name Of Hit Selection <STRING>
* 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>
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit", "_selection", "_damage", "_shooter", "_projectile", "_hitPointIndex"];
TRACE_5("ACE_DEBUG: HandleDamage Called",_unit, _selection, _damage, _shooter, _projectile);
// bug, apparently can fire for remote units in special cases
if !(local _unit) exitWith {
TRACE_2("ACE_DEBUG: HandleDamage on remote unit!",_unit, isServer);
nil
};
// bug, assumed fixed, @todo excessive testing, if nothing happens remove
if (_projectile isEqualType objNull) then {
_projectile = typeOf _projectile;
_this set [4, _projectile];
};
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
// 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);
_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", "arms"
if (_selection != "" && {!(_selection in EGVAR(medical,SELECTIONS))}) exitWith {0};
// Exit if we disable damage temporarily
if !(_unit getVariable [QEGVAR(medical,allowDamage), true]) exitWith {
TRACE_3("ACE_DEBUG: HandleDamage damage disabled.",_selection,damage _unit,_unit);
if (_selection == "") then {
damage _unit
} else {
_unit getHit _selection
};
};
// Get return damage
private _damageReturn = _damage;
private _newDamage = _this call FUNC(damageCache);
// handleDamage_caching may have modified the projectile string
private _typeOfDamage = [_projectile] call FUNC(getTypeOfDamage);
TRACE_3("ACE_DEBUG: HandleDamage caching new damage",_selection,_newDamage,_unit);
private _typeIndex = (EGVAR(medical,allAvailableDamageTypes) find _typeOfDamage);
private _minLethalDamage = if (_typeIndex >= 0) then {
EGVAR(medical,minLethalDamages) select _typeIndex
} else {
0.01
};
if (!isNull _shooter) then {
_unit setvariable [QGVAR(lastDamageSource), _shooter, false];
};
private _vehicle = vehicle _unit;
private _effectiveSelectionName = _selection;
if ((_vehicle != _unit) && {!(_vehicle isKindOf "StaticWeapon")} && {_shooter in [objNull, driver _vehicle, _vehicle]} && {_projectile == ""} && {_selection == ""}) then {
//if (GVAR(enableVehicleCrashes)) then {
// TODO implement properly
_effectiveSelectionName = _this select 1; //pull random selection from HDC
//};
};
// ensure we are not killing the unit in the handleDamage event
// TODO based on unit state, see if we are going ot kill the unit here. This will allow us to trigger ragdoll
_damageReturn = _damageReturn min 0.89;
/*if ((_minLethalDamage <= _newDamage) && {[_unit, [_effectiveSelectionName] call EFUNC(medical,selectionNameToNumber), _newDamage] call FUNC(determineIfFatal)}) then {
if ((_unit getVariable [QGVAR(preventInstaDeath), GVAR(preventInstaDeath)])) exitwith {
_damageReturn = 0.9;
};
if ([_unit, false, true] call FUNC(setDead)) then {
_damageReturn = 1;
} else {
_damageReturn = _damageReturn min 0.89;
};
} else {
};*/
// Start the loop that tracks the unit vitals
[_unit] call EFUNC(medical,addStateHandler);
/*
if (((_unit getVariable [QGVAR(enableRevive), GVAR(enableRevive)]) > 0) && {_damageReturn >= 0.9} && {_selection in ["", "head", "body"]}) exitWith {
// TODO execute this on revive entry
if (vehicle _unit != _unit and {damage (vehicle _unit) >= 1}) then {
[_unit] call EFUNC(common,unloadPerson);
};
0.89;
};*/
TRACE_3("ACE_DEBUG: HandleDamage damage return",_selection,_damageReturn,_unit);
_damageReturn

View File

@ -1,5 +0,0 @@
#include "script_component.hpp"
params ["_unit"];
_unit addEventHandler ["HandleDamage", {_this call FUNC(handleDamage)}];

View File

@ -1,32 +0,0 @@
/*
* Author: Glowbal
* Sets the hitpoint damage for au nit to the correct values
*
* Arguments:
* 0: Unit for which the hitpoint damage will be sorted out <OBJECT>
*
* Return Value:
* None
*
* Public: No
*/
#include "script_component.hpp"
params ["_unit"];
if (!local _unit) exitWith {};
// ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"]
private _bodyStatus = _unit getVariable [QEGVAR(medical,bodyPartStatus), [0,0,0,0,0,0]];
_bodyStatus params ["_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];
if (_bodyStatus isEqualTo [0,0,0,0,0,0]) then {
_unit setDamage 0;
};

View File

@ -1,96 +0,0 @@
/*
* Author: Glowbal
* Translate selection names into medical usable hit selection names.
* Aims to deal with the new hitpoint system introduced in Arma3 v1.50 and later.
*
* Arguments:
* 0: Unit <OBJECT>
* 1: selection name <STRING>
* 2: HitPoint Index/True to get hitpoint <NUMBER><BOOL>
*
* Return Value:
* 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"
#define HEAD_SELECTIONS ["face_hub", "neck", "head"]
#define HEAD_HITPOINTS ["hitface", "hitneck", "hithead"]
#define TORSO_SELECTIONS ["pelvis", "spine1", "spine2", "spine3", "body"]
#define TORSO_HITPOINTS ["hitpelvis", "hitabdomen", "hitdiaphragm", "hitchest", "hitbody"]
#define L_ARM_SELECTIONS ["hand_l"]
#define L_ARM_HITPOINTS ["hitleftarm", "hand_l"]
#define R_ARM_SELECTIONS ["hand_r"]
#define R_ARM_HITPOINTS ["hitrightarm", "hand_r"]
#define L_LEG_SELECTIONS ["leg_l"]
#define L_LEG_HITPOINTS ["hitleftleg", "leg_l"]
#define R_LEG_SELECTIONS ["leg_r"]
#define R_LEG_HITPOINTS ["hitrightleg", "leg_r"]
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 = EGVAR(medical,HITPOINTS) select (EGVAR(medical,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"};
// Not necessary unless we get more hitpoints variants in an next arma update
/*if (_selection in L_ARM_SELECTIONS) exitWith {"hand_l"};
if (_selection in R_ARM_SELECTIONS) exitWith {"hand_r"};
if (_selection in L_LEG_SELECTIONS) exitWith {"leg_l"};
if (_selection in R_LEG_SELECTIONS) exitWith {"leg_r"};*/
//Backup method to detect weird selections/hitpoints
if ((_selection == "?") || {!(_selection in EGVAR(medical,SELECTIONS))}) exitWith {
if (_hitPointIndex < 0) exitWith {_selection};
private _hitPoint = toLower configName ((configProperties [(configFile >> "CfgVehicles" >> (typeOf _unit) >> "HitPoints")]) select _hitPointIndex);
TRACE_4("Weird sel/hit", _unit, _selection, _hitPointIndex, _hitPoint);
if (_hitPoint in HEAD_HITPOINTS) exitWith {"head"};
if (_hitPoint in TORSO_HITPOINTS) exitWith {"body"};
if (_hitPoint in L_ARM_HITPOINTS) exitWith {"hand_l"};
if (_hitPoint in R_ARM_HITPOINTS) exitWith {"hand_r"};
if (_hitPoint in L_LEG_HITPOINTS) exitWith {"leg_l"};
if (_hitPoint in R_LEG_HITPOINTS) exitWith {"leg_r"};
_selection
};
_selection;