From 35f15435a3a77e39d9e26a3f1f157f8681c6005d Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 14 Aug 2025 09:12:58 +0200 Subject: [PATCH 1/5] #MANTIS - Added Pantsir S1, TOR M2, IRIS-T SLM to main man SAM data (from CH mod) --- Moose Development/Moose/Functional/Mantis.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Moose Development/Moose/Functional/Mantis.lua b/Moose Development/Moose/Functional/Mantis.lua index cd3ee9cae..67816cf04 100644 --- a/Moose Development/Moose/Functional/Mantis.lua +++ b/Moose Development/Moose/Functional/Mantis.lua @@ -108,6 +108,10 @@ -- * Patriot -- * Rapier -- * Roland +-- * IRIS-T SLM +-- * Pantsir S1 +-- * TOR M2 +-- * C-RAM -- * Silkworm (though strictly speaking this is a surface to ship missile) -- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19 -- * From IDF mod: STUNNER IDFA, TAMIR IDFA (Note all caps!) @@ -276,7 +280,7 @@ MANTIS = { ClassName = "MANTIS", name = "mymantis", - version = "0.9.33", + version = "0.9.34", SAM_Templates_Prefix = "", SAM_Group = nil, EWR_Templates_Prefix = "", @@ -385,7 +389,7 @@ MANTIS.SamData = { ["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" }, ["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Linebacker", Point="true" }, ["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" }, - ["HEMTT_C-RAM_Phalanx"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="HEMTT_C-RAM_Phalanx", Point="true" }, + ["C-RAM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="HEMTT_C-RAM_Phalanx", Point="true" }, -- units from HDS Mod, multi launcher options is tricky ["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"}, ["SA-17"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17" }, @@ -396,6 +400,10 @@ MANTIS.SamData = { ["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" }, ["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="Short", Radar="PantsirS1" }, + ["Tor M2"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" }, + ["IRIS-T SLM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM" }, } --- SAM data HDS @@ -1288,7 +1296,7 @@ do end end -- rejectzones - if #self.RejectZones > 0 and inzone then -- maybe in accept zone, but check the overlaps + if #self.RejectZones > 0 then for _,_zone in pairs(self.RejectZones) do local zone = _zone -- Core.Zone#ZONE if zone:IsCoordinateInZone(coord) then @@ -1299,7 +1307,7 @@ do end end -- conflictzones - if #self.ConflictZones > 0 and not inzone then -- if not already accepted, might be in conflict zones + if #self.ConflictZones > 0 then for _,_zone in pairs(self.ConflictZones) do local zone = _zone -- Core.Zone#ZONE if zone:IsCoordinateInZone(coord) then From 4a04d7cce7b178ff4ea48cb480d705a331e2030e Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 14 Aug 2025 17:15:43 +0200 Subject: [PATCH 2/5] xx --- Moose Development/Moose/Functional/Mantis.lua | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/Moose Development/Moose/Functional/Mantis.lua b/Moose Development/Moose/Functional/Mantis.lua index 67816cf04..9714fbe80 100644 --- a/Moose Development/Moose/Functional/Mantis.lua +++ b/Moose Development/Moose/Functional/Mantis.lua @@ -22,7 +22,7 @@ -- @module Functional.Mantis -- @image Functional.Mantis.jpg -- --- Last Update: July 2025 +-- Last Update: August 2025 ------------------------------------------------------------------------- --- **MANTIS** class, extends Core.Base#BASE @@ -308,7 +308,7 @@ MANTIS = { adv_state = 0, AWACS_Prefix = "", advAwacs = false, - verbose = false, + verbose = true, awacsrange = 250000, Shorad = nil, ShoradLink = false, @@ -401,8 +401,8 @@ MANTIS.SamData = { ["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="Short", Radar="PantsirS1" }, - ["Tor M2"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" }, + ["Pantsir S1"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1" , Point="true" }, + ["Tor M2"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true" }, ["IRIS-T SLM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM" }, } @@ -469,15 +469,15 @@ MANTIS.SamDataCH = { -- https://www.currenthill.com/ -- group name MUST contain CHM to ID launcher type correctly! ["2S38 CHM"] = { Range=6, Blindspot=0.1, Height=4.5, Type="Short", Radar="2S38" }, - ["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" }, + ["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1", Point="true" }, ["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" }, ["PGL-625 CHM"] = { Range=10, Blindspot=1, Height=5, Type="Short", Radar="PGL_625" }, ["HQ-17A CHM"] = { Range=15, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" }, ["M903PAC2 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" }, ["M903PAC3 CHM"] = { Range=160, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" }, - ["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" }, - ["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" }, - ["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" }, + ["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true" }, + ["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2K", Point="true" }, + ["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Point", Radar="TorM2M", Point="true" }, ["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" }, ["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" }, ["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" }, @@ -583,7 +583,7 @@ do self.advanced = false self.adv_ratio = 100 self.adv_state = 0 - self.verbose = false + self.verbose = true self.Adv_EWR_Group = nil self.AWACS_Prefix = awacs or nil self.awacsrange = 250000 --DONE: 250km, User Function to change @@ -893,7 +893,11 @@ do self.AcceptZones = AcceptZones or {} self.RejectZones = RejectZones or {} self.ConflictZones = ConflictZones or {} - if #self.AcceptZones > 0 or #self.RejectZones > 0 or #self.ConflictZones > 0 then + self.AcceptZonesNo = UTILS.TableLength(self.AcceptZones) + self.RejectZonesNo = UTILS.TableLength(self.RejectZones) + self.ConflictZonesNo = UTILS.TableLength(self.ConflictZones) + self:T(string.format("AcceptZonesNo = %d | RejectZonesNo = %d | ConflictZonesNo = %d",self.AcceptZonesNo,self.RejectZonesNo,self.ConflictZonesNo)) + if self.AcceptZonesNo > 0 or self.RejectZonesNo > 0 or self.ConflictZonesNo > 0 then self.usezones = true end return self @@ -1285,7 +1289,8 @@ do self:T(self.lid.."_CheckCoordinateInZones") local inzone = false -- acceptzones - if #self.AcceptZones > 0 then + self:T(string.format("AcceptZonesNo = %d | RejectZonesNo = %d | ConflictZonesNo = %d",self.AcceptZonesNo,self.RejectZonesNo,self.ConflictZonesNo)) + if self.AcceptZonesNo > 0 then for _,_zone in pairs(self.AcceptZones) do local zone = _zone -- Core.Zone#ZONE if zone:IsCoordinateInZone(coord) then @@ -1296,7 +1301,7 @@ do end end -- rejectzones - if #self.RejectZones > 0 then + if self.RejectZonesNo > 0 then for _,_zone in pairs(self.RejectZones) do local zone = _zone -- Core.Zone#ZONE if zone:IsCoordinateInZone(coord) then @@ -1307,7 +1312,7 @@ do end end -- conflictzones - if #self.ConflictZones > 0 then + if self.ConflictZonesNo > 0 then for _,_zone in pairs(self.ConflictZones) do local zone = _zone -- Core.Zone#ZONE if zone:IsCoordinateInZone(coord) then @@ -1373,6 +1378,7 @@ do end -- check accept/reject zones local zonecheck = true + self:T("self.usezones = "..tostring(self.usezones)) if self.usezones then -- DONE zonecheck = self:_CheckCoordinateInZones(coord) From b9cf1e46afcee679aa09b480d3451864da72a5e3 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 14 Aug 2025 17:17:34 +0200 Subject: [PATCH 3/5] xx --- Moose Development/Moose/Functional/Mantis.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Functional/Mantis.lua b/Moose Development/Moose/Functional/Mantis.lua index 9714fbe80..2e1ff3b18 100644 --- a/Moose Development/Moose/Functional/Mantis.lua +++ b/Moose Development/Moose/Functional/Mantis.lua @@ -308,7 +308,7 @@ MANTIS = { adv_state = 0, AWACS_Prefix = "", advAwacs = false, - verbose = true, + verbose = false, awacsrange = 250000, Shorad = nil, ShoradLink = false, @@ -583,7 +583,7 @@ do self.advanced = false self.adv_ratio = 100 self.adv_state = 0 - self.verbose = true + self.verbose = false self.Adv_EWR_Group = nil self.AWACS_Prefix = awacs or nil self.awacsrange = 250000 --DONE: 250km, User Function to change From 67cb84455029531efe460e3b2e664c23ae07befb Mon Sep 17 00:00:00 2001 From: smiki Date: Sun, 24 Aug 2025 15:07:27 +0200 Subject: [PATCH 4/5] Validate and Reposition Ground Units algorithm [ADDED] UTILS.ValidateAndRepositionGroundUnits [ADDED] SPAWN:InitValidateAndRepositionGroundUnits [ADDED] CTLD.validateAndRepositionUnits --- Moose Development/Moose/Core/Spawn.lua | 24 +++- Moose Development/Moose/Ops/CTLD.lua | 8 +- Moose Development/Moose/Utilities/Utils.lua | 121 ++++++++++++++++++++ 3 files changed, 151 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index c81aea59d..6e95e285b 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -1049,6 +1049,22 @@ function SPAWN:InitSetUnitAbsolutePositions(Positions) return self end + +--- Uses Disposition and other fallback logic to find better ground positions for ground units. +--- NOTE: This is not a spawn randomizer. +--- It will try to find clear ground locations avoiding trees, water, roads, runways, map scenery, statics and other units in the area. +--- Maintains the original layout and unit positions as close as possible by searching for the next closest valid position to each unit. +-- @param #boolean OnOff Enable/disable the feature. +-- @param #number MaxRadius (Optional) Max radius to search for valid ground locations in meters. Default is double the max radius of the units. +-- @param #number Spacing (Optional) Minimum spacing between units in meters. Default is 5% of the search radius or 5 meters, whichever is larger. +-- @return #SPAWN +function SPAWN:InitValidateAndRepositionGroundUnits(OnOff, MaxRadius, Spacing) + self.SpawnValidateAndRepositionGroundUnits = OnOff + self.SpawnValidateAndRepositionGroundUnitsRadius = MaxRadius + self.SpawnValidateAndRepositionGroundUnitsSpacing = Spacing + return self +end + --- This method is rather complicated to understand. But I'll try to explain. -- This method becomes useful when you need to spawn groups with random templates of groups defined within the mission editor, -- but they will all follow the same Template route and have the same prefix name. @@ -1829,7 +1845,13 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth ) if self.SpawnHiddenOnMap then SpawnTemplate.hidden=self.SpawnHiddenOnMap end - + + if self.SpawnValidateAndRepositionGroundUnits then + local units = SpawnTemplate.units + local gPos = { x = SpawnTemplate.x, y = SpawnTemplate.y } + UTILS.ValidateAndRepositionGroundUnits(gPos, units, self.SpawnValidateAndRepositionGroundUnitsRadius, self.SpawnValidateAndRepositionGroundUnitsSpacing) + end + -- Set country, coalition and category. SpawnTemplate.CategoryID = self.SpawnInitCategory or SpawnTemplate.CategoryID SpawnTemplate.CountryID = self.SpawnInitCountry or SpawnTemplate.CountryID diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 7b46d1439..40f2dc8e3 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -1564,7 +1564,9 @@ function CTLD:New(Coalition, Prefixes, Alias) self.FixedMinAngels = 165 -- for troop/cargo drop via chute self.FixedMaxAngels = 2000 -- for troop/cargo drop via chute self.FixedMaxSpeed = 77 -- 280 kph or 150kn eq 77 mps - + + self.validateAndRepositionUnits = false -- 280 kph or 150kn eq 77 mps + -- message suppression self.suppressmessages = false @@ -3735,6 +3737,7 @@ function CTLD:_UnloadTroops(Group, Unit) self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias) :InitDelayOff() :InitSetUnitAbsolutePositions(Positions) + :InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits) :OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end) :SpawnFromVec2(randomcoord:GetVec2()) self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter],type) @@ -4181,11 +4184,13 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation,Mult self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias) --:InitRandomizeUnits(true,20,2) :InitDelayOff() + :InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits) :OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end) :SpawnFromVec2(randomcoord) else -- don't random position of e.g. SAM units build as FOB self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias) :InitDelayOff() + :InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits) :OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end) :SpawnFromVec2(randomcoord) end @@ -5211,6 +5216,7 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID) self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template, alias) :InitDelayOff() :InitSetUnitAbsolutePositions(Positions) + :InitValidateAndRepositionGroundUnits(self.validateAndRepositionUnits) :OnSpawnGroup(function(grp) grp.spawntime = timer.getTime() end) :SpawnFromVec2(randomcoord:GetVec2()) self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter], cType) diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index a9a76d535..c7543b3a2 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -4871,3 +4871,124 @@ function UTILS.FindNearestPointOnCircle(Vec1,Radius,Vec2) return {x=qx, y=qy} end + +--- This function uses Disposition and other fallback logic to find better ground positions for a group of ground units. +--- NOTE: This is not a spawn randomizer. +--- It will try to find clear ground locations avoiding trees, water, roads, runways, map scenery, statics and other units in the area and modifies the provided positions table. +--- Maintains the original layout and unit positions as close as possible by searching for the next closest valid position to each unit. +-- @param table Positions A table of DCS#Vec2 or DCS#Vec3, can be a units table from the group template. +-- @param DCS#Vec2 Anchor (Optional) DCS#Vec2 or DCS#Vec3 as anchor point to calculate offset of the units. +-- @param #number MaxRadius (Optional) Max radius to search for valid ground locations in meters. Default is double the max radius of the units. +-- @param #number Spacing (Optional) Minimum spacing between units in meters. Default is 5% of the search radius or 5 meters, whichever is larger. +function UTILS.ValidateAndRepositionGroundUnits(Anchor, Positions, MaxRadius, Spacing) + local units = Positions + Anchor = Anchor or UTILS.GetCenterPoint(units) + local gPos = { x = Anchor.x, y = Anchor.z or Anchor.y } + local maxRadius = 0 + local unitCount = 0 + for _, unit in pairs(units) do + local pos = { x = unit.x, y = unit.z or unit.y } + local dist = UTILS.VecDist2D(pos, gPos) + if dist > maxRadius then + maxRadius = dist + end + unitCount = unitCount + 1 + end + maxRadius = MaxRadius or math.max(maxRadius * 2, 10) + local spacing = Spacing or math.max(maxRadius * 0.05, 5) + if unitCount > 0 and maxRadius > 5 then + local spots = UTILS.GetSimpleZones(UTILS.Vec2toVec3(gPos), maxRadius, spacing, 1000) + if spots and #spots > 0 then + local validSpots = {} + for _, spot in pairs(spots) do -- Disposition sometimes returns points on roads, hence this filter. + if land.getSurfaceType(spot) == land.SurfaceType.LAND then + table.insert(validSpots, spot) + end + end + spots = validSpots + end + + local step = spacing + for _, unit in pairs(units) do + local pos = { x = unit.x, y = unit.z or unit.y } + local isOnLand = land.getSurfaceType(pos) == land.SurfaceType.LAND + local isValid = false + if spots and #spots > 0 then + local si = 1 + local sid = 0 + local closestDist = 100000000 + local closestSpot + for _, spot in pairs(spots) do + local dist = UTILS.VecDist2D(pos, spot) + if dist < closestDist then + local skip = false + for _, unit2 in pairs(units) do + local pos2 = { x = unit2.x, y = unit2.z or unit2.y } + local dist2 = UTILS.VecDist2D(spot, pos2) + if dist2 < spacing and isOnLand then + skip = true + break + end + end + if not skip then + closestDist = dist + closestSpot = spot + sid = si + end + end + si = si + 1 + end + if closestSpot then + if closestDist >= spacing then + pos = closestSpot + end + isValid = true + table.remove(spots, sid) + end + end + + -- Failsafe calculation + if not isValid and not isOnLand then + + local h = UTILS.HdgTo(pos, gPos) + local retries = 0 + while not isValid and retries < 500 do + + local dist = UTILS.VecDist2D(pos, gPos) + pos = UTILS.Vec2Translate(pos, step, h) + + local skip = false + for _, unit2 in pairs(units) do + if unit ~= unit2 then + local pos2 = { x = unit2.x, y = unit2.z or unit2.y } + local dist2 = UTILS.VecDist2D(pos, pos2) + if dist2 < 12 then + isValid = false + skip = true + break + end + end + end + + if not skip and dist > step and land.getSurfaceType(pos) == land.SurfaceType.LAND then + isValid = true + break + elseif dist <= step then + break + end + + retries = retries + 1 + end + end + + if isValid then + unit.x = pos.x + if unit.z then + unit.z = pos.y + else + unit.y = pos.y + end + end + end + end +end From 78b3efcf0095044067eda0838604f5a929d0a9d9 Mon Sep 17 00:00:00 2001 From: smiki Date: Sun, 24 Aug 2025 15:10:47 +0200 Subject: [PATCH 5/5] Validate and Reposition Ground Units algorithm [ADDED] UTILS.ValidateAndRepositionGroundUnits [ADDED] SPAWN:InitValidateAndRepositionGroundUnits [ADDED] CTLD.validateAndRepositionUnits --- Moose Development/Moose/Ops/CTLD.lua | 3 ++- Moose Development/Moose/Utilities/Utils.lua | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 40f2dc8e3..6b1bb8d60 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -868,7 +868,8 @@ do -- my_ctld.showstockinmenuitems = false -- When set to true, the menu lines will also show the remaining items in stock (that is, if you set any), downside is that the menu for all will be build every 30 seconds anew. -- my_ctld.onestepmenu = false -- When set to true, the menu will create Drop and build, Get and load, Pack and remove, Pack and load, Pack. it will be a 1 step solution. -- my_ctld.VehicleMoveFormation = AI.Task.VehicleFormation.VEE -- When a group moves to a MOVE zone, then it takes this formation. Can be a table of formations, which are then randomly chosen. Defaults to "Vee". --- +-- my_ctld.validateAndRepositionUnits = false -- Uses Disposition and other logic to find better ground positions for ground units avoiding trees, water, roads, runways, map scenery, statics and other units in the area. (Default is false) +-- -- ## 2.1 CH-47 Chinook support -- -- The Chinook comes with the option to use the ground crew menu to load and unload cargo into the Helicopter itself for better immersion. As well, it can sling-load cargo from ground. The cargo you can actually **create** diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index c7543b3a2..bdbff6b38 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -4872,7 +4872,7 @@ function UTILS.FindNearestPointOnCircle(Vec1,Radius,Vec2) return {x=qx, y=qy} end ---- This function uses Disposition and other fallback logic to find better ground positions for a group of ground units. +--- This function uses Disposition and other fallback logic to find better ground positions for ground units. --- NOTE: This is not a spawn randomizer. --- It will try to find clear ground locations avoiding trees, water, roads, runways, map scenery, statics and other units in the area and modifies the provided positions table. --- Maintains the original layout and unit positions as close as possible by searching for the next closest valid position to each unit.