Update EW Script with fixes/enhancements (#584)

This commit is contained in:
Drexyl 2025-10-07 23:13:44 +11:00 committed by GitHub
parent 2832ece316
commit 0e5567ceee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -29,7 +29,7 @@
-- After the V1.0, which was based in a simple script where, it takes SAMs and switched them off depending on the distances and couple of other factors, i made this V2.0 which is much more advanced and have many other factors. -- After the V1.0, which was based in a simple script where, it takes SAMs and switched them off depending on the distances and couple of other factors, i made this V2.0 which is much more advanced and have many other factors.
--The script can be used with a player (A6 Prowler style) or with an Standoff Jamming with an AWACS or E2/E3 style... with the command "startEWjamm(jammer)" --The script can be used with a player (A6 Prowler style) or with an Standoff Jamming with an AWACS or E2/E3 style... with the command "startEWjamm(jammer)"
-- Now it takes into account, distances, angles between Jammer and SAMs and Aircraft targeted by SAMs (hereinafter “Target”), jammer altitude, Jammer and Target altitude differences, banking, pitching, and few other factors such as the “dice”. -- Now it takes into account distances, angles between Jammer and SAMs and Aircraft targeted by SAMs (hereinafter “Target”), jammer altitude, Jammer and Target altitude differences, banking, pitching, and few other factors such as the “dice”.
-- In this script I manage probabilities, and go/no go parameters. For instance, if the bank of the aircraft is too high, it takes into account, if the angle between the SAM and the Jammer... if it is not in the proper position, then, the jammer does not work. Others, such as distances, an altitudes, makes the probability of successful jamming to rise the lower the better... but if differences between Jammer and Target altitudes, the higher the differences, the lowest capacity of Jamming. -- In this script I manage probabilities, and go/no go parameters. For instance, if the bank of the aircraft is too high, it takes into account, if the angle between the SAM and the Jammer... if it is not in the proper position, then, the jammer does not work. Others, such as distances, an altitudes, makes the probability of successful jamming to rise the lower the better... but if differences between Jammer and Target altitudes, the higher the differences, the lowest capacity of Jamming.
-- Now I ll explain all these factors so you can plan your successful mission taking into account what is best for your mission profile. -- Now I ll explain all these factors so you can plan your successful mission taking into account what is best for your mission profile.
-- Another improvement is now, the radar does not Switch off. It just goes to Green Alarm state, it means, it does not fire, but is still working. Therefore, as in real life, you only know if the jamming is working if you are not being shot at!!!!!!. -- Another improvement is now, the radar does not Switch off. It just goes to Green Alarm state, it means, it does not fire, but is still working. Therefore, as in real life, you only know if the jamming is working if you are not being shot at!!!!!!.
@ -59,112 +59,167 @@ 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
-- ensure ActiveJammers table exists for multi-jammer support
ActiveJammers = ActiveJammers or {}
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() --- --- New logic to replace unreliable getRadar() ---
local UnitObject = Unit.getByName(samunit) local UnitObject = Unit.getByName(samunit)
if UnitObject ~= nil then if UnitObject == nil or not Unit.isExist(UnitObject) then
-- env.info("[DEBUG] check(): SAM unit does not exist: "..tostring(samunit))
return
end
local status, target = false, nil local status, target = false, nil
local controller = UnitObject:getController() local controller = UnitObject:getController()
local detectedTargets = controller:getDetectedTargets() local detectedTargets = controller and controller:getDetectedTargets() or {}
for _, tgt in pairs(detectedTargets) do for _, tgt in pairs(detectedTargets) do
if tgt.object and tgt.object:isExist() then if tgt and tgt.object and tgt.object:isExist() then
status = true status = true
target = tgt.object target = tgt.object
break break
end end
end end
--- Start of original script --- --- Start of original script ---
if target ~= nil then
-- trigger.action.outText(Unitobject,20)
-- if status == true then -- to see if the Radar is working
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(mist.utils.tableShow(jammerplanes),20)
-- trigger.action.outText("Target= "..target, "Jammer= "..jammer,10)
jammerobject = Unit.getByName(jammer) local jammerobject = Unit.getByName(jammer)
if jammerobject ~= nil then if jammerobject == nil or not Unit.isExist(jammerobject) then
-- trigger.action.outText(jammer.." "..samunit,20) -- env.info("[DEBUG] check(): jammer missing or destroyed: "..tostring(jammer).." for SAM "..tostring(samunit))
-- if jammer doesn't exist, only restore SAM if no other jammer active
local anyActive = false
for otherJammer, active in pairs(ActiveJammers or {}) do
if active and otherJammer ~= jammer then
-- env.info("[DEBUG] check(): other jammer still active ("..tostring(otherJammer)..") - keeping "..tostring(samunit).." suppressed")
anyActive = true
break
end
end
if not anyActive then
-- env.info("[DEBUG] check(): no other jammers - restoring "..tostring(samunit))
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25))
end
return
end
if isLOS(samunit, jammer)==true then -- ensure target object still valid
-- trigger.action.outText(jammer..'is LOS with '..samunit,20) local targetobject = Unit.getByName(targetname)
if targetobject == nil or not Unit.isExist(targetobject) then
-- env.info("[DEBUG] check(): target missing or destroyed: "..tostring(targetname).." for SAM "..tostring(samunit))
return
end
-- env.info("[DEBUG] Target Name = ".. tostring(targetname) .." | Sam UNIT = ".. tostring(samunit) .." | Jammer Name = ".. tostring(jammer))
-- LOS check
if not isLOS(samunit, jammer) then
-- LOS broken: only restore if no other jammer
local anyActive = false
for otherJammer, active in pairs(ActiveJammers or {}) do
if active and otherJammer ~= jammer then
-- env.info("[DEBUG] check(): LOS lost for "..tostring(jammer).." but "..tostring(otherJammer).." still jamming "..tostring(samunit))
anyActive = true
break
end
end
if not anyActive then
-- env.info("[DEBUG] check(): LOS lost and no other jammers - restoring "..tostring(samunit))
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25))
end
return
end
------------------------------------------------------------------------
-- distance/angle/probability logic (now guarded against nils)
------------------------------------------------------------------------
-- compute distances safely
local distSamJammer = nil
local distSamTarget = nil
if UnitObject and jammerobject then
local p1 = UnitObject:getPoint()
local p2 = jammerobject:getPoint()
if p1 and p2 then
distSamJammer = get3DDist(p1, p2)
end
end
if UnitObject and targetobject then
local p1 = UnitObject:getPoint()
local p3 = targetobject:getPoint()
if p1 and p3 then
distSamTarget = get3DDist(p1, p3)
end
end
if not distSamJammer or not distSamTarget or distSamJammer == 0 then
-- env.info("[DEBUG] check(): invalid distances for SAM "..tostring(samunit).." (distSamJammer="..tostring(distSamJammer)..", distSamTarget="..tostring(distSamTarget)..")")
return
end
local distSamJammer = get3DDist(Unit.getPoint(Unit.getByName(samunit)), Unit.getPoint(Unit.getByName(jammer)))
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 -- HEIGHT OF JAMMER
local Position_vec3 = jammerobject:getPoint()
local Position_vec3 = Unit.getByName(jammer):getPoint()
local _elevation = land.getHeight({x = Position_vec3.x, y = Position_vec3.z}) local _elevation = land.getHeight({x = Position_vec3.x, y = Position_vec3.z})
local _height = Position_vec3.y - _elevation local _height = Position_vec3.y - _elevation
local tPosition_vec3 = Unit.getByName(targetname):getPoint() local tPosition_vec3 = targetobject:getPoint()
local t_elevation = land.getHeight({x = tPosition_vec3.x, y = tPosition_vec3.z}) local t_elevation = land.getHeight({x = tPosition_vec3.x, y = tPosition_vec3.z})
local t_height = tPosition_vec3.y - t_elevation local t_height = tPosition_vec3.y - t_elevation
local prob = dice + _height/1000 + (_height - t_height)/1000 local prob = dice + _height/1000 + (_height - t_height)/1000
-- trigger.action.outText("dice "..dice.."prob "..prob.."altjammer".._height.."alttarget"..t_height,20) -- trigger.action.outText("dice "..dice.."prob "..prob.."altjammer".._height.."alttarget"..t_height,20)
-- LOBE parameter -- LOBE parameter
local SamPos = mist.utils.makeVec2(Unit.getByName(samunit):getPosition().p)-- tenemos un vector x e y local SamPos = mist.utils.makeVec2(UnitObject:getPosition().p) -- tenemos un vector x e y
-- trigger.action.outText(mist.utils.tableShow(SamPos),20) local JammerPos = mist.utils.makeVec2(jammerobject:getPosition().p)
local JammerPos = mist.utils.makeVec2(Unit.getByName(jammer):getPosition().p) local TargetPos = mist.utils.makeVec2(targetobject: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)))) 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)))) 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 ) local offsetJamTar = smallestAngleDiff(AngleSamJammer, AngleSamTarget )
-- trigger.action.outText(offsetJamTar,20)
local offsetJamSam = smallestAngleDiff(AngleSamJammer, 180 ) local offsetJamSam = smallestAngleDiff(AngleSamJammer, 180 )
-- trigger.action.outText("Jamm "..AngleSamJammer.."-Target ".. AngleSamTarget.."-Offjam ".. offsetJamSam.." -Offtar "..offsetJamTar,20)
local TargetandOffsetJamSam = smallestAngleDiff(AngleSamTarget, offsetJamSam )*2 local TargetandOffsetJamSam = smallestAngleDiff(AngleSamTarget, offsetJamSam )*2
if TargetandOffsetJamSam < 0 then if TargetandOffsetJamSam < 0 then
TargetandOffsetJamSam = -TargetandOffsetJamSam TargetandOffsetJamSam = -TargetandOffsetJamSam
end end
-- trigger.action.outText(conditiondist.." relacion ".. prob.." probabilidad",20) -- trigger.action.outText(conditiondist.." relacion ".. prob.." probabilidad",20)
local anglecondition = 2/3 * distSamJammer/1000 local anglecondition = 2/3 * distSamJammer/1000
-- trigger.action.outText(anglecondition.." target difference "..TargetandOffsetJamSam,20) -- trigger.action.outText(anglecondition.." target difference "..TargetandOffsetJamSam,20)
-- PITCH and BANK -- PITCH and BANK
local bankr = mist.utils.toDegree(mist.getRoll(Unit.getByName(jammer))) local bankr = mist.utils.toDegree(mist.getRoll(jammerobject))
if bankr < 0 then if bankr < 0 then
bankr = -bankr bankr = -bankr
end end
bank = bankr - 30 local bank = bankr - 30
-- trigger.action.outText("real"..bankr.."tocado"..bank,20) -- trigger.action.outText("real"..bankr.."tocado"..bank,20)
local pitchr = mist.utils.toDegree(mist.getPitch(Unit.getByName(jammer))) local pitchr = mist.utils.toDegree(mist.getPitch(jammerobject))
if pitchr < 0 then if pitchr < 0 then
pitchr = -pitchr pitchr = -pitchr
end end
pitch = pitchr - 30 local pitch = pitchr - 30
-- trigger.action.outText("real"..pitchr.."tocado"..pitch,20) -- trigger.action.outText("real"..pitchr.."tocado"..pitch,20)
local sPosition_vec3 = Unit.getByName(samunit):getPoint() local sPosition_vec3 = UnitObject:getPoint()
-- trigger.action.outText(mist.utils.tableShow(sPosition_vec3),20) -- trigger.action.outText(mist.utils.tableShow(sPosition_vec3),20)
local s_elevation = land.getHeight({x = sPosition_vec3.x, y = sPosition_vec3.z}) local s_elevation = land.getHeight({x = sPosition_vec3.x, y = sPosition_vec3.z})
local s_height = sPosition_vec3.y - s_elevation local s_height = sPosition_vec3.y - s_elevation
local cateto = _height - s_height local cateto = _height - s_height
-- trigger.action.outText("altura sam "..cateto,20) -- trigger.action.outText("altura sam "..cateto,20)
local samunitposition = Unit.getByName(samunit):getPosition().p local samunitposition = UnitObject:getPosition().p
local jammerposition = Unit.getByName(jammer):getPosition().p local jammerposition = jammerobject:getPosition().p
local _2DDistSamJammer = mist.utils.get2DDist(samunitposition, jammerposition) local _2DDistSamJammer = mist.utils.get2DDist(samunitposition, jammerposition)
local anglesamjam = mist.utils.toDegree(math.asin(cateto/_2DDistSamJammer)) local anglesamjam = mist.utils.toDegree(math.asin(cateto/_2DDistSamJammer))
-- trigger.action.outText("angulo is "..anglesamjam,20) -- trigger.action.outText("angulo is "..anglesamjam,20)
@ -178,7 +233,6 @@ function check(jammer, samunit)
and anglesamjam >= bank and anglesamjam >= bank
and anglesamjam > pitch and anglesamjam > pitch
then then
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector3.." "..dice,20)
mist.scheduleFunction(samOFF, {samunit}, timer.getTime()) mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
elseif ((conditiondist < 40.5) and (conditiondist > 13.33)) elseif ((conditiondist < 40.5) and (conditiondist > 13.33))
and (prob <= probsector2) and (prob <= probsector2)
@ -186,7 +240,6 @@ function check(jammer, samunit)
and anglesamjam >= bank and anglesamjam >= bank
and anglesamjam > pitch and anglesamjam > pitch
then then
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector2.." "..dice,20)
mist.scheduleFunction(samOFF, {samunit}, timer.getTime()) mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
elseif (conditiondist < 13.33) elseif (conditiondist < 13.33)
and (prob <= probsector1 ) and (prob <= probsector1 )
@ -195,46 +248,89 @@ function check(jammer, samunit)
and anglesamjam > pitch and anglesamjam > pitch
then then
mist.scheduleFunction(samOFF, {samunit}, timer.getTime()) mist.scheduleFunction(samOFF, {samunit}, timer.getTime())
-- trigger.action.outText(samunit.." "..conditiondist.." "..probsector1.." "..dice,20)
else else
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25)) -- Only restore SAM if no other jammer is still active
-- trigger.action.outText("fuera de cobertura",20) local anyActive = false
local blockingJammer = nil
for otherJammer, active in pairs(ActiveJammers or {}) do
if active and otherJammer ~= jammer then
anyActive = true
blockingJammer = otherJammer
break
end end
else
-- trigger.action.outText(jammer..'NOT LOS with '..samunit,20)
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25))
end end
if not anyActive then
-- env.info("[DEBUG] check(): SAM "..tostring(samunit).." restored (no other jammers)")
mist.scheduleFunction(samON, {samunit}, timer.getTime()+ math.random(15,25))
else
-- env.info("[DEBUG] check(): SAM "..tostring(samunit).." still jammed by "..tostring(blockingJammer))
end
end end
end
else else
-- no target
-- trigger.action.outText(samunit.." No detection",5) -- trigger.action.outText(samunit.." No detection",5)
-- end return
end end
offscriptfunc = mist.scheduleFunction(check, {jammer, samunit}, timer.getTime() + 5) offscriptfunc = mist.scheduleFunction(check, {jammer, samunit}, timer.getTime() + 5)
end end
-- check('radar1') -- check('radar1')
-- check('radar2') -- check('radar2')
---------------------------- SAM ON OFF. IT CHANGES THE RULE OF ENGAGEMENT OR ALERT STATE. ---------------------------- SAM ON OFF. IT CHANGES THE RULE OF ENGAGEMENT OR ALERT STATE.
function samON(groupsam) function samON(groupsam)
-- local samName = groupsam
local unitObj = Unit.getByName(groupsam)
if not unitObj or not Unit.isExist(unitObj) then
-- Unit missing (dead or wrong name) — avoid nil indexing
-- env.info("[DEBUG] samON() - Unit not found or destroyed: " .. tostring(groupsam))
return
end
_group = Unit.getByName(groupsam):getGroup() local _group = unitObj:getGroup()
_controller = _group:getController() if not _group then
_controller:setOption(AI.Option.Ground.id.ROE, AI.Option.Ground.val.ROE.OPEN_FIRE) -- env.info("[DEBUG] samON() - Group not found for unit: " .. tostring(groupsam))
-- trigger.action.outText(groupsam.." SAM SWITCHING ON", 10) return
end
local dice = math local _controller = _group:getController()
if not _controller then
-- env.info("[DEBUG] samON() - Controller missing for group of: " .. tostring(groupsam))
return
end
_controller:setOption(AI.Option.Ground.id.ROE, AI.Option.Ground.val.ROE.OPEN_FIRE)
-- trigger.action.outText(groupsam.." SAM SWITCHING ON", 10)
-- env.info("[DEBUG - OFFENSIVE] SAM has switched ON: " .. groupsam)
end end
function samOFF(groupsam)
_group = Unit.getByName(groupsam):getGroup() function samOFF(groupsam)
_controller = _group:getController() local unitObj = Unit.getByName(groupsam)
_controller:setOption(AI.Option.Ground.id.ROE, AI.Option.Ground.val.ROE.WEAPON_HOLD) if not unitObj or not Unit.isExist(unitObj) then
-- trigger.action.outText(groupsam.." SAM SWITCHING OFF", 10) -- env.info("[DEBUG] samOFF() - Unit not found or destroyed: " .. tostring(groupsam))
mist.scheduleFunction(samON, {groupsam}, timer.getTime()+ math.random(15,25)) return
end
local _group = unitObj:getGroup()
if not _group then
-- env.info("[DEBUG] samOFF() - Group not found for unit: " .. tostring(groupsam))
return
end
local _controller = _group:getController()
if not _controller then
-- env.info("[DEBUG] samOFF() - Controller missing for group of: " .. tostring(groupsam))
return
end
_controller:setOption(AI.Option.Ground.id.ROE, AI.Option.Ground.val.ROE.WEAPON_HOLD)
-- trigger.action.outText(groupsam.." SAM SWITCHING OFF", 10)
-- local samName = groupsam
-- env.info("[DEBUG - OFFENSIVE] SAM has switched OFF: " .. groupsam)
mist.scheduleFunction(samON, {groupsam}, timer.getTime()+ math.random(15,25))
end end
function isLOS(sam,radar) --- check if sam is LOS with Jammer function isLOS(sam,radar) --- check if sam is LOS with Jammer
@ -279,23 +375,51 @@ getRadars()
function startEWjamm(jammer) function startEWjamm(jammer)
-- local jammerName = jammer
trigger.action.outText("OFFENSIVE COUNTER MEASURES POD ON "..jammer,5) trigger.action.outText("OFFENSIVE COUNTER MEASURES POD ON "..jammer,5)
env.info("[DEBUG] Start Offensive Jamming: " ..jammer)
-- mark jammer active for multi-jammer logic
ActiveJammers[jammer] = true
for k,v in pairs ( radarList)do for k,v in pairs ( radarList)do
if Unit.getByName(radarList[k]):getCoalition()~= Unit.getByName(jammer):getCoalition() then if Unit.getByName(radarList[k]):getCoalition()~= Unit.getByName(jammer):getCoalition() then
check(jammer, radarList[k]) check(jammer, radarList[k])
-- trigger.action.outText(radarList[k],5) -- trigger.action.outText(radarList[k],5)
end end
end end
end
-- startEWjamm('Prowler1')
function stopEWjamm(jammer)
mist.removeFunction(offscriptfunc)
trigger.action.outText("OFFENSIVE COUNTER MEASURES POD OFF "..jammer,5)
end end
-- startEWjamm('Prowler1')
function stopEWjamm(jammer)
ActiveJammers[jammer] = nil
trigger.action.outText("OFFENSIVE COUNTER MEASURES OFF "..jammer,5)
env.info("[DEBUG] Stop Offensive Jamming: " .. jammer)
-- Check if *any* other jammer is still active
local anyActive = false
for otherJammer, active in pairs(ActiveJammers) do
if active and otherJammer ~= jammer then
-- env.info("[DEBUG] stopEWjamm(): "..jammer.." stopped, but "..otherJammer.." still active")
anyActive = true
break
end
end
-- Only restore SAMs if no other jammer exists
if not anyActive then
-- env.info("[DEBUG] stopEWjamm(): No jammers left, restoring all SAMs")
for _, samName in pairs(radarList) do
local samUnit = Unit.getByName(samName)
if samUnit and samUnit:isExist() then
mist.scheduleFunction(samON, {samName}, timer.getTime()+ math.random(5,15))
end
end
else
-- env.info("[DEBUG] stopEWjamm(): SAMs remain suppressed due to other active jammers")
end
end
switch = {} switch = {}
function EWJscript(jammer) function EWJscript(jammer)
@ -336,7 +460,7 @@ function createmenu(jammer)
end, nil) end, nil)
missionCommands.addCommandForGroup(_groupID, "Stop Defensive Jamming", _jammermenudef, function () missionCommands.addCommandForGroup(_groupID, "Stop Defensive Jamming", _jammermenudef, function ()
stopDjamming(jammer) stopIAdefjamming(jammer)
end, nil) end, nil)
-- Only create Offensive Jamming menu if ECM flag is set -- Only create Offensive Jamming menu if ECM flag is set
@ -355,22 +479,26 @@ function createmenu(jammer)
end end
-------------------- SWITCH TO ON AND OFF THE DEFENSIVE JAMMING -------------------- SWITCH TO ON AND OFF THE DEFENSIVE JAMMING
function startIAdefjamming(jammer) function startIAdefjamming(jammer)
startDjamming(jammer) startDjamming(jammer)
EWJD(jammer) EWJD(jammer)
end end
function startDjamming(jammer) function startDjamming(jammer)
switch[#switch+1]=jammer -- local jammerName = jammer
trigger.action.outText("DEFENSIVE COUNTER MEASURES POD ON "..jammer,5) switch[#switch+1]=jammer
end trigger.action.outText("DEFENSIVE COUNTER MEASURES POD ON "..jammer,5)
env.info("[DEBUG] Start Defensive Jamming: " ..jammer)
end
function stopDjamming(jammer) function stopIAdefjamming(jammer)
for i, v in pairs (switch) do -- local jammerName = jammer
if switch[i]==jammer then for i, v in pairs (switch) do
switch[i] = nil if switch[i]==jammer then
end switch[i] = nil
end end
trigger.action.outText("DEFENSIVE COUNTER MEASURES POD OFF "..jammer,5) end
trigger.action.outText("DEFENSIVE COUNTER MEASURES POD OFF "..jammer,5)
env.info("[DEBUG] Stop Defensive Jamming: " ..jammer)
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
@ -383,16 +511,20 @@ 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
-- DEBUG VALUES
-- 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 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.
@ -422,14 +554,17 @@ local pkill_5 =15
end end
local function removeMis(id) local function removeMis(id)
-- local jammerName = jammer
if Object.isExist(aiMissiles[id].missile) then -- if missile is still active and needs to be destroyed if Object.isExist(aiMissiles[id].missile) then -- if missile is still active and needs to be destroyed
if Weapon.getTarget(aiMissiles[id].missile) == aiMissiles[id].origTarg and Unit.getPlayerName(aiMissiles[id].origTarg) then if Weapon.getTarget(aiMissiles[id].missile) == aiMissiles[id].origTarg and Unit.getPlayerName(aiMissiles[id].origTarg) then
-- trigger.action.outText(Unit.getPlayerName(aiMissiles[id].origTarg) .. ' has been hit by a simulated missile. You should eject in shame.', 20) -- trigger.action.outText(Unit.getPlayerName(aiMissiles[id].origTarg) .. ' has been hit by a simulated missile. You should eject in shame.', 20)
-- env.info("[DEBUG - JAMMED] Missile NOT JAMMED and hit target: " ..jammer)
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) -- trigger.action.outText("MISSILE GO BOOM!!! "..jammer,10)
-- trigger.action.outText("Missile has been successfully jammed"..jammer,5)
-- env.info("[DEBUG - JAMMED] Missile has been jammed: " ..jammer)
else else
Object.destroy(aiMissiles[id].missile) Object.destroy(aiMissiles[id].missile)
end end
@ -439,8 +574,9 @@ local pkill_5 =15
return return
end end
local function checkMis(mis)
local function checkMis(mis)
-- local jammerName = jammer
local tot = 0 local tot = 0
@ -450,39 +586,44 @@ local pkill_5 =15
if Object.isExist(mis.origTarg) == true then if Object.isExist(mis.origTarg) == true then
local misVel = Object.getVelocity(mis.missile) local misVel = Object.getVelocity(mis.missile)
local targVel = Object.getVelocity(mis.origTarg) local targVel = Object.getVelocity(mis.origTarg)
for i, v in pairs (switch) do
if switch[i]==jammer then
for i, v in pairs(switch) do
if switch[i] == jammer then
if jammer ~= nil then if jammer ~= nil then
local dist = get3DDist(Object.getPoint(mis.missile), Unit.getPoint(Unit.getByName(jammer))) local jammerUnit = Unit.getByName(jammer)
-- trigger.action.outText(prob..jammer, 20) if jammerUnit and Unit.isExist(jammerUnit) then
local dist = get3DDist(mis.missile:getPoint(), jammerUnit:getPoint())
-- env.info("[DEBUG] Checking jammer: " .. jammer .. " | Distance: " .. dist .. " | Missile prob: " .. prob)
-- 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) -- env.info("[DEBUG - JAMMED] Missile UID " .. mis.uid .. " removed by jammer " .. jammer .. " within removalDist5 and prob < pkill_5" .. prob)
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) -- env.info("[DEBUG - JAMMED] Missile UID " .. mis.uid .. " removed by jammer " .. jammer .. " within removalDist4 and prob < pkill_4" .. prob)
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) -- env.info("[DEBUG - JAMMED] Missile UID " .. mis.uid .. " removed by jammer " .. jammer .. " within removalDist3 and prob < pkill_3" .. prob)
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) -- env.info("[DEBUG - JAMMED] Missile UID " .. mis.uid .. " removed by jammer " .. jammer .. " within removalDist2 and prob < pkill_2" .. prob)
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) -- env.info("[DEBUG - JAMMED] Missile UID " .. mis.uid .. " removed by jammer " .. jammer .. " within removalDist1 and prob < pkill_1" .. prob)
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)
end end
end else
end -- env.info("[DEBUG] Jammer " .. tostring(jammer) .. " does not exist or is destroyed")
end
end end
end end
end end
end
end
end
end
local function aiShot(event) local function aiShot(event)
prob = math.random(0,100) prob = math.random(0,100)
@ -539,4 +680,3 @@ end
-- EWJamming("Prowler1") -- EWJamming("Prowler1")
-- EWJamming("Prowler2") -- EWJamming("Prowler2")