From 4c52509d6d57f8c58bfa6dcd5b7561ba83e5b383 Mon Sep 17 00:00:00 2001 From: Rolln Date: Sat, 4 Jan 2025 11:06:39 -0700 Subject: [PATCH 1/3] ENHANCEMENT: Adds a ceiling to the range. --- Moose Development/Moose/Functional/Range.lua | 45 +++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua index 05ec5e895..abc7f8b28 100644 --- a/Moose Development/Moose/Functional/Range.lua +++ b/Moose Development/Moose/Functional/Range.lua @@ -107,6 +107,9 @@ -- @field Sound.SRS#MSRSQUEUE instructsrsQ SRS queue for range instructor. -- @field #number Coalition Coalition side for the menu, if any. -- @field Core.Menu#MENU_MISSION menuF10root Specific user defined root F10 menu. +-- @field #number ceilingaltitude Range ceiling altitude in ft MSL. Aircraft above this altitude are not considered to be in the range. Default is 20000 ft. +-- @field #boolean ceilingenabled Range has a ceiling and is not unlimited. Default is false. + -- @extends Core.Fsm#FSM --- *Don't only practice your art, but force your way into its secrets; art deserves that, for it and knowledge can raise man to the Divine.* - Ludwig van Beethoven @@ -273,6 +276,10 @@ -- -- Create a range object. -- GoldwaterRange=RANGE:New("Goldwater Range") -- +-- -- Set and enable the range ceiling altitude in feet MSL. If aircraft are above this altitude they are not considered to be in the range. +-- GoldwaterRange:SetRangeCeiling(20000) +-- GoldwaterRange:EnableRangeCeiling(true) +-- -- -- Distance between strafe target and foul line. You have to specify the names of the unit or static objects. -- -- Note that this could also be done manually by simply measuring the distance between the target and the foul line in the ME. -- GoldwaterRange:GetFoullineDistance("GWR Strafe Pit Left 1", "GWR Foul Line Left") @@ -358,6 +365,8 @@ RANGE = { targetpath = nil, targetprefix = nil, Coalition = nil, + ceilingaltitude = 20000, + ceilingenabled = false, } --- Default range parameters. @@ -1085,6 +1094,37 @@ function RANGE:SetRangeZone( zone ) return self end +--- Set range ceiling altitude in feet MSL. +-- @param #RANGE self +-- @param #number ceiling (optional) Ceiling altitude of the range in ft MSL. Default 20000ft MSL +-- @return #RANGE self +function RANGE:SetRangeCeiling( alt ) + self:T(self.lid.."SetRangeCeiling") + if alt and type(alt) == "number" then + self.ceilingaltitude=alt + else + self:E(self.lid.."Altitude either not provided or is not a number, using default setting (20000).") + self.ceilingaltitude=20000 + end + return self +end + +--- Enable range ceiling. Aircraft must be below the ceiling altitude to be considered in the range zone. +-- @param #RANGE self +-- @param #boolean enabled True if you would like to enable the ceiling check. If no value give, will Default to false. +-- @return #RANGE self +function RANGE:EnableRangeCeiling( enabled ) + self:T(self.lid.."EnableRangeCeiling") + if enabled and type(enabled) == "boolean" then + self.ceilingenabled=enabled + else + self:E(self.lid.."Enabled either not provide or is not a boolean, using default setting (false).") + self.ceilingenabled=false + end + + return self +end + --- Set smoke color for marking bomb targets. By default bomb targets are marked by red smoke. -- @param #RANGE self -- @param Utilities.Utils#SMOKECOLOR colorid Color id. Default `SMOKECOLOR.Red`. @@ -3112,7 +3152,10 @@ function RANGE:_CheckPlayers() if unit and unit:IsAlive() then - if unit:IsInZone( self.rangezone ) then + local unitalt = unit:GetAltitude(false) + local unitaltinfeet = UTILS.MetersToFeet(unitalt) + + if unit:IsInZone(self.rangezone) and (not self.ceilingenabled or unitaltinfeet < self.ceilingaltitude) then ------------------------------ -- Player INSIDE Range Zone -- From 8523b7e20a399aa296121f0a86886469c1a1c509 Mon Sep 17 00:00:00 2001 From: Shafik Date: Sun, 5 Jan 2025 10:47:14 +0200 Subject: [PATCH 2/3] [FIXED] `attempt to call method 'GetPlayerName' (a nil value)` --- Moose Development/Moose/Functional/CleanUp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Functional/CleanUp.lua b/Moose Development/Moose/Functional/CleanUp.lua index 6bf5228f0..14616331f 100644 --- a/Moose Development/Moose/Functional/CleanUp.lua +++ b/Moose Development/Moose/Functional/CleanUp.lua @@ -411,7 +411,7 @@ function CLEANUP_AIRBASE.__:CleanUpSchedule() end end -- Clean Units which are waiting for a very long time in the CleanUpZone. - if CleanUpUnit and not CleanUpUnit:GetPlayerName() then + if CleanUpUnit and (CleanUpUnit.GetPlayerName == nil or not CleanUpUnit:GetPlayerName()) then local CleanUpUnitVelocity = CleanUpUnit:GetVelocityKMH() if CleanUpUnitVelocity < 1 then if CleanUpListData.CleanUpMoved then From e86069d39c19392e213aacadf3e90135e813731a Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 5 Jan 2025 17:43:12 +0100 Subject: [PATCH 3/3] Smaller updates --- Moose Development/Moose/Core/Point.lua | 3 ++ Moose Development/Moose/Functional/Mantis.lua | 49 +++++++++++++++---- Moose Development/Moose/Ops/CSAR.lua | 23 +++++++-- 3 files changed, 61 insertions(+), 14 deletions(-) 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()