2015-01-11 16:42:31 +00:00
|
|
|
/*
|
|
|
|
* Author: KoffeinFlummi
|
|
|
|
*
|
|
|
|
* Calculates the angle offset necessary to hit the current target.
|
|
|
|
*
|
|
|
|
* Arguments:
|
|
|
|
* 0: distance to target in meters
|
|
|
|
* 1: current angle of the turret
|
|
|
|
* 2: maximum elevation of the turret
|
|
|
|
* 3: initSpeed of the projectile
|
|
|
|
* 4: airFriction of the projectile
|
|
|
|
* 5: maximum timeToLive of the projectile
|
|
|
|
* 6: simulationStep of the projectile
|
|
|
|
*
|
|
|
|
* Return Value:
|
|
|
|
* offset from the current angle necessary to hit the target
|
|
|
|
*/
|
|
|
|
|
2015-01-12 10:02:44 +00:00
|
|
|
#include "script_component.hpp"
|
2015-01-11 16:42:31 +00:00
|
|
|
#define PRECISION 0.1
|
|
|
|
|
2015-05-13 03:15:52 +00:00
|
|
|
private ["_distance", "_angleTarget", "_maxElev", "_initSpeed", "_airFriction", "_timeToLive", "_simulationStep", "_angle1", "_angle2", "_it2", "_f1", "_f2", "_temp", "_it1", "_angle"];
|
2015-01-11 16:42:31 +00:00
|
|
|
|
|
|
|
_distance = _this select 0;
|
|
|
|
_angleTarget = _this select 1;
|
|
|
|
_maxElev = _this select 2;
|
|
|
|
_initSpeed = _this select 3;
|
|
|
|
_airFriction = _this select 4;
|
|
|
|
_timeToLive = _this select 5;
|
|
|
|
_simulationStep = _this select 6;
|
|
|
|
|
|
|
|
if (_simulationStep == 0) exitWith {_angleTarget};
|
|
|
|
|
2015-01-12 10:02:44 +00:00
|
|
|
FUNC(traceBullet) = {
|
2015-05-13 03:15:52 +00:00
|
|
|
private ["_distance", "_angleTarget", "_maxElev", "_initSpeed", "_airFriction", "_timeToLive", "_simulationStep", "_angle", "_posTargetX", "_posTargetY", "_posX", "_posY", "_velocityX", "_velocityY", "_velocityMagnitude", "_i"];
|
2015-01-14 20:07:41 +00:00
|
|
|
|
|
|
|
_distance = _this select 0;
|
|
|
|
_angleTarget = _this select 1;
|
|
|
|
_maxElev = _this select 2;
|
|
|
|
_initSpeed = _this select 3;
|
|
|
|
_airFriction = _this select 4;
|
|
|
|
_timeToLive = _this select 5;
|
|
|
|
_simulationStep = _this select 6;
|
|
|
|
_angle = _this select 7;
|
|
|
|
|
|
|
|
_angle = _angle - _angleTarget;
|
|
|
|
_angleTarget = 0;
|
|
|
|
|
|
|
|
_posTargetX = (cos _angleTarget) * _distance;
|
|
|
|
_posTargetY = (sin _angleTarget) * _distance;
|
|
|
|
|
|
|
|
_posX = 0;
|
|
|
|
_posY = 0;
|
|
|
|
|
|
|
|
_velocityX = (cos _angle) * _initSpeed;
|
|
|
|
_velocityY = (sin _angle) * _initSpeed;
|
|
|
|
|
|
|
|
// trace the path of the bullet
|
|
|
|
for "_i" from 1 to ((floor (_timeToLive / _simulationStep)) + 1) do {
|
|
|
|
_velocityMagnitude = sqrt (_velocityX^2 + _velocityY^2);
|
|
|
|
_velocityX = _velocityX + _simulationStep * (_velocityX * _velocityMagnitude * _airFriction);
|
|
|
|
_velocityY = _velocityY + _simulationStep * (_velocityY * _velocityMagnitude * _airFriction - 9.81);
|
|
|
|
_posX = _posX + _velocityX * _simulationStep;
|
|
|
|
_posY = _posY + _velocityY * _simulationStep;
|
|
|
|
if (_posX >= _posTargetX) exitWith {}; // bullet passed the target
|
|
|
|
};
|
|
|
|
|
|
|
|
_posY - _posTargetY
|
2015-01-11 16:42:31 +00:00
|
|
|
};
|
|
|
|
|
2015-01-12 10:02:44 +00:00
|
|
|
if ((_this + [_maxElev]) call FUNC(traceBullet) < 0) exitWith {_maxElev - _angleTarget};
|
2015-01-11 16:42:31 +00:00
|
|
|
|
|
|
|
// Newton Method / Secand Method
|
|
|
|
_angle1 = _angleTarget;
|
|
|
|
_angle2 = _maxElev;
|
|
|
|
_it2 = 0;
|
2015-01-12 10:02:44 +00:00
|
|
|
_f1 = (_this + [_angle1]) call FUNC(traceBullet);
|
2015-01-11 16:42:31 +00:00
|
|
|
|
|
|
|
if ((abs _f1) <= PRECISION) exitWith {0};
|
|
|
|
while {(abs _f1) > PRECISION} do {
|
2015-01-14 20:07:41 +00:00
|
|
|
_f2 = (_this + [_angle2]) call FUNC(traceBullet);
|
|
|
|
_temp = _angle2-_f2*(_angle2-_angle1)/(_f2-_f1);
|
|
|
|
_angle1 = _angle2;
|
|
|
|
_angle2 = _temp;
|
|
|
|
_f1 = _f2;
|
|
|
|
_it2 = _it2+1;
|
2015-01-11 16:42:31 +00:00
|
|
|
};
|
|
|
|
//player globalChat format ["it1: %1 | _angle1: %2 | it2: %3 | _angle2: %4",_it1, _angle-_angleTarget, _it2, _angle2-_angleTarget];
|
|
|
|
|
|
|
|
_angle=_angle2;
|
|
|
|
_angle - _angleTarget
|