Merge remote-tracking branch 'origin/master' into develop

This commit is contained in:
Applevangelist
2026-01-22 17:19:21 +01:00
3 changed files with 94 additions and 57 deletions
+91 -54
View File
@@ -628,7 +628,7 @@ do
self.autoshorad = true self.autoshorad = true
self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP
self.FilterZones = Zones self.FilterZones = Zones
self.ARMWeaponSeen = {} self.LastThreatEval = {}
self.InboundARMs = {} self.InboundARMs = {}
self.SkateZones = nil self.SkateZones = nil
@@ -2117,64 +2117,82 @@ do
-- @param #number delay -- @param #number delay
-- @return #boolean Outcome -- @return #boolean Outcome
function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, weaponName, weaponWrapper, tti, delay) function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, weaponName, weaponWrapper, tti, delay)
self:T(self.lid.."SeadAllowSuppression")
-- Init per-SAM weapon tracking --- Thanks to @Goon Jan 2026
self.ARMWeaponSeen = self.ARMWeaponSeen or {} ----------------------------------------------------------------
self.ARMWeaponSeen[targetName] = self.ARMWeaponSeen[targetName] or {} -- LOG INCOMING REQUEST
----------------------------------------------------------------
-- Extract weapon ID self:T(string.format("MANTIS:SeadAllowSuppression REQUEST | target=%s | weapon=%s | tti=%s | delay=%s",tostring(targetName),
local wid = nil tostring(weaponName),tostring(tti),tostring(delay)))
if weaponWrapper and weaponWrapper.GetDCSObject then
local wpn = weaponWrapper:GetDCSObject() ----------------------------------------------------------------
if wpn then -- LOOK UP ARM CAPACITY FOR THIS SAM
wid = wpn:getID() ----------------------------------------------------------------
end local armcap = nil
for _, sam in pairs(self.SAM_Table or {}) do
if sam[1] == targetName then
armcap = sam[7] -- ARMCapacity
break
end end
end
self:T(string.format("MANTIS:SeadAllowSuppression SAM DATA | target=%s | ARMCapacity=%s",tostring(targetName),armcap and tostring(armcap) or "nil"))
----------------------------------------------------------------
-- TRACK SEAD THREATS (PER TARGET)
----------------------------------------------------------------
local THREAT_WINDOW = 0.1 -- seconds
-- Ignore duplicate evaluations of the same missile self.LastThreatEval = self.LastThreatEval or {}
if wid and self.ARMWeaponSeen[targetName][wid] then self.InboundARMs = self.InboundARMs or {}
self:T(string.format(
"MANTIS: Duplicate ARM ignored for %s (weapon %d)",
targetName, wid
))
return false
end
-- Mark weapon as seen local now = timer.getTime()
if wid then local last = self.LastThreatEval[targetName] or 0
self.ARMWeaponSeen[targetName][wid] = true
end
-- NOW increment ARM counter (once per weapon) if (now - last) >= THREAT_WINDOW then
self.InboundARMs[targetName] = (self.InboundARMs[targetName] or 0) + 1 self.InboundARMs[targetName] = (self.InboundARMs[targetName] or 0) + 1
self.LastThreatEval[targetName] = now
self:T(string.format("MANTIS:SeadAllowSuppression NEW threat accepted | Δt=%.3f",now - last))
else
self:T(string.format("MANTIS:SeadAllowSuppression duplicate evaluation ignored | Δt=%.3f",now - last))
end
local inbound = self.InboundARMs[targetName] or 0
self:T(string.format("MANTIS:SeadAllowSuppression THREAT COUNT | target=%s | inboundThreats=%d",tostring(targetName),inbound))
----------------------------------------------------------------
-- DECISION GATE
----------------------------------------------------------------
-- Lookup ARM capacity -- No missiles left over → legacy behavior
local samdata if targetGroup and targetGroup:IsAlive() then
for _, sam in pairs(self.SAM_Table or {}) do local AmmotT, AmmoS, _, _,AmmoM = targetGroup:GetAmmunition()
if sam[1] == targetName then -- TODO Check C-RAM probably needs an exception as it is a gun, need to check its effectiveness
samdata = sam if AmmoM and AmmoM == 0 then
break self:T(string.format("MANTIS:SeadAllowSuppression DECISION -> APPROVED (no MISSILES) | target=%s",tostring(targetName)))
end
end
local armcap = samdata and samdata[7]
if not armcap or armcap == 0 then
return true return true
end end
end
if targetGroup and targetGroup:IsAlive() then
local AmmotT, AmmoS, _, _,AmmoM = targetGroup:GetAmmunition()
if AmmoM and AmmoM == 0 then
return true
end
end
if self.InboundARMs[targetName] > armcap then -- No ARM capacity defined → legacy behavior
return true if (not armcap) or armcap == 0 then
end self:T(string.format("MANTIS:SeadAllowSuppression DECISION -> APPROVED (no ARMCAP) | target=%s",tostring(targetName)))
return true
return false end
-- Suppress only once enough threats accumulated
if inbound >= armcap then
self:T(string.format("MANTIS:SeadAllowSuppression DECISION -> APPROVED (inbound %d >= cap %d) | target=%s",inbound,armcap,tostring(targetName)))
return true
end
self:T(string.format("MANTIS:SeadAllowSuppression DECISION -> DENIED (inbound %d < cap %d) | target=%s",inbound,armcap,tostring(targetName)))
return false
end end
--- [Internal] Check detection function --- [Internal] Check detection function
@@ -2225,6 +2243,7 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
switch = true switch = true
end end
if self.SamStateTracker[name] ~= "RED" and switch then if self.SamStateTracker[name] ~= "RED" and switch then
self.SamStateTracker[name] = "RED"
self:__RedState(1,samgroup) self:__RedState(1,samgroup)
end end
-- DONE Restrict on Distance -- DONE Restrict on Distance
@@ -2257,8 +2276,8 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
samgroup:OptionAlarmStateGreen() samgroup:OptionAlarmStateGreen()
end end
if self.SamStateTracker[name] ~= "GREEN" then if self.SamStateTracker[name] ~= "GREEN" then
self:__GreenState(1,samgroup)
self.SamStateTracker[name] = "GREEN" self.SamStateTracker[name] = "GREEN"
self:__GreenState(1,samgroup)
end end
if self.debug or self.verbose then if self.debug or self.verbose then
local text = string.format("SAM %s in alarm state GREEN!", name) local text = string.format("SAM %s in alarm state GREEN!", name)
@@ -2268,12 +2287,13 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
end --end alive end --end alive
end --end check end --end check
end --for loop end --for loop
--[[
if self.debug or self.verbose or self.logsamstatus then if self.debug or self.verbose or self.logsamstatus then
for _,_status in pairs(self.SamStateTracker) do for _,_status in pairs(self.SamStateTracker) do
if _status == "GREEN" then if _status == "GREEN" then
instatusgreen=instatusgreen+1 instatusgreen=instatusgreen+1
elseif _status == "RED" then elseif _status == "RED" then
instatusred=instatusred+1 instatusred=instatusred+1
end end
end end
if self.Shorad then if self.Shorad then
@@ -2282,6 +2302,8 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
end end
end end
end end
self:T(self.lid..string.format("SAM State Count: GREEN %d | RED %d | SHORAD %d",instatusred, instatusgreen, activeshorads))
--]]
return instatusred, instatusgreen, activeshorads return instatusred, instatusgreen, activeshorads
end end
@@ -2313,13 +2335,29 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
local samset = self.SAM_Table_Short -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height local samset = self.SAM_Table_Short -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
local instatusreds, instatusgreens, activeshoradss = self:_CheckLoop(samset,detset,dlink,self.maxshortrange) local instatusreds, instatusgreens, activeshoradss = self:_CheckLoop(samset,detset,dlink,self.maxshortrange)
local samset = self.SAM_Table_PointDef -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height local samset = self.SAM_Table_PointDef -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxpointdefrange) local instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxpointdefrange)
else else
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic) local instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic)
end end
local function GetReport() local function GetReport()
if self.debug or self.verbose or self.logsamstatus then
for _,_status in pairs(self.SamStateTracker) do
if _status == "GREEN" then
instatusgreen=instatusgreen+1
elseif _status == "RED" then
instatusred=instatusred+1
end
end
if self.Shorad then
for _,_name in pairs(self.Shorad.ActiveGroups or {}) do
activeshorads=activeshorads+1
end
end
end
local statusreport = REPORT:New("\nMANTIS Status "..self.name) local statusreport = REPORT:New("\nMANTIS Status "..self.name)
statusreport:Add("+-----------------------------+") statusreport:Add("+-----------------------------+")
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred)) statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
@@ -2628,7 +2666,6 @@ function MANTIS:SeadAllowSuppression(targetGroup, targetName, attackerGroup, wea
self:T({From, Event, To, Name}) self:T({From, Event, To, Name})
self.SuppressedGroups[Name] = false self.SuppressedGroups[Name] = false
self.InboundARMs[Name] = 0 self.InboundARMs[Name] = 0
self.ARMWeaponSeen[Name] = nil
return self return self
end end
+2 -2
View File
@@ -318,7 +318,7 @@ function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADG
elseif height <= 12500 then elseif height <= 12500 then
Ropt = Ropt * 0.98 Ropt = Ropt * 0.98
end end
local WeaponWrapper = WEAPON:New(SEADWeapon)
-- look at a couple of zones across the trajectory -- look at a couple of zones across the trajectory
for n=1,3 do for n=1,3 do
local dist = Ropt - ((n-1)*20000) local dist = Ropt - ((n-1)*20000)
@@ -342,7 +342,7 @@ function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADG
_targetgroupname = tgtgrp:GetName() -- group name _targetgroupname = tgtgrp:GetName() -- group name
_targetskill = tgtgrp:GetUnit(1):GetSkill() _targetskill = tgtgrp:GetUnit(1):GetSkill()
self:T("*** Found Target = ".. _targetgroupname) self:T("*** Found Target = ".. _targetgroupname)
self:ManageEvasion(_targetskill,_targetgroup,pos0,"AGM_88",SEADGroup, 20) self:ManageEvasion(_targetskill,_targetgroup,pos0,"AGM_88",SEADGroup, 20, WeaponWrapper)
end end
--end --end
end end
+1 -1
View File
@@ -350,7 +350,7 @@ end
-- myweapon:SetFuncImpact(OnImpact) -- myweapon:SetFuncImpact(OnImpact)
-- --
-- -- Start tracking. -- -- Start tracking.
-- myweapon:Track() -- myweapon:StartTrack()
-- --
function WEAPON:SetFuncImpact(FuncImpact, ...) function WEAPON:SetFuncImpact(FuncImpact, ...)
self.impactFunc=FuncImpact self.impactFunc=FuncImpact