From 2c4c7c2fdf7bc86d12d9dbbeca453431e0e88a51 Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Fri, 23 Aug 2024 08:45:21 -0600 Subject: [PATCH 1/8] Maverick - Update to missile guidance framework (#10032) --- addons/maverick/ACE_GuidanceConfig.hpp | 2 +- addons/maverick/CfgAmmo.hpp | 55 +++++++++++++++++++--- addons/maverick/CfgMagazines.hpp | 64 ++++++++++++++++++++++++++ addons/maverick/CfgWeapons.hpp | 16 +++++++ addons/maverick/stringtable.xml | 21 +++++++++ 5 files changed, 151 insertions(+), 7 deletions(-) diff --git a/addons/maverick/ACE_GuidanceConfig.hpp b/addons/maverick/ACE_GuidanceConfig.hpp index 948404b7cc..4360bd4a87 100644 --- a/addons/maverick/ACE_GuidanceConfig.hpp +++ b/addons/maverick/ACE_GuidanceConfig.hpp @@ -2,6 +2,6 @@ class EGVAR(missileguidance,AttackProfiles) { class maverick { name = "LOAL-DIR"; nameLocked = "LOBL-DIR"; - functionName = QEFUNC(missileguidance,attackProfile_DIR); + functionName = QEFUNC(missileguidance,attackProfile_LIN); }; }; diff --git a/addons/maverick/CfgAmmo.hpp b/addons/maverick/CfgAmmo.hpp index 654c1fbe80..7e66e2edee 100644 --- a/addons/maverick/CfgAmmo.hpp +++ b/addons/maverick/CfgAmmo.hpp @@ -5,6 +5,45 @@ class CfgAmmo { }; class Missile_AGM_02_F: MissileBase {}; + class GVAR(D): Missile_AGM_02_F { + author = "Dani (TCVM)"; + missileLockMaxDistance = 14000; + maneuvrability = 0; + class ace_missileguidance { + enabled = 1; + + pitchRate = 15; + yawRate = 15; + + canVanillaLock = 1; + + defaultSeekerType = "Optic"; + seekerTypes[] = {"Optic"}; + + defaultSeekerLockMode = "LOBL"; + seekerLockModes[] = {"LOBL"}; + + defaultNavigationType = "AugmentedProportionalNavigation"; + navigationTypes[] = { "AugmentedProportionalNavigation" }; + + seekLastTargetPos = 1; + seekerAngle = 60; + seekerAccuracy = 1; + + seekerMinRange = 1; + seekerMaxRange = 14000; + + defaultAttackProfile = "maverick"; + attackProfiles[] = {"maverick"}; + }; + }; + + class GVAR(G): GVAR(D) { + class ace_missileguidance: ace_missileguidance { + enabled = 1; + }; + }; + class GVAR(L): Missile_AGM_02_F { author = "xrufix"; autoSeekTarget = 0; @@ -16,9 +55,8 @@ class CfgAmmo { class ace_missileguidance { enabled = 1; - minDeflection = 0; - maxDeflection = 0.002; - incDeflection = 0.001; + pitchRate = 15; + yawRate = 15; canVanillaLock = 0; @@ -28,6 +66,9 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = {"LOAL","LOBL"}; + defaultNavigationType = "AugmentedProportionalNavigation"; + navigationTypes[] = { "AugmentedProportionalNavigation" }; + seekLastTargetPos = 1; seekerAngle = 60; seekerAccuracy = 1; @@ -49,9 +90,8 @@ class CfgAmmo { class ace_missileguidance { enabled = 1; - minDeflection = 0; - maxDeflection = 0.002; - incDeflection = 0.001; + pitchRate = 20; + yawRate = 20; canVanillaLock = 0; @@ -61,6 +101,9 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = {"LOAL"}; + defaultNavigationType = "AugmentedProportionalNavigation"; + navigationTypes[] = { "AugmentedProportionalNavigation" }; + seekLastTargetPos = 1; seekerAngle = 40; seekerAccuracy = 1; diff --git a/addons/maverick/CfgMagazines.hpp b/addons/maverick/CfgMagazines.hpp index 705d52010d..1e51ede8b0 100644 --- a/addons/maverick/CfgMagazines.hpp +++ b/addons/maverick/CfgMagazines.hpp @@ -12,7 +12,71 @@ class CfgMagazines { class PylonRack_Missile_AGM_02_x1: magazine_Missile_AGM_02_x1 {}; class PylonRack_Missile_AGM_02_x2: magazine_Missile_AGM_02_x1 {}; + + // Optical Mavericks + class GVAR(D_magazine): 6Rnd_Missile_AGM_02_F { + ammo = QGVAR(D); + author = "Dani (TCVM)"; + displayName = CSTRING(d_mag_x1); + }; + class GVAR(D_pylonRack_1Rnd): PylonRack_1Rnd_Missile_AGM_02_F { + ammo = QGVAR(D); + author = "Dani (TCVM)"; + displayName = CSTRING(d_mag_x1); + pylonWeapon = QGVAR(D_Launcher); + }; + class GVAR(D_pylonRack_3Rnd): PylonRack_3Rnd_Missile_AGM_02_F { + ammo = QGVAR(D); + author = "Dani (TCVM)"; + displayName = CSTRING(d_mag_x3); + pylonWeapon = QGVAR(D_Launcher); + }; + class GVAR(G_magazine_x1): magazine_Missile_AGM_02_x1 { + ammo = QGVAR(G); + author = "Dani (TCVM)"; + displayName = CSTRING(g_mag_x1); + }; + class GVAR(G_pylonmissile_x1): PylonMissile_Missile_AGM_02_x1 { + ammo = QGVAR(G); + author = "Dani (TCVM)"; + displayName = CSTRING(g_mag_x1); + pylonWeapon = QGVAR(G_Launcher); + }; + class GVAR(G_pylonmissile_x2): PylonMissile_Missile_AGM_02_x2 { + ammo = QGVAR(G); + author = "Dani (TCVM)"; + displayName = CSTRING(g_mag_x2); + pylonWeapon = QGVAR(G_Launcher); + }; + + class GVAR(G_pylonRack_1Rnd): PylonRack_1Rnd_Missile_AGM_02_F { + ammo = QGVAR(G); + author = "Dani (TCVM)"; + displayName = CSTRING(g_mag_x1); + pylonWeapon = QGVAR(G_Launcher); + }; + class GVAR(G_PylonRack_3Rnd): PylonRack_3Rnd_Missile_AGM_02_F { + ammo = QGVAR(G); + author = "Dani (TCVM)"; + displayName = CSTRING(g_mag_x3); + pylonWeapon = QGVAR(G_Launcher); + }; + + class GVAR(G_PylonRack_x1): PylonRack_Missile_AGM_02_x1 { + ammo = QGVAR(G); + author = "Dani (TCVM)"; + displayName = CSTRING(g_mag_x1); + pylonWeapon = QGVAR(G_Launcher); + }; + class GVAR(G_PylonRack_x2): PylonRack_Missile_AGM_02_x2 { + ammo = QGVAR(G); + author = "Dani (TCVM)"; + displayName = CSTRING(g_mag_x2); + pylonWeapon = QGVAR(G_Launcher); + }; + + // Laser Mavericks class GVAR(L_magazine_x1): magazine_Missile_AGM_02_x1 { ammo = QGVAR(L); author = "xrufix"; diff --git a/addons/maverick/CfgWeapons.hpp b/addons/maverick/CfgWeapons.hpp index 1c0ae744ef..a60681a3cf 100644 --- a/addons/maverick/CfgWeapons.hpp +++ b/addons/maverick/CfgWeapons.hpp @@ -6,6 +6,22 @@ class CfgWeapons { class MissileLauncher: LauncherCore {}; class Missile_AGM_02_Plane_CAS_01_F: MissileLauncher {}; + class GVAR(D_Launcher): Missile_AGM_02_Plane_CAS_01_F { + author = "Dani (TCVM)"; + displayname = CSTRING(D); + magazines[] = {QGVAR(D_magazine), QGVAR(D_pylonRack_1Rnd), QGVAR(D_pylonRack_3Rnd)}; + weaponLockDelay = 0.1; + weaponLockSystem = 2; + }; + + class GVAR(G_Launcher): weapon_AGM_65Launcher { + author = "Dani (TCVM)"; + displayname = CSTRING(G); + magazines[] = {QGVAR(G_magazine_x1), QGVAR(G_pylonmissile_x1), QGVAR(G_pylonmissile_x2), QGVAR(G_pylonRack_1Rnd), QGVAR(G_PylonRack_3Rnd), QGVAR(G_PylonRack_x1), QGVAR(G_PylonRack_x2)}; + weaponLockDelay = 0.1; + weaponLockSystem = 2; + }; + class GVAR(L_Launcher): weapon_AGM_65Launcher { author = "xrufix"; displayname = CSTRING(L); diff --git a/addons/maverick/stringtable.xml b/addons/maverick/stringtable.xml index 6bf1d80e04..60af8c830f 100644 --- a/addons/maverick/stringtable.xml +++ b/addons/maverick/stringtable.xml @@ -111,6 +111,27 @@ 1x Kh-25ML [ACE] 1x Kh-25ML [ACE] + + AGM-65 Maverick D + + + AGM-65 Maverick G + + + AGM-65 Maverick D [ACE] + + + 3x AGM-65 Maverick D [ACE] + + + AGM-65 Maverick G [ACE] + + + 2x AGM-65 Maverick G [ACE] + + + 3x AGM-65 Maverick G [ACE] + From a1cafef5aea69a0705d6d4382caaf3a11863383a Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Fri, 23 Aug 2024 08:46:01 -0600 Subject: [PATCH 2/8] Nlaw - Update to use Missile Guidance Framework (#10034) --- addons/nlaw/ACE_GuidanceConfig.hpp | 6 ++ addons/nlaw/CfgAmmo.hpp | 8 +- addons/nlaw/XEH_PREP.hpp | 2 + addons/nlaw/XEH_postInit.sqf | 4 + addons/nlaw/functions/fnc_attackProfile.sqf | 16 +--- addons/nlaw/functions/fnc_keyDown.sqf | 2 +- addons/nlaw/functions/fnc_navigation.sqf | 78 +++++++++++++++++++ .../nlaw/functions/fnc_navigation_onFired.sqf | 70 +++++++++++++++++ addons/nlaw/functions/fnc_onFired.sqf | 25 +++++- addons/nlaw/functions/fnc_seeker.sqf | 17 +++- 10 files changed, 207 insertions(+), 21 deletions(-) create mode 100644 addons/nlaw/functions/fnc_navigation.sqf create mode 100644 addons/nlaw/functions/fnc_navigation_onFired.sqf diff --git a/addons/nlaw/ACE_GuidanceConfig.hpp b/addons/nlaw/ACE_GuidanceConfig.hpp index e04753d681..6003586fe8 100644 --- a/addons/nlaw/ACE_GuidanceConfig.hpp +++ b/addons/nlaw/ACE_GuidanceConfig.hpp @@ -12,3 +12,9 @@ class EGVAR(missileguidance,SeekerTypes) { functionName = QFUNC(seeker); }; }; +class EGVAR(missileguidance,NavigationTypes) { + class GVAR(PLOS) { + functionName = QFUNC(navigation); + onFired = QFUNC(navigation_onFired); + }; +}; diff --git a/addons/nlaw/CfgAmmo.hpp b/addons/nlaw/CfgAmmo.hpp index b579ebeb06..f572678d20 100644 --- a/addons/nlaw/CfgAmmo.hpp +++ b/addons/nlaw/CfgAmmo.hpp @@ -6,9 +6,8 @@ class CfgAmmo { class ace_missileguidance { enabled = 1; - minDeflection = 0.0005; // Minium flap deflection for guidance - maxDeflection = 0.01; // Maximum flap deflection for guidance - incDeflection = 0.0005; // The incrmeent in which deflection adjusts. + pitchRate = 5; // Minium flap deflection for guidance + yawRate = 10; // Maximum flap deflection for guidance canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode @@ -19,6 +18,9 @@ class CfgAmmo { defaultSeekerLockMode = "LOBL"; seekerLockModes[] = {"LOBL"}; + defaultNavigationType = QGVAR(PLOS); + navigationTypes[] = { QGVAR(PLOS) }; + seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 45; // Angle in front of the missile which can be searched seekerAccuracy = 1; // seeker accuracy multiplier diff --git a/addons/nlaw/XEH_PREP.hpp b/addons/nlaw/XEH_PREP.hpp index aad1e57efb..1cd8dbc3c5 100644 --- a/addons/nlaw/XEH_PREP.hpp +++ b/addons/nlaw/XEH_PREP.hpp @@ -4,3 +4,5 @@ PREP(attackProfile); PREP(keyDown); PREP(onFired); PREP(seeker); +PREP(navigation); +PREP(navigation_onFired); diff --git a/addons/nlaw/XEH_postInit.sqf b/addons/nlaw/XEH_postInit.sqf index 885e2d5e2f..16be48ce26 100644 --- a/addons/nlaw/XEH_postInit.sqf +++ b/addons/nlaw/XEH_postInit.sqf @@ -22,7 +22,11 @@ GVAR(pitchChange) = 0; // Visual debuging, idealy used with a moving vehicle called "testTarget" #ifdef DRAW_NLAW_INFO +GVAR(debug_firedPrediction) = []; addMissionEventHandler ["Draw3d", { + // BLACK - On fired path prediction + { drawIcon3D _x; } forEach GVAR(debug_firedPrediction); + // GREEN - Draw an object called "testTarget"'s aim pos and 1 sec aimpos predicted by velocity if ((!isNil "testTarget") && {!isNull testTarget}) then { { diff --git a/addons/nlaw/functions/fnc_attackProfile.sqf b/addons/nlaw/functions/fnc_attackProfile.sqf index 9628974800..f527780835 100644 --- a/addons/nlaw/functions/fnc_attackProfile.sqf +++ b/addons/nlaw/functions/fnc_attackProfile.sqf @@ -18,14 +18,13 @@ */ params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; + +#ifdef DRAW_NLAW_INFO _args params ["_firedEH", "_launchParams"]; _launchParams params ["","_targetLaunchParams", "", "_attackProfile"]; _targetLaunchParams params ["", "", "_launchPos"]; _firedEH params ["","","","","","","_projectile"]; -// Use seeker (if terminal) -if (_seekerTargetPos isNotEqualTo [0,0,0]) exitWith {_seekerTargetPos}; - _attackProfileStateParams params ["_startTime", "_startLOS", "_yawChange", "_pitchChange"]; (_startLOS call CBA_fnc_vect2Polar) params ["", "_yaw", "_pitch"]; @@ -36,14 +35,6 @@ private _flightTime = CBA_missionTime - _startTime; private _realYaw = _yaw + _yawChange * _flightTime; private _realPitch = _pitch + _pitchChange * _flightTime; -private _returnTargetPos = _launchPos vectorAdd ([_distanceFromLaunch, _realYaw, _realPitch] call CBA_fnc_polar2vect); - -if (_attackProfile == QGVAR(overflyTopAttack)) then { // Add 2m height in OTA attack mode - _returnTargetPos = _returnTargetPos vectorAdd [0,0,2]; -}; - - -#ifdef DRAW_NLAW_INFO drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,1,1], ASLtoAGL _launchPos, 0.75, 0.75, 0, "LAUNCH", 1, 0.025, "TahomaB"]; drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0,1,1,1], ASLtoAGL (_launchPos vectorAdd (_startLOS vectorMultiply (_distanceFromLaunch + 50))), 0.75, 0.75, 0, "Original LOS", 1, 0.025, "TahomaB"]; drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,0,1], ASLtoAGL (_launchPos vectorAdd ([_distanceFromLaunch + 50, _realYaw, _realPitch] call CBA_fnc_polar2vect)), 0.75, 0.75, 0, format ["Predicted @%1sec",(floor(_flightTime * 10)/10)], 1, 0.025, "TahomaB"]; @@ -56,5 +47,4 @@ if ((count _test) > 0) then { }; #endif -// TRACE_1("Adjusted target position",_returnTargetPos); -_returnTargetPos; +[0, 0, 1] diff --git a/addons/nlaw/functions/fnc_keyDown.sqf b/addons/nlaw/functions/fnc_keyDown.sqf index 5b75c72140..aee9739474 100644 --- a/addons/nlaw/functions/fnc_keyDown.sqf +++ b/addons/nlaw/functions/fnc_keyDown.sqf @@ -74,7 +74,7 @@ playSound "ACE_Sound_Click"; _args set [1, _yaw]; _args set [2, _pitch]; - #ifdef DEBUG_MODE_FULL + #ifdef DRAW_NLAW_INFO hintSilent format ["Instantaneous\nYaw: %1\n Pitch: %2\nGVAR\nYaw: %3\nPitch: %4", _yawChange, _pitchChange, GVAR(yawChange), GVAR(pitchChange)]; #endif }, .25, [CBA_missionTime, _yaw, _pitch, true]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/nlaw/functions/fnc_navigation.sqf b/addons/nlaw/functions/fnc_navigation.sqf new file mode 100644 index 0000000000..1cfd8f91d5 --- /dev/null +++ b/addons/nlaw/functions/fnc_navigation.sqf @@ -0,0 +1,78 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Attempts to hold angle as fed to by seeker. Does so with a simple proportional controller + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * Commanded acceleration normal to LOS in world space + * + * Example: + * [] call ace_missileguidance_fnc_navigationType_line + * + * Public: No + */ +// arbitrary constant +#define PROPORTIONALITY_CONSTANT 20 +params ["_args", "_timestep", "_seekerTargetPos", "_profileAdjustedTargetPos", "_targetData", "_navigationParams"]; +_args params ["_firedEH"]; +_firedEH params ["","","","","","","_projectile"]; + +_navigationParams params ["_yawChange", "_pitchChange", "_lastPitch", "_lastYaw", "_initialPitch", "_pitchUp", "_lastYawRateDifference"]; + +// for some reason we need to multiply this. I don't know why, but it just works +_pitchChange = _pitchChange * 1.5; +_yawChange = _yawChange * 1.5; + +((velocity _projectile) call CBA_fnc_vect2polar) params ["", "_currentYaw", "_currentPitch"]; + +private _pitchRate = if (_timestep == 0) then { + 0 +} else { + (_currentPitch - _lastPitch) / _timestep +}; +_navigationParams set [2, _currentPitch]; + +private _pitchModifier = if (_pitchChange == 0) then { + 1 +} else { + abs (_pitchRate / _pitchChange) +}; +private _desiredPitchChange = (_pitchChange - _pitchRate) * PROPORTIONALITY_CONSTANT * _pitchModifier; +_desiredPitchChange = _desiredPitchChange + _pitchUp * (_initialPitch - _currentPitch) * PROPORTIONALITY_CONSTANT * _pitchModifier; + +private _yawRate = if (_timestep == 0) then { + 0 +} else { + (_currentYaw - _lastYaw) / _timestep +}; +_navigationParams set [3, _currentYaw]; + +private _yawModifier = if (_yawChange == 0) then { + 1 +} else { + abs (_yawRate / _yawChange) +}; + +private _yawRateDifference = _yawChange - _yawRate; +private _yawChangeDerivative = if (_timestep == 0) then { + 0 +} else { + (_yawRateDifference - _lastYawRateDifference) / _timestep +}; +_navigationParams set [6, _yawRateDifference]; + +private _desiredYawChange = _yawRateDifference * PROPORTIONALITY_CONSTANT + _yawRateDifference * 2; + +#ifdef DRAW_NLAW_INFO +drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,1,1], ASLtoAGL getPosASLVisual _projectile, 0.75, 0.75, 0, format ["dP [%1] dY: [%2]", _desiredPitchChange, _desiredYawChange], 1, 0.025, "TahomaB"]; +drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,1,1], [0, 0, 1] vectorAdd ASLtoAGL getPosASLVisual _projectile, 0.75, 0.75, 0, format ["pitch proportional [%1] yaw proportional [%2]", _pitchModifier, _yawModifier], 1, 0.025, "TahomaB"]; +#endif + +TRACE_4("nlaw pitch/yaw info",_currentPitch,_lastPitch,_currentYaw,_lastYaw); +TRACE_6("nlaw navigation",_yawChange,_desiredYawChange,_pitchChange,_desiredPitchChange,_yawRate,_pitchRate); + +_projectile vectorModelToWorldVisual [_yawChange + _desiredYawChange, 0, _pitchChange + _desiredPitchChange] + diff --git a/addons/nlaw/functions/fnc_navigation_onFired.sqf b/addons/nlaw/functions/fnc_navigation_onFired.sqf new file mode 100644 index 0000000000..895d5ff78b --- /dev/null +++ b/addons/nlaw/functions/fnc_navigation_onFired.sqf @@ -0,0 +1,70 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Sets up missile guidance state arrays (called from missileGuidance's onFired). + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * Navigation Parameters + * + * Example: + * [] call ace_nlaw_fnc_onFired + * + * Public: No + */ + +params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"]; +_firedEH params ["_shooter","","","","","","_projectile"]; +_launchParams params ["","_targetLaunchParams","","_attackProfile"]; +_targetLaunchParams params ["_target"]; +_stateParams params ["", "", "", "", "_navigationParams"]; + +// Reset _launchPos origin as projectile's height instead of player's foot +_targetLaunchParams set [2, getPosASL _projectile]; + +// Get state params: +TRACE_3("start of attack profile",_attackProfile,_shooter,vectorDir _projectile); + +private _firedLOS = _shooter weaponDirection (currentWeapon _shooter); +private _yawChange = 0; +private _pitchChange = 0; + +if (_shooter == ACE_player) then { + TRACE_2("isPlayer",GVAR(yawChange),GVAR(pitchChange)); + _yawChange = GVAR(yawChange); + _pitchChange = GVAR(pitchChange); + TRACE_1("los check",_firedLOS call CBA_fnc_vect2Polar); +} else { + if ((!isNil "_target") && {!isNull _target}) then { + _firedLOS = (getPosASL _projectile) vectorFromTo (aimPos _target); + (((eyePos _shooter) vectorFromTo (aimPos _target)) call CBA_fnc_vect2Polar) params ["", "_startYaw", "_startPitch"]; + // Add some random error to AI's velocity prediction: + private _random = random [(_shooter skillFinal "aimingAccuracy") min 0.9, 1, 2-((_shooter skillFinal "aimingAccuracy") min 0.9)]; + (((eyePos _shooter) vectorFromTo ((aimPos _target) vectorAdd ((velocity _target) vectorMultiply (_random)))) call CBA_fnc_vect2Polar) params ["", "_predictedYaw", "_predictedPitch"]; + _yawChange = ([_predictedYaw - _startYaw] call CBA_fnc_simplifyAngle180); + _pitchChange = ([_predictedPitch - _startPitch] call CBA_fnc_simplifyAngle180); + TRACE_1("AI",_target); + } else { + TRACE_1("AI - no target",_target); + }; +}; + +// Limit Max Deflection +//_yawChange = -10 max _yawChange min 10; +//_pitchChange = -10 max _pitchChange min 10; + +((velocity _projectile) call CBA_fnc_vect2polar) params ["", "_currentYaw", "_currentPitch"]; +((ACE_player weaponDirection (currentWeapon ACE_player)) call CBA_fnc_vect2Polar) params ["", "_yaw", "_pitch"]; + +TRACE_5("attackProfileStateParams",_firedLOS,_yawChange,_pitchChange,_currentPitch,_currentYaw); +_navigationParams set [0, _yawChange]; +_navigationParams set [1, _pitchChange]; +_navigationParams set [2, _currentPitch]; // last pitch +_navigationParams set [3, _currentYaw]; // last yaw +_navigationParams set [4, _pitch]; // initial pitch +_navigationParams set [5, 0]; // whether or not to zero out the pitch +_navigationParams set [6, 0]; +_navigationParams + diff --git a/addons/nlaw/functions/fnc_onFired.sqf b/addons/nlaw/functions/fnc_onFired.sqf index 11b38a1da0..e8332b8caf 100644 --- a/addons/nlaw/functions/fnc_onFired.sqf +++ b/addons/nlaw/functions/fnc_onFired.sqf @@ -19,7 +19,7 @@ params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_statePa _firedEH params ["_shooter","","","","","","_projectile"]; _launchParams params ["","_targetLaunchParams","","_attackProfile"]; _targetLaunchParams params ["_target"]; -_stateParams params ["", "", "_attackProfileStateParams"]; +_stateParams params ["", "_seekerStateParams", "_attackProfileStateParams"]; // Reset _launchPos origin as projectile's height instead of player's foot _targetLaunchParams set [2, getPosASL _projectile]; @@ -27,7 +27,7 @@ _targetLaunchParams set [2, getPosASL _projectile]; // Get state params: TRACE_3("start of attack profile",_attackProfile,_shooter,vectorDir _projectile); -private _firedLOS = _shooter weaponDirection (currentWeapon _shooter); +private _firedLOS = vectorDir _projectile; private _yawChange = 0; private _pitchChange = 0; @@ -36,6 +36,23 @@ if (_shooter == ACE_player) then { _yawChange = GVAR(yawChange); _pitchChange = GVAR(pitchChange); TRACE_1("los check",_firedLOS call CBA_fnc_vect2Polar); + + #ifdef DRAW_NLAW_INFO + systemChat format ["YAW [%1]", _yawChange]; + systemChat format ["PITCH [%1]", _pitchChange]; + GVAR(debug_firedPrediction) = []; + private _debugPos = getPosASL _projectile; + ((ACE_player weaponDirection (currentWeapon ACE_player)) call CBA_fnc_vect2Polar) params ["", "_debugYaw", "_debugPitch"]; + private _distance = 0; + for "_x" from 0 to 6 step 0.1 do { + private _debugAproxVel = linearConversion [0, 1, 5, 40, 170, true]; + _distance = _distance + _debugAproxVel * 0.1; + private _debugYaw = _debugYaw + _yawChange * _x; + private _debugPitch = _debugPitch + _pitchChange * _x; + private _debugPos = _debugPos vectorAdd ([_distance, _debugYaw, _debugPitch] call CBA_fnc_polar2vect); + GVAR(debug_firedPrediction) pushBack ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0,0,0,1], ASLtoAGL _debugPos, 0.5, 0.5, 0, format ["%1", _x], 1, 0.025, "TahomaB"]; + }; + #endif } else { if ((!isNil "_target") && {!isNull _target}) then { _firedLOS = (getPosASL _projectile) vectorFromTo (aimPos _target); @@ -55,6 +72,10 @@ if (_shooter == ACE_player) then { _yawChange = -10 max _yawChange min 10; _pitchChange = -10 max _pitchChange min 10; +_seekerStateParams set [2, _yawChange]; +_seekerStateParams set [3, _pitchChange]; +_seekerStateParams set [4, CBA_missionTime]; + TRACE_3("attackProfileStateParams",_firedLOS,_yawChange,_pitchChange); _attackProfileStateParams set [0, CBA_missionTime]; _attackProfileStateParams set [1, _firedLOS]; diff --git a/addons/nlaw/functions/fnc_seeker.sqf b/addons/nlaw/functions/fnc_seeker.sqf index e5de6d320c..a3a60e94a1 100644 --- a/addons/nlaw/functions/fnc_seeker.sqf +++ b/addons/nlaw/functions/fnc_seeker.sqf @@ -16,14 +16,27 @@ * * Public: No */ +#define PITCH_UP_TIME 1 -params ["", "_args", "_seekerStateParams"]; +params ["", "_args", "_seekerStateParams", "", "", "_targetData"]; _args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams"]; _firedEH params ["","","","","","","_projectile"]; _launchParams params ["", "_targetLaunchParams", "", "_attackProfile"]; _targetLaunchParams params ["", "", "_launchPos"]; +_stateParams params ["", "", "", "", "_navigationParams"]; -if (_attackProfile == QGVAR(directAttack)) exitWith {[0,0,0]}; +if (_attackProfile == QGVAR(directAttack)) exitWith { + _navigationParams set [5, 1]; + [0,0,0] +}; + +_seekerStateParams params ["", "", "", "_originalPitchRate", "_startTime"]; +_navigationParams params ["", "_pitchRate"]; + +// pitch up for the first second of flight to begin an over-fly trajectory +private _pitchChange = linearConversion [0, PITCH_UP_TIME, CBA_missionTime - _startTime, 2, 0, true]; +_navigationParams set [1, _originalPitchRate + _pitchChange]; +_navigationParams set [5, ((CBA_missionTime - _startTime) min PITCH_UP_TIME) / PITCH_UP_TIME]; private _projPos = getPosASL _projectile; From 8d2b2ce3b97fcfeecb0d2975d895e99e84dcb7a1 Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Fri, 23 Aug 2024 08:46:30 -0600 Subject: [PATCH 3/8] Dragon - Update to new framework (#10025) --- addons/dragon/CfgAmmo.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/dragon/CfgAmmo.hpp b/addons/dragon/CfgAmmo.hpp index f736e8451b..22630e03b0 100644 --- a/addons/dragon/CfgAmmo.hpp +++ b/addons/dragon/CfgAmmo.hpp @@ -38,9 +38,8 @@ class CfgAmmo { EGVAR(vehicle_damage,incendiary) = 1.0; class ace_missileguidance { - minDeflection = 0; - maxDeflection = 0; - incDeflection = 0; + pitchRate = 0; + yawRate = 0; canVanillaLock = 0; @@ -51,6 +50,9 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; + defaultNavigationType = "LineOfSight"; + navigationTypes[] = { "LineOfSight" }; + seekLastTargetPos = 0; seekerAngle = 30; seekerAccuracy = 1; @@ -82,6 +84,9 @@ class CfgAmmo { class ace_missileguidance { enabled = 1; + pitchRate = 0; + yawRate = 0; + // Guidance type for munitions defaultSeekerType = "SACLOS"; seekerTypes[] = { "SACLOS" }; From 4d088fd828644ef67d527bc4746b9f0138fef9f5 Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Fri, 23 Aug 2024 08:46:44 -0600 Subject: [PATCH 4/8] Missileguidance - Update DAGR (#10024) --- addons/missileguidance/CfgAmmo.hpp | 11 ++++---- addons/missileguidance/CfgMagazines.hpp | 34 ++++++++++++++++++------- addons/missileguidance/CfgWeapons.hpp | 7 ++++- addons/missileguidance/stringtable.xml | 9 +++++++ 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/addons/missileguidance/CfgAmmo.hpp b/addons/missileguidance/CfgAmmo.hpp index a2b07b7fff..814e6575d5 100644 --- a/addons/missileguidance/CfgAmmo.hpp +++ b/addons/missileguidance/CfgAmmo.hpp @@ -20,19 +20,21 @@ class CfgAmmo { class ADDON { enabled = 1; - minDeflection = 0.0005; // Minium flap deflection for guidance - maxDeflection = 0.0025; // Maximum flap deflection for guidance - incDeflection = 0.0005; // The incrmeent in which deflection adjusts. + pitchRate = 40; // degrees per second + yawRate = 40; canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode // Guidance type for munitions defaultSeekerType = "SALH"; - seekerTypes[] = { "SALH", "LIDAR", "SARH", "Optic", "Thermal", "GPS", "SACLOS", "MCLOS" }; + seekerTypes[] = { "SALH" }; defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; + defaultNavigationType = "AugmentedProportionalNavigation"; + navigationTypes[] = { "AugmentedProportionalNavigation" }; + seekerAngle = 90; // Angle in front of the missile which can be searched seekerAccuracy = 1; // seeker accuracy multiplier @@ -68,7 +70,6 @@ class CfgAmmo { // Begin ACE guidance Configs class ADDON { enabled = 1; - minDeflection = 0.00005; // Minium flap deflection for guidance maxDeflection = 0.025; // Maximum flap deflection for guidance incDeflection = 0.00005; // The incrmeent in which deflection adjusts. diff --git a/addons/missileguidance/CfgMagazines.hpp b/addons/missileguidance/CfgMagazines.hpp index 74d75e8d4a..c7ef48004c 100644 --- a/addons/missileguidance/CfgMagazines.hpp +++ b/addons/missileguidance/CfgMagazines.hpp @@ -4,24 +4,40 @@ class CfgMagazines { class 6Rnd_ACE_Hydra70_DAGR: 12Rnd_PG_missiles { ammo = "ACE_Hydra70_DAGR"; count = 12; - displayName = "6 Round DAGR"; - displayNameShort = "6 Round DAGR"; - descriptionShort = "6 Round DAGR"; + displayName = CSTRING(Hydra70_DAGR_6x); weight = 36; }; class 12Rnd_ACE_Hydra70_DAGR: 6Rnd_ACE_Hydra70_DAGR { count = 12; - displayName = "16 Round DAGR"; - displayNameShort = "16 Round DAGR"; - descriptionShort = "16 Round DAGR"; + displayName = CSTRING(Hydra70_DAGR_12x); weight = 72; }; class 24Rnd_ACE_Hydra70_DAGR: 6Rnd_ACE_Hydra70_DAGR { count = 24; - displayName = "24 Round DAGR"; - displayNameShort = "24 Round DAGR"; - descriptionShort = "24 Round DAGR"; + displayName = CSTRING(Hydra70_DAGR_24x); weight = 72; }; + + class PylonRack_12Rnd_PG_missiles; + class PylonRack_6Rnd_ACE_DAGR: PylonRack_12Rnd_PG_missiles { + ammo = "ACE_Hydra70_DAGR"; + displayName = CSTRING(Hydra70_DAGR_6x); + count = 6; + pylonWeapon = QGVAR(dagr); + }; + + class PylonRack_12Rnd_ACE_DAGR: PylonRack_12Rnd_PG_missiles { + ammo = "ACE_Hydra70_DAGR"; + displayName = CSTRING(Hydra70_DAGR_12x); + count = 12; + pylonWeapon = QGVAR(dagr); + }; + + class PylonRack_24Rnd_ACE_DAGR: PylonRack_12Rnd_PG_missiles { + ammo = "ACE_Hydra70_DAGR"; + displayName = CSTRING(Hydra70_DAGR_24x); + count = 24; + pylonWeapon = QGVAR(dagr); + }; }; diff --git a/addons/missileguidance/CfgWeapons.hpp b/addons/missileguidance/CfgWeapons.hpp index b03628e777..d88cf27b53 100644 --- a/addons/missileguidance/CfgWeapons.hpp +++ b/addons/missileguidance/CfgWeapons.hpp @@ -2,8 +2,13 @@ class CfgWeapons { class missiles_DAGR; class GVAR(dagr): missiles_DAGR { + EGVAR(laser,canSelect) = 1; // can ace_laser lock (allows switching laser code) + EGVAR(laser,showHud) = 1; // show attack profile / lock on hud + magazines[] = {"6Rnd_ACE_Hydra70_DAGR","12Rnd_ACE_Hydra70_DAGR","24Rnd_ACE_Hydra70_DAGR","PylonRack_6Rnd_ACE_DAGR","PylonRack_12Rnd_ACE_DAGR","PylonRack_24Rnd_ACE_DAGR"}; + + autoFire = 0; canLock = 0; - magazines[] = {"6Rnd_ACE_Hydra70_DAGR","12Rnd_ACE_Hydra70_DAGR","24Rnd_ACE_Hydra70_DAGR"}; + weaponLockSystem = 0; lockingTargetSound[] = {"",0,1}; lockedTargetSound[] = {"",0,1}; }; diff --git a/addons/missileguidance/stringtable.xml b/addons/missileguidance/stringtable.xml index aacdd472d6..8020415eaa 100644 --- a/addons/missileguidance/stringtable.xml +++ b/addons/missileguidance/stringtable.xml @@ -205,5 +205,14 @@ 循環切換開火模式 Ateşleme Modunu Değiştir + + 6x DAGR [ACE] + + + 12x DAGR [ACE] + + + 24x DAGR [ACE] + From fad9244104e940d055bad694b18c18496e6096f7 Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Fri, 23 Aug 2024 08:47:28 -0600 Subject: [PATCH 5/8] Hellfire - Update to new framework (#10028) --- addons/hellfire/CfgAmmo.hpp | 25 ++++-- addons/hellfire/XEH_PREP.hpp | 1 + .../hellfire/functions/fnc_attackProfile.sqf | 81 ++++++++++++------- .../fnc_getAttackProfileSettings.sqf | 6 ++ .../functions/fnc_midCourseTransition.sqf | 29 +++++++ 5 files changed, 106 insertions(+), 36 deletions(-) create mode 100644 addons/hellfire/functions/fnc_midCourseTransition.sqf diff --git a/addons/hellfire/CfgAmmo.hpp b/addons/hellfire/CfgAmmo.hpp index 5eef9ad47e..02346deac3 100644 --- a/addons/hellfire/CfgAmmo.hpp +++ b/addons/hellfire/CfgAmmo.hpp @@ -26,9 +26,8 @@ class CfgAmmo { class ace_missileguidance { enabled = 1; - minDeflection = 0.0005; // Minium flap deflection for guidance - maxDeflection = 0.01; // Maximum flap deflection for guidance - incDeflection = 0.0005; // The incrmeent in which deflection adjusts. + pitchRate = 30; // degrees per second + yawRate = 30; canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode @@ -39,6 +38,9 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; + defaultNavigationType = "Direct"; + navigationTypes[] = { "Direct", "ZeroEffortMiss" }; + seekLastTargetPos = 1; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 70; // Angle in front of the missile which can be searched seekerAccuracy = 1; // seeker accuracy multiplier @@ -49,6 +51,19 @@ class CfgAmmo { // Attack profile type selection defaultAttackProfile = "hellfire"; attackProfiles[] = {"hellfire", "hellfire_hi", "hellfire_lo"}; + + class navigationStates { + class initial { + transitionCondition = QFUNC(midCourseTransition); + navigationType = "Direct"; + }; + class terminal { + transitionCondition = ""; + navigationType = "ZeroEffortMiss"; + }; + // transitions from initial -> termimal + states[] = {"initial", "terminal"}; + }; }; }; class ACE_Hellfire_AGM114N: ACE_Hellfire_AGM114K { @@ -75,8 +90,8 @@ class CfgAmmo { canVanillaLock = 1; enabled = 1; // Missile Guidance must be explicitly enabled seekLastTargetPos = 0; - defaultSeekerType = "ARH"; - seekerTypes[] = { "ARH" }; + defaultSeekerType = "MillimeterWaveRadar"; + seekerTypes[] = { "MillimeterWaveRadar" }; defaultSeekerLockMode = "LOBL"; seekerLockModes[] = { "LOBL" }; diff --git a/addons/hellfire/XEH_PREP.hpp b/addons/hellfire/XEH_PREP.hpp index f30cf0bffd..011810aa04 100644 --- a/addons/hellfire/XEH_PREP.hpp +++ b/addons/hellfire/XEH_PREP.hpp @@ -2,3 +2,4 @@ LOG("prep"); PREP(attackProfile); PREP(getAttackProfileSettings); PREP(setupVehicle); +PREP(midCourseTransition); diff --git a/addons/hellfire/functions/fnc_attackProfile.sqf b/addons/hellfire/functions/fnc_attackProfile.sqf index 26bc3f1ff0..221d99e7ae 100644 --- a/addons/hellfire/functions/fnc_attackProfile.sqf +++ b/addons/hellfire/functions/fnc_attackProfile.sqf @@ -18,80 +18,99 @@ */ params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; -_args params ["_firedEH", "_launchParams", "", "", "_stateParams"]; +_args params ["_firedEH", "_launchParams", "_flightParams", "", "_stateParams"]; _stateParams params ["", "_seekerStateParams"]; _launchParams params ["","_targetLaunchParams","_seekerType"]; -_targetLaunchParams params ["", "", "_launchPos"]; +_targetLaunchParams params ["", "", "_launchPos", "_launchDir"]; _firedEH params ["","","","","","","_projectile"]; // Get state params: if (_attackProfileStateParams isEqualTo []) then { _this call FUNC(getAttackProfileSettings); }; -_attackProfileStateParams params ["_attackStage", "_configLaunchHeightClear"]; - +_attackProfileStateParams params ["_attackStage", "_configLaunchHeightClear", "_missileStateData"]; private _projectilePos = getPosASL _projectile; private _distanceFromLaunch2d = _launchPos distance2d _projectilePos; private _heightAboveLaunch = (_projectilePos select 2) - (_launchPos select 2); // Add height depending on distance for compensate -private _returnTargetPos = nil; +private _returnTargetPos = _seekerTargetPos; +if (_returnTargetPos isEqualTo [0, 0, 0]) then { + private _initialDistanceToTarget = 8000; + _returnTargetPos = _launchPos vectorAdd (_launchDir vectorMultiply _initialDistanceToTarget); +}; + +private _closingRate = vectorMagnitude velocity _projectile; +// subtract 500 meters to account for the fact that we don't want to be at the perfect pitch exactly when we cross the target +// 500 seemed good in testing +private _timeToGo = ((_projectilePos distance2d _seekerTargetPos) - 500) / _closingRate; + +// we could do stuff like desired attack angle, but I'm not going that far today +private _los = _projectilePos vectorFromTo _seekerTargetPos; + +_flightParams params ["_pitchRate", "_yawRate"]; + +private _angleToTarget = acos ((vectorDir _projectile) vectorCos _los); +private _atMinRotationAngle = _angleToTarget >= (_pitchRate * _timeToGo); switch (_attackStage) do { case STAGE_LAUNCH: { // Gain height quickly to pass terrain mask - _returnTargetPos = _projectilePos getPos [100, getDir _projectile]; - _returnTargetPos set [2, (_projectilePos select 2) + 36.4]; // 100 and 36.4 gives a 20 deg angle + _missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"]; + + _returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 20)]; // 100 and 36.4 gives a 20 deg angle if (_heightAboveLaunch > _configLaunchHeightClear) then { _attackProfileStateParams set [0, STAGE_SEEK_CRUISE]; + + _attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]]; TRACE_2("New Stage: STAGE_SEEK_CRUISE",_distanceFromLaunch2d,_heightAboveLaunch); }; + + if (_atMinRotationAngle) then { + _attackProfileStateParams set [0, STAGE_ATTACK_TERMINAL]; + + _attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]]; + TRACE_2("New Stage: STAGE_ATTACK_TERMINAL",_distanceToTarget2d,_currentHeightOverTarget); + }; }; case STAGE_SEEK_CRUISE: { // Slowly gain altitude while searching for target + _missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"]; + // Before 4000 cruise at 5.7 degrees up, then level out - private _cruiseHeight = linearConversion [3000, 5000, _distanceFromLaunch2d, 10, 0, true]; - - _returnTargetPos = _projectilePos getPos [100, getDir _projectile]; - _returnTargetPos set [2, (_projectilePos select 2) + _cruiseHeight]; - + _returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 5.7)]; + if (_seekerTargetPos isNotEqualTo [0,0,0]) then { _attackProfileStateParams set [0, STAGE_ATTACK_CRUISE]; + + _attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]]; TRACE_1("New Stage: STAGE_ATTACK_CRUISE",_distanceFromLaunch2d); }; }; case STAGE_ATTACK_CRUISE: { + _missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"]; + private _currentHeightOverTarget = (_projectilePos select 2) - (_seekerTargetPos select 2); private _distanceToTarget2d = _seekerTargetPos distance2d _projectilePos; - private _distToGoRatio = _distanceToTarget2d / (_launchPos distance2d _seekerTargetPos); - // arcing up at 7 degrees to start until 50% left, then smooth curve to a downward attack - private _gainSlope = linearConversion [0.5, 0.1, _distToGoRatio, 7, -7, true]; - _returnTargetPos = +_seekerTargetPos; - _returnTargetPos set [2, ((_projectilePos select 2) + (_distanceToTarget2d * sin _gainSlope)) max (_seekerTargetPos select 2)]; + _returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 7)]; - if ((_distanceToTarget2d < 500) || {(_currentHeightOverTarget atan2 _distanceToTarget2d) > 15}) then { // Wait until we can come down at a sharp angle + // if we are at the rotation limit, rotate to target + if (_atMinRotationAngle || {(_currentHeightOverTarget atan2 _distanceToTarget2d) > 15}) then { // Wait until we can come down at a sharp angle _attackProfileStateParams set [0, STAGE_ATTACK_TERMINAL]; + + _attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]]; TRACE_2("New Stage: STAGE_ATTACK_TERMINAL",_distanceToTarget2d,_currentHeightOverTarget); }; }; case STAGE_ATTACK_TERMINAL: { - private _distanceToTarget2d = _seekerTargetPos distance2d _projectilePos; - _returnTargetPos = _seekerTargetPos vectorAdd [0, 0, _distanceToTarget2d * 0.02]; }; }; -// Special radar case. Adjust target position such that we are leading it -if (_attackStage >= 3 && { _seekerType isEqualTo "ARH" }) then { - _seekerStateParams params ["", "", "", "", "", "", "", "_lastKnownVelocity"]; - private _projectileVelocity = velocity _projectile; - if (_projectileVelocity#2 < 0) then { - private _projectileSpeed = vectorMagnitude _projectileVelocity; // this gives a precise impact time versus using speed _projectile. Dont change - private _timeUntilImpact = (_seekerTargetPos distance _projectilePos) / _projectileSpeed; - _returnTargetPos = _returnTargetPos vectorAdd (_lastKnownVelocity vectorMultiply _timeUntilImpact); - }; -}; +// missile guidance defines this variable in doAttackProfile +//IGNORE_PRIVATE_WARNING ["_attackProfileName"]; +_attackProfileName = ["na", "hellfire - LAUNCH", "hellfire - SEEK CRUISE", "hellfire - ATTACK CRUISE", "hellfire - TERMINAL"] select _attackStage; -// TRACE_1("Adjusted target position",_returnTargetPos); +TRACE_1("Adjusted target position",_returnTargetPos); _returnTargetPos; diff --git a/addons/hellfire/functions/fnc_getAttackProfileSettings.sqf b/addons/hellfire/functions/fnc_getAttackProfileSettings.sqf index 14d89f82e3..b032c44d23 100644 --- a/addons/hellfire/functions/fnc_getAttackProfileSettings.sqf +++ b/addons/hellfire/functions/fnc_getAttackProfileSettings.sqf @@ -27,6 +27,8 @@ private _attackConfig = configFile >> QEGVAR(missileguidance,AttackProfiles) >> // Launch (clearing terrain mask for LO/HI): private _configLaunchHeightClear = getNumber (_attackConfig >> QGVAR(launchHeightClear)); +private _projectilePos = getPosASL _projectile; + // Get starting stage private _startingStage = if (_configLaunchHeightClear > 0) then { STAGE_LAUNCH; // LOAL-HI / LO @@ -40,5 +42,9 @@ private _startingStage = if (_configLaunchHeightClear > 0) then { // Set data in param array _attackProfileStateParams set [0, _startingStage]; _attackProfileStateParams set [1, _configLaunchHeightClear]; +_attackProfileStateParams set [2, [ + _projectilePos select 2, + _seekerTargetPos distance2d _projectilePos +]]; TRACE_1("new shot settings",_attackProfileStateParams); diff --git a/addons/hellfire/functions/fnc_midCourseTransition.sqf b/addons/hellfire/functions/fnc_midCourseTransition.sqf new file mode 100644 index 0000000000..ee56773410 --- /dev/null +++ b/addons/hellfire/functions/fnc_midCourseTransition.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Condition to switch to next navigation profile + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * None + * + * Example: + * [] call ace_hellfire_fnc_midCourseTransition + * + * Public: No + */ + +_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams", "_targetData", "_navigationStateData"]; +_firedEH params ["_shooter","","","","_ammo","","_projectile"]; +_launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo","_navigationType"]; +_targetLaunchParams params ["_target", "_targetPos", "_launchPos", "_launchDir", "_launchTime"]; +_flightParams params ["_pitchRate", "_yawRate", "_isBangBangGuidance"]; +_stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState","_navigationParams", "_guidanceParameters"]; +_seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"]; +_targetData params ["_targetDirection", "_attackProfileDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"]; + +_attackProfileStateParams params ["_state"]; +_state isEqualTo STAGE_ATTACK_TERMINAL; + From 9d429b8be52673ade6d864e2fe0a08ec28c7377d Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Fri, 23 Aug 2024 08:47:52 -0600 Subject: [PATCH 6/8] Hot - Update to new framework (#10029) --- addons/hot/CfgAmmo.hpp | 16 ++++++++++++---- addons/hot/CfgVehicles.hpp | 11 +++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/addons/hot/CfgAmmo.hpp b/addons/hot/CfgAmmo.hpp index 1be8c6067f..c5978b6d92 100644 --- a/addons/hot/CfgAmmo.hpp +++ b/addons/hot/CfgAmmo.hpp @@ -58,12 +58,13 @@ class CfgAmmo { class ace_missileguidance { enabled = 1; - minDeflection = 0; // Minium flap deflection for guidance - maxDeflection = 0.0030; // Maximum flap deflection for guidance - incDeflection = 0.0005; // The incrmeent in which deflection adjusts. + pitchRate = 45; // Minium flap deflection for guidance + yawRate = 45; // Maximum flap deflection for guidance canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode + showTrail = 1; + // Guidance type for munitions defaultSeekerType = "SACLOS"; seekerTypes[] = { "SACLOS" }; @@ -71,6 +72,14 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; + defaultNavigationType = "Line"; + navigationTypes[] = { "Line" }; + + lineGainP = 7; + lineGainD = 6; + + initialPitch = 2; + seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 30; // Angle from the shooter's view that can track the missile seekerAccuracy = 1; // seeker accuracy multiplier @@ -78,7 +87,6 @@ class CfgAmmo { seekerMinRange = 75; seekerMaxRange = 4000; // Range from the missile which the seeker can visually search - correctionDistance = 8; // distance from center of crosshair where missile slows down offsetFromCrosshair[] = { 0, 0, 0.5 }; // where the missile wants to stay in relation to the center of the crosshair. // Attack profile type selection diff --git a/addons/hot/CfgVehicles.hpp b/addons/hot/CfgVehicles.hpp index db5b8b5262..46ac7d5136 100644 --- a/addons/hot/CfgVehicles.hpp +++ b/addons/hot/CfgVehicles.hpp @@ -4,11 +4,22 @@ class CfgVehicles { class Turrets; }; class LT_01_base_F: Tank_F { + class AnimationSources; class Turrets: Turrets { class MainTurret; }; }; class LT_01_AT_base_F: LT_01_base_F { + class AnimationSources: AnimationSources { + class Missiles_revolving { + source = "revolving"; + weapon = QGVAR(generic_launcher); + }; + class Missiles_reloadMagazine { + source = "reloadMagazine"; + weapon = QGVAR(generic_launcher); + }; + }; class Turrets: Turrets { class MainTurret: MainTurret { weapons[] = {"SmokeLauncher","HMG_127",QGVAR(generic_launcher)}; From b36961937c86fc99262baed0754f8b9fb5da7598 Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Fri, 23 Aug 2024 08:48:08 -0600 Subject: [PATCH 7/8] Metis - Update to use missile guidance framework (#10033) --- addons/metis/CfgAmmo.hpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/addons/metis/CfgAmmo.hpp b/addons/metis/CfgAmmo.hpp index 1f613a36b1..c070343253 100644 --- a/addons/metis/CfgAmmo.hpp +++ b/addons/metis/CfgAmmo.hpp @@ -10,12 +10,14 @@ class CfgAmmo { class ace_missileguidance { enabled = 1; - minDeflection = 0; // Minium flap deflection for guidance - maxDeflection = 0.0027; // Maximum flap deflection for guidance - incDeflection = 0.0005; // The incrmeent in which deflection adjusts. + pitchRate = 50; // Minium flap deflection for guidance + yawRate = 50; // Maximum flap deflection for guidance + initialPitch = 2; canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode + showTrail = 1; + // Guidance type for munitions defaultSeekerType = "SACLOS"; seekerTypes[] = { "SACLOS" }; @@ -23,6 +25,12 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; + defaultNavigationType = "Line"; + navigationTypes[] = { "Line" }; + + lineGainP = 10; + lineGainD = 9; + seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 15; // Angle from the shooter's view that can track the missile seekerAccuracy = 1; // seeker accuracy multiplier @@ -30,7 +38,6 @@ class CfgAmmo { seekerMinRange = 80; seekerMaxRange = 2000; // Range from the missile which the seeker can visually search - correctionDistance = 3; // distance from center of crosshair where missile slows down offsetFromCrosshair[] = { 0, 0, 0 }; // where the missile wants to stay in relation to the center of the crosshair. // Attack profile type selection @@ -50,9 +57,8 @@ class CfgAmmo { class ace_missileguidance { enabled = 1; - minDeflection = 0; // Minium flap deflection for guidance - maxDeflection = 0.0027; // Maximum flap deflection for guidance - incDeflection = 0.0005; // The incrmeent in which deflection adjusts. + pitchRate = 25; // Minium flap deflection for guidance + yawRate = 25; // Maximum flap deflection for guidance canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode @@ -63,6 +69,12 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; + defaultNavigationType = "Line"; + navigationTypes[] = { "Line" }; + + lineGainP = 21; + lineGainD = 18; + seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 15; // Angle from the shooter's view that can track the missile seekerAccuracy = 1; // seeker accuracy multiplier @@ -70,7 +82,7 @@ class CfgAmmo { seekerMinRange = 80; seekerMaxRange = 2000; // Range from the missile which the seeker can visually search - correctionDistance = 3; // distance from center of crosshair where missile slows down + correctionDistance = 1; // distance from center of crosshair where missile slows down offsetFromCrosshair[] = { 0, 0, 0 }; // where the missile wants to stay in relation to the center of the crosshair. // Attack profile type selection From 7279b94945eb1270345b9452400ff525524fca29 Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Fri, 23 Aug 2024 08:51:55 -0600 Subject: [PATCH 8/8] Missileguidance - Update Javelin (#10030) --- addons/missileguidance/CfgAmmo.hpp | 26 +++++++++++++-- addons/missileguidance/XEH_PREP.hpp | 1 + .../functions/fnc_attackProfile_JAV_DIR.sqf | 5 +-- .../functions/fnc_attackProfile_JAV_TOP.sqf | 2 +- .../fnc_javelin_midCourseTransition.sqf | 33 +++++++++++++++++++ 5 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 addons/missileguidance/functions/fnc_javelin_midCourseTransition.sqf diff --git a/addons/missileguidance/CfgAmmo.hpp b/addons/missileguidance/CfgAmmo.hpp index 814e6575d5..d9813fdf77 100644 --- a/addons/missileguidance/CfgAmmo.hpp +++ b/addons/missileguidance/CfgAmmo.hpp @@ -70,9 +70,11 @@ class CfgAmmo { // Begin ACE guidance Configs class ADDON { enabled = 1; - minDeflection = 0.00005; // Minium flap deflection for guidance - maxDeflection = 0.025; // Maximum flap deflection for guidance - incDeflection = 0.00005; // The incrmeent in which deflection adjusts. + + pitchRate = 100; // degrees per second + yawRate = 100; + stabilityCoefficient = 0.2; + bangBangGuidance = 0; canVanillaLock = 0; @@ -83,6 +85,11 @@ class CfgAmmo { defaultSeekerLockMode = "LOBL"; seekerLockModes[] = { "LOBL" }; + defaultNavigationType = "Direct"; + navigationTypes[] = { "Direct", "ZeroEffortMiss" }; + + navigationGain = 3; + seekerAngle = 180; // Angle in front of the missile which can be searched seekerAccuracy = 1; // seeker accuracy multiplier @@ -95,6 +102,19 @@ class CfgAmmo { defaultAttackProfile = "JAV_TOP"; attackProfiles[] = { "JAV_TOP", "JAV_DIR" }; useModeForAttackProfile = 1; + + class navigationStates { + class initial { + transitionCondition = QFUNC(javelin_midCourseTransition); + navigationType = "Direct"; + }; + class terminal { + transitionCondition = ""; + navigationType = "ZeroEffortMiss"; + }; + // transitions from initial -> termimal + states[] = {"initial", "terminal"}; + }; }; }; class ACE_Javelin_FGM148_static: ACE_Javelin_FGM148 { diff --git a/addons/missileguidance/XEH_PREP.hpp b/addons/missileguidance/XEH_PREP.hpp index d0c6b0af11..daff5b502b 100644 --- a/addons/missileguidance/XEH_PREP.hpp +++ b/addons/missileguidance/XEH_PREP.hpp @@ -32,6 +32,7 @@ PREP(attackProfile_BEAM); // Javelin profiles PREP(attackProfile_JAV_DIR); PREP(attackProfile_JAV_TOP); +PREP(javelin_midCourseTransition); // Navigation Profiles PREP(navigationType_zeroEffortMiss); diff --git a/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf b/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf index b690ab2075..6b06c0dd91 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf @@ -47,7 +47,7 @@ private _returnTargetPos = _seekerTargetPos; switch (_attackProfileStateParams select 0) do { case STAGE_LAUNCH: { TRACE_1("STAGE_LAUNCH",""); - if (_distanceToShooter < 10) then { + if (_distanceToShooter < 6) then { _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2]; } else { _attackProfileStateParams set [0, STAGE_CLIMB]; @@ -55,7 +55,8 @@ switch (_attackProfileStateParams select 0) do { }; case STAGE_CLIMB: { TRACE_1("STAGE_CLIMB",""); - private _cruisAlt = 60 * (_distanceShooterToTarget/2000); + // 65 is min range + private _cruisAlt = 60 * ((0 max (_distanceShooterToTarget - 65))/2000); if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then { _attackProfileStateParams set [0, STAGE_TERMINAL]; diff --git a/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf b/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf index f1f360e403..347d144914 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf @@ -57,7 +57,7 @@ switch( (_attackProfileStateParams select 0) ) do { TRACE_1("STAGE_CLIMB",""); private _cruisAlt = 140; if (_distanceShooterToTarget < 1250) then { - _cruisAlt = 140 * (_distanceShooterToTarget/1250); + _cruisAlt = 140 * ((0 max (_distanceShooterToTarget - 150))/1250); TRACE_1("_cruisAlt",_cruisAlt); }; if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then { diff --git a/addons/missileguidance/functions/fnc_javelin_midCourseTransition.sqf b/addons/missileguidance/functions/fnc_javelin_midCourseTransition.sqf new file mode 100644 index 0000000000..ad0eca65cb --- /dev/null +++ b/addons/missileguidance/functions/fnc_javelin_midCourseTransition.sqf @@ -0,0 +1,33 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Condition to switch to next navigation profile + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_javelin_midCourseTransition + * + * Public: No + */ +#define STAGE_LAUNCH 1 +#define STAGE_CLIMB 2 +#define STAGE_COAST 3 +#define STAGE_TERMINAL 4 + +_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams", "_targetData", "_navigationStateData"]; +_firedEH params ["_shooter","","","","_ammo","","_projectile"]; +_launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo","_navigationType"]; +_targetLaunchParams params ["_target", "_targetPos", "_launchPos", "_launchDir", "_launchTime"]; +_flightParams params ["_pitchRate", "_yawRate", "_isBangBangGuidance"]; +_stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState","_navigationParams", "_guidanceParameters"]; +_seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"]; +_targetData params ["_targetDirection", "_attackProfileDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"]; + +_attackProfileStateParams params ["_state"]; +_state isEqualTo STAGE_TERMINAL +