mirror of
https://github.com/iTracerFacer/DCS_MissionDev.git
synced 2025-12-03 04:14:46 +00:00
Updated MASH Zone functions to be setup like the other types.
This commit is contained in:
parent
0c71a0246e
commit
aa249a6a36
Binary file not shown.
Binary file not shown.
@ -37,6 +37,7 @@ ctldBlue = _MOOSE_CTLD:New({
|
|||||||
},
|
},
|
||||||
--DropZones = { { name = 'BRAVO', flag = 9002, activeWhen = 0 } },
|
--DropZones = { { name = 'BRAVO', flag = 9002, activeWhen = 0 } },
|
||||||
--FOBZones = { { name = 'CHARLIE', flag = 9003, activeWhen = 0 } },
|
--FOBZones = { { name = 'CHARLIE', flag = 9003, activeWhen = 0 } },
|
||||||
|
--MASHZones = { { name = 'MASH Alpha', freq = '251.0 AM', radius = 500, flag = 9010, activeWhen = 0 } },
|
||||||
},
|
},
|
||||||
BuildRequiresGroundCrates = true,
|
BuildRequiresGroundCrates = true,
|
||||||
})
|
})
|
||||||
@ -62,6 +63,7 @@ ctldRed = _MOOSE_CTLD:New({
|
|||||||
},
|
},
|
||||||
--DropZones = { { name = 'ECHO', flag = 9102, activeWhen = 0 } },
|
--DropZones = { { name = 'ECHO', flag = 9102, activeWhen = 0 } },
|
||||||
--FOBZones = { { name = 'FOXTROT', flag = 9103, activeWhen = 0 } },
|
--FOBZones = { { name = 'FOXTROT', flag = 9103, activeWhen = 0 } },
|
||||||
|
--MASHZones = { { name = 'MASH Bravo', freq = '252.0 AM', radius = 500, flag = 9111, activeWhen = 0 } },
|
||||||
},
|
},
|
||||||
BuildRequiresGroundCrates = true,
|
BuildRequiresGroundCrates = true,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,29 @@
|
|||||||
-- Setup Capture Missions & Zones
|
-- Setup Capture Missions & Zones
|
||||||
|
|
||||||
|
-- ================================================================================
|
||||||
|
-- MESSAGE AND TIMING CONFIGURATION
|
||||||
|
-- Control how often messages are sent and how long they are displayed
|
||||||
|
-- ================================================================================
|
||||||
|
local MESSAGE_CONFIG = {
|
||||||
|
-- Zone status broadcast frequency (in seconds)
|
||||||
|
STATUS_BROADCAST_FREQUENCY = 3602, -- Default: 3600 seconds (1 hour)
|
||||||
|
STATUS_BROADCAST_START_DELAY = 10, -- Default: 10 seconds initial delay
|
||||||
|
|
||||||
|
-- Zone color verification frequency (in seconds)
|
||||||
|
COLOR_VERIFICATION_FREQUENCY = 240, -- Default: 240 seconds (4 minutes)
|
||||||
|
COLOR_VERIFICATION_START_DELAY = 60, -- Default: 60 seconds initial delay
|
||||||
|
|
||||||
|
-- Tactical marker update frequency (in seconds)
|
||||||
|
TACTICAL_UPDATE_FREQUENCY = 180, -- Default: 180 seconds (3 minutes)
|
||||||
|
TACTICAL_UPDATE_START_DELAY = 30, -- Default: 30 seconds initial delay
|
||||||
|
|
||||||
|
-- Message display durations (in seconds)
|
||||||
|
STATUS_MESSAGE_DURATION = 15, -- Default: 15 seconds
|
||||||
|
VICTORY_MESSAGE_DURATION = 300, -- Default: 300 seconds
|
||||||
|
CAPTURE_MESSAGE_DURATION = 15, -- Default: 15 seconds
|
||||||
|
ATTACK_MESSAGE_DURATION = 15, -- Default: 15 seconds
|
||||||
|
}
|
||||||
|
|
||||||
-- ================================================================================
|
-- ================================================================================
|
||||||
-- ZONE COLOR CONFIGURATION
|
-- ZONE COLOR CONFIGURATION
|
||||||
-- Mission makers can easily customize zone colors here
|
-- Mission makers can easily customize zone colors here
|
||||||
@ -471,16 +495,16 @@ local function OnEnterGuarded(ZoneCapture, From, Event, To)
|
|||||||
ZoneCapture:UndrawZone()
|
ZoneCapture:UndrawZone()
|
||||||
local color = ZONE_COLORS.BLUE_CAPTURED
|
local color = ZONE_COLORS.BLUE_CAPTURED
|
||||||
ZoneCapture:DrawZone(-1, color, 0.5, color, 0.2, 2, true)
|
ZoneCapture:DrawZone(-1, color, 0.5, color, 0.2, 2, true)
|
||||||
US_CC:MessageTypeToCoalition( string.format( "%s is under protection of the USA", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
US_CC:MessageTypeToCoalition( string.format( "%s is under protection of the USA", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.CAPTURE_MESSAGE_DURATION )
|
||||||
RU_CC:MessageTypeToCoalition( string.format( "%s is under protection of the USA", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
RU_CC:MessageTypeToCoalition( string.format( "%s is under protection of the USA", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.CAPTURE_MESSAGE_DURATION )
|
||||||
else
|
else
|
||||||
ZoneCapture:Smoke( SMOKECOLOR.Red )
|
ZoneCapture:Smoke( SMOKECOLOR.Red )
|
||||||
-- Update zone visual markers to RED (captured)
|
-- Update zone visual markers to RED (captured)
|
||||||
ZoneCapture:UndrawZone()
|
ZoneCapture:UndrawZone()
|
||||||
local color = ZONE_COLORS.RED_CAPTURED
|
local color = ZONE_COLORS.RED_CAPTURED
|
||||||
ZoneCapture:DrawZone(-1, color, 0.5, color, 0.2, 2, true)
|
ZoneCapture:DrawZone(-1, color, 0.5, color, 0.2, 2, true)
|
||||||
RU_CC:MessageTypeToCoalition( string.format( "%s is under protection of Russia", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
RU_CC:MessageTypeToCoalition( string.format( "%s is under protection of Russia", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.CAPTURE_MESSAGE_DURATION )
|
||||||
US_CC:MessageTypeToCoalition( string.format( "%s is under protection of Russia", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
US_CC:MessageTypeToCoalition( string.format( "%s is under protection of Russia", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.CAPTURE_MESSAGE_DURATION )
|
||||||
end
|
end
|
||||||
-- Create/update tactical information marker
|
-- Create/update tactical information marker
|
||||||
CreateTacticalInfoMarker(ZoneCapture)
|
CreateTacticalInfoMarker(ZoneCapture)
|
||||||
@ -493,8 +517,8 @@ local function OnEnterEmpty(ZoneCapture)
|
|||||||
ZoneCapture:UndrawZone()
|
ZoneCapture:UndrawZone()
|
||||||
local color = ZONE_COLORS.EMPTY
|
local color = ZONE_COLORS.EMPTY
|
||||||
ZoneCapture:DrawZone(-1, color, 0.5, color, 0.2, 2, true)
|
ZoneCapture:DrawZone(-1, color, 0.5, color, 0.2, 2, true)
|
||||||
US_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
US_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.CAPTURE_MESSAGE_DURATION )
|
||||||
RU_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
RU_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.CAPTURE_MESSAGE_DURATION )
|
||||||
-- Create/update tactical information marker
|
-- Create/update tactical information marker
|
||||||
CreateTacticalInfoMarker(ZoneCapture)
|
CreateTacticalInfoMarker(ZoneCapture)
|
||||||
end
|
end
|
||||||
@ -507,12 +531,12 @@ local function OnEnterAttacked(ZoneCapture)
|
|||||||
local color
|
local color
|
||||||
if Coalition == coalition.side.BLUE then
|
if Coalition == coalition.side.BLUE then
|
||||||
color = ZONE_COLORS.BLUE_ATTACKED -- Light blue for Blue zone under attack
|
color = ZONE_COLORS.BLUE_ATTACKED -- Light blue for Blue zone under attack
|
||||||
US_CC:MessageTypeToCoalition( string.format( "%s is under attack by Russia", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
US_CC:MessageTypeToCoalition( string.format( "%s is under attack by Russia", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.ATTACK_MESSAGE_DURATION )
|
||||||
RU_CC:MessageTypeToCoalition( string.format( "We are attacking %s", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
RU_CC:MessageTypeToCoalition( string.format( "We are attacking %s", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.ATTACK_MESSAGE_DURATION )
|
||||||
else
|
else
|
||||||
color = ZONE_COLORS.RED_ATTACKED -- Orange for Red zone under attack
|
color = ZONE_COLORS.RED_ATTACKED -- Orange for Red zone under attack
|
||||||
RU_CC:MessageTypeToCoalition( string.format( "%s is under attack by the USA", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
RU_CC:MessageTypeToCoalition( string.format( "%s is under attack by the USA", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.ATTACK_MESSAGE_DURATION )
|
||||||
US_CC:MessageTypeToCoalition( string.format( "We are attacking %s", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information )
|
US_CC:MessageTypeToCoalition( string.format( "We are attacking %s", ZoneCapture:GetZoneName() ), MESSAGE.Type.Information, MESSAGE_CONFIG.ATTACK_MESSAGE_DURATION )
|
||||||
end
|
end
|
||||||
ZoneCapture:DrawZone(-1, color, 0.5, color, 0.2, 2, true)
|
ZoneCapture:DrawZone(-1, color, 0.5, color, 0.2, 2, true)
|
||||||
-- Create/update tactical information marker
|
-- Create/update tactical information marker
|
||||||
@ -830,7 +854,7 @@ local function BroadcastZoneStatus()
|
|||||||
|
|
||||||
local fullMessage = reportMessage .. detailMessage
|
local fullMessage = reportMessage .. detailMessage
|
||||||
|
|
||||||
US_CC:MessageTypeToCoalition( fullMessage, MESSAGE.Type.Information, 15 )
|
US_CC:MessageTypeToCoalition( fullMessage, MESSAGE.Type.Information, MESSAGE_CONFIG.STATUS_MESSAGE_DURATION )
|
||||||
|
|
||||||
log("[ZONE STATUS] " .. reportMessage:gsub("\n", " | "))
|
log("[ZONE STATUS] " .. reportMessage:gsub("\n", " | "))
|
||||||
|
|
||||||
@ -846,17 +870,17 @@ local ZoneMonitorScheduler = SCHEDULER:New( nil, function()
|
|||||||
US_CC:MessageTypeToCoalition(
|
US_CC:MessageTypeToCoalition(
|
||||||
string.format("APPROACHING VICTORY! %d more zone(s) needed for complete success!",
|
string.format("APPROACHING VICTORY! %d more zone(s) needed for complete success!",
|
||||||
status.total - status.blue),
|
status.total - status.blue),
|
||||||
MESSAGE.Type.Information, 10
|
MESSAGE.Type.Information, MESSAGE_CONFIG.VICTORY_MESSAGE_DURATION
|
||||||
)
|
)
|
||||||
|
|
||||||
RU_CC:MessageTypeToCoalition(
|
RU_CC:MessageTypeToCoalition(
|
||||||
string.format("CRITICAL SITUATION! Only %d zone(s) remain under our control!",
|
string.format("CRITICAL SITUATION! Only %d zone(s) remain under our control!",
|
||||||
status.red),
|
status.red),
|
||||||
MESSAGE.Type.Information, 10
|
MESSAGE.Type.Information, MESSAGE_CONFIG.VICTORY_MESSAGE_DURATION
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
end, {}, 10, 300 ) -- Start after 10 seconds, repeat every 300 seconds (5 minutes)
|
end, {}, MESSAGE_CONFIG.STATUS_BROADCAST_START_DELAY, MESSAGE_CONFIG.STATUS_BROADCAST_FREQUENCY ) -- Configurable timing
|
||||||
|
|
||||||
-- Periodic zone color verification system (every 2 minutes)
|
-- Periodic zone color verification system (every 2 minutes)
|
||||||
local ZoneColorVerificationScheduler = SCHEDULER:New( nil, function()
|
local ZoneColorVerificationScheduler = SCHEDULER:New( nil, function()
|
||||||
@ -893,7 +917,7 @@ local ZoneColorVerificationScheduler = SCHEDULER:New( nil, function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end, {}, 60, 240 ) -- Start after 60 seconds, repeat every 240 seconds (4 minutes)
|
end, {}, MESSAGE_CONFIG.COLOR_VERIFICATION_START_DELAY, MESSAGE_CONFIG.COLOR_VERIFICATION_FREQUENCY ) -- Configurable timing
|
||||||
|
|
||||||
-- Periodic tactical marker update system with change detection (every 3 minutes)
|
-- Periodic tactical marker update system with change detection (every 3 minutes)
|
||||||
local __lastForceCountsByZone = {}
|
local __lastForceCountsByZone = {}
|
||||||
@ -916,7 +940,7 @@ local TacticalMarkerUpdateScheduler = SCHEDULER:New( nil, function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end, {}, 30, 180 ) -- Start after 30 seconds, repeat every 180 seconds (3 minutes)
|
end, {}, MESSAGE_CONFIG.TACTICAL_UPDATE_START_DELAY, MESSAGE_CONFIG.TACTICAL_UPDATE_FREQUENCY ) -- Configurable timing
|
||||||
|
|
||||||
-- Function to refresh all zone colors based on current ownership
|
-- Function to refresh all zone colors based on current ownership
|
||||||
local function RefreshAllZoneColors()
|
local function RefreshAllZoneColors()
|
||||||
|
|||||||
@ -140,8 +140,8 @@ local TADC_SETTINGS = {
|
|||||||
-- Timing settings (applies to both coalitions)
|
-- Timing settings (applies to both coalitions)
|
||||||
checkInterval = 30, -- How often to scan for threats (seconds)
|
checkInterval = 30, -- How often to scan for threats (seconds)
|
||||||
monitorInterval = 30, -- How often to check interceptor status (seconds)
|
monitorInterval = 30, -- How often to check interceptor status (seconds)
|
||||||
statusReportInterval = 120, -- How often to report airbase status (seconds)
|
statusReportInterval = 1805, -- How often to report airbase status (seconds)
|
||||||
squadronSummaryInterval = 600, -- How often to broadcast squadron summary (seconds)
|
squadronSummaryInterval = 1800, -- How often to broadcast squadron summary (seconds)
|
||||||
cargoCheckInterval = 15, -- How often to check for cargo deliveries (seconds)
|
cargoCheckInterval = 15, -- How often to check for cargo deliveries (seconds)
|
||||||
|
|
||||||
-- RED Coalition Settings
|
-- RED Coalition Settings
|
||||||
|
|||||||
@ -291,6 +291,7 @@ CTLD.Config = {
|
|||||||
DrawPickupZones = true, -- draw Pickup/Supply zones as shaded circles with labels
|
DrawPickupZones = true, -- draw Pickup/Supply zones as shaded circles with labels
|
||||||
DrawDropZones = true, -- optionally draw Drop zones
|
DrawDropZones = true, -- optionally draw Drop zones
|
||||||
DrawFOBZones = true, -- optionally draw FOB zones
|
DrawFOBZones = true, -- optionally draw FOB zones
|
||||||
|
DrawMASHZones = true, -- optionally draw MASH (medical) zones
|
||||||
FontSize = 18, -- label text size
|
FontSize = 18, -- label text size
|
||||||
ReadOnly = true, -- prevent clients from removing the shapes
|
ReadOnly = true, -- prevent clients from removing the shapes
|
||||||
ForAll = false, -- if true, draw shapes to all (-1) instead of coalition only (useful for testing/briefing)
|
ForAll = false, -- if true, draw shapes to all (-1) instead of coalition only (useful for testing/briefing)
|
||||||
@ -300,12 +301,14 @@ CTLD.Config = {
|
|||||||
Pickup = {0, 1, 0, 0.15}, -- light green fill for Pickup zones
|
Pickup = {0, 1, 0, 0.15}, -- light green fill for Pickup zones
|
||||||
Drop = {0, 0, 0, 0.25}, -- black fill for Drop zones
|
Drop = {0, 0, 0, 0.25}, -- black fill for Drop zones
|
||||||
FOB = {1, 1, 0, 0.15}, -- yellow fill for FOB zones
|
FOB = {1, 1, 0, 0.15}, -- yellow fill for FOB zones
|
||||||
|
MASH = {1, 0.75, 0.8, 0.25}, -- pink fill for MASH zones
|
||||||
},
|
},
|
||||||
LineType = 1, -- default line type if per-kind is not set (0 None, 1 Solid, 2 Dashed, 3 Dotted, 4 DotDash, 5 LongDash, 6 TwoDash)
|
LineType = 1, -- default line type if per-kind is not set (0 None, 1 Solid, 2 Dashed, 3 Dotted, 4 DotDash, 5 LongDash, 6 TwoDash)
|
||||||
LineTypes = { -- override border style per zone kind
|
LineTypes = { -- override border style per zone kind
|
||||||
Pickup = 3, -- dotted
|
Pickup = 3, -- dotted
|
||||||
Drop = 2, -- dashed
|
Drop = 2, -- dashed
|
||||||
FOB = 4, -- dot-dash
|
FOB = 4, -- dot-dash
|
||||||
|
MASH = 1, -- solid
|
||||||
},
|
},
|
||||||
-- Label placement tuning (simple):
|
-- Label placement tuning (simple):
|
||||||
-- Effective extra offset from the circle edge = r * LabelOffsetRatio + LabelOffsetFromEdge
|
-- Effective extra offset from the circle edge = r * LabelOffsetRatio + LabelOffsetFromEdge
|
||||||
@ -317,6 +320,7 @@ CTLD.Config = {
|
|||||||
Pickup = 'Supply Zone',
|
Pickup = 'Supply Zone',
|
||||||
Drop = 'Drop Zone',
|
Drop = 'Drop Zone',
|
||||||
FOB = 'FOB Zone',
|
FOB = 'FOB Zone',
|
||||||
|
MASH = 'MASH',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -331,7 +335,7 @@ CTLD.Config = {
|
|||||||
-- Inventory system (per pickup zone and FOBs)
|
-- Inventory system (per pickup zone and FOBs)
|
||||||
Inventory = {
|
Inventory = {
|
||||||
Enabled = true, -- master switch for per-location stock control
|
Enabled = true, -- master switch for per-location stock control
|
||||||
FOBStockFactor = 0.25, -- starting stock at newly built FOBs relative to pickup-zone initialStock
|
FOBStockFactor = 0.50, -- starting stock at newly built FOBs relative to pickup-zone initialStock
|
||||||
ShowStockInMenu = true, -- if true, append simple stock hints to menu labels (per current nearest zone)
|
ShowStockInMenu = true, -- if true, append simple stock hints to menu labels (per current nearest zone)
|
||||||
HideZeroStockMenu = false, -- removed: previously created an "In Stock Here" submenu; now disabled by default
|
HideZeroStockMenu = false, -- removed: previously created an "In Stock Here" submenu; now disabled by default
|
||||||
},
|
},
|
||||||
@ -344,6 +348,16 @@ CTLD.Config = {
|
|||||||
-- If no catalog is loaded, empty table is used (and fallback logic applies)
|
-- If no catalog is loaded, empty table is used (and fallback logic applies)
|
||||||
TroopTypes = {},
|
TroopTypes = {},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
-- Zones (Supply/Pickup, Drop, FOB, MASH)
|
||||||
|
-- Mission makers should populate these arrays with zone definitions
|
||||||
|
-- Each zone entry can be: { name = 'ZoneName' } or { name = 'ZoneName', flag = 9001, activeWhen = 0, smoke = color, radius = meters }
|
||||||
|
Zones = {
|
||||||
|
PickupZones = {}, -- Supply zones where crates/troops can be requested
|
||||||
|
DropZones = {}, -- Optional Drop/AO zones
|
||||||
|
FOBZones = {}, -- FOB zones (restrict FOB building to these if RestrictFOBToZones = true)
|
||||||
|
MASHZones = {}, -- Medical zones for MEDEVAC crew delivery (MASH = Mobile Army Surgical Hospital)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
-- #endregion Config
|
-- #endregion Config
|
||||||
|
|
||||||
@ -430,12 +444,6 @@ CTLD.MEDEVAC = {
|
|||||||
{ time = 300, message = 'URGENT MEDEVAC: {crew} at {grid} will be KIA in 5 minutes!' },
|
{ time = 300, message = 'URGENT MEDEVAC: {crew} at {grid} will be KIA in 5 minutes!' },
|
||||||
},
|
},
|
||||||
|
|
||||||
-- MASH Zones (fixed, defined in mission editor)
|
|
||||||
MASHZones = {
|
|
||||||
-- Example: { name = 'MASH Alpha', freq = 251.0, radius = 500 },
|
|
||||||
-- Mission makers add their zones here or via CTLD:AddMASHZone()
|
|
||||||
},
|
|
||||||
|
|
||||||
MASHZoneRadius = 500, -- default radius for MASH zones
|
MASHZoneRadius = 500, -- default radius for MASH zones
|
||||||
MASHZoneColors = {
|
MASHZoneColors = {
|
||||||
border = {1, 1, 0, 0.85}, -- yellow border
|
border = {1, 1, 0, 0.85}, -- yellow border
|
||||||
@ -852,6 +860,7 @@ function CTLD:_getZoneCenterAndRadius(mz)
|
|||||||
local d = self._ZoneDefs.PickupZones and self._ZoneDefs.PickupZones[name]
|
local d = self._ZoneDefs.PickupZones and self._ZoneDefs.PickupZones[name]
|
||||||
or self._ZoneDefs.DropZones and self._ZoneDefs.DropZones[name]
|
or self._ZoneDefs.DropZones and self._ZoneDefs.DropZones[name]
|
||||||
or self._ZoneDefs.FOBZones and self._ZoneDefs.FOBZones[name]
|
or self._ZoneDefs.FOBZones and self._ZoneDefs.FOBZones[name]
|
||||||
|
or self._ZoneDefs.MASHZones and self._ZoneDefs.MASHZones[name]
|
||||||
if d and d.radius then r = d.radius end
|
if d and d.radius then r = d.radius end
|
||||||
end
|
end
|
||||||
r = r or (mz.GetRadius and mz:GetRadius()) or 150
|
r = r or (mz.GetRadius and mz:GetRadius()) or 150
|
||||||
@ -859,7 +868,7 @@ function CTLD:_getZoneCenterAndRadius(mz)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Draw a circle and label for a zone on the F10 map for this coalition.
|
-- Draw a circle and label for a zone on the F10 map for this coalition.
|
||||||
-- kind: 'Pickup' | 'Drop' | 'FOB'
|
-- kind: 'Pickup' | 'Drop' | 'FOB' | 'MASH'
|
||||||
function CTLD:_drawZoneCircleAndLabel(kind, mz, opts)
|
function CTLD:_drawZoneCircleAndLabel(kind, mz, opts)
|
||||||
if not (trigger and trigger.action and trigger.action.circleToAll and trigger.action.textToAll) then return end
|
if not (trigger and trigger.action and trigger.action.circleToAll and trigger.action.textToAll) then return end
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
@ -898,7 +907,7 @@ function CTLD:ClearMapDrawings()
|
|||||||
if ids.text then pcall(trigger.action.removeMark, ids.text) end
|
if ids.text then pcall(trigger.action.removeMark, ids.text) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self._MapMarkup = { Pickup = {}, Drop = {}, FOB = {} }
|
self._MapMarkup = { Pickup = {}, Drop = {}, FOB = {}, MASH = {} }
|
||||||
end
|
end
|
||||||
|
|
||||||
function CTLD:_removeZoneDrawing(kind, zname)
|
function CTLD:_removeZoneDrawing(kind, zname)
|
||||||
@ -912,14 +921,14 @@ end
|
|||||||
-- Public: set a specific zone active/inactive by kind and name
|
-- Public: set a specific zone active/inactive by kind and name
|
||||||
function CTLD:SetZoneActive(kind, name, active, silent)
|
function CTLD:SetZoneActive(kind, name, active, silent)
|
||||||
if not (kind and name) then return end
|
if not (kind and name) then return end
|
||||||
local k = (kind == 'Pickup' or kind == 'Drop' or kind == 'FOB') and kind or nil
|
local k = (kind == 'Pickup' or kind == 'Drop' or kind == 'FOB' or kind == 'MASH') and kind or nil
|
||||||
if not k then return end
|
if not k then return end
|
||||||
self._ZoneActive = self._ZoneActive or { Pickup = {}, Drop = {}, FOB = {} }
|
self._ZoneActive = self._ZoneActive or { Pickup = {}, Drop = {}, FOB = {}, MASH = {} }
|
||||||
self._ZoneActive[k][name] = (active ~= false)
|
self._ZoneActive[k][name] = (active ~= false)
|
||||||
-- Update drawings for this one zone only
|
-- Update drawings for this one zone only
|
||||||
if self.Config.MapDraw and self.Config.MapDraw.Enabled then
|
if self.Config.MapDraw and self.Config.MapDraw.Enabled then
|
||||||
-- Find the MOOSE zone object by name
|
-- Find the MOOSE zone object by name
|
||||||
local list = (k=='Pickup' and self.PickupZones) or (k=='Drop' and self.DropZones) or (k=='FOB' and self.FOBZones) or {}
|
local list = (k=='Pickup' and self.PickupZones) or (k=='Drop' and self.DropZones) or (k=='FOB' and self.FOBZones) or (k=='MASH' and self.MASHZones) or {}
|
||||||
local mz
|
local mz
|
||||||
for _,z in ipairs(list or {}) do if z and z.GetName and z:GetName() == name then mz = z break end end
|
for _,z in ipairs(list or {}) do if z and z.GetName and z:GetName() == name then mz = z break end end
|
||||||
if self._ZoneActive[k][name] then
|
if self._ZoneActive[k][name] then
|
||||||
@ -1002,6 +1011,17 @@ function CTLD:DrawZonesOnMap()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if md.DrawMASHZones then
|
||||||
|
for _,mz in ipairs(self.MASHZones or {}) do
|
||||||
|
local name = mz:GetName()
|
||||||
|
if self._ZoneActive.MASH[name] ~= false then
|
||||||
|
opts.LabelPrefix = (md.LabelPrefixes and md.LabelPrefixes.MASH) or 'MASH'
|
||||||
|
opts.LineType = (md.LineTypes and md.LineTypes.MASH) or md.LineType or 1
|
||||||
|
opts.FillColor = (md.FillColors and md.FillColors.MASH) or nil
|
||||||
|
self:_drawZoneCircleAndLabel('MASH', mz, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Unit preference detection and unit-aware formatting
|
-- Unit preference detection and unit-aware formatting
|
||||||
@ -1454,6 +1474,7 @@ function CTLD:New(cfg)
|
|||||||
pushFromZones('Pickup', o.Config.Zones and o.Config.Zones.PickupZones)
|
pushFromZones('Pickup', o.Config.Zones and o.Config.Zones.PickupZones)
|
||||||
pushFromZones('Drop', o.Config.Zones and o.Config.Zones.DropZones)
|
pushFromZones('Drop', o.Config.Zones and o.Config.Zones.DropZones)
|
||||||
pushFromZones('FOB', o.Config.Zones and o.Config.Zones.FOBZones)
|
pushFromZones('FOB', o.Config.Zones and o.Config.Zones.FOBZones)
|
||||||
|
pushFromZones('MASH', o.Config.Zones and o.Config.Zones.MASHZones)
|
||||||
|
|
||||||
o._BindingsMerged = merged
|
o._BindingsMerged = merged
|
||||||
if o._BindingsMerged and #o._BindingsMerged > 0 then
|
if o._BindingsMerged and #o._BindingsMerged > 0 then
|
||||||
@ -1532,8 +1553,9 @@ function CTLD:InitZones()
|
|||||||
self.PickupZones = {}
|
self.PickupZones = {}
|
||||||
self.DropZones = {}
|
self.DropZones = {}
|
||||||
self.FOBZones = {}
|
self.FOBZones = {}
|
||||||
self._ZoneDefs = { PickupZones = {}, DropZones = {}, FOBZones = {} }
|
self.MASHZones = {}
|
||||||
self._ZoneActive = { Pickup = {}, Drop = {}, FOB = {} }
|
self._ZoneDefs = { PickupZones = {}, DropZones = {}, FOBZones = {}, MASHZones = {} }
|
||||||
|
self._ZoneActive = { Pickup = {}, Drop = {}, FOB = {}, MASH = {} }
|
||||||
for _,z in ipairs(self.Config.Zones.PickupZones or {}) do
|
for _,z in ipairs(self.Config.Zones.PickupZones or {}) do
|
||||||
local mz = _findZone(z)
|
local mz = _findZone(z)
|
||||||
if mz then
|
if mz then
|
||||||
@ -1561,6 +1583,15 @@ function CTLD:InitZones()
|
|||||||
if self._ZoneActive.FOB[name] == nil then self._ZoneActive.FOB[name] = (z.active ~= false) end
|
if self._ZoneActive.FOB[name] == nil then self._ZoneActive.FOB[name] = (z.active ~= false) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
for _,z in ipairs(self.Config.Zones.MASHZones or {}) do
|
||||||
|
local mz = _findZone(z)
|
||||||
|
if mz then
|
||||||
|
table.insert(self.MASHZones, mz)
|
||||||
|
local name = mz:GetName()
|
||||||
|
self._ZoneDefs.MASHZones[name] = z
|
||||||
|
if self._ZoneActive.MASH[name] == nil then self._ZoneActive.MASH[name] = (z.active ~= false) end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Validate configured zone names exist in the mission; warn coalition if any are missing.
|
-- Validate configured zone names exist in the mission; warn coalition if any are missing.
|
||||||
@ -1593,9 +1624,9 @@ function CTLD:ValidateZones()
|
|||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
local missing = { Pickup = {}, Drop = {}, FOB = {} }
|
local missing = { Pickup = {}, Drop = {}, FOB = {}, MASH = {} }
|
||||||
local found = { Pickup = {}, Drop = {}, FOB = {} }
|
local found = { Pickup = {}, Drop = {}, FOB = {}, MASH = {} }
|
||||||
local coords = { Pickup = 0, Drop = 0, FOB = 0 }
|
local coords = { Pickup = 0, Drop = 0, FOB = 0, MASH = 0 }
|
||||||
|
|
||||||
for _,z in ipairs(self.Config.Zones.PickupZones or {}) do
|
for _,z in ipairs(self.Config.Zones.PickupZones or {}) do
|
||||||
if z.name then
|
if z.name then
|
||||||
@ -1618,6 +1649,13 @@ function CTLD:ValidateZones()
|
|||||||
coords.FOB = coords.FOB + 1
|
coords.FOB = coords.FOB + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
for _,z in ipairs(self.Config.Zones.MASHZones or {}) do
|
||||||
|
if z.name then
|
||||||
|
if zoneExistsByName(z.name) then table.insert(found.MASH, z.name) else table.insert(missing.MASH, z.name) end
|
||||||
|
elseif z.coord then
|
||||||
|
coords.MASH = coords.MASH + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Log a concise summary to dcs.log
|
-- Log a concise summary to dcs.log
|
||||||
local sideStr = sideToStr(self.Side)
|
local sideStr = sideToStr(self.Side)
|
||||||
@ -1630,8 +1668,11 @@ function CTLD:ValidateZones()
|
|||||||
env.info(string.format('[Moose_CTLD][ZoneValidation][%s] FOB : configured=%d (named=%d, coord=%d) found=%d missing=%d',
|
env.info(string.format('[Moose_CTLD][ZoneValidation][%s] FOB : configured=%d (named=%d, coord=%d) found=%d missing=%d',
|
||||||
sideStr,
|
sideStr,
|
||||||
#(self.Config.Zones.FOBZones or {}), #found.FOB + #missing.FOB, coords.FOB, #found.FOB, #missing.FOB))
|
#(self.Config.Zones.FOBZones or {}), #found.FOB + #missing.FOB, coords.FOB, #found.FOB, #missing.FOB))
|
||||||
|
env.info(string.format('[Moose_CTLD][ZoneValidation][%s] MASH : configured=%d (named=%d, coord=%d) found=%d missing=%d',
|
||||||
|
sideStr,
|
||||||
|
#(self.Config.Zones.MASHZones or {}), #found.MASH + #missing.MASH, coords.MASH, #found.MASH, #missing.MASH))
|
||||||
|
|
||||||
local anyMissing = (#missing.Pickup > 0) or (#missing.Drop > 0) or (#missing.FOB > 0)
|
local anyMissing = (#missing.Pickup > 0) or (#missing.Drop > 0) or (#missing.FOB > 0) or (#missing.MASH > 0)
|
||||||
if anyMissing then
|
if anyMissing then
|
||||||
if #missing.Pickup > 0 then
|
if #missing.Pickup > 0 then
|
||||||
local msg = 'CTLD config warning: Missing Pickup Zones: '..join(missing.Pickup)
|
local msg = 'CTLD config warning: Missing Pickup Zones: '..join(missing.Pickup)
|
||||||
@ -1645,6 +1686,10 @@ function CTLD:ValidateZones()
|
|||||||
local msg = 'CTLD config warning: Missing FOB Zones: '..join(missing.FOB)
|
local msg = 'CTLD config warning: Missing FOB Zones: '..join(missing.FOB)
|
||||||
_msgCoalition(self.Side, msg); env.info('[Moose_CTLD][ZoneValidation]['..sideStr..'] '..msg)
|
_msgCoalition(self.Side, msg); env.info('[Moose_CTLD][ZoneValidation]['..sideStr..'] '..msg)
|
||||||
end
|
end
|
||||||
|
if #missing.MASH > 0 then
|
||||||
|
local msg = 'CTLD config warning: Missing MASH Zones: '..join(missing.MASH)
|
||||||
|
_msgCoalition(self.Side, msg); env.info('[Moose_CTLD][ZoneValidation]['..sideStr..'] '..msg)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
env.info(string.format('[Moose_CTLD][ZoneValidation][%s] All configured zone names resolved successfully.', sideStr))
|
env.info(string.format('[Moose_CTLD][ZoneValidation][%s] All configured zone names resolved successfully.', sideStr))
|
||||||
end
|
end
|
||||||
@ -2010,6 +2055,9 @@ function CTLD:BuildGroupMenus(group)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Logistics -> Show Inventory at Nearest Pickup Zone/FOB
|
||||||
|
CMD('Show Inventory at Nearest Zone', logRoot, function() self:ShowNearestZoneInventory(group) end)
|
||||||
|
|
||||||
-- Field Tools
|
-- Field Tools
|
||||||
CMD('Create Drop Zone (AO)', toolsRoot, function() self:CreateDropZoneAtGroup(group) end)
|
CMD('Create Drop Zone (AO)', toolsRoot, function() self:CreateDropZoneAtGroup(group) end)
|
||||||
local smokeRoot = MENU_GROUP:New(group, 'Smoke My Location', toolsRoot)
|
local smokeRoot = MENU_GROUP:New(group, 'Smoke My Location', toolsRoot)
|
||||||
@ -3730,6 +3778,110 @@ function CTLD:DropLoadedCrates(group, howMany)
|
|||||||
_msgGroup(group, string.format('Reminder: Dropped crates will despawn after %d mins to prevent clutter.', mins))
|
_msgGroup(group, string.format('Reminder: Dropped crates will despawn after %d mins to prevent clutter.', mins))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Show inventory at the nearest pickup zone/FOB
|
||||||
|
function CTLD:ShowNearestZoneInventory(group)
|
||||||
|
local unit = group:GetUnit(1)
|
||||||
|
if not unit or not unit:IsAlive() then return end
|
||||||
|
|
||||||
|
-- Find nearest active pickup zone
|
||||||
|
local zone, dist = self:_nearestActivePickupZone(unit)
|
||||||
|
|
||||||
|
if not zone then
|
||||||
|
_msgGroup(group, 'No active pickup zones found nearby. Move closer to a supply zone.')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local zoneName = zone:GetName()
|
||||||
|
local isMetric = _getPlayerIsMetric(unit)
|
||||||
|
local rngV, rngU = _fmtRange(dist, isMetric)
|
||||||
|
|
||||||
|
-- Get inventory for this zone
|
||||||
|
local stockTbl = CTLD._stockByZone[zoneName] or {}
|
||||||
|
|
||||||
|
-- Build the inventory display
|
||||||
|
local lines = {}
|
||||||
|
table.insert(lines, string.format('Inventory at %s', zoneName))
|
||||||
|
table.insert(lines, string.format('Distance: %.1f %s', rngV, rngU))
|
||||||
|
table.insert(lines, '')
|
||||||
|
|
||||||
|
-- Check if inventory system is enabled
|
||||||
|
local invEnabled = self.Config.Inventory and self.Config.Inventory.Enabled ~= false
|
||||||
|
if not invEnabled then
|
||||||
|
table.insert(lines, 'Inventory tracking is disabled - all items available.')
|
||||||
|
_msgGroup(group, table.concat(lines, '\n'), 20)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Count total items and organize by category
|
||||||
|
local totalItems = 0
|
||||||
|
local byCategory = {}
|
||||||
|
|
||||||
|
for key, count in pairs(stockTbl) do
|
||||||
|
if count > 0 then
|
||||||
|
local def = self.Config.CrateCatalog[key]
|
||||||
|
if def and ((not def.side) or def.side == self.Side) then
|
||||||
|
local cat = (def.menuCategory or 'Other')
|
||||||
|
byCategory[cat] = byCategory[cat] or {}
|
||||||
|
table.insert(byCategory[cat], {
|
||||||
|
key = key,
|
||||||
|
name = def.menu or def.description or key,
|
||||||
|
count = count,
|
||||||
|
isRecipe = (type(def.requires) == 'table')
|
||||||
|
})
|
||||||
|
totalItems = totalItems + count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if totalItems == 0 then
|
||||||
|
table.insert(lines, 'No items in stock at this location.')
|
||||||
|
table.insert(lines, 'Request resupply or move to another zone.')
|
||||||
|
else
|
||||||
|
table.insert(lines, string.format('Total items in stock: %d', totalItems))
|
||||||
|
table.insert(lines, '')
|
||||||
|
|
||||||
|
-- Sort categories for consistent display
|
||||||
|
local categories = {}
|
||||||
|
for cat, _ in pairs(byCategory) do
|
||||||
|
table.insert(categories, cat)
|
||||||
|
end
|
||||||
|
table.sort(categories)
|
||||||
|
|
||||||
|
-- Display items by category
|
||||||
|
for _, cat in ipairs(categories) do
|
||||||
|
table.insert(lines, string.format('-- %s --', cat))
|
||||||
|
local items = byCategory[cat]
|
||||||
|
-- Sort items by name
|
||||||
|
table.sort(items, function(a, b) return a.name < b.name end)
|
||||||
|
for _, item in ipairs(items) do
|
||||||
|
if item.isRecipe then
|
||||||
|
-- For recipes, calculate available bundles
|
||||||
|
local def = self.Config.CrateCatalog[item.key]
|
||||||
|
local bundles = math.huge
|
||||||
|
if def and def.requires then
|
||||||
|
for reqKey, qty in pairs(def.requires) do
|
||||||
|
local have = tonumber(stockTbl[reqKey] or 0) or 0
|
||||||
|
local need = tonumber(qty or 0) or 0
|
||||||
|
if need > 0 then
|
||||||
|
bundles = math.min(bundles, math.floor(have / need))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if bundles == math.huge then bundles = 0 end
|
||||||
|
table.insert(lines, string.format(' %s: %d bundle%s', item.name, bundles, (bundles == 1 and '' or 's')))
|
||||||
|
else
|
||||||
|
table.insert(lines, string.format(' %s: %d', item.name, item.count))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(lines, '')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Display the inventory
|
||||||
|
_msgGroup(group, table.concat(lines, '\n'), 30)
|
||||||
|
end
|
||||||
|
|
||||||
-- #endregion Loaded crate management
|
-- #endregion Loaded crate management
|
||||||
|
|
||||||
-- =========================
|
-- =========================
|
||||||
@ -4865,59 +5017,22 @@ function CTLD:_InitMASHZones()
|
|||||||
local cfg = CTLD.MEDEVAC
|
local cfg = CTLD.MEDEVAC
|
||||||
if not cfg or not cfg.Enabled then return end
|
if not cfg or not cfg.Enabled then return end
|
||||||
|
|
||||||
-- Load fixed MASH zones from config
|
-- Fixed MASH zones are now initialized via InitZones() in the standard Zones structure
|
||||||
for _, zoneConfig in ipairs(cfg.MASHZones or {}) do
|
-- This function now focuses on setting up mobile MASH tracking and announcements
|
||||||
if zoneConfig.name then
|
|
||||||
local zone = ZONE:FindByName(zoneConfig.name)
|
|
||||||
if zone then
|
|
||||||
CTLD._mashZones[zoneConfig.name] = {
|
|
||||||
zone = zone,
|
|
||||||
side = self.Side,
|
|
||||||
isMobile = false,
|
|
||||||
radius = zoneConfig.radius or cfg.MASHZoneRadius or 500,
|
|
||||||
freq = zoneConfig.freq
|
|
||||||
}
|
|
||||||
env.info('[Moose_CTLD][MEDEVAC] Registered MASH zone: '..zoneConfig.name)
|
|
||||||
else
|
|
||||||
env.info('[Moose_CTLD][MEDEVAC] WARNING: MASH zone not found in mission: '..zoneConfig.name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Draw MASH zones on map
|
-- Register fixed MASH zones in the global _mashZones table for delivery detection
|
||||||
if cfg.MapMarkers and cfg.MapMarkers.Enabled then
|
-- (mobile MASH zones will be added dynamically when built)
|
||||||
self:_DrawMASHZones()
|
for _, mz in ipairs(self.MASHZones or {}) do
|
||||||
end
|
local name = mz:GetName()
|
||||||
end
|
local zdef = self._ZoneDefs.MASHZones[name]
|
||||||
|
CTLD._mashZones[name] = {
|
||||||
-- Draw MASH zones on F10 map
|
zone = mz,
|
||||||
function CTLD:_DrawMASHZones()
|
side = self.Side,
|
||||||
local cfg = CTLD.MEDEVAC
|
isMobile = false,
|
||||||
if not cfg or not cfg.Enabled then return end
|
radius = (zdef and zdef.radius) or cfg.MASHZoneRadius or 500,
|
||||||
|
freq = (zdef and zdef.freq) or nil
|
||||||
local md = self.Config.MapDraw
|
}
|
||||||
if not md or not md.Enabled then return end
|
env.info('[Moose_CTLD][MEDEVAC] Registered fixed MASH zone: '..name)
|
||||||
|
|
||||||
for zoneName, mashData in pairs(CTLD._mashZones) do
|
|
||||||
if mashData.side == self.Side then
|
|
||||||
local zone = mashData.zone
|
|
||||||
if zone then
|
|
||||||
local p, r = self:_getZoneCenterAndRadius(zone)
|
|
||||||
if p and r then
|
|
||||||
local circleId = _nextMarkupId()
|
|
||||||
local textId = _nextMarkupId()
|
|
||||||
|
|
||||||
local borderColor = cfg.MASHZoneColors.border or {1, 1, 0, 0.85}
|
|
||||||
local fillColor = cfg.MASHZoneColors.fill or {1, 0.75, 0.8, 0.25}
|
|
||||||
|
|
||||||
trigger.action.circleToCoalition(self.Side, circleId, p, r, borderColor, fillColor, 1, true, "")
|
|
||||||
|
|
||||||
local label = string.format('MASH: %s', zoneName)
|
|
||||||
local textPos = {x = p.x, y = 0, z = p.z - r - 50}
|
|
||||||
trigger.action.textToCoalition(self.Side, textId, textPos, {1,1,1,0.9}, {0,0,0,0}, 18, true, label)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,7 @@ ctldBlue = _MOOSE_CTLD:New({
|
|||||||
PickupZones = { { name = 'ALPHA', smoke = trigger.smokeColor.Blue, flag = 9001, activeWhen = 0 } },
|
PickupZones = { { name = 'ALPHA', smoke = trigger.smokeColor.Blue, flag = 9001, activeWhen = 0 } },
|
||||||
DropZones = { { name = 'BRAVO', flag = 9002, activeWhen = 0 } },
|
DropZones = { { name = 'BRAVO', flag = 9002, activeWhen = 0 } },
|
||||||
FOBZones = { { name = 'CHARLIE', flag = 9003, activeWhen = 0 } },
|
FOBZones = { { name = 'CHARLIE', flag = 9003, activeWhen = 0 } },
|
||||||
|
--MASHZones = { { name = 'MASH Alpha', freq = '251.0 AM', radius = 500, flag = 9010, activeWhen = 0 } },
|
||||||
},
|
},
|
||||||
BuildRequiresGroundCrates = true,
|
BuildRequiresGroundCrates = true,
|
||||||
})
|
})
|
||||||
@ -47,6 +48,7 @@ ctldRed = _MOOSE_CTLD:New({
|
|||||||
PickupZones = { { name = 'DELTA', smoke = trigger.smokeColor.Red, flag = 9101, activeWhen = 0 } },
|
PickupZones = { { name = 'DELTA', smoke = trigger.smokeColor.Red, flag = 9101, activeWhen = 0 } },
|
||||||
DropZones = { { name = 'ECHO', flag = 9102, activeWhen = 0 } },
|
DropZones = { { name = 'ECHO', flag = 9102, activeWhen = 0 } },
|
||||||
FOBZones = { { name = 'FOXTROT', flag = 9103, activeWhen = 0 } },
|
FOBZones = { { name = 'FOXTROT', flag = 9103, activeWhen = 0 } },
|
||||||
|
--MASHZones = { { name = 'MASH Bravo', freq = '252.0 AM', radius = 500, flag = 9111, activeWhen = 0 } },
|
||||||
},
|
},
|
||||||
BuildRequiresGroundCrates = true,
|
BuildRequiresGroundCrates = true,
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user