diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index e9b618cf2..f88b7c2f6 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -1270,8 +1270,10 @@ end -- @return Core.Set#SET_UNIT Set of units and statics inside the zone. function ZONE_RADIUS:GetScannedSetUnit(Coalition) - local SetUnit = SET_UNIT:New() - + self.SetUnit = self.SetUnit or SET_UNIT:New() + self.SetUnit:Clear(false) + self.SetUnit.Set={} + if self.ScanData then for ObjectID, UnitObject in pairs( self.ScanData.Units ) do local UnitObject = UnitObject -- DCS#Unit @@ -1283,18 +1285,18 @@ function ZONE_RADIUS:GetScannedSetUnit(Coalition) if Coalition == nil then includeoncoalition = true end --self:I(string.format("Unit name %s coalition %s filter coalition = %s include = %s",FoundUnit:GetName(),tostring(FoundCoalition),tostring(Coalition),tostring(includeoncoalition))) if FoundUnit and includeoncoalition then - SetUnit:AddUnit( FoundUnit ) + self.SetUnit:AddUnit( FoundUnit ) else local FoundStatic = STATIC:FindByName( UnitObject:getName(), false ) if FoundStatic then - SetUnit:AddUnit( FoundStatic ) + self.SetUnit:AddUnit( FoundStatic ) end end end end end - return SetUnit + return self.SetUnit end --- Get a set of scanned groups. diff --git a/Moose Development/Moose/Functional/Mantis.lua b/Moose Development/Moose/Functional/Mantis.lua index 3d5dde62b..7128e7afd 100644 --- a/Moose Development/Moose/Functional/Mantis.lua +++ b/Moose Development/Moose/Functional/Mantis.lua @@ -404,7 +404,7 @@ MANTIS.SamData = { ["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" }, ["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" }, ["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" }, - ["NIKE"] = { Range=155, Blindspot=6, Height=30, Type="Long", Radar="HIPAR" }, + ["Nike"] = { Range=155, Blindspot=6, Height=30, Type="Long", Radar="HIPAR" }, ["Dog Ear"] = { Range=11, Blindspot=0, Height=9, Type="Point", Radar="Dog Ear", Point="true" }, -- CH Added to DCS core 2.9.19.x ["Pantsir S1"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1" , Point="true" }, @@ -530,7 +530,7 @@ do --@param #string samprefix Prefixes for the SAM groups from the ME, e.g. all groups starting with "Red Sam..." --@param #string ewrprefix Prefixes for the EWR groups from the ME, e.g. all groups starting with "Red EWR..." --@param #string hq Group name of your HQ (optional) - --@param #string coalition Coalition side of your setup, e.g. "blue", "red" or "neutral" + --@param #string Coalition Coalition side of your setup, e.g. "blue", "red" or "neutral" --@param #boolean dynamic Use constant (true) filtering or just filter once (false, default) (optional) --@param #string awacs Group name of your Awacs (optional) --@param #boolean EmOnOff Make MANTIS switch Emissions on and off instead of changing the alarm state between RED and GREEN (optional) @@ -554,7 +554,7 @@ do -- mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs") -- mybluemantis:Start() -- - function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs, EmOnOff, Padding, Zones) + function MANTIS:New(name,samprefix,ewrprefix,hq,Coalition,dynamic,awacs, EmOnOff, Padding, Zones) -- Inherit everything from BASE class. @@ -573,7 +573,8 @@ do self.SAM_Templates_Prefix = samprefix or "Red SAM" self.EWR_Templates_Prefix = ewrprefix or "Red EWR" self.HQ_Template_CC = hq or nil - self.Coalition = coalition or "red" + self.Coalition = Coalition or "red" + self.coalition = Coalition == "blue" and coalition.side.BLUE or coalition.side.RED self.SAM_Table = {} self.SAM_Table_Long = {} self.SAM_Table_Medium = {} @@ -1501,11 +1502,19 @@ do local coord = grp:GetCoordinate() local dist = 0 local include = true + if grp:IsGround() then include = false end + if grp:GetCoalition() == self.coalition then include = false end if coord and SamCoordinate and grp:IsHelicopter() then dist = coord:Get2DDistance(SamCoordinate) or 0 if dist > self.ShoradActDistance then include = false end -- we do not want long range shooting at helos end - if grp:GetHeight(true) < height and include == true then + if self.debug then + local text = "Looking at Group: "..grp:GetName() or "N/A" + text = text .. " Include = "..tostring(include) + MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.verbose):ToLog() + end + local grpalt = grp:GetHeight(true) + if grpalt < height and grpalt > 10 and include == true then table.insert(set,coord) end end @@ -1610,16 +1619,18 @@ do self.intelset = {} - local IntelOne = INTEL:New(groupset,self.Coalition,self.name.." IntelOne") + local IntelOne = INTEL:New(groupset,self.coalition,self.name.." IntelOne") IntelOne.DetectAccoustic = self.DetectAccoustic IntelOne.DetectAccousticRadius = self.DetectAccousticRadius or 2000 IntelOne.DetectAccousticUnitTypes = self.DetectAccousticCategories or {Unit.Category.HELICOPTER} + --IntelOne:SetClusterAnalysis(true,true,true) IntelOne:Start() - local IntelTwo = INTEL:New(samset,self.Coalition,self.name.." IntelTwo") + local IntelTwo = INTEL:New(samset,self.coalition,self.name.." IntelTwo") IntelTwo.DetectAccoustic = self.DetectAccoustic IntelTwo.DetectAccousticRadius = self.DetectAccousticRadius or 2000 IntelTwo.DetectAccousticUnitTypes = self.DetectAccousticCategories or {Unit.Category.HELICOPTER} + --IntelTwo:SetClusterAnalysis(true,true,true) IntelTwo:Start() local CacheTime = self.DLinkCacheTime or 120 @@ -2025,7 +2036,7 @@ do self:__RedState(1,samgroup) end -- DONE Restrict on Distance - if shortsam == true and self.SmokeDecoy == true and Distance < self.DetectAccousticRadius*2 then + if shortsam == true and self.SmokeDecoy == true and Distance < self.DetectAccousticRadius*1.5 then self:T("Smoking") self:_SmokeUnits(samgroup) end @@ -2218,7 +2229,7 @@ do end --]] if self.autoshorad then - self.Shorad = SHORAD:New(self.name.."-SHORAD","SHORAD",self.SAM_Group,self.ShoradActDistance,self.ShoradTime,self.coalition,self.UseEmOnOff) + self.Shorad = SHORAD:New(self.name.."-SHORAD","SHORAD",self.SAM_Group,self.ShoradActDistance,self.ShoradTime,self.Coalition,self.UseEmOnOff,self.SmokeDecoy,self.SmokeDecoyColor) self.Shorad:SetDefenseLimits(80,95) self.ShoradLink = true self.Shorad.Groupset=self.ShoradGroupSet diff --git a/Moose Development/Moose/Functional/Shorad.lua b/Moose Development/Moose/Functional/Shorad.lua index bc5156943..9b8ff7428 100644 --- a/Moose Development/Moose/Functional/Shorad.lua +++ b/Moose Development/Moose/Functional/Shorad.lua @@ -48,7 +48,9 @@ -- @field #number minscootdist Min distance of the next zone -- @field #number maxscootdist Max distance of the next zone -- @field #boolean scootrandomcoord If true, use a random coordinate in the zone and not the center --- @field #string scootformation Formation to take for scooting, e.g. "Vee" or "Cone" +-- @field #string scootformation Formation to take for scooting, e.g. "Vee" or "Cone" +-- @field #boolean SmokeDecoy = false, +-- @field #number SmokeDecoyColor = SMOKECOLOR.White -- @extends Core.Base#BASE @@ -114,7 +116,9 @@ SHORAD = { SkateZones = nil, minscootdist = 100, maxscootdist = 3000, - scootrandomcoord = false, + scootrandomcoord = false, + SmokeDecoy = false, + SmokeDecoyColor = SMOKECOLOR.White } ----------------------------------------------------------------------- @@ -161,8 +165,10 @@ do -- @param #number ActiveTimer Determines how many seconds the systems stay on red alert after wake-up call -- @param #string Coalition Coalition, i.e. "blue", "red", or "neutral" -- @param #boolean UseEmOnOff Use Emissions On/Off rather than Alarm State Red/Green (default: use Emissions switch) + -- @param #boolean SmokeDecoy Throw smoke decoy when getting activated. Defaults to false. + -- @param #number SmokeDecoyColor SMOLECOLOR to use. Defaults to SMOLECOLOR.White -- @return #SHORAD self - function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff) + function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff, SmokeDecoy, SmokeDecoyColor) local self = BASE:Inherit( self, FSM:New() ) self:T({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition}) @@ -171,6 +177,7 @@ do self.name = Name or "MyShorad" self.Prefixes = ShoradPrefix or "SAM SHORAD" self.Radius = Radius or 20000 + if type(Coalition) == "number" then Coalition = string.lower(UTILS.GetCoalitionName(Coalition)) end self.Coalition = Coalition or "blue" self.Samset = Samset or GroupSet self.ActiveTimer = ActiveTimer or 600 @@ -181,8 +188,15 @@ do self.DefenseLowProb = 70 -- probability to detect a missile shot, low margin self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin self.UseEmOnOff = true -- Decide if we are using Emission on/off (default) or AlarmState red/green + if UseEmOnOff == false then self.UseEmOnOff = UseEmOnOff end - self:I("*** SHORAD - Started Version 0.3.4") + + if SmokeDecoy then + self.SmokeDecoy = SmokeDecoy + self.SmokeDecoyColor = SmokeDecoyColor or SMOKECOLOR.White + end + + self:I("*** SHORAD - Started Version 0.3.5") -- Set the string id for output to DCS.log file. self.lid=string.format("SHORAD %s | ", self.name) self:_InitState() @@ -451,6 +465,32 @@ do return returnname end + --- Smoke a SHORAD Group + -- @param #SHORAD self + -- @param Wrapper.Group#GROUP Group The Shorad Group to Smoke + -- @return self + function SHORAD:_SmokeUnits(Group) + if self.SmokeDecoy == true then + if Group and Group:IsAlive() then + local units = Group:GetUnits() + for _,_unit in pairs(units) do + local unit = _unit -- Wrapper.Unit#UNIT + if unit and unit:IsAlive() then + local coordinate = unit:GetCoordinate() + if coordinate then + coordinate:SwitchSmokeOffsetOn() + coordinate:Smoke(self.SmokeDecoyColor,Duration,nil,Name,true,1,20) + coordinate:Smoke(self.SmokeDecoyColor,Duration,nil,Name,true,180,20) + coordinate:Smoke(self.SmokeDecoyColor,Duration,nil,Name,true,270,20) + coordinate:Smoke(self.SmokeDecoyColor,Duration,nil,Name,true,90,20) + end + end + end + end + end + return self + end + --- Calculate if the missile shot is detected -- @param #SHORAD self -- @return #boolean Returns true for a detection, else false @@ -537,7 +577,7 @@ do local text = string.format("Shot at SHORAD %s! Evading!", _group:GetName()) self:T(text) local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug) - + self:_SmokeUnits(_group) --Shoot and Scoot if self.shootandscoot then self:__ShootAndScoot(1,_group) @@ -552,6 +592,7 @@ do _group:EnableEmission(true) end _group:OptionAlarmStateRed() + self:_SmokeUnits(_group) if self.ActiveGroups[groupname] == nil then -- no timer yet for this group self.ActiveGroups[groupname] = { Timing = ActiveTimer } local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit diff --git a/Moose Development/Moose/Ops/Intelligence.lua b/Moose Development/Moose/Ops/Intelligence.lua index 73e89134a..c47b35421 100644 --- a/Moose Development/Moose/Ops/Intelligence.lua +++ b/Moose Development/Moose/Ops/Intelligence.lua @@ -41,7 +41,7 @@ -- @field #number statusupdate Time interval in seconds after which the status is refreshed. Default 60 sec. Should be negative. -- @field #boolean DetectAccoustic If true, also detect by sound (ie proximity). -- @field #number DetectAccousticRadius Radius dfor accoustic detection, defaults to 2000 meters. --- @field #table DetectAccousticUnitTypes Types of units we can detect accousticly. Defaults to {Unit.Category.GROUND_UNIT,Unit.Category.HELICOPTER} +-- @field #table DetectAccousticUnitTypes Types of units we can detect accousticly. Defaults to {Unit.Category.HELICOPTER} -- @extends Core.Fsm#FSM --- Top Secret! @@ -107,7 +107,7 @@ INTEL = { detectStatics = false, DetectAccoustic = false, DetectAccousticRadius = 1000, - DetectAccousticUnitTypes = {Unit.Category.GROUND_UNIT,Unit.Category.HELICOPTER}, + DetectAccousticUnitTypes = {Unit.Category.HELICOPTER}, } --- Detected item info. @@ -412,7 +412,7 @@ end function INTEL:SetAccousticDetectionOn(Radius,UnitCategories) self.DetectAccoustic = true self.DetectAccousticRadius = Radius or 1000 - self.DetectAccousticUnitTypes = UnitCategories or {Unit.Category.GROUND_UNIT,Unit.Category.HELICOPTER} + self.DetectAccousticUnitTypes = UnitCategories or {Unit.Category.HELICOPTER} return self end @@ -865,7 +865,7 @@ function INTEL:UpdateIntel() detectionzone = ZONE_GROUP:New(group.IdentifiableName.."INTEL_DETECT_ACCZONE",group,self.DetectAccousticRadius or 2000) group:SetProperty("INTEL_DETECT_ACCZONE",detectionzone) end - if recce then + if recce and recce:IsGround() then self:GetDetectedUnitsAccoustic(recce,DetectedUnits,RecceDetecting,detectionzone) end end @@ -1252,18 +1252,18 @@ function INTEL:GetDetectedUnitsAccoustic(Recce,DetectedUnits,RecceDetecting,dete if detectionzone then -- Get detected units local reccename = Recce:GetName() - detectionzone:Scan({Object.Category.UNIT},self.DetectAccousticUnitTypes) + local DetectAccousticUnitTypes = self.DetectAccousticUnitTypes or {Unit.Category.HELICOPTER} + detectionzone:Scan({Object.Category.UNIT},DetectAccousticUnitTypes) local unitset = detectionzone:GetScannedSetUnit(othercoalition) -- Core.Set#SET_UNIT self:T("Accoustic detection found #Units "..unitset:CountAlive()) for _,_unit in pairs(unitset.Set or {}) do - if _unit and _unit:IsAlive() then + if _unit and _unit:IsAlive() and _unit:GetCoalition() ~= self.coalition then local name = _unit:GetName() or "none" DetectedUnits[name]=_unit RecceDetecting[name]=reccename self:T("Unit name = "..name) end end - unitset = nil end end