diff --git a/addons/laser/functions/fnc_dev_drawVisibleLaserTargets.sqf b/addons/laser/functions/fnc_dev_drawVisibleLaserTargets.sqf index 00a4e8a5e6..7598bf8f46 100644 --- a/addons/laser/functions/fnc_dev_drawVisibleLaserTargets.sqf +++ b/addons/laser/functions/fnc_dev_drawVisibleLaserTargets.sqf @@ -14,7 +14,7 @@ private _testSeekerPosASL = AGLtoASL (_seekerVehicle modelToWorldVisual [0,0,1]) private _testSeekerDir = vectorDirVisual _seekerVehicle; { 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; if (!isNil "_resultPos") then { // Draw lock results diff --git a/addons/laser/functions/fnc_seekerFindLaserSpot.sqf b/addons/laser/functions/fnc_seekerFindLaserSpot.sqf index c16e4389e2..612cc17fe5 100644 --- a/addons/laser/functions/fnc_seekerFindLaserSpot.sqf +++ b/addons/laser/functions/fnc_seekerFindLaserSpot.sqf @@ -7,9 +7,10 @@ * 0: Position of seeker (ASL) * 1: Direction vector (will be normalized) * 2: Seeker FOV in degrees - * 3: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. - * 4: Seeker laser code. - * 5: Ignore 1 (e.g. Player's vehicle) + * 3: Seeker max distance in meters + * 4: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. + * 5: Seeker laser code. + * 6: Ignore 1 (e.g. Player's vehicle) * * Return Value: * Array, [Strongest compatible laser spot ASL pos, owner object] Nil array values if nothing found. @@ -24,13 +25,15 @@ BEGIN_COUNTER(seekerFindLaserSpot); -params ["_posASL", "_dir", "_seekerFov", "_seekerWavelengths", "_seekerCode", ["_ignoreObj1", objNull]]; +params ["_posASL", "_dir", "_seekerFov", "_seekerMaxDistnace", "_seekerWavelengths", "_seekerCode", ["_ignoreObj1", objNull]]; _dir = vectorNormalized _dir; _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 _finalPos = nil; @@ -76,7 +79,7 @@ private _finalOwner = objNull; _testPoint = _x select 0; private _testPointVector = _posASL vectorFromTo _testPoint; private _testDotProduct = _dir vectorDotProduct _testPointVector; - if (_testDotProduct > _seekerCos) then { + if ((_testDotProduct > _seekerCos) && {(_testPoint vectorDistanceSqr _posASL) < _seekerMaxDistSq}) then { _spots pushBack [_testPoint, _owner]; }; } forEach _resultPositions; @@ -87,7 +90,7 @@ private _finalOwner = objNull; if (_distance > 0) then { private _testPointVector = _posASL vectorFromTo _resultPos; private _testDotProduct = _dir vectorDotProduct _testPointVector; - if (_testDotProduct > _seekerCos) then { + if ((_testDotProduct > _seekerCos) && {(_testPoint vectorDistanceSqr _posASL) < _seekerMaxDistSq}) then { _spots pushBack [_resultPos, _owner]; }; }; diff --git a/addons/missileguidance/ACE_Settings.hpp b/addons/missileguidance/ACE_Settings.hpp index e73d533c08..6394e75390 100644 --- a/addons/missileguidance/ACE_Settings.hpp +++ b/addons/missileguidance/ACE_Settings.hpp @@ -2,9 +2,8 @@ class ACE_Settings { class GVAR(enabled) { value = 2; typeName = "SCALAR"; - isClientSettable = 1; displayName = CSTRING(Title); description = CSTRING(Desc); values[] = {CSTRING(Off), CSTRING(PlayerOnly), CSTRING(PlayerAndAi)}; }; -}; \ No newline at end of file +}; diff --git a/addons/missileguidance/CfgAmmo.hpp b/addons/missileguidance/CfgAmmo.hpp index 1d2c58ad93..343b911f23 100644 --- a/addons/missileguidance/CfgAmmo.hpp +++ b/addons/missileguidance/CfgAmmo.hpp @@ -108,6 +108,8 @@ class CfgAmmo { seekerMinRange = 0; 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 defaultAttackProfile = "JAV_TOP"; attackProfiles[] = { "JAV_TOP", "JAV_DIR" }; diff --git a/addons/missileguidance/XEH_PREP.hpp b/addons/missileguidance/XEH_PREP.hpp index 55948e7171..8d13e2b499 100644 --- a/addons/missileguidance/XEH_PREP.hpp +++ b/addons/missileguidance/XEH_PREP.hpp @@ -1,6 +1,4 @@ -PREP(rotateVectLineGetMap); -PREP(rotateVectLine); PREP(changeMissileDirection); PREP(checkSeekerAngle); @@ -17,11 +15,11 @@ PREP(doHandoff); PREP(handleHandoff); // Attack Profiles -PREP(attackProfile_LIN); -PREP(attackProfile_DIR); -PREP(attackProfile_MID); -PREP(attackProfile_HI); PREP(attackProfile_AIR); +PREP(attackProfile_DIR); +PREP(attackProfile_HI); +PREP(attackProfile_LIN); +PREP(attackProfile_MID); // Javelin profiles PREP(attackProfile_JAV_DIR); diff --git a/addons/missileguidance/functions/fnc_attackProfile_AIR.sqf b/addons/missileguidance/functions/fnc_attackProfile_AIR.sqf index 9909124e2f..3d2b5f36b8 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_AIR.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_AIR.sqf @@ -1,4 +1,22 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Attack profile: AIR + * TODO: falls back to Linear + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Seeker State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_AIR; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -_this call FUNC(attackProfile_LIN); \ No newline at end of file +_this call FUNC(attackProfile_LIN); diff --git a/addons/missileguidance/functions/fnc_attackProfile_DIR.sqf b/addons/missileguidance/functions/fnc_attackProfile_DIR.sqf index 9909124e2f..8e049a9fe2 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_DIR.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_DIR.sqf @@ -1,4 +1,22 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Attack profile: DIR + * TODO: falls back to Linear + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Seeker State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_DIR; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -_this call FUNC(attackProfile_LIN); \ No newline at end of file +_this call FUNC(attackProfile_LIN); diff --git a/addons/missileguidance/functions/fnc_attackProfile_HI.sqf b/addons/missileguidance/functions/fnc_attackProfile_HI.sqf index 9909124e2f..279196a888 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_HI.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_HI.sqf @@ -1,4 +1,22 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Attack profile: HI + * TODO: falls back to Linear + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Attack Profile State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_HI; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -_this call FUNC(attackProfile_LIN); \ No newline at end of file +_this call FUNC(attackProfile_LIN); diff --git a/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf b/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf index adcdc703de..4740bf6f0f 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf @@ -1,4 +1,21 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Attack profile: Javelin Dir + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Attack Profile State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_JAV_DIR; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" #define STAGE_LAUNCH 1 @@ -6,48 +23,41 @@ #define STAGE_COAST 3 #define STAGE_TERMINAL 4 -EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); -private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"]; -private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_state"]; -private["_cruisAlt", "_distanceShooterToTarget", "_shooterPos"]; -_seekerTargetPos = _this select 0; -_launchParams = _this select 1; +params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; +_args params ["_firedEH"]; +_firedEH params ["_shooter","","","","","","_projectile"]; -_target = _launchParams select 0; -_targetLaunchParams = _launchParams select 1; - -_state = _this select 2; -if( (count _state) < 1) then { - _state set[0, STAGE_LAUNCH]; +if (_attackProfileStateParams isEqualTo []) then { + _attackProfileStateParams set [0, STAGE_LAUNCH]; }; -_shooterPos = getPosASL _shooter; -_projectilePos = getPosASL _projectile; +private _shooterPos = getPosASL _shooter; +private _projectilePos = getPosASL _projectile; -_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos; -_distanceToShooter = _projectilePos vectorDistance _shooterPos; -_distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos; +private _distanceToTarget = _projectilePos vectorDistance _seekerTargetPos; +private _distanceToShooter = _projectilePos vectorDistance _shooterPos; +private _distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos; TRACE_2("", _distanceToTarget, _distanceToShooter); // 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: { TRACE_1("STAGE_LAUNCH",""); - if(_distanceToShooter < 10) then { + if (_distanceToShooter < 10) then { _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2]; } else { - _state set[0, STAGE_CLIMB]; + _attackProfileStateParams set [0, STAGE_CLIMB]; }; }; case 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 { - _state set[0, STAGE_TERMINAL]; + if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then { + _attackProfileStateParams set [0, STAGE_TERMINAL]; } else { _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); _returnTargetPos; diff --git a/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf b/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf index b3361ede9f..06ef934ea5 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf @@ -1,4 +1,21 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Attack profile: Javelin Top + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Attack Profile State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_JAV_TOP; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" #define STAGE_LAUNCH 1 @@ -6,55 +23,47 @@ #define STAGE_COAST 3 #define STAGE_TERMINAL 4 -EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); -private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"]; -private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_state"]; -private["_cruisAlt", "_distanceShooterToTarget", "_shooterPos"]; +params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; +_args params ["_firedEH"]; +_firedEH params ["_shooter","","","","","","_projectile"]; -_seekerTargetPos = _this select 0; -_launchParams = _this select 1; - -_target = _launchParams select 0; -_targetLaunchParams = _launchParams select 1; - -_state = _this select 2; -if( (count _state) < 1) then { - _state set[0, STAGE_LAUNCH]; +if (_attackProfileStateParams isEqualTo []) then { + _attackProfileStateParams set [0, STAGE_LAUNCH]; }; -_shooterPos = getPosASL _shooter; -_projectilePos = getPosASL _projectile; +private _shooterPos = getPosASL _shooter; +private _projectilePos = getPosASL _projectile; -_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos; -_distanceToShooter = _projectilePos vectorDistance _shooterPos; -_distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos; +private _distanceToTarget = _projectilePos vectorDistance _seekerTargetPos; +private _distanceToShooter = _projectilePos vectorDistance _shooterPos; +private _distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos; TRACE_2("", _distanceToTarget, _distanceToShooter); // 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: { TRACE_1("STAGE_LAUNCH",""); - if(_distanceToShooter < 10) then { + if (_distanceToShooter < 10) then { _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2]; } else { - _state set[0, STAGE_CLIMB]; + _attackProfileStateParams set [0, STAGE_CLIMB]; }; }; case STAGE_CLIMB: { TRACE_1("STAGE_CLIMB",""); _cruisAlt = 140; - if(_distanceShooterToTarget < 1250) then { - _cruisAlt = 140 * (_distanceShooterToTarget/1250); + if (_distanceShooterToTarget < 1250) then { + private _cruisAlt = 140 * (_distanceShooterToTarget/1250); TRACE_1("_cruisAlt", _cruisAlt); }; - if( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then { - if(_cruisAlt < 140) then { - _state set[0, STAGE_TERMINAL]; + if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then { + if (_cruisAlt < 140) then { + _attackProfileStateParams set [0, STAGE_TERMINAL]; } else { - _state set[0, STAGE_COAST]; + _attackProfileStateParams set [0, STAGE_COAST]; }; } else { _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5]; @@ -63,8 +72,8 @@ switch( (_state select 0) ) do { case STAGE_COAST: { TRACE_1("STAGE_COAST",""); TRACE_1("", ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) ); - if(_distanceToTarget < ( ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) ) * 1.5) then { - _state set[0, STAGE_TERMINAL]; + if (_distanceToTarget < ( ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) ) * 2) then { + _attackProfileStateParams set [0, STAGE_TERMINAL]; } else { _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); _returnTargetPos; diff --git a/addons/missileguidance/functions/fnc_attackProfile_LIN.sqf b/addons/missileguidance/functions/fnc_attackProfile_LIN.sqf index b399f9553d..58d2768607 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_LIN.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_LIN.sqf @@ -1,50 +1,63 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Attack profile: Linear (used by DAGR) + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Attack Profile State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_LIN; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); -private["_targetPos", "_projectilePos", "_target", "_seekerTargetPos", "_launchParams", "_targetLaunchParams"]; -private["_distanceToTarget", "_distanceToShooter", "_addHeight", "_returnTargetPos", "_shooterPos"]; -_seekerTargetPos = _this select 0; -_launchParams = _this select 1; +params ["_seekerTargetPos", "_args"]; +_args params ["_firedEH"]; +_firedEH params ["_shooter","","","","","","_projectile"]; -_target = _launchParams select 0; -_targetLaunchParams = _launchParams select 1; +private _shooterPos = getPosASL _shooter; +private _projectilePos = getPosASL _projectile; -_shooterPos = getPosASL _shooter; -_projectilePos = getPosASL _projectile; +private _distanceToTarget = _projectilePos vectorDistance _seekerTargetPos; +private _distanceToShooter = _projectilePos vectorDistance _shooterPos; +private _distanceShooterToTarget = _shooterPos vectorDistance _seekerTargetPos; -_distanceToTarget = _projectilePos vectorDistance _seekerTargetPos; -_distanceToShooter = _projectilePos vectorDistance _shooterPos; - -TRACE_3("", _distanceToTarget, _distanceToShooter, _seekerTargetPos); +TRACE_2("", _distanceToTarget, _distanceToShooter); // 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 -if( ((ASLtoAGL _projectilePos) select 2) < 5 && _distanceToShooter < 15) then { - _addHeight = _addHeight vectorAdd [0,0,_distanceToTarget]; +if ((((ASLtoAGL _projectilePos) select 2) < 5) && {_distanceToShooter < 15}) then { + _addHeight = _addHeight vectorAdd [0,0,_distanceToTarget]; + TRACE_1("climb - near shooter",_addHeight); } else { // 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))]; + TRACE_1("climb - below target and far",_addHeight); }; }; -// Handle arcing terminal low for high decent -if( (_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget < 100) then { - _addHeight = _addHeight vectorDiff [0,0, ((_projectilePos select 2) - (_seekerTargetPos select 2)) * 0.5]; -} else { - if((_projectilePos select 2) > (_seekerTargetPos select 2) && _distanceToTarget > 100) then { +// Handle arcing terminal low for high decent (when projectile above target) +if ((_projectilePos select 2) > (_seekerTargetPos select 2)) then { + if (_distanceToTarget < 100) then { + _addHeight = _addHeight vectorDiff [0,0, ((_projectilePos select 2) - (_seekerTargetPos select 2)) * 0.5]; + TRACE_1("above - close",_addHeight); + } else { + TRACE_1("above - far",_addHeight); _addHeight = _addHeight vectorAdd [0,0, _distanceToTarget*0.02]; }; }; -_returnTargetPos = _seekerTargetPos vectorAdd _addHeight; +private _returnTargetPos = _seekerTargetPos vectorAdd _addHeight; -#ifdef DEBUG_MODE_FULL -drawLine3D [(ASLtoAGL _returnTargetPos) vectorAdd _addHeight, ASLtoAGL _returnTargetPos, [0,1,0,1]]; -#endif - -TRACE_1("Adjusted target position", _returnTargetPos); +TRACE_2("Adjusted target position",_returnTargetPos,_addHeight); _returnTargetPos; diff --git a/addons/missileguidance/functions/fnc_attackProfile_MID.sqf b/addons/missileguidance/functions/fnc_attackProfile_MID.sqf index 9909124e2f..0349a101e4 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_MID.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_MID.sqf @@ -1,4 +1,22 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Attack profile: MID + * TODO: falls back to Linear + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Attack Profile State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_MID; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -_this call FUNC(attackProfile_LIN); \ No newline at end of file +_this call FUNC(attackProfile_LIN); diff --git a/addons/missileguidance/functions/fnc_changeMissileDirection.sqf b/addons/missileguidance/functions/fnc_changeMissileDirection.sqf index f5fdee95a0..28fb46fe28 100644 --- a/addons/missileguidance/functions/fnc_changeMissileDirection.sqf +++ b/addons/missileguidance/functions/fnc_changeMissileDirection.sqf @@ -1,11 +1,26 @@ +/* + * Author: jaynus / nou + * Change a projectile's direction, maintaing speed + * + * Arguments: + * 0: Projectile + * 1: Direction (unit vector) + * + * Return Value: + * None + * + * Example: + * [missile, [0,1,0]] call ace_missileguidance_fnc_changeMissileDirection; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -private ["_projectile", "_v", "_l", "_r"]; -_projectile = _this select 0; -_v = _this select 1; +params ["_projectile", "_v"]; -_l = sqrt ((_v select 0) ^ 2 + (_v select 1) ^ 2); -_r = -(_v select 2) / _l; +private _l = sqrt ((_v select 0) ^ 2 + (_v select 1) ^ 2); +private _r = -(_v select 2) / _l; _projectile setVectorDirAndUp [ _v, [(_v select 0) * _r,(_v select 1) * _r, _l] ]; -_projectile setVelocity (_v vectorMultiply (vectorMagnitude (velocity _projectile))); \ No newline at end of file +_projectile setVelocity (_v vectorMultiply (vectorMagnitude (velocity _projectile))); diff --git a/addons/missileguidance/functions/fnc_checkLos.sqf b/addons/missileguidance/functions/fnc_checkLos.sqf index d41554dc65..1e1d3c7d3e 100644 --- a/addons/missileguidance/functions/fnc_checkLos.sqf +++ b/addons/missileguidance/functions/fnc_checkLos.sqf @@ -3,17 +3,25 @@ * Returns whether the seeker object can see the target position with lineIntersect * * Arguments: - * 0: Seeker [Object] - * 1: Target [Object] + * 0: Seeker + * 1: Target * * Return Value: - * Boolean + * Has LOS + * + * Example: + * [player, cursorTarget] call ace_missileguidance_fnc_checkLOS; + * + * Public: No */ #include "script_component.hpp" 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 _targetAimPos = aimPos _target; @@ -21,11 +29,11 @@ private _seekerPos = getPosASL _seeker; private _return = true; if (!((terrainIntersectASL [_seekerPos, _targetPos]) && {terrainIntersectASL [_seekerPos, _targetAimPos]})) then { - if(lineIntersects [_seekerPos, _targetPos, _seeker, _target]) then { + if (lineIntersects [_seekerPos, _targetPos, _seeker, _target]) then { _return = false; }; } else { _return = false; }; -_return; \ No newline at end of file +_return; diff --git a/addons/missileguidance/functions/fnc_checkSeekerAngle.sqf b/addons/missileguidance/functions/fnc_checkSeekerAngle.sqf index 9415f347b6..8ddc848594 100644 --- a/addons/missileguidance/functions/fnc_checkSeekerAngle.sqf +++ b/addons/missileguidance/functions/fnc_checkSeekerAngle.sqf @@ -1,31 +1,35 @@ /* * Author: jaynus - * Returns whether the target position is within the maximum angle FOV of the provided seeker + * Returns whether the target position is within the maximum angle FOV of the provided seeker * objects current direction. * * Arguments: - * 0: Seeker [Object] - * 1: Target [Position] - * 2: Max Angle [Degrees] - * + * 0: Seeker + * 1: Target PosASL + * 2: Max Angle (degrees) + * * Return Value: - * Boolean + * Can See + * + * Example: + * [player, cursorTarget, 45] call ace_missileguidance_fnc_checkSeekerAngle; + * + * Public: No */ - +// #define DEBUG_MODE_FULL #include "script_component.hpp" -private ["_seeker", "_targetPos", "_seekerMaxAngle", "_sensorPos", "_testPointVector", "_testDotProduct"]; -_seeker = _this select 0; -_targetPos = _this select 1; -_seekerMaxAngle = _this select 2; +params ["_seeker", "_targetPos", "_seekerMaxAngle"]; -_sensorPos = getPosASL _seeker; +private _sensorPos = getPosASL _seeker; -_testPointVector = vectorNormalized (_targetPos vectorDiff _sensorPos); -_testDotProduct = (vectorNormalized (velocity _seeker)) vectorDotProduct _testPointVector; +private _testPointVector = vectorNormalized (_targetPos vectorDiff _sensorPos); +private _testDotProduct = (vectorNormalized (velocity _seeker)) vectorDotProduct _testPointVector; -if(_testDotProduct < (cos _seekerMaxAngle)) exitWith { - false +TRACE_2("fov",acos _testDotProduct,_seekerMaxAngle); + +if (_testDotProduct < (cos _seekerMaxAngle)) exitWith { + false }; -true \ No newline at end of file +true diff --git a/addons/missileguidance/functions/fnc_doAttackProfile.sqf b/addons/missileguidance/functions/fnc_doAttackProfile.sqf index 1c589838f5..3f390a39a2 100644 --- a/addons/missileguidance/functions/fnc_doAttackProfile.sqf +++ b/addons/missileguidance/functions/fnc_doAttackProfile.sqf @@ -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 + * 1: Guidance Arg Array + * 2: Seeker State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_doAttackProfile; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); -private ["_testName", "_attackProfilePos", "_attackProfile", "_attackProfileName", "_attackProfilesCfg", "_i", "_launchParams", "_testame", "_testProfile"]; -_launchParams = ((_this select 1) select 1); -_attackProfileName = _launchParams select 3; +params ["_seekerTargetPos", "_args"]; +_args params ["", "_launchParams"]; +_launchParams params ["", "", "", "_attackProfileName"]; -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; -for [{_i=0}, {_i< (count _attackProfilesCfg) }, {_i=_i+1}] do { - _testProfile = _attackProfilesCfg select _i; - _testName = configName _testProfile; - TRACE_3("", _testName, _testProfile, _attackProfilesCfg); - - if( _testName == _attackProfileName) exitWith { - _attackProfile = _attackProfilesCfg select _i; - }; +if ((isNil "_attackProfilePos") || {(vectorMagnitude _attackProfilePos) == 0}) exitWith { + ERROR_1("attack profile returned bad pos",_attackProfilePos); + [0,0,0] }; -_attackProfilePos = [0,0,0]; -if(!isNil "_attackProfile") then { - _attackProfilePos = _this call (missionNamespace getVariable (getText (_attackProfile >> "functionName"))); -}; +#ifdef DRAW_GUIDANCE_INFO +drawLine3D [(ASLtoAGL _attackProfilePos), (ASLtoAGL _seekerTargetPos), [0,1,1,1]]; +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; diff --git a/addons/missileguidance/functions/fnc_doHandoff.sqf b/addons/missileguidance/functions/fnc_doHandoff.sqf index 011c3d52d1..db722713e1 100644 --- a/addons/missileguidance/functions/fnc_doHandoff.sqf +++ b/addons/missileguidance/functions/fnc_doHandoff.sqf @@ -1,4 +1,5 @@ +// Not currently used #include "script_component.hpp" PARAMS_2(_target,_args); -[QGVAR(handoff), [_target, _args]] call CBA_fnc_globalEvent; \ No newline at end of file +[QGVAR(handoff), [_target, _args]] call CBA_fnc_globalEvent; diff --git a/addons/missileguidance/functions/fnc_doSeekerSearch.sqf b/addons/missileguidance/functions/fnc_doSeekerSearch.sqf index 4eaefb6656..3b36aeaf58 100644 --- a/addons/missileguidance/functions/fnc_doSeekerSearch.sqf +++ b/addons/missileguidance/functions/fnc_doSeekerSearch.sqf @@ -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 + * 3: Last known pos state array + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[], [], []] call ace_missileguidance_fnc_seekerType_Optic; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); -private ["_seekerProfilePos", "_i", "_launchParams", "_seekerType", "_seekerTypeName", "_seekerTypesCfg", "_testName", "_testProfile"]; +params ["", "_args", "", "_lastKnownPosState"]; +_args params ["", "_launchParams"]; +_launchParams params ["", "", "_seekerTypeName"]; +_lastKnownPosState params ["_seekLastTargetPos", "_lastKnownPos"]; -_launchParams = ((_this select 1) select 1); -_seekerTypeName = _launchParams select 2; +private _seekerFunction = getText (configFile >> QGVAR(SeekerTypes) >> _seekerTypeName >> "functionName"); -TRACE_1("Seeker type", _seekerTypeName); +private _seekerTargetPos = _this call (missionNamespace getVariable _seekerFunction); -_seekerTypesCfg = ( configFile >> QGVAR(SeekerTypes) ); - -_seekerType = nil; -for [{_i = 0}, {_i< (count _seekerTypesCfg) }, {_i=_i + 1}] do { - _testProfile = _seekerTypesCfg select _i; - _testName = configName _testProfile; - TRACE_3("", _testName, _testProfile, _seekerTypesCfg); - - if( _testName == _seekerTypeName) exitWith { - _seekerType = _seekerTypesCfg select _i; +if ((isNil "_seekerTargetPos") || {(vectorMagnitude _seekerTargetPos) == 0}) then { + // Seeker returned nil / bad pos + if (_seekLastTargetPos && {(vectorMagnitude _lastKnownPos) != 0}) then { + TRACE_2("seeker returned bad pos - using last known",_seekLastTargetPos,_lastKnownPos); + _seekerTargetPos = _lastKnownPos; + } else { + TRACE_1("seeker returned no pos",_seekerTargetPos); + _seekerTargetPos = [0,0,0]; + }; +} else { + if (_seekLastTargetPos) then { + TRACE_1("saving current pos",_seekLastTargetPos); + _lastKnownPosState set [1, _seekerTargetPos]; }; }; -_seekerProfilePos = [0, 0, 0]; -if(!isNil "_seekerType") then { - _seekerProfilePos = _this call (missionNamespace getVariable (getText (_seekerType >> "functionName"))); -}; +#ifdef DRAW_GUIDANCE_INFO +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"]; +#endif -_seekerProfilePos; +TRACE_2("return",_seekerTargetPos,_seekerTypeName); +_seekerTargetPos; diff --git a/addons/missileguidance/functions/fnc_guidancePFH.sqf b/addons/missileguidance/functions/fnc_guidancePFH.sqf index e7fa5a4fd1..e7fe71ca39 100644 --- a/addons/missileguidance/functions/fnc_guidancePFH.sqf +++ b/addons/missileguidance/functions/fnc_guidancePFH.sqf @@ -1,33 +1,41 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Guidance Per Frame Handler + * + * Arguments: + * 0: Guidance Arg Array + * 1: PFID + * + * Return Value: + * Nothing + * + * Example: + * [[], 0] call ace_missileguidance_fnc_guidancePFH; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" +BEGIN_COUNTER(guidancePFH); + #define TIMESTEP_FACTOR 0.01 -private ["_launchParams", "_targetLaunchParams", "_flightParams", "_seekerParams", "_stateParams"]; -private ["_lastRunTime", "_runtimeDelta", "_adjustTime", "_args", "_seekerTargetPos", "_projectilePos"]; -private ["_profileAdjustedTargetPos", "_incDeflection", "_minDeflection", "_maxDeflection"]; -private ["_targetVector", "_adjustVector", "_finalAdjustVector", "_changeVector", "_pitch", "_yaw", "_roll"]; -private ["_PS", "_distanceToTarget", "_targetRelativeVector", "_vectorTo"]; +params ["_args", "_pfID"]; +_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"]; +_firedEH params ["_shooter","","","","_ammo","","_projectile"]; +_launchParams params ["","_targetLaunchParams"]; +_stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState"]; -_args = _this select 0; -EXPLODE_7_PVT((_args select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); - -if(!alive _projectile || isNull _projectile || isNull _shooter) exitWith { - [(_this select 1)] call CBA_fnc_removePerFrameHandler; +if (!alive _projectile || isNull _projectile || isNull _shooter) exitWith { + [_pfID] call CBA_fnc_removePerFrameHandler; + END_COUNTER(guidancePFH); }; -_launchParams = _args select 1; -_targetLaunchParams = _launchParams select 1; -_flightParams = _args select 2; -_seekerParams = _args select 3; +private _runtimeDelta = diag_tickTime - _lastRunTime; +private _adjustTime = 1; -_stateParams = _args select 4; - -_lastRunTime = _stateParams select 0; -_runtimeDelta = diag_tickTime - _lastRunTime; -_adjustTime = 1; - -if(accTime > 0) then { +if (accTime > 0) then { _adjustTime = 1/accTime; _adjustTime = _adjustTime * (_runtimeDelta / TIMESTEP_FACTOR); TRACE_4("Adjust timing", 1/accTime, _adjustTime, _runtimeDelta, (_runtimeDelta / TIMESTEP_FACTOR) ); @@ -35,72 +43,71 @@ if(accTime > 0) then { _adjustTime = 0; }; -_minDeflection = ((_flightParams select 0) - ((_flightParams select 0) * _adjustTime)) max 0; -_maxDeflection = (_flightParams select 1) * _adjustTime; -_incDeflection = _flightParams select 2; +private _minDeflection = ((_flightParams select 0) - ((_flightParams select 0) * _adjustTime)) max 0; +private _maxDeflection = (_flightParams select 1) * _adjustTime; +// private _incDeflection = _flightParams select 2; // todo -_projectilePos = getPosASL _projectile; +private _projectilePos = getPosASL _projectile; -// @TODO: placeholder for "last seek target position" -// Last target pos should be optional based on the seeker unit -_seekerTargetPos = [ [0,0,0], _args, (_stateParams select 1)] call FUNC(doSeekerSearch); -if(isNil "_seekerTargetPos") then { - _seekerTargetPos = _seekerTargetPos vectorAdd ((velocity _projectile) vectorMultiply 5); -} else { - if( (vectorMagnitude _seekerTargetPos) == 0) then { - _seekerTargetPos = _seekerTargetPos vectorAdd ((velocity _projectile) vectorMultiply 5); +// Run seeker function: +private _seekerTargetPos = [[0,0,0], _args, _seekerStateParams, _lastKnownPosState] call FUNC(doSeekerSearch); + +// If we have no seeker target, then do not change anything +if (!(_seekerTargetPos isEqualTo [0,0,0])) then { + // Run attack profile function: + private _profileAdjustedTargetPos = [_seekerTargetPos, _args, _attackProfileStateParams] call FUNC(doAttackProfile); + + 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); -_targetVector = _projectilePos vectorFromTo _profileAdjustedTargetPos; -_adjustVector = _targetVector vectorDiff (vectorDir _projectile); +#ifdef DRAW_GUIDANCE_INFO +TRACE_3("",_projectilePos,_seekerTargetPos,_profileAdjustedTargetPos); +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; -_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); +private _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 setDropInterval 3.0; - -//hintSilent format["d: %1", _distanceToTarget]; #endif -_stateParams set[0, diag_tickTime]; +_stateParams set [0, diag_tickTime]; -_args set[4, _stateParams]; -_this set[0, _args]; +END_COUNTER(guidancePFH); + diff --git a/addons/missileguidance/functions/fnc_handleHandoff.sqf b/addons/missileguidance/functions/fnc_handleHandoff.sqf index af23ed84d8..25c01694eb 100644 --- a/addons/missileguidance/functions/fnc_handleHandoff.sqf +++ b/addons/missileguidance/functions/fnc_handleHandoff.sqf @@ -1,6 +1,7 @@ +// Not currently used #include "script_component.hpp" 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; \ No newline at end of file +[FUNC(guidancePFH), 0, _args] call CBA_fnc_addPerFrameHandler; diff --git a/addons/missileguidance/functions/fnc_onFired.sqf b/addons/missileguidance/functions/fnc_onFired.sqf index 2269810b94..224cfb14ec 100644 --- a/addons/missileguidance/functions/fnc_onFired.sqf +++ b/addons/missileguidance/functions/fnc_onFired.sqf @@ -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) + * 4: Ammo + * 6: Projectile + * + * Return Value: + * Nothing + * + * Example: + * [player, "", "", "", "ACE_Javelin_FGM148", "", theMissile] call ace_missileguidance_fnc_onFired; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_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 }; +params ["_shooter","","","","_ammo","","_projectile"]; // Bail on not missile -if(! (_ammo isKindOf "MissileBase") ) exitWith { false }; +if (!(_ammo isKindOf "MissileBase")) exitWith {}; -private ["_config", "_configs", "_enabled", "_target", "_seekerType", "_attackProfile"]; -private ["_args", "_canUseLock", "_guidingUnit", "_launchPos", "_lockMode", "_targetPos", "_vanillaTarget"]; +// Bail if guidance is disabled for this ammo +if ((getNumber (configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON) >> "enabled")) != 1) exitWith {}; -//Verify ammo has explicity added guidance config (ignore inheritances) -_configs = configProperties [(configFile >> "CfgAmmo" >> _ammo), QUOTE(configName _x == QUOTE(QUOTE(ADDON))), false]; -if( (count _configs) < 1) exitWith {}; +// Bail on locality of the projectile, it should be local to us +if (GVAR(enabled) < 1 || {!local _projectile} ) exitWith {}; -_config = (configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON)); -_enabled = getNumber ( _config >> "enabled"); +// Bail if shooter isn't player AND system not enabled for AI: +if ( !isPlayer _shooter && { GVAR(enabled) < 2 } ) exitWith {}; -// Bail if guidance is not enabled -if(isNil "_enabled" || {_enabled != 1}) exitWith { false }; +// Verify ammo has explicity added guidance config (ignore inheritances) +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]; -_targetPos = (vehicle _shooter) getVariable [QGVAR(targetPosition), nil]; -_seekerType = (vehicle _shooter) getVariable [QGVAR(seekerType), nil]; -_attackProfile = (vehicle _shooter) getVariable [QGVAR(attackProfile), nil]; -_lockMode = (vehicle _shooter) getVariable [QGVAR(lockMode), nil]; +// MissileGuidance is enabled for this shot +TRACE_4("enabled",_shooter,_ammo,_projectile,typeOf _shooter); -// @TODO: make this vehicle shooter, but we need to differentiate where its set in ace_laser -_laserCode = _shooter getVariable [QEGVAR(laser,code), ACE_DEFAULT_LASER_CODE]; -_laserInfo = [_laserCode, ACE_DEFAULT_LASER_WAVELENGTH, ACE_DEFAULT_LASER_WAVELENGTH]; +private _config = configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON); -_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 { _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(isNil "_target") then { - if(!isPlayer _shooter) then { +if (isNil "_target") then { + if (!isPlayer _shooter) then { // 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); } else { - _canUseLock = getNumber (_config >> "canVanillaLock"); + private _canUseLock = getNumber (_config >> "canVanillaLock"); // @TODO: Get vanilla target - if(_canUseLock > 0 || difficulty < 1) then { - _vanillaTarget = cursorTarget; + if (_canUseLock > 0 || difficulty < 1) then { + private _vanillaTarget = cursorTarget; TRACE_1("Using Vanilla Locking", _vanillaTarget); - if(!isNil "_vanillaTarget") then { + if (!isNil "_vanillaTarget") then { _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); -_args = [_this, - [_shooter, +private _args = [_this, + [ _shooter, [_target, _targetPos, _launchPos], _seekerType, _attackProfile, @@ -89,30 +112,41 @@ _args = [_this, getNumber ( _config >> "seekerAccuracy" ), 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 // 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 // Lasers need to be handled in a special LOAL/LOBL case -//if(isPlayer _shooter) then { -// _guidingUnit = ACE_player; +//if (isPlayer _shooter) then { +// private _guidingUnit = ACE_player; // -// if(local _guidingUnit) then { +// if (local _guidingUnit) then { // [FUNC(guidancePFH), 0, _args ] call CBA_fnc_addPerFrameHandler; // } else { // [QGVAR(handoff), [_guidingUnit, _args] ] call FUNC(doHandoff); // }; //} 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 (vehicle _shooter) setVariable [QGVAR(target), nil]; (vehicle _shooter) setVariable [QGVAR(seekerType), nil]; (vehicle _shooter) setVariable [QGVAR(attackProfile), nil]; (vehicle _shooter) setVariable [QGVAR(lockMode), nil]; -*/ + */ diff --git a/addons/missileguidance/functions/fnc_onIncomingMissile.sqf b/addons/missileguidance/functions/fnc_onIncomingMissile.sqf index 14902c32a5..2dcc93b793 100644 --- a/addons/missileguidance/functions/fnc_onIncomingMissile.sqf +++ b/addons/missileguidance/functions/fnc_onIncomingMissile.sqf @@ -1,8 +1,27 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Handles AI shooting a locking missile + * + * Arguments: + * 0: Target + * 1: Ammo + * 2: Shooter + * + * Return Value: + * None + * + * Example: + * [cursorTarget, "x", player] call ace_missileguidance_fnc_changeMissileDirection; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #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 -_shooter setVariable [QGVAR(vanilla_target),_target, false]; \ No newline at end of file +_shooter setVariable [QGVAR(vanilla_target),_target, false]; +TRACE_2("setting vanilla target",_shooter,_target); diff --git a/addons/missileguidance/functions/fnc_rotateVectLine.sqf b/addons/missileguidance/functions/fnc_rotateVectLine.sqf deleted file mode 100644 index 9adb283cae..0000000000 --- a/addons/missileguidance/functions/fnc_rotateVectLine.sqf +++ /dev/null @@ -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; \ No newline at end of file diff --git a/addons/missileguidance/functions/fnc_rotateVectLineGetMap.sqf b/addons/missileguidance/functions/fnc_rotateVectLineGetMap.sqf deleted file mode 100644 index 258cc93ae2..0000000000 --- a/addons/missileguidance/functions/fnc_rotateVectLineGetMap.sqf +++ /dev/null @@ -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] \ No newline at end of file diff --git a/addons/missileguidance/functions/fnc_seekerType_Optic.sqf b/addons/missileguidance/functions/fnc_seekerType_Optic.sqf index b491110ac6..173b6ba708 100644 --- a/addons/missileguidance/functions/fnc_seekerType_Optic.sqf +++ b/addons/missileguidance/functions/fnc_seekerType_Optic.sqf @@ -1,52 +1,54 @@ -//#define DEBUG_MODE_FULL +/* + * Author: jaynus / nou + * Seeker Type: Optic + * + * Arguments: + * 1: Guidance Arg Array + * 2: Seeker State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[], [], []] call ace_missileguidance_fnc_seekerType_Optic; + * + * Public: No + */ +// #define DEBUG_MODE_FULL #include "script_component.hpp" -EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); -private ["_targets", "_foundTargetPos", "_launchParams", "_seekerParams", "_targetLaunchParams"]; -private ["_angleFov", "_angleOkay", "_losOkay", "_seekerTargetPos", "_sensorPos", "_target"]; +params ["", "_args"]; +_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams"]; +_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; -_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)); -}; +private _foundTargetPos = aimPos _target; // @TODO: This is seeker LOS and angle checks for LOAL only; LOBL does not need visual -_angleFov = _seekerParams select 0; -_angleOkay = [_projectile, _foundTargetPos, _angleFov] call FUNC(checkSeekerAngle); +private _angleOkay = [_projectile, _foundTargetPos, _seekerAngle] call FUNC(checkSeekerAngle); -_losOkay = false; -if(_angleOkay) then { +private _losOkay = false; +if (_angleOkay) then { _losOkay = [_projectile, _target] call FUNC(checkLos); }; TRACE_2("", _angleOkay, _losOkay); -// If we got here, it was an invalid target, just return a spot 5m in front of the missile -if(!_angleOkay || !_losOkay) then { - _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; +// Can't see target, return [0,0,0] and let doSeekerSearch handle it +if (!_angleOkay || !_losOkay) exitWith {[0,0,0]}; - _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; - TRACE_3("leading target",_distanceToTarget,_eta,_adjustDistance); - _foundTargetPos = _foundTargetPos vectorAdd _adjustDistance; -}; +private _adjustDistance = (velocity _target) vectorMultiply _eta; +TRACE_3("leading target",_distanceToTarget,_eta,_adjustDistance); +_foundTargetPos = _foundTargetPos vectorAdd _adjustDistance; TRACE_2("return",_foundTargetPos,(aimPos _target) distance _foundTargetPos); _foundTargetPos; diff --git a/addons/missileguidance/functions/fnc_seekerType_SALH.sqf b/addons/missileguidance/functions/fnc_seekerType_SALH.sqf index eda26fe358..3f78f5d3c5 100644 --- a/addons/missileguidance/functions/fnc_seekerType_SALH.sqf +++ b/addons/missileguidance/functions/fnc_seekerType_SALH.sqf @@ -1,32 +1,33 @@ +/* + * Author: jaynus / nou + * Seeker Type: SALH (Laser) + * Wrapper for ace_laser_fnc_seekerFindLaserSpot + * + * Arguments: + * 1: Guidance Arg Array + * 2: Seeker State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[], [], []] call ace_missileguidance_fnc_seekerType_SALH; + * + * Public: No + */ // #define DEBUG_MODE_FULL #include "script_component.hpp" -params ["_lastSeekTargetPos", "_args"]; -_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"]; -_firedEH params ["_shooter","_weapon","_muzzle","_mode","_ammo","_magazine","_projectile"]; +params ["", "_args"]; +_args params ["_firedEH", "_launchParams", "", "_seekerParams"]; +_firedEH params ["","","","","","","_projectile"]; _launchParams params ["","","","","","_laserParams"]; _seekerParams params ["_seekerAngle", "", "_seekerMaxRange"]; _laserParams params ["_code", "_wavelengthMin", "_wavelengthMax"]; -private "_foundTargetPos"; -if (!isNil "_target") then { - // Handle AI or moving vanilla lasers - _foundTargetPos = getPosASL _target; -} 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); - }; -}; +private _laserResult = [(getPosASL _projectile), (velocity _projectile), _seekerAngle, _seekerMaxRange, [_wavelengthMin, _wavelengthMax], _code, _projectile] call EFUNC(laser,seekerFindLaserSpot); +private _foundTargetPos = _laserResult select 0; +TRACE_1("Search", _laserResult); _foundTargetPos; diff --git a/addons/missileguidance/script_component.hpp b/addons/missileguidance/script_component.hpp index d09e1e3113..298de3a051 100644 --- a/addons/missileguidance/script_component.hpp +++ b/addons/missileguidance/script_component.hpp @@ -2,6 +2,7 @@ #define COMPONENT_BEAUTIFIED Missile Guidance #include "\z\ace\addons\main\script_mod.hpp" +// #define DRAW_GUIDANCE_INFO // #define DEBUG_MODE_FULL // #define DISABLE_COMPILE_CACHE // #define ENABLE_PERFORMANCE_COUNTERS @@ -15,5 +16,3 @@ #endif #include "\z\ace\addons\main\script_macros.hpp" - -#define FIREMODE_DIRECT_LOAL 1