mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
176 lines
5.9 KiB
Plaintext
176 lines
5.9 KiB
Plaintext
#include "..\script_component.hpp"
|
|
/*
|
|
* Author: Jaynus, NouberNou, Lambda.Tiger
|
|
* This function creates fragments targeted at specific entities, up to
|
|
* a configured maximum
|
|
*
|
|
* Arguments:
|
|
* 0: Position of fragmenting projectile ASL <ARRAY>
|
|
* 1: Velocity of the fragmenting projectile <ARRAY>
|
|
* 2: Maximum range of fragments to calculate <SCALAR>
|
|
* 3: Maximum number of fragments to produce <SCALAR>
|
|
* 4: Types of fragments <ARRAY>
|
|
* 5: A modified parameter used to calulate whether a framgent hits <SCALAR>
|
|
* 6: Shot parent <ARRAY>
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*
|
|
* Example:
|
|
* [getPosASL _proj, velocity _proj, 50, 50, [], 1, [player, player]] call ace_frag_fnc_doFragTargeted;
|
|
*
|
|
* Public: No
|
|
*/
|
|
|
|
params [
|
|
"_posASL",
|
|
["_fragVel", 800, [123]],
|
|
["_fragRange", 50, [123]],
|
|
["_maxFrags", 20, [123]],
|
|
["_fragTypes", [], [[]]],
|
|
["_modFragCount", 1, [123]],
|
|
["_shotPrnt", [objNull, objNull], [[]], [2]]
|
|
];
|
|
TRACE_5("fnc_doFragTargeted", _posASL, _fragRange, _maxFrags, _fragTypes, _modFragCount);
|
|
|
|
if (_fragTypes isEqualTo []) then {
|
|
_fragTypes = [
|
|
QGVAR(tiny), QGVAR(tiny), QGVAR(tiny),
|
|
QGVAR(tiny_HD), QGVAR(tiny_HD), QGVAR(tiny_HD),
|
|
QGVAR(small), QGVAR(small), QGVAR(small), QGVAR(small),
|
|
QGVAR(small_HD), QGVAR(small_HD), QGVAR(small_HD), QGVAR(small_HD),
|
|
QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD)
|
|
];
|
|
};
|
|
|
|
private _objects = (ASLToATL _posASL) nearEntities [["Car", "Motorcycle", "Tank", "StaticWeapon", "CAManBase", "Air", "Ship"], _fragRange];
|
|
if (_objects isEqualTo []) exitWith {
|
|
TRACE_2("No nearby targets", _posASL, _fragRange);
|
|
0;
|
|
};
|
|
|
|
|
|
// grab crews and add them in so that targets stay approx. sorted by distance
|
|
{
|
|
private _crew = (crew _x);
|
|
if (count _crew > 1) then {
|
|
private _arr = [_x];
|
|
{
|
|
_arr pushBackUnique _x;
|
|
} forEach _crew;
|
|
|
|
_objects set [_forEachIndex, _arr];
|
|
};
|
|
} forEach _objects;
|
|
_objects = flatten _objects; // flatten out sub arrays
|
|
TRACE_3("Targets found", _posASL, _fragRange, count _objects);
|
|
|
|
// limit number of fragments per direction (2D) to 10 using _fragArcs
|
|
private _fragArcs = createHashMap;
|
|
private _fragCount = 0; // limit of # of fragments to _maxFrags
|
|
{
|
|
if (!alive _x) then {continue};
|
|
private _target = _x;
|
|
|
|
#ifdef DEBUG_MODE_DRAWFRAG
|
|
[_target, false] call FUNC(dev_trackHitBox);
|
|
#endif
|
|
|
|
// Calculate volume and height of target
|
|
private _vol = 1.5;
|
|
private _height = 0;
|
|
private _crossSectionArea = 1;
|
|
private _isPerson = _target isKindOf "CAManBase";
|
|
if (_isPerson) then {
|
|
private _stance = stance _target;
|
|
switch (true) do {
|
|
case (_stance isEqualTo "STAND"): {_height = 1.9; _crossSectionArea = 1.5;};
|
|
case (_stance isEqualTo "CROUCH"): {_height = 1.2; _crossSectionArea = 1;};
|
|
default {_height = 0.5; _crossSectionArea = 0.75;};
|
|
};
|
|
} else {
|
|
private _boxParams = boundingBoxReal [_target, "FireGeometry"];
|
|
_boxParams params ["_pointA", "_pointB"];
|
|
private _dims = _pointB vectorDiff _pointA;
|
|
_vol = (_dims#0) * (_dims#1) * (_dims#2);
|
|
_crossSectionArea = (_dims#1)*(_dims#2);
|
|
_height = _dims#2;
|
|
};
|
|
|
|
if (_vol <= 0.5) then {continue}; // too small => exit
|
|
|
|
|
|
private _distance = _target distance _posASL;
|
|
|
|
// calculate chance to be hit by a fragment
|
|
private _fragChance = _crossSectionArea*_modFragCount/(_distance^2);
|
|
private _count = if (_fragChance > 1) then {
|
|
3 min (floor _fragChance);
|
|
} else {
|
|
[0, 1] select (GVAR(atLeastOne) || {random 1 < _fragChance});
|
|
};
|
|
if (_count == 0) then {TRACE_2("fragments",_fragChance,_count); continue};
|
|
|
|
// Approximate offset to hit including speed & gravity
|
|
private _locFragVel = _fragVel * (1 - random 0.5);
|
|
private _tof = _distance / _locFragVel;
|
|
private _targetPos = (velocity _target vectorMultiply _tof) vectorAdd [0, 0, 9.81 / 2 * _tof ^ 2];
|
|
|
|
// handle limiting fragments per dewgree arc
|
|
private _dir = floor (_posASL getDir _target);
|
|
private _fragPerArc = _fragArcs getOrDefault [_dir, 0];
|
|
if (_fragPerArc > 10) then {
|
|
continue;
|
|
} else {
|
|
_fragArcs set [_dir, _fragPerArc + _count];
|
|
};
|
|
|
|
// actual target pos for fragment to hit
|
|
if _isPerson then {
|
|
private _hitPoint = selectRandom ACE_FRAG_HITPOINTS;
|
|
private _hitPointPos = _target selectionPosition [_hitPoint, "HitPoints", "AveragePoint"];
|
|
_targetPos = _target modelToWorldWorld _hitPointPos;
|
|
} else {
|
|
_targetPos = getPosASL _target vectorAdd [
|
|
-0.5 + random 1,
|
|
-0.5 + random 1,
|
|
(0.1 + random 0.4) * _height
|
|
];
|
|
};
|
|
|
|
// select a fragment / submunition frag spawner
|
|
private _fragSpawner = selectRandom _fragTypes;
|
|
if (_count > 1) then {
|
|
_fragSpawner = _fragSpawner + "_spawner_" + str _count + (switch (true) do {
|
|
case (_distance < 10): {"_short"};
|
|
case (_distance < 20): {"_mid"};
|
|
default {"_far"};
|
|
});
|
|
};
|
|
|
|
TRACE_4("fragments",_fragSpawner,_fragChance,_distance,_locFragVel);
|
|
|
|
// Create fragment
|
|
private _vecDir = _posASL vectorFromTo _targetPos;
|
|
private _fragObj = createVehicle [_fragSpawner, ASLtoATL _posASL, [], 0, "CAN_COLLIDE"];
|
|
_fragObj setVectorDir _vecDir;
|
|
_fragObj setVelocity (_vecDir vectorMultiply _locFragVel);
|
|
_fragObj setShotParents _shotPrnt;
|
|
#ifdef DEBUG_MODE_DRAW
|
|
[_fragObj, "purple", true] call FUNC(dev_trackObj);
|
|
if (GVAR(dbgSphere)) then {
|
|
[_targetPos, "orange"] call FUNC(dev_sphereDraw);
|
|
};
|
|
#endif
|
|
|
|
_fragCount = _fragCount + _count;
|
|
if (_fragCount >= _maxFrags) then {
|
|
TRACE_2("maxFrags", _fragCount, _maxFrags);
|
|
break
|
|
};
|
|
} forEach _objects;
|
|
#ifdef DEBUG_MODE_FULL
|
|
systemChat ("fragCount cnt: " + str _fragCount);
|
|
#endif
|
|
TRACE_1("fragCount",_fragCount);
|
|
_fragCount |