ACE3/TO_MERGE/ace/arty_computers/gyk-37/fnc_calcFiringSolution.sqf

141 lines
4.8 KiB
Plaintext

scriptName format ["%1ARTY\data\scripts\ARTY_tof.sqf (_this: %1)",_this];
// ARTY_firingSolution.sqf
//
// Use the ballistics table to calculate a firing solution
#define GETELEV(T,I) ((##T## select ##I##) select 0)
#define GETMAXHEIGHT(T,I) ((##T## select ##I##) select 1)
#define GETSLICES(T,I) ((##T## select ##I##) select 2)
// Rocket ballistics values
#define GETOFFSETH(T,I) ((##T## select ##I##) select 3)
#define GETOFFSETV(T,I) ((##T## select ##I##) select 4)
#define GETDECAYELEV(T,I) ((##T## select ##I##) select 5)
#define GETDECAYSPD(T,I) ((##T## select ##I##) select 6)
private ["_firingPos", "_targetPos", "_btab", "_position", "_btab", "_i", "_sliceN", "_sliceNN", "_hmin", "_hmax", "_hstep", "_deltaX", "_deltaY", "_fs"];
_deltaX = _this select 0;
_deltaY = _this select 1;
_ballistics = _this select 2;
_btab = _ballistics select 0;
_minRange = _ballistics select 1;
_maxRange = _ballistics select 2;
_hmin = _ballistics select 3;
_hmax = _ballistics select 4;
_hstep = _ballistics select 5;
// Blank fs to return if there is an error (i.e. out of range)
_blank = [];
// _deltaX = [_firingPos select 0, _firingPos select 1, 0] distance [_targetPos select 0, _targetPos select 1, 0];
// _deltaY = (_targetPos select 2) - (_firingPos select 2);
// Out of range if height deltaY exceeds height differential in either direction.
if (_deltaY < _hmin || _deltaY > _hmax) exitWith {
if (BIS_ARTY_DEBUG==1) then {textLogFormat ["dY of %1 exceeds vertical range of artillery.", _deltaY];};
_blank
};
_hrange = _hmax - _hmin;
_colL = floor((_deltaY - _hmin)/_hstep);
_colH = ceil((_deltaY - _hmin)/_hstep);
// deltaY is on a boundary
if (_colL == _colH) then {_colH = _colH + 1};
_muY = ((_deltaY - _hmin) - _colL*_hstep) / (_colH*_hstep - _colL*_hstep);
_distN = 9999999;
_rowN = -1;
_rowNN = -1;
for [{_i=1},{_i < ((count _btab) - 1)},{_i=_i+1}] do
{
_prevSliceCount = count (GETSLICES(_btab, _i-1)); // Enforce boundary conditions that will come in when picking NN
_slices = GETSLICES(_btab, _i);
_nextSliceCount = count (GETSLICES(_btab, _i+1));
if ((count _slices) > _colH &&
_prevSliceCount > _colH &&
_nextSliceCount > _colH) then
{
_v1 = _slices select _colL; // Select data vectors
_v2 = _slices select _colH;
_testVec = [[_v1 select 0], [_v2 select 0], _muY] call BIS_ARTY_VEC_LERP; // Interpolate
_testDist = _testVec select 0;
if (abs(_testDist - _deltaX) < _distN) then
{
_distN = abs(_testDist - _deltaX);
_rowN = _i;
};
};
};
// Select nearest neighbor.
_n1 = GETSLICES(_btab,_rowN-1);
_v11 = _n1 select _colL;
_v12 = _n1 select _colH;
_n2 = GETSLICES(_btab,_rowN+1);;
_v21 = _n2 select _colL;
_v22 = _n2 select _colH;
_s1 = [_v11, _v12, _muY] call BIS_ARTY_VEC_LERP;
_s2 = [_v21, _v22, _muY] call BIS_ARTY_VEC_LERP;
_d1 = _s1 select 0;
_d2 = _s2 select 0;
if (abs(_d1 - _deltaX) < abs(_d2 - _deltaX)) then
{
_rowNN = (_rowN - 1);
_sliceNN = _s1;
} else {
_rowNN = (_rowN + 1);
_sliceNN = _s2;
};
// Check out of range condition in the horizontal
if ((_deltaX < _d1 && _deltaX < _d2) ||
(_deltaX > _d1 && _deltaX > _d2)) exitWith {
if (BIS_ARTY_DEBUG==1) then {textLogFormat ["dY = %1, dX = %2 out of firing envelope.", _deltaY, _deltaX];};
_blank
};
_n0 = GETSLICES(_btab,_rowN);
_v1 = _n0 select _colL;
_v2 = _n0 select _colH;
_sliceN = [_v1, _v2, _muY] call BIS_ARTY_VEC_LERP;
_elevN = GETELEV(_btab,_rowN);
_elevNN = GETELEV(_btab,_rowNN);
_muX = (_deltaX - (_sliceN select 0)) / ((_sliceNN select 0) - (_sliceN select 0));
// Check the type of ballistics table being worked with (single or rocket)
if (count (_btab select 0) >= 7) then
{
// Load rocket parameters
_offHN = GETOFFSETH(_btab,_rowN);
_offVN = GETOFFSETV(_btab,_rowN);
_decayElevN = GETDECAYELEV(_btab,_rowN);
_decaySpdN = GETDECAYSPD(_btab,_rowN);
_offHNN = GETOFFSETH(_btab,_rowNN);
_offVNN = GETOFFSETV(_btab,_rowNN);
_decayElevNN = GETDECAYELEV(_btab,_rowNN);
_decaySpdNN = GETDECAYSPD(_btab,_rowNN);
// Rocket-based firing solution.
_fs = [[_elevN, (_sliceN select 0), (_sliceN select 2), (_sliceN select 1), _offHN, _offVN, _decayElevN, _decaySpdN],
[_elevNN, (_sliceNN select 0), (_sliceNN select 2), (_sliceNN select 1), _offHNN, _offVNN, _decayElevNN, _decaySpdNN],
_muX] call BIS_ARTY_VEC_LERP;
}
else
{
// Single projectile firing solution.
_fs = [[_elevN, (_sliceN select 0), (_sliceN select 2), (_sliceN select 1), (_sliceN select 3), (_sliceN select 4)],
[_elevNN, (_sliceNN select 0), (_sliceNN select 2), (_sliceNN select 1), (_sliceNN select 3), (_sliceNN select 4)],
_muX] call BIS_ARTY_VEC_LERP;
};
_fs