diff --git a/Moose_CTLD_Pure/Moose_CTLD.lua b/Moose_CTLD_Pure/Moose_CTLD.lua index 3c864f3..684a442 100644 --- a/Moose_CTLD_Pure/Moose_CTLD.lua +++ b/Moose_CTLD_Pure/Moose_CTLD.lua @@ -28,6 +28,7 @@ CTLD.Config = { }, UseGroupMenus = true, -- if true, F10 menus per player group; otherwise coalition-wide UseCategorySubmenus = true, -- if true, organize crate requests by category submenu (menuCategory) + UseBuiltinCatalog = false, -- if false, starts with an empty catalog; intended when you preload a global catalog and want only that RestrictFOBToZones = false, -- if true, recipes marked isFOB only build inside configured FOBZones AutoBuildFOBInZones = false, -- if true, CTLD auto-builds FOB recipes when required crates are inside a FOB zone BuildRadius = 60, -- meters around build point to collect crates @@ -38,10 +39,21 @@ CTLD.Config = { Zones = { -- Optional: supply by name (ME trigger zones) or define coordinates inline PickupZones = { - -- examples: - -- { name = 'PICKUP_BLUE_MAIN' }, - -- { name = 'Pickup-West', smoke = trigger.smokeColor.Green }, - -- { coord = { x = 12345, y = 0, z = 67890 }, radius = 150, name = 'ScriptPickup1' }, + -- Examples: + -- Create 5 trigger zones in the Mission Editor named exactly as below to get started quickly. + -- If you run separate CTLD instances for BLUE and RED, give each side its own set of uniquely named zones + -- (recommended to avoid overlap). You can keep the simple "Pickup Zone #" pattern per side if you prefer, + -- just ensure the names in the ME match what you configure here. + -- + -- Uncomment the lines you want to use: + -- { name = 'Pickup Zone 1', smoke = trigger.smokeColor.Green }, + -- { name = 'Pickup Zone 2', smoke = trigger.smokeColor.Blue }, + -- { name = 'Pickup Zone 3', smoke = trigger.smokeColor.Orange }, + -- { name = 'Pickup Zone 4', smoke = trigger.smokeColor.White }, + -- { name = 'Pickup Zone 5', smoke = trigger.smokeColor.Red }, + -- + -- Tip: You can also define zones purely in script (no ME zone needed): + -- { coord = { x = 12345, y = 0, z = 67890 }, radius = 150, name = 'Pickup Zone 1' }, }, DropZones = { -- { name = 'DROP_BLUE_1' }, @@ -92,7 +104,7 @@ CTLD.Config = { end, }, -- Example: FARP/FOB build from 4 crates (spawns helipads + support statics/vehicles) - FOB = { + FOB = { description = '4x Crates -> FARP/FOB', weight = 500, dcsCargoType = 'container_cargo', @@ -100,7 +112,7 @@ CTLD.Config = { isFOB = true, -- mark as FOB recipe for zone restrictions/auto-build side = coalition.side.BLUE, category = Group.Category.GROUND, - build = function(point, headingDeg) + build = function(point, headingDeg, spawnSide) local heading = math.rad(headingDeg or 0) -- Spawn statics that provide FARP services local function addStatic(typeName, dx, dz, nameSuffix) @@ -111,7 +123,7 @@ CTLD.Config = { x = p.x, y = p.z, heading = heading, } - coalition.addStaticObject(coalition.side.BLUE, st) + coalition.addStaticObject(spawnSide or coalition.side.BLUE, st) end -- Common FARP layout addStatic('FARP', 0, 0, 'PAD') @@ -208,6 +220,33 @@ local function _vec3FromUnit(unit) return { x = p.x, y = p.y, z = p.z } end +-- Determine an approximate radius for a ZONE. Tries MOOSE radius, then trigger zone radius, then configured radius. +function CTLD:_getZoneRadius(zone) + if zone and zone.Radius then return zone.Radius end + local name = zone and zone.GetName and zone:GetName() or nil + if name and trigger and trigger.misc and trigger.misc.getZone then + local z = trigger.misc.getZone(name) + if z and z.radius then return z.radius end + end + if name and self._ZoneDefs and self._ZoneDefs.FOBZones and self._ZoneDefs.FOBZones[name] then + local d = self._ZoneDefs.FOBZones[name] + if d and d.radius then return d.radius end + end + return 150 +end + +-- Check if a 2D point (x,z) lies within any FOB zone; returns (bool, zone) +function CTLD:IsPointInFOBZones(point) + for _,z in ipairs(self.FOBZones or {}) do + local pz = z:GetPointVec3() + local r = self:_getZoneRadius(z) + local dx = (pz.x - point.x) + local dz = (pz.z - point.z) + if (dx*dx + dz*dz) <= (r*r) then return true, z end + end + return false, nil +end + -- ========================= -- Construction -- ========================= @@ -218,6 +257,24 @@ function CTLD:New(cfg) o.Side = o.Config.CoalitionSide o.MenuRoots = {} o.MenusByGroup = {} + + -- If caller disabled builtin catalog, clear it before merging any globals + if o.Config.UseBuiltinCatalog == false then + o.Config.CrateCatalog = {} + end + + -- If a global catalog was loaded earlier (via DO SCRIPT FILE), merge it automatically + -- Supported globals: _CTLD_EXTRACTED_CATALOG (our extractor), CTLD_CATALOG, MOOSE_CTLD_CATALOG + do + local globalsToCheck = { '_CTLD_EXTRACTED_CATALOG', 'CTLD_CATALOG', 'MOOSE_CTLD_CATALOG' } + for _,gn in ipairs(globalsToCheck) do + local t = rawget(_G, gn) + if type(t) == 'table' then + o:MergeCatalog(t) + if o.Config.Debug then env.info('[Moose_CTLD] Merged crate catalog from global '..gn) end + end + end + end o:InitZones() o:InitMenus() @@ -415,6 +472,12 @@ function CTLD:BuildAtGroup(group) local here = { x = p.x, z = p.z } local radius = self.Config.BuildRadius local nearby = self:GetNearbyCrates(here, radius) + -- filter crates to coalition side for this CTLD instance + local filtered = {} + for _,c in ipairs(nearby) do + if c.meta.side == self.Side then table.insert(filtered, c) end + end + nearby = filtered if #nearby == 0 then _msgGroup(group, 'No crates within '..radius..'m') return end -- Count by key @@ -437,24 +500,30 @@ function CTLD:BuildAtGroup(group) end end + local insideFOBZone, fz = self:IsPointInFOBZones(here) + local fobBlocked = false -- Try composite recipes first (requires is a map of key->qty) for recipeKey,cat in pairs(self.Config.CrateCatalog) do if type(cat.requires) == 'table' and cat.build then - local ok = true - for reqKey,qty in pairs(cat.requires) do - if (counts[reqKey] or 0) < qty then ok = false; break end - end - if ok then - local hdg = unit:GetHeading() - local gdata = cat.build({ x = here.x, z = here.z }, math.deg(hdg)) - local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata) - if g then - for reqKey,qty in pairs(cat.requires) do consumeCrates(reqKey, qty) end - _msgGroup(group, string.format('Built %s at your location', cat.description or recipeKey)) - return - else - _msgGroup(group, 'Build failed: DCS group spawn error') - return + if cat.isFOB and self.Config.RestrictFOBToZones and not insideFOBZone then + fobBlocked = true + else + local ok = true + for reqKey,qty in pairs(cat.requires) do + if (counts[reqKey] or 0) < qty then ok = false; break end + end + if ok then + local hdg = unit:GetHeading() + local gdata = cat.build({ x = here.x, z = here.z }, math.deg(hdg), cat.side or self.Side) + local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata) + if g then + for reqKey,qty in pairs(cat.requires) do consumeCrates(reqKey, qty) end + _msgGroup(group, string.format('Built %s at your location', cat.description or recipeKey)) + return + else + _msgGroup(group, 'Build failed: DCS group spawn error') + return + end end end end @@ -464,20 +533,29 @@ function CTLD:BuildAtGroup(group) for key,count in pairs(counts) do local cat = self.Config.CrateCatalog[key] if cat and cat.build and (not cat.requires) and count >= (cat.required or 1) then - local hdg = unit:GetHeading() - local gdata = cat.build({ x = here.x, z = here.z }, math.deg(hdg)) - local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata) - if g then - consumeCrates(key, cat.required or 1) - _msgGroup(group, string.format('Built %s at your location', cat.description or key)) - return + if cat.isFOB and self.Config.RestrictFOBToZones and not insideFOBZone then + fobBlocked = true else - _msgGroup(group, 'Build failed: DCS group spawn error') - return + local hdg = unit:GetHeading() + local gdata = cat.build({ x = here.x, z = here.z }, math.deg(hdg), cat.side or self.Side) + local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata) + if g then + consumeCrates(key, cat.required or 1) + _msgGroup(group, string.format('Built %s at your location', cat.description or key)) + return + else + _msgGroup(group, 'Build failed: DCS group spawn error') + return + end end end end + if fobBlocked then + _msgGroup(group, 'FOB building is restricted to designated FOB zones. Move inside a FOB zone to build.') + return + end + _msgGroup(group, 'Insufficient crates to build any asset here') end @@ -530,6 +608,78 @@ function CTLD:UnloadTroops(group) end end +-- ========================= +-- Public helpers +-- ========================= +-- ========================= +-- Auto-build FOB in zones +-- ========================= +function CTLD:AutoBuildFOBCheck() + if not (self.FOBZones and #self.FOBZones > 0) then return end + -- Find any FOB recipe definitions + local fobDefs = {} + for key,def in pairs(self.Config.CrateCatalog) do if def.isFOB and def.build then fobDefs[key] = def end end + if next(fobDefs) == nil then return end + + for _,zone in ipairs(self.FOBZones) do + local center = zone:GetPointVec3() + local radius = self:_getZoneRadius(zone) + local nearby = self:GetNearbyCrates({ x = center.x, z = center.z }, radius) + -- filter to this coalition side + local filtered = {} + for _,c in ipairs(nearby) do if c.meta.side == self.Side then table.insert(filtered, c) end end + nearby = filtered + if #nearby == 0 then goto continue end + + local counts = {} + for _,c in ipairs(nearby) do counts[c.meta.key] = (counts[c.meta.key] or 0) + 1 end + + local function consumeCrates(key, qty) + local removed = 0 + for _,c in ipairs(nearby) do + if removed >= qty then break end + if c.meta.key == key then + local obj = StaticObject.getByName(c.name) + if obj then obj:destroy() end + CTLD._crates[c.name] = nil + removed = removed + 1 + end + end + end + + -- Prefer composite recipes + for recipeKey,cat in pairs(fobDefs) do + if type(cat.requires) == 'table' then + local ok = true + for reqKey,qty in pairs(cat.requires) do if (counts[reqKey] or 0) < qty then ok = false; break end end + if ok then + local gdata = cat.build({ x = center.x, z = center.z }, 0, cat.side or self.Side) + local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata) + if g then + for reqKey,qty in pairs(cat.requires) do consumeCrates(reqKey, qty) end + _msgCoalition(self.Side, string.format('FOB auto-built at %s', zone:GetName())) + goto continue -- move to next zone; avoid multiple builds per tick + end + end + end + end + -- Then single-key FOB recipes + for key,cat in pairs(fobDefs) do + if not cat.requires and (counts[key] or 0) >= (cat.required or 1) then + local gdata = cat.build({ x = center.x, z = center.z }, 0, cat.side or self.Side) + local g = _coalitionAddGroup(cat.side or self.Side, cat.category or Group.Category.GROUND, gdata) + if g then + consumeCrates(key, cat.required or 1) + _msgCoalition(self.Side, string.format('FOB auto-built at %s', zone:GetName())) + goto continue + end + end + end + + ::continue:: + end +end + -- ========================= -- Public helpers -- ========================= diff --git a/Moose_CTLD_Pure/README.md b/Moose_CTLD_Pure/README.md index ff354b6..09af964 100644 --- a/Moose_CTLD_Pure/README.md +++ b/Moose_CTLD_Pure/README.md @@ -10,9 +10,10 @@ Pure-MOOSE CTLD-style logistics and FAC/RECCE without MIST or mission editor tem ## Quick start -1) Load `Moose.lua` first, then include these files (order matters): - - `Moose_CTLD_Pure/Moose_CTLD.lua` - - `Moose_CTLD_Pure/Moose_CTLD_FAC.lua` (optional, for FAC/RECCE) +1) Load `Moose.lua` first, then include these files (order matters). Easiest path: load the crate catalog first so CTLD auto-detects it. + - `Moose_CTLD_Pure/catalogs/CrateCatalog_CTLD_Extract.lua` (sets `_CTLD_EXTRACTED_CATALOG`) + - `Moose_CTLD_Pure/Moose_CTLD.lua` + - `Moose_CTLD_Pure/Moose_CTLD_FAC.lua` (optional, for FAC/RECCE) 2) Initialize CTLD with minimal config: @@ -20,15 +21,16 @@ Pure-MOOSE CTLD-style logistics and FAC/RECCE without MIST or mission editor tem local CTLD = dofile(lfs.writedir()..[[Scripts\Moose_CTLD_Pure\Moose_CTLD.lua]]) local ctld = CTLD:New({ CoalitionSide = coalition.side.BLUE, + -- If you want to rely ONLY on the external catalog, disable built-ins + -- UseBuiltinCatalog = false, Zones = { PickupZones = { { name = 'PICKUP_BLUE_MAIN' } }, DropZones = { { name = 'DROP_BLUE_1' } }, }, }) --- Optionally load a larger crate catalog extracted from your CTLD.lua -local extracted = dofile(lfs.writedir()..[[Scripts\Moose_CTLD_Pure\catalogs\CrateCatalog_CTLD_Extract.lua]]) -ctld:MergeCatalog(extracted) +-- No manual merge needed if you loaded the catalog file before CTLD.lua. +-- Supported globals that auto-merge: _CTLD_EXTRACTED_CATALOG, CTLD_CATALOG, MOOSE_CTLD_CATALOG ``` - If you don't have ME trigger zones, define by coordinates: @@ -96,6 +98,12 @@ CrateCatalog = { - Artillery marking uses `Controller.setTask('FireAtPoint')` on configured groups. Ensure those groups exist and are artillery-capable. - JTAC Auto-Lase helper provided: `fac:StartJTACOnGroup(groupName, laserCode, smokeColor)` uses `FAC_AUTO`. +### Catalog sources and precedence + +- By default, CTLD includes a small built-in sample catalog so it works out-of-the-box. +- If you load a catalog file before calling `CTLD:New()`, CTLD auto-merges the global catalog (no extra code needed). +- To use only your external catalog and avoid sample entries, set `UseBuiltinCatalog = false` in the `CTLD:New({...})` config. + ## Extending - Add radio beacons, FOB build recipes, fuel/ammo crates, and CSAR hooks by registering more `CrateCatalog` entries and/or adding helper methods. diff --git a/Moose_CTLD_Pure/catalogs/CrateCatalog_CTLD_Extract.lua b/Moose_CTLD_Pure/catalogs/CrateCatalog_CTLD_Extract.lua index d8b7ba9..d297cf0 100644 --- a/Moose_CTLD_Pure/catalogs/CrateCatalog_CTLD_Extract.lua +++ b/Moose_CTLD_Pure/catalogs/CrateCatalog_CTLD_Extract.lua @@ -160,7 +160,9 @@ cat['FOB_SMALL'] = { menuCategory='Support', menu='FOB Crate - Smal -- spawns a harmless placeholder truck for visibility; consumed by FOB_SITE build return singleUnit('Ural-375')(point, headingDeg) end } -cat['FOB_SITE'] = { menuCategory='Support', menu='FOB Crates - All', description='FOB Site', dcsCargoType='container_cargo', requires={ FOB_SMALL=3 }, side=nil, category=Group.Category.GROUND, +cat['FOB_SITE'] = { menuCategory='Support', menu='FOB Crates - All', description='FOB Site', isFOB=true, dcsCargoType='container_cargo', requires={ FOB_SMALL=3 }, side=nil, category=Group.Category.GROUND, build=multiUnits({ {type='HEMTT TFFT'}, {type='Ural-375 PBU', dx=10, dz=8}, {type='Ural-375', dx=-10, dz=8} }) } +-- Also export as a global for mission setups that load via DO SCRIPT FILE (no return capture) +_CTLD_EXTRACTED_CATALOG = cat return cat diff --git a/Moose_CTLD_Pure/init_mission_dual_coalition.lua b/Moose_CTLD_Pure/init_mission_dual_coalition.lua new file mode 100644 index 0000000..fabae9d --- /dev/null +++ b/Moose_CTLD_Pure/init_mission_dual_coalition.lua @@ -0,0 +1,113 @@ +-- init_mission_dual_coalition.lua +-- Use in Mission Editor with DO SCRIPT FILE load order: +-- 1) Moose.lua +-- 2) Moose_CTLD_Pure/Moose_CTLD.lua +-- 3) Moose_CTLD_Pure/catalogs/CrateCatalog_CTLD_Extract.lua -- optional but recommended catalog with BLUE+RED items (_CTLD_EXTRACTED_CATALOG) +-- 4) Moose_CTLD_Pure/Moose_CTLD_FAC.lua -- optional FAC/RECCE support +-- 5) DO SCRIPT: dofile on this file OR paste the block below directly +-- +-- Zones you should create in the Mission Editor (as trigger zones): +-- BLUE: PICKUP_BLUE_MAIN, DROP_BLUE_1, FOB_BLUE_A +-- RED : PICKUP_RED_MAIN, DROP_RED_1, FOB_RED_A +-- Adjust names below if you use different zone names. + +-- Create CTLD for BLUE +ctldBlue = _MOOSE_CTLD:New({ + CoalitionSide = coalition.side.BLUE, + UseCategorySubmenus = true, + UseBuiltinCatalog = false, -- rely on external catalog (recommended) + RestrictFOBToZones = true, + AutoBuildFOBInZones = true, + Zones = { + PickupZones = { { name = 'PICKUP_BLUE_MAIN' } }, + DropZones = { { name = 'DROP_BLUE_1' } }, + FOBZones = { { name = 'FOB_BLUE_A' } }, + }, +}) + +-- Create CTLD for RED +ctldRed = _MOOSE_CTLD:New({ + CoalitionSide = coalition.side.RED, + UseCategorySubmenus = true, + UseBuiltinCatalog = false, -- rely on external catalog (recommended) + RestrictFOBToZones = true, + AutoBuildFOBInZones = true, + Zones = { + PickupZones = { { name = 'PICKUP_RED_MAIN' } }, + DropZones = { { name = 'DROP_RED_1' } }, + FOBZones = { { name = 'FOB_RED_A' } }, + }, +}) + +-- If the external catalog was loaded (as _CTLD_EXTRACTED_CATALOG), both instances auto-merged it +-- thanks to Moose_CTLD.lua. If you want to load it manually or from a different path, you can do: +-- local extracted = dofile(lfs.writedir()..[[Scripts\Moose_CTLD_Pure\catalogs\CrateCatalog_CTLD_Extract.lua]]) +-- ctldBlue:MergeCatalog(extracted) +-- ctldRed:MergeCatalog(extracted) + +-- Optional: add a couple of small, side-specific examples if you don't use the big catalog +-- (Uncomment to add a simple MANPADS and AAA on each side) +-- ctldBlue:RegisterCrate('MANPADS', { +-- menuCategory='Infantry', description='2x crates -> MANPADS (Stinger)', dcsCargoType='uh1h_cargo', required=2, +-- side=coalition.side.BLUE, category=Group.Category.GROUND, +-- build=function(point, headingDeg) +-- local hdg = math.rad(headingDeg or 0) +-- return { visible=false, lateActivation=false, tasks={}, task='Ground Nothing', route={}, name='CTLD_BP_MANPADS_'..math.random(1,999999), +-- units={ { type='Soldier stinger', name='CTLD-Stinger-'..math.random(1,999999), x=point.x, y=point.z, heading=hdg } } } +-- end, +-- }) +-- ctldBlue:RegisterCrate('AAA', { +-- menuCategory='AAA', description='3x crates -> ZU-23 site', dcsCargoType='container_cargo', required=3, +-- side=coalition.side.BLUE, category=Group.Category.GROUND, +-- build=function(point, headingDeg) +-- local hdg = math.rad(headingDeg or 0) +-- local function off(dx,dz) return { x=point.x+dx, z=point.z+dz } end +-- local units={ +-- { type='ZU-23 Emplacement', name='CTLD-ZU23-'..math.random(1,999999), x=point.x, y=point.z, heading=hdg }, +-- { type='Ural-375', name='CTLD-TRK-'..math.random(1,999999), x=off(15,12).x, y=off(15,12).z, heading=hdg }, +-- { type='Infantry AK', name='CTLD-INF-'..math.random(1,999999), x=off(-12,-15).x, y=off(-12,-15).z, heading=hdg }, +-- } +-- return { visible=false, lateActivation=false, tasks={}, task='Ground Nothing', units=units, route={}, name='CTLD_BP_AAA_'..math.random(1,999999) } +-- end, +-- }) +-- ctldRed:RegisterCrate('MANPADS', { +-- menuCategory='Infantry', description='2x crates -> MANPADS (Igla)', dcsCargoType='uh1h_cargo', required=2, +-- side=coalition.side.RED, category=Group.Category.GROUND, +-- build=function(point, headingDeg) +-- local hdg = math.rad(headingDeg or 0) +-- -- Using generic infantry to avoid DCS type-name mismatches; replace with accurate manpad unit if desired +-- return { visible=false, lateActivation=false, tasks={}, task='Ground Nothing', route={}, name='CTLD_RP_MANPADS_'..math.random(1,999999), +-- units={ { type='Infantry AK', name='CTLD-Igla-'..math.random(1,999999), x=point.x, y=point.z, heading=hdg } } } +-- end, +-- }) +-- ctldRed:RegisterCrate('AAA', { +-- menuCategory='AAA', description='3x crates -> ZU-23 site', dcsCargoType='container_cargo', required=3, +-- side=coalition.side.RED, category=Group.Category.GROUND, +-- build=function(point, headingDeg) +-- local hdg = math.rad(headingDeg or 0) +-- local function off(dx,dz) return { x=point.x+dx, z=point.z+dz } end +-- local units={ +-- { type='ZU-23 Emplacement', name='CTLD-ZU23-'..math.random(1,999999), x=point.x, y=point.z, heading=hdg }, +-- { type='Ural-375', name='CTLD-TRK-'..math.random(1,999999), x=off(15,12).x, y=off(15,12).z, heading=hdg }, +-- { type='Infantry AK', name='CTLD-INF-'..math.random(1,999999), x=off(-12,-15).x, y=off(-12,-15).z, heading=hdg }, +-- } +-- return { visible=false, lateActivation=false, tasks={}, task='Ground Nothing', units=units, route={}, name='CTLD_RP_AAA_'..math.random(1,999999) } +-- end, +-- }) + +-- Optional: FAC/RECCE for both sides (requires Moose_CTLD_FAC.lua) +if _MOOSE_CTLD_FAC then + facBlue = _MOOSE_CTLD_FAC:New(ctldBlue, { + CoalitionSide = coalition.side.BLUE, + Arty = { Enabled = false }, + }) + -- facBlue:AddRecceZone({ name = 'RECCE_BLUE_1' }) + facBlue:Run() + + facRed = _MOOSE_CTLD_FAC:New(ctldRed, { + CoalitionSide = coalition.side.RED, + Arty = { Enabled = false }, + }) + -- facRed:AddRecceZone({ name = 'RECCE_RED_1' }) + facRed:Run() +end diff --git a/Moose_CTLD_Pure/init_mission_example.lua b/Moose_CTLD_Pure/init_mission_example.lua new file mode 100644 index 0000000..4830393 --- /dev/null +++ b/Moose_CTLD_Pure/init_mission_example.lua @@ -0,0 +1,46 @@ +-- init_mission_example.lua +-- Use this with Mission Editor triggers as DO SCRIPT (no paths) +-- Load order (Mission Start): +-- Option A (catalog first): +-- 1) DO SCRIPT FILE: Moose.lua +-- 2) DO SCRIPT FILE: Moose_CTLD_Pure/catalogs/CrateCatalog_CTLD_Extract.lua -- sets _CTLD_EXTRACTED_CATALOG +-- 3) DO SCRIPT FILE: Moose_CTLD_Pure/Moose_CTLD.lua +-- 4) DO SCRIPT FILE: Moose_CTLD_Pure/Moose_CTLD_FAC.lua (optional) +-- 5) DO SCRIPT: paste the block below +-- Option B (catalog after CTLD file): +-- 1) DO SCRIPT FILE: Moose.lua +-- 2) DO SCRIPT FILE: Moose_CTLD_Pure/Moose_CTLD.lua +-- 3) DO SCRIPT FILE: Moose_CTLD_Pure/catalogs/CrateCatalog_CTLD_Extract.lua -- still fine: load before ctld:New() +-- 4) DO SCRIPT FILE: Moose_CTLD_Pure/Moose_CTLD_FAC.lua (optional) +-- 5) DO SCRIPT: paste the block below + +-- create CTLD instance for BLUE +ctld = _MOOSE_CTLD:New({ + CoalitionSide = coalition.side.BLUE, + UseCategorySubmenus = true, + -- Set to false if you want ONLY the external catalog and no built-in examples + -- UseBuiltinCatalog = false, + RestrictFOBToZones = true, + AutoBuildFOBInZones = true, + Zones = { + PickupZones = { { name = 'PICKUP_BLUE_MAIN' } }, + DropZones = { { name = 'DROP_BLUE_1' } }, + FOBZones = { { name = 'FOB_ALPHA' } }, + }, +}) + +-- No manual merge needed: Moose_CTLD auto-detects and merges global catalogs +-- supported global names: _CTLD_EXTRACTED_CATALOG, CTLD_CATALOG, MOOSE_CTLD_CATALOG + +-- set allowed transports (optional override) +-- ctld:SetAllowedAircraft({'UH-1H','Mi-8MTV2','Mi-24P'}) + +-- FAC/RECCE (optional) +if _MOOSE_CTLD_FAC then + fac = _MOOSE_CTLD_FAC:New(ctld, { + CoalitionSide = coalition.side.BLUE, + Arty = { Enabled=true, Groups={'BLUE_ARTY_1'}, Rounds=2, Spread=80 }, + }) + fac:AddRecceZone({ name = 'RECCE_ZONE_1' }) + fac:Run() +end