diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 964f8e1ee..7f2b3d558 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -970,6 +970,9 @@ do -- COORDINATE if not TargetCoordinate then return 1000000 end --local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z} local a = self:GetVec2() + if not TargetCoordinate.ClassName then + TargetCoordinate=COORDINATE:NewFromVec3(TargetCoordinate) + end local b = TargetCoordinate:GetVec2() local norm=UTILS.VecDist2D(a,b) return norm diff --git a/Moose Development/Moose/Functional/Mantis.lua b/Moose Development/Moose/Functional/Mantis.lua index 0124af4ba..28f511a91 100644 --- a/Moose Development/Moose/Functional/Mantis.lua +++ b/Moose Development/Moose/Functional/Mantis.lua @@ -60,6 +60,8 @@ -- @field #number ShoradActDistance Distance of an attacker in meters from a Mantis SAM site, on which Shorad will be switched on. Useful to not give away Shorad sites too early. Default 15km. Should be smaller than checkradius. -- @field #boolean checkforfriendlies If true, do not activate a SAM installation if a friendly aircraft is in firing range. -- @field #table FilterZones Table of Core.Zone#ZONE Zones Consider SAM groups in this zone(s) only for this MANTIS instance, must be handed as #table of Zone objects. +-- @field #boolean SmokeDecoy If true, smoke short range SAM units as decoy if a plane is in firing range. +-- @field #number SmokeDecoyColor Color to use, defaults to SMOKECOLOR.White -- @extends Core.Base#BASE @@ -329,6 +331,8 @@ MANTIS = { autoshorad = true, ShoradGroupSet = nil, checkforfriendlies = false, + SmokeDecoy = false, + SmokeDecoyColor = SMOKECOLOR.White, } --- Advanced state enumerator @@ -590,7 +594,10 @@ do self.SkateZones = nil self.SkateNumber = 3 - self.shootandscoot = false + self.shootandscoot = false + + self.SmokeDecoy = false + self.SmokeDecoyColor = SMOKECOLOR.White self.UseEmOnOff = true if EmOnOff == false then @@ -602,6 +609,7 @@ do else self.advAwacs = false end + -- Set the string id for output to DCS.log file. self.lid=string.format("MANTIS %s | ", self.name) @@ -663,7 +671,7 @@ do -- TODO Version -- @field #string version - self.version="0.8.22" + self.version="0.8.23" self:I(string.format("***** Starting MANTIS Version %s *****", self.version)) --- FSM Functions --- @@ -899,6 +907,16 @@ do return self end + --- Function to set Short Range SAMs to spit out smoke as decoy, if an enemy plane is in range. + -- @param #MANTIS self + -- @param #boolean Onoff Set to true for on and nil/false for off. + -- @param #number Color (Optional) Color to use, defaults to `SMOKECOLOR.White` + function MANTIS:SetSmokeDecoy(Onoff,Color) + self.SmokeDecoy = Onoff + self.SmokeDecoyColor = Color or SMOKECOLOR.White + return self + end + --- Function to set number of SAMs going active on a valid, detected thread -- @param #MANTIS self -- @param #number Short Number of short-range systems activated, defaults to 1. @@ -1550,18 +1568,18 @@ do local grpname = group:GetName() local grpcoord = group:GetCoordinate() local grprange,grpheight,type,blind = self:_GetSAMRange(grpname) - table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind}) + table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) --table.insert( SEAD_Grps, grpname ) if type == MANTIS.SamType.LONG then - table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind}) + table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind, type}) table.insert( SEAD_Grps, grpname ) --self:T("SAM "..grpname.." is type LONG") elseif type == MANTIS.SamType.MEDIUM then - table.insert( SAM_Tbl_md, {grpname, grpcoord, grprange, grpheight, blind}) + table.insert( SAM_Tbl_md, {grpname, grpcoord, grprange, grpheight, blind, type}) table.insert( SEAD_Grps, grpname ) --self:T("SAM "..grpname.." is type MEDIUM") elseif type == MANTIS.SamType.SHORT then - table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind}) + table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind, type}) --self:T("SAM "..grpname.." is type SHORT") self.ShoradGroupSet:Add(grpname,group) if not self.autoshorad then @@ -1609,16 +1627,16 @@ do local grpname = group:GetName() local grpcoord = group:GetCoordinate() local grprange, grpheight,type,blind = self:_GetSAMRange(grpname) - table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind}) -- make the table lighter, as I don't really use the zone here + table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) -- make the table lighter, as I don't really use the zone here table.insert( SEAD_Grps, grpname ) if type == MANTIS.SamType.LONG then - table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind}) + table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind, type}) --self:I({grpname,grprange, grpheight}) elseif type == MANTIS.SamType.MEDIUM then - table.insert( SAM_Tbl_md, {grpname, grpcoord, grprange, grpheight, blind}) + table.insert( SAM_Tbl_md, {grpname, grpcoord, grprange, grpheight, blind, type}) --self:I({grpname,grprange, grpheight}) elseif type == MANTIS.SamType.SHORT then - table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind}) + table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind, type}) --self:I({grpname,grprange, grpheight}) self.ShoradGroupSet:Add(grpname,group) if self.autoshorad then @@ -1688,6 +1706,7 @@ do local radius = _data[3] local height = _data[4] local blind = _data[5] * 1.25 + 1 + local shortsam = _data[6] == MANTIS.SamType.SHORT and true or false local samgroup = GROUP:FindByName(name) local IsInZone, Distance = self:_CheckObjectInZone(detset, samcoordinate, radius, height, dlink) local suppressed = self.SuppressedGroups[name] or false @@ -1713,6 +1732,16 @@ do self:__RedState(1,samgroup) self.SamStateTracker[name] = "RED" end + if shortsam == true and self.SmokeDecoy == true then + self:I("Smoking") + local units = samgroup:GetUnits() or {} + local smoke = self.SmokeDecoyColor or SMOKECOLOR.White + for _,unit in pairs(units) do + if unit and unit:IsAlive() then + unit:GetCoordinate():Smoke(smoke) + end + end + end -- link in to SHORAD if available -- DONE: Test integration fully if self.ShoradLink and (Distance < self.ShoradActDistance or Distance < blind ) then -- don't give SHORAD position away too early diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index 4bf18ac40..8cc55125c 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -31,7 +31,7 @@ -- @image OPS_CSAR.jpg --- --- Last Update Sep 2024 +-- Last Update Jan 2025 ------------------------------------------------------------------------- --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM @@ -92,7 +92,7 @@ -- mycsar.immortalcrew = true -- Set to true to make wounded crew immortal. -- mycsar.invisiblecrew = false -- Set to true to make wounded crew insvisible. -- mycsar.loadDistance = 75 -- configure distance for pilots to get into helicopter in meters. --- mycsar.mashprefix = {"MASH"} -- prefixes of #GROUP objects used as MASHes. +-- mycsar.mashprefix = {"MASH"} -- prefixes of #GROUP objects used as MASHes. Will also try to add ZONE and STATIC objects with this prefix once at startup. -- mycsar.max_units = 6 -- max number of pilots that can be carried if #CSAR.AircraftType is undefined. -- mycsar.messageTime = 15 -- Time to show messages for in seconds. Doubled for long messages. -- mycsar.radioSound = "beacon.ogg" -- the name of the sound file to use for the pilots\' radio beacons. @@ -313,7 +313,7 @@ CSAR.AircraftType["CH-47Fbl1"] = 31 --- CSAR class version. -- @field #string version -CSAR.version="1.0.29" +CSAR.version="1.0.30" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -2425,7 +2425,22 @@ function CSAR:onafterStart(From, Event, To) self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart() end - self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also? + self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() + + local staticmashes = SET_STATIC:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterOnce() + local zonemashes = SET_ZONE:New():FilterPrefixes(self.mashprefix):FilterOnce() + + if staticmashes:Count() > 0 then + for _,_mash in pairs(staticmashes.Set) do + self.mash:AddObject(_mash) + end + end + + if zonemashes:Count() > 0 then + for _,_mash in pairs(zonemashes.Set) do + self.mash:AddObject(_mash) + end + end if not self.coordinate then local csarhq = self.mash:GetRandom()