From f2fff98ad05f34ec9af4c59454d6b96de3c2b672 Mon Sep 17 00:00:00 2001 From: Brandon Danyluk Date: Mon, 30 Dec 2019 11:29:08 -0700 Subject: [PATCH] Add AGM-114L Active Radar Homing Hellfire (#7337) * Create AGM-114L * If we lose LOS dont continue tracking magically Allow for datalinked targets to donate data to the missile. * Update documentation * RHS 2x hellfire compatability * Make ARH more realistic by not allowing to switch targets after firing * Fix filename. Change Hellfire attack profile to lead target. Switch to two LOS checks. We check two Line's of Sight to ensure that we are 100% gone from the target. A raw LOS check will be blocked by bushes and light trees while the checkVisibility wont while on the otherhand smoke will block a visiblity check but not a raw LOS check. We get best of both worlds with this. I changed the attack profile so that it will lead moving targets. This isnt needed with the laser version because the user will "lead" the target if needed, but with the radar scan we have velocity information so we might as well lead the target as much as possible * Change function calls to FUNC macro. Slightly change radar logic. Up poll frequency to 7hz Instead of the missile immediately going active when the shooter doesn't have radar, check if targets are in datalink. If they are, use the datalink to guide the missile instead of its internal radar. * Add logic for missiles launched without target If a missile is fired without a locked target, it will immediately go active and target the first thing its seeker picks up. This is an incredibly dangerous trait of active radar homing missiles and is so in this implementation. Be careful! * Change from `exitWith` to basic `then` Legacy code that never got changed. This is essentially what happened before * Update CfgMagazineWells.hpp Co-authored-by: PabstMirror --- addons/hellfire/CfgAmmo.hpp | 61 +++++++++ addons/hellfire/CfgMagazineWells.hpp | 1 + addons/hellfire/CfgMagazines.hpp | 39 ++++++ addons/hellfire/CfgWeapons.hpp | 23 ++++ .../hellfire/functions/fnc_attackProfile.sqf | 19 ++- addons/missileguidance/ACE_GuidanceConfig.hpp | 8 ++ addons/missileguidance/XEH_PREP.hpp | 2 + .../functions/fnc_ahr_onFired.sqf | 73 +++++++++++ .../functions/fnc_checkLos.sqf | 30 ++++- .../functions/fnc_seekerType_ARH.sqf | 119 ++++++++++++++++++ addons/missileguidance/script_component.hpp | 2 + docs/wiki/feature/hellfire.md | 20 ++- .../compat_rhs_usf3/CfgMagazineWells.hpp | 5 +- optionals/compat_rhs_usf3/CfgMagazines.hpp | 5 + 14 files changed, 395 insertions(+), 12 deletions(-) create mode 100644 addons/missileguidance/functions/fnc_ahr_onFired.sqf create mode 100644 addons/missileguidance/functions/fnc_seekerType_ARH.sqf diff --git a/addons/hellfire/CfgAmmo.hpp b/addons/hellfire/CfgAmmo.hpp index a5d7214292..e03a174a91 100644 --- a/addons/hellfire/CfgAmmo.hpp +++ b/addons/hellfire/CfgAmmo.hpp @@ -65,4 +65,65 @@ class CfgAmmo { enabled = 1; // Missile Guidance must be explicitly enabled }; }; + class ACE_Hellfire_AGM114L: ACE_Hellfire_AGM114K { + displayName = "AGM-114L"; + displayNameShort = "AGM-114L"; + description = "AGM-114L"; + descriptionShort = "AGM-114L"; + class ace_missileguidance: ace_missileguidance { + canVanillaLock = 1; + enabled = 1; // Missile Guidance must be explicitly enabled + seekLastTargetPos = 0; + defaultSeekerType = "ARH"; + seekerTypes[] = { "ARH" }; + defaultSeekerLockMode = "LOBL"; + seekerLockModes[] = { "LOBL" }; + + activeRadarEngageDistance = 1000; + seekerMaxRange = 2000; // distance that the hellfire internal radar can scan + }; + + // Vanilla lock system vars + weaponLockSystem = "8"; + airLock = 1; + lockType = 0; + maneuvrability = 0; // no maneuvrability so that default guidance doesnt work + + missileLockMaxDistance = 8000; + missileLockMinDistance = 250; + missileLockMaxSpeed = 600; + missileKeepLockedCone = 70; + + flightProfiles[] = {}; + class Components { + class SensorsManagerComponent { + class Components { + class MillimeterWaveRadar { + componentType = "ActiveRadarSensorComponent"; + class AirTarget { + minRange = 0; + maxRange = 8000; + objectDistanceLimitCoef = -1 + viewDistanceLimitCoef = -1; + }; + class GroundTarget { + minRange = 0; + maxRange = 8000; + objectDistanceLimitCoef = -1; + viewDistanceLimitCoef = -1; + }; + typeRecognitionDistance = 4000; + angleRangeHorizontal = 70; + angleRangeVertical = 70; + groundNoiseDistanceCoef = 0; // relevant to AA missiles - not really for this + maxGroundNoiseDistance = 250; + minSpeedThreshold = 0; + maxSpeedThreshold = 600; + nightRangeCoef = 1; + maxFogSeeThrough = 0.8; + }; + }; + }; + }; + }; }; diff --git a/addons/hellfire/CfgMagazineWells.hpp b/addons/hellfire/CfgMagazineWells.hpp index 5077d2faa6..17d6adee59 100644 --- a/addons/hellfire/CfgMagazineWells.hpp +++ b/addons/hellfire/CfgMagazineWells.hpp @@ -1,4 +1,5 @@ class CfgMagazineWells { class GVAR(K) {}; class GVAR(N) {}; + class GVAR(L) {}; }; diff --git a/addons/hellfire/CfgMagazines.hpp b/addons/hellfire/CfgMagazines.hpp index de63540a2a..51dba52661 100644 --- a/addons/hellfire/CfgMagazines.hpp +++ b/addons/hellfire/CfgMagazines.hpp @@ -84,4 +84,43 @@ class CfgMagazines { ammo = "ACE_Hellfire_AGM114N"; pylonWeapon = QGVAR(launcher_N); }; + + // Lima - tandem shaped charge HEAT (anti-tank) Fire and Forget Active Radar Homing + class 6Rnd_ACE_Hellfire_AGM114L: 6Rnd_ACE_Hellfire_AGM114K { // Old style vehicle magazine + count = 6; + ammo = "ACE_Hellfire_AGM114L"; + displayName = "AGM-114L [ACE]"; + displayNameShort = "AGM-114L"; + descriptionShort = "AGM-114L"; + }; + + // 1.70 pylon magazines: + class PylonMissile_1Rnd_ACE_Hellfire_AGM114L: PylonMissile_1Rnd_ACE_Hellfire_AGM114K { // Bare missle + displayName = "1x AGM-114L [ACE]"; + displayNameShort = "AGM-114L"; + descriptionShort = "AGM-114L"; + ammo = "ACE_Hellfire_AGM114L"; + pylonWeapon = QGVAR(launcher_L); + }; + class PylonRack_1Rnd_ACE_Hellfire_AGM114L: PylonRack_1Rnd_ACE_Hellfire_AGM114K { // 1x Launcher Support Rack + displayName = "1x AGM-114L [ACE]"; + displayNameShort = "AGM-114L"; + descriptionShort = "AGM-114L"; + ammo = "ACE_Hellfire_AGM114L"; + pylonWeapon = QGVAR(launcher_L); + }; + class PylonRack_3Rnd_ACE_Hellfire_AGM114L: PylonRack_3Rnd_ACE_Hellfire_AGM114K { // 3x Launcher Support Rack + displayName = "3x AGM-114L [ACE]"; + displayNameShort = "AGM-114L"; + descriptionShort = "AGM-114L"; + ammo = "ACE_Hellfire_AGM114L"; + pylonWeapon = QGVAR(launcher_L); + }; + class PylonRack_4Rnd_ACE_Hellfire_AGM114L: PylonRack_4Rnd_ACE_Hellfire_AGM114K { // 4x Launcher Support Rack + displayName = "4x AGM-114L [ACE]"; + displayNameShort = "AGM-114L"; + descriptionShort = "AGM-114L"; + ammo = "ACE_Hellfire_AGM114L"; + pylonWeapon = QGVAR(launcher_L); + }; }; diff --git a/addons/hellfire/CfgWeapons.hpp b/addons/hellfire/CfgWeapons.hpp index 5806ab5fbe..a09c642696 100644 --- a/addons/hellfire/CfgWeapons.hpp +++ b/addons/hellfire/CfgWeapons.hpp @@ -1,5 +1,6 @@ class CfgWeapons { class RocketPods; + class MissileLauncher; class GVAR(launcher): RocketPods { displayName = "AGM-114K Hellfire II"; GVAR(enabled) = 1; // handle adding interactions and adding Laser Designator @@ -29,4 +30,26 @@ class CfgWeapons { magazines[] = {"6Rnd_ACE_Hellfire_AGM114N", "PylonMissile_1Rnd_ACE_Hellfire_AGM114N", "PylonRack_1Rnd_ACE_Hellfire_AGM114N", "PylonRack_3Rnd_ACE_Hellfire_AGM114N", "PylonRack_4Rnd_ACE_Hellfire_AGM114N"}; magazineWell[] += {QGVAR(N)}; }; + class GVAR(launcher_L): GVAR(launcher) { + displayName = "AGM-114L Hellfire ""Longbow"""; + magazines[] = {"6Rnd_ACE_Hellfire_AGM114L", "PylonMissile_1Rnd_ACE_Hellfire_AGM114L", "PylonRack_1Rnd_ACE_Hellfire_AGM114L", "PylonRack_3Rnd_ACE_Hellfire_AGM114L", "PylonRack_4Rnd_ACE_Hellfire_AGM114L"}; + magazineWell[] += {QGVAR(L)}; + EGVAR(laser,showHud) = 1; // Just to show the attack profile + EGVAR(laser,canSelect) = 0; + class StandardSound { + begin1[] = {"A3\Sounds_F\weapons\Rockets\missile_1",1.12202,1.3,1000}; + soundBegin[] = {"begin1",1}; + soundsetshot[] = {"RocketsMedium_Shot_SoundSet"}; + }; + cursor = "EmptyCursor"; + cursorAim = "missile"; + showAimCursorInternal = 0; + + // vanilla weapon lock systems + weaponLockSystem = 8; + cmImmunity = 0.9; + lockAcquire = 0; + weaponLockDelay = 0.1; + canLock = 2; + }; }; diff --git a/addons/hellfire/functions/fnc_attackProfile.sqf b/addons/hellfire/functions/fnc_attackProfile.sqf index 8904d57978..7d4980a1b3 100644 --- a/addons/hellfire/functions/fnc_attackProfile.sqf +++ b/addons/hellfire/functions/fnc_attackProfile.sqf @@ -18,8 +18,10 @@ */ params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; -_args params ["_firedEH", "_launchParams"]; -_launchParams params ["","_targetLaunchParams"]; +_args params ["_firedEH", "_launchParams", "", "", "_stateParams"]; +_stateParams params ["", "_seekerStateParams"]; +_launchParams params ["","_targetLaunchParams","_seekerType"]; + _targetLaunchParams params ["", "", "_launchPos"]; _firedEH params ["","","","","","","_projectile"]; @@ -68,7 +70,7 @@ switch (_attackStage) do { 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)]; - + if ((_distanceToTarget2d < 500) || {(_currentHeightOverTarget atan2 _distanceToTarget2d) > 15}) then { // Wait until we can come down at a sharp angle _attackProfileStateParams set [0, STAGE_ATTACK_TERMINAL]; TRACE_2("New Stage: STAGE_ATTACK_TERMINAL",_distanceToTarget2d,_currentHeightOverTarget); @@ -80,5 +82,16 @@ switch (_attackStage) do { }; }; +// 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); + }; +}; + // TRACE_1("Adjusted target position", _returnTargetPos); _returnTargetPos; diff --git a/addons/missileguidance/ACE_GuidanceConfig.hpp b/addons/missileguidance/ACE_GuidanceConfig.hpp index d3c9a8a999..8e3324b09d 100644 --- a/addons/missileguidance/ACE_GuidanceConfig.hpp +++ b/addons/missileguidance/ACE_GuidanceConfig.hpp @@ -82,4 +82,12 @@ class GVAR(SeekerTypes) { functionName = QFUNC(seekerType_SACLOS); onFired = QFUNC(SACLOS_onFired); }; + class ARH { + name = ""; + visualName = ""; + description = ""; + + functionName = QFUNC(seekerType_ARH); + onFired = QFUNC(ahr_onFired); + }; }; diff --git a/addons/missileguidance/XEH_PREP.hpp b/addons/missileguidance/XEH_PREP.hpp index 2580831e84..075f2f03c5 100644 --- a/addons/missileguidance/XEH_PREP.hpp +++ b/addons/missileguidance/XEH_PREP.hpp @@ -33,9 +33,11 @@ PREP(attackProfile_JAV_TOP); PREP(seekerType_SALH); PREP(seekerType_Optic); PREP(seekerType_SACLOS); +PREP(seekerType_ARH); // Attack Profiles OnFired PREP(wire_onFired); // Seeker OnFired PREP(SACLOS_onFired); +PREP(ahr_onFired); diff --git a/addons/missileguidance/functions/fnc_ahr_onFired.sqf b/addons/missileguidance/functions/fnc_ahr_onFired.sqf new file mode 100644 index 0000000000..331484f4a2 --- /dev/null +++ b/addons/missileguidance/functions/fnc_ahr_onFired.sqf @@ -0,0 +1,73 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Sets up Active Radar state arrays (called from missileGuidance's onFired). + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_ahr_onFired + * + * Public: No + */ +params ["_firedEH", "_launchParams", "", "", "_stateParams"]; +_firedEH params ["_shooter","","","","","","_projectile"]; +_stateParams params ["", "_seekerStateParams"]; +_launchParams params ["","_targetLaunchParams"]; +_targetLaunchParams params ["_target"]; + +_target = missileTarget _projectile; +if (isNull _target && isVehicleRadarOn vehicle _shooter) then { + _target = cursorTarget; +}; +if !(_target isKindOf "AllVehicles") then { + _target = nil; +}; +_launchParams set [0, _target]; +_projectile setMissileTarget objNull; // to emulate a no launch warning + +private _projectileConfig = [_projectile] call CBA_fnc_getObjectConfig; +private _config = _projectileConfig >> "ace_missileguidance"; + +private _isActive = false; +private _activeRadarDistance = [_config >> "activeRadarEngageDistance", "NUMBER", 500] call CBA_fnc_getConfigEntry; +private _projectileThrust = [_projectileConfig >> "thrust", "NUMBER", 0] call CBA_fnc_getConfigEntry; +private _projectileThrustTime = [_projectileConfig >> "thrustTime", "NUMBER", 0] call CBA_fnc_getConfigEntry; + +private _velocityAtImpact = _projectileThrust * _projectileThrustTime; +private _timeToActive = 0; +if (!isNil "_target" && _velocityAtImpact > 0) then { + private _distanceUntilActive = (((getPosASL _shooter) vectorDistance (getPosASL _target)) - _activeRadarDistance); + _timeToActive = 0 max (_distanceUntilActive / _velocityAtImpact); +}; + +if (isNil "_target") then { + _timeToActive = 0; + _isActive = true; + _target = objNull; +}; + +private _shooterHasActiveRadar = { + if ("ActiveRadarSensorComponent" in _x) exitWith { true }; + false +} forEach listVehicleSensors vehicle _shooter; + +if !(isVehicleRadarOn vehicle _shooter) then { + _isActive = true; +}; + +_seekerStateParams set [0, _isActive]; +_seekerStateParams set [1, _activeRadarDistance]; +_seekerStateParams set [2, CBA_missionTime + _timeToActive]; +_seekerStateParams set [3, getPosASL _target]; +_seekerStateParams set [4, CBA_missionTime]; +_seekerStateParams set [5, _shooterHasActiveRadar]; +_seekerStateParams set [6, false]; +_seekerStateParams set [7, [0, 0, 0]]; +_seekerStateParams set [8, CBA_missionTime]; +_seekerStateParams set [9, isNull _target]; + diff --git a/addons/missileguidance/functions/fnc_checkLos.sqf b/addons/missileguidance/functions/fnc_checkLos.sqf index edc8b5ab19..f813c5a4e6 100644 --- a/addons/missileguidance/functions/fnc_checkLos.sqf +++ b/addons/missileguidance/functions/fnc_checkLos.sqf @@ -6,6 +6,7 @@ * Arguments: * 0: Seeker * 1: Target + * 2: Whether or not to use checkVisibility to test for LOS * * Return Value: * Has LOS @@ -16,7 +17,30 @@ * Public: No */ -params ["_seeker", "_target"]; +params ["_seeker", "_target", ["_checkVisibilityTest", true]]; + +// Boolean checkVisibilityTest so that if the seeker type is one that ignores smoke we revert back to raw LOS checking. +if (_checkVisibilityTest) exitWith { + private _visibility = [_seeker, "VIEW", _target] checkVisibility [getPosASL _seeker, aimPos _target]; + _visibility > 0.001 +}; +if ((isNil "_seeker") || {isNil "_target"}) exitWith { + ERROR_2("nil",_seeker,_target); + false +}; + +private _targetPos = getPosASL _target; +private _targetAimPos = aimPos _target; +private _seekerPos = getPosASL _seeker; +private _return = true; + +if (!((terrainIntersectASL [_seekerPos, _targetPos]) && {terrainIntersectASL [_seekerPos, _targetAimPos]})) then { + if (lineIntersects [_seekerPos, _targetPos, _seeker, _target]) then { + _return = false; + }; +} else { + _return = false; +}; + +_return -private _visibility = [_seeker, "VIEW", _target] checkVisibility [getPosASL _seeker, aimPos _target]; -_visibility > 0.001 diff --git a/addons/missileguidance/functions/fnc_seekerType_ARH.sqf b/addons/missileguidance/functions/fnc_seekerType_ARH.sqf new file mode 100644 index 0000000000..4f098f6cae --- /dev/null +++ b/addons/missileguidance/functions/fnc_seekerType_ARH.sqf @@ -0,0 +1,119 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Active Radar Homing seeker + * + * Arguments: + * 1: Guidance Arg Array + * 2: Seeker State + * + * Return Value: + * Seeker Pos + * + * Example: + * [] call call ace_missileguidance_fnc_seekerType_ARH; + * + * Public: No + */ +params ["", "_args", "_seekerStateParams"]; +_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams"]; +_firedEH params ["_shooter","","","","","","_projectile"]; +_launchParams params ["_target","","","",""]; +_seekerParams params ["_seekerAngle", "", "_seekerMaxRange"]; +_seekerStateParams params ["_isActive", "_activeRadarEngageDistance", "_timeWhenActive", "_expectedTargetPos", "_lastTargetPollTime", "_shooterHasRadar", "_wasActive", "_lastKnownVelocity", "_lastTimeSeen", "_doesntHaveTarget"]; + +if (_isActive || { CBA_missionTime >= _timeWhenActive }) then { + if !(_isActive) then { + _seekerStateParams set [0, true]; + }; + if !(_wasActive) then { + _seekerStateParams set [6, true]; + TRACE_1("Missile Pitbull"); + }; + // Internal radar homing + // For performance reasons only poll for target every so often instead of each frame + if ((_lastTargetPollTime + ACTIVE_RADAR_POLL_FREQUENCY) - CBA_missionTime < 0) then { + private _searchPos = _expectedTargetPos; + if (_searchPos isEqualTo [0, 0, 0] || { _doesntHaveTarget }) then { + _seekerStateParams set [9, true]; + // no target pos - shot without lock. Have the missile's radar search infront of it on the ground + _searchPos = (getPosASL _projectile) vectorAdd (_projectile vectorModelToWorld [0, _seekerMaxRange, -((getPos _projectile)#2)]); + }; + + _target = objNull; + _lastTargetPollTime = CBA_missionTime; + _seekerStateParams set [4, _lastTargetPollTime]; + private _distanceToExpectedTarget = _seekerMaxRange min ((getPosASL _projectile) vectorDistance _searchPos); + + // Simulate how much the seeker can see at the ground + private _projDir = vectorDir _projectile; + private _projYaw = getDir _projectile; + private _rotatedYaw = (+(_projDir select 0) * sin _projYaw) + (+(_projDir select 1) * cos _projYaw); + if (_rotatedYaw isEqualTo 0) then { _rotatedYaw = 0.001 }; + private _projPitch = atan ((_projDir select 2) / _rotatedYaw); + private _a1 = abs _projPitch; + private _a2 = 180 - ((_seekerAngle / 2) + _a1); + private _seekerBaseRadiusAtGround = ACTIVE_RADAR_MINIMUM_SCAN_AREA max (_distanceToExpectedTarget / sin(_a2) * sin(_seekerAngle / 2)); + private _seekerBaseRadiusAdjusted = linearConversion [0, _seekerBaseRadiusAtGround, (CBA_missionTime - _lastTimeSeen) * vectorMagnitude _lastKnownVelocity, ACTIVE_RADAR_MINIMUM_SCAN_AREA, _seekerBaseRadiusAtGround, false]; + if (_doesntHaveTarget) then { + _seekerBaseRadiusAdjusted = _seekerBaseRadiusAtGround; + }; + // Look in front of seeker for any targets + private _nearestObjects = nearestObjects [_searchPos, ["Air", "LandVehicle", "Ship"], _seekerBaseRadiusAdjusted, false]; + + _nearestObjects = _nearestObjects apply { + // I check both Line of Sight versions to make sure that a single bush doesnt make the target lock dissapear but at the same time ensure that this can see through smoke. Should work 80% of the time + if ([_projectile, getPosASL _x, _seekerAngle] call FUNC(checkSeekerAngle) && { ([_projectile, _x, true] call FUNC(checkLOS)) || { ([_projectile, _x, false] call FUNC(checkLOS)) } }) then { + _x + } else { + objNull + }; + }; + _nearestObjects = _nearestObjects select { !isNull _x }; + + // Select closest object to the expected position to be the current radar target + if ((count _nearestObjects) <= 0) exitWith { + _projectile setMissileTarget objNull; + _searchPos + }; + private _closestDistance = _seekerBaseRadiusAtGround; + { + if ((_x distance2d _searchPos) < _closestDistance) then { + _closestDistance = _x distance2d _searchPos; + _target = _x; + }; + } forEach _nearestObjects; + _expectedTargetPos = _searchPos; + }; + + _projectile setMissileTarget _target; +} else { + #ifdef DRAW_GUIDANCE_INFO + _seekerTypeName = "AHR - EXT"; + #endif + // External radar homing + // if the target is in the remote targets for the side, whoever the donor is will "datalink" the target for the hellfire. + private _remoteTargets = listRemoteTargets side _shooter; + if ((_remoteTargets findIf { (_target in _x) && (_x#1 > 0) }) < 0) then { + // I check both Line of Sight versions to make sure that a single bush doesnt make the target lock dissapear but at the same time ensure that this can see through smoke. Should work 80% of the time + if (!_shooterHasRadar || { !isVehicleRadarOn vehicle _shooter } || { !alive vehicle _shooter } || { !([vehicle _shooter, _target, true] call FUNC(checkLOS)) && { !([vehicle _shooter, _target, false] call FUNC(checkLOS)) } }) then { + _seekerStateParams set [0, true]; + _target = objNull; // set up state for active guidance + }; + }; +}; + +if !(isNull _target) then { + private _centerOfObject = getCenterOfMass _target; + private _targetAdjustedPos = _target modelToWorldWorld _centerOfObject; + _expectedTargetPos = _targetAdjustedPos; + + _seekerStateParams set [3, _expectedTargetPos]; + _seekerStateParams set [7, velocity _target]; + _seekerStateParams set [8, CBA_missionTime]; + _seekerStateParams set [9, false]; +}; + +_launchParams set [0, _target]; +_expectedTargetPos + diff --git a/addons/missileguidance/script_component.hpp b/addons/missileguidance/script_component.hpp index 1fd8d81756..2b43be42f3 100644 --- a/addons/missileguidance/script_component.hpp +++ b/addons/missileguidance/script_component.hpp @@ -26,4 +26,6 @@ #define DEFAULT_CORRECTION_DISTANCE 2 #define DEFAULT_LEAD_DISTANCE 5 +#define ACTIVE_RADAR_POLL_FREQUENCY (1 / 7) +#define ACTIVE_RADAR_MINIMUM_SCAN_AREA 30 diff --git a/docs/wiki/feature/hellfire.md b/docs/wiki/feature/hellfire.md index 0f8376db20..c2f4dd198a 100644 --- a/docs/wiki/feature/hellfire.md +++ b/docs/wiki/feature/hellfire.md @@ -14,11 +14,14 @@ version: ## 1. Overview -### 1.1 Guidance -Hellfire missile is a semi-active laser guided weapon. -It requires an observer (either the launch platform or an external source) to provide laser designation. +### 1.1 AGM-114K/N Guidance +The AGM-114K/N Hellfire is a semi-active laser guided weapon. It requires an observer (either the launch platform or an external source) to provide laser designation. -### 1.2 Attack profiles +### 1.2 AGM-114L Guidance +The AGM-114L Hellfire is an active-radar homing guided weapon. It is fire and forget as long as you lock a target initially. This does not require an external laser designation +The missile uses an external radar source to guide the missile towards the target. If this radar lock is dropped or if it gets within range of the target, it switches to an internal radar to guide itself for the terminal phase. + +### 1.3 Attack profiles Missile does not need line of sight to target when fired and can Lock-On-After-Launch (can also delay lasing target). This and the attack profile used will effect missile's flight and max altitude. - LOBL: Lock-On-Before-Launch, standard top attack. @@ -26,12 +29,19 @@ This and the attack profile used will effect missile's flight and max altitude. - LOAL-LOW: Missile immediately gains ~90m altitude. - LOAL-HI: Missile immediately gains ~300m altitude. -## 2. Usage +## 2.1 AGM-114K/N Usage - Switching to the hellfire weapon will show additional information about the weapon in weapon status display. - Shows: lock mode, laser code and a laser receiver indicator. E.G. `LOAL-DIR CODE: 1111` - Laser receiver indicator turns red when it detects a laser pulse set the the current code. - Cycle attack profiles with vehicle's ACE3 Interaction Menu or with the missile guidance "Cycle Fire Mode" keybind (default: Ctrl + Tab) +## 2.2 AGM-114L Usage +- Switching to the hellfire weapon will show additional information about the weapon in weapon status display. +- Shows: lock mode. E.G. `LOAL-HI` +- Cycle attack profiles with vehicle's ACE3 Interaction Menu or with the missile guidance "Cycle Fire Mode" keybind (default: Ctrl + Tab) +- Lock onto a target using the default ARMA targeting (default: T) +- Once you fire the missile you can either stay locked on or abandon the lock and let the missile guide itself + ## 3 Adding to vehicles - Easiest way to add is via the 1.70 Pylons system. - Hellfires can also be added to other vehicles via config or script. diff --git a/optionals/compat_rhs_usf3/CfgMagazineWells.hpp b/optionals/compat_rhs_usf3/CfgMagazineWells.hpp index 7ee767c4a9..a5d8f8c58d 100644 --- a/optionals/compat_rhs_usf3/CfgMagazineWells.hpp +++ b/optionals/compat_rhs_usf3/CfgMagazineWells.hpp @@ -3,6 +3,9 @@ class CfgMagazineWells { ADDON[] = {QGVAR(pylon_mag_2rnd_hellfire_k)}; }; class ace_hellfire_N { - ADDON[] = {GVAR(pylon_mag_2rnd_hellfire_n)}; + ADDON[] = {QGVAR(pylon_mag_2rnd_hellfire_n)}; + }; + class ace_hellfire_L { + ADDON[] = {QGVAR(pylon_mag_2rnd_hellfire_L)}; }; }; diff --git a/optionals/compat_rhs_usf3/CfgMagazines.hpp b/optionals/compat_rhs_usf3/CfgMagazines.hpp index 61d6493079..2dd486d3eb 100644 --- a/optionals/compat_rhs_usf3/CfgMagazines.hpp +++ b/optionals/compat_rhs_usf3/CfgMagazines.hpp @@ -50,6 +50,11 @@ class cfgMagazines { pylonWeapon = "ace_hellfire_launcher_N"; ammo = "ACE_Hellfire_AGM114N"; }; + class GVAR(pylon_mag_2rnd_hellfire_l): rhs_mag_AGM114K_2 { + displayName = "2x AGM-114L [ACE]"; + pylonWeapon = "ace_hellfire_launcher_L"; + ammo = "ACE_Hellfire_AGM114L"; + }; class rhsusf_m112_mag: CA_Magazine { ace_explosives_DelayTime = 1;