mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Missile Guidance Overhaul
This commit is contained in:
@ -14,7 +14,7 @@ private _testSeekerPosASL = AGLtoASL (_seekerVehicle modelToWorldVisual [0,0,1])
|
|||||||
private _testSeekerDir = vectorDirVisual _seekerVehicle;
|
private _testSeekerDir = vectorDirVisual _seekerVehicle;
|
||||||
{
|
{
|
||||||
private _code = _x;
|
private _code = _x;
|
||||||
private _results = [_testSeekerPosASL, _testSeekerDir, 45, [1550,1550], _code, _seekerVehicle] call FUNC(seekerFindLaserSpot);
|
private _results = [_testSeekerPosASL, _testSeekerDir, 45, 10000, [1550,1550], _code, _seekerVehicle] call FUNC(seekerFindLaserSpot);
|
||||||
private _resultPos = _results select 0;
|
private _resultPos = _results select 0;
|
||||||
if (!isNil "_resultPos") then {
|
if (!isNil "_resultPos") then {
|
||||||
// Draw lock results
|
// Draw lock results
|
||||||
|
@ -7,9 +7,10 @@
|
|||||||
* 0: Position of seeker (ASL) <ARRAY>
|
* 0: Position of seeker (ASL) <ARRAY>
|
||||||
* 1: Direction vector (will be normalized) <ARRAY>
|
* 1: Direction vector (will be normalized) <ARRAY>
|
||||||
* 2: Seeker FOV in degrees <NUMBER>
|
* 2: Seeker FOV in degrees <NUMBER>
|
||||||
* 3: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. <ARRAY>
|
* 3: Seeker max distance in meters <NUMBER>
|
||||||
* 4: Seeker laser code. <NUMBER>
|
* 4: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. <ARRAY>
|
||||||
* 5: Ignore 1 (e.g. Player's vehicle) <OPTIONAL><OBJECT>
|
* 5: Seeker laser code. <NUMBER>
|
||||||
|
* 6: Ignore 1 (e.g. Player's vehicle) <OPTIONAL><OBJECT>
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* Array, [Strongest compatible laser spot ASL pos, owner object] Nil array values if nothing found.
|
* Array, [Strongest compatible laser spot ASL pos, owner object] Nil array values if nothing found.
|
||||||
@ -24,13 +25,15 @@
|
|||||||
|
|
||||||
BEGIN_COUNTER(seekerFindLaserSpot);
|
BEGIN_COUNTER(seekerFindLaserSpot);
|
||||||
|
|
||||||
params ["_posASL", "_dir", "_seekerFov", "_seekerWavelengths", "_seekerCode", ["_ignoreObj1", objNull]];
|
params ["_posASL", "_dir", "_seekerFov", "_seekerMaxDistnace", "_seekerWavelengths", "_seekerCode", ["_ignoreObj1", objNull]];
|
||||||
|
|
||||||
_dir = vectorNormalized _dir;
|
_dir = vectorNormalized _dir;
|
||||||
_seekerWavelengths params ["_seekerWavelengthMin", "_seekerWavelengthMax"];
|
_seekerWavelengths params ["_seekerWavelengthMin", "_seekerWavelengthMax"];
|
||||||
private _seekerCos = cos _seekerFov;
|
|
||||||
|
|
||||||
TRACE_5("",_posASL,_dir,_seekerFov,_seekerWavelengths,_seekerCode);
|
private _seekerCos = cos _seekerFov;
|
||||||
|
private _seekerMaxDistSq = _seekerMaxDistnace ^ 2;
|
||||||
|
|
||||||
|
TRACE_6("",_posASL,_dir,_seekerFov,_seekerMaxDistnace,_seekerWavelengths,_seekerCode);
|
||||||
|
|
||||||
private _spots = [];
|
private _spots = [];
|
||||||
private _finalPos = nil;
|
private _finalPos = nil;
|
||||||
@ -76,7 +79,7 @@ private _finalOwner = objNull;
|
|||||||
_testPoint = _x select 0;
|
_testPoint = _x select 0;
|
||||||
private _testPointVector = _posASL vectorFromTo _testPoint;
|
private _testPointVector = _posASL vectorFromTo _testPoint;
|
||||||
private _testDotProduct = _dir vectorDotProduct _testPointVector;
|
private _testDotProduct = _dir vectorDotProduct _testPointVector;
|
||||||
if (_testDotProduct > _seekerCos) then {
|
if ((_testDotProduct > _seekerCos) && {(_testPoint vectorDistanceSqr _posASL) < _seekerMaxDistSq}) then {
|
||||||
_spots pushBack [_testPoint, _owner];
|
_spots pushBack [_testPoint, _owner];
|
||||||
};
|
};
|
||||||
} forEach _resultPositions;
|
} forEach _resultPositions;
|
||||||
@ -87,7 +90,7 @@ private _finalOwner = objNull;
|
|||||||
if (_distance > 0) then {
|
if (_distance > 0) then {
|
||||||
private _testPointVector = _posASL vectorFromTo _resultPos;
|
private _testPointVector = _posASL vectorFromTo _resultPos;
|
||||||
private _testDotProduct = _dir vectorDotProduct _testPointVector;
|
private _testDotProduct = _dir vectorDotProduct _testPointVector;
|
||||||
if (_testDotProduct > _seekerCos) then {
|
if ((_testDotProduct > _seekerCos) && {(_testPoint vectorDistanceSqr _posASL) < _seekerMaxDistSq}) then {
|
||||||
_spots pushBack [_resultPos, _owner];
|
_spots pushBack [_resultPos, _owner];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,6 @@ class ACE_Settings {
|
|||||||
class GVAR(enabled) {
|
class GVAR(enabled) {
|
||||||
value = 2;
|
value = 2;
|
||||||
typeName = "SCALAR";
|
typeName = "SCALAR";
|
||||||
isClientSettable = 1;
|
|
||||||
displayName = CSTRING(Title);
|
displayName = CSTRING(Title);
|
||||||
description = CSTRING(Desc);
|
description = CSTRING(Desc);
|
||||||
values[] = {CSTRING(Off), CSTRING(PlayerOnly), CSTRING(PlayerAndAi)};
|
values[] = {CSTRING(Off), CSTRING(PlayerOnly), CSTRING(PlayerAndAi)};
|
||||||
|
@ -108,6 +108,8 @@ class CfgAmmo {
|
|||||||
seekerMinRange = 0;
|
seekerMinRange = 0;
|
||||||
seekerMaxRange = 2500; // Range from the missile which the seeker can visually search
|
seekerMaxRange = 2500; // Range from the missile which the seeker can visually search
|
||||||
|
|
||||||
|
seekLastTargetPos = 1; // seek last target position [if seeker loses LOS of target, continue to last known pos]
|
||||||
|
|
||||||
// Attack profile type selection
|
// Attack profile type selection
|
||||||
defaultAttackProfile = "JAV_TOP";
|
defaultAttackProfile = "JAV_TOP";
|
||||||
attackProfiles[] = { "JAV_TOP", "JAV_DIR" };
|
attackProfiles[] = { "JAV_TOP", "JAV_DIR" };
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
PREP(rotateVectLineGetMap);
|
|
||||||
PREP(rotateVectLine);
|
|
||||||
PREP(changeMissileDirection);
|
PREP(changeMissileDirection);
|
||||||
|
|
||||||
PREP(checkSeekerAngle);
|
PREP(checkSeekerAngle);
|
||||||
@ -17,11 +15,11 @@ PREP(doHandoff);
|
|||||||
PREP(handleHandoff);
|
PREP(handleHandoff);
|
||||||
|
|
||||||
// Attack Profiles
|
// Attack Profiles
|
||||||
PREP(attackProfile_LIN);
|
|
||||||
PREP(attackProfile_DIR);
|
|
||||||
PREP(attackProfile_MID);
|
|
||||||
PREP(attackProfile_HI);
|
|
||||||
PREP(attackProfile_AIR);
|
PREP(attackProfile_AIR);
|
||||||
|
PREP(attackProfile_DIR);
|
||||||
|
PREP(attackProfile_HI);
|
||||||
|
PREP(attackProfile_LIN);
|
||||||
|
PREP(attackProfile_MID);
|
||||||
|
|
||||||
// Javelin profiles
|
// Javelin profiles
|
||||||
PREP(attackProfile_JAV_DIR);
|
PREP(attackProfile_JAV_DIR);
|
||||||
|
@ -1,4 +1,22 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Attack profile: AIR
|
||||||
|
* TODO: falls back to Linear
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Seeker Target PosASL <ARRAY>
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Seeker State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_AIR;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
_this call FUNC(attackProfile_LIN);
|
_this call FUNC(attackProfile_LIN);
|
@ -1,4 +1,22 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Attack profile: DIR
|
||||||
|
* TODO: falls back to Linear
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Seeker Target PosASL <ARRAY>
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Seeker State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_DIR;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
_this call FUNC(attackProfile_LIN);
|
_this call FUNC(attackProfile_LIN);
|
@ -1,4 +1,22 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Attack profile: HI
|
||||||
|
* TODO: falls back to Linear
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Seeker Target PosASL <ARRAY>
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Attack Profile State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_HI;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
_this call FUNC(attackProfile_LIN);
|
_this call FUNC(attackProfile_LIN);
|
@ -1,4 +1,21 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Attack profile: Javelin Dir
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Seeker Target PosASL <ARRAY>
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Attack Profile State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_JAV_DIR;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
#define STAGE_LAUNCH 1
|
#define STAGE_LAUNCH 1
|
||||||
@ -6,48 +23,41 @@
|
|||||||
#define STAGE_COAST 3
|
#define STAGE_COAST 3
|
||||||
#define STAGE_TERMINAL 4
|
#define STAGE_TERMINAL 4
|
||||||
|
|
||||||
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
|
||||||
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
|
_args params ["_firedEH"];
|
||||||
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_state"];
|
_firedEH params ["_shooter","","","","","","_projectile"];
|
||||||
private["_cruisAlt", "_distanceShooterToTarget", "_shooterPos"];
|
|
||||||
_seekerTargetPos = _this select 0;
|
|
||||||
_launchParams = _this select 1;
|
|
||||||
|
|
||||||
_target = _launchParams select 0;
|
if (_attackProfileStateParams isEqualTo []) then {
|
||||||
_targetLaunchParams = _launchParams select 1;
|
_attackProfileStateParams set [0, STAGE_LAUNCH];
|
||||||
|
|
||||||
_state = _this select 2;
|
|
||||||
if( (count _state) < 1) then {
|
|
||||||
_state set[0, STAGE_LAUNCH];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_shooterPos = getPosASL _shooter;
|
private _shooterPos = getPosASL _shooter;
|
||||||
_projectilePos = getPosASL _projectile;
|
private _projectilePos = getPosASL _projectile;
|
||||||
|
|
||||||
_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
|
private _distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
|
||||||
_distanceToShooter = _projectilePos vectorDistance _shooterPos;
|
private _distanceToShooter = _projectilePos vectorDistance _shooterPos;
|
||||||
_distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos;
|
private _distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos;
|
||||||
|
|
||||||
TRACE_2("", _distanceToTarget, _distanceToShooter);
|
TRACE_2("", _distanceToTarget, _distanceToShooter);
|
||||||
|
|
||||||
// Add height depending on distance for compensate
|
// Add height depending on distance for compensate
|
||||||
_returnTargetPos = _seekerTargetPos;
|
private _returnTargetPos = _seekerTargetPos;
|
||||||
|
|
||||||
switch( (_state select 0) ) do {
|
switch (_attackProfileStateParams select 0) do {
|
||||||
case STAGE_LAUNCH: {
|
case STAGE_LAUNCH: {
|
||||||
TRACE_1("STAGE_LAUNCH","");
|
TRACE_1("STAGE_LAUNCH","");
|
||||||
if(_distanceToShooter < 10) then {
|
if (_distanceToShooter < 10) then {
|
||||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2];
|
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2];
|
||||||
} else {
|
} else {
|
||||||
_state set[0, STAGE_CLIMB];
|
_attackProfileStateParams set [0, STAGE_CLIMB];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
case STAGE_CLIMB: {
|
case STAGE_CLIMB: {
|
||||||
TRACE_1("STAGE_CLIMB","");
|
TRACE_1("STAGE_CLIMB","");
|
||||||
_cruisAlt = 60 * (_distanceShooterToTarget/2000);
|
private _cruisAlt = 60 * (_distanceShooterToTarget/2000);
|
||||||
|
|
||||||
if( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
||||||
_state set[0, STAGE_TERMINAL];
|
_attackProfileStateParams set [0, STAGE_TERMINAL];
|
||||||
} else {
|
} else {
|
||||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5];
|
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5];
|
||||||
};
|
};
|
||||||
@ -58,9 +68,5 @@ switch( (_state select 0) ) do {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DEBUG_MODE_FULL
|
|
||||||
drawLine3D [(ASLtoAGL _returnTargetPos), (ASLtoAGL _seekerTargetPos), [0,1,0,1]];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TRACE_1("Adjusted target position", _returnTargetPos);
|
TRACE_1("Adjusted target position", _returnTargetPos);
|
||||||
_returnTargetPos;
|
_returnTargetPos;
|
||||||
|
@ -1,4 +1,21 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Attack profile: Javelin Top
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Seeker Target PosASL <ARRAY>
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Attack Profile State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_JAV_TOP;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
#define STAGE_LAUNCH 1
|
#define STAGE_LAUNCH 1
|
||||||
@ -6,55 +23,47 @@
|
|||||||
#define STAGE_COAST 3
|
#define STAGE_COAST 3
|
||||||
#define STAGE_TERMINAL 4
|
#define STAGE_TERMINAL 4
|
||||||
|
|
||||||
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
|
||||||
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
|
_args params ["_firedEH"];
|
||||||
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_state"];
|
_firedEH params ["_shooter","","","","","","_projectile"];
|
||||||
private["_cruisAlt", "_distanceShooterToTarget", "_shooterPos"];
|
|
||||||
|
|
||||||
_seekerTargetPos = _this select 0;
|
if (_attackProfileStateParams isEqualTo []) then {
|
||||||
_launchParams = _this select 1;
|
_attackProfileStateParams set [0, STAGE_LAUNCH];
|
||||||
|
|
||||||
_target = _launchParams select 0;
|
|
||||||
_targetLaunchParams = _launchParams select 1;
|
|
||||||
|
|
||||||
_state = _this select 2;
|
|
||||||
if( (count _state) < 1) then {
|
|
||||||
_state set[0, STAGE_LAUNCH];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_shooterPos = getPosASL _shooter;
|
private _shooterPos = getPosASL _shooter;
|
||||||
_projectilePos = getPosASL _projectile;
|
private _projectilePos = getPosASL _projectile;
|
||||||
|
|
||||||
_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
|
private _distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
|
||||||
_distanceToShooter = _projectilePos vectorDistance _shooterPos;
|
private _distanceToShooter = _projectilePos vectorDistance _shooterPos;
|
||||||
_distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos;
|
private _distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos;
|
||||||
|
|
||||||
TRACE_2("", _distanceToTarget, _distanceToShooter);
|
TRACE_2("", _distanceToTarget, _distanceToShooter);
|
||||||
|
|
||||||
// Add height depending on distance for compensate
|
// Add height depending on distance for compensate
|
||||||
_returnTargetPos = _seekerTargetPos;
|
private _returnTargetPos = _seekerTargetPos;
|
||||||
|
|
||||||
switch( (_state select 0) ) do {
|
switch( (_attackProfileStateParams select 0) ) do {
|
||||||
case STAGE_LAUNCH: {
|
case STAGE_LAUNCH: {
|
||||||
TRACE_1("STAGE_LAUNCH","");
|
TRACE_1("STAGE_LAUNCH","");
|
||||||
if(_distanceToShooter < 10) then {
|
if (_distanceToShooter < 10) then {
|
||||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2];
|
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2];
|
||||||
} else {
|
} else {
|
||||||
_state set[0, STAGE_CLIMB];
|
_attackProfileStateParams set [0, STAGE_CLIMB];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
case STAGE_CLIMB: {
|
case STAGE_CLIMB: {
|
||||||
TRACE_1("STAGE_CLIMB","");
|
TRACE_1("STAGE_CLIMB","");
|
||||||
_cruisAlt = 140;
|
_cruisAlt = 140;
|
||||||
if(_distanceShooterToTarget < 1250) then {
|
if (_distanceShooterToTarget < 1250) then {
|
||||||
_cruisAlt = 140 * (_distanceShooterToTarget/1250);
|
private _cruisAlt = 140 * (_distanceShooterToTarget/1250);
|
||||||
TRACE_1("_cruisAlt", _cruisAlt);
|
TRACE_1("_cruisAlt", _cruisAlt);
|
||||||
};
|
};
|
||||||
if( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
||||||
if(_cruisAlt < 140) then {
|
if (_cruisAlt < 140) then {
|
||||||
_state set[0, STAGE_TERMINAL];
|
_attackProfileStateParams set [0, STAGE_TERMINAL];
|
||||||
} else {
|
} else {
|
||||||
_state set[0, STAGE_COAST];
|
_attackProfileStateParams set [0, STAGE_COAST];
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5];
|
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5];
|
||||||
@ -63,8 +72,8 @@ switch( (_state select 0) ) do {
|
|||||||
case STAGE_COAST: {
|
case STAGE_COAST: {
|
||||||
TRACE_1("STAGE_COAST","");
|
TRACE_1("STAGE_COAST","");
|
||||||
TRACE_1("", ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) );
|
TRACE_1("", ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) );
|
||||||
if(_distanceToTarget < ( ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) ) * 1.5) then {
|
if (_distanceToTarget < ( ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) ) * 2) then {
|
||||||
_state set[0, STAGE_TERMINAL];
|
_attackProfileStateParams set [0, STAGE_TERMINAL];
|
||||||
} else {
|
} else {
|
||||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,(_projectilePos select 2)];
|
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,(_projectilePos select 2)];
|
||||||
};
|
};
|
||||||
@ -76,9 +85,5 @@ switch( (_state select 0) ) do {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DEBUG_MODE_FULL
|
|
||||||
drawLine3D [(ASLtoAGL _returnTargetPos), (ASLtoAGL _seekerTargetPos), [0,1,0,1]];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TRACE_1("Adjusted target position", _returnTargetPos);
|
TRACE_1("Adjusted target position", _returnTargetPos);
|
||||||
_returnTargetPos;
|
_returnTargetPos;
|
||||||
|
@ -1,50 +1,63 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Attack profile: Linear (used by DAGR)
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Seeker Target PosASL <ARRAY>
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Attack Profile State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_LIN;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
params ["_seekerTargetPos", "_args"];
|
||||||
private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"];
|
_args params ["_firedEH"];
|
||||||
private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_shooterPos"];
|
_firedEH params ["_shooter","","","","","","_projectile"];
|
||||||
_seekerTargetPos = _this select 0;
|
|
||||||
_launchParams = _this select 1;
|
|
||||||
|
|
||||||
_target = _launchParams select 0;
|
private _shooterPos = getPosASL _shooter;
|
||||||
_targetLaunchParams = _launchParams select 1;
|
private _projectilePos = getPosASL _projectile;
|
||||||
|
|
||||||
_shooterPos = getPosASL _shooter;
|
private _distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
|
||||||
_projectilePos = getPosASL _projectile;
|
private _distanceToShooter = _projectilePos vectorDistance _shooterPos;
|
||||||
|
private _distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos;
|
||||||
|
|
||||||
_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos;
|
TRACE_2("", _distanceToTarget, _distanceToShooter);
|
||||||
_distanceToShooter = _projectilePos vectorDistance _shooterPos;
|
|
||||||
|
|
||||||
TRACE_3("", _distanceToTarget, _distanceToShooter, _seekerTargetPos);
|
|
||||||
|
|
||||||
// Add height depending on distance for compensate
|
// Add height depending on distance for compensate
|
||||||
_addHeight = [0,0,0];
|
private _addHeight = [0,0,0];
|
||||||
|
|
||||||
// Always climb an arc on initial launch if we are close to the round
|
// Always climb an arc on initial launch if we are close to the round
|
||||||
if( ((ASLtoAGL _projectilePos) select 2) < 5 && _distanceToShooter < 15) then {
|
if ((((ASLtoAGL _projectilePos) select 2) < 5) && {_distanceToShooter < 15}) then {
|
||||||
_addHeight = _addHeight vectorAdd [0,0,_distanceToTarget];
|
_addHeight = _addHeight vectorAdd [0,0,_distanceToTarget];
|
||||||
|
TRACE_1("climb - near shooter",_addHeight);
|
||||||
} else {
|
} else {
|
||||||
// If we are below the target, increase the climbing arc
|
// If we are below the target, increase the climbing arc
|
||||||
if((_projectilePos select 2) < (_seekerTargetPos select 2) && _distanceToTarget > 100) then {
|
if (((_projectilePos select 2) < (_seekerTargetPos select 2)) && {_distanceToTarget > 100}) then {
|
||||||
_addHeight = _addHeight vectorAdd [0,0, ((_seekerTargetPos select 2) - (_projectilePos select 2))];
|
_addHeight = _addHeight vectorAdd [0,0, ((_seekerTargetPos select 2) - (_projectilePos select 2))];
|
||||||
|
TRACE_1("climb - below target and far",_addHeight);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle arcing terminal low for high decent
|
// Handle arcing terminal low for high decent (when projectile above target)
|
||||||
if( (_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget < 100) then {
|
if ((_projectilePos select 2) > (_seekerTargetPos select 2)) then {
|
||||||
_addHeight = _addHeight vectorDiff [0,0, ((_projectilePos select 2) - (_seekerTargetPos select 2)) * 0.5];
|
if (_distanceToTarget < 100) then {
|
||||||
} else {
|
_addHeight = _addHeight vectorDiff [0,0, ((_projectilePos select 2) - (_seekerTargetPos select 2)) * 0.5];
|
||||||
if((_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget > 100) then {
|
TRACE_1("above - close",_addHeight);
|
||||||
|
} else {
|
||||||
|
TRACE_1("above - far",_addHeight);
|
||||||
_addHeight = _addHeight vectorAdd [0,0, _distanceToTarget*0.02];
|
_addHeight = _addHeight vectorAdd [0,0, _distanceToTarget*0.02];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_returnTargetPos = _seekerTargetPos vectorAdd _addHeight;
|
private _returnTargetPos = _seekerTargetPos vectorAdd _addHeight;
|
||||||
|
|
||||||
#ifdef DEBUG_MODE_FULL
|
TRACE_2("Adjusted target position",_returnTargetPos,_addHeight);
|
||||||
drawLine3D [(ASLtoAGL _returnTargetPos) vectorAdd _addHeight, ASLtoAGL _returnTargetPos, [0,1,0,1]];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TRACE_1("Adjusted target position", _returnTargetPos);
|
|
||||||
_returnTargetPos;
|
_returnTargetPos;
|
||||||
|
@ -1,4 +1,22 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Attack profile: MID
|
||||||
|
* TODO: falls back to Linear
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Seeker Target PosASL <ARRAY>
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Attack Profile State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_MID;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
_this call FUNC(attackProfile_LIN);
|
_this call FUNC(attackProfile_LIN);
|
@ -1,11 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Change a projectile's direction, maintaing speed
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Projectile <OBJECT>
|
||||||
|
* 1: Direction (unit vector) <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [missile, [0,1,0]] call ace_missileguidance_fnc_changeMissileDirection;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
private ["_projectile", "_v", "_l", "_r"];
|
|
||||||
|
|
||||||
_projectile = _this select 0;
|
params ["_projectile", "_v"];
|
||||||
_v = _this select 1;
|
|
||||||
|
|
||||||
_l = sqrt ((_v select 0) ^ 2 + (_v select 1) ^ 2);
|
private _l = sqrt ((_v select 0) ^ 2 + (_v select 1) ^ 2);
|
||||||
_r = -(_v select 2) / _l;
|
private _r = -(_v select 2) / _l;
|
||||||
|
|
||||||
_projectile setVectorDirAndUp [ _v, [(_v select 0) * _r,(_v select 1) * _r, _l] ];
|
_projectile setVectorDirAndUp [ _v, [(_v select 0) * _r,(_v select 1) * _r, _l] ];
|
||||||
_projectile setVelocity (_v vectorMultiply (vectorMagnitude (velocity _projectile)));
|
_projectile setVelocity (_v vectorMultiply (vectorMagnitude (velocity _projectile)));
|
@ -3,17 +3,25 @@
|
|||||||
* Returns whether the seeker object can see the target position with lineIntersect
|
* Returns whether the seeker object can see the target position with lineIntersect
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* 0: Seeker [Object]
|
* 0: Seeker <OBJECT>
|
||||||
* 1: Target [Object]
|
* 1: Target <OBJECT>
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* Boolean
|
* Has LOS <BOOL>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [player, cursorTarget] call ace_missileguidance_fnc_checkLOS;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
*/
|
*/
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
params ["_seeker", "_target"];
|
params ["_seeker", "_target"];
|
||||||
|
|
||||||
if ((isNil "_seeker") || {isNil "_target"}) exitWith {false};
|
if ((isNil "_seeker") || {isNil "_target"}) exitWith {
|
||||||
|
ERROR_2("nil",_seeker,_target);
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
private _targetPos = getPosASL _target;
|
private _targetPos = getPosASL _target;
|
||||||
private _targetAimPos = aimPos _target;
|
private _targetAimPos = aimPos _target;
|
||||||
@ -21,7 +29,7 @@ private _seekerPos = getPosASL _seeker;
|
|||||||
private _return = true;
|
private _return = true;
|
||||||
|
|
||||||
if (!((terrainIntersectASL [_seekerPos, _targetPos]) && {terrainIntersectASL [_seekerPos, _targetAimPos]})) then {
|
if (!((terrainIntersectASL [_seekerPos, _targetPos]) && {terrainIntersectASL [_seekerPos, _targetAimPos]})) then {
|
||||||
if(lineIntersects [_seekerPos, _targetPos, _seeker, _target]) then {
|
if (lineIntersects [_seekerPos, _targetPos, _seeker, _target]) then {
|
||||||
_return = false;
|
_return = false;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
@ -4,27 +4,31 @@
|
|||||||
* objects current direction.
|
* objects current direction.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* 0: Seeker [Object]
|
* 0: Seeker <OBJECT>
|
||||||
* 1: Target [Position]
|
* 1: Target PosASL <ARRAY>
|
||||||
* 2: Max Angle [Degrees]
|
* 2: Max Angle (degrees) <NUMBER>
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* Boolean
|
* Can See <BOOL>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [player, cursorTarget, 45] call ace_missileguidance_fnc_checkSeekerAngle;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
*/
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
private ["_seeker", "_targetPos", "_seekerMaxAngle", "_sensorPos", "_testPointVector", "_testDotProduct"];
|
|
||||||
|
|
||||||
_seeker = _this select 0;
|
params ["_seeker", "_targetPos", "_seekerMaxAngle"];
|
||||||
_targetPos = _this select 1;
|
|
||||||
_seekerMaxAngle = _this select 2;
|
|
||||||
|
|
||||||
_sensorPos = getPosASL _seeker;
|
private _sensorPos = getPosASL _seeker;
|
||||||
|
|
||||||
_testPointVector = vectorNormalized (_targetPos vectorDiff _sensorPos);
|
private _testPointVector = vectorNormalized (_targetPos vectorDiff _sensorPos);
|
||||||
_testDotProduct = (vectorNormalized (velocity _seeker)) vectorDotProduct _testPointVector;
|
private _testDotProduct = (vectorNormalized (velocity _seeker)) vectorDotProduct _testPointVector;
|
||||||
|
|
||||||
if(_testDotProduct < (cos _seekerMaxAngle)) exitWith {
|
TRACE_2("fov",acos _testDotProduct,_seekerMaxAngle);
|
||||||
|
|
||||||
|
if (_testDotProduct < (cos _seekerMaxAngle)) exitWith {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,29 +1,40 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou, PabstMirror
|
||||||
|
* Do attack profile with a valid seeker target location
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Seeker Target PosASL <ARRAY>
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Seeker State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[1,2,3], [], []] call ace_missileguidance_fnc_doAttackProfile;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
params ["_seekerTargetPos", "_args"];
|
||||||
private ["_testName", "_attackProfilePos", "_attackProfile", "_attackProfileName", "_attackProfilesCfg", "_i", "_launchParams", "_testame", "_testProfile"];
|
_args params ["", "_launchParams"];
|
||||||
_launchParams = ((_this select 1) select 1);
|
_launchParams params ["", "", "", "_attackProfileName"];
|
||||||
_attackProfileName = _launchParams select 3;
|
|
||||||
|
|
||||||
TRACE_1("Attacking profile", _attackProfileName);
|
private _attackProfileFunction = getText (configFile >> QGVAR(AttackProfiles) >> _attackProfileName >> "functionName");
|
||||||
|
|
||||||
_attackProfilesCfg = ( configFile >> QGVAR(AttackProfiles) );
|
private _attackProfilePos = _this call (missionNamespace getVariable _attackProfileFunction);
|
||||||
|
|
||||||
_attackProfile = nil;
|
if ((isNil "_attackProfilePos") || {(vectorMagnitude _attackProfilePos) == 0}) exitWith {
|
||||||
for [{_i=0}, {_i< (count _attackProfilesCfg) }, {_i=_i+1}] do {
|
ERROR_1("attack profile returned bad pos",_attackProfilePos);
|
||||||
_testProfile = _attackProfilesCfg select _i;
|
[0,0,0]
|
||||||
_testName = configName _testProfile;
|
|
||||||
TRACE_3("", _testName, _testProfile, _attackProfilesCfg);
|
|
||||||
|
|
||||||
if( _testName == _attackProfileName) exitWith {
|
|
||||||
_attackProfile = _attackProfilesCfg select _i;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_attackProfilePos = [0,0,0];
|
#ifdef DRAW_GUIDANCE_INFO
|
||||||
if(!isNil "_attackProfile") then {
|
drawLine3D [(ASLtoAGL _attackProfilePos), (ASLtoAGL _seekerTargetPos), [0,1,1,1]];
|
||||||
_attackProfilePos = _this call (missionNamespace getVariable (getText (_attackProfile >> "functionName")));
|
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0,0,1,1], ASLtoAGL _attackProfilePos, 0.5, 0.5, 0, _attackProfileName, 1, 0.025, "TahomaB"];
|
||||||
};
|
#endif
|
||||||
|
|
||||||
|
TRACE_2("return",_attackProfilePos,_attackProfileName);
|
||||||
_attackProfilePos;
|
_attackProfilePos;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// Not currently used
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
PARAMS_2(_target,_args);
|
PARAMS_2(_target,_args);
|
||||||
|
|
||||||
|
@ -1,30 +1,51 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou, PabstMirror
|
||||||
|
* Do seeker search
|
||||||
|
* Handles a nil/bad return and will attempt to use last known position if enabled on ammo
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 3: Last known pos state array <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[], [], []] call ace_missileguidance_fnc_seekerType_Optic;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
params ["", "_args", "", "_lastKnownPosState"];
|
||||||
private ["_seekerProfilePos", "_i", "_launchParams", "_seekerType", "_seekerTypeName", "_seekerTypesCfg", "_testName", "_testProfile"];
|
_args params ["", "_launchParams"];
|
||||||
|
_launchParams params ["", "", "_seekerTypeName"];
|
||||||
|
_lastKnownPosState params ["_seekLastTargetPos", "_lastKnownPos"];
|
||||||
|
|
||||||
_launchParams = ((_this select 1) select 1);
|
private _seekerFunction = getText (configFile >> QGVAR(SeekerTypes) >> _seekerTypeName >> "functionName");
|
||||||
_seekerTypeName = _launchParams select 2;
|
|
||||||
|
|
||||||
TRACE_1("Seeker type", _seekerTypeName);
|
private _seekerTargetPos = _this call (missionNamespace getVariable _seekerFunction);
|
||||||
|
|
||||||
_seekerTypesCfg = ( configFile >> QGVAR(SeekerTypes) );
|
if ((isNil "_seekerTargetPos") || {(vectorMagnitude _seekerTargetPos) == 0}) then {
|
||||||
|
// Seeker returned nil / bad pos
|
||||||
_seekerType = nil;
|
if (_seekLastTargetPos && {(vectorMagnitude _lastKnownPos) != 0}) then {
|
||||||
for [{_i = 0}, {_i< (count _seekerTypesCfg) }, {_i=_i + 1}] do {
|
TRACE_2("seeker returned bad pos - using last known",_seekLastTargetPos,_lastKnownPos);
|
||||||
_testProfile = _seekerTypesCfg select _i;
|
_seekerTargetPos = _lastKnownPos;
|
||||||
_testName = configName _testProfile;
|
} else {
|
||||||
TRACE_3("", _testName, _testProfile, _seekerTypesCfg);
|
TRACE_1("seeker returned no pos",_seekerTargetPos);
|
||||||
|
_seekerTargetPos = [0,0,0];
|
||||||
if( _testName == _seekerTypeName) exitWith {
|
};
|
||||||
_seekerType = _seekerTypesCfg select _i;
|
} else {
|
||||||
|
if (_seekLastTargetPos) then {
|
||||||
|
TRACE_1("saving current pos",_seekLastTargetPos);
|
||||||
|
_lastKnownPosState set [1, _seekerTargetPos];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_seekerProfilePos = [0, 0, 0];
|
#ifdef DRAW_GUIDANCE_INFO
|
||||||
if(!isNil "_seekerType") then {
|
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0,1,0,1], ASLtoAGL _seekerTargetPos, 0.5, 0.5, 0, _seekerTypeName, 1, 0.025, "TahomaB"];
|
||||||
_seekerProfilePos = _this call (missionNamespace getVariable (getText (_seekerType >> "functionName")));
|
#endif
|
||||||
};
|
|
||||||
|
|
||||||
_seekerProfilePos;
|
TRACE_2("return",_seekerTargetPos,_seekerTypeName);
|
||||||
|
_seekerTargetPos;
|
||||||
|
@ -1,33 +1,41 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Guidance Per Frame Handler
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Guidance Arg Array <ARRAY>
|
||||||
|
* 1: PFID <NUMBER>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Nothing
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[], 0] call ace_missileguidance_fnc_guidancePFH;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
|
BEGIN_COUNTER(guidancePFH);
|
||||||
|
|
||||||
#define TIMESTEP_FACTOR 0.01
|
#define TIMESTEP_FACTOR 0.01
|
||||||
|
|
||||||
private ["_launchParams", "_targetLaunchParams", "_flightParams", "_seekerParams", "_stateParams"];
|
params ["_args", "_pfID"];
|
||||||
private ["_lastRunTime", "_runtimeDelta", "_adjustTime", "_args", "_seekerTargetPos", "_projectilePos"];
|
_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"];
|
||||||
private ["_profileAdjustedTargetPos", "_incDeflection", "_minDeflection", "_maxDeflection"];
|
_firedEH params ["_shooter","","","","_ammo","","_projectile"];
|
||||||
private ["_targetVector", "_adjustVector", "_finalAdjustVector", "_changeVector", "_pitch", "_yaw", "_roll"];
|
_launchParams params ["","_targetLaunchParams"];
|
||||||
private ["_PS", "_distanceToTarget", "_targetRelativeVector", "_vectorTo"];
|
_stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState"];
|
||||||
|
|
||||||
_args = _this select 0;
|
if (!alive _projectile || isNull _projectile || isNull _shooter) exitWith {
|
||||||
EXPLODE_7_PVT((_args select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
[_pfID] call CBA_fnc_removePerFrameHandler;
|
||||||
|
END_COUNTER(guidancePFH);
|
||||||
if(!alive _projectile || isNull _projectile || isNull _shooter) exitWith {
|
|
||||||
[(_this select 1)] call CBA_fnc_removePerFrameHandler;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_launchParams = _args select 1;
|
private _runtimeDelta = diag_tickTime - _lastRunTime;
|
||||||
_targetLaunchParams = _launchParams select 1;
|
private _adjustTime = 1;
|
||||||
_flightParams = _args select 2;
|
|
||||||
_seekerParams = _args select 3;
|
|
||||||
|
|
||||||
_stateParams = _args select 4;
|
if (accTime > 0) then {
|
||||||
|
|
||||||
_lastRunTime = _stateParams select 0;
|
|
||||||
_runtimeDelta = diag_tickTime - _lastRunTime;
|
|
||||||
_adjustTime = 1;
|
|
||||||
|
|
||||||
if(accTime > 0) then {
|
|
||||||
_adjustTime = 1/accTime;
|
_adjustTime = 1/accTime;
|
||||||
_adjustTime = _adjustTime * (_runtimeDelta / TIMESTEP_FACTOR);
|
_adjustTime = _adjustTime * (_runtimeDelta / TIMESTEP_FACTOR);
|
||||||
TRACE_4("Adjust timing", 1/accTime, _adjustTime, _runtimeDelta, (_runtimeDelta / TIMESTEP_FACTOR) );
|
TRACE_4("Adjust timing", 1/accTime, _adjustTime, _runtimeDelta, (_runtimeDelta / TIMESTEP_FACTOR) );
|
||||||
@ -35,72 +43,71 @@ if(accTime > 0) then {
|
|||||||
_adjustTime = 0;
|
_adjustTime = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
_minDeflection = ((_flightParams select 0) - ((_flightParams select 0) * _adjustTime)) max 0;
|
private _minDeflection = ((_flightParams select 0) - ((_flightParams select 0) * _adjustTime)) max 0;
|
||||||
_maxDeflection = (_flightParams select 1) * _adjustTime;
|
private _maxDeflection = (_flightParams select 1) * _adjustTime;
|
||||||
_incDeflection = _flightParams select 2;
|
// private _incDeflection = _flightParams select 2; // todo
|
||||||
|
|
||||||
_projectilePos = getPosASL _projectile;
|
private _projectilePos = getPosASL _projectile;
|
||||||
|
|
||||||
// @TODO: placeholder for "last seek target position"
|
// Run seeker function:
|
||||||
// Last target pos should be optional based on the seeker unit
|
private _seekerTargetPos = [[0,0,0], _args, _seekerStateParams, _lastKnownPosState] call FUNC(doSeekerSearch);
|
||||||
_seekerTargetPos = [ [0,0,0], _args, (_stateParams select 1)] call FUNC(doSeekerSearch);
|
|
||||||
if(isNil "_seekerTargetPos") then {
|
// If we have no seeker target, then do not change anything
|
||||||
_seekerTargetPos = _seekerTargetPos vectorAdd ((velocity _projectile) vectorMultiply 5);
|
if (!(_seekerTargetPos isEqualTo [0,0,0])) then {
|
||||||
} else {
|
// Run attack profile function:
|
||||||
if( (vectorMagnitude _seekerTargetPos) == 0) then {
|
private _profileAdjustedTargetPos = [_seekerTargetPos, _args, _attackProfileStateParams] call FUNC(doAttackProfile);
|
||||||
_seekerTargetPos = _seekerTargetPos vectorAdd ((velocity _projectile) vectorMultiply 5);
|
|
||||||
|
private _targetVector = _projectilePos vectorFromTo _profileAdjustedTargetPos;
|
||||||
|
private _adjustVector = _targetVector vectorDiff (vectorDir _projectile);
|
||||||
|
_adjustVector params ["_adjustVectorX", "_adjustVectorY", "_adjustVectorZ"];
|
||||||
|
|
||||||
|
private _yaw = 0;
|
||||||
|
private _pitch = 0;
|
||||||
|
private _roll = 0;
|
||||||
|
|
||||||
|
if (_adjustVectorX < 0) then {
|
||||||
|
_yaw = - ( (_minDeflection max ((abs _adjustVectorX) min _maxDeflection) ) );
|
||||||
|
} else {
|
||||||
|
if (_adjustVectorX > 0) then {
|
||||||
|
_yaw = ( (_minDeflection max (_adjustVectorX min _maxDeflection) ) );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (_adjustVectorY < 0) then {
|
||||||
|
_roll = - ( (_minDeflection max ((abs _adjustVectorY) min _maxDeflection) ) );
|
||||||
|
} else {
|
||||||
|
if (_adjustVectorY > 0) then {
|
||||||
|
_roll = ( (_minDeflection max (_adjustVectorY min _maxDeflection) ) );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (_adjustVectorZ < 0) then {
|
||||||
|
_pitch = - ( (_minDeflection max ((abs _adjustVectorZ) min _maxDeflection) ) );
|
||||||
|
} else {
|
||||||
|
if (_adjustVectorZ > 0) then {
|
||||||
|
_pitch = ( (_minDeflection max (_adjustVectorZ min _maxDeflection) ) );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
private _finalAdjustVector = [_yaw, _roll, _pitch];
|
||||||
|
|
||||||
|
TRACE_3("", _pitch, _yaw, _roll);
|
||||||
|
TRACE_3("", _targetVector, _adjustVector, _finalAdjustVector);
|
||||||
|
|
||||||
|
if (accTime > 0) then {
|
||||||
|
private _changeVector = (vectorDir _projectile) vectorAdd _finalAdjustVector;
|
||||||
|
TRACE_2("",_projectile,_changeVector);
|
||||||
|
[_projectile, _changeVector] call FUNC(changeMissileDirection);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_profileAdjustedTargetPos = [_seekerTargetPos,_args, (_stateParams select 2)] call FUNC(doAttackProfile);
|
#ifdef DRAW_GUIDANCE_INFO
|
||||||
_targetVector = _projectilePos vectorFromTo _profileAdjustedTargetPos;
|
TRACE_3("",_projectilePos,_seekerTargetPos,_profileAdjustedTargetPos);
|
||||||
_adjustVector = _targetVector vectorDiff (vectorDir _projectile);
|
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,0,1], ASLtoAGL _projectilePos, 0.75, 0.75, 0, _ammo, 1, 0.025, "TahomaB"];
|
||||||
|
|
||||||
_yaw = 0;
|
private _ps = "#particlesource" createVehicleLocal (ASLtoAGL _projectilePos);
|
||||||
_pitch = 0;
|
|
||||||
_roll = 0;
|
|
||||||
if((_adjustVector select 0) < 0) then {
|
|
||||||
_yaw = - ( (_minDeflection max (abs(_adjustVector select 0) min _maxDeflection) ) );
|
|
||||||
} else {
|
|
||||||
if((_adjustVector select 0) > 0) then {
|
|
||||||
_yaw = ( (_minDeflection max ((_adjustVector select 0) min _maxDeflection) ) );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
if((_adjustVector select 1) < 0) then {
|
|
||||||
_roll = - ( (_minDeflection max (abs(_adjustVector select 1) min _maxDeflection) ) );
|
|
||||||
} else {
|
|
||||||
if((_adjustVector select 1) > 0) then {
|
|
||||||
_roll = ( (_minDeflection max ((_adjustVector select 1) min _maxDeflection) ) );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
if((_adjustVector select 2) < 0) then {
|
|
||||||
_pitch = - ( (_minDeflection max (abs(_adjustVector select 2) min _maxDeflection) ) );
|
|
||||||
} else {
|
|
||||||
if((_adjustVector select 2) > 0) then {
|
|
||||||
_pitch = ( (_minDeflection max ((_adjustVector select 2) min _maxDeflection) ) );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
_finalAdjustVector = [_yaw, _roll, _pitch];
|
|
||||||
TRACE_2("", _pitch, _yaw);
|
|
||||||
TRACE_4("", _targetVector, _targetRelativeVector, _adjustVector, _finalAdjustVector);
|
|
||||||
|
|
||||||
if(accTime > 0) then {
|
|
||||||
_changeVector = (vectorDir _projectile) vectorAdd _finalAdjustVector;
|
|
||||||
[_projectile, _changeVector] call FUNC(changeMissileDirection);
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef DEBUG_MODE_FULL
|
|
||||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoAGL _projectilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"];
|
|
||||||
drawLine3D [ASLtoAGL _projectilePos, ASLtoAGL _profileAdjustedTargetPos, [1,0,0,1]];
|
|
||||||
|
|
||||||
_ps = "#particlesource" createVehicleLocal (ASLtoAGL _projectilePos);
|
|
||||||
_PS setParticleParams [["\A3\Data_f\cl_basic", 8, 3, 1], "", "Billboard", 1, 3.0141, [0, 0, 2], [0, 0, 0], 1, 1.275, 1, 0, [1, 1], [[1, 0, 0, 1], [1, 0, 0, 1], [1, 0, 0, 1]], [1], 1, 0, "", "", nil];
|
_PS setParticleParams [["\A3\Data_f\cl_basic", 8, 3, 1], "", "Billboard", 1, 3.0141, [0, 0, 2], [0, 0, 0], 1, 1.275, 1, 0, [1, 1], [[1, 0, 0, 1], [1, 0, 0, 1], [1, 0, 0, 1]], [1], 1, 0, "", "", nil];
|
||||||
_PS setDropInterval 3.0;
|
_PS setDropInterval 3.0;
|
||||||
|
|
||||||
//hintSilent format["d: %1", _distanceToTarget];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_stateParams set[0, diag_tickTime];
|
_stateParams set [0, diag_tickTime];
|
||||||
|
|
||||||
|
END_COUNTER(guidancePFH);
|
||||||
|
|
||||||
_args set[4, _stateParams];
|
|
||||||
_this set[0, _args];
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
// Not currently used
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
PARAMS_2(_target,_args);
|
PARAMS_2(_target,_args);
|
||||||
|
|
||||||
if(isNil "_target" || {isNull _target} || {!local _target} ) exitWith { false };
|
if (isNil "_target" || {isNull _target} || {!local _target} ) exitWith { false };
|
||||||
|
|
||||||
[FUNC(guidancePFH), 0, _args] call CBA_fnc_addPerFrameHandler;
|
[FUNC(guidancePFH), 0, _args] call CBA_fnc_addPerFrameHandler;
|
@ -1,44 +1,58 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Fired event handler, starts guidance if enabled for ammo
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Shooter (Man/Vehicle) <OBJECT>
|
||||||
|
* 4: Ammo <STRING>
|
||||||
|
* 6: Projectile <OBJECT>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Nothing
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [player, "", "", "", "ACE_Javelin_FGM148", "", theMissile] call ace_missileguidance_fnc_onFired;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
params ["_shooter","","","","_ammo","","_projectile"];
|
||||||
|
|
||||||
// Bail if guidance is disabled
|
|
||||||
// Bail on locality of the projectile, it should be local to us
|
|
||||||
if(GVAR(enabled) < 1 || {!local _projectile} ) exitWith { false };
|
|
||||||
|
|
||||||
//Bail if shooter isn't player AND system not enabled for AI:
|
|
||||||
if( !isPlayer _shooter && { GVAR(enabled) < 2 } ) exitWith { false };
|
|
||||||
|
|
||||||
// Bail on not missile
|
// Bail on not missile
|
||||||
if(! (_ammo isKindOf "MissileBase") ) exitWith { false };
|
if (!(_ammo isKindOf "MissileBase")) exitWith {};
|
||||||
|
|
||||||
private ["_config", "_configs", "_enabled", "_target", "_seekerType", "_attackProfile"];
|
// Bail if guidance is disabled for this ammo
|
||||||
private ["_args", "_canUseLock", "_guidingUnit", "_launchPos", "_lockMode", "_targetPos", "_vanillaTarget"];
|
if ((getNumber (configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON) >> "enabled")) != 1) exitWith {};
|
||||||
|
|
||||||
//Verify ammo has explicity added guidance config (ignore inheritances)
|
// Bail on locality of the projectile, it should be local to us
|
||||||
_configs = configProperties [(configFile >> "CfgAmmo" >> _ammo), QUOTE(configName _x == QUOTE(QUOTE(ADDON))), false];
|
if (GVAR(enabled) < 1 || {!local _projectile} ) exitWith {};
|
||||||
if( (count _configs) < 1) exitWith {};
|
|
||||||
|
|
||||||
_config = (configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON));
|
// Bail if shooter isn't player AND system not enabled for AI:
|
||||||
_enabled = getNumber ( _config >> "enabled");
|
if ( !isPlayer _shooter && { GVAR(enabled) < 2 } ) exitWith {};
|
||||||
|
|
||||||
// Bail if guidance is not enabled
|
// Verify ammo has explicity added guidance config (ignore inheritances)
|
||||||
if(isNil "_enabled" || {_enabled != 1}) exitWith { false };
|
private _configs = configProperties [(configFile >> "CfgAmmo" >> _ammo), QUOTE(configName _x == QUOTE(QUOTE(ADDON))), false];
|
||||||
|
if ((count _configs) < 1) exitWith {};
|
||||||
|
|
||||||
_target = (vehicle _shooter) getVariable [QGVAR(target), nil];
|
// MissileGuidance is enabled for this shot
|
||||||
_targetPos = (vehicle _shooter) getVariable [QGVAR(targetPosition), nil];
|
TRACE_4("enabled",_shooter,_ammo,_projectile,typeOf _shooter);
|
||||||
_seekerType = (vehicle _shooter) getVariable [QGVAR(seekerType), nil];
|
|
||||||
_attackProfile = (vehicle _shooter) getVariable [QGVAR(attackProfile), nil];
|
|
||||||
_lockMode = (vehicle _shooter) getVariable [QGVAR(lockMode), nil];
|
|
||||||
|
|
||||||
// @TODO: make this vehicle shooter, but we need to differentiate where its set in ace_laser
|
private _config = configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON);
|
||||||
_laserCode = _shooter getVariable [QEGVAR(laser,code), ACE_DEFAULT_LASER_CODE];
|
|
||||||
_laserInfo = [_laserCode, ACE_DEFAULT_LASER_WAVELENGTH, ACE_DEFAULT_LASER_WAVELENGTH];
|
|
||||||
|
|
||||||
_launchPos = getPosASL (vehicle _shooter);
|
private _target = _shooter getVariable [QGVAR(target), nil];
|
||||||
|
private _targetPos = _shooter getVariable [QGVAR(targetPosition), nil];
|
||||||
|
private _seekerType = _shooter getVariable [QGVAR(seekerType), nil];
|
||||||
|
private _attackProfile = _shooter getVariable [QGVAR(attackProfile), nil];
|
||||||
|
private _lockMode = _shooter getVariable [QGVAR(lockMode), nil];
|
||||||
|
|
||||||
TRACE_3("Begin guidance", _target, _seekerType, _attackProfile);
|
private _laserCode = _shooter getVariable [QEGVAR(laser,code), ACE_DEFAULT_LASER_CODE];
|
||||||
|
private _laserInfo = [_laserCode, ACE_DEFAULT_LASER_WAVELENGTH, ACE_DEFAULT_LASER_WAVELENGTH];
|
||||||
|
|
||||||
|
TRACE_6("getVars",_target,_targetPos,_seekerType,_attackProfile,_lockMode,_laserCode);
|
||||||
|
|
||||||
|
private _launchPos = getPosASL (vehicle _shooter);
|
||||||
|
|
||||||
if (isNil "_seekerType" || {!(_seekerType in (getArray (_config >> "seekerTypes")))}) then {
|
if (isNil "_seekerType" || {!(_seekerType in (getArray (_config >> "seekerTypes")))}) then {
|
||||||
_seekerType = getText (_config >> "defaultSeekerType");
|
_seekerType = getText (_config >> "defaultSeekerType");
|
||||||
@ -51,28 +65,37 @@ if (isNil "_lockMode" || {!(_lockMode in (getArray (_config >> "seekerLockModes"
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If we didn't get a target, try to fall back on tab locking
|
// If we didn't get a target, try to fall back on tab locking
|
||||||
if(isNil "_target") then {
|
if (isNil "_target") then {
|
||||||
if(!isPlayer _shooter) then {
|
if (!isPlayer _shooter) then {
|
||||||
// This was an AI shot, lets still guide it on the AI target
|
// This was an AI shot, lets still guide it on the AI target
|
||||||
_target = _shooter getVariable[QGVAR(vanilla_target), nil];
|
_target = _shooter getVariable [QGVAR(vanilla_target), nil];
|
||||||
TRACE_1("Detected AI Shooter!", _target);
|
TRACE_1("Detected AI Shooter!", _target);
|
||||||
} else {
|
} else {
|
||||||
_canUseLock = getNumber (_config >> "canVanillaLock");
|
private _canUseLock = getNumber (_config >> "canVanillaLock");
|
||||||
// @TODO: Get vanilla target
|
// @TODO: Get vanilla target
|
||||||
if(_canUseLock > 0 || difficulty < 1) then {
|
if (_canUseLock > 0 || difficulty < 1) then {
|
||||||
_vanillaTarget = cursorTarget;
|
private _vanillaTarget = cursorTarget;
|
||||||
|
|
||||||
TRACE_1("Using Vanilla Locking", _vanillaTarget);
|
TRACE_1("Using Vanilla Locking", _vanillaTarget);
|
||||||
if(!isNil "_vanillaTarget") then {
|
if (!isNil "_vanillaTarget") then {
|
||||||
_target = _vanillaTarget;
|
_target = _vanillaTarget;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Array for seek last target position
|
||||||
|
private _seekLastTargetPos = (getNumber ( _config >> "seekLastTargetPos")) == 1;
|
||||||
|
private _lastKnownPosState = [_seekLastTargetPos];
|
||||||
|
if (_seekLastTargetPos && {!isNil "_target"}) then {
|
||||||
|
_lastKnownPosState set [1, (getPosASL _target)];
|
||||||
|
} else {
|
||||||
|
_lastKnownPosState set [1, [0,0,0]];
|
||||||
|
};
|
||||||
|
|
||||||
TRACE_4("Beginning ACE guidance system",_target,_ammo,_seekerType,_attackProfile);
|
TRACE_4("Beginning ACE guidance system",_target,_ammo,_seekerType,_attackProfile);
|
||||||
_args = [_this,
|
private _args = [_this,
|
||||||
[_shooter,
|
[ _shooter,
|
||||||
[_target, _targetPos, _launchPos],
|
[_target, _targetPos, _launchPos],
|
||||||
_seekerType,
|
_seekerType,
|
||||||
_attackProfile,
|
_attackProfile,
|
||||||
@ -89,30 +112,41 @@ _args = [_this,
|
|||||||
getNumber ( _config >> "seekerAccuracy" ),
|
getNumber ( _config >> "seekerAccuracy" ),
|
||||||
getNumber ( _config >> "seekerMaxRange" )
|
getNumber ( _config >> "seekerMaxRange" )
|
||||||
],
|
],
|
||||||
[ diag_tickTime, [], [] ]
|
[ diag_tickTime, [], [], _lastKnownPosState]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Reverse:
|
||||||
|
// _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"];
|
||||||
|
// _firedEH params ["_shooter","","","","_ammo","","_projectile"];
|
||||||
|
// _launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo"];
|
||||||
|
// _targetLaunchParams params ["_target", "_targetPos", "_launchPos"];
|
||||||
|
// _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState"];
|
||||||
|
// _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange"];
|
||||||
|
|
||||||
|
|
||||||
// Hand off to the guiding unit. We just use local player so local PFH fires for now
|
// Hand off to the guiding unit. We just use local player so local PFH fires for now
|
||||||
// Laser code needs to give us a shooter for LOBL, or the seeker unit needs to be able to shift locality
|
// Laser code needs to give us a shooter for LOBL, or the seeker unit needs to be able to shift locality
|
||||||
// Based on its homing laser
|
// Based on its homing laser
|
||||||
// Lasers need to be handled in a special LOAL/LOBL case
|
// Lasers need to be handled in a special LOAL/LOBL case
|
||||||
|
|
||||||
//if(isPlayer _shooter) then {
|
//if (isPlayer _shooter) then {
|
||||||
// _guidingUnit = ACE_player;
|
// private _guidingUnit = ACE_player;
|
||||||
//
|
//
|
||||||
// if(local _guidingUnit) then {
|
// if (local _guidingUnit) then {
|
||||||
// [FUNC(guidancePFH), 0, _args ] call CBA_fnc_addPerFrameHandler;
|
// [FUNC(guidancePFH), 0, _args ] call CBA_fnc_addPerFrameHandler;
|
||||||
// } else {
|
// } else {
|
||||||
// [QGVAR(handoff), [_guidingUnit, _args] ] call FUNC(doHandoff);
|
// [QGVAR(handoff), [_guidingUnit, _args] ] call FUNC(doHandoff);
|
||||||
// };
|
// };
|
||||||
//} else {
|
//} else {
|
||||||
[FUNC(guidancePFH), 0, _args ] call CBA_fnc_addPerFrameHandler;
|
// [FUNC(guidancePFH), 0, _args ] call CBA_fnc_addPerFrameHandler;
|
||||||
//};
|
//};
|
||||||
|
|
||||||
|
[FUNC(guidancePFH), 0, _args ] call CBA_fnc_addPerFrameHandler;
|
||||||
|
|
||||||
|
|
||||||
/* Clears locking settings
|
/* Clears locking settings
|
||||||
(vehicle _shooter) setVariable [QGVAR(target), nil];
|
(vehicle _shooter) setVariable [QGVAR(target), nil];
|
||||||
(vehicle _shooter) setVariable [QGVAR(seekerType), nil];
|
(vehicle _shooter) setVariable [QGVAR(seekerType), nil];
|
||||||
(vehicle _shooter) setVariable [QGVAR(attackProfile), nil];
|
(vehicle _shooter) setVariable [QGVAR(attackProfile), nil];
|
||||||
(vehicle _shooter) setVariable [QGVAR(lockMode), nil];
|
(vehicle _shooter) setVariable [QGVAR(lockMode), nil];
|
||||||
*/
|
*/
|
||||||
|
@ -1,8 +1,27 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Handles AI shooting a locking missile
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 0: Target <OBJECT>
|
||||||
|
* 1: Ammo <STRING>
|
||||||
|
* 2: Shooter <OBJECT>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [cursorTarget, "x", player] call ace_missileguidance_fnc_changeMissileDirection;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
PARAMS_3(_target,_ammo,_shooter);
|
|
||||||
|
|
||||||
if(GVAR(enabled) < 1) exitWith {}; // bail if enabled
|
params ["_target", "_ammo", "_shooter"];
|
||||||
|
|
||||||
|
if (GVAR(enabled) < 1) exitWith {}; // bail if enabled
|
||||||
if !(local (gunner _shooter) || {local _shooter}) exitWith {}; // bail if not shooter
|
if !(local (gunner _shooter) || {local _shooter}) exitWith {}; // bail if not shooter
|
||||||
|
|
||||||
_shooter setVariable [QGVAR(vanilla_target),_target, false];
|
_shooter setVariable [QGVAR(vanilla_target),_target, false];
|
||||||
|
TRACE_2("setting vanilla target",_shooter,_target);
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
#include "script_component.hpp"
|
|
||||||
private ["_d", "_map", "_p", "_theta", "_u"];
|
|
||||||
|
|
||||||
_map = _this select 0;
|
|
||||||
_theta = _this select 1;
|
|
||||||
|
|
||||||
_p = _map select 0;
|
|
||||||
_p1 = _map select 1;
|
|
||||||
_p2 = _map select 2;
|
|
||||||
|
|
||||||
_q1 = +(_map select 3);
|
|
||||||
_q2 = +(_map select 4);
|
|
||||||
_u = _map select 5;
|
|
||||||
_d = _map select 6;
|
|
||||||
|
|
||||||
/* Step 4 */
|
|
||||||
_q2 set[0, (_q1 select 0) * cos(_theta) - (_q1 select 1) * sin(_theta)];
|
|
||||||
_q2 set[1, (_q1 select 0) * sin(_theta) + (_q1 select 1) * cos(_theta)];
|
|
||||||
_q2 set[2, (_q1 select 2)];
|
|
||||||
|
|
||||||
/* Inverse of step 3 */
|
|
||||||
_q1 set[0, (_q2 select 0) * _d + (_q2 select 2) * (_u select 0)];
|
|
||||||
_q1 set[1, (_q2 select 1)];
|
|
||||||
_q1 set[2, - (_q2 select 0) * (_u select 0) + (_q2 select 2) * _d];
|
|
||||||
|
|
||||||
/* Inverse of step 2 */
|
|
||||||
if (_d != 0) then {
|
|
||||||
_q2 set[0, (_q1 select 0)];
|
|
||||||
_q2 set[1, (_q1 select 1) * (_u select 2) / _d + (_q1 select 2) * (_u select 1) / _d];
|
|
||||||
_q2 set[2, - (_q1 select 1) * (_u select 1) / _d + (_q1 select 2) * (_u select 2) / _d];
|
|
||||||
} else {
|
|
||||||
_q2 = _q1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Inverse of step 1 */
|
|
||||||
_q1 set[0, (_q2 select 0) + (_p1 select 0)];
|
|
||||||
_q1 set[1, (_q2 select 1) + (_p1 select 1)];
|
|
||||||
_q1 set[2, (_q2 select 2) + (_p1 select 2)];
|
|
||||||
_q1;
|
|
@ -1,37 +0,0 @@
|
|||||||
#include "script_component.hpp"
|
|
||||||
|
|
||||||
private ["_p", "_theta", "_p1", "_p2", "_q1", "_q2", "_u", "_d"];
|
|
||||||
_p = _this select 0;
|
|
||||||
_p1 = _this select 1;
|
|
||||||
_p2 = _this select 2;
|
|
||||||
|
|
||||||
_q1 = [];
|
|
||||||
_q2 = [];
|
|
||||||
_u = [];
|
|
||||||
|
|
||||||
/* Step 1 */
|
|
||||||
_q1 set[0, (_p select 0) - (_p1 select 0)];
|
|
||||||
_q1 set[1, (_p select 1) - (_p1 select 1)];
|
|
||||||
_q1 set[2, (_p select 2) - (_p1 select 2)];
|
|
||||||
|
|
||||||
_u set[0, (_p2 select 0) - (_p1 select 0)];
|
|
||||||
_u set[1, (_p2 select 1) - (_p1 select 1)];
|
|
||||||
_u set[2, (_p2 select 2) - (_p1 select 2)];
|
|
||||||
_u = _u call BIS_fnc_unitVector;
|
|
||||||
_d = sqrt((_u select 1)*(_u select 1) + (_u select 2)*(_u select 2));
|
|
||||||
|
|
||||||
/* Step 2 */
|
|
||||||
if (_d != 0) then {
|
|
||||||
_q2 set[0, (_q1 select 0)];
|
|
||||||
_q2 set[1, (_q1 select 1) * (_u select 2) / _d - (_q1 select 2) * (_u select 1) / _d];
|
|
||||||
_q2 set[2, (_q1 select 1) * (_u select 1) / _d + (_q1 select 2) * (_u select 2) / _d];
|
|
||||||
} else {
|
|
||||||
_q2 = _q1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Step 3 */
|
|
||||||
_q1 set[0, (_q2 select 0) * _d - (_q2 select 2) * (_u select 0)];
|
|
||||||
_q1 set[1, (_q2 select 1)];
|
|
||||||
_q1 set[2, (_q2 select 0) * (_u select 0) + (_q2 select 2) * _d];
|
|
||||||
|
|
||||||
[_p, _p1, _p2, _q1, _q2, _u, _d]
|
|
@ -1,52 +1,54 @@
|
|||||||
//#define DEBUG_MODE_FULL
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Seeker Type: Optic
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Seeker State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[], [], []] call ace_missileguidance_fnc_seekerType_Optic;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
params ["", "_args"];
|
||||||
private ["_targets", "_foundTargetPos", "_launchParams", "_seekerParams", "_targetLaunchParams"];
|
_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams"];
|
||||||
private ["_angleFov", "_angleOkay", "_losOkay", "_seekerTargetPos", "_sensorPos", "_target"];
|
_firedEH params ["","","","","","","_projectile"];
|
||||||
|
_launchParams params ["", "_targetParams"];
|
||||||
|
_targetParams params ["_target"];
|
||||||
|
_seekerParams params ["_seekerAngle", "", "_seekerMaxRange"];
|
||||||
|
|
||||||
_seekerTargetPos = _this select 0;
|
if (isNil "_target") exitWith {[0,0,0]};
|
||||||
|
|
||||||
_launchParams = _this select 1;
|
private _foundTargetPos = aimPos _target;
|
||||||
_target = (((_launchParams select 1) select 1) select 0);
|
|
||||||
_seekerParams = _launchParams select 3;
|
|
||||||
|
|
||||||
TRACE_1("", _this);
|
|
||||||
TRACE_1("", _launchParams);
|
|
||||||
|
|
||||||
// TODO:: Make sure the missile maintains LOS
|
|
||||||
_foundTargetPos = [0,0,0];
|
|
||||||
if(!isNil "_target") then {
|
|
||||||
_foundTargetPos = aimPos _target ;
|
|
||||||
//_foundTargetPos = (_target modelToWorldVisual (getCenterOfMass _target));
|
|
||||||
};
|
|
||||||
|
|
||||||
// @TODO: This is seeker LOS and angle checks for LOAL only; LOBL does not need visual
|
// @TODO: This is seeker LOS and angle checks for LOAL only; LOBL does not need visual
|
||||||
_angleFov = _seekerParams select 0;
|
private _angleOkay = [_projectile, _foundTargetPos, _seekerAngle] call FUNC(checkSeekerAngle);
|
||||||
_angleOkay = [_projectile, _foundTargetPos, _angleFov] call FUNC(checkSeekerAngle);
|
|
||||||
|
|
||||||
_losOkay = false;
|
private _losOkay = false;
|
||||||
if(_angleOkay) then {
|
if (_angleOkay) then {
|
||||||
_losOkay = [_projectile, _target] call FUNC(checkLos);
|
_losOkay = [_projectile, _target] call FUNC(checkLos);
|
||||||
};
|
};
|
||||||
TRACE_2("", _angleOkay, _losOkay);
|
TRACE_2("", _angleOkay, _losOkay);
|
||||||
|
|
||||||
// If we got here, it was an invalid target, just return a spot 5m in front of the missile
|
// Can't see target, return [0,0,0] and let doSeekerSearch handle it
|
||||||
if(!_angleOkay || !_losOkay) then {
|
if (!_angleOkay || !_losOkay) exitWith {[0,0,0]};
|
||||||
_foundTargetPos = _sensorPos vectorAdd ((velocity _projectile) vectorMultiply 5);
|
|
||||||
} else {
|
|
||||||
TRACE_2("", _target, _foundTargetPos);
|
|
||||||
private ["_projectileSpeed", "_distanceToTarget", "_eta", "_adjustDistance"];
|
|
||||||
// @TODO: Configurable lead for seekers
|
|
||||||
_projectileSpeed = (vectorMagnitude velocity _projectile);
|
|
||||||
_distanceToTarget = (getPosASL _projectile) vectorDistance _foundTargetPos;
|
|
||||||
|
|
||||||
_eta = _distanceToTarget / _projectileSpeed;
|
TRACE_2("", _target, _foundTargetPos);
|
||||||
|
// @TODO: Configurable lead for seekers
|
||||||
|
private _projectileSpeed = (vectorMagnitude velocity _projectile);
|
||||||
|
private _distanceToTarget = (getPosASL _projectile) vectorDistance _foundTargetPos;
|
||||||
|
private _eta = _distanceToTarget / _projectileSpeed;
|
||||||
|
|
||||||
_adjustDistance = (velocity _target) vectorMultiply _eta;
|
private _adjustDistance = (velocity _target) vectorMultiply _eta;
|
||||||
TRACE_3("leading target",_distanceToTarget,_eta,_adjustDistance);
|
TRACE_3("leading target",_distanceToTarget,_eta,_adjustDistance);
|
||||||
_foundTargetPos = _foundTargetPos vectorAdd _adjustDistance;
|
_foundTargetPos = _foundTargetPos vectorAdd _adjustDistance;
|
||||||
};
|
|
||||||
|
|
||||||
TRACE_2("return",_foundTargetPos,(aimPos _target) distance _foundTargetPos);
|
TRACE_2("return",_foundTargetPos,(aimPos _target) distance _foundTargetPos);
|
||||||
_foundTargetPos;
|
_foundTargetPos;
|
||||||
|
@ -1,32 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Author: jaynus / nou
|
||||||
|
* Seeker Type: SALH (Laser)
|
||||||
|
* Wrapper for ace_laser_fnc_seekerFindLaserSpot
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 1: Guidance Arg Array <ARRAY>
|
||||||
|
* 2: Seeker State <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* Missile Aim PosASL <ARRAY>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [[], [], []] call ace_missileguidance_fnc_seekerType_SALH;
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
// #define DEBUG_MODE_FULL
|
// #define DEBUG_MODE_FULL
|
||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
params ["_lastSeekTargetPos", "_args"];
|
params ["", "_args"];
|
||||||
_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"];
|
_args params ["_firedEH", "_launchParams", "", "_seekerParams"];
|
||||||
_firedEH params ["_shooter","_weapon","_muzzle","_mode","_ammo","_magazine","_projectile"];
|
_firedEH params ["","","","","","","_projectile"];
|
||||||
_launchParams params ["","","","","","_laserParams"];
|
_launchParams params ["","","","","","_laserParams"];
|
||||||
_seekerParams params ["_seekerAngle", "", "_seekerMaxRange"];
|
_seekerParams params ["_seekerAngle", "", "_seekerMaxRange"];
|
||||||
_laserParams params ["_code", "_wavelengthMin", "_wavelengthMax"];
|
_laserParams params ["_code", "_wavelengthMin", "_wavelengthMax"];
|
||||||
|
|
||||||
private "_foundTargetPos";
|
|
||||||
|
|
||||||
if (!isNil "_target") then {
|
private _laserResult = [(getPosASL _projectile), (velocity _projectile), _seekerAngle, _seekerMaxRange, [_wavelengthMin, _wavelengthMax], _code, _projectile] call EFUNC(laser,seekerFindLaserSpot);
|
||||||
// Handle AI or moving vanilla lasers
|
private _foundTargetPos = _laserResult select 0;
|
||||||
_foundTargetPos = getPosASL _target;
|
TRACE_1("Search", _laserResult);
|
||||||
} else {
|
|
||||||
private _laserResult = [(getPosASL _projectile), (velocity _projectile), _seekerAngle, [_wavelengthMin, _wavelengthMax], _code, _projectile] call EFUNC(laser,seekerFindLaserSpot);
|
|
||||||
_foundTargetPos = _laserResult select 0;
|
|
||||||
TRACE_1("Search", _laserResult);
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!isNil "_foundTargetPos") then {
|
|
||||||
// Fov is already checked by laser func, check if distance
|
|
||||||
|
|
||||||
private _canSeeTarget = _seekerMaxRange >= (_foundTargetPos vectorDistance (getPosASL _projectile));
|
|
||||||
// If we got here, it was an invalid target, just return a spot 5m in front of the missile
|
|
||||||
if(!_canSeeTarget) then {
|
|
||||||
_foundTargetPos = _sensorPos vectorAdd ((velocity _projectile) vectorMultiply 5);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
_foundTargetPos;
|
_foundTargetPos;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define COMPONENT_BEAUTIFIED Missile Guidance
|
#define COMPONENT_BEAUTIFIED Missile Guidance
|
||||||
#include "\z\ace\addons\main\script_mod.hpp"
|
#include "\z\ace\addons\main\script_mod.hpp"
|
||||||
|
|
||||||
|
// #define DRAW_GUIDANCE_INFO
|
||||||
// #define DEBUG_MODE_FULL
|
// #define DEBUG_MODE_FULL
|
||||||
// #define DISABLE_COMPILE_CACHE
|
// #define DISABLE_COMPILE_CACHE
|
||||||
// #define ENABLE_PERFORMANCE_COUNTERS
|
// #define ENABLE_PERFORMANCE_COUNTERS
|
||||||
@ -15,5 +16,3 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "\z\ace\addons\main\script_macros.hpp"
|
#include "\z\ace\addons\main\script_macros.hpp"
|
||||||
|
|
||||||
#define FIREMODE_DIRECT_LOAL 1
|
|
||||||
|
Reference in New Issue
Block a user