mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Combined medium and advanced into one, with options to turn on other features.
Changed wounds for a more diverse variation. Added handleDamage caching for advanced.
This commit is contained in:
parent
a609d00730
commit
5b507ed9f5
@ -22,24 +22,33 @@
|
||||
*/
|
||||
#define DEFAULT_CARDIAC_OUTPUT 5.25
|
||||
|
||||
private ["_totalBloodLoss","_tourniquets","_openWounds", "_value", "_cardiacOutput"];
|
||||
private ["_totalBloodLoss","_tourniquets","_openWounds", "_value", "_cardiacOutput", "_internalWounds"];
|
||||
|
||||
|
||||
// TODO Only use this calculation if medium or higher, otherwise use vanilla calculations (for basic medical).
|
||||
_totalBloodLoss = 0;
|
||||
|
||||
// Advanced medical bloodloss handling
|
||||
if (GVAR(level) >= 1) then {
|
||||
_tourniquets = _this getvariable [QGVAR(tourniquets), [0,0,0,0,0,0]];
|
||||
_openWounds = _this getvariable [QGVAR(openWounds), []];
|
||||
//_cardiacOutput = [_this] call FUNC(getCardiacOutput);
|
||||
|
||||
{
|
||||
if ((_tourniquets select (_x select 2)) < 1) then {
|
||||
// total bleeding ratio * percentage of injury left
|
||||
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
|
||||
|
||||
_totalBloodLoss = _totalBloodLoss + ([BLOODLOSS_SMALL_WOUNDS, BLOODLOSS_MEDIUM_WOUNDS, BLOODLOSS_LARGE_WOUNDS] select (_x select 1));
|
||||
// (((BLOODLOSS_SMALL_WOUNDS * (_x select 0))) + ((BLOODLOSS_MEDIUM_WOUNDS * (_x select 1))) + ((BLOODLOSS_LARGE_WOUNDS * (_x select 2))) * (_cardiacOutput / DEFAULT_CARDIAC_OUTPUT));
|
||||
};
|
||||
}foreach _openWounds;
|
||||
|
||||
_internalWounds = _this getvariable [QGVAR(internalWounds), []];
|
||||
{
|
||||
_totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
|
||||
}foreach _internalWounds;
|
||||
|
||||
// cap the blood loss to be no greater as the current cardiac output
|
||||
//(_totalBloodLoss min _cardiacOutput);
|
||||
|
||||
};
|
||||
_totalBloodLoss;
|
@ -45,18 +45,18 @@ if (isNil QGVAR(level)) then {
|
||||
};
|
||||
|
||||
_damageReturn = (_this select 2);
|
||||
_typeOfDamage = [_this select 4] call FUNC(getTypeOfDamage);
|
||||
|
||||
if (GVAR(level) >= 0) then {
|
||||
_damageReturn = (_this + [_damageReturn, _typeOfDamage]) call FUNC(handleDamage_basic);
|
||||
if (GVAR(level) == 0) then {
|
||||
_damageReturn = (_this + [_damageReturn]) call FUNC(handleDamage_basic);
|
||||
};
|
||||
|
||||
if (_damageReturn < 0.01) exitWith {0};
|
||||
|
||||
if (GVAR(level) >= 1) then {
|
||||
_damageReturn = (_this + [_damageReturn, _typeOfDamage]) call FUNC(handleDamage_medium);
|
||||
if (GVAR(level) >= 2) then {
|
||||
_damageReturn = (_this + [_damageReturn, _typeOfDamage]) call FUNC(handleDamage_advanced);
|
||||
[_unit, _selectionName, _damage, _source, _projectile, _damageReturn] call FUNC(handleDamage_caching);
|
||||
|
||||
// TODO check if this should would have killed the unit..
|
||||
if (_damageReturn > 0.95) then {
|
||||
_damageReturn = 0.95;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,9 @@ _amountOfDamage = _this select 2;
|
||||
_sourceOfDamage = _this select 3;
|
||||
_typeOfProjectile = _this select 4;
|
||||
_returnDamage = _this select 5;
|
||||
_typeOfDamage = _this select 6; //[_typeOfProjectile] call FUNC(getTypeOfDamage);
|
||||
_typeOfDamage = [_typeOfProjectile] call FUNC(getTypeOfDamage);
|
||||
|
||||
[_unit, _selectionName, _amountOfDamage, _typeOfProjectile, _typeOfDamage] call FUNC(handleDamage_wounds);
|
||||
|
||||
if (GVAR(enableAirway)) then {
|
||||
[_unit,_selectionName,_amountOfDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_airway);
|
||||
|
136
addons/medical/functions/fnc_handleDamage_caching.sqf
Normal file
136
addons/medical/functions/fnc_handleDamage_caching.sqf
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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: Current damage to be returned <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* <nil>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_unit", "_selectionName","_damage", "_source","_projectile","_hitSelections","_hitPoints","_newDamage","_cache_hitpoints","_cache_projectiles","_cache_params","_cache_damages"];
|
||||
_unit = _this select 0;
|
||||
_selectionName = _this select 1;
|
||||
_damage = _this select 2;
|
||||
_source = _this select 3;
|
||||
_projectile = _this select 4;
|
||||
_returnDamage = _this select 5;
|
||||
|
||||
_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_damageCaching), -3]) + 2) then {
|
||||
_unit setVariable [QGVAR(frameNo_damageCaching), diag_frameno];
|
||||
|
||||
// handle the cached damages 3 frames later
|
||||
[{
|
||||
private ["_args","_unit","_frameNo"];
|
||||
_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_advanced);
|
||||
};
|
||||
}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 {
|
||||
private ["_index","_otherDamage"];
|
||||
// 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 {
|
||||
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];
|
||||
|
||||
// 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];
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Author: Glowbal
|
||||
* Medium 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 <STRING>
|
||||
* 5: Current damage to be returned <NUMBER>
|
||||
* 6: Type of Damage <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* Damage To Be Inflicted <NUMBER>
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_unit","_selectionName","_amountOfDamage","_sourceOfDamage","_typeOfProjectile","_typeOfDamage"];
|
||||
_unit = _this select 0;
|
||||
_selectionName = _this select 1;
|
||||
_amountOfDamage = _this select 2;
|
||||
_sourceOfDamage = _this select 3;
|
||||
_typeOfProjectile = _this select 4;
|
||||
_returnDamage = _this select 5;
|
||||
_typeOfDamage = _this select 6; //[_typeOfProjectile] call FUNC(getTypeOfDamage);
|
||||
|
||||
if (GVAR(enableAirway)) then {
|
||||
[_unit,_selectionName,_amountOfDamage,_sourceOfDamage, _typeOfDamage] call FUNC(handleDamage_wounds);
|
||||
};
|
||||
|
||||
_returnDamage;
|
@ -16,64 +16,127 @@
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
#define RANDOM_BODY_PART round(random(6))
|
||||
#define RANDOM_OPEN_WOUND (1 + round(random(2)))
|
||||
#define ADD_INJURY(BODYPART,TYPE,AMOUNT) _woundID = 1; \
|
||||
_amountOf = count _openWounds; \
|
||||
if (_amountOf > 0) then { _woundID = (_openWounds select (_amountOf - 1) select 0) + 1; }; \
|
||||
for "_i" from 1 to AMOUNT /* step +1 */ do { \
|
||||
_openWounds pushback [_woundID, _woundType, _bodyPartn, 1 /* percentage treated */]; \
|
||||
_openWounds pushback [_woundID, _woundType, BODYPART, 1 /* percentage treated */, FIND_BLEEDING_RATE(TYPE)]; \
|
||||
_woundID = _woundID + 1; \
|
||||
};
|
||||
|
||||
private ["_unit", "_selectionName", "_amountOfDamage", "_sourceOfDamage", "_typeOfDamage", "_bodyPartn", "_woundType"];
|
||||
private ["_unit", "_selectionName", "_damage", "_typeOfProjectile", "_typeOfDamage", "_bodyPartn", "_woundType"];
|
||||
_unit = _this select 0;
|
||||
_selectionName = _this select 1;
|
||||
_amountOfDamage = _this select 2;
|
||||
_sourceOfDamage = _this select 3;
|
||||
_damage = _this select 2;
|
||||
_typeOfProjectile = _this select 3;
|
||||
_typeOfDamage = _this select 4;
|
||||
_bodyPartn = [_selectionName] call FUNC(selectionNameToNumber);
|
||||
|
||||
_woundType = 1;
|
||||
if (_amountOfDamage > 0.05) then {
|
||||
if (_damage > 0.05) then {
|
||||
private ["_wounds", "_woundID", "_amountOf"];
|
||||
_openWounds = _unit getvariable[QGVAR(openWounds), []];
|
||||
|
||||
// TODO specify openWounds based off typeOfInjury details better.
|
||||
switch (toLower _typeOfInjury) do {
|
||||
case "bullet": {
|
||||
ADD_INJURY(_bodyPartn, round(random(2)), 1);
|
||||
if (_damage < 0.1) exitwith {
|
||||
if (random(1) => 0.5) then {
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(_bodyPartn, SCRATCH, 1);
|
||||
} else {
|
||||
ADD_INJURY(_bodyPartn, BRUISES, 1); // didn't do much damage, so the skin got only bruised.
|
||||
};
|
||||
} else {
|
||||
ADD_INJURY(_bodyPartn, GRAZE_WOUND, 1);
|
||||
};
|
||||
};
|
||||
// TODO base upon caliber of the round and damage done, using _typeOfProjectile and CfgAmmo class.
|
||||
switch (true) do {
|
||||
case (_damage >= 1.2): {ADD_INJURY(_bodyPartn, LARGE_OPEN_WOUND, 1);};
|
||||
case (_damage >= 0.7): {ADD_INJURY(_bodyPartn, MEDIUM_OPEN_WOUND, 1);};
|
||||
default {ADD_INJURY(_bodyPartn, MINOR_OPEN_WOUND, 1);};
|
||||
};
|
||||
};
|
||||
case "grenade": {
|
||||
ADD_INJURY(_bodyPartn, round(random(2)), 1);
|
||||
if (_damage < 0.1) exitwith {
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, BRUISES, 1);
|
||||
} else {
|
||||
ADD_INJURY(RANDOM_BODY_PART, GRAZE_WOUND, 1);
|
||||
};
|
||||
};
|
||||
for "_i" from 0 to round(random(3)) /* step +1 */ do {
|
||||
ADD_INJURY(round(random(6)), round(random(2)), 1);
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, RANDOM_OPEN_WOUND, 1);
|
||||
} else {
|
||||
ADD_INJURY(RANDOM_BODY_PART, SCHRAPNEL_WOUND, 1);
|
||||
};
|
||||
};
|
||||
};
|
||||
case "explosive": {
|
||||
ADD_INJURY(_bodyPartn, round(random(2)), 1);
|
||||
if (_damage < 0.1) exitwith {
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, BRUISES, 1);
|
||||
} else {
|
||||
ADD_INJURY(RANDOM_BODY_PART, GRAZE_WOUND, 1);
|
||||
};
|
||||
};
|
||||
|
||||
ADD_INJURY(RANDOM_BODY_PART, RANDOM_OPEN_WOUND, 1);
|
||||
for "_i" from 0 to round(random(4)) /* step +1 */ do {
|
||||
ADD_INJURY(round(random(6)), round(random(2)), 1);
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, SCHRAPNEL_WOUND, 1);
|
||||
};
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, RANDOM_OPEN_WOUND, 1);
|
||||
}:
|
||||
};
|
||||
};
|
||||
case "shell": {
|
||||
ADD_INJURY(_bodyPartn, round(random(2)), 1);
|
||||
for "_i" from 0 to round(random(5)) /* step +1 */ do {
|
||||
ADD_INJURY(round(random(6)), round(random(2)), 1);
|
||||
if (_damage < 0.1) exitwith {
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, BRUISES, 1);
|
||||
} else {
|
||||
ADD_INJURY(RANDOM_BODY_PART, GRAZE_WOUND, 1);
|
||||
};
|
||||
};
|
||||
|
||||
ADD_INJURY(RANDOM_BODY_PART, RANDOM_OPEN_WOUND, 1);
|
||||
for "_i" from 0 to round(random(5)) /* step +1 */ do {
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, SCHRAPNEL_WOUND, 1);
|
||||
};
|
||||
if (random(1) => 0.5) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, RANDOM_OPEN_WOUND, 1);
|
||||
}:
|
||||
};
|
||||
|
||||
};
|
||||
case "backblast": {
|
||||
if (random(1)>=0.5) then {
|
||||
ADD_INJURY(_bodyPartn, round(random(2)), 1);
|
||||
ADD_INJURY(RANDOM_BODY_PART, BRUISES, 1);
|
||||
};
|
||||
};
|
||||
case "unknown": {
|
||||
ADD_INJURY(_bodyPartn, round(random(1)), 1);
|
||||
ADD_INJURY(_bodyPartn, RANDOM_OPEN_WOUND, 1);
|
||||
};
|
||||
case "vehiclecrash": {
|
||||
if (random(1)>=0.5) then {
|
||||
ADD_INJURY(_bodyPartn, round(random(1)), 1);
|
||||
ADD_INJURY(_bodyPartn, RANDOM_OPEN_WOUND, 1);
|
||||
};
|
||||
for "_i" from 0 to round(random(5)) /* step +1 */ do {
|
||||
if (random(_damage) => 0.25) then {
|
||||
ADD_INJURY(RANDOM_BODY_PART, BRUISES, 1);
|
||||
};
|
||||
};
|
||||
};
|
||||
default {
|
||||
ADD_INJURY(_bodyPartn, round(random(1)), 1);
|
||||
ADD_INJURY(_bodyPartn, RANDOM_OPEN_WOUND, 1);
|
||||
// TODO allow third party to handle this instead ?
|
||||
};
|
||||
};
|
||||
_unit setvariable [GVAR(openWounds), _openWounds, true];
|
||||
|
@ -68,7 +68,7 @@ if ([_unit] call EFUNC(common,isAwake)) then {
|
||||
};
|
||||
|
||||
// handle advanced medical, with vitals
|
||||
if ((missionNamespace getvariable[QGVAR(setting_AdvancedLevel), 0]) > 0) exitwith {
|
||||
if ((missionNamespace getvariable[QGVAR(level), 0]) > 0) exitwith {
|
||||
|
||||
// Set the vitals
|
||||
_heartRate = (_unit getvariable [QGVAR(heartRate), 0]) + ([_unit] call FUNC(getHeartRateChange));
|
||||
|
Loading…
Reference in New Issue
Block a user