From 1873467deb516e30637599c30f876ddab1a45858 Mon Sep 17 00:00:00 2001 From: Brandon Danyluk Date: Tue, 13 Apr 2021 16:10:39 -0600 Subject: [PATCH] Add zero-effort miss. Seeker now feeds data to navigation --- addons/aim120/CfgAmmo.hpp | 8 ++-- addons/missileguidance/ACE_GuidanceConfig.hpp | 4 ++ addons/missileguidance/XEH_PREP.hpp | 1 + .../fnc_navigationType_augmentedProNav.sqf | 31 +++++---------- .../fnc_navigationType_lineOfSight.sqf | 15 ++++---- .../functions/fnc_navigationType_proNav.sqf | 25 ++++-------- .../fnc_navigationType_zeroEffortMiss.sqf | 38 +++++++++++++++++++ .../missileguidance/functions/fnc_onFired.sqf | 14 +++++-- .../functions/fnc_proNav_onFired.sqf | 2 - .../functions/fnc_seekerType_ARH.sqf | 8 +++- .../functions/fnc_seekerType_Optic.sqf | 10 ++--- .../functions/fnc_seekerType_SACLOS.sqf | 4 +- .../functions/fnc_seekerType_SALH.sqf | 7 +++- addons/missileguidance/todo.txt | 2 +- 14 files changed, 106 insertions(+), 63 deletions(-) create mode 100644 addons/missileguidance/functions/fnc_navigationType_zeroEffortMiss.sqf diff --git a/addons/aim120/CfgAmmo.hpp b/addons/aim120/CfgAmmo.hpp index 27a044143c..a7c1a00959 100644 --- a/addons/aim120/CfgAmmo.hpp +++ b/addons/aim120/CfgAmmo.hpp @@ -22,8 +22,8 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; - defaultNavigationType = "AugmentedProportionalNavigation"; - navigationTypes[] = { "AugmentedProportionalNavigation" }; + defaultNavigationType = "ZeroEffortMiss"; + navigationTypes[] = { "ZeroEffortMiss" }; seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 50; // Angle from the shooter's view that can track the missile @@ -62,8 +62,8 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; - defaultNavigationType = "AugmentedProportionalNavigation"; - navigationTypes[] = { "AugmentedProportionalNavigation" }; + defaultNavigationType = "ZeroEffortMiss"; + navigationTypes[] = { "ZeroEffortMiss" }; seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 50; // Angle from the shooter's view that can track the missile diff --git a/addons/missileguidance/ACE_GuidanceConfig.hpp b/addons/missileguidance/ACE_GuidanceConfig.hpp index 36f48ffe8e..3858353462 100644 --- a/addons/missileguidance/ACE_GuidanceConfig.hpp +++ b/addons/missileguidance/ACE_GuidanceConfig.hpp @@ -93,6 +93,7 @@ class GVAR(SeekerTypes) { class GVAR(NavigationTypes) { class LineOfSight { functionName = QFUNC(navigationType_lineOfSight); + onFired = QFUNC(proNav_onFired); }; class ProportionalNavigation { functionName = QFUNC(navigationType_proNav); @@ -102,4 +103,7 @@ class GVAR(NavigationTypes) { functionName = QFUNC(navigationType_augmentedProNav); onFired = QFUNC(proNav_onFired); }; + class ZeroEffortMiss { + functionName = QFUNC(navigationType_zeroEffortMiss); + }; }; diff --git a/addons/missileguidance/XEH_PREP.hpp b/addons/missileguidance/XEH_PREP.hpp index 6632d64d41..c4d20ac106 100644 --- a/addons/missileguidance/XEH_PREP.hpp +++ b/addons/missileguidance/XEH_PREP.hpp @@ -29,6 +29,7 @@ PREP(attackProfile_JAV_DIR); PREP(attackProfile_JAV_TOP); // Navigation Profiles +PREP(navigationType_zeroEffortMiss); PREP(navigationType_augmentedProNav); PREP(navigationType_proNav); PREP(navigationType_lineOfSight); diff --git a/addons/missileguidance/functions/fnc_navigationType_augmentedProNav.sqf b/addons/missileguidance/functions/fnc_navigationType_augmentedProNav.sqf index b6a8c19cde..c13b8e7ec2 100644 --- a/addons/missileguidance/functions/fnc_navigationType_augmentedProNav.sqf +++ b/addons/missileguidance/functions/fnc_navigationType_augmentedProNav.sqf @@ -15,49 +15,38 @@ * Public: No */ params ["_args", "_timestep", "_seekerTargetPos", "_profileAdjustedTargetPos"]; -_args params ["_firedEH", "", "", "", "_stateParams"]; +_args params ["_firedEH", "", "", "", "_stateParams", "_targetData"]; _firedEH params ["","","","","","","_projectile"]; _stateParams params ["", "", "", "","_navigationParams"]; _navigationParams params ["_lastMissileFrame", "_navigationGain"]; -_lastMissileFrame params ["_lastTargetPosition", "_lastTargetVelocity", "_lastLineOfSight"]; +_lastMissileFrame params ["_lastLineOfSight"]; +_targetData params ["_targetDirection", "", "_targetVelocity", "_targetAcceleration"]; // Proportional navigation implemented via "Fundamentals of proportional navigation" by Stephen Murtaugh and Harry Criel -private _projectileVelocity = velocity _projectile; +private _closingVelocity = _targetVelocity vectorDiff velocity _projectile; -// integrate target velocity for realistic inference of velocity -private _targetVelocity = _lastTargetVelocity; -private _targetAcceleration = [0, 0, 0]; -if (_timestep != 0) then { - _targetVelocity = (_seekerTargetPos vectorDiff _lastTargetPosition) vectorMultiply (1 / _timestep); - _targetAcceleration = (_targetVelocity vectorDiff _lastTargetVelocity) vectorMultiply (1 / _timestep); -}; - -private _closingVelocity = _targetVelocity vectorDiff _projectileVelocity; - -private _lineOfSight = vectorNormalized (_profileAdjustedTargetPos vectorDiff getPosASLVisual _projectile); - -private _targetAccelerationProjected = _lineOfSight vectorMultiply (_targetAcceleration vectorDotProduct _lineOfSight); +private _targetAccelerationProjected = _targetDirection vectorMultiply (_targetAcceleration vectorDotProduct _targetDirection); _targetAcceleration = _targetAcceleration vectorDiff _targetAccelerationProjected; -systemChat str vectorMagnitude _targetAcceleration; + // the los rate is tiny, so we multiply by a constant of a power of ten to get more aggressive acceleration // this is just due to how we measure our LOS delta, the vectors involved are _tiny_ -private _losDelta = _lineOfSight vectorDiff _lastLineOfSight; +private _losDelta = _targetDirection vectorDiff _lastLineOfSight; private _losRate = if (_timestep == 0) then { 0 } else { 10 * (vectorMagnitude _losDelta) / _timestep; }; -private _lateralAcceleration = (_navigationGain * _losRate); +private _lateralAcceleration = _navigationGain * _losRate; private _commandedAcceleration = _closingVelocity vectorMultiply _lateralAcceleration; _commandedAcceleration = _commandedAcceleration vectorAdd (_losDelta vectorMultiply (0.5 * _navigationGain * vectorMagnitude _targetAcceleration)); // we need acceleration normal to our LOS -private _commandedAccelerationProjected = _lineOfSight vectorMultiply (_commandedAcceleration vectorDotProduct _lineOfSight); +private _commandedAccelerationProjected = _targetDirection vectorMultiply (_commandedAcceleration vectorDotProduct _targetDirection); _commandedAcceleration = _commandedAcceleration vectorDiff _commandedAccelerationProjected; if (accTime > 0) then { - _navigationParams set [0, [_seekerTargetPos, _targetVelocity, _lineOfSight]]; + _navigationParams set [0, [_seekerTargetPos, _targetVelocity, _targetDirection]]; }; _commandedAcceleration diff --git a/addons/missileguidance/functions/fnc_navigationType_lineOfSight.sqf b/addons/missileguidance/functions/fnc_navigationType_lineOfSight.sqf index 8c85392281..99e014a14b 100644 --- a/addons/missileguidance/functions/fnc_navigationType_lineOfSight.sqf +++ b/addons/missileguidance/functions/fnc_navigationType_lineOfSight.sqf @@ -15,32 +15,33 @@ * Public: No */ params ["_args", "_timestep", "_seekerTargetPos", "_profileAdjustedTargetPos"]; -_args params ["_firedEH", "", "", "", "_stateParams"]; +_args params ["_firedEH", "", "", "", "_stateParams", "_targetData"]; _firedEH params ["","","","","","","_projectile"]; _stateParams params ["", "", "", "","_navigationParams"]; -_navigationParams params [["_lastLineOfSight", [0, 0, 0]]]; +_navigationParams params ["_lastLineOfSight"]; +_targetData params ["_targetDirection", "", "_targetVelocity", ""]; // Semi-proportional navigation implemented via "Fundamentals of proportional navigation" by Stephen Murtaugh and Harry Criel -private _lineOfSight = vectorNormalized (_profileAdjustedTargetPos vectorDiff getPosASLVisual _projectile); // the los rate is tiny, so we multiply by a constant of a power of ten to get more aggressive acceleration // this is just due to how we measure our LOS delta, the vectors involved are _tiny_ -private _losDelta = _lineOfSight vectorDiff _lastLineOfSight; +private _losDelta = _targetDirection vectorDiff _lastLineOfSight; private _losRate = if (_timestep == 0) then { 0 } else { 10 * (vectorMagnitude _losDelta) / _timestep; }; -private _commandedAcceleration = (velocity _projectile) vectorMultiply _losRate; -TRACE_5("LOS NAV",_commandedAcceleration,_projectile,_losRate,_lineOfSight,_lastLineOfSight); +private _closingVelocity = _targetVelocity vectorDiff (velocity _projectile); + +private _commandedAcceleration = _closingVelocity vectorMultiply _losRate; // we need acceleration normal to our LOS private _commandedAccelerationProjected = _lineOfSight vectorMultiply (_commandedAcceleration vectorDotProduct _lineOfSight); _commandedAcceleration = _commandedAcceleration vectorDiff _commandedAccelerationProjected; if (accTime > 0) then { - _navigationParams set [0, _lineOfSight]; + _navigationParams set [0, _targetDirection]; }; _commandedAccelerationProjected diff --git a/addons/missileguidance/functions/fnc_navigationType_proNav.sqf b/addons/missileguidance/functions/fnc_navigationType_proNav.sqf index 658e447f04..3e6e768062 100644 --- a/addons/missileguidance/functions/fnc_navigationType_proNav.sqf +++ b/addons/missileguidance/functions/fnc_navigationType_proNav.sqf @@ -15,43 +15,34 @@ * Public: No */ params ["_args", "_timestep", "_seekerTargetPos", "_profileAdjustedTargetPos"]; -_args params ["_firedEH", "", "", "", "_stateParams"]; +_args params ["_firedEH", "", "", "", "_stateParams", "_targetData"]; _firedEH params ["","","","","","","_projectile"]; _stateParams params ["", "", "", "","_navigationParams"]; _navigationParams params ["_lastMissileFrame", "_navigationGain"]; -_lastMissileFrame params ["_lastTargetPosition", "_lastTargetVelocity", "_lastLineOfSight"]; +_lastMissileFrame params ["_lastLineOfSight"]; +_targetData params ["_targetDirection", "", "_targetVelocity", ""]; // Proportional navigation implemented via "Fundamentals of proportional navigation" by Stephen Murtaugh and Harry Criel -private _projectileVelocity = velocity _projectile; - -// integrate target velocity for realistic inference of velocity -private _targetVelocity = _lastTargetVelocity; -if (_timestep != 0) then { - _targetVelocity = (_seekerTargetPos vectorDiff _lastTargetPosition) vectorMultiply (1 / _timestep); -}; - -private _closingVelocity = _targetVelocity vectorDiff _projectileVelocity; - -private _lineOfSight = vectorNormalized (_profileAdjustedTargetPos vectorDiff getPosASLVisual _projectile); +private _closingVelocity = _targetVelocity vectorDiff velocity _projectile; // the los rate is tiny, so we multiply by a constant of a power of ten to get more aggressive acceleration // this is just due to how we measure our LOS delta, the vectors involved are _tiny_ -private _losDelta = _lineOfSight vectorDiff _lastLineOfSight; +private _losDelta = _targetDirection vectorDiff _lastLineOfSight; private _losRate = if (_timestep == 0) then { 0 } else { 10 * (vectorMagnitude _losDelta) / _timestep; }; -private _lateralAcceleration = (_navigationGain * _losRate); +private _lateralAcceleration = _navigationGain * _losRate; private _commandedAcceleration = _closingVelocity vectorMultiply _lateralAcceleration; // we need acceleration normal to our LOS -private _commandedAccelerationProjected = _lineOfSight vectorMultiply (_commandedAcceleration vectorDotProduct _lineOfSight); +private _commandedAccelerationProjected = _targetDirection vectorMultiply (_commandedAcceleration vectorDotProduct _targetDirection); _commandedAcceleration = _commandedAcceleration vectorDiff _commandedAccelerationProjected; if (accTime > 0) then { - _navigationParams set [0, [_seekerTargetPos, _targetVelocity, _lineOfSight]]; + _navigationParams set [0, [_seekerTargetPos, _targetVelocity, _targetDirection]]; }; _commandedAcceleration diff --git a/addons/missileguidance/functions/fnc_navigationType_zeroEffortMiss.sqf b/addons/missileguidance/functions/fnc_navigationType_zeroEffortMiss.sqf new file mode 100644 index 0000000000..8c802ebc77 --- /dev/null +++ b/addons/missileguidance/functions/fnc_navigationType_zeroEffortMiss.sqf @@ -0,0 +1,38 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Determine path for projectile to take in accordance to zero-effort miss pro-nav, takes target acceleration into account. Super deadly + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * Commanded acceleration normal to LOS in world space + * + * Example: + * [] call ace_missileguidance_fnc_navigationType_zeroEffortMiss + * + * Public: No + */ +params ["_args", "_timestep", "_seekerTargetPos", "_profileAdjustedTargetPos"]; +_args params ["_firedEH", "", "", "", "_stateParams", "_targetData"]; +_firedEH params ["","","","","","","_projectile"]; +_stateParams params ["", "", "", "","_navigationParams"]; +_navigationParams params ["", "_navigationGain"]; +_targetData params ["_targetDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"]; + +private _vectorToTarget = _targetDirection vectorMultiply _targetRange; +private _closingVelocity = _targetVelocity vectorDiff velocity _projectile; +private _timeToGo = _targetRange / vectorMagnitude _closingVelocity; + +private _zeroEffortMiss = _vectorToTarget vectorAdd (_closingVelocity vectorMultiply _timeToGo); +private _zeroEffortMissProjectiled = _targetDirection vectorMultiply (_zeroEffortMiss vectorDotProduct _targetDirection); +private _zeroEffortMissNormal = _zeroEffortMiss vectorDiff _zeroEffortMissProjectiled; + +private _commandedAcceleration = _zeroEffortMissNormal vectorMultiply (_navigationGain / (_timeToGo * _timeToGo)); + +if (accTime > 0) then { + _navigationParams set [0, [_lineOfSight]]; +}; + +_commandedAcceleration diff --git a/addons/missileguidance/functions/fnc_onFired.sqf b/addons/missileguidance/functions/fnc_onFired.sqf index d1b5fc87c0..83bf2b9da0 100644 --- a/addons/missileguidance/functions/fnc_onFired.sqf +++ b/addons/missileguidance/functions/fnc_onFired.sqf @@ -137,7 +137,14 @@ private _args = [_this, getNumber ( _config >> "seekerMaxRange" ), getNumber ( _config >> "seekerMinRange" ) ], - [ diag_tickTime, [], [], _lastKnownPosState, _navigationParameters, [_pitchYaw select 1, 0, _pitchYaw select 2]] + [ diag_tickTime, [], [], _lastKnownPosState, _navigationParameters, [_pitchYaw select 1, 0, _pitchYaw select 2]], + [ + // target data from missile. Must be filled by seeker for navigation to work + [0, 0, 0], // direction to target + 0, // range to target + [0, 0, 0], // target velocity + [0, 0, 0] // target acceleration + ] ]; private _onFiredFunc = getText (configFile >> QGVAR(SeekerTypes) >> _seekerType >> "onFired"); @@ -166,13 +173,14 @@ if (_onFiredFunc != "") then { }; // Reverse: -// _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"]; +// _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams", "_targetData"]; // _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"]; +// _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState","_navigationParams", "_guidanceParameters"]; // _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"]; +// _targetData params ["_targetDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"]; [LINKFUNC(guidancePFH),0, _args ] call CBA_fnc_addPerFrameHandler; diff --git a/addons/missileguidance/functions/fnc_proNav_onFired.sqf b/addons/missileguidance/functions/fnc_proNav_onFired.sqf index d1806c1907..9725f628ef 100644 --- a/addons/missileguidance/functions/fnc_proNav_onFired.sqf +++ b/addons/missileguidance/functions/fnc_proNav_onFired.sqf @@ -29,8 +29,6 @@ if (_navigationGain == 0) then { _navigationParams = [ [ // Last Missile Frame - [0, 0, 0], // Last target position array - [0, 0, 0], // Last target velocity [0, 0, 0] // Last line of sight ], _navigationGain // navigation gain of missile. Set in the navigation onFired function diff --git a/addons/missileguidance/functions/fnc_seekerType_ARH.sqf b/addons/missileguidance/functions/fnc_seekerType_ARH.sqf index c1bf048ee1..eb21860069 100644 --- a/addons/missileguidance/functions/fnc_seekerType_ARH.sqf +++ b/addons/missileguidance/functions/fnc_seekerType_ARH.sqf @@ -16,7 +16,7 @@ * Public: No */ params ["", "_args", "_seekerStateParams"]; -_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams"]; +_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams", "_targetData"]; _firedEH params ["_shooter","","","","","","_projectile"]; _launchParams params ["_target","","","",""]; _seekerParams params ["_seekerAngle", "", "_seekerMaxRange"]; @@ -116,8 +116,14 @@ if !(isNull _target) then { _seekerStateParams set [7, velocity _target]; _seekerStateParams set [8, CBA_missionTime]; _seekerStateParams set [9, false]; + + _targetData set [1, _projectile distance _target]; + _targetData set [2, velocity _target]; + _targetData set [3, 0]; // todo: acceleration }; +_targetData set [0, _projectile vectorFromTo _expectedTargetPos]; + _seekerStateParams set [3, _expectedTargetPos]; _launchParams set [0, _target]; _expectedTargetPos diff --git a/addons/missileguidance/functions/fnc_seekerType_Optic.sqf b/addons/missileguidance/functions/fnc_seekerType_Optic.sqf index f61e799565..d473cdc021 100644 --- a/addons/missileguidance/functions/fnc_seekerType_Optic.sqf +++ b/addons/missileguidance/functions/fnc_seekerType_Optic.sqf @@ -17,7 +17,7 @@ */ params ["", "_args"]; -_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams"]; +_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams", "_targetData"]; _firedEH params ["","","","","","","_projectile"]; _launchParams params ["", "_targetParams"]; _targetParams params ["_target"]; @@ -40,14 +40,14 @@ TRACE_2("", _angleOkay, _losOkay); if (!_angleOkay || !_losOkay) exitWith {[0,0,0]}; TRACE_2("", _target, _foundTargetPos); -// @TODO: Configurable lead for seekers private _projectileSpeed = (vectorMagnitude velocity _projectile); private _distanceToTarget = (getPosASL _projectile) vectorDistance _foundTargetPos; private _eta = _distanceToTarget / _projectileSpeed; -private _adjustDistance = (velocity _target) vectorMultiply _eta; -TRACE_3("leading target",_distanceToTarget,_eta,_adjustDistance); -//_foundTargetPos = _foundTargetPos vectorAdd _adjustDistance; +_targetData set [0, (getPosASL _projectile) vectorFromTo _foundTargetPos]; +_targetData set [1, _distanceToTarget]; +_targetData set [2, velocity _target]; +_targetData set [3, 0]; TRACE_2("return",_foundTargetPos,(aimPos _target) distance _foundTargetPos); _foundTargetPos; diff --git a/addons/missileguidance/functions/fnc_seekerType_SACLOS.sqf b/addons/missileguidance/functions/fnc_seekerType_SACLOS.sqf index 2d0a1e9170..a1e5fc49ac 100644 --- a/addons/missileguidance/functions/fnc_seekerType_SACLOS.sqf +++ b/addons/missileguidance/functions/fnc_seekerType_SACLOS.sqf @@ -16,7 +16,7 @@ * Public: No */ params ["", "_args"]; -_args params ["_firedEH", "", "", "_seekerParams", "_stateParams"]; +_args params ["_firedEH", "", "", "_seekerParams", "_stateParams", "_targetData"]; _firedEH params ["_shooter","_weapon","","","","","_projectile"]; _seekerParams params ["_seekerAngle"]; _stateParams params ["", "_seekerStateParams"]; @@ -58,5 +58,7 @@ if ((_testDotProduct < (cos _seekerAngle)) || {_testIntersections isNotEqualTo [ [0, 0, 0] }; +_targetData set [0, _lookDirection]; + _shooterPos vectorAdd (_lookDirection vectorMultiply _distanceToProj); diff --git a/addons/missileguidance/functions/fnc_seekerType_SALH.sqf b/addons/missileguidance/functions/fnc_seekerType_SALH.sqf index f08aeac9f9..dadfb591a5 100644 --- a/addons/missileguidance/functions/fnc_seekerType_SALH.sqf +++ b/addons/missileguidance/functions/fnc_seekerType_SALH.sqf @@ -19,7 +19,7 @@ #define MAX_AVERAGES 15 params ["", "_args"]; -_args params ["_firedEH", "_launchParams", "", "_seekerParams"]; +_args params ["_firedEH", "_launchParams", "", "_seekerParams", "", "_targetData"]; _firedEH params ["","","","","","","_projectile"]; _launchParams params ["","","","","","_laserParams"]; _seekerParams params ["_seekerAngle", "", "_seekerMaxRange", "", ["_lastPositions", []], ["_lastPositionIndex", 0]]; @@ -52,6 +52,11 @@ if (MAX_AVERAGES == count _lastPositions) then { _positionSum = _positionSum vectorMultiply (1 / count _lastPositions); }; +_targetData set [0, (getPosASL _projectile) vectorFromTo _positionSum]; +_targetData set [1, 0]; +_targetData set [2, 0]; +_targetData set [3, 0]; + TRACE_3("laser target found",_foundTargetPos,_positionSum,count _lastPositions); _positionSum diff --git a/addons/missileguidance/todo.txt b/addons/missileguidance/todo.txt index 66a97bc70c..b55ed262ef 100644 --- a/addons/missileguidance/todo.txt +++ b/addons/missileguidance/todo.txt @@ -60,7 +60,7 @@ Navigation States: Navigation Types: X Augmented Pro-Nav - Zero Effort Miss + X Zero Effort Miss General To-Do: Add more weapons