mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Medical - Add damage handling for explosive damage while inside vehicles (#9246)
* Add vehicle explosion handling * Missing semicolon * scale armor damage using passthrough * add - to comment Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com> * improve condition Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com> * remove extra brackets Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com> * remove extra brackets * fix damage sorting * whitespace * comment * fix function header * fix infinite armor when no item equipped * modify condition & handling for vehicle explosion * add vehiclehit woundHandler * finalize * add vehiclehit woundHandler * finalize * cleanup * more cleanup * name * randomize hitpoints * finalize * don't scale structural damage * fix undefined var * remove _i * fix script error, tone down scaling * add AVD checks * Update addons/medical_damage/functions/fnc_woundsHandlerVehiclehit.sqf Co-authored-by: PabstMirror <pabstmirror@gmail.com> * nuke AVD crew damage handling * get rid of aircraft crash lethality compensation --------- Co-authored-by: James Woods <pterolatypus@gmail.com> Co-authored-by: GhostIsSpooky <69561145+Salluci@users.noreply.github.com> Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com> Co-authored-by: PabstMirror <pabstmirror@gmail.com>
This commit is contained in:
parent
94f3b301e0
commit
aee47c9bc6
@ -167,6 +167,13 @@ class ACE_Medical_Injuries {
|
||||
painMultiplier = 0.9;
|
||||
};
|
||||
};
|
||||
class vehiclehit: explosive {
|
||||
// vehicle explosions are usually caused by explosive damage and should behave similarly
|
||||
thresholds[] = {{6, 3}, {4.5, 2}, {2, 2}, {0.8, 1}, {0.2, 1}, {0, 0}};
|
||||
class woundHandlers: woundHandlers {
|
||||
GVAR(vehiclehit) = QFUNC(woundsHandlerVehiclehit);
|
||||
};
|
||||
};
|
||||
class vehiclecrash {
|
||||
thresholds[] = {{1.5, 3}, {1.5, 2}, {1, 2}, {1, 1}, {0.05, 1}}; // prevent subdividing wounds past FRACTURE_DAMAGE_THRESHOLD to ensure limp/fractue is triggered
|
||||
selectionSpecific = 0;
|
||||
|
@ -9,3 +9,4 @@ PREP(woundReceived);
|
||||
PREP(woundsHandlerBase);
|
||||
PREP(woundsHandlerBurning);
|
||||
PREP(woundsHandlerVehiclecrash);
|
||||
PREP(woundsHandlerVehiclehit);
|
||||
|
@ -0,0 +1,37 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: Pterolatypus, LinkIsGrim
|
||||
* Custom wound handler for vehicle hits and explosions, sends damage to a random hitpoint
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit That Was Hit <OBJECT>
|
||||
* 1: Damage done to each body part <ARRAY>
|
||||
* 2: Type of the damage done <STRING>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [player, [[0.5, "#structural", 1.5]], "vehiclehit"] call ace_medical_damage_fnc_woundsHandlerVehiclehit
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
params ["_unit", "_allDamages", "_typeOfDamage"];
|
||||
TRACE_3("woundsHandlerVehiclehit",_unit,_allDamages,_typeOfDamage);
|
||||
|
||||
// this should only trigger for hits to just structural
|
||||
if (count _allDamages > 1) exitWith {_this};
|
||||
|
||||
// damage can sometimes be negative (why?)
|
||||
// damage to structural is low unless it's a very large explosion, in which case it is typically >= 1
|
||||
private _damageToApply = (abs (_allDamages select 0 select 0));
|
||||
|
||||
private _newDamages = [];
|
||||
|
||||
// hitpoints are randomized, more damage means more wounds in different body parts
|
||||
for "_i" from 1 to (_damageToApply * 6) do {
|
||||
_newDamages pushBack [_damageToApply, selectRandom ALL_BODY_PARTS, _damageToApply]
|
||||
};
|
||||
|
||||
TRACE_1("Vehicle explosion handled, passing damage", _newDamages);
|
||||
[_unit, _newDamages, _typeOfDamage] //return
|
@ -61,20 +61,6 @@
|
||||
};
|
||||
}] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
// Guarantee aircraft crashes are more lethal
|
||||
["Air", "Killed", {
|
||||
params ["_vehicle", "_killer"];
|
||||
TRACE_3("air killed",_vehicle,typeOf _vehicle,velocity _vehicle);
|
||||
if ((getText (configOf _vehicle >> "destrType")) == "") exitWith {};
|
||||
if (unitIsUAV _vehicle) exitWith {};
|
||||
|
||||
private _lethality = linearConversion [0, 25, (vectorMagnitude velocity _vehicle), 0.5, 1];
|
||||
TRACE_2("air crash",_lethality,crew _vehicle);
|
||||
{
|
||||
[QEGVAR(medical,woundReceived), [_x, [[_lethality, "Head", _lethality]], _killer, "#vehiclecrash"], _x] call CBA_fnc_targetEvent;
|
||||
} forEach (crew _vehicle);
|
||||
}, true, ["ParachuteBase"]] call CBA_fnc_addClassEventHandler;
|
||||
|
||||
// Fixes units being stuck in unconscious animation when being knocked over by a PhysX object
|
||||
["CAManBase", "AnimDone", {
|
||||
params ["_unit", "_anim"];
|
||||
|
@ -57,14 +57,16 @@ if (
|
||||
0
|
||||
};
|
||||
|
||||
// Faster than (vehicle _unit), also handles dead units
|
||||
private _vehicle = objectParent _unit;
|
||||
|
||||
// Crashing a vehicle doesn't fire the EH for each hitpoint so the "ace_hdbracket" code never runs
|
||||
// It does fire the EH multiple times, but this seems to scale with the intensity of the crash
|
||||
private _vehicle = vehicle _unit;
|
||||
if (
|
||||
EGVAR(medical,enableVehicleCrashes) &&
|
||||
{_hitPoint isEqualTo "#structural"} &&
|
||||
{_ammo isEqualTo ""} &&
|
||||
{_vehicle != _unit} &&
|
||||
{!isNull _vehicle} &&
|
||||
{vectorMagnitude (velocity _vehicle) > 5}
|
||||
// todo: no way to detect if stationary and another vehicle hits you
|
||||
) exitWith {
|
||||
@ -74,6 +76,29 @@ if (
|
||||
0
|
||||
};
|
||||
|
||||
// Receiving explosive damage inside a vehicle doesn't trigger for each hitpoint
|
||||
// This is the case for mines, explosives, artillery, and catasthrophic vehicle explosions
|
||||
// Triggers twice, but that doesn't matter as damage is low
|
||||
if (
|
||||
_hitPoint isEqualTo "#structural" &&
|
||||
{!isNull _vehicle} &&
|
||||
{_ammo isNotEqualTo ""} &&
|
||||
{
|
||||
private _ammoCfg = configFile >> "CfgAmmo" >> _ammo;
|
||||
GET_NUMBER(_ammoCfg >> "explosive", 0) > 0 ||
|
||||
{GET_NUMBER(_ammoCfg >> "indirectHit", 0) > 0}
|
||||
}
|
||||
) exitwith {
|
||||
TRACE_6("Vehicle hit",_unit,_shooter,_instigator,_damage,_newDamage,_damages);
|
||||
|
||||
_unit setVariable [QEGVAR(medical,lastDamageSource), _shooter];
|
||||
_unit setVariable [QEGVAR(medical,lastInstigator), _instigator];
|
||||
|
||||
[QEGVAR(medical,woundReceived), [_unit, [[_newDamage, _hitPoint, _newDamage]], _shooter, "vehiclehit"]] call CBA_fnc_localEvent;
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
// This hitpoint is set to trigger last, evaluate all the stored damage values
|
||||
// to determine where wounds are applied
|
||||
if (_hitPoint isEqualTo "ace_hdbracket") exitWith {
|
||||
|
@ -5,7 +5,6 @@ PREP(handleVehicleDamage);
|
||||
PREP(handleCookoff);
|
||||
PREP(detonate);
|
||||
PREP(processHit);
|
||||
PREP(injureOccupants);
|
||||
PREP(handleDetonation);
|
||||
PREP(handleDamage);
|
||||
PREP(knockOut);
|
||||
|
@ -1,76 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm
|
||||
* Injures occupants in a vehicle based on percent chance of injury.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: The vehicle <OBJECT>
|
||||
* 1: Injury Chance <NUMBER>
|
||||
* 2: Maximum people to injure <NUMBER>
|
||||
* 3: Projectile source <OBJECT> (default: objNull)
|
||||
* 4: Modifiers for probability for each crew type to be injured. <ARRAY> (In order of: driver, gunner, commander, cargo)
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [myVehicle, 0.6, 10] call ace_vehicle_damage_fnc_injureOccupants;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle", "_chance", "_count", ["_source", objNull], ["_probabilityModifier", [1, 1, 1, 1]]];
|
||||
TRACE_4("adding damage to units", _vehicle, _chance, _count, _source);
|
||||
|
||||
private _vehicleCrew = crew _vehicle;
|
||||
private _crewCount = count _vehicleCrew;
|
||||
if (_crewCount <= 0) exitWith {};
|
||||
|
||||
private _crewInjuryIndices = [];
|
||||
{
|
||||
_crewInjuryIndices pushBack _forEachIndex;
|
||||
} forEach _vehicleCrew;
|
||||
|
||||
_crewInjuryIndices = _crewInjuryIndices call BIS_fnc_arrayShuffle;
|
||||
|
||||
private _injuryCount = 0;
|
||||
// Not actually doing anything to any initial vehicle crew in this forEach - just a way to loop through all crew at least once
|
||||
{
|
||||
private _indexToInjure = -1;
|
||||
{
|
||||
private _modifier = _probabilityModifier select 3;
|
||||
if ((_vehicleCrew select _x) isEqualTo driver _vehicle) then {
|
||||
_modifier = _probabilityModifier select 0;
|
||||
};
|
||||
if ((_vehicleCrew select _x) isEqualTo gunner _vehicle) then {
|
||||
_modifier = _probabilityModifier select 1;
|
||||
};
|
||||
if ((_vehicleCrew select _x) isEqualTo commander _vehicle) then {
|
||||
_modifier = _probabilityModifier select 2;
|
||||
};
|
||||
|
||||
if ((_chance * _modifier) > random 1) exitWith {
|
||||
_indexToInjure = _forEachIndex;
|
||||
};
|
||||
} forEach _crewInjuryIndices;
|
||||
|
||||
if (_indexToInjure >= 0) then {
|
||||
private _casualty = _vehicleCrew select (_crewInjuryIndices select _indexToInjure);
|
||||
if (alive _casualty) then {
|
||||
_injuryCount = _injuryCount + 1;
|
||||
private _indexCount = count _crewInjuryIndices;
|
||||
if (_indexCount >= 0) then {
|
||||
_crewInjuryIndices deleteAt _indexToInjure;
|
||||
|
||||
// arbitrary percentages
|
||||
private _injuredBodyPart = ["Head", "Body", "LeftArm", "RightArm", "LeftLeg", "RightLeg"] selectRandomWeighted [0.3, 0.8, 0.5, 0.5, 0.3, 0.3];
|
||||
private _currentUnitDamage = _casualty getHitpointDamage _injuredBodyPart;
|
||||
private _damageAmount = (_currentUnitDamage + random 1.8) max (_currentUnitDamage + 0.1);
|
||||
|
||||
[_casualty, _damageAmount, _injuredBodyPart, "shell", _source] call EFUNC(medical,addDamageToUnit);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (_injuryCount >= _count) exitWith {};
|
||||
} forEach _vehicleCrew;
|
@ -119,28 +119,6 @@ if (_isCar) then {
|
||||
_ammoEffectiveness = (_ammoEffectiveness + (_ammoEffectiveness * 0.5)) min 1;
|
||||
};
|
||||
|
||||
private _injuryChance = 0;
|
||||
private _injuryCount = 0;
|
||||
switch (_warheadType) do {
|
||||
case WARHEAD_TYPE_AP: {
|
||||
_injuryChance = (_ammoEffectiveness * 2) min 1;
|
||||
_injuryCount = 1 + (_ammoEffectiveness * round random 9);
|
||||
};
|
||||
case WARHEAD_TYPE_HE: {
|
||||
_injuryChance = 0.03 * (1 + _ammoEffectiveness); // spalling injury chance alongside direct hit potential
|
||||
_injuryCount = 2 + (ceil random 3);
|
||||
if (_isCar) then {
|
||||
_injuryChance = 0.8;
|
||||
_injuryCount = 3 max random count crew _vehicle;
|
||||
};
|
||||
};
|
||||
default {
|
||||
_injuryChance = (4 * _ammoEffectiveness) min 1;
|
||||
_injuryCount = 2 + round random 3;
|
||||
};
|
||||
};
|
||||
_injuryChance = _injuryChance * _penChance;
|
||||
|
||||
private _currentVehicleAmmo = [_vehicle] call EFUNC(cookoff,getVehicleAmmo);
|
||||
private _chanceOfDetonation = 0;
|
||||
private _explosiveAmmoCount = 0;
|
||||
@ -200,8 +178,6 @@ switch (_hitArea) do {
|
||||
[_vehicle, _hitIndex, _hitpointName, _nextPartDamage * _penChance] call FUNC(addDamage);
|
||||
};
|
||||
|
||||
// slightly lower injury chance since this hit the engine block
|
||||
[_vehicle, _injuryChance, _injuryCount, _injurer, [0.2, 0.2, 0.2, 0.4]] call FUNC(injureOccupants);
|
||||
[_vehicle, _chanceOfFire, _cookoffIntensity, _injurer, _hitArea, false] call FUNC(handleCookoff);
|
||||
};
|
||||
case "hull": {
|
||||
@ -220,8 +196,6 @@ switch (_hitArea) do {
|
||||
[_vehicle] call FUNC(knockOut);
|
||||
};
|
||||
|
||||
[_vehicle, _injuryChance, _injuryCount, _injurer, [1, 0.4, 0.4, 1]] call FUNC(injureOccupants);
|
||||
|
||||
private _hash = _vehicle getVariable [QGVAR(hitpointHash), []];
|
||||
private _hashKeys = [_hash] call CBA_fnc_hashKeys;
|
||||
|
||||
@ -301,7 +275,6 @@ switch (_hitArea) do {
|
||||
_vehicle setVariable [QGVAR(canShoot), false];
|
||||
};
|
||||
|
||||
[_vehicle, _injuryChance, _injuryCount, _injurer, [0.5, 1.5, 1.5, 0.8]] call FUNC(injureOccupants);
|
||||
[_vehicle, _chanceOfFire, _cookoffIntensity, _injurer, "", true] call FUNC(handleCookoff);
|
||||
};
|
||||
case "gun": {
|
||||
|
Loading…
Reference in New Issue
Block a user