mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Update EW Script and refine logic (#555)
This commit is contained in:
parent
756602e682
commit
d2aa615133
@ -13,12 +13,16 @@
|
|||||||
* **[Modding]** Add Military Aircraft Mod 1.7.2 (See VSN Discord)
|
* **[Modding]** Add Military Aircraft Mod 1.7.2 (See VSN Discord)
|
||||||
* **[Payload Editor]** Add Sniper POD
|
* **[Payload Editor]** Add Sniper POD
|
||||||
* **[Modding]** Update SU-30 mod to v2.8.03 Beta + CWS 3.70
|
* **[Modding]** Update SU-30 mod to v2.8.03 Beta + CWS 3.70
|
||||||
|
* **[Plugins]** EW Script - DEAD added to applicable flight types.
|
||||||
|
* **[Plugins]** EW Script - Offensive Jamming restricted to aircraft with ALQ99/249 pods, or "has_built_in_jamming: true" in aircarft yaml (AI and Player)
|
||||||
|
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
* **[Flight Plans]** Fixed a bug when a package was created with only escort flights
|
* **[Flight Plans]** Fixed a bug when a package was created with only escort flights
|
||||||
* **[Flight Plans]** Added AntiShipStrike as a fallback task for OCA/Aircraft to fix a bug where the S-3B could not do OCA/Aircraft
|
* **[Flight Plans]** Added AntiShipStrike as a fallback task for OCA/Aircraft to fix a bug where the S-3B could not do OCA/Aircraft
|
||||||
* **[Squadrons]** Fixed a bug where loading an air wing config would not properly load all squadrons
|
* **[Squadrons]** Fixed a bug where loading an air wing config would not properly load all squadrons
|
||||||
* **[Flight Plans]** Fixed a bug where SEAD flights would fire one ARM and RTB
|
* **[Flight Plans]** Fixed a bug where SEAD flights would fire one ARM and RTB
|
||||||
|
* **[Plugins]** EW Script - Fix radar detection routine.
|
||||||
|
|
||||||
# Retribution v1.4.1 (hotfix)
|
# Retribution v1.4.1 (hotfix)
|
||||||
|
|
||||||
|
|||||||
@ -123,6 +123,7 @@ class WeaponType(Enum):
|
|||||||
TGP = "TGP"
|
TGP = "TGP"
|
||||||
DECOY = "DECOY"
|
DECOY = "DECOY"
|
||||||
JAMMER = "JAMMER"
|
JAMMER = "JAMMER"
|
||||||
|
OFFENSIVE_JAMMER = "OFFENSIVE_JAMMER"
|
||||||
UNKNOWN = "unknown"
|
UNKNOWN = "unknown"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -233,10 +233,14 @@ class AircraftType(UnitType[Type[FlyingType]]):
|
|||||||
# when no TGP is mounted on any station.
|
# when no TGP is mounted on any station.
|
||||||
has_built_in_target_pod: bool
|
has_built_in_target_pod: bool
|
||||||
|
|
||||||
# indicates if the aircraft has a built-in jammer allowing EWJamming to be used
|
# indicates if the aircraft has a built-in jammer allowing Defensive EWJamming to be used
|
||||||
# without the need for a jamming pod
|
# without the need for a jamming pod
|
||||||
has_built_in_ecm: bool
|
has_built_in_ecm: bool
|
||||||
|
|
||||||
|
# Indicates if the aircraft has a built in jammer allowing Offensive EWJamming to be used
|
||||||
|
# without the need for a jamming pod
|
||||||
|
has_built_in_jamming: bool
|
||||||
|
|
||||||
task_priorities: dict[FlightType, int]
|
task_priorities: dict[FlightType, int]
|
||||||
laser_code_configs: list[LaserCodeConfig]
|
laser_code_configs: list[LaserCodeConfig]
|
||||||
|
|
||||||
@ -600,6 +604,7 @@ class AircraftType(UnitType[Type[FlyingType]]):
|
|||||||
task_priorities=task_priorities,
|
task_priorities=task_priorities,
|
||||||
has_built_in_target_pod=data.get("has_built_in_target_pod", False),
|
has_built_in_target_pod=data.get("has_built_in_target_pod", False),
|
||||||
has_built_in_ecm=data.get("has_built_in_ecm", False),
|
has_built_in_ecm=data.get("has_built_in_ecm", False),
|
||||||
|
has_built_in_jamming=data.get("has_built_in_jamming", False),
|
||||||
laser_code_configs=[
|
laser_code_configs=[
|
||||||
LaserCodeConfig.from_yaml(d) for d in data.get("laser_codes", [])
|
LaserCodeConfig.from_yaml(d) for d in data.get("laser_codes", [])
|
||||||
],
|
],
|
||||||
|
|||||||
@ -366,7 +366,9 @@ class AircraftGenerator:
|
|||||||
and (
|
and (
|
||||||
not self.need_ecm
|
not self.need_ecm
|
||||||
or flight.any_member_has_weapon_of_type(WeaponType.JAMMER)
|
or flight.any_member_has_weapon_of_type(WeaponType.JAMMER)
|
||||||
|
or flight.any_member_has_weapon_of_type(WeaponType.OFFENSIVE_JAMMER)
|
||||||
or flight.squadron.aircraft.has_built_in_ecm
|
or flight.squadron.aircraft.has_built_in_ecm
|
||||||
|
or flight.squadron.aircraft.has_built_in_jamming
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
self.ewrj_package_dict[id(flight.package)].append(group)
|
self.ewrj_package_dict[id(flight.package)].append(group)
|
||||||
|
|||||||
@ -189,8 +189,17 @@ class FlightGroupConfigurator:
|
|||||||
return
|
return
|
||||||
# Check if ecm_required option is enabled
|
# Check if ecm_required option is enabled
|
||||||
jammer_required = settings.plugin_option("ewrj.ecm_required")
|
jammer_required = settings.plugin_option("ewrj.ecm_required")
|
||||||
has_jammer = member.loadout.has_weapon_of_type(WeaponType.JAMMER)
|
offensive_jammer = member.loadout.has_weapon_of_type(
|
||||||
if jammer_required and not has_jammer:
|
WeaponType.OFFENSIVE_JAMMER
|
||||||
|
)
|
||||||
|
offensive_inbuilt = self.flight.squadron.aircraft.has_built_in_jamming
|
||||||
|
has_jammer = (
|
||||||
|
member.loadout.has_weapon_of_type(WeaponType.JAMMER) or offensive_jammer
|
||||||
|
)
|
||||||
|
built_in_jammer = (
|
||||||
|
self.flight.squadron.aircraft.has_built_in_ecm or offensive_inbuilt
|
||||||
|
)
|
||||||
|
if jammer_required and not (has_jammer or built_in_jammer):
|
||||||
return
|
return
|
||||||
# Create the original ewrj_menu_trigger for player flight members
|
# Create the original ewrj_menu_trigger for player flight members
|
||||||
ewrj_menu_trigger = TriggerStart(comment=f"EWRJ-{unit.name}")
|
ewrj_menu_trigger = TriggerStart(comment=f"EWRJ-{unit.name}")
|
||||||
@ -199,6 +208,20 @@ class FlightGroupConfigurator:
|
|||||||
self.group.points[0].tasks[0] = OptReactOnThreat(
|
self.group.points[0].tasks[0] = OptReactOnThreat(
|
||||||
OptReactOnThreat.Values.PassiveDefense
|
OptReactOnThreat.Values.PassiveDefense
|
||||||
)
|
)
|
||||||
|
# Create LUA Flags for Offensive Jamming in EW Script for Player Flights
|
||||||
|
if not (offensive_jammer or offensive_inbuilt):
|
||||||
|
return
|
||||||
|
ewrj_offensive_trigger = TriggerStart(
|
||||||
|
comment=f"Offensive Jammer Flag {unit.name}"
|
||||||
|
)
|
||||||
|
ewrj_offensive_trigger.add_action(
|
||||||
|
DoScript(
|
||||||
|
String(
|
||||||
|
f'trigger.action.setUserFlag("offensive_jamming_{unit.name}", 1)'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.mission.triggerrules.triggers.append(ewrj_offensive_trigger)
|
||||||
|
|
||||||
def setup_radios(self) -> RadioFrequency:
|
def setup_radios(self) -> RadioFrequency:
|
||||||
freq = self.flight.frequency
|
freq = self.flight.frequency
|
||||||
|
|||||||
@ -60,6 +60,7 @@ class JoinPointBuilder(PydcsWaypointBuilder):
|
|||||||
FlightType.SEAD_SWEEP,
|
FlightType.SEAD_SWEEP,
|
||||||
FlightType.SEAD,
|
FlightType.SEAD,
|
||||||
FlightType.SEAD_ESCORT,
|
FlightType.SEAD_ESCORT,
|
||||||
|
FlightType.DEAD,
|
||||||
]:
|
]:
|
||||||
settings = self.flight.coalition.game.settings
|
settings = self.flight.coalition.game.settings
|
||||||
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
|
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
|
||||||
|
|||||||
@ -164,12 +164,17 @@ class PydcsWaypointBuilder:
|
|||||||
settings = self.flight.coalition.game.settings
|
settings = self.flight.coalition.game.settings
|
||||||
ecm_required = settings.plugin_option("ewrj.ecm_required")
|
ecm_required = settings.plugin_option("ewrj.ecm_required")
|
||||||
for unit, member in zip(self.group.units, self.flight.iter_members()):
|
for unit, member in zip(self.group.units, self.flight.iter_members()):
|
||||||
has_jammer = member.loadout.has_weapon_of_type(WeaponType.JAMMER)
|
has_jammer = member.loadout.has_weapon_of_type(
|
||||||
built_in_jammer = self.flight.squadron.aircraft.has_built_in_ecm
|
WeaponType.JAMMER
|
||||||
|
) or member.loadout.has_weapon_of_type(WeaponType.OFFENSIVE_JAMMER)
|
||||||
|
built_in_jammer = (
|
||||||
|
self.flight.squadron.aircraft.has_built_in_ecm
|
||||||
|
or self.flight.squadron.aircraft.has_built_in_jamming
|
||||||
|
)
|
||||||
if ecm_required and not (has_jammer or built_in_jammer):
|
if ecm_required and not (has_jammer or built_in_jammer):
|
||||||
continue
|
continue
|
||||||
if not member.is_player:
|
if not member.is_player:
|
||||||
script_content = f'{action}Djamming("{unit.name}")'
|
script_content = f'{action}IAdefjamming("{unit.name}")'
|
||||||
jamming_script = RunScript(script_content)
|
jamming_script = RunScript(script_content)
|
||||||
waypoint.tasks.append(jamming_script)
|
waypoint.tasks.append(jamming_script)
|
||||||
|
|
||||||
@ -178,8 +183,8 @@ class PydcsWaypointBuilder:
|
|||||||
settings = self.flight.coalition.game.settings
|
settings = self.flight.coalition.game.settings
|
||||||
ecm_required = settings.plugin_option("ewrj.ecm_required")
|
ecm_required = settings.plugin_option("ewrj.ecm_required")
|
||||||
for unit, member in zip(self.group.units, self.flight.iter_members()):
|
for unit, member in zip(self.group.units, self.flight.iter_members()):
|
||||||
has_jammer = member.loadout.has_weapon_of_type(WeaponType.JAMMER)
|
has_jammer = member.loadout.has_weapon_of_type(WeaponType.OFFENSIVE_JAMMER)
|
||||||
built_in_jammer = self.flight.squadron.aircraft.has_built_in_ecm
|
built_in_jammer = self.flight.squadron.aircraft.has_built_in_jamming
|
||||||
if ecm_required and not (has_jammer or built_in_jammer):
|
if ecm_required and not (has_jammer or built_in_jammer):
|
||||||
continue
|
continue
|
||||||
if not member.is_player:
|
if not member.is_player:
|
||||||
|
|||||||
@ -43,6 +43,7 @@ class RaceTrackBuilder(PydcsWaypointBuilder):
|
|||||||
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
|
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
|
||||||
if settings.plugins.get("ewrj") and ai_jammer:
|
if settings.plugins.get("ewrj") and ai_jammer:
|
||||||
self.defensive_jamming(waypoint, "start")
|
self.defensive_jamming(waypoint, "start")
|
||||||
|
self.offensive_jamming(waypoint, "start")
|
||||||
|
|
||||||
# NB: It's important that the engage task comes before the orbit task.
|
# NB: It's important that the engage task comes before the orbit task.
|
||||||
# Though they're on the same waypoint, if the orbit task comes first it
|
# Though they're on the same waypoint, if the orbit task comes first it
|
||||||
|
|||||||
@ -23,6 +23,7 @@ class RaceTrackEndBuilder(PydcsWaypointBuilder):
|
|||||||
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
|
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
|
||||||
if settings.plugins.get("ewrj") and ai_jammer:
|
if settings.plugins.get("ewrj") and ai_jammer:
|
||||||
self.defensive_jamming(waypoint, "stop")
|
self.defensive_jamming(waypoint, "stop")
|
||||||
|
self.offensive_jamming(waypoint, "stop")
|
||||||
|
|
||||||
def build(self) -> MovingPoint:
|
def build(self) -> MovingPoint:
|
||||||
waypoint = super().build()
|
waypoint = super().build()
|
||||||
|
|||||||
@ -47,6 +47,7 @@ class SplitPointBuilder(PydcsWaypointBuilder):
|
|||||||
FlightType.SEAD_SWEEP,
|
FlightType.SEAD_SWEEP,
|
||||||
FlightType.SEAD,
|
FlightType.SEAD,
|
||||||
FlightType.SEAD_ESCORT,
|
FlightType.SEAD_ESCORT,
|
||||||
|
FlightType.DEAD,
|
||||||
]:
|
]:
|
||||||
if self.flight.flight_type == FlightType.SEAD_ESCORT:
|
if self.flight.flight_type == FlightType.SEAD_ESCORT:
|
||||||
# Moved previous escort split tasks
|
# Moved previous escort split tasks
|
||||||
|
|||||||
@ -1057,6 +1057,7 @@ class PretenseAircraftGenerator:
|
|||||||
and (
|
and (
|
||||||
not self.need_ecm
|
not self.need_ecm
|
||||||
or flight.any_member_has_weapon_of_type(WeaponType.JAMMER)
|
or flight.any_member_has_weapon_of_type(WeaponType.JAMMER)
|
||||||
|
or flight.any_member_has_weapon_of_type(WeaponType.OFFENSIVE_JAMMER)
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
self.ewrj_package_dict[id(flight.package)].append(group)
|
self.ewrj_package_dict[id(flight.package)].append(group)
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
--EW Script 1.01
|
-- EW Script 2.02
|
||||||
|
-- Original script by ESA_Matador
|
||||||
|
-- Adapted for Retribution with fixes by Drexyl
|
||||||
|
--
|
||||||
-- DEFENSIVE JAMMING
|
-- DEFENSIVE JAMMING
|
||||||
-- We all know that DCS lacks an Electronic War (EW) enviroment… The ECM, are available only for individual aircraft. But in modern conflicts, since Vietnam, the Jammers, with aircrafts like, F4 Phantom, A6 Intruder, F18 Hornet, or AWACS... have been used to avoid enemy SAMs to shot down aircrafts.
|
-- We all know that DCS lacks an Electronic War (EW) enviroment… The ECM, are available only for individual aircraft. But in modern conflicts, since Vietnam, the Jammers, with aircrafts like, F4 Phantom, A6 Intruder, F18 Hornet, or AWACS... have been used to avoid enemy SAMs to shot down aircrafts.
|
||||||
-- What I did in this Script is to Emulate this EW (not simulate!!!). We need to use a little bit our imagination and to imagine, that some aircraft has Jamming Pods... with chaffs, ECMs or whatever. So i recommend that if you or any of your friends is flying as if he is carrying ECM pods... just put One or Two Mk82-84 to simulate that they are carrying this pod. And AVOID them to use them as weapons... (I would love if someone can model an AN/ANQ pod...
|
-- What I did in this Script is to Emulate this EW (not simulate!!!). We need to use a little bit our imagination and to imagine, that some aircraft has Jamming Pods... with chaffs, ECMs or whatever. So i recommend that if you or any of your friends is flying as if he is carrying ECM pods... just put One or Two Mk82-84 to simulate that they are carrying this pod. And AVOID them to use them as weapons... (I would love if someone can model an AN/ANQ pod...
|
||||||
@ -57,132 +60,146 @@ end
|
|||||||
|
|
||||||
---------------------------- LOOP TO SEE IF A SAM SHOULD BE SHUT OFF DEPENDING ON THE TARGET DETECTED, THE JAMMER AND THE SAM
|
---------------------------- LOOP TO SEE IF A SAM SHOULD BE SHUT OFF DEPENDING ON THE TARGET DETECTED, THE JAMMER AND THE SAM
|
||||||
function check(jammer, samunit)
|
function check(jammer, samunit)
|
||||||
-- trigger.action.outText(samunit.."Checking",1)
|
-- trigger.action.outText(samunit.."Checking",1)
|
||||||
|
|
||||||
|
--- New logic to replace unreliable getRadar() ---
|
||||||
|
|
||||||
local UnitObject = Unit.getByName(samunit)
|
local UnitObject = Unit.getByName(samunit)
|
||||||
if UnitObject ~= nil then
|
if UnitObject ~= nil then
|
||||||
local status, target = UnitObject:getRadar()
|
|
||||||
|
local status, target = false, nil
|
||||||
|
local controller = UnitObject:getController()
|
||||||
|
local detectedTargets = controller:getDetectedTargets()
|
||||||
|
|
||||||
|
for _, tgt in pairs(detectedTargets) do
|
||||||
|
if tgt.object and tgt.object:isExist() then
|
||||||
|
status = true
|
||||||
|
target = tgt.object
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Start of original script ---
|
||||||
|
|
||||||
-- trigger.action.outText(Unitobject,20)
|
-- trigger.action.outText(Unitobject,20)
|
||||||
-- if status == true then -- to see if the Radar is working
|
-- if status == true then -- to see if the Radar is working
|
||||||
if target ~= nil then -- to see if it is engaging
|
if target ~= nil then -- to see if it is engaging
|
||||||
local targetname = target:getName()
|
local targetname = target:getName()
|
||||||
-- trigger.action.outText(samunit.." Detecting "..targetname,2)
|
-- trigger.action.outText(samunit.." Detecting "..targetname,2)
|
||||||
-- trigger.action.outText(mist.utils.tableShow(jammerplanes),20)
|
-- trigger.action.outText(mist.utils.tableShow(jammerplanes),20)
|
||||||
|
-- trigger.action.outText("Target= "..target, "Jammer= "..jammer,10)
|
||||||
|
|
||||||
jammerobject = Unit.getByName(jammer)
|
jammerobject = Unit.getByName(jammer)
|
||||||
if jammerobject ~= nil then
|
if jammerobject ~= nil then
|
||||||
-- trigger.action.outText(jammer.." "..samunit,20)
|
-- trigger.action.outText(jammer.." "..samunit,20)
|
||||||
|
|
||||||
if isLOS(samunit, jammer)==true then
|
if isLOS(samunit, jammer)==true then
|
||||||
-- trigger.action.outText(jammer..'is LOS with '..samunit,20)
|
-- trigger.action.outText(jammer..'is LOS with '..samunit,20)
|
||||||
|
|
||||||
local distSamJammer = get3DDist(Unit.getPoint(Unit.getByName(samunit)), Unit.getPoint(Unit.getByName(jammer)))
|
local distSamJammer = get3DDist(Unit.getPoint(Unit.getByName(samunit)), Unit.getPoint(Unit.getByName(jammer)))
|
||||||
local distSamTarget = get3DDist(Unit.getPoint(Unit.getByName(samunit)), Unit.getPoint(Unit.getByName(targetname)))
|
local distSamTarget = get3DDist(Unit.getByName(samunit):getPoint(), Unit.getByName(targetname):getPoint())
|
||||||
local dice = math.random(0,100)
|
local dice = math.random(0,100)
|
||||||
local conditiondist = 100 * distSamTarget / distSamJammer
|
local conditiondist = 100 * distSamTarget / distSamJammer
|
||||||
-------------------------------------------- HEIGHT OF JAMMER
|
|
||||||
|
|
||||||
local Position_vec3 = Unit.getByName(jammer):getPoint()
|
-- HEIGHT OF JAMMER
|
||||||
local _elevation = land.getHeight({x = Position_vec3.x, y = Position_vec3.z})
|
|
||||||
local _height = Position_vec3.y - _elevation
|
|
||||||
|
|
||||||
|
|
||||||
local tPosition_vec3 = Unit.getByName(targetname):getPoint()
|
|
||||||
local t_elevation = land.getHeight({x = tPosition_vec3.x, y = tPosition_vec3.z})
|
|
||||||
local t_height = tPosition_vec3.y - t_elevation
|
|
||||||
local prob = dice + _height/1000 + (_height - t_height)/1000
|
|
||||||
-- trigger.action.outText("dice "..dice.."prob "..prob.."altjammer".._height.."alttarget"..t_height,20)
|
|
||||||
|
|
||||||
|
local Position_vec3 = Unit.getByName(jammer):getPoint()
|
||||||
-------------------------------------------- LOBE parameter
|
local _elevation = land.getHeight({x = Position_vec3.x, y = Position_vec3.z})
|
||||||
local SamPos = mist.utils.makeVec2(Unit.getByName(samunit):getPosition().p)-- tenemos un vector x e y
|
local _height = Position_vec3.y - _elevation
|
||||||
-- trigger.action.outText(mist.utils.tableShow(SamPos),20)
|
|
||||||
local JammerPos = mist.utils.makeVec2(Unit.getByName(jammer):getPosition().p)
|
|
||||||
-- trigger.action.outText(mist.utils.tableShow(JammerPos),20)
|
|
||||||
local TargetPos = mist.utils.makeVec2(Unit.getByName(targetname):getPosition().p)
|
|
||||||
-- trigger.action.outText(mist.utils.tableShow(TargetPos),20)
|
|
||||||
local AngleSamJammer = mist.utils.toDegree(mist.utils.getDir(mist.vec.sub(mist.utils.makeVec3GL(JammerPos),mist.utils.makeVec3GL(SamPos))))
|
|
||||||
-- trigger.action.outText(AngleSamJammer,20)
|
|
||||||
local AngleSamTarget = mist.utils.toDegree(mist.utils.getDir(mist.vec.sub(mist.utils.makeVec3GL(TargetPos),mist.utils.makeVec3GL(SamPos))))
|
|
||||||
-- trigger.action.outText(AngleSamTarget,20)
|
|
||||||
local offsetJamTar = smallestAngleDiff(AngleSamJammer, AngleSamTarget )
|
|
||||||
-- trigger.action.outText(offsetJamTar,20)
|
|
||||||
local offsetJamSam = smallestAngleDiff(AngleSamJammer, 180 )
|
|
||||||
-- trigger.action.outText("Jamm "..AngleSamJammer.."-Target ".. AngleSamTarget.."-Offjam ".. offsetJamSam.." -Offtar "..offsetJamTar,20)
|
|
||||||
|
|
||||||
local TargetandOffsetJamSam = smallestAngleDiff(AngleSamTarget, offsetJamSam )*2
|
|
||||||
if TargetandOffsetJamSam < 0 then
|
|
||||||
TargetandOffsetJamSam = -TargetandOffsetJamSam
|
|
||||||
|
|
||||||
end
|
|
||||||
-- trigger.action.outText(conditiondist.." relacion ".. prob.." probabilidad",20)
|
|
||||||
local anglecondition = 2/3 * distSamJammer/1000
|
|
||||||
-- trigger.action.outText(anglecondition.." target difference "..TargetandOffsetJamSam,20)
|
|
||||||
|
|
||||||
--------------------------------------------------- PITCH and BANK
|
local tPosition_vec3 = Unit.getByName(targetname):getPoint()
|
||||||
|
local t_elevation = land.getHeight({x = tPosition_vec3.x, y = tPosition_vec3.z})
|
||||||
|
local t_height = tPosition_vec3.y - t_elevation
|
||||||
|
local prob = dice + _height/1000 + (_height - t_height)/1000
|
||||||
|
-- trigger.action.outText("dice "..dice.."prob "..prob.."altjammer".._height.."alttarget"..t_height,20)
|
||||||
|
|
||||||
local bankr = mist.utils.toDegree(mist.getRoll(Unit.getByName(jammer)))
|
|
||||||
|
|
||||||
if bankr < 0 then
|
-- LOBE parameter
|
||||||
bankr = -bankr
|
local SamPos = mist.utils.makeVec2(Unit.getByName(samunit):getPosition().p)-- tenemos un vector x e y
|
||||||
end
|
-- trigger.action.outText(mist.utils.tableShow(SamPos),20)
|
||||||
bank = bankr - 30
|
local JammerPos = mist.utils.makeVec2(Unit.getByName(jammer):getPosition().p)
|
||||||
|
-- trigger.action.outText(mist.utils.tableShow(JammerPos),20)
|
||||||
|
local TargetPos = mist.utils.makeVec2(Unit.getByName(targetname):getPosition().p)
|
||||||
|
-- trigger.action.outText(mist.utils.tableShow(TargetPos),20)
|
||||||
|
local AngleSamJammer = mist.utils.toDegree(mist.utils.getDir(mist.vec.sub(mist.utils.makeVec3GL(JammerPos),mist.utils.makeVec3GL(SamPos))))
|
||||||
|
-- trigger.action.outText(AngleSamJammer,20)
|
||||||
|
local AngleSamTarget = mist.utils.toDegree(mist.utils.getDir(mist.vec.sub(mist.utils.makeVec3GL(TargetPos),mist.utils.makeVec3GL(SamPos))))
|
||||||
|
-- trigger.action.outText(AngleSamTarget,20)
|
||||||
|
local offsetJamTar = smallestAngleDiff(AngleSamJammer, AngleSamTarget )
|
||||||
|
-- trigger.action.outText(offsetJamTar,20)
|
||||||
|
local offsetJamSam = smallestAngleDiff(AngleSamJammer, 180 )
|
||||||
|
-- trigger.action.outText("Jamm "..AngleSamJammer.."-Target ".. AngleSamTarget.."-Offjam ".. offsetJamSam.." -Offtar "..offsetJamTar,20)
|
||||||
|
|
||||||
|
local TargetandOffsetJamSam = smallestAngleDiff(AngleSamTarget, offsetJamSam )*2
|
||||||
|
if TargetandOffsetJamSam < 0 then
|
||||||
|
TargetandOffsetJamSam = -TargetandOffsetJamSam
|
||||||
|
|
||||||
-- trigger.action.outText("real"..bankr.."tocado"..bank,20)
|
end
|
||||||
|
-- trigger.action.outText(conditiondist.." relacion ".. prob.." probabilidad",20)
|
||||||
local pitchr = mist.utils.toDegree(mist.getPitch(Unit.getByName(jammer)))
|
local anglecondition = 2/3 * distSamJammer/1000
|
||||||
if pitchr < 0 then
|
-- trigger.action.outText(anglecondition.." target difference "..TargetandOffsetJamSam,20)
|
||||||
pitchr = -pitch
|
|
||||||
end
|
|
||||||
pitch = pitchr - 30
|
|
||||||
|
|
||||||
-- trigger.action.outText("real"..bankr.."tocado"..bank,20)
|
|
||||||
|
|
||||||
local sPosition_vec3 = Unit.getByName(samunit):getPoint()
|
-- PITCH and BANK
|
||||||
-- trigger.action.outText(mist.utils.tableShow(sPosition_vec3),20)
|
local bankr = mist.utils.toDegree(mist.getRoll(Unit.getByName(jammer)))
|
||||||
local s_elevation = land.getHeight({x = sPosition_vec3.x, y = sPosition_vec3.z})
|
if bankr < 0 then
|
||||||
local s_height = sPosition_vec3.y - s_elevation
|
bankr = -bankr
|
||||||
|
end
|
||||||
|
bank = bankr - 30
|
||||||
|
|
||||||
|
-- trigger.action.outText("real"..bankr.."tocado"..bank,20)
|
||||||
|
|
||||||
|
local pitchr = mist.utils.toDegree(mist.getPitch(Unit.getByName(jammer)))
|
||||||
|
if pitchr < 0 then
|
||||||
|
pitchr = -pitchr
|
||||||
|
end
|
||||||
|
pitch = pitchr - 30
|
||||||
|
|
||||||
|
-- trigger.action.outText("real"..pitchr.."tocado"..pitch,20)
|
||||||
|
|
||||||
local cateto = _height - s_height
|
local sPosition_vec3 = Unit.getByName(samunit):getPoint()
|
||||||
-- trigger.action.outText("altura sam "..cateto,20)
|
-- trigger.action.outText(mist.utils.tableShow(sPosition_vec3),20)
|
||||||
local samunitposition = Unit.getByName(samunit):getPosition().p
|
local s_elevation = land.getHeight({x = sPosition_vec3.x, y = sPosition_vec3.z})
|
||||||
local jammerposition = Unit.getByName(jammer):getPosition().p
|
local s_height = sPosition_vec3.y - s_elevation
|
||||||
local _2DDistSamJammer = mist.utils.get2DDist(samunitposition, jammerposition)
|
|
||||||
local anglesamjam = mist.utils.toDegree(math.asin(cateto/_2DDistSamJammer))
|
local cateto = _height - s_height
|
||||||
-- trigger.action.outText("angulo is "..anglesamjam,20)
|
-- trigger.action.outText("altura sam "..cateto,20)
|
||||||
------------------------------------------------------------------------
|
local samunitposition = Unit.getByName(samunit):getPosition().p
|
||||||
local probsector1 = ((5/2)*conditiondist)+10
|
local jammerposition = Unit.getByName(jammer):getPosition().p
|
||||||
local probsector2 = (conditiondist+30)
|
local _2DDistSamJammer = mist.utils.get2DDist(samunitposition, jammerposition)
|
||||||
local probsector3 = ((conditiondist/3)+57)
|
local anglesamjam = mist.utils.toDegree(math.asin(cateto/_2DDistSamJammer))
|
||||||
if (conditiondist > 40.5)
|
-- trigger.action.outText("angulo is "..anglesamjam,20)
|
||||||
and (prob <= probsector3)
|
------------------------------------------------------------------------
|
||||||
and (anglecondition < TargetandOffsetJamSam)
|
local probsector1 = ((5/2)*conditiondist)+10
|
||||||
and anglesamjam >= bank
|
local probsector2 = (conditiondist+30)
|
||||||
and anglesamjam > pitch
|
local probsector3 = ((conditiondist/3)+57)
|
||||||
then
|
if (conditiondist > 40.5)
|
||||||
|
and (prob <= probsector3)
|
||||||
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector3.." "..dice,20)
|
and (anglecondition < TargetandOffsetJamSam)
|
||||||
mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
|
and anglesamjam >= bank
|
||||||
|
and anglesamjam > pitch
|
||||||
elseif ((conditiondist < 40.5) and (conditiondist > 13.33))
|
then
|
||||||
and (prob <= probsector2)
|
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector3.." "..dice,20)
|
||||||
and (anglecondition < TargetandOffsetJamSam)
|
mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
|
||||||
and anglesamjam >= bank
|
elseif ((conditiondist < 40.5) and (conditiondist > 13.33))
|
||||||
and anglesamjam > pitch
|
and (prob <= probsector2)
|
||||||
then
|
and (anglecondition < TargetandOffsetJamSam)
|
||||||
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector2.." "..dice,20)
|
and anglesamjam >= bank
|
||||||
mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
|
and anglesamjam > pitch
|
||||||
elseif (conditiondist < 13.33)
|
then
|
||||||
and (prob <= probsector1 )
|
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector2.." "..dice,20)
|
||||||
and (anglecondition < TargetandOffsetJamSam)
|
mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
|
||||||
and anglesamjam >= bank
|
elseif (conditiondist < 13.33)
|
||||||
and anglesamjam > pitch
|
and (prob <= probsector1 )
|
||||||
then
|
and (anglecondition < TargetandOffsetJamSam)
|
||||||
mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
|
and anglesamjam >= bank
|
||||||
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector1.." "..dice,20)
|
and anglesamjam > pitch
|
||||||
else
|
then
|
||||||
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25))
|
mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
|
||||||
-- trigger.action.outText("fuera de cobertura",20)
|
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector1.." "..dice,20)
|
||||||
end
|
else
|
||||||
|
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25))
|
||||||
|
-- trigger.action.outText("fuera de cobertura",20)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- trigger.action.outText(jammer..'NOT LOS with '..samunit,20)
|
-- trigger.action.outText(jammer..'NOT LOS with '..samunit,20)
|
||||||
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25))
|
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25))
|
||||||
@ -288,20 +305,53 @@ end
|
|||||||
|
|
||||||
--------------------- MENU CRATION FOR START/STOP JAMMING
|
--------------------- MENU CRATION FOR START/STOP JAMMING
|
||||||
|
|
||||||
|
--function createmenu(jammer)
|
||||||
|
--if Unit.getByName(jammer) ~= nil then
|
||||||
|
--local _groupID = Unit.getByName(jammer):getGroup():getID()
|
||||||
|
--
|
||||||
|
--local _jammermenu = missionCommands.addSubMenuForGroup(_groupID,"Jammer menu", nil)
|
||||||
|
--local _jammermenudef = missionCommands.addSubMenuForGroup(_groupID,"Defensive Jamming", _jammermenu)
|
||||||
|
--local _jammermenuoff = missionCommands.addSubMenuForGroup(_groupID,"Offensive Jamming", _jammermenu)
|
||||||
|
--
|
||||||
|
--missionCommands.addCommandForGroup(_groupID, "Start Defensive Jamming ",_jammermenudef, function () startDjamming(jammer)end, nil)
|
||||||
|
--missionCommands.addCommandForGroup(_groupID, "Stop Defensive Jamming ",_jammermenudef, function () stopDjamming(jammer)end, nil)
|
||||||
|
--missionCommands.addCommandForGroup(_groupID, "Start Offensive Jamming ",_jammermenuoff, function () startEWjamm(jammer)end, nil)
|
||||||
|
--missionCommands.addCommandForGroup(_groupID, "Stop Offensive Jamming ",_jammermenuoff, function () stopEWjamm(jammer)end, nil)
|
||||||
|
--end
|
||||||
|
--end
|
||||||
|
|
||||||
|
-------------------- Retribution Specific Menu Creation
|
||||||
|
|
||||||
function createmenu(jammer)
|
function createmenu(jammer)
|
||||||
if Unit.getByName(jammer) ~= nil then
|
if Unit.getByName(jammer) ~= nil then
|
||||||
local _groupID = Unit.getByName(jammer):getGroup():getID()
|
local _groupID = Unit.getByName(jammer):getGroup():getID()
|
||||||
|
|
||||||
|
local ecmFlag = trigger.misc.getUserFlag("offensive_jamming_" .. jammer)
|
||||||
|
|
||||||
local _jammermenu = missionCommands.addSubMenuForGroup(_groupID,"Jammer menu", nil)
|
local _jammermenu = missionCommands.addSubMenuForGroup(_groupID, "Jammer menu", nil)
|
||||||
local _jammermenudef = missionCommands.addSubMenuForGroup(_groupID,"Defensive Jamming", _jammermenu)
|
local _jammermenudef = missionCommands.addSubMenuForGroup(_groupID, "Defensive Jamming", _jammermenu)
|
||||||
local _jammermenuoff = missionCommands.addSubMenuForGroup(_groupID,"Offensive Jamming", _jammermenu)
|
|
||||||
|
|
||||||
missionCommands.addCommandForGroup(_groupID, "Start Defensive Jamming ",_jammermenudef, function () startDjamming(jammer)end, nil)
|
missionCommands.addCommandForGroup(_groupID, "Start Defensive Jamming", _jammermenudef, function ()
|
||||||
missionCommands.addCommandForGroup(_groupID, "Stop Defensive Jamming ",_jammermenudef, function () stopDjamming(jammer)end, nil)
|
startDjamming(jammer)
|
||||||
missionCommands.addCommandForGroup(_groupID, "Start Offensive Jamming ",_jammermenuoff, function () startEWjamm(jammer)end, nil)
|
end, nil)
|
||||||
missionCommands.addCommandForGroup(_groupID, "Stop Offensive Jamming ",_jammermenuoff, function () stopEWjamm(jammer)end, nil)
|
|
||||||
end
|
missionCommands.addCommandForGroup(_groupID, "Stop Defensive Jamming", _jammermenudef, function ()
|
||||||
|
stopDjamming(jammer)
|
||||||
|
end, nil)
|
||||||
|
|
||||||
|
-- Only create Offensive Jamming menu if ECM flag is set
|
||||||
|
if ecmFlag == 1 then
|
||||||
|
local _jammermenuoff = missionCommands.addSubMenuForGroup(_groupID, "Offensive Jamming", _jammermenu)
|
||||||
|
|
||||||
|
missionCommands.addCommandForGroup(_groupID, "Start Offensive Jamming", _jammermenuoff, function ()
|
||||||
|
startEWjamm(jammer)
|
||||||
|
end, nil)
|
||||||
|
|
||||||
|
missionCommands.addCommandForGroup(_groupID, "Stop Offensive Jamming", _jammermenuoff, function ()
|
||||||
|
stopEWjamm(jammer)
|
||||||
|
end, nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------- SWITCH TO ON AND OFF THE DEFENSIVE JAMMING
|
-------------------- SWITCH TO ON AND OFF THE DEFENSIVE JAMMING
|
||||||
@ -311,7 +361,7 @@ EWJD(jammer)
|
|||||||
end
|
end
|
||||||
function startDjamming(jammer)
|
function startDjamming(jammer)
|
||||||
switch[#switch+1]=jammer
|
switch[#switch+1]=jammer
|
||||||
trigger.action.outText("DEFENSIVE COUNTER MEASURES POD ON"..jammer,5)
|
trigger.action.outText("DEFENSIVE COUNTER MEASURES POD ON "..jammer,5)
|
||||||
end
|
end
|
||||||
|
|
||||||
function stopDjamming(jammer)
|
function stopDjamming(jammer)
|
||||||
@ -320,25 +370,29 @@ if switch[i]==jammer then
|
|||||||
switch[i] = nil
|
switch[i] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
trigger.action.outText("DEFENSIVE COUNTER MEASURES POD OFF"..jammer,5)
|
trigger.action.outText("DEFENSIVE COUNTER MEASURES POD OFF "..jammer,5)
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------- FUNCTION THAT EVALUATES THE DISTANCE OF THE MISSILE TO THE TARGET... YOU CAN EVEN DEFEND CLOSER AIRCRAFTS. BASED ON TRAINING MISSILES FROM GRIMES
|
-------------------------------------- FUNCTION THAT EVALUATES THE DISTANCE OF THE MISSILE TO THE TARGET... YOU CAN EVEN DEFEND CLOSER AIRCRAFTS. BASED ON TRAINING MISSILES FROM GRIMES
|
||||||
function EWJD(jammer)
|
function EWJD(jammer)
|
||||||
|
|
||||||
trigger.action.outText("EWJD Script ON"..jammer,5)
|
-- trigger.action.outText("EWJD Script ON "..jammer,5)
|
||||||
------------------------------------------------------------ DISTANCES AND PROBABILITIES OF JAMM THE MISSILE FOR DEFENSIVE JAMMING REMOVALDIST1 CORRESPOND TO PKILL1, REMOVALDIST2 CORRESPOND TO PKILL2, ETC...
|
------------------------------------------------------------ DISTANCES AND PROBABILITIES OF JAMM THE MISSILE FOR DEFENSIVE JAMMING REMOVALDIST1 CORRESPOND TO PKILL1, REMOVALDIST2 CORRESPOND TO PKILL2, ETC...
|
||||||
local removalDist1 = 500
|
local removalDist1 = 500
|
||||||
local removalDist2 = 1500
|
local removalDist2 = 1500
|
||||||
local removalDist3 = 3000
|
local removalDist3 = 3000
|
||||||
local removalDist4 = 5000
|
local removalDist4 = 5000
|
||||||
local removalDist5 = 7000
|
local removalDist5 = 7000
|
||||||
|
-- local pkill_1 =100 -------- PROBAILITY OF SUCCESFULL JAMMING REMOVALDIST1 CORRESPOND TO PKILL1, REMOVALDIST2 CORRESPOND TO PKILL2, ETC...
|
||||||
|
-- local pkill_2 =100
|
||||||
|
-- local pkill_3 =100
|
||||||
|
-- local pkill_4 =100
|
||||||
|
-- local pkill_5 =100
|
||||||
local pkill_1 =95 -------- PROBAILITY OF SUCCESFULL JAMMING REMOVALDIST1 CORRESPOND TO PKILL1, REMOVALDIST2 CORRESPOND TO PKILL2, ETC...
|
local pkill_1 =95 -------- PROBAILITY OF SUCCESFULL JAMMING REMOVALDIST1 CORRESPOND TO PKILL1, REMOVALDIST2 CORRESPOND TO PKILL2, ETC...
|
||||||
local pkill_2 =65
|
local pkill_2 =65
|
||||||
local pkill_3 =50
|
local pkill_3 =50
|
||||||
local pkill_4 =30
|
local pkill_4 =30
|
||||||
local pkill_5 =15
|
local pkill_5 =15
|
||||||
|
|
||||||
local remove_missile_method = 0
|
local remove_missile_method = 0
|
||||||
-- 0 will create an explosion
|
-- 0 will create an explosion
|
||||||
-- 1 will use Object.destroy() which simply makes the missile disappear.
|
-- 1 will use Object.destroy() which simply makes the missile disappear.
|
||||||
@ -375,6 +429,7 @@ local pkill_5 =15
|
|||||||
end
|
end
|
||||||
if remove_missile_method == 0 then
|
if remove_missile_method == 0 then
|
||||||
trigger.action.explosion(Object.getPosition(aiMissiles[id].missile).p, 5)
|
trigger.action.explosion(Object.getPosition(aiMissiles[id].missile).p, 5)
|
||||||
|
-- trigger.action.outText("MISSILE GO BOOM!!! "..jammer,10)
|
||||||
else
|
else
|
||||||
Object.destroy(aiMissiles[id].missile)
|
Object.destroy(aiMissiles[id].missile)
|
||||||
end
|
end
|
||||||
@ -403,19 +458,19 @@ local pkill_5 =15
|
|||||||
-- trigger.action.outText(prob..jammer, 20)
|
-- trigger.action.outText(prob..jammer, 20)
|
||||||
if dist < removalDist5 and prob < pkill_5 then -- if its close and still guiding
|
if dist < removalDist5 and prob < pkill_5 then -- if its close and still guiding
|
||||||
removeMis(mis.uid)
|
removeMis(mis.uid)
|
||||||
-- trigger.action.outText('5', 20)
|
-- trigger.action.outText('5', 20)
|
||||||
elseif dist < removalDist4 and prob < pkill_4 then -- if its close and still guiding
|
elseif dist < removalDist4 and prob < pkill_4 then -- if its close and still guiding
|
||||||
removeMis(mis.uid)
|
removeMis(mis.uid)
|
||||||
-- trigger.action.outText('4', 20)
|
-- trigger.action.outText('4', 20)
|
||||||
elseif dist < removalDist3 and prob < pkill_3 then -- if its close and still guiding
|
elseif dist < removalDist3 and prob < pkill_3 then -- if its close and still guiding
|
||||||
removeMis(mis.uid)
|
removeMis(mis.uid)
|
||||||
-- trigger.action.outText('3', 20)
|
-- trigger.action.outText('3', 20)
|
||||||
elseif dist < removalDist2 and prob < pkill_2 then -- if its close and still guiding
|
elseif dist < removalDist2 and prob < pkill_2 then -- if its close and still guiding
|
||||||
removeMis(mis.uid)
|
removeMis(mis.uid)
|
||||||
-- trigger.action.outText('2', 20)
|
-- trigger.action.outText('2', 20)
|
||||||
elseif dist < removalDist1 and prob < pkill_1 then -- if its close and still guiding
|
elseif dist < removalDist1 and prob < pkill_1 then -- if its close and still guiding
|
||||||
removeMis(mis.uid)
|
removeMis(mis.uid)
|
||||||
-- trigger.action.outText('1', 20)
|
-- trigger.action.outText('1', 20)
|
||||||
else
|
else
|
||||||
tot = math.min(10, dist/getMag(mist.vec.sub(misVel, targVel)))
|
tot = math.min(10, dist/getMag(mist.vec.sub(misVel, targVel)))
|
||||||
timer.scheduleFunction(checkMis, mis, timer.getTime() + tot)
|
timer.scheduleFunction(checkMis, mis, timer.getTime() + tot)
|
||||||
BIN
resources/plugins/ewrj/JAMMING MANUAL.pdf
Normal file
BIN
resources/plugins/ewrj/JAMMING MANUAL.pdf
Normal file
Binary file not shown.
@ -15,7 +15,7 @@
|
|||||||
],
|
],
|
||||||
"scriptsWorkOrders": [
|
"scriptsWorkOrders": [
|
||||||
{
|
{
|
||||||
"file": "EW script 2.00.lua",
|
"file": "EW script 2.02.lua",
|
||||||
"mnemonic": "ewrj"
|
"mnemonic": "ewrj"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -8,4 +8,4 @@ variants:
|
|||||||
E-7A Wedgetail: {}
|
E-7A Wedgetail: {}
|
||||||
tasks:
|
tasks:
|
||||||
AEW&C: 30
|
AEW&C: 30
|
||||||
has_built_in_ecm: true
|
has_built_in_jamming: true
|
||||||
|
|||||||
@ -68,3 +68,5 @@ tasks:
|
|||||||
SEAD Escort: 450
|
SEAD Escort: 450
|
||||||
Strike: 600
|
Strike: 600
|
||||||
TARCAP: 450
|
TARCAP: 450
|
||||||
|
|
||||||
|
has_built_in_ecm: true
|
||||||
@ -76,3 +76,5 @@ weapon_injections: # AGM-154B only works for AI
|
|||||||
8:
|
8:
|
||||||
- "{AGM-154B}"
|
- "{AGM-154B}"
|
||||||
- "{BRU57_2*AGM-154B}"
|
- "{BRU57_2*AGM-154B}"
|
||||||
|
|
||||||
|
has_built_in_ecm: true
|
||||||
@ -60,3 +60,4 @@ tasks:
|
|||||||
Refueling: 0
|
Refueling: 0
|
||||||
Recovery: 0
|
Recovery: 0
|
||||||
|
|
||||||
|
has_built_in_ecm: true
|
||||||
@ -76,3 +76,5 @@ weapon_injections: # AGM-154B only works for AI
|
|||||||
8:
|
8:
|
||||||
- "{AGM-154B}"
|
- "{AGM-154B}"
|
||||||
- "{BRU57_2*AGM-154B}"
|
- "{BRU57_2*AGM-154B}"
|
||||||
|
|
||||||
|
has_built_in_ecm: true
|
||||||
@ -59,3 +59,5 @@ utc_kneeboard: true
|
|||||||
tasks:
|
tasks:
|
||||||
Refueling: 0
|
Refueling: 0
|
||||||
Recovery: 0
|
Recovery: 0
|
||||||
|
|
||||||
|
has_built_in_ecm: true
|
||||||
@ -1,5 +1,5 @@
|
|||||||
name: ALQ-249 Mid Band Next Generation Jammer
|
name: ALQ-249 Mid Band Next Generation Jammer
|
||||||
type: JAMMER
|
type: OFFENSIVE_JAMMER
|
||||||
# https://www.deagel.com/Components/ALQ-249%20Next%20Generation%20Jammer/a002543#001
|
# https://www.deagel.com/Components/ALQ-249%20Next%20Generation%20Jammer/a002543#001
|
||||||
year: 2025
|
year: 2025
|
||||||
fallback:
|
fallback:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: AN/ALQ-99 ECM
|
name: AN/ALQ-99 ECM
|
||||||
type: JAMMER
|
type: OFFENSIVE_JAMMER
|
||||||
# https://www.deagel.com/Components/ANALQ-99/a000899#001
|
# https://www.deagel.com/Components/ANALQ-99/a000899#001
|
||||||
year: 1973
|
year: 1973
|
||||||
fallback:
|
fallback:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user