Added AGM handleDamage caching

This commit is contained in:
Thomas Kooi 2015-01-22 22:00:04 +01:00
parent 23f8b8a9ad
commit 68ab7b5143
5 changed files with 270 additions and 1 deletions

View File

@ -110,6 +110,7 @@ PREP(onTreatmentCompleted);
PREP(onUnconscious);
PREP(onStartMovingUnit);
PREP(onCarryObjectDropped);
PREP(onDamage);
PREP(openMenu);
PREP(playInjuredSound);
@ -127,6 +128,10 @@ PREP(updateUIInfo);
PREP(useEquipment);
PREP(cacheHandledamageCall);
PREP(checkDamage);
// initalize all module parameters.
GVAR(setting_allowInstantDead) = true;
GVAR(setting_AdvancedLevel) = 0;

View File

@ -0,0 +1,126 @@
/**
* fnc_cacheHandleDamageCall.sqf
* @Descr: Cache a handleDamage call to execute it 3 frames later
* @Author: KoffeinFlummi
*
* @Arguments: [unit OBJECT, selection STRING, damagE NUMBER, source OBJECT, projectile STRING (Could be an OBJECT on occasion)]
* @Return:
* @PublicAPI: false
*/
#include "script_component.hpp"
private ["_unit", "_selectionName","_damage"];
_unit = _this select 0;
_selectionName = _this select 1;
_damage = _this select 2;
_source = _this select 3;
_projectile = _this select 4;
_hitSelections = ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"];
_hitPoints = ["HitHead", "HitBody", "HitLeftArm", "HitRightArm", "HitLeftLeg", "HitRightLeg"];
// Calculate change in damage.
_newDamage = _damage - (damage _unit);
if (_selectionName in _hitSelections) then {
_newDamage = _damage - (_unit getHitPointDamage (_hitPoints select (_hitSelections find _selectionName)));
};
// we want to move damage to another selection; have to do it ourselves.
// this is only the case for limbs, so this will not impact the killed EH.
if (_selectionName != (_this select 1)) then {
_unit setHitPointDamage [_hitPoints select (_hitSelections find _selectionName), _damage + _newDamage];
_newDamage = 0;
};
_damage = _damage + _newDamage;
// From AGM medical:
// Exclude falling damage to everything other than legs; reduce structural damage.
if (((velocity _unit) select 2 < -5) && (vehicle _unit == _unit)) then {
_unit setVariable [QGVAR(isFalling), True];
};
if (_unit getVariable [QGVAR(isFalling), false] && !(_selectionName in ["", "leg_l", "leg_r"])) exitWith {};
if (_unit getVariable [QGVAR(isFalling), false]) then {
_newDamage = _newDamage * 0.7;
};
// Finished with the current frame, reset variables
// Note: sometimes handleDamage spans over 2 or even 3 frames.
if (diag_frameno > (_unit getVariable [QGVAR(frameNo), -3]) + 2) then {
_unit setVariable [QGVAR(frameNo), diag_frameno];
// handle the cached damages 3 frames later
[{
_args = _this select 0;
_unit = _args select 0;
_frameNo = _args select 1;
if (diag_frameno > _frameNo + 2) then {
_cache_projectiles = _unit getVariable [QGVAR(cachedProjectiles), []];
_cache_hitpoints = _unit getVariable [QGVAR(cachedHitPoints), []];
_cache_damages = _unit getVariable [QGVAR(cachedDamages), []];
_cache_params = _unit getVariable [QGVAR(cachedHandleDamageParams), []];
{
if (typeName _x == typeName "") then {
(_cache_params select _foreachIndex) call FUNC(handleDamage);
};
}foreach _cache_projectiles;
[(_this select 1)] 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), []];
};
// Make sure there's only one damaged selection per projectile per frame.
_cache_projectiles = _unit getVariable QGVAR(cachedProjectiles);
_cache_hitpoints = _unit getVariable QGVAR(cachedHitPoints);
_cache_damages = _unit getVariable QGVAR(cachedDamages);
_cache_params = _unit getVariable QGVAR(cachedHandleDamageParams);
// Caching of the damage events
if (_selectionName != "") then {
// Check if the current projectile has already been handled once
if (_projectile in _cache_projectiles) then {
// if it has been handled, find the index in the cache
_index = _cache_projectiles find _projectile;
// Find the previous damage this projectile has done
_otherDamage = (_cache_damages select _index);
// Take the highest damage of the two
if (_otherDamage > _newDamage) then {
_newDamage = 0;
} else {
// 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];
// Make entry unfindable and add the new damage cache
_cache_projectiles set [_index, objNull];
_cache_projectiles pushBack _projectile;
_cache_hitpoints pushBack (_hitPoints select (_hitSelections find _selectionName));
_cache_damages pushBack _newDamage;
_cache_params pushBack [_unit, _selectionName, _damage, _source, _projectile];
};
} else {
// This is an unhandled projectile
_cache_projectiles pushBack _projectile;
_cache_hitpoints pushBack (_hitPoints select (_hitSelections find _selectionName));
_cache_damages pushBack _newDamage;
_cache_params pushBack [_unit, _selectionName, _damage, _source, _projectile];
};
};
// 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];

View File

@ -0,0 +1,55 @@
/*
* Author: KoffeinFlummi
*
* Checks the unit for leg and arm damage, and removes orphan structural damage.
*
* Arguments:
+ 0: Unit
* 1: Leg Damage
* 2: Arm Damage
* 3: Remove orphan damage? (Bool; optional, default No)
*
* Return Value:
* None
*/
#define LEGDAMAGETRESHOLD1 1
#define LEGDAMAGETRESHOLD2 1.7
#define ARMDAMAGETRESHOLD1 1
#define ARMDAMAGETRESHOLD2 1.7
private ["_unit", "_legdamage", "_armdamage", "_damagesum"];
_unit = _this select 0;
_legdamage = _this select 1;
_armdamage = _this select 2;
// Leg Damage
// lightly wounded, only limit walking speed (forceWalk is for suckers)
if (_legdamage >= LEGDAMAGETRESHOLD1) then {
if (_unit getHitPointDamage "HitLegs" != 1) then {_unit setHitPointDamage ["HitLegs", 1]};
} else {
if (_unit getHitPointDamage "HitLegs" != 0) then {_unit setHitPointDamage ["HitLegs", 0]};
};
// @ŧodo: force prone for completely fucked up legs.
// Arm Damage
// fx only
if (_armdamage >= ARMDAMAGETRESHOLD1) then {
if (_unit getHitPointDamage "HitHands" != 1) then {_unit setHitPointDamage ["HitHands", 1]};
} else {
if (_unit getHitPointDamage "HitHands" != 0) then {_unit setHitPointDamage ["HitHands", 0]};
};
// remove leftover structural damage if unit is already fully healed
if (count _this > 3 and _this select 3) then {
_damagesum = (_unit getHitPointDamage "HitHead") +
(_unit getHitPointDamage "HitBody") +
(_unit getHitPointDamage "HitLeftArm") +
(_unit getHitPointDamage "HitRightArm") +
(_unit getHitPointDamage "HitLeftLeg") +
(_unit getHitPointDamage "HitRightLeg");
if (_damagesum <= 0.06) then {
_unit setDamage 0;
};
};

View File

@ -0,0 +1,83 @@
/**
* fnc_onDamage.sqf
* @Descr: Called when some dude gets shot. Or stabbed. Or blown up. Or pushed off a cliff. Or hit by a car. Or burnt. Or poisoned. Or gassed. Or cut. You get the idea.
* @Author: KoffeinFlummi
*
* @Arguments: [unit OBJECT, selection STRING, damagE NUMBER, source OBJECT, projectile STRING (Could be an OBJECT on occasion)]
* @Return: damage value to be inflicted
* @PublicAPI: false
*/
#include "script_component.hpp"
#define ARMOURCOEF 2
private ["_unit", "_selectionName", "_damage", "_source", "_source", "_projectile", "_hitSelections", "_hitPoints", "_newDamage", "_found", "_cache_projectiles", "_cache_hitpoints", "_cache_damages"];
_unit = _this select 0;
_selectionName = _this select 1;
_damage = _this select 2;
_source = _this select 3;
_projectile = _this select 4;
if (!([_unit] call FUNC(hasMedicalEnabled))) exitwith {
call FUNC(handleDamage); // let it run through the damage threshold script
};
// Otherwise we carry on with collecting the necessary information
if (typeName _projectile == "OBJECT") then {
_projectile = typeOf _projectile;
};
// This seems to only show up in MP too, but since it doesn't
// collide with anything, I'll check it in SP as well.
if (_selectionName == "r_femur_hit") then {
_selectionName = "leg_r";
};
// If the damage is being weird, we just tell it to fuck off.
if !(_selectionName in ["head", "body", "hand_l", "hand_r", "leg_l", "leg_r"]) exitWith {0.01};
// Cache the handleDamage call
[_unit, _selectionName, _damage, _source, _projectile] call FUNC(cacheHandledamageCall);
// Checking if we should return full damage or not
if (_damage > 0.95) then {
_damage = 0.95;
};
// Check if a unit would die from this hit
if (alive _unit && (vehicle _unit == _unit) && {alive (vehicle _unit)}) then {
_bodyPartn = [_selectionName] call FUNC(getBodyPartNumber);
// Find the correct Damage threshold for unit.
_damageThreshold = [1,1,1];
if (isPlayer _unit) then {
_damageThreshold =_unit getvariable[QGVAR(unitDamageThreshold), [GVAR(damageThreshold_Players), GVAR(damageThreshold_Players), GVAR(damageThreshold_Players)]];
} else {
_damageThreshold =_unit getvariable[QGVAR(unitDamageThreshold), [GVAR(damageThreshold_AI), GVAR(damageThreshold_AI), GVAR(damageThreshold_AI)]];
};
_damageBodyPart = ([_unit,QGVAR(bodyPartStatus),[0,0,0,0,0,0]] call EFUNC(common,getDefinedVariable)) select _bodyPartn;
// Check if damage to body part is higher as damage head
if (_bodyPartn == 0) exitwith {
if (_damageBodyPart >= ((_damageThreshold select 0) + _newDamage) && {(random(1) > 0.2)}) then {
_damage = 1;
};
};
// Check if damage to body part is higher as damage torso
if (_bodyPartn == 1) exitwith {
if (_damageBodyPart >= ((_damageThreshold select 1) + _newDamage) && {(random(1) > 0.2)}) then {
_damage = 1;
};
};
// Check if damage to body part is higher as damage limbs
if (_damageBodyPart >= ((_damageThreshold select 2) + _newDamage) && {(random(1) > 0.95)}) then {
_damage = 1;
};
} else {
_damage = 1;
};
_damage

View File

@ -21,7 +21,7 @@ if !(_unit isKindOf "CAManBase") exitwith{};
_unit addEventhandler["handleDamage", {
if ((missionNamespace getvariable[QGVAR(setting_AdvancedLevel), 0]) >= 0) then {
call FUNC(handleDamage);
call FUNC(onDamage); // cache damage and pass it to handleDamage function
};
}];