21 Commits
Author SHA1 Message Date
dutchie031 a351c45b73 wip
PR Prerequisites / Lua Check (pull_request) Failing after 14s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 28s
2026-09-09 22:04:15 +02:00
dutchie031 e081b8e446 updated luals version
PR Prerequisites / Lua Check (pull_request) Successful in 10s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 30s
2026-09-09 15:55:11 +02:00
dutchie031 4b3d87f589 updated luals version
PR Prerequisites / Lua Check (pull_request) Failing after 10s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 24s
2026-09-09 15:49:32 +02:00
dutchie031 1fde8ec3b1 updated luals version 2026-09-09 15:49:22 +02:00
dutchie031 68e8d1c9ac updated luals version
PR Prerequisites / Lua Check (pull_request) Failing after 12s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 23s
2026-09-09 15:49:05 +02:00
dutchie031 ccd38078f3 updated luals version
PR Prerequisites / Lua Check (pull_request) Failing after 11s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 24s
2026-09-09 15:47:50 +02:00
dutchie031 de1e6ffae9 updated luals version
PR Prerequisites / Lua Check (pull_request) Failing after 11s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 29s
2026-09-09 15:37:39 +02:00
dutchie031 2a76df1e21 updated
PR Prerequisites / Lua Check (pull_request) Failing after 13s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 27s
2026-09-09 15:36:02 +02:00
dutchie031 a55cd2bf2a trying other check
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 24s
PR Prerequisites / Lua Check (pull_request) Failing after 1m21s
2026-09-09 12:36:29 +02:00
dutchie031 d16e25531a non important trailing whitespace ignored
PR Prerequisites / Lua Check (pull_request) Failing after 24s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 23s
2026-09-09 11:27:23 +02:00
dutchie031 30c7124a86 non important trailing whitespace ignored
PR Prerequisites / Lua Check (pull_request) Failing after 24s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 26s
2026-09-09 11:25:23 +02:00
dutchie031 514a9a9c55 non important trailing whitespace ignored
PR Prerequisites / Lua Check (pull_request) Failing after 24s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 24s
2026-09-09 11:24:09 +02:00
dutchie031 96fab864c3 non important trailing whitespace ignored
PR Prerequisites / Lua Check (pull_request) Failing after 21s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 23s
2026-09-09 11:22:21 +02:00
dutchie031 0346f8a7a8 linter fixes
PR Prerequisites / Lua Check (pull_request) Failing after 20s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 28s
2026-09-09 11:12:58 +02:00
dutchie031 ba240db310 fixing linting
PR Prerequisites / Lua Check (pull_request) Failing after 22s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 22s
2026-09-08 21:04:40 +02:00
dutchie031 50f2a0eea0 added CI for all source files
PR Prerequisites / Lua Check (pull_request) Failing after 20s
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 24s
2026-09-08 17:35:21 +02:00
dutchie031 70d18f4ac3 updated luacheck rc
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 24s
2026-09-08 17:07:41 +02:00
dutchie031 341590e981 fixed minor bug
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 49s
2026-09-08 16:54:00 +02:00
dutchie031 233310209b changed checkout version
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 39s
2026-09-08 16:44:52 +02:00
dutchie031 2cae676a10 changed checkout version
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 6s
2026-09-08 16:41:35 +02:00
dutchie031 de81fdf419 added lua check CI step
PR Prerequisites / Bundles Without Errors (pull_request) Failing after 8s
2026-09-08 16:40:04 +02:00
50 changed files with 529 additions and 622 deletions
+71
View File
@@ -0,0 +1,71 @@
name: PR Prerequisites
on:
pull_request:
branches:
- main
- develop
env:
LUA_VERSION: "5.1"
LUA_LANGUAGE_SERVER_VERSION: "3.19.1"
jobs:
bundles_without_error:
runs-on: ubuntu-latest
name: Bundles Without Errors
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Lua
uses: leafo/gh-actions-lua@v13
with:
luaVersion: ${{ env.LUA_VERSION }}
- name: Compile Spearhead
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-action@action/v0
with:
source-root: ./src
output-file: ./output/spearhead.lua
- name: Verify Compiled Lua Syntax
run: lua -e "assert(loadfile('./output/spearhead.lua'))"
- name: Set up Luarocks
uses: leafo/gh-actions-luarocks@v4
- name: Install luacheck
run: luarocks install luacheck
- name: Lint Compiled Output
run: luacheck ./output/spearhead.lua
lua_check:
runs-on: ubuntu-latest
name: Lua Check
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Lua
uses: leafo/gh-actions-lua@v13
with:
luaVersion: ${{ env.LUA_VERSION }}
- name: Install lua-language-server
run: |
mkdir -p ./luals
# For Ubuntu/Debian
wget https://github.com/LuaLS/lua-language-server/releases/download/${{ env.LUA_LANGUAGE_SERVER_VERSION }}/lua-language-server-${{ env.LUA_LANGUAGE_SERVER_VERSION }}-linux-x64.tar.gz
tar -xzf lua-language-server-*.tar.gz -C ./luals
rm lua-language-server-*.tar.gz
- name: Verify Lua Language Server Installation
run: ./luals/bin/lua-language-server --version
- name: Run Lua Language Server
run: ./luals/bin/lua-language-server --check ./src --checklevel=Warning
+30
View File
@@ -0,0 +1,30 @@
{
"Lua": {
"runtime": {
"version": "Lua 5.1"
},
"workspace": {
"library": [
"./src",
"./DcsTypes.lua"
],
"checkThirdParty": false
},
"diagnostics": {
"enable": true,
"globals": [
"lfs"
],
"severity": {
"undefined-field": "Warning",
"unused-local": "Warning"
}
},
"hint": {
"enable": false
},
"completion": {
"enable": true
}
}
}
-73
View File
@@ -1,73 +0,0 @@
--assert(loadfile("C:\\Repos\\DCS\\Spearhead\\dev\\dev_classes.lua"))()
local basePath = "C:\\Repos\\DCS\\Spearhead\\"
local classPath = basePath .. "classes\\"
assert(loadfile(classPath .. "_baseClasses\\Queue.lua"))()
assert(loadfile(classPath .. "spearhead_base.lua"))()
assert(loadfile(classPath .. "spearhead_routeutil.lua"))()
assert(loadfile(classPath .. "spearhead_events.lua"))()
assert(loadfile(classPath .. "spearhead_db.lua"))()
assert(loadfile(classPath .. "fleetClasses\\FleetGroup.lua"))()
assert(loadfile(classPath .. "fleetClasses\\GlobalFleetManager.lua"))()
assert(loadfile(classPath .. "helpers\\MizGroupsManager.lua"))()
assert(loadfile(classPath .. "helpers\\SpawnManager.lua"))()
assert(loadfile(classPath .. "configuration\\CapConfig.lua"))()
assert(loadfile(classPath .. "configuration\\StageConfig.lua"))()
assert(loadfile(classPath .. "stageClasses\\GlobalStageManager.lua"))()
assert(loadfile(classPath .. "stageClasses\\missions\\baseMissions\\Mission.lua"))()
assert(loadfile(classPath .. "stageClasses\\missions\\ZoneMission.lua"))()
assert(loadfile(classPath .. "stageClasses\\missions\\RunwayStrikeMission.lua"))()
assert(loadfile(classPath .. "stageClasses\\missions\\BuildableMission.lua"))()
assert(loadfile(classPath .. "stageClasses\\Stages\\BaseStage\\Stage.lua"))()
assert(loadfile(classPath .. "stageClasses\\Stages\\PrimaryStage.lua"))()
assert(loadfile(classPath .. "stageClasses\\Stages\\ExtraStage.lua"))()
assert(loadfile(classPath .. "stageClasses\\Stages\\WaitingStage.lua"))()
assert(loadfile(classPath .. "stageClasses\\Groups\\SpearheadGroup.lua"))()
assert(loadfile(classPath .. "stageClasses\\Groups\\SpearheadSceneryObject.lua"))()
assert(loadfile(classPath .. "stageClasses\\helpers\\MissionCommandsHelper.lua"))()
assert(loadfile(classPath .. "stageClasses\\helpers\\SupplyConfig.lua"))()
assert(loadfile(classPath .. "stageClasses\\helpers\\SupplyUnitsTracker.lua"))()
assert(loadfile(classPath .. "stageClasses\\helpers\\BattleManager.lua"))()
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\abstract\\BuildableZone.lua"))()
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\StageBase.lua"))()
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\BlueSam.lua"))()
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\FarpZone.lua"))()
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\SupplyHub.lua"))()
assert(loadfile(classPath .. "capClasses\\taskings\\RTB.lua"))()
assert(loadfile(classPath .. "capClasses\\taskings\\CAP.lua"))()
assert(loadfile(classPath .. "capClasses\\taskings\\SWEEP.lua"))()
assert(loadfile(classPath .. "capClasses\\taskings\\INTERCEPT.lua"))()
assert(loadfile(classPath .. "capClasses\\airGroups\\AirGroup.lua"))()
assert(loadfile(classPath .. "capClasses\\airGroups\\CapGroup.lua"))()
assert(loadfile(classPath .. "capClasses\\airGroups\\SweepGroup.lua"))()
assert(loadfile(classPath .. "capClasses\\airGroups\\InterceptGroup.lua"))()
assert(loadfile(classPath .. "capClasses\\detection\\DetectionManager.lua"))()
assert(loadfile(classPath .. "capClasses\\GlobalCapManager.lua"))()
assert(loadfile(classPath .. "capClasses\\CapAirbase.lua"))()
assert(loadfile(classPath .. "capClasses\\runwayBombing\\RunwayBombingTracker.lua"))()
assert(loadfile(classPath .. "persistence\\Persistence.lua"))()
-- Startup:
assert(loadfile(basePath .. "main.lua"))()
-79
View File
@@ -1,79 +0,0 @@
SpearheadConfig = {
debugEnabled = true,
CapConfig = {
--quickly enable of disable the entire CAP Logic
--(you can also just rename all units to not be named "CAP_")
enabled = true, -- default true
--min ground speed for CAP aircraft during patrol
-- unit: knots
minSpeed = 400, -- default 400
--max speed for CAP aircraft during patrol
-- unit: knots
maxSpeed = 500, -- default 500
--minAlt for aircraft on patrol
-- unit: feet
minAlt = 18000, -- default 18000
--maxAlt for aircraft on patrol
-- unit: feet
maxAlt = 28000, -- default 28000
--Delay for aircraft from touchdown to off the chocks.
-- unit: seconds
rearmDelay = 180, -- default 600
repairDelay = 600, -- default 600
--Delay for aircraft from death to takeoff.
--When the seconds remaining is the same at the rearmDelay it will be spawned on the ramp and follow the rearm logic.
-- !! Can not be lower than rearmDelay
-- unit: seconds
deathDelay = 1800, -- default 1800
},
StageConfig = {
-- management of stages and its missions.
-- This is not related to CAP managers which will continue to work even if stage management is disabled
enabled = true, -- default true
--Will draw the active and the next stage
drawStages = true, -- default true
drawPreActivated = true,
markLastContact = true,
--AutoStages will continue to the next stage automatically on completion of the missions within the stage.
-- If you want to make it so the next stage triggers only when you want to disable it here and manually implement the actions needed.
--[[
TODO: Add manual stage transition documentation
]]
autoStages = true, --default true
--Maximum missions per stage (includes all types of missions)
maxMissionStage = 100,
--Stage starting number
startingStage = 1,
---DEBUG logging. Consider keeping this disabled
debugEnabled = true
},
Persistence = {
--- io and lfs cannot be sanitized in the MissionScripting.lua
--- enables or disables the persistence logic in spearhead
enabled = true,
--- sets the directory where the persistence file is stored
--- if nil then lfs.writedir() will be used.
--- which will
directory = nil ,
--- the filename of the persistence file. Should end with .json for convention, but any text extension should do.
fileName = "Spearhead_Persistence_Dev"
}
}
+11 -15
View File
@@ -2,7 +2,6 @@ local Util = require("classes.util.Util")
local CapGroup = require("classes.capClasses.airGroups.CapGroup") local CapGroup = require("classes.capClasses.airGroups.CapGroup")
local SweepGroup = require("classes.capClasses.airGroups.SweepGroup") local SweepGroup = require("classes.capClasses.airGroups.SweepGroup")
local InterceptGroup = require("classes.capClasses.airGroups.InterceptGroup") local InterceptGroup = require("classes.capClasses.airGroups.InterceptGroup")
local RunwayBombingTracker = require("classes.capClasses.runwayBombing.RunwayBombingTracker")
local SpearheadEvents = require("classes.spearhead_events") local SpearheadEvents = require("classes.spearhead_events")
local RunwayStrikeMission = require("classes.stageClasses.missions.RunwayStrikeMission") local RunwayStrikeMission = require("classes.stageClasses.missions.RunwayStrikeMission")
@@ -37,12 +36,11 @@ end
---@param database Database ---@param database Database
---@param logger table ---@param logger table
---@param capConfig table ---@param capConfig table
---@param stageConfig table
---@param runwayBombingTracker RunwayBombingTracker ---@param runwayBombingTracker RunwayBombingTracker
---@param detectionManager DetectionManager ---@param detectionManager DetectionManager
---@param spawnManager SpawnManager ---@param spawnManager SpawnManager
---@return CapBase ---@return CapBase
function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager) function CapBase.new(airbaseName, database, logger, capConfig, runwayBombingTracker, detectionManager, spawnManager)
CapBase.__index = CapBase CapBase.__index = CapBase
local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]] local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]]
@@ -61,7 +59,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
local baseData = database:getAirbaseDataForZone(airbaseName) local baseData = database:getAirbaseDataForZone(airbaseName)
if baseData and baseData.CapGroups then if baseData and baseData.CapGroups then
for key, name in pairs(baseData.CapGroups) do for _, name in pairs(baseData.CapGroups) do
local capGroup = CapGroup.New(name, capConfig, logger, spawnManager) local capGroup = CapGroup.New(name, capConfig, logger, spawnManager)
if capGroup then if capGroup then
self.capGroupsByName[name] = capGroup self.capGroupsByName[name] = capGroup
@@ -70,7 +68,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
end end
if baseData and baseData.SweepGroups then if baseData and baseData.SweepGroups then
for key, name in pairs(baseData.SweepGroups) do for _, name in pairs(baseData.SweepGroups) do
local sweepGroup = SweepGroup.New(name, capConfig, logger, spawnManager) local sweepGroup = SweepGroup.New(name, capConfig, logger, spawnManager)
if sweepGroup then if sweepGroup then
self.sweepGroupsByName[name] = sweepGroup self.sweepGroupsByName[name] = sweepGroup
@@ -79,7 +77,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
end end
if baseData and baseData.InterceptGroups then if baseData and baseData.InterceptGroups then
for key, name in pairs(baseData.InterceptGroups) do for _, name in pairs(baseData.InterceptGroups) do
local interceptGroup = InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager) local interceptGroup = InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
if interceptGroup then if interceptGroup then
self.interceptGroupsByName[name] = interceptGroup self.interceptGroupsByName[name] = interceptGroup
@@ -98,7 +96,6 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
timer.scheduleFunction(CheckStateContinuous, self, timer.getTime() + 15) timer.scheduleFunction(CheckStateContinuous, self, timer.getTime() + 15)
return self return self
end end
@@ -127,7 +124,7 @@ end
function CapBase:SpawnIfApplicable() function CapBase:SpawnIfApplicable()
self.logger:debug("Check spawns for airbase " .. self.airbaseName) self.logger:debug("Check spawns for airbase " .. self.airbaseName)
for groupName, capGroup in pairs(self.capGroupsByName) do for _, capGroup in pairs(self.capGroupsByName) do
local targetStage = capGroup:GetZoneIDWhenStageID(tostring(self.activeStage)) local targetStage = capGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
if targetStage ~= nil and capGroup:GetState() == "UnSpawned" then if targetStage ~= nil and capGroup:GetState() == "UnSpawned" then
@@ -135,7 +132,7 @@ function CapBase:SpawnIfApplicable()
end end
end end
for groupName, sweepGroup in pairs(self.sweepGroupsByName) do for _, sweepGroup in pairs(self.sweepGroupsByName) do
local targetStage = sweepGroup:GetZoneIDWhenStageID(tostring(self.activeStage)) local targetStage = sweepGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
if targetStage ~= nil and sweepGroup:GetState() == "UnSpawned" then if targetStage ~= nil and sweepGroup:GetState() == "UnSpawned" then
@@ -143,7 +140,7 @@ function CapBase:SpawnIfApplicable()
end end
end end
for groupName, interceptGroup in pairs(self.interceptGroupsByName) do for _, interceptGroup in pairs(self.interceptGroupsByName) do
local targetStage = interceptGroup:GetZoneIDWhenStageID(tostring(self.activeStage)) local targetStage = interceptGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
if targetStage ~= nil and interceptGroup:GetState() == "UnSpawned" then if targetStage ~= nil and interceptGroup:GetState() == "UnSpawned" then
@@ -154,8 +151,9 @@ end
function CapBase:CheckAndScheduleCAP() function CapBase:CheckAndScheduleCAP()
self.logger:debug("Check taskings for airbase " .. self.airbaseName) self.logger:debug("Check taskings for airbase " .. self.airbaseName)
---@type table<string, number>
local countPerStage = {} local countPerStage = {}
---@type table<string, number>
local requiredPerStage = {} local requiredPerStage = {}
local airbase = Airbase.getByName(self.airbaseName) local airbase = Airbase.getByName(self.airbaseName)
@@ -312,8 +310,7 @@ function CapBase:CheckAndScheduleIntercept()
self.logger:debug("Check intercept taskings for airbase " .. self.airbaseName) self.logger:debug("Check intercept taskings for airbase " .. self.airbaseName)
local interceptZoneIDs = {} ---@type table<string, boolean>
local interceptZoneIDs = {} local interceptZoneIDs = {}
local airbase = Airbase.getByName(self.airbaseName) local airbase = Airbase.getByName(self.airbaseName)
@@ -321,7 +318,7 @@ function CapBase:CheckAndScheduleIntercept()
return nil return nil
end end
for name, group in pairs(self.interceptGroupsByName) do for _, group in pairs(self.interceptGroupsByName) do
local targetZoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage)) local targetZoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
if targetZoneID then if targetZoneID then
interceptZoneIDs[targetZoneID] = true interceptZoneIDs[targetZoneID] = true
@@ -379,7 +376,6 @@ function CapBase:CheckAndScheduleIntercept()
if total < required then if total < required then
for _, group in pairs(self.interceptGroupsByName) do for _, group in pairs(self.interceptGroupsByName) do
if total < required then if total < required then
local zoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
if group:GetState() == "ReadyOnTheRamp" then if group:GetState() == "ReadyOnTheRamp" then
group:SendToInterceptUnits(targets, name, airbase) group:SendToInterceptUnits(targets, name, airbase)
total = total + 1 total = total + 1
+3 -8
View File
@@ -8,19 +8,15 @@ local GlobalCapManager = {}
do do
local airbasesPerStage = {} local airbasesPerStage = {}
local allAirbasesByName = {} local allAirbasesByName = {}
local activeAirbasesPerActiveStage = {}
local unitsPerzonePerStage = {}
local initiated = false local initiated = false
---comment ---comment
---@param database Database ---@param database Database
---@param capConfig table ---@param capConfig table
---@param stageConfig StageConfig
---@param detectionManager DetectionManager ---@param detectionManager DetectionManager
---@param logLevel LogLevel ---@param logLevel LogLevel
---@param spawnManager SpawnManager ---@param spawnManager SpawnManager
function GlobalCapManager.start(database, capConfig, detectionManager, stageConfig, logLevel, spawnManager) function GlobalCapManager.start(database, capConfig, detectionManager, logLevel, spawnManager)
if initiated == true then return end if initiated == true then return end
local logger = Logger.new("AirbaseManager", logLevel) local logger = Logger.new("AirbaseManager", logLevel)
@@ -29,7 +25,7 @@ do
local zones = database:getStagezoneNames() local zones = database:getStagezoneNames()
if zones then if zones then
for key, stageName in pairs(zones) do for _, stageName in pairs(zones) do
if airbasesPerStage[stageName] == nil then if airbasesPerStage[stageName] == nil then
airbasesPerStage[stageName] = {} airbasesPerStage[stageName] = {}
end end
@@ -40,8 +36,7 @@ do
if airbaseName then if airbaseName then
local airbaseSpecificLogger = Logger.new("CAP_" .. airbaseName, logLevel) local airbaseSpecificLogger = Logger.new("CAP_" .. airbaseName, logLevel)
local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager) local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, runwayBombingTracker, detectionManager, spawnManager)
if airbase then if airbase then
table.insert(airbasesPerStage[stageName], airbase) table.insert(airbasesPerStage[stageName], airbase)
allAirbasesByName[airbaseName] = airbase allAirbasesByName[airbaseName] = airbase
@@ -1,7 +1,6 @@
local SpearheadEvents = require("classes.spearhead_events") local SpearheadEvents = require("classes.spearhead_events")
local RTBMission = require("classes.capClasses.taskings.RTB") local RTBMission = require("classes.capClasses.taskings.RTB")
local Util = require("classes.util.Util") local Util = require("classes.util.Util")
local DcsUtil = require("classes.util.DcsUtil")
local GlobalConfig = require("classes.configuration.GlobalConfig") local GlobalConfig = require("classes.configuration.GlobalConfig")
local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing") local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing")
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper") local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
@@ -81,7 +80,7 @@ function AirGroup:SetMission(mission)
end end
end end
local setMissionDelayed = function(data, time) local setMissionDelayed = function(data, _)
data.self:SetMissionPrivate(data.mission) data.self:SetMissionPrivate(data.mission)
end end
@@ -357,7 +356,7 @@ do --- RESPAWN FUNCTIONS
self:SetState("Dead") self:SetState("Dead")
---@param selfA AirGroup ---@param selfA AirGroup
local respawnTask = function(selfA, time) local respawnTask = function(selfA, _)
selfA:StartRepair() selfA:StartRepair()
end end
@@ -376,8 +375,7 @@ do --- RESPAWN FUNCTIONS
end end
---comment ---comment
---@param selfA AirGroup local rearmTask = function(_, _)
local rearmTask = function(selfA, time)
self:StartRearm() self:StartRearm()
end end
@@ -402,7 +400,7 @@ do --- RESPAWN FUNCTIONS
end end
---@param selfA AirGroup ---@param selfA AirGroup
local rearmTask = function(selfA, time) local rearmTask = function(selfA, _)
selfA:MarkRearmComplete() selfA:MarkRearmComplete()
end end
@@ -415,6 +413,7 @@ end
do --EVENT LISTENERS do --EVENT LISTENERS
---@param unit Unit ---@param unit Unit
function AirGroup:OnUnitLost(unit) function AirGroup:OnUnitLost(unit)
if unit == nil then return end
self:CheckLiveness() self:CheckLiveness()
end end
@@ -434,7 +433,7 @@ do --EVENT LISTENERS
end end
end end
function AirGroup:OnUnitLanded(unit, airbase) function AirGroup:OnUnitLanded(_, _)
local anyInAir = false local anyInAir = false
local group = Group.getByName(self._groupName) local group = Group.getByName(self._groupName)
if group then if group then
@@ -107,13 +107,13 @@ function CapGroup:InitWithName(groupName)
local subsplit = Util.split_string(configPart, "|") local subsplit = Util.split_string(configPart, "|")
if subsplit then if subsplit then
for key, value in pairs(subsplit) do for _, value in pairs(subsplit) do
local keySplit = Util.split_string(value, "]") local keySplit = Util.split_string(value, "]")
local targetZone = keySplit[2] local targetZone = keySplit[2]
local allActives = string.sub(keySplit[1], 2, #keySplit[1]) local allActives = string.sub(keySplit[1], 2, #keySplit[1])
local commaSeperated = Util.split_string(allActives, ",") local commaSeperated = Util.split_string(allActives, ",")
for _, value in pairs(commaSeperated) do for _, childValue in pairs(commaSeperated) do
local dashSeperated = Util.split_string(value, "-") local dashSeperated = Util.split_string(childValue, "-")
if Util.tableLength(dashSeperated) > 1 then if Util.tableLength(dashSeperated) > 1 then
local from = tonumber(dashSeperated[1]) local from = tonumber(dashSeperated[1])
local till = tonumber(dashSeperated[2]) local till = tonumber(dashSeperated[2])
@@ -213,8 +213,6 @@ function InterceptGroup:UpdateTask()
self._currentTargetName = nil self._currentTargetName = nil
end end
local speed = self._config:getMaxSpeed() local speed = self._config:getMaxSpeed()
local interceptPoint = self:GetInterceptPoint(groupPoint, speed, closestUnit) local interceptPoint = self:GetInterceptPoint(groupPoint, speed, closestUnit)
@@ -323,13 +321,13 @@ function InterceptGroup:InitWithName(groupName)
configPart = string.sub(configPart, 2, #configPart) configPart = string.sub(configPart, 2, #configPart)
local subsplit = Util.split_string(configPart, "|") local subsplit = Util.split_string(configPart, "|")
if subsplit then if subsplit then
for key, value in pairs(subsplit) do for _, value in pairs(subsplit) do
local keySplit = Util.split_string(value, "]") local keySplit = Util.split_string(value, "]")
local targetZone = keySplit[2] local targetZone = keySplit[2]
local allActives = string.sub(keySplit[1], 2, #keySplit[1]) local allActives = string.sub(keySplit[1], 2, #keySplit[1])
local commaSeperated = Util.split_string(allActives, ",") local commaSeperated = Util.split_string(allActives, ",")
for _, value in pairs(commaSeperated) do for _, childValue in pairs(commaSeperated) do
local dashSeperated = Util.split_string(value, "-") local dashSeperated = Util.split_string(childValue, "-")
if Util.tableLength(dashSeperated) > 1 then if Util.tableLength(dashSeperated) > 1 then
local from = tonumber(dashSeperated[1]) local from = tonumber(dashSeperated[1])
local till = tonumber(dashSeperated[2]) local till = tonumber(dashSeperated[2])
@@ -41,7 +41,7 @@ end
---@field self SweepGroup ---@field self SweepGroup
---@param params SetTaskParams ---@param params SetTaskParams
local setMissionDelayedTask = function(params, time) local setMissionDelayedTask = function(params, _)
params.self:SetMissionPrivate(params.task) params.self:SetMissionPrivate(params.task)
end end
@@ -50,8 +50,6 @@ function SweepGroup:SendToZone(zone, targetZoneID, airbase)
self._currentTargetZoneID = targetZoneID self._currentTargetZoneID = targetZoneID
local group = Group.getByName(self._groupName)
local mission = SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config) local mission = SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
if mission then if mission then
---@type SetTaskParams ---@type SetTaskParams
@@ -82,13 +80,13 @@ function SweepGroup:InitWithName(groupName)
local subsplit = Util.split_string(configPart, "|") local subsplit = Util.split_string(configPart, "|")
if subsplit then if subsplit then
for key, value in pairs(subsplit) do for _, value in pairs(subsplit) do
local keySplit = Util.split_string(value, "]") local keySplit = Util.split_string(value, "]")
local targetZone = keySplit[2] local targetZone = keySplit[2]
local allActives = string.sub(keySplit[1], 2, #keySplit[1]) local allActives = string.sub(keySplit[1], 2, #keySplit[1])
local commaSeperated = Util.split_string(allActives, ",") local commaSeperated = Util.split_string(allActives, ",")
for _, value in pairs(commaSeperated) do for _, childValue in pairs(commaSeperated) do
local dashSeperated = Util.split_string(value, "-") local dashSeperated = Util.split_string(childValue, "-")
if Util.tableLength(dashSeperated) > 1 then if Util.tableLength(dashSeperated) > 1 then
local from = tonumber(dashSeperated[1]) local from = tonumber(dashSeperated[1])
local till = tonumber(dashSeperated[2]) local till = tonumber(dashSeperated[2])
@@ -38,7 +38,6 @@ function DetectionManager.New(logger)
end end
timer.scheduleFunction(updateDetected, self, timer.getTime() + 130) timer.scheduleFunction(updateDetected, self, timer.getTime() + 130)
return self return self
end end
@@ -21,7 +21,7 @@ end
---comment ---comment
---@param weapon Weapon ---@param weapon Weapon
function RunwayBombingTracker:OnWeaponFired(unit, weapon, target) function RunwayBombingTracker:OnWeaponFired(_, weapon, _)
if weapon == nil then if weapon == nil then
return return
@@ -83,11 +83,7 @@ function RunwayBombingTracker.trackWeaponTask(weaponTrackingArgs, time)
x = pos.x + velocity.x * nextInterval, x = pos.x + velocity.x * nextInterval,
y = pos.z + velocity.z * nextInterval y = pos.z + velocity.z * nextInterval
} }
self:OnWeaponImpact(weapon:getDesc(), impactPoint) self:OnWeaponImpact(weapon:getDesc(), impactPoint)
return nil return nil
end end
@@ -109,7 +105,7 @@ function RunwayBombingTracker:OnWeaponImpact(weaponDesc, impactPoint)
local warhead = weaponDesc.warhead local warhead = weaponDesc.warhead
local explosiveMass = warhead.explosiveMass or warhead.shapedExplosiveMass local explosiveMass = warhead.explosiveMass or warhead.shapedExplosiveMass
for runway, strikeMission in pairs(self.trackedRunways) do for _, strikeMission in pairs(self.trackedRunways) do
local zone= strikeMission:GetRunwayZone() local zone= strikeMission:GetRunwayZone()
-3
View File
@@ -33,9 +33,6 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
local furthestA = nil local furthestA = nil
local furthestB = nil local furthestB = nil
local furthestFromBase = nil
local furthestFromBaseDistance = 0
local furthestDistance = 0 local furthestDistance = 0
for indexA, pointA in ipairs(capZone.verts) do for indexA, pointA in ipairs(capZone.verts) do
@@ -1,8 +1,4 @@
local briefingMessageTime = nil
---@class GlobalConfig ---@class GlobalConfig
---@field private _briefingTime number ---@field private _briefingTime number
---@field private _debugEnabled boolean ---@field private _debugEnabled boolean
-1
View File
@@ -1,5 +1,4 @@
local Logger = require("classes.util.Logger") local Logger = require("classes.util.Logger")
local Util = require("classes.util.Util")
local StageRepository = require("classes.stageClasses.StageRepository") local StageRepository = require("classes.stageClasses.StageRepository")
---@class DebugMenu ---@class DebugMenu
+48 -42
View File
@@ -4,37 +4,43 @@ local MissionEditorWarning = require("classes.util.MissionEditorWarnings")
local RouteUtil = require("classes.spearhead_routeutil") local RouteUtil = require("classes.spearhead_routeutil")
local SpearheadEvents = require("classes.spearhead_events") local SpearheadEvents = require("classes.spearhead_events")
---@class FleetGroup ---@class FleetGroup : OnStageChangedListener
---@field private fleetGroupName string
---@field private logger Logger
---@field private fleetNameIdentifier string
---@field private targetZonePerStage table<string, string>
---@field private currentTargetZone string
---@field private pointsPerZone table<string, {pointA: Vec2, pointB: Vec2}>
local FleetGroup = {} local FleetGroup = {}
FleetGroup.__index = FleetGroup
---comment ---comment
---@param fleetGroupName string ---@param fleetGroupName string
---@param database Database ---@param database Database
---@param logger Logger ---@param logger Logger
---@return nil ---@return FleetGroup?
function FleetGroup:new(fleetGroupName, database, logger) function FleetGroup.new(fleetGroupName, database, logger)
local o = {}
setmetatable(o, { __index = self }) local self = setmetatable({}, FleetGroup)
o.fleetGroupName = fleetGroupName self.fleetGroupName = fleetGroupName
o.logger = logger self.logger = logger
local split_name = Util.split_string(fleetGroupName, "_") local split_name = Util.split_string(fleetGroupName, "_")
if Util.tableLength(split_name) < 2 then if Util.tableLength(split_name) < 2 then
MissionEditorWarning.Add("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>") MissionEditorWarning.Add("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>")
return nil return nil
end end
o.fleetNameIdentifier = split_name[2] self.fleetNameIdentifier = split_name[2]
o.targetZonePerStage = {} self.targetZonePerStage = {}
o.currentTargetZone = nil self.currentTargetZone = nil
o.pointsPerZone = {} self.pointsPerZone = {}
do --INIT do --INIT
local carrierRouteZones = database:getCarrierRouteZones() local carrierRouteZones = database:getCarrierRouteZones()
for _, zoneName in pairs(carrierRouteZones) do for _, zoneName in pairs(carrierRouteZones) do
if Util.strContains(string.lower(zoneName), "_".. string.lower(o.fleetNameIdentifier) .. "_" ) == true then if Util.strContains(string.lower(zoneName), "_".. string.lower(self.fleetNameIdentifier) .. "_" ) == true then
local zone = DcsUtil.getZoneByName(zoneName) local zone = DcsUtil.getZoneByName(zoneName)
if zone and zone.zone_type == DcsUtil.ZoneType.Polygon then if zone and zone.zone_type == DcsUtil.ZoneType.Polygon then
local split_string = Util.split_string(zoneName, "_") local split_string = Util.split_string(zoneName, "_")
@@ -43,18 +49,18 @@ function FleetGroup:new(fleetGroupName, database, logger)
"CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName) "CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName)
else else
---@param zone SpearheadTriggerZone ---@param zoneA SpearheadTriggerZone
---@return Vec2, Vec2 ---@return Vec2, Vec2
local function GetTwoFurthestPoints(zone) local function GetTwoFurthestPoints(zoneA)
local biggest = nil local biggest = nil
local biggestA = zone.verts[1] local biggestA = zoneA.verts[1]
local biggestB = zone.verts[2] local biggestB = zoneA.verts[2]
for i = 1, 3 do for i = 1, 3 do
for ii = i + 1, 4 do for ii = i + 1, 4 do
local a = zone.verts[i] local a = zoneA.verts[i]
local b = zone.verts[ii] local b = zoneA.verts[ii]
local dist = Util.VectorDistance2d(a, b) local dist = Util.VectorDistance2d(a, b)
if biggest == nil or dist > biggest then if biggest == nil or dist > biggest then
@@ -100,9 +106,9 @@ function FleetGroup:new(fleetGroupName, database, logger)
local first, second = getMinMaxStage(split_string[3]) local first, second = getMinMaxStage(split_string[3])
if first ~= nil and second ~= nil then if first ~= nil and second ~= nil then
for i = first, second do for i = first, second do
o.targetZonePerStage[tostring(i)] = zoneName self.targetZonePerStage[tostring(i)] = zoneName
end end
o.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} } self.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} }
else else
MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName) MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
end end
@@ -114,32 +120,32 @@ function FleetGroup:new(fleetGroupName, database, logger)
end end
end end
local SetTaskAsync = function(input, time) SpearheadEvents.AddStageNumberChangedListener(self)
local targetZone = input.targetZone return self
local task = input.task end
local groupName = input.groupName
local logger = input.logger
local group = Group.getByName(groupName) local SetTaskAsync = function(input, _)
if group then local targetZone = input.targetZone
logger:info("Sending " .. groupName .. " to " .. targetZone) local task = input.task
group:getController():setTask(task) local groupName = input.groupName
end local l_logger = input.logger
local group = Group.getByName(groupName)
if group then
l_logger:info("Sending " .. groupName .. " to " .. targetZone)
group:getController():setTask(task)
end end
end
o.OnStageNumberChanged = function(self, number, laneIdentifier) function FleetGroup:OnStageNumberChanged(number, laneIdentifier)
-- only react on "main" lane changes, ignore other lanes for now -- only react on "main" lane changes, ignore other lanes for now
if laneIdentifier ~= nil then return end if laneIdentifier ~= nil then return end
local targetZone = self.targetZonePerStage[tostring(number)] local targetZone = self.targetZonePerStage[tostring(number)]
if targetZone and targetZone ~= self.currentTargetZone then if targetZone and targetZone ~= self.currentTargetZone then
local points = self.pointsPerZone[targetZone] local points = self.pointsPerZone[targetZone]
local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB) local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5) timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5)
end
end end
SpearheadEvents.AddStageNumberChangedListener(o)
return o
end end
return FleetGroup return FleetGroup
@@ -17,7 +17,7 @@ GlobalFleetManager.start = function(database)
for _, groupName in pairs(all_groups) do for _, groupName in pairs(all_groups) do
if Util.startswith(string.lower(groupName), "carriergroup" ) == true then if Util.startswith(string.lower(groupName), "carriergroup" ) == true then
logger:info("Registering " .. groupName .. " as a managed fleet") logger:info("Registering " .. groupName .. " as a managed fleet")
local carrierGroup = FleetGroup:new(groupName, database, logger) local carrierGroup = FleetGroup.new(groupName, database, logger)
table.insert(fleetGroups, carrierGroup) table.insert(fleetGroups, carrierGroup)
end end
end end
+3 -4
View File
@@ -15,14 +15,13 @@ MizGroupsManager._groupNames = {}
MizGroupsManager._spawnTemplateData = {} MizGroupsManager._spawnTemplateData = {}
do --init do --init
for coalition_name, coalition_data in pairs(env.mission.coalition) do for _, coalition_data in pairs(env.mission.coalition) do
local coalition_nr = DcsUtil.stringToCoalition(coalition_name)
if coalition_data.country then if coalition_data.country then
for country_index, country_data in pairs(coalition_data.country) do for _, country_data in pairs(coalition_data.country) do
for category_name, categorydata in pairs(country_data) do for category_name, categorydata in pairs(country_data) do
local category_id = DcsUtil.stringToGroupCategory(category_name) local category_id = DcsUtil.stringToGroupCategory(category_name)
if category_id ~= nil and type(categorydata) == "table" and categorydata.group ~= nil and type(categorydata.group) == "table" then if category_id ~= nil and type(categorydata) == "table" and categorydata.group ~= nil and type(categorydata.group) == "table" then
for group_index, group in pairs(categorydata.group) do for _, group in pairs(categorydata.group) do
local name = group.name local name = group.name
local skippable = false local skippable = false
local isStatic = false local isStatic = false
+4 -5
View File
@@ -44,7 +44,7 @@ function SpawnManager:SpawnGroup(groupName, overrides, isGroupPersistant)
if spawnData.isStatic == true then if spawnData.isStatic == true then
return self:SpawnStaticInternal(groupName, spawnData, overrides, isGroupPersistant), true return self:SpawnStaticInternal(groupName, spawnData, overrides, isGroupPersistant), true
else else
return self:SpawnGroupInternal(groupName, spawnData, overrides, isGroupPersistant), false return self:SpawnGroupInternal(spawnData, overrides, isGroupPersistant), false
end end
end end
@@ -103,20 +103,20 @@ function SpawnManager:OnUnitLost(object)
end end
end end
---@param groupName string
function SpawnManager:SpawnCorpsesOnly(groupName) function SpawnManager:SpawnCorpsesOnly(groupName)
if groupName == nil then return end
end end
do --- privates do --- privates
---@private ---@private
---@param groupName string
---@param spawnData SpawnData ---@param spawnData SpawnData
---@param override SpawnOverrides? ---@param override SpawnOverrides?
---@param isPersistent boolean? ---@param isPersistent boolean?
---@return Group|nil ---@return Group|nil
function SpawnManager:SpawnGroupInternal(groupName, spawnData, override, isPersistent) function SpawnManager:SpawnGroupInternal(spawnData, override, isPersistent)
if not spawnData then return end if not spawnData then return end
local country = spawnData.country local country = spawnData.country
@@ -181,7 +181,6 @@ do --- privates
return group return group
end end
return nil return nil
end end
+2 -2
View File
@@ -112,7 +112,7 @@ do
logger:info("Wrote persistence data to file") logger:info("Wrote persistence data to file")
end end
local UpdateContinuous = function(null, time) local UpdateContinuous = function(_, time)
env.info("[Spearhead][Persistence] Checking up on persistence state...") env.info("[Spearhead][Persistence] Checking up on persistence state...")
if Persistence._updateRequired == true then if Persistence._updateRequired == true then
local status, result = pcall(writeToFile) local status, result = pcall(writeToFile)
@@ -135,7 +135,7 @@ do
end end
local warnForNonPersistenceContinous = function(null, time) local warnForNonPersistenceContinous = function(_, time)
trigger.action.outText("Persistence was enabeld, however, io and lfs are not available and no persistence will be done. Make sure to either disable persistence or fix the issues before continuing.", 10) trigger.action.outText("Persistence was enabeld, however, io and lfs are not available and no persistence will be done. Make sure to either disable persistence or fix the issues before continuing.", 10)
return time + 9 return time + 9
end end
+15 -17
View File
@@ -121,7 +121,7 @@ function Database.New(Logger)
self._logger:debug("Initiating tables") self._logger:debug("Initiating tables")
do -- INIT ZONE TABLES do -- INIT ZONE TABLES
for zone_ind, zone_data in pairs(DcsUtil.__trigger_zones) do for _, zone_data in pairs(DcsUtil.__trigger_zones) do
local zone_name = zone_data.name local zone_name = zone_data.name
---@type Vec2 ---@type Vec2
@@ -208,9 +208,9 @@ function Database.New(Logger)
self._logger:debug("initiated zone tables, continuing with descriptions") self._logger:debug("initiated zone tables, continuing with descriptions")
do --load markers do --load markers
if env.mission.drawings and env.mission.drawings.layers then if env.mission.drawings and env.mission.drawings.layers then
for i, layer in pairs(env.mission.drawings.layers) do for _, layer in pairs(env.mission.drawings.layers) do
if string.lower(layer.name) == "author" then if string.lower(layer.name) == "author" then
for key, layer_object in pairs(layer.objects) do for _, layer_object in pairs(layer.objects) do
if Util.startswith(string.lower(layer_object.name), "buildable", true) == true then if Util.startswith(string.lower(layer_object.name), "buildable", true) == true then
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object) local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
if airbaseData then if airbaseData then
@@ -228,9 +228,9 @@ function Database.New(Logger)
---@type table<integer, boolean> ---@type table<integer, boolean>
do -- custom drawings do -- custom drawings
if env.mission.drawings and env.mission.drawings.layers then if env.mission.drawings and env.mission.drawings.layers then
for i, layer in pairs(env.mission.drawings.layers) do for _, layer in pairs(env.mission.drawings.layers) do
if string.lower(layer.name) == "author" then if string.lower(layer.name) == "author" then
for key, layer_object in pairs(layer.objects) do for _, layer_object in pairs(layer.objects) do
if Util.startswith(layer_object.name, "drawing_", true) then if Util.startswith(layer_object.name, "drawing_", true) then
local object = layer_object --[[@as DrawingObject]] local object = layer_object --[[@as DrawingObject]]
local stageDrawing = StageDrawing.New(object) local stageDrawing = StageDrawing.New(object)
@@ -256,9 +256,9 @@ function Database.New(Logger)
-- Find and add Briefing -- Find and add Briefing
if env.mission.drawings and env.mission.drawings.layers then if env.mission.drawings and env.mission.drawings.layers then
for i, layer in pairs(env.mission.drawings.layers) do for _, layer in pairs(env.mission.drawings.layers) do
if string.lower(layer.name) == "author" then if string.lower(layer.name) == "author" then
for key, layer_object in pairs(layer.objects) do for _, layer_object in pairs(layer.objects) do
if Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then if Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then
local zone = DcsUtil.getZoneByName(stageZoneName) local zone = DcsUtil.getZoneByName(stageZoneName)
local vec2 = { x = layer_object.mapX, y = layer_object.mapY } local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
@@ -339,14 +339,14 @@ function Database.New(Logger)
end end
-- fill missions -- fill missions
for key, missionZone in pairs(self._tables.MissionZones) do for _, missionZone in pairs(self._tables.MissionZones) do
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
table.insert(stageData.MissionZones, missionZone) table.insert(stageData.MissionZones, missionZone)
end end
end end
-- fill random missions -- fill random missions
for key, missionZone in pairs(self._tables.RandomMissionZones) do for _, missionZone in pairs(self._tables.RandomMissionZones) do
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
table.insert(stageData.RandomMissionZones, missionZone) table.insert(stageData.RandomMissionZones, missionZone)
end end
@@ -620,9 +620,9 @@ function Database:loadBlueSamUnits()
samData.buildingKilos = number samData.buildingKilos = number
if env.mission.drawings and env.mission.drawings.layers then if env.mission.drawings and env.mission.drawings.layers then
for i, layer in pairs(env.mission.drawings.layers) do for _, layer in pairs(env.mission.drawings.layers) do
if string.lower(layer.name) == "author" then if string.lower(layer.name) == "author" then
for key, layer_object in pairs(layer.objects) do for _, layer_object in pairs(layer.objects) do
local vec2 = { x = layer_object.mapX, y = layer_object.mapY } local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
@@ -720,9 +720,9 @@ function Database:LoadZoneData(missionZoneName)
---Adds Briefings ---Adds Briefings
if env.mission.drawings and env.mission.drawings.layers then if env.mission.drawings and env.mission.drawings.layers then
for i, layer in pairs(env.mission.drawings.layers) do for _, layer in pairs(env.mission.drawings.layers) do
if string.lower(layer.name) == "author" then if string.lower(layer.name) == "author" then
for key, layer_object in pairs(layer.objects) do for _, layer_object in pairs(layer.objects) do
local vec2 = { x = layer_object.mapX, y = layer_object.mapY } local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
@@ -776,9 +776,9 @@ function Database:loadFarpData()
-- check briefings -- check briefings
if env.mission.drawings and env.mission.drawings.layers then if env.mission.drawings and env.mission.drawings.layers then
for i, layer in pairs(env.mission.drawings.layers) do for _, layer in pairs(env.mission.drawings.layers) do
if string.lower(layer.name) == "author" then if string.lower(layer.name) == "author" then
for key, layer_object in pairs(layer.objects) do for _, layer_object in pairs(layer.objects) do
local vec2 = { x = layer_object.mapX, y = layer_object.mapY } local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
@@ -796,8 +796,6 @@ function Database:loadFarpData()
else else
MissionEditorWarnings.Add("Buildable number for " .. farpZone .. " is invalid.") MissionEditorWarnings.Add("Buildable number for " .. farpZone .. " is invalid.")
end end
end end
end end
end end
+20 -21
View File
@@ -65,7 +65,7 @@ do
end) end)
for _, callable in pairs(OnStageNumberChangedListeners) do for _, callable in pairs(OnStageNumberChangedListeners) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnStageNumberChanged(newStageNumber, laneIdentifier) callable:OnStageNumberChanged(newStageNumber, laneIdentifier)
end) end)
if err then if err then
@@ -74,14 +74,14 @@ do
end end
for _, callable in pairs(OnStageNumberChangedHandlers) do for _, callable in pairs(OnStageNumberChangedHandlers) do
local succ, err = pcall(callable, newStageNumber, laneIdentifier) local _, err = pcall(callable, newStageNumber, laneIdentifier)
if err then if err then
logError(err) logError(err)
end end
end end
for _, callable in pairs(OnStageNumberChangeCompleteListeners) do for _, callable in pairs(OnStageNumberChangeCompleteListeners) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnStageNumberChangeComplete(newStageNumber, laneIdentifier) callable:OnStageNumberChangeComplete(newStageNumber, laneIdentifier)
end) end)
if err then if err then
@@ -112,7 +112,7 @@ do
local triggerWeaponFired = function(unit, weapon, target) local triggerWeaponFired = function(unit, weapon, target)
for _, callable in pairs(onWeaponFiredListeners) do for _, callable in pairs(onWeaponFiredListeners) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnWeaponFired(unit, weapon, target) callable:OnWeaponFired(unit, weapon, target)
end) end)
@@ -186,7 +186,7 @@ do
if groupName ~= nil then if groupName ~= nil then
if OnGroupRTBListeners[groupName] then if OnGroupRTBListeners[groupName] then
for _, callable in pairs(OnGroupRTBListeners[groupName]) do for _, callable in pairs(OnGroupRTBListeners[groupName]) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnGroupRTB(groupName) callable:OnGroupRTB(groupName)
end) end)
if err then if err then
@@ -221,7 +221,7 @@ do
if groupName ~= nil then if groupName ~= nil then
if OnGroupRTBInTenListeners[groupName] then if OnGroupRTBInTenListeners[groupName] then
for _, callable in pairs(OnGroupRTBInTenListeners[groupName]) do for _, callable in pairs(OnGroupRTBInTenListeners[groupName]) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnGroupRTBInTen(groupName) callable:OnGroupRTBInTen(groupName)
end) end)
if err then if err then
@@ -257,7 +257,7 @@ do
if groupName ~= nil then if groupName ~= nil then
if OnGroupOnStationListeners[groupName] then if OnGroupOnStationListeners[groupName] then
for _, callable in pairs(OnGroupOnStationListeners[groupName]) do for _, callable in pairs(OnGroupOnStationListeners[groupName]) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnGroupOnStation(groupName) callable:OnGroupOnStation(groupName)
end) end)
if err then if err then
@@ -286,7 +286,7 @@ do
if unit ~= nil then if unit ~= nil then
if playerEnterUnitListeners then if playerEnterUnitListeners then
for _, callable in pairs(playerEnterUnitListeners) do for _, callable in pairs(playerEnterUnitListeners) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnPlayerEntersUnit(unit) callable:OnPlayerEntersUnit(unit)
end) end)
if err then if err then
@@ -321,7 +321,7 @@ do
local name = unit:getName() local name = unit:getName()
if onLandEventListeners[name] then if onLandEventListeners[name] then
for _, callable in pairs(onLandEventListeners[name]) do for _, callable in pairs(onLandEventListeners[name]) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnUnitLanded(unit, airbase) callable:OnUnitLanded(unit, airbase)
end) end)
if err then if err then
@@ -344,7 +344,7 @@ do
if object and object.getName and OnUnitLostListeners[object:getName()] then if object and object.getName and OnUnitLostListeners[object:getName()] then
for _, callable in pairs(OnUnitLostListeners[object:getName()]) do for _, callable in pairs(OnUnitLostListeners[object:getName()]) do
local succ, err = pcall(function() local _, err = pcall(function()
callable:OnUnitLost(object) callable:OnUnitLost(object)
end) end)
@@ -374,26 +374,26 @@ do
local AI_GROUPS = {} local AI_GROUPS = {}
local function CheckAndTriggerSpawnAsync(unit, time) local function CheckAndTriggerSpawnAsync(unit, _)
local function isPlayer(unit) local function isPlayer(checkUnit)
if unit == nil then return false, "unit is nil" end if checkUnit == nil then return false, "unit is nil" end
if unit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end if checkUnit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end
if Object.getCategory(unit) ~= Object.Category.UNIT then if Object.getCategory(checkUnit) ~= Object.Category.UNIT then
return false, "object is not a unit" return false, "object is not a unit"
end end
if unit:isExist() ~= true then return false, "unit does not exist" end if checkUnit:isExist() ~= true then return false, "unit does not exist" end
local group = unit:getGroup() local group = checkUnit:getGroup()
if group ~= nil then if group ~= nil then
if AI_GROUPS[group:getName()] == true then if AI_GROUPS[group:getName()] == true then
return false return false
end end
local players = DcsUtil.getAllPlayerUnits() local players = DcsUtil.getAllPlayerUnits()
local unitName = unit:getName() local unitName = checkUnit:getName()
for i, unit in pairs(players) do for _, playerUnit in pairs(players) do
if unit:getName() == unitName then if playerUnit:getName() == unitName then
return true return true
end end
end end
@@ -403,7 +403,6 @@ do
end end
if isPlayer(unit) == true then if isPlayer(unit) == true then
local groupId = unit:getGroup():getID()
SpearheadEvents.TriggerPlayerEntersUnit(unit) SpearheadEvents.TriggerPlayerEntersUnit(unit)
end end
+70 -62
View File
@@ -2,7 +2,6 @@ local Events = require("classes.spearhead_events")
local Util = require("classes.util.Util") local Util = require("classes.util.Util")
local DcsUtil = require("classes.util.DcsUtil") local DcsUtil = require("classes.util.DcsUtil")
local Logger = require("classes.util.Logger") local Logger = require("classes.util.Logger")
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
local PersistenceConfig = require("classes.configuration.PersistenceConfig") local PersistenceConfig = require("classes.configuration.PersistenceConfig")
local ExtraStage = require("classes.stageClasses.Stages.ExtraStage") local ExtraStage = require("classes.stageClasses.Stages.ExtraStage")
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage") local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
@@ -35,7 +34,6 @@ local singletonInstance = nil
---@param spawnManager SpawnManager ---@param spawnManager SpawnManager
---@return GlobalStageManager ---@return GlobalStageManager
function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager) function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
if singletonInstance ~= nil then if singletonInstance ~= nil then
return singletonInstance return singletonInstance
end end
@@ -52,7 +50,8 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
self.logger = logger self.logger = logger
if stageConfig.isAutoStages ~= true then if stageConfig.isAutoStages ~= true then
logger:warn("Spearhead will not automatically progress stages due to the given settings. If you manually have implemented this, please ignore this message") logger:warn(
"Spearhead will not automatically progress stages due to the given settings. If you manually have implemented this, please ignore this message")
end end
Events.AddStageNumberChangedListener(self) Events.AddStageNumberChangedListener(self)
@@ -81,12 +80,12 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
stage:AddStageCompleteListener(self) stage:AddStageCompleteListener(self)
self._stageRepository:AddStage(stage) self._stageRepository:AddStage(stage)
elseif parseResult.stageType == "WaitingStage" then elseif parseResult.stageType == "WaitingStage" then
local waitingStage = WaitingStage.New(database, stageConfig, logger, initData, parseResult.waitingStageSeconds, spawnManager) local waitingStage = WaitingStage.New(database, stageConfig, logger, initData,
parseResult.waitingStageSeconds, spawnManager)
waitingStage:AddStageCompleteListener(self) waitingStage:AddStageCompleteListener(self)
self._stageRepository:AddStage(waitingStage) self._stageRepository:AddStage(waitingStage)
end end
end end
end end
singletonInstance = self singletonInstance = self
@@ -103,11 +102,11 @@ function GlobalStageManager:Start()
local stageLanes = self._stageRepository:getAllStageLanes() local stageLanes = self._stageRepository:getAllStageLanes()
for _, stageLane in pairs(stageLanes) do for _, stageLane in pairs(stageLanes) do
local stageLaneIdentifier = stageLane:GetStageLaneIdentifier() local stageLaneIdentifier = stageLane:GetStageLaneIdentifier()
local persistedStage = Persistence.GetActiveStage(stageLaneIdentifier) local persistedStage = Persistence.GetActiveStage(stageLaneIdentifier)
if persistedStage then if persistedStage then
self.logger:info("Loaded persisted stage " .. persistedStage .. " for lane " .. (stageLaneIdentifier or "default")) self.logger:info("Loaded persisted stage " ..
persistedStage .. " for lane " .. (stageLaneIdentifier or "default"))
stageLane:SetActiveStageIndex(persistedStage) stageLane:SetActiveStageIndex(persistedStage)
Events.PublishStageNumberChanged(persistedStage, stageLaneIdentifier) Events.PublishStageNumberChanged(persistedStage, stageLaneIdentifier)
else else
@@ -139,17 +138,16 @@ end
---@param stageName string ---@param stageName string
---@return StageNameParseResult ---@return StageNameParseResult
function GlobalStageManager:ParseStageName(stageName) function GlobalStageManager:ParseStageName(stageName)
local split = Util.split_string(stageName, "_") local split = Util.split_string(stageName, "_")
if Util.tableLength(split) < 3 then if Util.tableLength(split) < 3 then
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " does not have a order number or valid format" } return { isValid = false, invalidReason = "Stage zone with name " ..
stageName .. " does not have a order number or valid format" }
end end
local typePart = string.lower(split[1]) local typePart = string.lower(split[1])
if typePart == "missionstage" then if typePart == "missionstage" then
local orderNumberString = string.lower(split[2]) local orderNumberString = string.lower(split[2])
---@type StageType ---@type StageType
local stageType = "PrimaryStage" local stageType = "PrimaryStage"
@@ -167,7 +165,8 @@ function GlobalStageManager:ParseStageName(stageName)
local orderNumber = tonumber(orderNumberString) local orderNumber = tonumber(orderNumberString)
if orderNumber == nil then if orderNumber == nil then
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " does not have a valid order number : " .. orderNumberString } return { isValid = false, invalidReason = "Stage zone with name " ..
stageName .. " does not have a valid order number : " .. orderNumberString }
end end
local stageDisplayName = split[3] local stageDisplayName = split[3]
@@ -182,18 +181,19 @@ function GlobalStageManager:ParseStageName(stageName)
} }
return result return result
elseif typePart == "waitingstage" then elseif typePart == "waitingstage" then
local stageType = "WaitingStage" local stageType = "WaitingStage"
local orderNumberString = split[2] local orderNumberString = split[2]
local orderNumber = tonumber(orderNumberString) local orderNumber = tonumber(orderNumberString)
if orderNumber == nil then if orderNumber == nil then
return { isValid = false, invalidReason = "Waiting Stage zone with name " .. stageName .. " does not have a valid order number : " .. orderNumberString } return { isValid = false, invalidReason = "Waiting Stage zone with name " ..
stageName .. " does not have a valid order number : " .. orderNumberString }
end end
local waitingSecondsString = split[3] local waitingSecondsString = split[3]
local waitingSeconds = tonumber(waitingSecondsString) local waitingSeconds = tonumber(waitingSecondsString)
if waitingSeconds == nil then if waitingSeconds == nil then
return { isValid = false, invalidReason = "Waiting Stage zone with name " .. stageName .. " does not have a valid amount of seconds parameter : " .. waitingSecondsString } return { isValid = false, invalidReason = "Waiting Stage zone with name " ..
stageName .. " does not have a valid amount of seconds parameter : " .. waitingSecondsString }
end end
local stageDisplayName = "Waiting Stage " .. orderNumber local stageDisplayName = "Waiting Stage " .. orderNumber
@@ -209,9 +209,9 @@ function GlobalStageManager:ParseStageName(stageName)
waitingStageSeconds = waitingSeconds waitingStageSeconds = waitingSeconds
} }
return result return result
end end
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " has an unrecognized type: " .. typePart } return { isValid = false, invalidReason = "Stage zone with name " ..
stageName .. " has an unrecognized type: " .. typePart }
end end
---@param stage Stage ---@param stage Stage
@@ -223,7 +223,8 @@ function GlobalStageManager:OnStageComplete(stage)
local stageLane = self._stageRepository:getStageLane(laneIdentifier) local stageLane = self._stageRepository:getStageLane(laneIdentifier)
if not stageLane or not stageLane:IsCurrentStageIndexComplete() then if not stageLane or not stageLane:IsCurrentStageIndexComplete() then
self.logger:debug("Stage lane " .. (laneIdentifier or "default") .. " is not complete for stage index " .. stageIndex) self.logger:debug("Stage lane " ..
(laneIdentifier or "default") .. " is not complete for stage index " .. stageIndex)
return return
end end
@@ -242,7 +243,9 @@ function GlobalStageManager:OnStageComplete(stage)
if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey and lane:GetStageLaneState() == "BetweenChapters" then if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey and lane:GetStageLaneState() == "BetweenChapters" then
local nextChapterStart = lane:GetNextChapterStart() local nextChapterStart = lane:GetNextChapterStart()
if nextChapterStart == nextStageIndex then if nextChapterStart == nextStageIndex then
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is at chapter start for next stage index " .. nextStageIndex) self.logger:debug("Lane " ..
(lane:GetStageLaneIdentifier() or "default") ..
" is at chapter start for next stage index " .. nextStageIndex)
Events.PublishStageNumberChanged(nextStageIndex, lane:GetStageLaneIdentifier()) Events.PublishStageNumberChanged(nextStageIndex, lane:GetStageLaneIdentifier())
lane:SetActiveStageIndex(nextStageIndex) lane:SetActiveStageIndex(nextStageIndex)
end end
@@ -256,7 +259,6 @@ function GlobalStageManager:OnStageComplete(stage)
if defaultStageLane and defaultStageLane:GetStageLaneState() == "BetweenChapters" then if defaultStageLane and defaultStageLane:GetStageLaneState() == "BetweenChapters" then
local nextChapterStart = defaultStageLane:GetNextChapterStart() local nextChapterStart = defaultStageLane:GetNextChapterStart()
if nextChapterStart == nextStageIndex then if nextChapterStart == nextStageIndex then
-- 2. Check if all side lanes are at or beyond the next chapter starts -- 2. Check if all side lanes are at or beyond the next chapter starts
local allLanes = self._stageRepository:getAllStageLanes() local allLanes = self._stageRepository:getAllStageLanes()
local allSideLanesReady = true local allSideLanesReady = true
@@ -265,15 +267,19 @@ function GlobalStageManager:OnStageComplete(stage)
-- Check if the lane is at or beyond the next chapter starts when "InChapter" eq "Active" -- Check if the lane is at or beyond the next chapter starts when "InChapter" eq "Active"
if lane:GetStageLaneState() == "InChapter" and lane:GetActiveStageIndex() < nextStageIndex then if lane:GetStageLaneState() == "InChapter" and lane:GetActiveStageIndex() < nextStageIndex then
allSideLanesReady = false allSideLanesReady = false
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is not ready for next stage index " .. nextStageIndex) self.logger:debug("Lane " ..
(lane:GetStageLaneIdentifier() or "default") ..
" is not ready for next stage index " .. nextStageIndex)
break break
-- When in between chapters, check if the next chapter start is less than the next stage index, meaning there is still stages to be completed before the main lane can be activated again -- When in between chapters, check if the next chapter start is less than the next stage index, meaning there is still stages to be completed before the main lane can be activated again
elseif lane:GetStageLaneState() == "BetweenChapters" then elseif lane:GetStageLaneState() == "BetweenChapters" then
local nextChapter = lane:GetNextChapterStart() local nextChapter = lane:GetNextChapterStart()
if nextChapter and nextChapter < nextStageIndex then if nextChapter and nextChapter < nextStageIndex then
allSideLanesReady = false allSideLanesReady = false
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is not ready for next stage index " .. nextStageIndex) self.logger:debug("Lane " ..
(lane:GetStageLaneIdentifier() or "default") ..
" is not ready for next stage index " .. nextStageIndex)
break break
end end
end end
@@ -281,13 +287,14 @@ function GlobalStageManager:OnStageComplete(stage)
end end
if allSideLanesReady then if allSideLanesReady then
self.logger:debug("All side lanes are ready for next stage index " .. nextStageIndex .. ", activating default lane") self.logger:debug("All side lanes are ready for next stage index " ..
nextStageIndex .. ", activating default lane")
Events.PublishStageNumberChanged(nextStageIndex, nil) Events.PublishStageNumberChanged(nextStageIndex, nil)
defaultStageLane:SetActiveStageIndex(nextStageIndex) defaultStageLane:SetActiveStageIndex(nextStageIndex)
else else
self.logger:debug("Not all side lanes are ready for next stage index " .. nextStageIndex .. ", default lane will not be activated") self.logger:debug("Not all side lanes are ready for next stage index " ..
nextStageIndex .. ", default lane will not be activated")
end end
end end
end end
end end
@@ -308,7 +315,6 @@ end
---@public ---@public
function GlobalStageManager:OnStageNumberChanged(stageNumber, stageLaneIdentifier) function GlobalStageManager:OnStageNumberChanged(stageNumber, stageLaneIdentifier)
-- only react on "main" lane changes, ignore other lanes for now -- only react on "main" lane changes, ignore other lanes for now
if stageLaneIdentifier ~= nil then return end if stageLaneIdentifier ~= nil then return end
@@ -321,7 +327,6 @@ function GlobalStageManager:OnStageNumberChangeComplete(stageNumber, stageLaneId
if stageLaneIdentifier ~= nil then return end if stageLaneIdentifier ~= nil then return end
self.logger:debug("Stage number change complete to: " .. tostring(stageNumber)) self.logger:debug("Stage number change complete to: " .. tostring(stageNumber))
local groups = {} local groups = {}
for _, player in pairs(DcsUtil.getAllPlayerUnits()) do for _, player in pairs(DcsUtil.getAllPlayerUnits()) do
@@ -349,17 +354,18 @@ function GlobalStageManager:UpdateDrawings(stageNumber, stageLaneIdentifier)
if laneIdentifier == stageLaneIdentifier then if laneIdentifier == stageLaneIdentifier then
if stageNumber >= startStage and stageNumber < stopStage then if stageNumber >= startStage and stageNumber < stopStage then
self.logger:debug("Drawing " .. drawing:GetName() .. " is active for stage number: " .. tostring(stageNumber)) self.logger:debug("Drawing " ..
drawing:GetName() .. " is active for stage number: " .. tostring(stageNumber))
drawing:Draw() drawing:Draw()
else else
self.logger:debug("Drawing " .. drawing:GetName() .. " is not active for stage number: " .. tostring(stageNumber)) self.logger:debug("Drawing " ..
drawing:GetName() .. " is not active for stage number: " .. tostring(stageNumber))
drawing:Remove() drawing:Remove()
end end
end end
end end
end end
function GlobalStageManager:PrintMermaidStage() function GlobalStageManager:PrintMermaidStage()
local lanes = self._stageRepository:getAllStageLanes() local lanes = self._stageRepository:getAllStageLanes()
@@ -370,32 +376,32 @@ function GlobalStageManager:PrintMermaidStage()
-- Color palette for lanes (26 vibrant colors optimized for dark mode) -- Color palette for lanes (26 vibrant colors optimized for dark mode)
local laneColors = { local laneColors = {
"#FF6B6B", -- 1: Red "#FF6B6B", -- 1: Red
"#4ECDC4", -- 2: Teal "#4ECDC4", -- 2: Teal
"#45B7D1", -- 3: Blue "#45B7D1", -- 3: Blue
"#FFA502", -- 4: Orange "#FFA502", -- 4: Orange
"#95E1D3", -- 5: Mint "#95E1D3", -- 5: Mint
"#F38181", -- 6: Coral "#F38181", -- 6: Coral
"#AA96DA", -- 7: Purple "#AA96DA", -- 7: Purple
"#FCBAD3", -- 8: Pink "#FCBAD3", -- 8: Pink
"#A8E6CF", -- 9: Light green "#A8E6CF", -- 9: Light green
"#FFD3B6", -- 10: Peach "#FFD3B6", -- 10: Peach
"#FFAAA5", -- 11: Light red "#FFAAA5", -- 11: Light red
"#FF8B94", -- 12: Rose "#FF8B94", -- 12: Rose
"#FFEAA7", -- 13: Butter "#FFEAA7", -- 13: Butter
"#DFE6E9", -- 14: Gray "#DFE6E9", -- 14: Gray
"#00B894", -- 15: Emerald "#00B894", -- 15: Emerald
"#0984E3", -- 16: Cobalt "#0984E3", -- 16: Cobalt
"#6C5CE7", -- 17: Indigo "#6C5CE7", -- 17: Indigo
"#A29BFE", -- 18: Lavender "#A29BFE", -- 18: Lavender
"#FD79A8", -- 19: Magenta "#FD79A8", -- 19: Magenta
"#FDCB6E", -- 20: Gold "#FDCB6E", -- 20: Gold
"#6C757D", -- 21: Slate "#6C757D", -- 21: Slate
"#20C997", -- 22: Seafoam "#20C997", -- 22: Seafoam
"#E74C3C", -- 23: Scarlet "#E74C3C", -- 23: Scarlet
"#3498DB", -- 24: Dodger blue "#3498DB", -- 24: Dodger blue
"#9B59B6", -- 25: Amethyst "#9B59B6", -- 25: Amethyst
"#1ABC9C", -- 26: Turquoise "#1ABC9C", -- 26: Turquoise
} }
local laneColorMap = {} -- Map lane ID to color local laneColorMap = {} -- Map lane ID to color
local colorIndex = 1 local colorIndex = 1
@@ -552,11 +558,12 @@ function GlobalStageManager:PrintMermaidStage()
end end
-- Build complete Mermaid diagram -- Build complete Mermaid diagram
local diagramLines = {"graph TD"} local diagramLines = { "graph TD" }
-- Add class definitions for each lane with colors and contrasting text -- Add class definitions for each lane with colors and contrasting text
for laneId, color in pairs(laneColorMap) do for laneId, color in pairs(laneColorMap) do
table.insert(diagramLines, string.format(' classDef lane_%s fill:%s,stroke:#333,stroke-width:2px,color:#000', laneId, color)) table.insert(diagramLines,
string.format(' classDef lane_%s fill:%s,stroke:#333,stroke-width:2px,color:#000', laneId, color))
end end
-- Add nodes -- Add nodes
@@ -578,7 +585,8 @@ function GlobalStageManager:PrintMermaidStage()
end end
-- Print as single multi-line message -- Print as single multi-line message
local diagram = "========== STAGE FLOW DIAGRAM ==========\n" .. table.concat(diagramLines, "\n") .. "\n========== END DIAGRAM ==========" local diagram = "========== STAGE FLOW DIAGRAM ==========\n" ..
table.concat(diagramLines, "\n") .. "\n========== END DIAGRAM =========="
self.logger:info(diagram) self.logger:info(diagram)
end end
@@ -586,10 +594,10 @@ end
---@param stageNumber number ---@param stageNumber number
---@param stageLaneIdentifier string? nil for default lan ---@param stageLaneIdentifier string? nil for default lan
---@return boolean | nil ---@return boolean | nil
GlobalStageManager.isStageComplete = function (stageNumber, stageLaneIdentifier) GlobalStageManager.isStageComplete = function(stageNumber, stageLaneIdentifier)
if singletonInstance == nil then if singletonInstance == nil then
Logger.new("StageManager", "INFO"):warn("GlobalStageManager.isStageComplete called before GlobalStageManager was initialized. Returning nil") Logger.new("StageManager", "INFO"):warn(
"GlobalStageManager.isStageComplete called before GlobalStageManager was initialized. Returning nil")
return nil return nil
end end
@@ -57,7 +57,7 @@ function SpearheadGroup:Spawn(lateStart)
uncontrolled = lateStart, uncontrolled = lateStart,
} }
local spawnedObject, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent) local _, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
self._isStatic = isStatic self._isStatic = isStatic
self._isSpawned = true self._isSpawned = true
end end
@@ -50,12 +50,6 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
---@type table<string, Vec3> ---@type table<string, Vec3>
local redUnitsPos = {} local redUnitsPos = {}
local buildable = false
if self._buildableCrateKilos and self._buildableCrateKilos > 0 then
buildable = true
end
for _, groupName in pairs(blueSamData.groups) do for _, groupName in pairs(blueSamData.groups) do
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true) local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
if spearheadGroup then if spearheadGroup then
@@ -78,7 +72,7 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
--Cleanup units --Cleanup units
local cleanup_distance = 5 local cleanup_distance = 5
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do for _, blueUnitPos in pairs(blueUnitsPos) do
for redUnitName, redUnitPos in pairs(redUnitsPos) do for redUnitName, redUnitPos in pairs(redUnitsPos) do
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos) local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
if distance <= cleanup_distance then if distance <= cleanup_distance then
@@ -140,7 +134,9 @@ end
function BlueSam:SpawnGroups() function BlueSam:SpawnGroups()
for unitName, needsCleanup in pairs(self._cleanupUnits) do for unitName, needsCleanup in pairs(self._cleanupUnits) do
DcsUtil.DestroyUnit(unitName) if needsCleanup then
DcsUtil.DestroyUnit(unitName)
end
end end
for _, group in pairs(self._blueGroups) do for _, group in pairs(self._blueGroups) do
@@ -90,7 +90,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
local cleanup_distance = 5 local cleanup_distance = 5
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do for _, blueUnitPos in pairs(blueUnitsPos) do
for redUnitName, redUnitPos in pairs(redUnitsPos) do for redUnitName, redUnitPos in pairs(redUnitsPos) do
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos) local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
if distance <= cleanup_distance then if distance <= cleanup_distance then
@@ -76,8 +76,6 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
self._buildableMission = nil self._buildableMission = nil
end end
if self._buildableMission == nil then if self._buildableMission == nil then
self._buildableLogger:debug("No buildable mission for zone: " .. targetZone.name) self._buildableLogger:debug("No buildable mission for zone: " .. targetZone.name)
end end
@@ -99,23 +97,11 @@ function BuildableZone:OnBuildingComplete() end
---@field unpackedItems number ---@field unpackedItems number
---@field unpackedKilos number ---@field unpackedKilos number
---@param mission BuildableMission? ---@param _ BuildableMission?
---@param kilos number ---@param kilos number
function BuildableZone:OnCrateDroppedOff(mission, kilos) function BuildableZone:OnCrateDroppedOff(_, kilos)
self._buildableLogger:debug("Crate dropped off in zone: " .. self._targetZone.name) self._buildableLogger:debug("Crate dropped off in zone: " .. self._targetZone.name)
local timeToUnpack = (kilos / 500) * 15
---@type UnpackCrateParam
local params = {
self = self,
groupsPerKilo = self._groupsPerKilo,
unpackedItems = 0,
kilosPerSecond = kilos/timeToUnpack,
unpackedKilos = 0,
kilos = kilos
}
---@param params UnpackCrateParam ---@param params UnpackCrateParam
---@param time number ---@param time number
local startUnpackingCrate = function(params, time) local startUnpackingCrate = function(params, time)
@@ -136,6 +122,17 @@ function BuildableZone:OnCrateDroppedOff(mission, kilos)
return time + 2 return time + 2
end end
local timeToUnpack = (kilos / 500) * 15
---@type UnpackCrateParam
local params = {
self = self,
groupsPerKilo = self._groupsPerKilo,
unpackedItems = 0,
kilosPerSecond = kilos/timeToUnpack,
unpackedKilos = 0,
kilos = kilos
}
timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 2) timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 2)
end end
@@ -190,7 +187,7 @@ function BuildableZone:SpawnAmount(amount)
return nil return nil
end end
for i = 1, amount do for _ = 1, amount do
local spawned = spawnOne() local spawned = spawnOne()
if spawned ~= true then if spawned ~= true then
self._buildableLogger:debug("No more groups to spawn in zone: " .. self._targetZone.name) self._buildableLogger:debug("No more groups to spawn in zone: " .. self._targetZone.name)
@@ -49,7 +49,6 @@ end
function StageRepository:AddStage(stage) function StageRepository:AddStage(stage)
local stageLaneIdentifier = stage:GetStageLaneIdentifier() or StageLane.DefaultLaneKey local stageLaneIdentifier = stage:GetStageLaneIdentifier() or StageLane.DefaultLaneKey
if self.StageLanes[tostring(stageLaneIdentifier)] == nil then if self.StageLanes[tostring(stageLaneIdentifier)] == nil then
self.StageLanes[tostring(stageLaneIdentifier)] = StageLane.New(stageLaneIdentifier) self.StageLanes[tostring(stageLaneIdentifier)] = StageLane.New(stageLaneIdentifier)
end end
@@ -160,13 +160,13 @@ function Stage:superNew(database, stageConfig, logger, initData, stageType, miss
self._logger:info("Initiating new Stage with name: " .. self.zoneName) self._logger:info("Initiating new Stage with name: " .. self.zoneName)
---comment ---comment
---@param self Stage ---@param selfA Stage
---@param time number? ---@param time number?
self.CheckContinuousAsync = function (self, time) self.CheckContinuousAsync = function (selfA, time)
self:CheckAndUpdateSelf() selfA:CheckAndUpdateSelf()
if self:IsComplete() == true then if selfA:IsComplete() == true then
self:NotifyComplete() selfA:NotifyComplete()
return nil return nil
end end
@@ -284,14 +284,14 @@ end
function Stage:IsComplete() function Stage:IsComplete()
if self._currentStageState >= StageState.Blue then return true end if self._currentStageState >= StageState.Blue then return true end
for i, mission in pairs(self._db.sams) do for _, mission in pairs(self._db.sams) do
local state = mission:getState() local state = mission:getState()
if state == "ACTIVE" or state == "NEW" or state =="WAITING" then if state == "ACTIVE" or state == "NEW" or state =="WAITING" then
return false return false
end end
end end
for i, mission in pairs(self._db.missions) do for _, mission in pairs(self._db.missions) do
local state = mission:getState() local state = mission:getState()
if state == "ACTIVE" or state == "NEW" then if state == "ACTIVE" or state == "NEW" then
return false return false
@@ -370,9 +370,9 @@ function Stage:CheckAndUpdateSelf()
local availableMissionsCount = Util.tableLength(getAvailableMissions()) local availableMissionsCount = Util.tableLength(getAvailableMissions())
local activeCount = getActiveMissionsCount() local activeCount = getActiveMissionsCount()
if activeCount < max and availableMissionsCount > 0 then if activeCount < max and availableMissionsCount > 0 then
for i = activeCount+1, max do for _ = activeCount+1, max do
if availableMissionsCount == 0 then if availableMissionsCount == 0 then
i = max+1 --exits this loop break
else else
local mission = Util.randomFromList(getAvailableMissions()) --[[@as Mission]] local mission = Util.randomFromList(getAvailableMissions()) --[[@as Mission]]
if mission then if mission then
@@ -426,7 +426,7 @@ function Stage:PreActivate()
end end
self._currentStageState = StageState.PreActivated self._currentStageState = StageState.PreActivated
for key, mission in pairs(self._db.sams) do for _, mission in pairs(self._db.sams) do
if mission then if mission then
mission:SpawnInactive() mission:SpawnInactive()
end end
@@ -589,8 +589,8 @@ function Stage:OnStageNumberChanged(number, stageLaneIdentifier)
end end
---@param self Stage ---@param self Stage
---@param mission Mission ---@param _ Mission
Stage.OnMissionComplete = function(self, mission) Stage.OnMissionComplete = function(self, _)
self:CheckAndUpdateSelf() self:CheckAndUpdateSelf()
end end
@@ -645,7 +645,7 @@ function Stage:GetStageStats()
end end
end end
for _, mission in pairs(self._db.sams) do for _, _ in pairs(self._db.sams) do
dead = dead + 1 dead = dead + 1
end end
@@ -673,13 +673,13 @@ function Stage:ActivateBlueStage()
miscGroup:Spawn() miscGroup:Spawn()
end end
---@param self Stage ---@param selfA Stage
local ActivateBlueAsync = function(self) local ActivateBlueAsync = function(selfA)
pcall(function() pcall(function()
self:MarkStage() selfA:MarkStage()
end) end)
self:ActivateBlueGroups() selfA:ActivateBlueGroups()
return nil return nil
end end
@@ -1,7 +1,7 @@
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage") local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
local GlobalCapManager = require("classes.capClasses.GlobalCapManager") local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
local StageState = require("classes.stageClasses.Stages.StageState") local StageState = require("classes.stageClasses.Stages.BaseStage.StageState")
---@class ExtraStage : Stage ---@class ExtraStage : Stage
local ExtraStage = {} local ExtraStage = {}
@@ -23,7 +23,6 @@ function ExtraStage.New(database, stageConfig, logger, initData, spawnManager)
self:superNew(database, stageConfig, logger, initData, "ExtraStage", "secondary", spawnManager) self:superNew(database, stageConfig, logger, initData, "ExtraStage", "secondary", spawnManager)
self.OnPostBlueActivated = function (selfStage) self.OnPostBlueActivated = function (selfStage)
selfStage:MarkStage() selfStage:MarkStage()
end end
@@ -48,7 +47,6 @@ function ExtraStage:OnStageNumberChanged(number, stageLaneIdentifier)
return return
end end
local previousActive = self._activeStage
self._activeStage = number self._activeStage = number
if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then
@@ -62,7 +60,7 @@ function ExtraStage:OnStageNumberChanged(number, stageLaneIdentifier)
self:ActivateStage() self:ActivateStage()
end end
if self._currentStageState == StageState.BLUE then if self._currentStageState == StageState.Blue then
self:ActivateBlueStage() self:ActivateBlueStage()
end end
@@ -56,7 +56,7 @@ function WaitingStage:OnStageNumberChanged()
self._logger:debug("Waiting Stage OnStageNumberChanged override") self._logger:debug("Waiting Stage OnStageNumberChanged override")
end end
function WaitingStage:MarkStage(stageColor) function WaitingStage:MarkStage(_)
self._logger:debug("Waiting Stage MarkStage override") self._logger:debug("Waiting Stage MarkStage override")
end end
@@ -1,7 +1,5 @@
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper") local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
local Util = require("classes.util.Util")
local Logger = require("classes.util.Logger") local Logger = require("classes.util.Logger")
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
local drawingLogger = Logger.new("CustomDrawing") local drawingLogger = Logger.new("CustomDrawing")
@@ -1,4 +1,3 @@
local Util = require("classes.util.Util")
local DcsUtil = require("classes.util.DcsUtil") local DcsUtil = require("classes.util.DcsUtil")
local Logger = require("classes.util.Logger") local Logger = require("classes.util.Logger")
local GlobalConfig = require("classes.configuration.GlobalConfig") local GlobalConfig = require("classes.configuration.GlobalConfig")
@@ -1,6 +1,5 @@
local Logger = require("classes.util.Logger") local Logger = require("classes.util.Logger")
local Util = require("classes.util.Util") local Util = require("classes.util.Util")
local DcsUtil = require("classes.util.DcsUtil")
---@class BattleManager ---@class BattleManager
---@field private _name string ---@field private _name string
@@ -13,8 +12,6 @@ local DcsUtil = require("classes.util.DcsUtil")
local BattleManager = {} local BattleManager = {}
BattleManager.__index = BattleManager BattleManager.__index = BattleManager
local debugDrawing = false
---@param redGroups Array<SpearheadGroup> ---@param redGroups Array<SpearheadGroup>
---@param blueGroups Array<SpearheadGroup> ---@param blueGroups Array<SpearheadGroup>
---@param name string ---@param name string
@@ -90,8 +87,6 @@ function BattleManager:Update()
self._logger:debug("BattleManager Update called for " .. self._name) self._logger:debug("BattleManager Update called for " .. self._name)
local shootChance = 1 -- Adjust this value to control the shooting probability (0.0 to 1.0)
self:LetUnitsShoot(self._redGroups, self._blueGroups) self:LetUnitsShoot(self._redGroups, self._blueGroups)
self:LetUnitsShoot(self._blueGroups, self._redGroups) self:LetUnitsShoot(self._blueGroups, self._redGroups)
@@ -31,8 +31,6 @@ local function sortMissions(list, groupPos)
end) end)
end end
local id = 0
local instance = nil local instance = nil
---@return MissionCommandsHelper ---@return MissionCommandsHelper
@@ -57,16 +55,16 @@ function MissionCommandsHelper.getOrCreate()
instance._supplyUnitsTracker:AddOnSupplyUnitEventListener( instance._supplyUnitsTracker:AddOnSupplyUnitEventListener(
{ {
enteredSupplyHub = function(self, unit) enteredSupplyHub = function(_, unit)
if unit == nil then return end if unit == nil then return end
instance.updateNeeded = true instance.updateNeeded = true
instance:updateCommandsForGroup(unit:getGroup():getID()) instance:updateCommandsForGroup(unit:getGroup():getID())
end, end,
exitedSupplyHub = function(self, unit) exitedSupplyHub = function(_, unit)
instance.updateNeeded = true instance.updateNeeded = true
instance:updateCommandsForGroup(unit:getGroup():getID()) instance:updateCommandsForGroup(unit:getGroup():getID())
end, end,
supplyUnitSpawned = function(self, unit) supplyUnitSpawned = function(_, unit)
instance.updateNeeded = true instance.updateNeeded = true
instance:updateCommandsForGroup(unit:getGroup():getID()) instance:updateCommandsForGroup(unit:getGroup():getID())
end end
@@ -509,7 +507,6 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
local unloadCargoCommand = function(params) local unloadCargoCommand = function(params)
local unitID = params.unitID local unitID = params.unitID
local crateType = params.crateType local crateType = params.crateType
local supplyUnitsTracker = params.supplyUnitsTracker
params.supplyUnitsTracker:UnloadRequested(unitID, crateType, params.commandHelper) params.supplyUnitsTracker:UnloadRequested(unitID, crateType, params.commandHelper)
end end
@@ -518,7 +515,7 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
for cargoType, amount in pairs(cargo) do for cargoType, amount in pairs(cargo) do
local cargoConfig = SupplyConfigHelper.getSupplyConfig(cargoType) local cargoConfig = SupplyConfigHelper.getSupplyConfig(cargoType)
if cargoConfig then if cargoConfig then
for i = 1, amount do for _ = 1, amount do
local path = { [1] = folderNames.cargo } local path = { [1] = folderNames.cargo }
---@type UnloadCargoCommandParams ---@type UnloadCargoCommandParams
local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self
@@ -185,7 +185,7 @@ function SupplyUnitsTracker:RemoveCargoFromUnit(unitID, crateType)
self._cargoInUnits[unitIDStr][crateType] = self._cargoInUnits[unitIDStr][crateType] - 1 self._cargoInUnits[unitIDStr][crateType] = self._cargoInUnits[unitIDStr][crateType] - 1
local hasCargo = false local hasCargo = false
for type, count in pairs(self._cargoInUnits[unitIDStr]) do for _, count in pairs(self._cargoInUnits[unitIDStr]) do
if count > 0 then if count > 0 then
hasCargo = true hasCargo = true
break break
@@ -216,13 +216,11 @@ end
function SupplyUnitsTracker:CheckUnitsInZones() function SupplyUnitsTracker:CheckUnitsInZones()
for name, unit in pairs(self._supplyUnitsByName) do for _, unit in pairs(self._supplyUnitsByName) do
if unit ~= nil and unit:isExist() == true then if unit ~= nil and unit:isExist() == true then
self._logger:debug("Checking unit: " .. unit:getName()) self._logger:debug("Checking unit: " .. unit:getName())
local pos = unit:getPoint() local pos = unit:getPoint()
local group = unit:getGroup()
for hub, enabled in pairs(self._registeredHubs) do for hub, enabled in pairs(self._registeredHubs) do
if enabled == true then if enabled == true then
local zone = hub:GetZone() local zone = hub:GetZone()
@@ -614,7 +612,7 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
} }
local occupiedObjects = {} local occupiedObjects = {}
local found = function(foundItem, val) local found = function(foundItem, _)
local bbox = self:GetBoundingBoxes(foundItem) local bbox = self:GetBoundingBoxes(foundItem)
if bbox then if bbox then
self._logger:debug("Found object: " .. foundItem:getTypeName() .. " at (" .. foundItem:getPoint().x .. ", " .. foundItem:getPoint().z .. ")") self._logger:debug("Found object: " .. foundItem:getTypeName() .. " at (" .. foundItem:getPoint().x .. ", " .. foundItem:getPoint().z .. ")")
@@ -25,7 +25,7 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe
local BuildableMission = {} local BuildableMission = {}
BuildableMission.__index = BuildableMission BuildableMission.__index = BuildableMission
---@return string
local function getDefaultBriefing(siteType, coords) local function getDefaultBriefing(siteType, coords)
return "We've dispatched forward units to find a proper spot for a new " .. siteType .. "." .. return "We've dispatched forward units to find a proper spot for a new " .. siteType .. "." ..
"\nYou will need to drop off supplies so they can start building." .. "\nYou will need to drop off supplies so they can start building." ..
@@ -83,13 +83,6 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
self.name = "Resupply" self.name = "Resupply"
end end
local type = "site"
if requiredCrateType == "SAM_CRATE" then
type = "SAM site"
elseif requiredCrateType == "FARP_CRATE" then
type = "FARP"
end
self.zoneName = targetZone.name .. "_supply" self.zoneName = targetZone.name .. "_supply"
self._logger = logger self._logger = logger
self._onCrateDroppedOfListeners = {} self._onCrateDroppedOfListeners = {}
@@ -84,7 +84,6 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
self._logger:debug("Runway hit: " .. self._airportName .. ":" .. self._runway.Name) self._logger:debug("Runway hit: " .. self._airportName .. ":" .. self._runway.Name)
for _, section in pairs(self._runwaySections) do for _, section in pairs(self._runwaySections) do
local zone = self:SectionToSpearheadZone(section) local zone = self:SectionToSpearheadZone(section)
if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
if section.kilosHit == nil then if section.kilosHit == nil then
@@ -96,7 +95,7 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
end end
---@param selfA RunwayStrikeMission ---@param selfA RunwayStrikeMission
local updateState = function(selfA, time) local updateState = function(selfA, _)
selfA:UpdateState() selfA:UpdateState()
end end
@@ -213,7 +212,6 @@ function RunwayStrikeMission:StartRepair()
if interval == nil then return nil end if interval == nil then return nil end
return time + interval return time + interval
end end
timer.scheduleFunction(repairTask, self, timer.getTime() + 5) timer.scheduleFunction(repairTask, self, timer.getTime() + 5)
end end
@@ -211,7 +211,7 @@ end
---@return boolean ---@return boolean
function ZoneMission:AllDependenciesMet() function ZoneMission:AllDependenciesMet()
local allDependenciesMet = true local allDependenciesMet = true
for missionName, value in pairs(self._dependencies) do for missionName, _ in pairs(self._dependencies) do
if self._parentStage:IsMissionComplete(missionName) == false then if self._parentStage:IsMissionComplete(missionName) == false then
allDependenciesMet = false allDependenciesMet = false
self._dependencies[missionName] = false self._dependencies[missionName] = false
@@ -70,6 +70,7 @@ function Mission:SpawnActive() end
---comment ---comment
---@param checkHealth boolean ---@param checkHealth boolean
---@param messageIfDone boolean ---@param messageIfDone boolean
---@diagnostic disable-next-line: unused-local
function Mission:UpdateState(checkHealth, messageIfDone) end function Mission:UpdateState(checkHealth, messageIfDone) end
function Mission:StartCheckingContinuous() end function Mission:StartCheckingContinuous() end
@@ -120,7 +121,7 @@ function Mission:NotifyMissionComplete()
end) end)
end end
local succ, err = pcall(function() local _, _ = pcall(function()
SpearheadAPI.Internal.notifyMissionComplete(self.zoneName) SpearheadAPI.Internal.notifyMissionComplete(self.zoneName)
end) end)
@@ -131,6 +132,8 @@ function Mission:ForceMissionComplete()
self:NotifyMissionComplete() self:NotifyMissionComplete()
end end
---@param groupId number
---@diagnostic disable-next-line: unused-local
function Mission:MarkMissionAreaToGroup(groupId) end function Mission:MarkMissionAreaToGroup(groupId) end
---endregion ---endregion
+21 -22
View File
@@ -77,7 +77,7 @@ do -- INIT DCS_UTIL
do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment
do --init trigger zones do --init trigger zones
for i, trigger_zone in pairs(env.mission.triggers.zones) do for _, trigger_zone in pairs(env.mission.triggers.zones) do
-- reorder verts as they are not ordered correctly in the ME -- reorder verts as they are not ordered correctly in the ME
local verts = {} local verts = {}
if Util.tableLength(trigger_zone.verticies) >= 4 then if Util.tableLength(trigger_zone.verticies) >= 4 then
@@ -192,7 +192,7 @@ do -- INIT DCS_UTIL
BLUE = 2 BLUE = 2
} }
]] -- ]] --
local input = string.lower(input) input = string.lower(input)
if input == 'neutrals' or input == "neutral" or input == "0" then if input == 'neutrals' or input == "neutral" or input == "0" then
return DCS_UTIL.Coalition.NEUTRAL return DCS_UTIL.Coalition.NEUTRAL
end end
@@ -235,7 +235,7 @@ do -- INIT DCS_UTIL
end end
end end
for index, zone_name in pairs(zone_names) do for _, zone_name in pairs(zone_names) do
local zone = DCS_UTIL.__trigger_zones[zone_name] local zone = DCS_UTIL.__trigger_zones[zone_name]
if zone then if zone then
zones[#zones + 1] = zone zones[#zones + 1] = zone
@@ -247,7 +247,7 @@ do -- INIT DCS_UTIL
local lUnit = units[units_ind] local lUnit = units[units_ind]
local unit_pos = lUnit:getPosition().p local unit_pos = lUnit:getPosition().p
local lCat = Object.getCategory(lUnit) local lCat = Object.getCategory(lUnit)
for zone_name, zone in pairs(zones) do for _, zone in pairs(zones) do
if unit_pos and ((lCat == 1 and lUnit:isActive() == true) or lCat ~= 1) then -- it is a unit and is active or it is not a unit if unit_pos and ((lCat == 1 and lUnit:isActive() == true) or lCat ~= 1) then -- it is a unit and is active or it is not a unit
local isInZone = Util.is3dPointInZone(unit_pos, zone) local isInZone = Util.is3dPointInZone(unit_pos, zone)
if isInZone == true then if isInZone == true then
@@ -313,7 +313,7 @@ do -- INIT DCS_UTIL
function DCS_UTIL.isPositionInZones(x, z, zone_names) function DCS_UTIL.isPositionInZones(x, z, zone_names)
---@type Array<SpearheadTriggerZone> ---@type Array<SpearheadTriggerZone>
local zones = {} local zones = {}
for index, zone_name in pairs(zone_names) do for _, zone_name in pairs(zone_names) do
local zone = DCS_UTIL.__trigger_zones[zone_name] local zone = DCS_UTIL.__trigger_zones[zone_name]
if zone then if zone then
zones[#zones + 1] = zone zones[#zones + 1] = zone
@@ -321,7 +321,7 @@ do -- INIT DCS_UTIL
end end
local result_zones = {} local result_zones = {}
for zone_name, zone in pairs(zones) do for _, zone in pairs(zones) do
if Util.is3dPointInZone({ x = x, z = z, y = 0 }, zone) == true then if Util.is3dPointInZone({ x = x, z = z, y = 0 }, zone) == true then
result_zones[#result_zones + 1] = zone.name result_zones[#result_zones + 1] = zone.name
end end
@@ -414,7 +414,7 @@ do -- INIT DCS_UTIL
local height = land.getHeight(location) local height = land.getHeight(location)
local vec3 = { x = location.x, y = height, z = location.y } local vec3 = { x = location.x, y = height, z = location.y }
local unitType = string.lower(unitType or "") unitType = string.lower(unitType or "")
local conversionType = config[unitType] local conversionType = config[unitType]
if not conversionType then conversionType = "DDM" end if not conversionType then conversionType = "DDM" end
@@ -574,7 +574,7 @@ do -- INIT DCS_UTIL
local units = {} local units = {}
for i = 0, 2 do for i = 0, 2 do
local players = coalition.getPlayers(i) local players = coalition.getPlayers(i)
for key, unit in pairs(players) do for _, unit in pairs(players) do
units[#units + 1] = unit units[#units + 1] = unit
end end
end end
@@ -617,8 +617,7 @@ do -- INIT DCS_UTIL
end end
function DCS_UTIL.CleanCorpse(unitName) function DCS_UTIL.CleanCorpse(unitName)
local unitName = "dead_" .. unitName unitName = "dead_" .. unitName
local object = StaticObject.getByName(unitName) local object = StaticObject.getByName(unitName)
if object then if object then
@@ -632,11 +631,11 @@ do -- INIT DCS_UTIL
---@field b number ---@field b number
---@field a number ---@field a number
local drawID = 4210 local __drawID = 4210
function DCS_UTIL.GetNextDrawID() function DCS_UTIL.GetNextDrawID()
drawID = drawID + 1 __drawID = __drawID + 1
return drawID return __drawID
end end
---@param groupID number ---@param groupID number
@@ -644,9 +643,9 @@ do -- INIT DCS_UTIL
---@param location Vec3 ---@param location Vec3
---@return number markID ---@return number markID
function DCS_UTIL.AddMarkToGroup(groupID, text, location) function DCS_UTIL.AddMarkToGroup(groupID, text, location)
local drawID = DCS_UTIL.GetNextDrawID() local nextId = DCS_UTIL.GetNextDrawID()
trigger.action.markToGroup(drawID, text, location, groupID, true, nil) trigger.action.markToGroup(nextId, text, location, groupID, true, nil)
return drawID return nextId
end end
---comment ---comment
@@ -654,9 +653,9 @@ do -- INIT DCS_UTIL
---@param location Vec3 ---@param location Vec3
---@return integer ---@return integer
function DCS_UTIL.AddMarkToAll(text, location) function DCS_UTIL.AddMarkToAll(text, location)
local drawID = DCS_UTIL.GetNextDrawID() local nextId = DCS_UTIL.GetNextDrawID()
trigger.action.markToAll(drawID, text, location, true, nil) trigger.action.markToAll(nextId, text, location, true, nil)
return drawID return nextId
end end
---@param markId number ---@param markId number
@@ -705,7 +704,7 @@ do -- INIT DCS_UTIL
---@return number? id ---@return number? id
function DCS_UTIL.GetNeutralCountry() function DCS_UTIL.GetNeutralCountry()
for name, id in pairs(country.id) do for _, id in pairs(country.id) do
if coalition.getCountryCoalition(id) == DCS_UTIL.Coalition.NEUTRAL then if coalition.getCountryCoalition(id) == DCS_UTIL.Coalition.NEUTRAL then
return id return id
end end
@@ -759,7 +758,7 @@ do -- INIT DCS_UTIL
function DCS_UTIL.GetPlayerGroupByGroupID(groupId) function DCS_UTIL.GetPlayerGroupByGroupID(groupId)
for i = 0, 2 do for i = 0, 2 do
local players = coalition.getPlayers(i) local players = coalition.getPlayers(i)
for key, unit in pairs(players) do for _, unit in pairs(players) do
if unit and unit:isExist() == true then if unit and unit:isExist() == true then
local group = unit:getGroup() local group = unit:getGroup()
if group and group:getID() == groupId then if group and group:getID() == groupId then
@@ -775,7 +774,7 @@ do -- INIT DCS_UTIL
function DCS_UTIL.GetPlayerUnitByID(unitID) function DCS_UTIL.GetPlayerUnitByID(unitID)
for i = 0, 2 do for i = 0, 2 do
local players = coalition.getPlayers(i) local players = coalition.getPlayers(i)
for key, unit in pairs(players) do for _, unit in pairs(players) do
if unit and unit:getID() == unitID then if unit and unit:getID() == unitID then
return unit return unit
end end
+8 -1
View File
@@ -149,7 +149,7 @@ do -- INIT UTIL
---@param findableTable table ---@param findableTable table
---@return boolean ---@return boolean
UTIL.startswithAny = function(str, findableTable) UTIL.startswithAny = function(str, findableTable)
for key, value in pairs(findableTable) do for _, value in pairs(findableTable) do
if type(value) == "string" and UTIL.startswith(str, value) then return true end if type(value) == "string" and UTIL.startswith(str, value) then return true end
end end
return false return false
@@ -238,7 +238,12 @@ do -- INIT UTIL
return ((vec1Norm.x * vec2Norm.x) + (vec1Norm.y * vec2Norm.y) + (vec1Norm.z * vec2Norm.z)) return ((vec1Norm.x * vec2Norm.x) + (vec1Norm.y * vec2Norm.y) + (vec1Norm.z * vec2Norm.z))
end end
---@param polygon Array<Vec2> of pairs { x, y }
---@param x number X location
---@param y number Y location
---@return boolean
local function isInComplexPolygon(polygon, x, y) local function isInComplexPolygon(polygon, x, y)
---@param poly Array<Vec2> of pairs { x, y }
local function getEdges(poly) local function getEdges(poly)
local result = {} local result = {}
for i = 1, #poly do for i = 1, #poly do
@@ -399,7 +404,9 @@ do -- INIT UTIL
if #points == 0 then return {} end if #points == 0 then return {} end
-- Simple clustering: group points that are within minSeparation of each other -- Simple clustering: group points that are within minSeparation of each other
---@type Array<Array<Vec2>>
local clusters = {} local clusters = {}
---@type table<integer, boolean>
local assigned = {} local assigned = {}
for i, p in ipairs(points) do for i, p in ipairs(points) do
+1 -2
View File
@@ -1,7 +1,6 @@
--Single player purpose --Single player purpose
local Logger = require("classes.util.Logger") local Logger = require("classes.util.Logger")
local DcsUtil = require("classes.util.DcsUtil")
local Database = require("classes.spearhead_db") local Database = require("classes.spearhead_db")
local SpearheadEvents = require("classes.spearhead_events") local SpearheadEvents = require("classes.spearhead_events")
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper") local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
@@ -47,7 +46,7 @@ local spawnManager = SpawnManager.new(spawnLogger)
local detectionLogger = Logger.new("DetectionManager", defaultLogLevel) local detectionLogger = Logger.new("DetectionManager", defaultLogLevel)
local detectionManager = DetectionManager.New(detectionLogger) local detectionManager = DetectionManager.New(detectionLogger)
GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager) GlobalCapManager.start(databaseManager, capConfig, detectionManager, defaultLogLevel, spawnManager)
local globalStageManager = GlobalStageManager.new(databaseManager, stageConfig, defaultLogLevel, spawnManager) local globalStageManager = GlobalStageManager.new(databaseManager, stageConfig, defaultLogLevel, spawnManager)
GlobalFleetManager.start(databaseManager) GlobalFleetManager.start(databaseManager)