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:
iTracerFacer 2025-11-16 14:25:37 -06:00
parent 7dfe72afc6
commit bb57d306b4
21 changed files with 2932 additions and 222 deletions

View File

@ -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>

View File

@ -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>

View File

@ -1,2 +0,0 @@
Grammar__default_id=lua-5.1
eclipse.preferences.version=1

View File

@ -63,9 +63,11 @@ local redCfg = {
},
Zones = {
PickupZones = { { name = 'ReadLoadZone1', flag = 9101, activeWhen = 0 },
{ name = "ReadLoadZone2", flag = 9104, activeWhen = 0 },
{ name = "ReadLoadZone3", flag = 9105, activeWhen = 0 } },
PickupZones = { { name = 'RedLoadZone1', flag = 9101, activeWhen = 0 },
{ name = "RedLoadZone2", flag = 9104, 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 } },
--FOBZones = { { name = 'FOXTROT', flag = 9103, activeWhen = 0 } },
--MASHZones = { { name = 'MASH Bravo', freq = '252.0 AM', radius = 500, flag = 9111, activeWhen = 0 } },

View File

@ -212,8 +212,8 @@ end
-- ==========================================
-- Storage for all zone capture objects and metadata
local zoneCaptureObjects = {}
local zoneNames = {}
zoneCaptureObjects = {}
zoneNames = {}
local zoneMetadata = {} -- Stores coalition ownership info
-- Function to initialize all zones from configuration
@ -1065,7 +1065,9 @@ end
local function SetupZoneStatusCommands()
-- Add F10 radio menu commands for BLUE coalition
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, "Check Victory Progress", USMenu, function()
@ -1097,7 +1099,9 @@ local function SetupZoneStatusCommands()
-- Add F10 radio menu commands for RED coalition
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, "Check Victory Progress", RUMenu, function()

View File

@ -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 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.
local RedA2ADefaultOverhead = 1.5
local RedDefaultCAP = 1
local BlueA2ADefaultOverhead = 1.5
local BlueDefaultCAP = 1
-- Create the main mission menu.
missionMenu = MENU_MISSION:New("Mission Menu")
--Build Command Center and Mission for Blue
US_CC = COMMANDCENTER:New( GROUP:FindByName( "BLUEHQ" ), "USA HQ" )
US_Mission = MISSION:New( US_CC, "Insurgent Sandstorm", "Primary", "Clear the front lines of enemy activity.", coalition.side.BLUE)
US_Score = SCORING:New( "Insurgent Sandstorm - Blue" )
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 for Blue Coalition
local blueHQ = GROUP:FindByName("BLUEHQ")
if blueHQ then
US_CC = COMMANDCENTER:New(blueHQ, "USA HQ")
US_Mission = MISSION:New(US_CC, "Insurgent Sandstorm", "Primary", "", coalition.side.BLUE)
US_Mission:GetCommandCenter():SetMenu() -- Disable mission F10 menu
--US_Score = SCORING:New("Operation Polar Hammer") -- Commented out to prevent Scoring F10 menu
--US_Mission:AddScoring(US_Score)
--US_Mission:Start()
env.info("Blue Coalition Command Center and Mission started successfully")
else
env.info("ERROR: BLUEHQ group not found! Blue mission will not start.")
end
--Build Command Center and Mission Red
RU_CC = COMMANDCENTER:New( GROUP:FindByName( "REDHQ" ), "Russia HQ" )
RU_Mission = MISSION:New (RU_CC, "Insurgent Sandstorm", "Primary", "Destroy U.S. and NATO forces.", coalition.side.RED)
RU_Score = SCORING:New("Insurgent Sandstorm - Red")
RU_Mission:AddScoring( RU_Score)
local redHQ = GROUP:FindByName("REDHQ")
if redHQ then
RU_CC = COMMANDCENTER:New(redHQ, "Russia HQ")
RU_Mission = MISSION:New(RU_CC, "Insurgent Sandstorm", "Primary", "Hold what we have, take what we don't.", coalition.side.RED)
RU_Mission:GetCommandCenter():SetMenu() -- Disable mission F10 menu
--RU_Score = SCORING:New("Operation Polar Shield") -- Commented out to prevent Scoring F10 menu
--RU_Mission:AddScoring(RU_Score)
RU_Mission:Start()
RU_Score:SetMessagesHit(false)
RU_Score:SetMessagesDestroy(false)
RU_Score:SetMessagesScore(false)
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
@ -116,59 +118,7 @@ end
------------------------------------------------------------------------------------------------------------------------------------------------------
-- Setup Air Dispatchers for RED and BLUE
------------------------------------------------------------------------------------------------------------------------------------------------------
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 )
--now handled by TADC system.
------------------------------------------------------------------------------------------------------------------------------------------------------
-- Clean up the airbases of debris and stuck aircraft.

