mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Added AGM handleDamage caching
This commit is contained in:
parent
23f8b8a9ad
commit
68ab7b5143
@ -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;
|
||||
|
126
addons/medical/functions/fnc_cacheHandleDamageCall.sqf
Normal file
126
addons/medical/functions/fnc_cacheHandleDamageCall.sqf
Normal 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];
|
55
addons/medical/functions/fnc_checkDamage.sqf
Normal file
55
addons/medical/functions/fnc_checkDamage.sqf
Normal 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;
|
||||
};
|
||||
};
|
83
addons/medical/functions/fnc_onDamage.sqf
Normal file
83
addons/medical/functions/fnc_onDamage.sqf
Normal 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
|
@ -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
|
||||
};
|
||||
}];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user