2018-09-17 19:19:29 +00:00
|
|
|
#include "script_component.hpp"
|
2017-04-11 15:33:56 +00:00
|
|
|
/*
|
|
|
|
* Author: Jaynus, NouberNou
|
|
|
|
* Server func to create the fragmentation for a round.
|
|
|
|
*
|
|
|
|
* Arguments:
|
|
|
|
* 0: Last Position (ASL) <ARRAY>
|
|
|
|
* 1: Velocity <ARRAY>
|
|
|
|
* 2: Ammo Classname <STRING>
|
|
|
|
*
|
|
|
|
* Return Value:
|
2017-06-08 13:31:51 +00:00
|
|
|
* None
|
2017-04-11 15:33:56 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* [[], [], "handGrenade"] call ace_frag_fnc_frago
|
|
|
|
*
|
|
|
|
* Public: No
|
|
|
|
*/
|
2016-05-30 16:37:03 +00:00
|
|
|
|
|
|
|
#define FRAG_VEC_VAR 0.004
|
|
|
|
#define MAX_FRAG_COUNT 50
|
|
|
|
|
|
|
|
BEGIN_COUNTER(frago);
|
|
|
|
|
2017-04-11 15:33:56 +00:00
|
|
|
params ["_lastPos", "_lastVel", "_shellType"];
|
|
|
|
TRACE_3("frago",_lastPos,_lastVel,_shellType);
|
|
|
|
|
|
|
|
// Limit max frag count if there was a recent frag
|
|
|
|
private _maxFrags = round (MAX_FRAG_COUNT * linearConversion [0.1, 1.5, (CBA_missionTime - GVAR(lastFragTime)), 0.1, 1, true]);
|
|
|
|
TRACE_2("",_maxFrags,CBA_missionTime - GVAR(lastFragTime));
|
|
|
|
GVAR(lastFragTime) = CBA_missionTime;
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-09-04 14:44:22 +00:00
|
|
|
private _fragTypes = [
|
|
|
|
QGVAR(tiny), QGVAR(tiny), QGVAR(tiny),
|
|
|
|
QGVAR(tiny_HD), QGVAR(tiny_HD), QGVAR(tiny_HD),
|
2016-10-26 22:16:31 +00:00
|
|
|
QGVAR(small), QGVAR(small), QGVAR(small), QGVAR(small),
|
|
|
|
QGVAR(small_HD), QGVAR(small_HD), QGVAR(small_HD), QGVAR(small_HD),
|
2016-09-04 14:44:22 +00:00
|
|
|
QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD)
|
|
|
|
];
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-09-04 14:44:22 +00:00
|
|
|
private _warn = false;
|
2016-10-26 22:16:31 +00:00
|
|
|
if (isArray (configFile >> "CfgAmmo" >> _shellType >> QGVAR(CLASSES))) then {
|
2016-07-20 04:15:18 +00:00
|
|
|
_fragTypes = getArray (configFile >> "CfgAmmo" >> _shellType >> QGVAR(CLASSES));
|
2016-05-30 16:37:03 +00:00
|
|
|
} else {
|
|
|
|
_warn = true;
|
|
|
|
};
|
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
private _indirectHitRange = getNumber(configFile >> "CfgAmmo" >> _shellType >> "indirecthitrange");
|
|
|
|
private _fragRange = 20 * _indirectHitRange * 4;
|
2016-05-30 16:37:03 +00:00
|
|
|
// _c = 185; // grams of comp-b
|
|
|
|
// _m = 210; // grams of fragmentating metal
|
|
|
|
// _k = 3/5; // spherical K factor
|
|
|
|
// _gC = 2843; // Gurney constant of comp-b in /ms
|
|
|
|
|
|
|
|
// _c = 429; // grams of tritonal
|
|
|
|
// _m = 496; // grams of fragmentating metal
|
|
|
|
// _k = 1/2; // spherical K factor
|
|
|
|
// _gC = 2320; // Gurney constant of tritonal in /ms
|
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
private _c = getNumber (configFile >> "CfgAmmo" >> _shellType >> QGVAR(CHARGE));
|
|
|
|
if (_c == 0) then {_c = 1; _warn = true;};
|
|
|
|
private _m = getNumber (configFile >> "CfgAmmo" >> _shellType >> QGVAR(METAL));
|
|
|
|
if (_m == 0) then {_m = 2; _warn = true;};
|
|
|
|
private _k = getNumber (configFile >> "CfgAmmo" >> _shellType >> QGVAR(GURNEY_K));
|
|
|
|
if (_k == 0) then {_k = 0.5; _warn = true;};
|
|
|
|
private _gC = getNumber (configFile >> "CfgAmmo" >> _shellType >> QGVAR(GURNEY_C));
|
|
|
|
if (_gC == 0) then {_gC = 2440; _warn = true;};
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
if (_warn) then {
|
2016-12-01 17:01:55 +00:00
|
|
|
INFO_1("Ammo class %1 lacks proper explosive properties definitions for frag!",_shellType);
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
|
|
|
|
2017-02-11 21:07:10 +00:00
|
|
|
// Gunery equation is for a non-fragmenting metal, imperical value of 80% represents fragmentation
|
|
|
|
private _fragPower = 0.8 * (((_m / _c) + _k) ^ - (1 / 2)) * _gC;
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
private _atlPos = ASLtoATL _lastPos;
|
|
|
|
|
|
|
|
private _fragPowerRandom = _fragPower * 0.5;
|
|
|
|
if ((_atlPos select 2) < 0.5) then {
|
2017-02-10 18:28:27 +00:00
|
|
|
_lastPos vectorAdd [0, 0, 0.5];
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
private _objects = _atlPos nearEntities [["Car", "Motorcycle", "Tank", "StaticWeapon", "CAManBase", "Air", "Ship"], _fragRange];
|
|
|
|
// Add unique crews in faster way
|
2016-05-30 16:37:03 +00:00
|
|
|
{
|
|
|
|
{
|
2016-10-26 22:16:31 +00:00
|
|
|
_objects pushBackUnique _x;
|
2016-05-30 16:37:03 +00:00
|
|
|
} forEach (crew _x);
|
|
|
|
} forEach _objects;
|
2017-04-11 15:33:56 +00:00
|
|
|
TRACE_2("",_fragRange,count _objects);
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
private _fragCount = 0;
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
private _fragArcs = [];
|
|
|
|
_fragArcs set [360, 0];
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
private _doRandom = true;
|
2021-02-27 17:05:05 +00:00
|
|
|
if (_objects isNotEqualTo []) then {
|
2017-02-10 18:28:27 +00:00
|
|
|
if (GVAR(reflectionsEnabled)) then {
|
2016-05-30 16:37:03 +00:00
|
|
|
[_lastPos, _shellType] call FUNC(doReflections);
|
|
|
|
};
|
|
|
|
{
|
2017-04-11 15:33:56 +00:00
|
|
|
private _target = _x;
|
|
|
|
if (alive _target) then {
|
|
|
|
(boundingBox _target) params ["_boundingBoxA", "_boundingBoxB"];
|
|
|
|
|
|
|
|
private _cubic = ((abs (_boundingBoxA select 0)) + (_boundingBoxB select 0)) * ((abs (_boundingBoxA select 1)) + (_boundingBoxB select 1)) * ((abs (_boundingBoxA select 2)) + (_boundingBoxB select 2));
|
|
|
|
|
|
|
|
if (_cubic <= 1) exitWith {};
|
|
|
|
// _doRandom = true;
|
|
|
|
|
|
|
|
private _targetVel = velocity _target;
|
|
|
|
private _targetPos = getPosASL _target;
|
|
|
|
private _distance = _targetPos vectorDistance _lastPos;
|
|
|
|
private _add = ((_boundingBoxB select 2) / 2) + ((((_distance - (_fragpower / 8)) max 0) / _fragPower) * 10);
|
|
|
|
|
|
|
|
_targetPos = _targetPos vectorAdd [
|
|
|
|
(_targetVel select 0) * (_distance / _fragPower),
|
|
|
|
(_targetVel select 1) * (_distance / _fragPower),
|
|
|
|
_add
|
|
|
|
];
|
|
|
|
|
|
|
|
private _baseVec = _lastPos vectorFromTo _targetPos;
|
|
|
|
|
|
|
|
private _dir = floor (_baseVec call CBA_fnc_vectDir);
|
|
|
|
private _currentCount = RETDEF(_fragArcs select _dir,0);
|
|
|
|
if (_currentCount < 10) then {
|
|
|
|
private _count = ceil (random (sqrt (_m / 1000)));
|
|
|
|
private _vecVar = FRAG_VEC_VAR;
|
|
|
|
if (!(_target isKindOf "Man")) then {
|
|
|
|
ADD(_vecVar,(sqrt _cubic) / 2000);
|
|
|
|
if ((crew _target) isEqualTo [] && {_count > 0}) then {
|
|
|
|
_count = 0 max (_count / 2);
|
2017-02-10 18:28:27 +00:00
|
|
|
};
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
2017-04-11 15:33:56 +00:00
|
|
|
for "_i" from 1 to _count do {
|
|
|
|
private _vec = _baseVec vectorDiff [
|
|
|
|
(_vecVar / 2) + (random _vecVar),
|
|
|
|
(_vecVar / 2) + (random _vecVar),
|
|
|
|
(_vecVar / 2) + (random _vecVar)
|
|
|
|
];
|
|
|
|
|
|
|
|
private _fp = _fragPower - (random (_fragPowerRandom));
|
|
|
|
private _vel = _vec vectorMultiply _fp;
|
|
|
|
|
|
|
|
private _fragObj = (selectRandom _fragTypes) createVehicleLocal [0,0,10000];
|
|
|
|
// TRACE_4("targeted",_fp, typeOf _fragObj,_lastPos vectorDistance _targetPos,typeOf _x);
|
|
|
|
_fragObj setPosASL _lastPos;
|
|
|
|
_fragObj setVectorDir _vec;
|
|
|
|
_fragObj setVelocity _vel;
|
|
|
|
#ifdef DRAW_FRAG_INFO
|
|
|
|
[ACE_player, _fragObj, [1,0,0,1]] call FUNC(dev_addTrack);
|
|
|
|
#endif
|
|
|
|
INC(_fragCount);
|
|
|
|
INC(_currentCount);
|
|
|
|
};
|
|
|
|
_fragArcs set [_dir, _currentCount];
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
2017-04-11 15:33:56 +00:00
|
|
|
};
|
|
|
|
if (_fragCount > _maxFrags) exitWith {};
|
2016-05-30 16:37:03 +00:00
|
|
|
} forEach _objects;
|
2017-04-11 15:33:56 +00:00
|
|
|
TRACE_1("targeted",_fragCount);
|
|
|
|
if (_fragCount > _maxFrags) exitWith {};
|
|
|
|
private _randomCount = ceil ((_maxFrags - _fragCount) * 0.35);
|
|
|
|
TRACE_1("",_randomCount);
|
2016-10-26 22:16:31 +00:00
|
|
|
private _sectorSize = 360 / (_randomCount max 1);
|
2017-04-11 15:33:56 +00:00
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
if (_doRandom) then {
|
2016-05-30 16:37:03 +00:00
|
|
|
for "_i" from 1 to _randomCount do {
|
|
|
|
// Distribute evenly
|
2016-10-26 22:16:31 +00:00
|
|
|
private _sectorOffset = 360 * (_i - 1) / (_randomCount max 1);
|
|
|
|
private _randomDir = random (_sectorSize);
|
|
|
|
_vec = [cos (_sectorOffset + _randomDir), sin (_sectorOffset + _randomDir), sin (30 - (random 45))];
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-10-26 22:16:31 +00:00
|
|
|
_fp = (_fragPower - (random (_fragPowerRandom)));
|
2016-05-30 16:37:03 +00:00
|
|
|
|
|
|
|
_vel = _vec vectorMultiply _fp;
|
|
|
|
|
2017-04-11 15:33:56 +00:00
|
|
|
_fragObj = (selectRandom _fragTypes) createVehicleLocal [0, 0, 10000];
|
2016-05-30 16:37:03 +00:00
|
|
|
_fragObj setPosASL _lastPos;
|
|
|
|
_fragObj setVectorDir _vec;
|
|
|
|
_fragObj setVelocity _vel;
|
|
|
|
|
2017-04-11 15:33:56 +00:00
|
|
|
#ifdef DRAW_FRAG_INFO
|
|
|
|
[ACE_player, _fragObj, [1,0.5,0,1]] call FUNC(dev_addTrack);
|
|
|
|
#endif
|
2016-10-26 22:16:31 +00:00
|
|
|
INC(_fragCount);
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2017-04-11 15:33:56 +00:00
|
|
|
|
|
|
|
TRACE_1("total created",_fragCount);
|
|
|
|
|
2016-07-20 04:15:18 +00:00
|
|
|
END_COUNTER(frago);
|