View File

@ -56,12 +56,12 @@ end
local CARGO_SUPPLY_CONFIG = {
red = {
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)
},
blue = {
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)
}
}

View File

@ -90,8 +90,8 @@ RED_SQUADRON_CONFIG = {
type = "FIGHTER",
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
secondaryZone = nil, -- Secondary coverage area (zone name)
primaryZone = "BostBorderZone", -- Main responsibility area (zone name from mission editor)
secondaryZone = "DwyerBorderZone", -- Secondary coverage area (zone name)
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
-- Zone behavior settings (optional - uses defaults if not specified)
@ -118,8 +118,8 @@ RED_SQUADRON_CONFIG = {
type = "FIGHTER",
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
secondaryZone = nil, -- Secondary coverage area (zone name)
primaryZone = "DwyerBorderZone", -- Main responsibility area (zone name from mission editor)
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
-- Zone behavior settings (optional - uses defaults if not specified)
@ -146,8 +146,8 @@ RED_SQUADRON_CONFIG = {
type = "FIGHTER",
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
secondaryZone = nil, -- Secondary coverage area (zone name)
primaryZone = "DwyerBorderZone", -- Main responsibility area (zone name from mission editor)
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
-- Zone behavior settings (optional - uses defaults if not specified)
@ -173,8 +173,8 @@ RED_SQUADRON_CONFIG = {
type = "FIGHTER",
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
secondaryZone = nil, -- Secondary coverage area (zone name)
primaryZone = "DwyerBorderZone", -- Main responsibility area (zone name from mission editor)
secondaryZone = "BostBorderZone", -- Secondary coverage area (zone name)
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
-- Zone behavior settings (optional - uses defaults if not specified)
@ -199,9 +199,9 @@ RED_SQUADRON_CONFIG = {
type = "FIGHTER",
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
secondaryZone = nil, -- Secondary coverage area (zone name)
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
secondaryZone = "DwyerBorderZone", -- Secondary coverage area (zone name)
tertiaryZone = "BostBorderZone", -- Emergency/fallback zone (zone name)
-- Zone behavior settings (optional - uses defaults if not specified)
zoneConfig = {
@ -225,9 +225,9 @@ RED_SQUADRON_CONFIG = {
type = "FIGHTER",
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
secondaryZone = nil, -- Secondary coverage area (zone name)
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
secondaryZone = "DwyerBorderZone", -- Secondary coverage area (zone name)
tertiaryZone = "BostBorderZone", -- Emergency/fallback zone (zone name)
-- Zone behavior settings (optional - uses defaults if not specified)
zoneConfig = {
@ -251,9 +251,115 @@ RED_SQUADRON_CONFIG = {
type = "FIGHTER",
-- Zone-based Areas of Responsibility (optional - leave nil for global response)
primaryZone = "RED_BORDER", -- Main responsibility area (zone name from mission editor)
secondaryZone = nil, -- Secondary coverage area (zone name)
tertiaryZone = nil, -- Emergency/fallback zone (zone name)
primaryZone = "BATTLE GROUND", -- Main responsibility area (zone name from mission editor)
secondaryZone = "DwyerBorderZone", -- Secondary coverage area (zone name)
tertiaryZone = "BostBorderZone", -- 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 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 = {
@ -369,6 +475,6 @@ BLUE_SQUADRON_CONFIG = {
priorityThreshold = 4, -- Min aircraft count for "major threat"
ignoreLowPriority = false, -- Ignore threats below threshold in secondary zones
}
},
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +0,0 @@
local function main()
end
main()

View File

@ -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
MOOSE_DEVELOPMENT_FOLDER='Scripts'
end
@ -19229,41 +19229,6 @@ return nil
end
end
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={
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})
return self
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={
ClassName="AIRBOSS",
Debug=false,
@ -62058,6 +62282,7 @@ AV8B="AV8BNA",
HORNET="FA-18C_hornet",
A4EC="A-4E-C",
F14A="F-14A-135-GR",
F14A_Early="F-14A-135-GR-Early",
F14B="F-14B",
F14A_AI="F-14A",
FA18C="F/A-18C",
@ -64024,7 +64249,7 @@ or playerData.actype==AIRBOSS.AircraftCarrier.GROWLER
local goshawk=playerData.actype==AIRBOSS.AircraftCarrier.T45C
local skyhawk=playerData.actype==AIRBOSS.AircraftCarrier.A4EC
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 aoa={}
if hornet then
@ -64080,7 +64305,7 @@ return aoa
end
function AIRBOSS:_AoAUnit2Deg(playerData,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=0.918*aoaunits-3.411
elseif playerData.actype==AIRBOSS.AircraftCarrier.A4EC then
@ -64090,7 +64315,7 @@ return degrees
end
function AIRBOSS:_AoADeg2Units(playerData,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=1.089*degrees+3.715
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)
local unitClient=Unit.getByName(unit:GetName())
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
local nozzlePosL=0
local burnerPosL=unitClient:getDrawArgumentValue(28)
@ -67177,7 +67402,7 @@ nozzlePosL=unitClient:getDrawArgumentValue(89)
else
nozzlePosL=0
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)
end
return nozzlePosL
@ -67194,7 +67419,7 @@ nozzlePosR=unitClient:getDrawArgumentValue(90)
else
nozzlePosR=0
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)
end
return nozzlePosR
@ -68770,7 +68995,7 @@ elseif actype==AIRBOSS.AircraftCarrier.E2D then
nickname="Hawkeye"
elseif actype==AIRBOSS.AircraftCarrier.C2A then
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"
elseif actype==AIRBOSS.AircraftCarrier.FA18C or actype==AIRBOSS.AircraftCarrier.HORNET then
nickname="Hornet"
@ -71953,10 +72178,9 @@ end
self.followset=SET_GROUP:New()
self.followset:AddGroup(self.helo)
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:SetFollowTimeInterval(self.dtFollow)
self.formation:SetFlightModeFormation(self.helo)
self.formation:__Start(delay)
self:__Status(1)
return self
@ -105492,7 +105716,7 @@ if Task.dcstask.id==AUFTRAG.SpecialTask.FORMATION then
local followSet=SET_GROUP:New():AddGroup(self.group)
local param=Task.dcstask.params
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:SetFollowTimeInterval(param.dtFollow)
Task.formation:SetFlightModeFormation(self.group)

View File

@ -201,8 +201,9 @@ end
-- ==========================================
-- Storage for all zone capture objects and metadata
local zoneCaptureObjects = {}
local zoneNames = {}
-- NOTE: These are exported as globals for plugin compatibility (e.g., Moose_DynamicGroundBattle_Plugin.lua)
zoneCaptureObjects = {} -- Global: accessible by other scripts
zoneNames = {} -- Global: accessible by other scripts
local zoneMetadata = {} -- Stores coalition ownership info
-- Function to initialize all zones from configuration
@ -1054,7 +1055,9 @@ end
local function SetupZoneStatusCommands()
-- Add F10 radio menu commands for BLUE coalition
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, "Check Victory Progress", USMenu, function()
@ -1086,7 +1089,9 @@ local function SetupZoneStatusCommands()
-- Add F10 radio menu commands for RED coalition
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, "Check Victory Progress", RUMenu, function()

View File

@ -3,8 +3,7 @@
Written by: [F99th-TracerFacer]
Version: 1.0.0
Date: 15 November 2024
Description: Warehouse-driven ground unit spawning system that works as a plugin
with Moose_DualCoalitionZoneCapture.lua
Description: Warehouse-driven ground unit spawning system that works as a plugin with Moose_DualCoalitionZoneCapture.lua
This script handles:
- Warehouse-based reinforcement system
@ -71,7 +70,7 @@
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- 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
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
SCHEDULER:New(nil, AssignTasksToGroups, {}, 120, ASSIGN_TASKS_SCHED)
-- Add F10 menu for manual checks
-- Add F10 menu for manual checks (using MenuManager if available)
if MenuManager then
-- 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(string.format("[DGB PLUGIN] Infantry movement: %s", MOVING_INFANTRY_PATROLS and "ENABLED" or "DISABLED"))