mirror of
https://github.com/iTracerFacer/DCS_MissionDev.git
synced 2025-12-03 04:14:46 +00:00
Official Release of Insurgent Sandstorm 2.0 - Ripped out all of the old CTLD, put in all of my new scripts, updating those where needed for bugs and portability.
This commit is contained in:
parent
7dfe72afc6
commit
bb57d306b4
@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<buildpath>
|
|
||||||
<buildpathentry kind="src" path="src"/>
|
|
||||||
<buildpathentry combineaccessrules="false" kind="prj" path="/Moose_Framework"/>
|
|
||||||
</buildpath>
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>DCS_Afgainistan</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.dltk.core.scriptbuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.ldt.nature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
Grammar__default_id=lua-5.1
|
|
||||||
eclipse.preferences.version=1
|
|
||||||
Binary file not shown.
@ -63,9 +63,11 @@ local redCfg = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Zones = {
|
Zones = {
|
||||||
PickupZones = { { name = 'ReadLoadZone1', flag = 9101, activeWhen = 0 },
|
PickupZones = { { name = 'RedLoadZone1', flag = 9101, activeWhen = 0 },
|
||||||
{ name = "ReadLoadZone2", flag = 9104, activeWhen = 0 },
|
{ name = "RedLoadZone2", flag = 9104, activeWhen = 0 },
|
||||||
{ name = "ReadLoadZone3", flag = 9105, activeWhen = 0 } },
|
{ name = "RedLoadZone3", flag = 9105, activeWhen = 0 },
|
||||||
|
{ name = "RedLoadZone4", flag = 9106, activeWhen = 0 },
|
||||||
|
{ name = "RedLoadZone5", flag = 9107, 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 } },
|
--MASHZones = { { name = 'MASH Bravo', freq = '252.0 AM', radius = 500, flag = 9111, activeWhen = 0 } },
|
||||||
|
|||||||
@ -212,8 +212,8 @@ end
|
|||||||
-- ==========================================
|
-- ==========================================
|
||||||
|
|
||||||
-- Storage for all zone capture objects and metadata
|
-- Storage for all zone capture objects and metadata
|
||||||
local zoneCaptureObjects = {}
|
zoneCaptureObjects = {}
|
||||||
local zoneNames = {}
|
zoneNames = {}
|
||||||
local zoneMetadata = {} -- Stores coalition ownership info
|
local zoneMetadata = {} -- Stores coalition ownership info
|
||||||
|
|
||||||
-- Function to initialize all zones from configuration
|
-- Function to initialize all zones from configuration
|
||||||
@ -1065,7 +1065,9 @@ end
|
|||||||
local function SetupZoneStatusCommands()
|
local function SetupZoneStatusCommands()
|
||||||
-- Add F10 radio menu commands for BLUE coalition
|
-- Add F10 radio menu commands for BLUE coalition
|
||||||
if US_CC then
|
if US_CC then
|
||||||
local USMenu = MENU_COALITION:New( coalition.side.BLUE, "Zone Control" )
|
-- Use MenuManager to create zone control menu under Mission Options
|
||||||
|
local USMenu = MenuManager and MenuManager.CreateCoalitionMenu(coalition.side.BLUE, "Zone Control")
|
||||||
|
or MENU_COALITION:New( coalition.side.BLUE, "Zone Control" )
|
||||||
MENU_COALITION_COMMAND:New( coalition.side.BLUE, "Get Zone Status Report", USMenu, BroadcastZoneStatus )
|
MENU_COALITION_COMMAND:New( coalition.side.BLUE, "Get Zone Status Report", USMenu, BroadcastZoneStatus )
|
||||||
|
|
||||||
MENU_COALITION_COMMAND:New( coalition.side.BLUE, "Check Victory Progress", USMenu, function()
|
MENU_COALITION_COMMAND:New( coalition.side.BLUE, "Check Victory Progress", USMenu, function()
|
||||||
@ -1097,7 +1099,9 @@ local function SetupZoneStatusCommands()
|
|||||||
|
|
||||||
-- Add F10 radio menu commands for RED coalition
|
-- Add F10 radio menu commands for RED coalition
|
||||||
if RU_CC then
|
if RU_CC then
|
||||||
local RUMenu = MENU_COALITION:New( coalition.side.RED, "Zone Control" )
|
-- Use MenuManager to create zone control menu under Mission Options
|
||||||
|
local RUMenu = MenuManager and MenuManager.CreateCoalitionMenu(coalition.side.RED, "Zone Control")
|
||||||
|
or MENU_COALITION:New( coalition.side.RED, "Zone Control" )
|
||||||
MENU_COALITION_COMMAND:New( coalition.side.RED, "Get Zone Status Report", RUMenu, BroadcastZoneStatus )
|
MENU_COALITION_COMMAND:New( coalition.side.RED, "Get Zone Status Report", RUMenu, BroadcastZoneStatus )
|
||||||
|
|
||||||
MENU_COALITION_COMMAND:New( coalition.side.RED, "Check Victory Progress", RUMenu, function()
|
MENU_COALITION_COMMAND:New( coalition.side.RED, "Check Victory Progress", RUMenu, function()
|
||||||
|
|||||||
@ -1,34 +1,36 @@
|
|||||||
|
-- Disable MOOSE's automatic F10 menus
|
||||||
|
_SETTINGS:SetPlayerMenuOff() -- Disables the "Settings" F10 menu
|
||||||
|
-- Note: MOOSE does not add scoring menus by default unless SCORING objects are created
|
||||||
|
|
||||||
local ENABLE_SAMS = true -- used for testing purposes. Set to true to enable SAMs, false to disable.
|
local ENABLE_SAMS = true -- used for testing purposes. Set to true to enable SAMs, false to disable.
|
||||||
local TAC_DISPLAY = false -- Set to false to disable Tacview display for AI flights (default = false)
|
|
||||||
|
|
||||||
-- How many red/blue aircraft are in the air by default.
|
-- Build Command Center and Mission for Blue Coalition
|
||||||
local RedA2ADefaultOverhead = 1.5
|
local blueHQ = GROUP:FindByName("BLUEHQ")
|
||||||
local RedDefaultCAP = 1
|
if blueHQ then
|
||||||
local BlueA2ADefaultOverhead = 1.5
|
US_CC = COMMANDCENTER:New(blueHQ, "USA HQ")
|
||||||
local BlueDefaultCAP = 1
|
US_Mission = MISSION:New(US_CC, "Insurgent Sandstorm", "Primary", "", coalition.side.BLUE)
|
||||||
|
US_Mission:GetCommandCenter():SetMenu() -- Disable mission F10 menu
|
||||||
-- Create the main mission menu.
|
--US_Score = SCORING:New("Operation Polar Hammer") -- Commented out to prevent Scoring F10 menu
|
||||||
missionMenu = MENU_MISSION:New("Mission Menu")
|
--US_Mission:AddScoring(US_Score)
|
||||||
|
--US_Mission:Start()
|
||||||
--Build Command Center and Mission for Blue
|
env.info("Blue Coalition Command Center and Mission started successfully")
|
||||||
US_CC = COMMANDCENTER:New( GROUP:FindByName( "BLUEHQ" ), "USA HQ" )
|
else
|
||||||
US_Mission = MISSION:New( US_CC, "Insurgent Sandstorm", "Primary", "Clear the front lines of enemy activity.", coalition.side.BLUE)
|
env.info("ERROR: BLUEHQ group not found! Blue mission will not start.")
|
||||||
US_Score = SCORING:New( "Insurgent Sandstorm - Blue" )
|
end
|
||||||
US_Mission:AddScoring( US_Score )
|
|
||||||
US_Mission:Start()
|
|
||||||
US_Score:SetMessagesHit(false)
|
|
||||||
US_Score:SetMessagesDestroy(false)
|
|
||||||
US_Score:SetMessagesScore(false)
|
|
||||||
|
|
||||||
--Build Command Center and Mission Red
|
--Build Command Center and Mission Red
|
||||||
RU_CC = COMMANDCENTER:New( GROUP:FindByName( "REDHQ" ), "Russia HQ" )
|
local redHQ = GROUP:FindByName("REDHQ")
|
||||||
RU_Mission = MISSION:New (RU_CC, "Insurgent Sandstorm", "Primary", "Destroy U.S. and NATO forces.", coalition.side.RED)
|
if redHQ then
|
||||||
RU_Score = SCORING:New("Insurgent Sandstorm - Red")
|
RU_CC = COMMANDCENTER:New(redHQ, "Russia HQ")
|
||||||
RU_Mission:AddScoring( RU_Score)
|
RU_Mission = MISSION:New(RU_CC, "Insurgent Sandstorm", "Primary", "Hold what we have, take what we don't.", coalition.side.RED)
|
||||||
RU_Mission:Start()
|
RU_Mission:GetCommandCenter():SetMenu() -- Disable mission F10 menu
|
||||||
RU_Score:SetMessagesHit(false)
|
--RU_Score = SCORING:New("Operation Polar Shield") -- Commented out to prevent Scoring F10 menu
|
||||||
RU_Score:SetMessagesDestroy(false)
|
--RU_Mission:AddScoring(RU_Score)
|
||||||
RU_Score:SetMessagesScore(false)
|
RU_Mission:Start()
|
||||||
|
env.info("Red Coalition Command Center and Mission started successfully")
|
||||||
|
else
|
||||||
|
env.info("ERROR: REDHQ group not found! Red mission will not start.")
|
||||||
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Setup SAM Systems
|
-- Setup SAM Systems
|
||||||
@ -116,59 +118,7 @@ end
|
|||||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Setup Air Dispatchers for RED and BLUE
|
-- Setup Air Dispatchers for RED and BLUE
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
--now handled by TADC system.
|
||||||
BLUEBorderZone = ZONE_POLYGON:New( "BLUE BORDER", GROUP:FindByName( "BLUE BORDER" ) )
|
|
||||||
BLUEA2ADispatcher = AI_A2A_GCICAP:NewWithBorder( { "BLUE EWR" }, { "FIGHTER SWEEP BLUE" }, 'BLUE BORDER', 'BLUE BORDER', BlueDefaultCAP, 10000, 50000, 75000, 100)
|
|
||||||
BLUEA2ADispatcher:SetDefaultLandingAtRunway()
|
|
||||||
BLUEA2ADispatcher:SetDefaultTakeoffInAir()
|
|
||||||
BLUEA2ADispatcher:SetTacticalDisplay(TAC_DISPLAY)
|
|
||||||
BLUEA2ADispatcher:SetDefaultFuelThreshold( 0.20 )
|
|
||||||
BLUEA2ADispatcher:SetRefreshTimeInterval( 300 )
|
|
||||||
BLUEA2ADispatcher:SetDefaultOverhead(BlueA2ADefaultOverhead)
|
|
||||||
BLUEA2ADispatcher:SetDisengageRadius( 100000 )
|
|
||||||
BLUEA2ADispatcher:SetEngageRadius( 50000 )
|
|
||||||
BLUEA2ADispatcher:SetGciRadius( 75000 )
|
|
||||||
|
|
||||||
CCCPBorderZone = ZONE_POLYGON:New( "RED BORDER", GROUP:FindByName( "RED BORDER" ) )
|
|
||||||
RedA2ADispatcher = AI_A2A_GCICAP:NewWithBorder( { "RED EWR" }, { "FIGHTER SWEEP RED" }, "RED BORDER", "RED BORDER", RedDefaultCAP, 10000, 50000, 75000, 100)
|
|
||||||
RedA2ADispatcher:SetDefaultLandingAtRunway()
|
|
||||||
RedA2ADispatcher:SetDefaultTakeoffInAir()
|
|
||||||
RedA2ADispatcher:SetTacticalDisplay(TAC_DISPLAY)
|
|
||||||
RedA2ADispatcher:SetDefaultFuelThreshold( 0.20 )
|
|
||||||
RedA2ADispatcher:SetRefreshTimeInterval( 300 )
|
|
||||||
RedA2ADispatcher:SetDefaultOverhead(RedA2ADefaultOverhead)
|
|
||||||
RedA2ADispatcher:SetDisengageRadius( 100000 )
|
|
||||||
RedA2ADispatcher:SetEngageRadius( 50000 )
|
|
||||||
RedA2ADispatcher:SetGciRadius( 75000 )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DwyerBorderZone = ZONE_POLYGON:New( "DwyerBorderZone", GROUP:FindByName( "DwyerBorderZone" ) )
|
|
||||||
DwyerDispatcher = AI_A2A_GCICAP:NewWithBorder( { "RED EWR" }, { "DwyerBorderCAP" }, "DwyerBorderZone", "DwyerBorderZone", RedDefaultCAP, 10000, 50000, 75000, 100)
|
|
||||||
DwyerDispatcher:SetDefaultLandingAtRunway()
|
|
||||||
DwyerDispatcher:SetDefaultTakeoffInAir()
|
|
||||||
DwyerDispatcher:SetBorderZone( DwyerBorderZone )
|
|
||||||
DwyerDispatcher:SetTacticalDisplay(TAC_DISPLAY)
|
|
||||||
DwyerDispatcher:SetDefaultFuelThreshold( 0.20 )
|
|
||||||
DwyerDispatcher:SetRefreshTimeInterval( 300 )
|
|
||||||
DwyerDispatcher:SetDefaultOverhead(RedA2ADefaultOverhead)
|
|
||||||
DwyerDispatcher:SetDisengageRadius( 100000 )
|
|
||||||
DwyerDispatcher:SetEngageRadius( 50000 )
|
|
||||||
DwyerDispatcher:SetGciRadius( 75000 )
|
|
||||||
|
|
||||||
|
|
||||||
BostZone = ZONE_POLYGON:New( "BostBorderZone", GROUP:FindByName( "BostBorderZone" ) )
|
|
||||||
BostDispatcher = AI_A2A_GCICAP:NewWithBorder( { "RED EWR" }, { "BostBorderCAP" }, "BostBorderZone", "BostBorderZone", RedDefaultCAP, 10000, 50000, 75000, 100)
|
|
||||||
BostDispatcher:SetDefaultLandingAtRunway()
|
|
||||||
BostDispatcher:SetDefaultTakeoffInAir()
|
|
||||||
BostDispatcher:SetBorderZone(BostZone)
|
|
||||||
BostDispatcher:SetTacticalDisplay(TAC_DISPLAY)
|
|
||||||
BostDispatcher:SetDefaultFuelThreshold( 0.20 )
|
|
||||||
BostDispatcher:SetRefreshTimeInterval( 300 )
|
|
||||||
BostDispatcher:SetDefaultOverhead(RedA2ADefaultOverhead)
|
|
||||||
BostDispatcher:SetDisengageRadius( 100000 )
|
|
||||||
BostDispatcher:SetEngageRadius( 50000 )
|
|
||||||
BostDispatcher:SetGciRadius( 75000 )
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Clean up the airbases of debris and stuck aircraft.
|
-- Clean up the airbases of debris and stuck aircraft.
|
||||||
|
|||||||
@ -56,12 +56,12 @@ end
|
|||||||
local CARGO_SUPPLY_CONFIG = {
|
local CARGO_SUPPLY_CONFIG = {
|
||||||
red = {
|
red = {
|
||||||
supplyAirfields = { "Farah", "Nimroz", "Herat", "Shindand" }, -- replace with your RED supply airbase names
|
supplyAirfields = { "Farah", "Nimroz", "Herat", "Shindand" }, -- replace with your RED supply airbase names
|
||||||
cargoTemplate = "CARGO_RED_AN26", -- replace with your RED cargo aircraft template name
|
cargoTemplate = "CARGO_IL-76MD", -- replace with your RED cargo aircraft template name
|
||||||
threshold = 0.90 -- ratio below which to trigger resupply (testing)
|
threshold = 0.90 -- ratio below which to trigger resupply (testing)
|
||||||
},
|
},
|
||||||
blue = {
|
blue = {
|
||||||
supplyAirfields = { "Sharana", "Tarinkot" }, -- replace with your BLUE supply airbase names
|
supplyAirfields = { "Sharana", "Tarinkot" }, -- replace with your BLUE supply airbase names
|
||||||
cargoTemplate = "CARGO_BLUE_C130", -- replace with your BLUE cargo aircraft template name
|
cargoTemplate = "CARGO_C-130", -- replace with your BLUE cargo aircraft template name
|
||||||
threshold = 0.90 -- ratio below which to trigger resupply (testing)
|
threshold = 0.90 -- ratio below which to trigger resupply (testing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,8 +90,8 @@ RED_SQUADRON_CONFIG = {
|
|||||||
type = "FIGHTER",
|
type = "FIGHTER",
|
||||||
|
|
||||||
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
|
primaryZone = "BostBorderZone", -- Main responsibility area (zone name from mission editor)
|
||||||
secondaryZone = nil, -- Secondary coverage area (zone name)
|
secondaryZone = "DwyerBorderZone", -- Secondary coverage area (zone name)
|
||||||
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
-- Zone behavior settings (optional - uses defaults if not specified)
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
@ -118,8 +118,8 @@ RED_SQUADRON_CONFIG = {
|
|||||||
type = "FIGHTER",
|
type = "FIGHTER",
|
||||||
|
|
||||||
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
|
primaryZone = "DwyerBorderZone", -- Main responsibility area (zone name from mission editor)
|
||||||
secondaryZone = nil, -- Secondary coverage area (zone name)
|
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
|
||||||
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
-- Zone behavior settings (optional - uses defaults if not specified)
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
@ -146,8 +146,8 @@ RED_SQUADRON_CONFIG = {
|
|||||||
type = "FIGHTER",
|
type = "FIGHTER",
|
||||||
|
|
||||||
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
|
primaryZone = "DwyerBorderZone", -- Main responsibility area (zone name from mission editor)
|
||||||
secondaryZone = nil, -- Secondary coverage area (zone name)
|
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
|
||||||
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
-- Zone behavior settings (optional - uses defaults if not specified)
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
@ -173,8 +173,8 @@ RED_SQUADRON_CONFIG = {
|
|||||||
type = "FIGHTER",
|
type = "FIGHTER",
|
||||||
|
|
||||||
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
|
primaryZone = "DwyerBorderZone", -- Main responsibility area (zone name from mission editor)
|
||||||
secondaryZone = nil, -- Secondary coverage area (zone name)
|
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
|
||||||
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
-- Zone behavior settings (optional - uses defaults if not specified)
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
@ -199,9 +199,9 @@ RED_SQUADRON_CONFIG = {
|
|||||||
type = "FIGHTER",
|
type = "FIGHTER",
|
||||||
|
|
||||||
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
|
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
|
||||||
secondaryZone = nil, -- Secondary coverage area (zone name)
|
secondaryZone = "DwyerBorderZone", -- Secondary coverage area (zone name)
|
||||||
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
tertiaryZone = "BostBorderZone", -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
-- Zone behavior settings (optional - uses defaults if not specified)
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
zoneConfig = {
|
zoneConfig = {
|
||||||
@ -225,9 +225,9 @@ RED_SQUADRON_CONFIG = {
|
|||||||
type = "FIGHTER",
|
type = "FIGHTER",
|
||||||
|
|
||||||
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
|
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
|
||||||
secondaryZone = nil, -- Secondary coverage area (zone name)
|
secondaryZone = "DwyerBorderZone", -- Secondary coverage area (zone name)
|
||||||
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
tertiaryZone = "BostBorderZone", -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
-- Zone behavior settings (optional - uses defaults if not specified)
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
zoneConfig = {
|
zoneConfig = {
|
||||||
@ -251,9 +251,9 @@ RED_SQUADRON_CONFIG = {
|
|||||||
type = "FIGHTER",
|
type = "FIGHTER",
|
||||||
|
|
||||||
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
|
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
|
||||||
secondaryZone = nil, -- Secondary coverage area (zone name)
|
secondaryZone = "DwyerBorderZone", -- Secondary coverage area (zone name)
|
||||||
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
|
tertiaryZone = "BostBorderZone", -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
-- Zone behavior settings (optional - uses defaults if not specified)
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
zoneConfig = {
|
zoneConfig = {
|
||||||
@ -266,6 +266,112 @@ RED_SQUADRON_CONFIG = {
|
|||||||
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
|
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ templateName = "Bost MiG-21", -- Change to your RED template name
|
||||||
|
displayName = "Bost MiG-21", -- Change to your preferred name
|
||||||
|
airbaseName = "Bost", -- Change to your RED airbase
|
||||||
|
aircraft = 14, -- Adjust aircraft count
|
||||||
|
skill = AI.Skill.ACE, -- AVERAGE, GOOD, HIGH, EXCELLENT
|
||||||
|
altitude = 20000, -- Patrol altitude (feet)
|
||||||
|
speed = 350, -- Patrol speed (knots)
|
||||||
|
patrolTime = 25, -- Time on station (minutes)
|
||||||
|
type = "FIGHTER",
|
||||||
|
|
||||||
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
|
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
|
||||||
|
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
|
||||||
|
tertiaryZone = "DwyerBorderZone", -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
|
zoneConfig = {
|
||||||
|
primaryResponse = 1.0, -- Intercept ratio multiplier in primary zone
|
||||||
|
secondaryResponse = 0.6, -- Intercept ratio multiplier in secondary zone
|
||||||
|
tertiaryResponse = 1.4, -- Intercept ratio multiplier in tertiary zone
|
||||||
|
maxRange = 200, -- Maximum engagement range from airbase (nm)
|
||||||
|
enableFallback = false, -- Auto-switch to tertiary when base threatened
|
||||||
|
priorityThreshold = 4, -- Min aircraft count for "major threat"
|
||||||
|
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ templateName = "Bost Su-27", -- Change to your RED template name
|
||||||
|
displayName = "Bost Su-27", -- Change to your preferred name
|
||||||
|
airbaseName = "Bost", -- Change to your RED airbase
|
||||||
|
aircraft = 12, -- Adjust aircraft count
|
||||||
|
skill = AI.Skill.ACE, -- AVERAGE, GOOD, HIGH, EXCELLENT
|
||||||
|
altitude = 20000, -- Patrol altitude (feet)
|
||||||
|
speed = 350, -- Patrol speed (knots)
|
||||||
|
patrolTime = 25, -- Time on station (minutes)
|
||||||
|
type = "FIGHTER",
|
||||||
|
|
||||||
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
|
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
|
||||||
|
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
|
||||||
|
tertiaryZone = "DwyerBorderZone", -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
|
zoneConfig = {
|
||||||
|
primaryResponse = 1.0, -- Intercept ratio multiplier in primary zone
|
||||||
|
secondaryResponse = 0.6, -- Intercept ratio multiplier in secondary zone
|
||||||
|
tertiaryResponse = 1.4, -- Intercept ratio multiplier in tertiary zone
|
||||||
|
maxRange = 200, -- Maximum engagement range from airbase (nm)
|
||||||
|
enableFallback = false, -- Auto-switch to tertiary when base threatened
|
||||||
|
priorityThreshold = 4, -- Min aircraft count for "major threat"
|
||||||
|
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ templateName = "Dwyer MiG-23MLD", -- Change to your RED template name
|
||||||
|
displayName = "Dwyer MiG-23MLD", -- Change to your preferred name
|
||||||
|
airbaseName = "Dwyer", -- Change to your RED airbase
|
||||||
|
aircraft = 12, -- Adjust aircraft count
|
||||||
|
skill = AI.Skill.ACE, -- AVERAGE, GOOD, HIGH, EXCELLENT
|
||||||
|
altitude = 20000, -- Patrol altitude (feet)
|
||||||
|
speed = 350, -- Patrol speed (knots)
|
||||||
|
patrolTime = 25, -- Time on station (minutes)
|
||||||
|
type = "FIGHTER",
|
||||||
|
|
||||||
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
|
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
|
||||||
|
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
|
||||||
|
tertiaryZone = "DwyerBorderZone", -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
|
zoneConfig = {
|
||||||
|
primaryResponse = 1.0, -- Intercept ratio multiplier in primary zone
|
||||||
|
secondaryResponse = 0.6, -- Intercept ratio multiplier in secondary zone
|
||||||
|
tertiaryResponse = 1.4, -- Intercept ratio multiplier in tertiary zone
|
||||||
|
maxRange = 200, -- Maximum engagement range from airbase (nm)
|
||||||
|
enableFallback = false, -- Auto-switch to tertiary when base threatened
|
||||||
|
priorityThreshold = 4, -- Min aircraft count for "major threat"
|
||||||
|
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
templateName = "Dwyer Su-27", -- Change to your RED template name
|
||||||
|
displayName = "Dwyer Su-27", -- Change to your preferred name
|
||||||
|
airbaseName = "Dwyer", -- Change to your RED airbase
|
||||||
|
aircraft = 12, -- Adjust aircraft count
|
||||||
|
skill = AI.Skill.ACE, -- AVERAGE, GOOD, HIGH, EXCELLENT
|
||||||
|
altitude = 20000, -- Patrol altitude (feet)
|
||||||
|
speed = 350, -- Patrol speed (knots)
|
||||||
|
patrolTime = 25, -- Time on station (minutes)
|
||||||
|
type = "FIGHTER",
|
||||||
|
|
||||||
|
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
|
||||||
|
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
|
||||||
|
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
|
||||||
|
tertiaryZone = "DwyerBorderZone", -- Emergency/fallback zone (zone name)
|
||||||
|
|
||||||
|
-- Zone behavior settings (optional - uses defaults if not specified)
|
||||||
|
zoneConfig = {
|
||||||
|
primaryResponse = 1.0, -- Intercept ratio multiplier in primary zone
|
||||||
|
secondaryResponse = 0.6, -- Intercept ratio multiplier in secondary zone
|
||||||
|
tertiaryResponse = 1.4, -- Intercept ratio multiplier in tertiary zone
|
||||||
|
maxRange = 200, -- Maximum engagement range from airbase (nm)
|
||||||
|
enableFallback = false, -- Auto-switch to tertiary when base threatened
|
||||||
|
priorityThreshold = 4, -- Min aircraft count for "major threat"
|
||||||
|
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
-- ═══════════════════════════════════════════════════════════════════════════
|
-- ═══════════════════════════════════════════════════════════════════════════
|
||||||
@ -369,6 +475,6 @@ BLUE_SQUADRON_CONFIG = {
|
|||||||
priorityThreshold = 4, -- Min aircraft count for "major threat"
|
priorityThreshold = 4, -- Min aircraft count for "major threat"
|
||||||
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
|
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,4 +0,0 @@
|
|||||||
local function main()
|
|
||||||
|
|
||||||
end
|
|
||||||
main()
|
|
||||||
316
Moose_.lua
316
Moose_.lua
@ -1,4 +1,4 @@
|
|||||||
env.info('*** MOOSE GITHUB Commit Hash ID: 2025-11-14T17:27:02+01:00-cdbf1e147e76dcfab3d1bc471edf593a0e92182a ***')
|
env.info('*** MOOSE GITHUB Commit Hash ID: 2025-11-16T16:54:04+01:00-5d1123e7df5a5578924c48a5dd93386739269191 ***')
|
||||||
if not MOOSE_DEVELOPMENT_FOLDER then
|
if not MOOSE_DEVELOPMENT_FOLDER then
|
||||||
MOOSE_DEVELOPMENT_FOLDER='Scripts'
|
MOOSE_DEVELOPMENT_FOLDER='Scripts'
|
||||||
end
|
end
|
||||||
@ -19229,41 +19229,6 @@ return nil
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
do
|
do
|
||||||
POINT_VEC3={
|
|
||||||
ClassName="POINT_VEC3",
|
|
||||||
Metric=true,
|
|
||||||
RoutePointAltType={
|
|
||||||
BARO="BARO",
|
|
||||||
},
|
|
||||||
RoutePointType={
|
|
||||||
TakeOffParking="TakeOffParking",
|
|
||||||
TurningPoint="Turning Point",
|
|
||||||
},
|
|
||||||
RoutePointAction={
|
|
||||||
FromParkingArea="From Parking Area",
|
|
||||||
TurningPoint="Turning Point",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
function POINT_VEC3:New(x,y,z)
|
|
||||||
local self=BASE:Inherit(self,COORDINATE:New(x,y,z))
|
|
||||||
self:F2(self)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
end
|
|
||||||
do
|
|
||||||
POINT_VEC2={
|
|
||||||
ClassName="POINT_VEC2",
|
|
||||||
}
|
|
||||||
function POINT_VEC2:New(x,y,LandHeightAdd)
|
|
||||||
local LandHeight=land.getHeight({["x"]=x,["y"]=y})
|
|
||||||
LandHeightAdd=LandHeightAdd or 0
|
|
||||||
LandHeight=LandHeight+LandHeightAdd
|
|
||||||
local self=BASE:Inherit(self,COORDINATE:New(x,LandHeight,y))
|
|
||||||
self:F2(self)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
end
|
|
||||||
do
|
|
||||||
VELOCITY={
|
VELOCITY={
|
||||||
ClassName="VELOCITY",
|
ClassName="VELOCITY",
|
||||||
}
|
}
|
||||||
@ -61930,6 +61895,265 @@ end
|
|||||||
self:I({"Detected client spawn and applied internal functions and events.",PlayerName=self.PlayerName,UnitName=self.UnitName,GroupName=self.GroupName})
|
self:I({"Detected client spawn and applied internal functions and events.",PlayerName=self.PlayerName,UnitName=self.UnitName,GroupName=self.GroupName})
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
FORMATION={
|
||||||
|
ClassName="FORMATION",
|
||||||
|
FollowName=nil,
|
||||||
|
FollowUnit=nil,
|
||||||
|
FollowGroupSet=nil,
|
||||||
|
FollowScheduler=nil,
|
||||||
|
OptionROE=AI.Option.Air.val.ROE.OPEN_FIRE,
|
||||||
|
OptionReactionOnThreat=AI.Option.Air.val.REACTION_ON_THREAT.ALLOW_ABORT_MISSION,
|
||||||
|
dtFollow=0.5,
|
||||||
|
}
|
||||||
|
FORMATION.Formation={
|
||||||
|
None=1,
|
||||||
|
Line=2,
|
||||||
|
Trail=3,
|
||||||
|
Stack=4,
|
||||||
|
LeftLine=5,
|
||||||
|
RightLine=6,
|
||||||
|
LeftWing=7,
|
||||||
|
RightWing=8,
|
||||||
|
Vic=9,
|
||||||
|
Box=10,
|
||||||
|
}
|
||||||
|
function FORMATION:New(FollowUnit,FollowGroupSet,FollowName)
|
||||||
|
local self=BASE:Inherit(self,FSM_SET:New(FollowGroupSet))
|
||||||
|
self:F({FollowUnit,FollowGroupSet,FollowName})
|
||||||
|
self.FollowUnit=FollowUnit
|
||||||
|
self.FollowGroupSet=FollowGroupSet
|
||||||
|
self:SetFlightRandomization(2)
|
||||||
|
self:SetStartState("None")
|
||||||
|
self:AddTransition("*","Stop","Stopped")
|
||||||
|
self:AddTransition({"None","Stopped"},"Start","Following")
|
||||||
|
self:AddTransition("*","FormationLine","*")
|
||||||
|
self:AddTransition("*","FormationTrail","*")
|
||||||
|
self:AddTransition("*","FormationStack","*")
|
||||||
|
self:AddTransition("*","FormationLeftLine","*")
|
||||||
|
self:AddTransition("*","FormationRightLine","*")
|
||||||
|
self:AddTransition("*","FormationLeftWing","*")
|
||||||
|
self:AddTransition("*","FormationRightWing","*")
|
||||||
|
self:AddTransition("*","FormationCenterWing","*")
|
||||||
|
self:AddTransition("*","FormationVic","*")
|
||||||
|
self:AddTransition("*","FormationBox","*")
|
||||||
|
self:AddTransition("*","Follow","Following")
|
||||||
|
self:FormationLeftLine(500,0,250,250)
|
||||||
|
self.FollowName=FollowName
|
||||||
|
self.CT1=0
|
||||||
|
self.GT1=0
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:SetFollowTimeInterval(dt)
|
||||||
|
self.dtFollow=dt or 0.5
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:TestSmokeDirectionVector(SmokeDirection)
|
||||||
|
self.SmokeDirectionVector=(SmokeDirection==true)and true or false
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,ZStart,ZSpace,Formation)
|
||||||
|
self:F({FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,ZStart,ZSpace,Formation})
|
||||||
|
XStart=XStart or self.XStart
|
||||||
|
XSpace=XSpace or self.XSpace
|
||||||
|
YStart=YStart or self.YStart
|
||||||
|
YSpace=YSpace or self.YSpace
|
||||||
|
ZStart=ZStart or self.ZStart
|
||||||
|
ZSpace=ZSpace or self.ZSpace
|
||||||
|
local FollowSet=FollowGroupSet:GetSet()
|
||||||
|
local i=1
|
||||||
|
for FollowID,FollowGroup in pairs(FollowSet)do
|
||||||
|
local PointVec3=COORDINATE:New()
|
||||||
|
PointVec3:SetX(XStart+i*XSpace)
|
||||||
|
PointVec3:SetY(YStart+i*YSpace)
|
||||||
|
PointVec3:SetZ(ZStart+i*ZSpace)
|
||||||
|
local Vec3=PointVec3:GetVec3()
|
||||||
|
FollowGroup:SetState(self,"FormationVec3",Vec3)
|
||||||
|
i=i+1
|
||||||
|
FollowGroup:SetState(FollowGroup,"Formation",Formation)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationTrail(FollowGroupSet,From,Event,To,XStart,XSpace,YStart)
|
||||||
|
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,0,0,self.Formation.Trail)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationStack(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace)
|
||||||
|
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,0,0,self.Formation.Stack)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationLeftLine(FollowGroupSet,From,Event,To,XStart,YStart,ZStart,ZSpace)
|
||||||
|
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,0,YStart,0,-ZStart,-ZSpace,self.Formation.LeftLine)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationRightLine(FollowGroupSet,From,Event,To,XStart,YStart,ZStart,ZSpace)
|
||||||
|
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,0,YStart,0,ZStart,ZSpace,self.Formation.RightLine)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationLeftWing(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,ZStart,ZSpace)
|
||||||
|
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,-ZStart,-ZSpace,self.Formation.LeftWing)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationRightWing(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,ZStart,ZSpace)
|
||||||
|
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,ZStart,ZSpace,self.Formation.RightWing)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationCenterWing(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,ZStart,ZSpace)
|
||||||
|
local FollowSet=FollowGroupSet:GetSet()
|
||||||
|
local i=0
|
||||||
|
for FollowID,FollowGroup in pairs(FollowSet)do
|
||||||
|
local PointVec3=COORDINATE:New()
|
||||||
|
local Side=(i%2==0)and 1 or-1
|
||||||
|
local Row=i/2+1
|
||||||
|
PointVec3:SetX(XStart+Row*XSpace)
|
||||||
|
PointVec3:SetY(YStart)
|
||||||
|
PointVec3:SetZ(Side*(ZStart+i*ZSpace))
|
||||||
|
local Vec3=PointVec3:GetVec3()
|
||||||
|
FollowGroup:SetState(self,"FormationVec3",Vec3)
|
||||||
|
i=i+1
|
||||||
|
FollowGroup:SetState(FollowGroup,"Formation",self.Formation.Vic)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationVic(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,ZStart,ZSpace)
|
||||||
|
self:onafterFormationCenterWing(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,ZStart,ZSpace)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterFormationBox(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,ZStart,ZSpace,ZLevels)
|
||||||
|
local FollowSet=FollowGroupSet:GetSet()
|
||||||
|
local i=0
|
||||||
|
for FollowID,FollowGroup in pairs(FollowSet)do
|
||||||
|
local PointVec3=COORDINATE:New()
|
||||||
|
local ZIndex=i%ZLevels
|
||||||
|
local XIndex=math.floor(i/ZLevels)
|
||||||
|
local YIndex=math.floor(i/ZLevels)
|
||||||
|
PointVec3:SetX(XStart+XIndex*XSpace)
|
||||||
|
PointVec3:SetY(YStart+YIndex*YSpace)
|
||||||
|
PointVec3:SetZ(-ZStart-(ZSpace*ZLevels/2)+ZSpace*ZIndex)
|
||||||
|
local Vec3=PointVec3:GetVec3()
|
||||||
|
FollowGroup:SetState(self,"FormationVec3",Vec3)
|
||||||
|
i=i+1
|
||||||
|
FollowGroup:SetState(FollowGroup,"Formation",self.Formation.Box)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:SetFlightRandomization(FlightRandomization)
|
||||||
|
self.FlightRandomization=FlightRandomization
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function FORMATION:onafterStop(FollowGroupSet,From,Event,To)
|
||||||
|
self:E("Stopping formation.")
|
||||||
|
end
|
||||||
|
function FORMATION:onbeforeFollow(FollowGroupSet,From,Event,To)
|
||||||
|
if From=="Stopped"then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
function FORMATION:onenterFollowing(FollowGroupSet)
|
||||||
|
if self.FollowUnit:IsAlive()then
|
||||||
|
local ClientUnit=self.FollowUnit
|
||||||
|
local CT1,CT2,CV1,CV2
|
||||||
|
CT1=ClientUnit:GetState(self,"CT1")
|
||||||
|
local CuVec3=ClientUnit:GetVec3()
|
||||||
|
if CT1==nil or CT1==0 then
|
||||||
|
ClientUnit:SetState(self,"CV1",CuVec3)
|
||||||
|
ClientUnit:SetState(self,"CT1",timer.getTime())
|
||||||
|
else
|
||||||
|
CT1=ClientUnit:GetState(self,"CT1")
|
||||||
|
CT2=timer.getTime()
|
||||||
|
CV1=ClientUnit:GetState(self,"CV1")
|
||||||
|
CV2=CuVec3
|
||||||
|
ClientUnit:SetState(self,"CT1",CT2)
|
||||||
|
ClientUnit:SetState(self,"CV1",CV2)
|
||||||
|
end
|
||||||
|
for _,_group in pairs(FollowGroupSet:GetSet())do
|
||||||
|
local group=_group
|
||||||
|
if group and group:IsAlive()then
|
||||||
|
self:FollowMe(group,ClientUnit,CT1,CV1,CT2,CV2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:__Follow(-self.dtFollow)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function FORMATION:FollowMe(FollowGroup,ClientUnit,CT1,CV1,CT2,CV2)
|
||||||
|
if not self:Is("Stopped")then
|
||||||
|
self:T({Mode=FollowGroup:GetState(FollowGroup,"Mode")})
|
||||||
|
FollowGroup:OptionROTEvadeFire()
|
||||||
|
FollowGroup:OptionROEReturnFire()
|
||||||
|
local GroupUnit=FollowGroup:GetUnit(1)
|
||||||
|
local GuVec3=GroupUnit:GetVec3()
|
||||||
|
local FollowFormation=FollowGroup:GetState(self,"FormationVec3")
|
||||||
|
if FollowFormation then
|
||||||
|
local FollowDistance=FollowFormation.x
|
||||||
|
local GT1=GroupUnit:GetState(self,"GT1")
|
||||||
|
if CT1==nil or CT1==0 or GT1==nil or GT1==0 then
|
||||||
|
GroupUnit:SetState(self,"GV1",GuVec3)
|
||||||
|
GroupUnit:SetState(self,"GT1",timer.getTime())
|
||||||
|
else
|
||||||
|
local CD=((CV2.x-CV1.x)^2+(CV2.y-CV1.y)^2+(CV2.z-CV1.z)^2)^0.5
|
||||||
|
local CT=CT2-CT1
|
||||||
|
local CS=(3600/CT)*(CD/1000)/3.6
|
||||||
|
local CDv={x=CV2.x-CV1.x,y=CV2.y-CV1.y,z=CV2.z-CV1.z}
|
||||||
|
local Ca=math.atan2(CDv.x,CDv.z)
|
||||||
|
local GT1=GroupUnit:GetState(self,"GT1")
|
||||||
|
local GT2=timer.getTime()
|
||||||
|
local GV1=GroupUnit:GetState(self,"GV1")
|
||||||
|
local GV2=GuVec3
|
||||||
|
GV2.x=GV2.x+math.random(-self.FlightRandomization/2,self.FlightRandomization/2)
|
||||||
|
GV2.y=GV2.y+math.random(-self.FlightRandomization/2,self.FlightRandomization/2)
|
||||||
|
GV2.z=GV2.z+math.random(-self.FlightRandomization/2,self.FlightRandomization/2)
|
||||||
|
GroupUnit:SetState(self,"GT1",GT2)
|
||||||
|
GroupUnit:SetState(self,"GV1",GV2)
|
||||||
|
local GD=((GV2.x-GV1.x)^2+(GV2.y-GV1.y)^2+(GV2.z-GV1.z)^2)^0.5
|
||||||
|
local GT=GT2-GT1
|
||||||
|
local GDv={x=GV2.x-CV1.x,y=GV2.y-CV1.y,z=GV2.z-CV1.z}
|
||||||
|
local Alpha_T=math.atan2(GDv.x,GDv.z)-math.atan2(CDv.x,CDv.z)
|
||||||
|
local Alpha_R=(Alpha_T<0)and Alpha_T+2*math.pi or Alpha_T
|
||||||
|
local Position=math.cos(Alpha_R)
|
||||||
|
local GD=((GDv.x)^2+(GDv.z)^2)^0.5
|
||||||
|
local Distance=GD*Position+-CS*0.5
|
||||||
|
local GV={x=GV2.x-CV2.x,y=GV2.y-CV2.y,z=GV2.z-CV2.z}
|
||||||
|
local GH2={x=GV2.x,y=CV2.y+FollowFormation.y,z=GV2.z}
|
||||||
|
local alpha=math.atan2(GV.x,GV.z)
|
||||||
|
local GVx=FollowFormation.z*math.cos(Ca)+FollowFormation.x*math.sin(Ca)
|
||||||
|
local GVz=FollowFormation.x*math.cos(Ca)-FollowFormation.z*math.sin(Ca)
|
||||||
|
local Inclination=(Distance+FollowFormation.x)/10
|
||||||
|
if Inclination<-30 then
|
||||||
|
Inclination=-30
|
||||||
|
end
|
||||||
|
local CVI={
|
||||||
|
x=CV2.x+CS*10*math.sin(Ca),
|
||||||
|
y=GH2.y+Inclination,
|
||||||
|
z=CV2.z+CS*10*math.cos(Ca),
|
||||||
|
}
|
||||||
|
local DV={x=CV2.x-CVI.x,y=CV2.y-CVI.y,z=CV2.z-CVI.z}
|
||||||
|
local DVu={x=DV.x/FollowDistance,y=DV.y,z=DV.z/FollowDistance}
|
||||||
|
local GDV={x=CVI.x,y=CVI.y,z=CVI.z}
|
||||||
|
local ADDx=FollowFormation.x*math.cos(alpha)-FollowFormation.z*math.sin(alpha)
|
||||||
|
local ADDz=FollowFormation.z*math.cos(alpha)+FollowFormation.x*math.sin(alpha)
|
||||||
|
local GDV_Formation={
|
||||||
|
x=GDV.x-GVx,
|
||||||
|
y=GDV.y,
|
||||||
|
z=GDV.z-GVz
|
||||||
|
}
|
||||||
|
if self.SmokeDirectionVector==true then
|
||||||
|
trigger.action.smoke(GDV,trigger.smokeColor.Green)
|
||||||
|
trigger.action.smoke(GDV_Formation,trigger.smokeColor.White)
|
||||||
|
end
|
||||||
|
local Time=120
|
||||||
|
local Speed=-(Distance+FollowFormation.x)/Time
|
||||||
|
if Distance>-10000 then
|
||||||
|
Speed=-(Distance+FollowFormation.x)/60
|
||||||
|
end
|
||||||
|
if Distance>-2500 then
|
||||||
|
Speed=-(Distance+FollowFormation.x)/20
|
||||||
|
end
|
||||||
|
local GS=Speed+CS
|
||||||
|
FollowGroup:RouteToVec3(GDV_Formation,GS)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
AIRBOSS={
|
AIRBOSS={
|
||||||
ClassName="AIRBOSS",
|
ClassName="AIRBOSS",
|
||||||
Debug=false,
|
Debug=false,
|
||||||
@ -62058,6 +62282,7 @@ AV8B="AV8BNA",
|
|||||||
HORNET="FA-18C_hornet",
|
HORNET="FA-18C_hornet",
|
||||||
A4EC="A-4E-C",
|
A4EC="A-4E-C",
|
||||||
F14A="F-14A-135-GR",
|
F14A="F-14A-135-GR",
|
||||||
|
F14A_Early="F-14A-135-GR-Early",
|
||||||
F14B="F-14B",
|
F14B="F-14B",
|
||||||
F14A_AI="F-14A",
|
F14A_AI="F-14A",
|
||||||
FA18C="F/A-18C",
|
FA18C="F/A-18C",
|
||||||
@ -64024,7 +64249,7 @@ or playerData.actype==AIRBOSS.AircraftCarrier.GROWLER
|
|||||||
local goshawk=playerData.actype==AIRBOSS.AircraftCarrier.T45C
|
local goshawk=playerData.actype==AIRBOSS.AircraftCarrier.T45C
|
||||||
local skyhawk=playerData.actype==AIRBOSS.AircraftCarrier.A4EC
|
local skyhawk=playerData.actype==AIRBOSS.AircraftCarrier.A4EC
|
||||||
local harrier=playerData.actype==AIRBOSS.AircraftCarrier.AV8B
|
local harrier=playerData.actype==AIRBOSS.AircraftCarrier.AV8B
|
||||||
local tomcat=playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B
|
local tomcat=playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B or playerData.actype==AIRBOSS.AircraftCarrier.F14A_Early
|
||||||
local corsair=playerData.actype==AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype==AIRBOSS.AircraftCarrier.CORSAIR_CW
|
local corsair=playerData.actype==AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype==AIRBOSS.AircraftCarrier.CORSAIR_CW
|
||||||
local aoa={}
|
local aoa={}
|
||||||
if hornet then
|
if hornet then
|
||||||
@ -64080,7 +64305,7 @@ return aoa
|
|||||||
end
|
end
|
||||||
function AIRBOSS:_AoAUnit2Deg(playerData,aoaunits)
|
function AIRBOSS:_AoAUnit2Deg(playerData,aoaunits)
|
||||||
local degrees=aoaunits
|
local degrees=aoaunits
|
||||||
if playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B then
|
if playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B or playerData.actype==AIRBOSS.AircraftCarrier.F14A_Early then
|
||||||
degrees=-10+50/30*aoaunits
|
degrees=-10+50/30*aoaunits
|
||||||
degrees=0.918*aoaunits-3.411
|
degrees=0.918*aoaunits-3.411
|
||||||
elseif playerData.actype==AIRBOSS.AircraftCarrier.A4EC then
|
elseif playerData.actype==AIRBOSS.AircraftCarrier.A4EC then
|
||||||
@ -64090,7 +64315,7 @@ return degrees
|
|||||||
end
|
end
|
||||||
function AIRBOSS:_AoADeg2Units(playerData,degrees)
|
function AIRBOSS:_AoADeg2Units(playerData,degrees)
|
||||||
local aoaunits=degrees
|
local aoaunits=degrees
|
||||||
if playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B then
|
if playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B or playerData.actype==AIRBOSS.AircraftCarrier.F14A_Early then
|
||||||
aoaunits=(degrees+10)*30/50
|
aoaunits=(degrees+10)*30/50
|
||||||
aoaunits=1.089*degrees+3.715
|
aoaunits=1.089*degrees+3.715
|
||||||
elseif playerData.actype==AIRBOSS.AircraftCarrier.A4EC then
|
elseif playerData.actype==AIRBOSS.AircraftCarrier.A4EC then
|
||||||
@ -67061,7 +67286,7 @@ local lueWire=self:_LineupWIRE(playerData.unit,true)
|
|||||||
text=text..string.format("\nLineUpForWireCalls=%.2f° | lineup for Groove calls=%.2f°",lueWire or 0,lue or 0)
|
text=text..string.format("\nLineUpForWireCalls=%.2f° | lineup for Groove calls=%.2f°",lueWire or 0,lue or 0)
|
||||||
local unitClient=Unit.getByName(unit:GetName())
|
local unitClient=Unit.getByName(unit:GetName())
|
||||||
local hornet=playerData.actype==AIRBOSS.AircraftCarrier.HORNET
|
local hornet=playerData.actype==AIRBOSS.AircraftCarrier.HORNET
|
||||||
local tomcat=playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B
|
local tomcat=playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B or playerData.actype==AIRBOSS.AircraftCarrier.F14A_Early
|
||||||
if hornet then
|
if hornet then
|
||||||
local nozzlePosL=0
|
local nozzlePosL=0
|
||||||
local burnerPosL=unitClient:getDrawArgumentValue(28)
|
local burnerPosL=unitClient:getDrawArgumentValue(28)
|
||||||
@ -67177,7 +67402,7 @@ nozzlePosL=unitClient:getDrawArgumentValue(89)
|
|||||||
else
|
else
|
||||||
nozzlePosL=0
|
nozzlePosL=0
|
||||||
end
|
end
|
||||||
elseif typeName=="F-14A-135-GR"or typeName=="F-14B"then
|
elseif typeName=="F-14A-135-GR"or typeName=="F-14B"or typeName=="F-14A-135-GR-Early"then
|
||||||
nozzlePosL=unitClient:getDrawArgumentValue(434)
|
nozzlePosL=unitClient:getDrawArgumentValue(434)
|
||||||
end
|
end
|
||||||
return nozzlePosL
|
return nozzlePosL
|
||||||
@ -67194,7 +67419,7 @@ nozzlePosR=unitClient:getDrawArgumentValue(90)
|
|||||||
else
|
else
|
||||||
nozzlePosR=0
|
nozzlePosR=0
|
||||||
end
|
end
|
||||||
elseif typeName=="F-14A-135-GR"or typeName=="F-14B"then
|
elseif typeName=="F-14A-135-GR"or typeName=="F-14B"or typeName=="F-14A-135-GR-Early"then
|
||||||
nozzlePosR=unitClient:getDrawArgumentValue(433)
|
nozzlePosR=unitClient:getDrawArgumentValue(433)
|
||||||
end
|
end
|
||||||
return nozzlePosR
|
return nozzlePosR
|
||||||
@ -68770,7 +68995,7 @@ elseif actype==AIRBOSS.AircraftCarrier.E2D then
|
|||||||
nickname="Hawkeye"
|
nickname="Hawkeye"
|
||||||
elseif actype==AIRBOSS.AircraftCarrier.C2A then
|
elseif actype==AIRBOSS.AircraftCarrier.C2A then
|
||||||
nickname="Greyhound"
|
nickname="Greyhound"
|
||||||
elseif actype==AIRBOSS.AircraftCarrier.F14A_AI or actype==AIRBOSS.AircraftCarrier.F14A or actype==AIRBOSS.AircraftCarrier.F14B then
|
elseif actype==AIRBOSS.AircraftCarrier.F14A_AI or actype==AIRBOSS.AircraftCarrier.F14A or actype==AIRBOSS.AircraftCarrier.F14B or actype==AIRBOSS.AircraftCarrier.F14A_Early then
|
||||||
nickname="Tomcat"
|
nickname="Tomcat"
|
||||||
elseif actype==AIRBOSS.AircraftCarrier.FA18C or actype==AIRBOSS.AircraftCarrier.HORNET then
|
elseif actype==AIRBOSS.AircraftCarrier.FA18C or actype==AIRBOSS.AircraftCarrier.HORNET then
|
||||||
nickname="Hornet"
|
nickname="Hornet"
|
||||||
@ -71953,10 +72178,9 @@ end
|
|||||||
self.followset=SET_GROUP:New()
|
self.followset=SET_GROUP:New()
|
||||||
self.followset:AddGroup(self.helo)
|
self.followset:AddGroup(self.helo)
|
||||||
self.HeloFuel0=self.helo:GetFuel()
|
self.HeloFuel0=self.helo:GetFuel()
|
||||||
self.formation=AI_FORMATION:New(self.carrier,self.followset,"Helo Formation with Carrier","Follow Carrier at given parameters.")
|
self.formation=FORMATION:New(self.carrier,self.followset,"Helo Formation with Carrier")
|
||||||
self.formation:FormationCenterWing(-self.offsetX,50,math.abs(self.altitude),50,self.offsetZ,50)
|
self.formation:FormationCenterWing(-self.offsetX,50,math.abs(self.altitude),50,self.offsetZ,50)
|
||||||
self.formation:SetFollowTimeInterval(self.dtFollow)
|
self.formation:SetFollowTimeInterval(self.dtFollow)
|
||||||
self.formation:SetFlightModeFormation(self.helo)
|
|
||||||
self.formation:__Start(delay)
|
self.formation:__Start(delay)
|
||||||
self:__Status(1)
|
self:__Status(1)
|
||||||
return self
|
return self
|
||||||
@ -105492,7 +105716,7 @@ if Task.dcstask.id==AUFTRAG.SpecialTask.FORMATION then
|
|||||||
local followSet=SET_GROUP:New():AddGroup(self.group)
|
local followSet=SET_GROUP:New():AddGroup(self.group)
|
||||||
local param=Task.dcstask.params
|
local param=Task.dcstask.params
|
||||||
local followUnit=UNIT:FindByName(param.unitname)
|
local followUnit=UNIT:FindByName(param.unitname)
|
||||||
Task.formation=AI_FORMATION:New(followUnit,followSet,AUFTRAG.SpecialTask.FORMATION,"Follow X at given parameters.")
|
Task.formation=FORMATION:New(followUnit,followSet,AUFTRAG.SpecialTask.FORMATION)
|
||||||
Task.formation:FormationCenterWing(-param.offsetX,50,math.abs(param.altitude),50,param.offsetZ,50)
|
Task.formation:FormationCenterWing(-param.offsetX,50,math.abs(param.altitude),50,param.offsetZ,50)
|
||||||
Task.formation:SetFollowTimeInterval(param.dtFollow)
|
Task.formation:SetFollowTimeInterval(param.dtFollow)
|
||||||
Task.formation:SetFlightModeFormation(self.group)
|
Task.formation:SetFlightModeFormation(self.group)
|
||||||
|
|||||||
@ -201,8 +201,9 @@ end
|
|||||||
-- ==========================================
|
-- ==========================================
|
||||||
|
|
||||||
-- Storage for all zone capture objects and metadata
|
-- Storage for all zone capture objects and metadata
|
||||||
local zoneCaptureObjects = {}
|
-- NOTE: These are exported as globals for plugin compatibility (e.g., Moose_DynamicGroundBattle_Plugin.lua)
|
||||||
local zoneNames = {}
|
zoneCaptureObjects = {} -- Global: accessible by other scripts
|
||||||
|
zoneNames = {} -- Global: accessible by other scripts
|
||||||
local zoneMetadata = {} -- Stores coalition ownership info
|
local zoneMetadata = {} -- Stores coalition ownership info
|
||||||
|
|
||||||
-- Function to initialize all zones from configuration
|
-- Function to initialize all zones from configuration
|
||||||
@ -1054,7 +1055,9 @@ end
|
|||||||
local function SetupZoneStatusCommands()
|
local function SetupZoneStatusCommands()
|
||||||
-- Add F10 radio menu commands for BLUE coalition
|
-- Add F10 radio menu commands for BLUE coalition
|
||||||
if US_CC then
|
if US_CC then
|
||||||
local USMenu = MENU_COALITION:New( coalition.side.BLUE, "Zone Control" )
|
-- Use MenuManager to create zone control menu under Mission Options
|
||||||
|
local USMenu = MenuManager and MenuManager.CreateCoalitionMenu(coalition.side.BLUE, "Zone Control")
|
||||||
|
or MENU_COALITION:New( coalition.side.BLUE, "Zone Control" )
|
||||||
MENU_COALITION_COMMAND:New( coalition.side.BLUE, "Get Zone Status Report", USMenu, BroadcastZoneStatus )
|
MENU_COALITION_COMMAND:New( coalition.side.BLUE, "Get Zone Status Report", USMenu, BroadcastZoneStatus )
|
||||||
|
|
||||||
MENU_COALITION_COMMAND:New( coalition.side.BLUE, "Check Victory Progress", USMenu, function()
|
MENU_COALITION_COMMAND:New( coalition.side.BLUE, "Check Victory Progress", USMenu, function()
|
||||||
@ -1086,7 +1089,9 @@ local function SetupZoneStatusCommands()
|
|||||||
|
|
||||||
-- Add F10 radio menu commands for RED coalition
|
-- Add F10 radio menu commands for RED coalition
|
||||||
if RU_CC then
|
if RU_CC then
|
||||||
local RUMenu = MENU_COALITION:New( coalition.side.RED, "Zone Control" )
|
-- Use MenuManager to create zone control menu under Mission Options
|
||||||
|
local RUMenu = MenuManager and MenuManager.CreateCoalitionMenu(coalition.side.RED, "Zone Control")
|
||||||
|
or MENU_COALITION:New( coalition.side.RED, "Zone Control" )
|
||||||
MENU_COALITION_COMMAND:New( coalition.side.RED, "Get Zone Status Report", RUMenu, BroadcastZoneStatus )
|
MENU_COALITION_COMMAND:New( coalition.side.RED, "Get Zone Status Report", RUMenu, BroadcastZoneStatus )
|
||||||
|
|
||||||
MENU_COALITION_COMMAND:New( coalition.side.RED, "Check Victory Progress", RUMenu, function()
|
MENU_COALITION_COMMAND:New( coalition.side.RED, "Check Victory Progress", RUMenu, function()
|
||||||
|
|||||||
@ -3,8 +3,7 @@
|
|||||||
Written by: [F99th-TracerFacer]
|
Written by: [F99th-TracerFacer]
|
||||||
Version: 1.0.0
|
Version: 1.0.0
|
||||||
Date: 15 November 2024
|
Date: 15 November 2024
|
||||||
Description: Warehouse-driven ground unit spawning system that works as a plugin
|
Description: Warehouse-driven ground unit spawning system that works as a plugin with Moose_DualCoalitionZoneCapture.lua
|
||||||
with Moose_DualCoalitionZoneCapture.lua
|
|
||||||
|
|
||||||
This script handles:
|
This script handles:
|
||||||
- Warehouse-based reinforcement system
|
- Warehouse-based reinforcement system
|
||||||
@ -71,7 +70,7 @@
|
|||||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- Infantry Patrol Settings
|
-- Infantry Patrol Settings
|
||||||
local MOVING_INFANTRY_PATROLS = false -- Set to false to disable infantry movement (they spawn and hold position)
|
local MOVING_INFANTRY_PATROLS = true -- Set to false to disable infantry movement (they spawn and hold position)
|
||||||
|
|
||||||
-- Warehouse Marker Settings
|
-- Warehouse Marker Settings
|
||||||
local ENABLE_WAREHOUSE_MARKERS = true -- Enable/disable warehouse map markers (disabled by default if you have other marker systems)
|
local ENABLE_WAREHOUSE_MARKERS = true -- Enable/disable warehouse map markers (disabled by default if you have other marker systems)
|
||||||
@ -493,9 +492,19 @@ SCHEDULER:New(nil, MonitorWarehouses, {}, 30, 120)
|
|||||||
-- Schedule task assignments
|
-- Schedule task assignments
|
||||||
SCHEDULER:New(nil, AssignTasksToGroups, {}, 120, ASSIGN_TASKS_SCHED)
|
SCHEDULER:New(nil, AssignTasksToGroups, {}, 120, ASSIGN_TASKS_SCHED)
|
||||||
|
|
||||||
-- Add F10 menu for manual checks
|
-- Add F10 menu for manual checks (using MenuManager if available)
|
||||||
local missionMenu = MENU_MISSION:New("Ground Battle")
|
if MenuManager then
|
||||||
MENU_MISSION_COMMAND:New("Check Warehouse Status", missionMenu, MonitorWarehouses)
|
-- Create coalition-specific menus under Mission Options
|
||||||
|
local blueMenu = MenuManager.CreateCoalitionMenu(coalition.side.BLUE, "Ground Battle")
|
||||||
|
MENU_COALITION_COMMAND:New(coalition.side.BLUE, "Check Warehouse Status", blueMenu, MonitorWarehouses)
|
||||||
|
|
||||||
|
local redMenu = MenuManager.CreateCoalitionMenu(coalition.side.RED, "Ground Battle")
|
||||||
|
MENU_COALITION_COMMAND:New(coalition.side.RED, "Check Warehouse Status", redMenu, MonitorWarehouses)
|
||||||
|
else
|
||||||
|
-- Fallback to root-level mission menu
|
||||||
|
local missionMenu = MENU_MISSION:New("Ground Battle")
|
||||||
|
MENU_MISSION_COMMAND:New("Check Warehouse Status", missionMenu, MonitorWarehouses)
|
||||||
|
end
|
||||||
|
|
||||||
env.info("[DGB PLUGIN] Dynamic Ground Battle Plugin initialized successfully!")
|
env.info("[DGB PLUGIN] Dynamic Ground Battle Plugin initialized successfully!")
|
||||||
env.info(string.format("[DGB PLUGIN] Infantry movement: %s", MOVING_INFANTRY_PATROLS and "ENABLED" or "DISABLED"))
|
env.info(string.format("[DGB PLUGIN] Infantry movement: %s", MOVING_INFANTRY_PATROLS and "ENABLED" or "DISABLED"))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user