Fixed bugs found in v0.0.2

This commit is contained in:
2025-05-01 21:53:54 +02:00
parent d16792064f
commit fc726cbb37
18 changed files with 737 additions and 694 deletions
+1
View File
@@ -540,6 +540,7 @@ end
do -- Controller do -- Controller
---@class Controller ---@class Controller
---@field setTask fun(self:Controller, task: Task) Sets the task of the controller to the passed task ---@field setTask fun(self:Controller, task: Task) Sets the task of the controller to the passed task
---@field setCommand function
Controller = Controller Controller = Controller
Binary file not shown.
+70 -55
View File
@@ -1,35 +1,71 @@
---@class CapBase : OnStageChangedListener
---@field groupNames Array<string>
---@field database Database
---@field airbaseName string
---@field logger table
---@field activeStage number
---@field capConfig table
---@field activeCapStages number
---@field lastStatesByName table<string, string>
---@field groupsByName table<string, CapGroup>
---@field PrimaryGroups Array<CapGroup>
---@field BackupGroups Array<CapGroup>
local CapBase = {} local CapBase = {}
local CheckReschedulingAsync = function(self, time)
self:CheckAndScheduleCAP()
end
---comment ---comment
---@param airbaseId number ---@param airbaseName string
---@param database table ---@param database Database
---@param logger table ---@param logger table
---@param capConfig table ---@param capConfig table
---@param stageConfig table ---@param stageConfig table
---@return table ---@return CapBase
function CapBase:new(airbaseId, database, logger, capConfig, stageConfig) function CapBase.new(airbaseName, database, logger, capConfig, stageConfig)
local o = {}
setmetatable(o, { __index = self })
o.groupNames = database:getCapGroupsAtAirbase(airbaseId) CapBase.__index = CapBase
o.database = database local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]]
o.airbaseId = airbaseId
o.logger = logger
o.activeStage = 0
o.capConfig = capConfig
o.activeCapStages = (stageConfig or {}).capActiveStages or 10
o.lastStatesByName = {} self.groupNames = database:getCapGroupsAtAirbase(airbaseName)
o.groupsByName = {} self.database = database
o.PrimaryGroups = {}
o.BackupGroups = {}
local CheckReschedulingAsync = function(self, time) self.airbaseName = airbaseName
self:CheckAndScheduleCAP() self.logger = logger
self.activeStage = 0
self.capConfig = capConfig
self.activeCapStages = (stageConfig or {}).capActiveStages or 10
self.lastStatesByName = {}
self.groupsByName = {}
self.PrimaryGroups = {}
self.BackupGroups = {}
for key, name in pairs(self.groupNames) do
local capGroup = Spearhead.internal.CapGroup.new(name, airbaseName, logger, database, capConfig)
if capGroup then
self.groupsByName[name] = capGroup
if capGroup.isBackup ==true then
table.insert(self.BackupGroups, capGroup)
else
table.insert(self.PrimaryGroups, capGroup)
end end
o.OnGroupStateUpdated = function (self, capGroup) capGroup:AddOnStateUpdatedListener(self)
end
end
logger:info("Airbase with name '" .. airbaseName .. "' has a total of " .. Spearhead.Util.tableLength(self.groupsByName) .. "cap flights registered")
Spearhead.Events.AddStageNumberChangedListener(self)
return self
end
function CapBase:onGroupStateUpdated(capGroup)
--[[ --[[
There is no update needed for INTRANSIT, ONSTATION or REARMING as the PREVIOUS state already was checked and nothing changes in the actual overal state. There is no update needed for INTRANSIT, ONSTATION or REARMING as the PREVIOUS state already was checked and nothing changes in the actual overal state.
]]-- ]]--
@@ -40,30 +76,13 @@ function CapBase:new(airbaseId, database, logger, capConfig, stageConfig)
return return
end end
timer.scheduleFunction(CheckReschedulingAsync, self, timer.getTime() + 1) timer.scheduleFunction(CheckReschedulingAsync, self, timer.getTime() + 1)
end end
for key, name in pairs(o.groupNames) do function CapBase:SpawnIfApplicable()
local capGroup = Spearhead.internal.CapGroup:new(name, airbaseId, logger, database, capConfig) self.logger:debug("Check spawns for airbase " .. self.airbaseName )
if capGroup then
o.groupsByName[name] = capGroup
if capGroup.isBackup ==true then
table.insert(o.BackupGroups, capGroup)
else
table.insert(o.PrimaryGroups, capGroup)
end
capGroup:AddOnStateUpdatedListener(o)
end
end
logger:info("Airbase with Id '" .. airbaseId .. "' has a total of " .. Spearhead.Util.tableLength(o.groupsByName) .. "cap flights registered")
o.SpawnIfApplicable = function(self)
self.logger:debug("Check spawns for airbase " .. self.airbaseId )
for groupName, capGroup in pairs(self.groupsByName) do for groupName, capGroup in pairs(self.groupsByName) do
local activeStage = tostring(self.activeStage) local targetStage = capGroup:GetTargetZone(self.activeStage)
local targetStage = capGroup:GetTargetZone(activeStage)
if targetStage ~= nil and capGroup.state == Spearhead.internal.CapGroup.GroupState.UNSPAWNED then if targetStage ~= nil and capGroup.state == Spearhead.internal.CapGroup.GroupState.UNSPAWNED then
capGroup:SpawnOnTheRamp() capGroup:SpawnOnTheRamp()
@@ -71,9 +90,9 @@ function CapBase:new(airbaseId, database, logger, capConfig, stageConfig)
end end
end end
o.CheckAndScheduleCAP = function (self) function CapBase:CheckAndScheduleCAP()
self.logger:debug("Check taskings for airbase " .. self.airbaseId ) self.logger:debug("Check taskings for airbase " .. self.airbaseName )
local countPerStage = {} local countPerStage = {}
local requiredPerStage = {} local requiredPerStage = {}
@@ -156,17 +175,16 @@ function CapBase:new(airbaseId, database, logger, capConfig, stageConfig)
end end
end end
o.OnStageNumberChanged = function (self, number) function CapBase:OnStageNumberChanged(number)
self.activeStage = number self.activeStage = number
self:SpawnIfApplicable() self:SpawnIfApplicable()
timer.scheduleFunction(CheckReschedulingAsync, self, timer.getTime() + 5) timer.scheduleFunction(CheckReschedulingAsync, self, timer.getTime() + 5)
end end
---Check if any CAP is active when a certain stage is active
---@param self table ---@param stageNumber number
---@param stageNumber number ---@return boolean
---@return boolean function CapBase:IsBaseActiveWhenStageIsActive(stageNumber)
o.IsBaseActiveWhenStageIsActive = function (self, stageNumber)
for _, group in pairs(self.PrimaryGroups) do for _, group in pairs(self.PrimaryGroups) do
local target = group:GetTargetZone(stageNumber) local target = group:GetTargetZone(stageNumber)
if target ~= nil then if target ~= nil then
@@ -174,11 +192,8 @@ function CapBase:new(airbaseId, database, logger, capConfig, stageConfig)
end end
end end
return false return false
end
Spearhead.Events.AddStageNumberChangedListener(o)
return o
end end
if not Spearhead.internal then Spearhead.internal = {} end if not Spearhead.internal then Spearhead.internal = {} end
Spearhead.internal.CapAirbase = CapBase Spearhead.internal.CapAirbase = CapBase
+115 -95
View File
@@ -77,7 +77,7 @@ local function setTaskAsync(input, time)
local groupName = input.groupName local groupName = input.groupName
local group = Group.getByName(groupName) local group = Group.getByName(groupName)
if task then if task and group then
group:getController():setTask(task) group:getController():setTask(task)
if input.logger ~= nil then if input.logger ~= nil then
input.logger:debug("task set succesfully to group " .. groupName) input.logger:debug("task set succesfully to group " .. groupName)
@@ -86,6 +86,21 @@ local function setTaskAsync(input, time)
return nil return nil
end end
---@class OnUpdateListener
---@field onGroupStateUpdated fun(self: OnUpdateListener, capGroup: CapGroup)
---@class CapGroup : OnUnitLostListener
---@field isBackup boolean
---@field groupName string
---@field assignedStageNumber string
---@field private airbaseName string
---@field private logger Logger
---@field private database Database
---@field private capConfig table
---@field private capZonesConfig table<string, string>
---@field private aliveUnits table<string, boolean>
---@field private onStatusUpdatedListener Array<OnUpdateListener>
local CapGroup = {} local CapGroup = {}
CapGroup.GroupState = { CapGroup.GroupState = {
@@ -103,66 +118,87 @@ local function SetReadyOnRampAsync(self, time)
self:SetState(CapGroup.GroupState.READYONRAMP) self:SetState(CapGroup.GroupState.READYONRAMP)
end end
local RESPAWN_AFTER_TOUCHDOWN_SECONDS = 180
---comment ---comment
---@param groupName string ---@param groupName string
---@param airbaseId number ---@param airbaseName string
---@param logger table logger dependency injection ---@param logger Logger logger dependency injection
---@param database table database dependency injection ---@param database Database database dependency injection
---@param capConfig table config dependency injection ---@param capConfig table config dependency injection
---@return table? o ---@return CapGroup? self
function CapGroup:new(groupName, airbaseId, logger, database, capConfig) function CapGroup.new(groupName, airbaseName, logger, database, capConfig)
local o = {}
setmetatable(o, { __index = self })
local RESPAWN_AFTER_TOUCHDOWN_SECONDS = 180 CapGroup.__index = CapGroup
local self = setmetatable({}, CapGroup)
Spearhead.DcsUtil.DestroyGroup(groupName) Spearhead.DcsUtil.DestroyGroup(groupName)
-- initials -- initials
o.groupName = groupName self.groupName = groupName
o.airbaseId = airbaseId self.airbaseName = airbaseName
o.logger = logger
o.database = database local airbase = Airbase.getByName(airbaseName)
if airbase == nil then
logger:error("Airbase with name " .. airbaseName .. " does not exist")
return nil
end
self.airbaseId = airbase:getID()
self.logger = logger
self.database = database
local parsed = CapHelper.ParseGroupName(groupName) local parsed = CapHelper.ParseGroupName(groupName)
if parsed == nil then return nil end if parsed == nil then return nil end
o.capZonesConfig = parsed.zonesConfig self.capZonesConfig = parsed.zonesConfig
o.isBackup = parsed.isBackup self.isBackup = parsed.isBackup
--vars --vars
o.assignedStageNumber = nil self.assignedStageNumber = nil
o.state = CapGroup.GroupState.UNSPAWNED self.state = CapGroup.GroupState.UNSPAWNED
o.aliveUnits = {} self.aliveUnits = {}
o.landedUnits = {} self.landedUnits = {}
o.unitCount = 0 self.unitCount = 0
o.onStationSince = 0 self.onStationSince = 0
o.currentCapTaskingDuration = 0 self.currentCapTaskingDuration = 0
o.markedForDespawn = false self.markedForDespawn = false
self.onStatusUpdatedListener = {}
--config --config
o.capConfig = capConfig self.capConfig = capConfig
---comment Spearhead.Events.addOnGroupRTBListener(self.groupName, self)
---@param self table Spearhead.Events.addOnGroupRTBInTenListener(self.groupName, self)
---@param currentActive number Spearhead.Events.addOnGroupOnStationListener(self.groupName, self)
---@return table local units = Group.getByName(groupName):getUnits()
o.GetTargetZone = function (self, currentActive) for key, unit in pairs(units) do
return self.capZonesConfig[tostring(currentActive)] Spearhead.Events.addOnUnitLandEventListener(unit:getName(), self)
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self)
end end
o.SetState = function(self, state) return self
end
---@param currentActive number
---@return string
function CapGroup:GetTargetZone(currentActive)
return self.capZonesConfig[tostring(currentActive)]
end
function CapGroup:SetState(state)
self.state = state self.state = state
self:PublishUnitUpdatedEvent() self:PublishUnitUpdatedEvent()
end end
o.StartRearm = function(self) function CapGroup:StartRearm()
self:SpawnOnTheRamp() self:SpawnOnTheRamp()
self:SetState(CapGroup.GroupState.REARMING) self:SetState(CapGroup.GroupState.REARMING)
timer.scheduleFunction(SetReadyOnRampAsync, self, timer.getTime() + self.capConfig:getRearmDelay() - RESPAWN_AFTER_TOUCHDOWN_SECONDS) timer.scheduleFunction(SetReadyOnRampAsync, self, timer.getTime() + self.capConfig:getRearmDelay() - RESPAWN_AFTER_TOUCHDOWN_SECONDS)
end end
o.SpawnOnTheRamp = function(self) function CapGroup:SpawnOnTheRamp()
self.markedForDespawn = false self.markedForDespawn = false
self.logger:debug("Spawning group " .. self.groupName) self.logger:debug("Spawning group " .. self.groupName)
self.aliveUnits = {} self.aliveUnits = {}
@@ -183,15 +219,15 @@ function CapGroup:new(groupName, airbaseId, logger, database, capConfig)
self.landedUnits[name] = false self.landedUnits[name] = false
end end
end end
end end
o.Despawn = function(self) function CapGroup:Despawn()
self.logger:debug("Despawning group " .. self.groupName) self.logger:debug("Despawning group " .. self.groupName)
Spearhead.DcsUtil.DestroyGroup(self.groupName) Spearhead.DcsUtil.DestroyGroup(self.groupName)
self:SetState(CapGroup.GroupState.UNSPAWNED) self:SetState(CapGroup.GroupState.UNSPAWNED)
end end
o.SendRTB = function(self) function CapGroup:SendRTB()
local group = Group.getByName(self.groupName) local group = Group.getByName(self.groupName)
if group and group:isExist() then if group and group:isExist() then
local speed = math.random(self.capConfig:getMinSpeed(), self.capConfig:getMaxSpeed()) local speed = math.random(self.capConfig:getMinSpeed(), self.capConfig:getMaxSpeed())
@@ -205,17 +241,15 @@ function CapGroup:new(groupName, airbaseId, logger, database, capConfig)
end end
end end
end end
end end
o.SendRTBAndDespawn = function(self) function CapGroup:SendRTBAndDespawn()
self.markedForDespawn = true self.markedForDespawn = true
o.SendRTB(self) self:SendRTB()
end end
---Starts and send this group to perform CAP at a stage ---@param stageZoneNumber string
---@param self any function CapGroup:SendToStage(stageZoneNumber)
---@param stageZoneNumber string
o.SendToStage = function(self, stageZoneNumber)
if self.state == CapGroup.GroupState.DEAD or self.state == CapGroup.GroupState.RTB then if self.state == CapGroup.GroupState.DEAD or self.state == CapGroup.GroupState.RTB then
return --Can't task a unit that's dead or RTB return --Can't task a unit that's dead or RTB
end end
@@ -225,7 +259,7 @@ function CapGroup:new(groupName, airbaseId, logger, database, capConfig)
if group and group:isExist() then if group and group:isExist() then
self.logger:debug("Sending group out " .. self.groupName) self.logger:debug("Sending group out " .. self.groupName)
local controller = group:getController() local controller = group:getController()
local capPoints = database:getCapRouteInZone(stageZoneNumber, self.airbaseId) local capPoints = self.database:getCapRouteInZone(stageZoneNumber, self.airbaseName)
local altitude = math.random(self.capConfig:getMinAlt(), self.capConfig:getMaxAlt()) local altitude = math.random(self.capConfig:getMinAlt(), self.capConfig:getMaxAlt())
local speed = math.random(self.capConfig:getMinSpeed(), self.capConfig:getMaxSpeed()) local speed = math.random(self.capConfig:getMinSpeed(), self.capConfig:getMaxSpeed())
@@ -243,7 +277,7 @@ function CapGroup:new(groupName, airbaseId, logger, database, capConfig)
capTask = Spearhead.RouteUtil.createCapMission(self.groupName, self.airbaseId, capPoints.point1, capPoints.point2, altitude, speed, duration, attackHelos, deviationDistance) capTask = Spearhead.RouteUtil.createCapMission(self.groupName, self.airbaseId, capPoints.point1, capPoints.point2, altitude, speed, duration, attackHelos, deviationDistance)
else else
local duration = self.currentCapTaskingDuration - (timer.getTime() - o.onStationSince) local duration = self.currentCapTaskingDuration - (timer.getTime() - self.onStationSince)
capTask = Spearhead.RouteUtil.createCapMission(self.groupName, self.airbaseId, capPoints.point1, capPoints.point2, altitude, speed, duration, attackHelos, deviationDistance) capTask = Spearhead.RouteUtil.createCapMission(self.groupName, self.airbaseId, capPoints.point1, capPoints.point2, altitude, speed, duration, attackHelos, deviationDistance)
end end
@@ -253,16 +287,16 @@ function CapGroup:new(groupName, airbaseId, logger, database, capConfig)
end end
self:SetState(CapGroup.GroupState.INTRANSIT) self:SetState(CapGroup.GroupState.INTRANSIT)
end end
end end
---Starts and send a unit to another airbase ---@param airdomeId any
---@param self table function CapGroup:SendToAirbase(airdomeId)
---@param airdomeId any
o.SendToAirbase = function(self, airdomeId)
self.airbaseId = airdomeId self.airbaseId = airdomeId
local speed = math.random(self.capConfig:getMinSpeed(), self.capConfig:getMaxSpeed()) local speed = math.random(self.capConfig:getMinSpeed(), self.capConfig:getMaxSpeed())
local rtbTask = Spearhead.RouteUtil.CreateRTBMission(self.groupName, airdomeId, speed) local rtbTask = Spearhead.RouteUtil.CreateRTBMission(self.groupName, airdomeId, speed)
local group = Group.getByName(self.groupName) local group = Group.getByName(self.groupName)
if not group then return end
local controller = group:getController() local controller = group:getController()
controller:setCommand({ controller:setCommand({
id = 'Start', id = 'Start',
@@ -270,9 +304,9 @@ function CapGroup:new(groupName, airbaseId, logger, database, capConfig)
}) })
timer.scheduleFunction(setTaskAsync, { task = rtbTask, groupName = self.groupName, logger = self.logger }, timer.scheduleFunction(setTaskAsync, { task = rtbTask, groupName = self.groupName, logger = self.logger },
timer.getTime() + 5) timer.getTime() + 5)
end end
o.OnGroupRTB = function(self, groupName) function CapGroup:OnGroupRTB(groupName)
if groupName == self.groupName then if groupName == self.groupName then
self.logger:debug("Setting group " .. self.logger:debug("Setting group " ..
groupName .. groupName ..
@@ -280,26 +314,25 @@ function CapGroup:new(groupName, airbaseId, logger, database, capConfig)
timer.getTime() - self.onStationSince .. "s of the " .. self.currentCapTaskingDuration .. "s") timer.getTime() - self.onStationSince .. "s of the " .. self.currentCapTaskingDuration .. "s")
self:SetState(CapGroup.GroupState.RTB) self:SetState(CapGroup.GroupState.RTB)
end end
end end
o.OnGroupRTBInTen = function(self, groupName) function CapGroup:OnGroupRTBInTen(groupName)
if groupName == self.groupName then if groupName == self.groupName then
self:SetState(CapGroup.GroupState.RTBINTEN) self:SetState(CapGroup.GroupState.RTBINTEN)
end end
end end
o.OnGroupOnStation = function(self, groupName) function CapGroup:OnGroupOnStation(groupName)
if groupName == self.groupName then if groupName == self.groupName then
self.onStationSince = timer.getTime() self.onStationSince = timer.getTime()
self.logger:debug("Setting group " .. groupName .. " to state Onstation") self.logger:debug("Setting group " .. groupName .. " to state Onstation")
self:SetState(CapGroup.GroupState.ONSTATION) self:SetState(CapGroup.GroupState.ONSTATION)
end end
end end
---comment
---@param self table ---@param proActive boolean Will check all units in group for aliveness
---@param proActive boolean Will check all units in group for aliveness function CapGroup:UpdateState(proActive)
o.UpdateState = function(self, proActive)
local landed = false local landed = false
local landedCount = 0 local landedCount = 0
for name, landedBool in pairs(self.landedUnits) do for name, landedBool in pairs(self.landedUnits) do
@@ -337,66 +370,53 @@ function CapGroup:new(groupName, airbaseId, logger, database, capConfig)
end end
end end
end end
end end
o.eventListeners = {}
---comment ---@param listener table object with function OnGroupStateUpdated(capGroupTable)
---@param self table function CapGroup:AddOnStateUpdatedListener(listener)
---@param listener table object with function OnGroupStateUpdated(capGroupTable)
o.AddOnStateUpdatedListener = function(self, listener)
if type(listener) ~= "table" then if type(listener) ~= "table" then
self.logger:error("Listener not of type table for AddOnStateUpdatedListener") self.logger:error("Listener not of type table for AddOnStateUpdatedListener")
return return
end end
if listener.OnGroupStateUpdated == nil then if listener.onGroupStateUpdated == nil then
self.logger:error("Listener does not implement OnGroupStateUpdated") self.logger:error("Listener does not implement onGroupStateUpdated")
return return
end end
table.insert(self.eventListeners, listener) table.insert(self.onStatusUpdatedListener, listener)
end end
o.PublishUnitUpdatedEvent = function(self) function CapGroup:PublishUnitUpdatedEvent()
for _, callable in pairs(self.eventListeners) do for _, callable in pairs(self.onStatusUpdatedListener) do
local _, error = pcall(function() local _, error = pcall(function()
callable:OnGroupStateUpdated(self) callable:onGroupStateUpdated(self)
end) end)
if error then if error then
self.logger:error(error) self.logger:error(error)
end end
end end
end end
o.OnUnitLanded = function(self, initiatorUnit, airbase) function CapGroup:OnUnitLanded(initiatorUnit, airbase)
if airbase then if airbase then
local airdomeId = airbase:getID() self.airbaseName = airbase:getName()
self.airbaseId = airdomeId
end end
local name = initiatorUnit:getName() local name = initiatorUnit:getName()
self.logger:debug("Received unit land event for unit " .. name .. " of group " .. self.groupName) self.logger:debug("Received unit land event for unit " .. name .. " of group " .. self.groupName)
self.landedUnits[name] = true self.landedUnits[name] = true
self:UpdateState(false) self:UpdateState(false)
end end
o.OnUnitLost = function(self, initiatorUnit) function CapGroup:OnUnitLost(initiatorUnit)
self.logger:debug("Received unit lost event for group " .. self.groupName) self.logger:debug("Received unit lost event for group " .. self.groupName)
if initiatorUnit then if initiatorUnit then
self.aliveUnits[initiatorUnit:getName()] = false self.aliveUnits[initiatorUnit:getName()] = false
end end
self:UpdateState(false) self:UpdateState(false)
end
Spearhead.Events.addOnGroupRTBListener(o.groupName, o)
Spearhead.Events.addOnGroupRTBInTenListener(o.groupName, o)
Spearhead.Events.addOnGroupOnStationListener(o.groupName, o)
local units = Group.getByName(groupName):getUnits()
for key, unit in pairs(units) do
Spearhead.Events.addOnUnitLandEventListener(unit:getName(), o)
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), o)
end
return o
end end
if not Spearhead.internal then Spearhead.internal = {} end if not Spearhead.internal then Spearhead.internal = {} end
Spearhead.internal.CapGroup = CapGroup Spearhead.internal.CapGroup = CapGroup
+10 -7
View File
@@ -7,10 +7,14 @@ do
local initiated = false local initiated = false
---comment
---@param database Database
---@param capConfig any
---@param stageConfig any
function GlobalCapManager.start(database, capConfig, stageConfig) function GlobalCapManager.start(database, capConfig, stageConfig)
if initiated == true then return end if initiated == true then return end
local logger = Spearhead.LoggerTemplate:new("AirbaseManager", capConfig.logLevel) local logger = Spearhead.LoggerTemplate.new("AirbaseManager", capConfig.logLevel)
local zones = database:getStagezoneNames() local zones = database:getStagezoneNames()
if zones then if zones then
@@ -19,13 +23,12 @@ do
airbasesPerStage[stageName] = {} airbasesPerStage[stageName] = {}
end end
local airbaseIds = database:getAirbaseIdsInStage(stageName) local airbaseNames = database:getAirbaseNamesInStage(stageName)
if airbaseIds then if airbaseNames then
for _, id in pairs(airbaseIds) do for _, airbaseName in pairs(airbaseNames) do
local airbaseName = Spearhead.DcsUtil.getAirbaseName(id)
if airbaseName then if airbaseName then
local airbaseSpecificLogger = Spearhead.LoggerTemplate:new("CAP_" .. airbaseName, capConfig.logLevel) local airbaseSpecificLogger = Spearhead.LoggerTemplate.new("CAP_" .. airbaseName, capConfig.logLevel)
local airbase = Spearhead.internal.CapAirbase:new(id, database, airbaseSpecificLogger, capConfig, stageConfig) local airbase = Spearhead.internal.CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig)
if airbase then if airbase then
table.insert(airbasesPerStage[stageName], airbase) table.insert(airbasesPerStage[stageName], airbase)
allAirbasesByName[airbaseName] = airbase allAirbasesByName[airbaseName] = airbase
+1 -1
View File
@@ -6,7 +6,7 @@ local fleetGroups = {}
GlobalFleetManager.start = function(database) GlobalFleetManager.start = function(database)
local logger = Spearhead.LoggerTemplate:new("CARRIERFLEET", "INFO") local logger = Spearhead.LoggerTemplate.new("CARRIERFLEET", "INFO")
local all_groups = Spearhead.DcsUtil.getAllGroupNames() local all_groups = Spearhead.DcsUtil.getAllGroupNames()
for _, groupName in pairs(all_groups) do for _, groupName in pairs(all_groups) do
+23 -34
View File
@@ -800,14 +800,15 @@ do -- INIT DCS_UTIL
end end
---Get the starting coalition of a farp or airbase ---Get the starting coalition of a farp or airbase
---@param airbase Airbase
---@return number? coalition ---@return number? coalition
function DCS_UTIL.getStartingCoalition(baseId) function DCS_UTIL.getStartingCoalition(airbase)
if baseId == nil then if airbase == nil then
return nil return nil
end end
--STRING based dictionary otherwise it'll be a string/collapsed array --STRING based dictionary otherwise it'll be a string/collapsed array
baseId = tostring(baseId) or "nil" local baseId = tostring(airbase:getID())
local result = DCS_UTIL.__airportsStartingCoalition[baseId] local result = DCS_UTIL.__airportsStartingCoalition[baseId]
if result == nil then if result == nil then
@@ -920,32 +921,28 @@ do -- INIT DCS_UTIL
end end
Spearhead.DcsUtil = DCS_UTIL Spearhead.DcsUtil = DCS_UTIL
--- @class Logger
--- @field LoggerName string the name of the logger
--- @field LogLevel string the log level of the logger
local LOGGER = {} local LOGGER = {}
do do
local PreFix = "Spearhead" local PreFix = "Spearhead"
--- @class Logger
--- @field debug fun(self:Logger, text:string)
--- @field info fun(self:Logger, text:string)
--- @field warn fun(self:Logger, text:string)
--- @field error fun(self:Logger, text:string)
---comment ---comment
---@param logger_name any ---@param logger_name any
---@param logLevel LogLevel ---@param logLevel LogLevel
---@return Logger ---@return Logger
function LOGGER:new(logger_name, logLevel) function LOGGER.new(logger_name, logLevel)
local o = {} LOGGER.__index = LOGGER
setmetatable(o, { __index = self }) local self = setmetatable({}, LOGGER)
o.LoggerName = logger_name or "(loggername not set)" self.LoggerName = logger_name or "(loggername not set)"
o.LogLevel = logLevel or "INFO" self.LogLevel = logLevel or "INFO"
return self
end
---comment
---@param self table self logger
---@param message any the message ---@param message any the message
o.info = function(self, message) function LOGGER:info(message)
if message == nil then if message == nil then
return return
end end
@@ -958,36 +955,32 @@ do
---comment ---comment
---@param message string ---@param message string
o.warn = function(self, message) function LOGGER:warn(message)
if message == nil then if message == nil then
return return
end end
message = UTIL.toString(message) message = UTIL.toString(message)
if self.LogLevel == "INFO" or self.LogLevel == "DEBUG" or self.LogLevel == "WARN" then if self.LogLevel == "INFO" or self.LogLevel == "DEBUG" or self.LogLevel == "WARN" then
env.info("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "] " .. message) env.warning("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "] " .. message)
end end
end end
---comment
---@param self table -- logger
---@param message any -- the message ---@param message any -- the message
o.error = function(self, message) function LOGGER:error(message)
if message == nil then if message == nil then
return return
end end
message = UTIL.toString(message) message = UTIL.toString(message)
if self.LogLevel == "INFO" or self.LogLevel == "DEBUG" or self.LogLevel == "WARN" or self.logLevel == "ERROR" then if self.LogLevel == "INFO" or self.LogLevel == "DEBUG" or self.LogLevel == "WARN" or self.LogLevel == "ERROR" then
env.info("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "] " .. message) env.error("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "] " .. message)
end end
end end
---write debug
---@param self table
---@param message any the message ---@param message any the message
o.debug = function(self, message) function LOGGER:debug(message)
if message == nil then if message == nil then
return return
end end
@@ -997,10 +990,6 @@ do
env.info("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "][DEBUG] " .. message) env.info("[" .. PreFix .. "]" .. "[" .. self.LoggerName .. "][DEBUG] " .. message)
end end
end end
return o
end
end end
Spearhead.LoggerTemplate = LOGGER Spearhead.LoggerTemplate = LOGGER
@@ -1015,7 +1004,7 @@ Spearhead.LoadingDone = function()
return return
end end
local warningLogger = Spearhead.LoggerTemplate:new("MISSIONPARSER", "INFO") local warningLogger = Spearhead.LoggerTemplate.new("MISSIONPARSER", "INFO")
if Spearhead.Util.tableLength(Spearhead.MissionEditingWarnings) > 0 then if Spearhead.Util.tableLength(Spearhead.MissionEditingWarnings) > 0 then
for key, message in pairs(Spearhead.MissionEditingWarnings) do for key, message in pairs(Spearhead.MissionEditingWarnings) do
warningLogger:warn(message) warningLogger:warn(message)
+209 -202
View File
@@ -17,6 +17,7 @@
---@field BlueSamDataPerZone table<string, BlueSamData> ---@field BlueSamDataPerZone table<string, BlueSamData>
---@field MissionZoneData table<string, MissionZoneData> ---@field MissionZoneData table<string, MissionZoneData>
---@field FarpZoneData table<string,FarpZoneData> ---@field FarpZoneData table<string,FarpZoneData>
---@field missionCodes table<string, boolean>
---@class CapData ---@class CapData
---@field routes Array<CapRoute> ---@field routes Array<CapRoute>
@@ -59,9 +60,9 @@
local Database = {} local Database = {}
---comment ---comment
---@param Logger table ---@param Logger Logger
---@return Database ---@return Database
function Database.New(Logger, debug) function Database.New(Logger)
---@type DatabaseTables ---@type DatabaseTables
local tables = { local tables = {
@@ -81,7 +82,8 @@ function Database.New(Logger, debug)
AirbaseDataPerAirfield = {}, AirbaseDataPerAirfield = {},
BlueSamDataPerZone = {}, BlueSamDataPerZone = {},
MissionZoneData = {}, MissionZoneData = {},
FarpZoneData = {} FarpZoneData = {},
missionCodes = {}
} }
Database.__index = Database Database.__index = Database
@@ -90,7 +92,7 @@ function Database.New(Logger, debug)
self._logger = Logger self._logger = Logger
self._tables = tables self._tables = tables
Logger:debug("Initiating tables") self._logger:debug("Initiating tables")
do -- INIT ZONE TABLES do -- INIT ZONE TABLES
for zone_ind, zone_data in pairs(Spearhead.DcsUtil.__trigger_zones) do for zone_ind, zone_data in pairs(Spearhead.DcsUtil.__trigger_zones) do
@@ -118,7 +120,7 @@ function Database.New(Logger, debug)
RandomMissionZones = {}, RandomMissionZones = {},
MiscGroups = {} MiscGroups = {}
} }
self._tables.StageZones[zone_name] = zone_data self._tables.StageZones[zone_name] = stageData
end end
end end
@@ -152,7 +154,7 @@ function Database.New(Logger, debug)
end end
end end
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 i, layer in pairs(env.mission.drawings.layers) do
@@ -237,13 +239,6 @@ function Database.New(Logger, debug)
end end
end end
Logger:info("initiated the database with amount of zones: ")
Logger:info("Stages: " .. Spearhead.Util.tableLength(self._tables.StageZones))
Logger:info("Total Missions: " .. Spearhead.Util.tableLength(self._tables.MissionZoneData))
Logger:info("Random Missions: " .. Spearhead.Util.tableLength(self._tables.RandomMissionZones))
Logger:info("Farps: " .. Spearhead.Util.tableLength(self._tables.AllFarpZones))
Logger:info("Airbases: " .. Spearhead.Util.tableLength(self._tables.AirbaseDataPerAirfield))
for _, missionZone in pairs(self._tables.MissionZones) do for _, missionZone in pairs(self._tables.MissionZones) do
if self._tables.DescriptionsByMission[missionZone] == nil then if self._tables.DescriptionsByMission[missionZone] == nil then
Spearhead.AddMissionEditorWarning("Mission with zonename: " .. Spearhead.AddMissionEditorWarning("Mission with zonename: " ..
@@ -261,33 +256,6 @@ function Database.New(Logger, debug)
end end
end end
local is_group_taken = {}
do
local all_groups = Spearhead.DcsUtil.getAllGroupNames()
for _, value in pairs(all_groups) do
is_group_taken[value] = false
end
end
local getAvailableGroups = function()
local result = {}
for name, value in pairs(is_group_taken) do
if value == false then
table.insert(result, name)
end
end
return result
end
local getAvailableCAPGroups = function()
local result = {}
for name, value in pairs(is_group_taken) do
if value == false and Spearhead.Util.startswith(name, "CAP") then
table.insert(result, name)
end
end
return result
end
---@private ---@private
---@param baseName string ---@param baseName string
@@ -305,159 +273,7 @@ function Database.New(Logger, debug)
return baseData return baseData
end end
---@private
function Database:loadCapUnits()
local all_groups = getAvailableCAPGroups()
local airbases = world.getAirbases()
for _, airbase in pairs(airbases) do
local baseId = airbase:getID()
local point = airbase:getPoint()
local zone = Spearhead.DcsUtil.getAirbaseZoneById(baseId) or { x = point.x, z = point.z, radius = 4000 }
local baseData = self:getOrCreateAirbaseData(airbase:getName())
local groups = Spearhead.DcsUtil.areGroupsInCustomZone(all_groups, zone)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(baseData.CapGroups, groupName)
end
self._tables.AirbaseDataPerAirfield[airbase:getName()] = baseData
end
end
---@private
function Database:loadBlueSamUnits()
local all_groups = Spearhead.DcsUtil.getAllGroupNames()
for _, blueSamZone in pairs(self._tables.BlueSams) do
self._tables.BlueSamDataPerZone[blueSamZone] = {
Groups = {}
}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, blueSamZone)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(self._tables.BlueSamDataPerZone[blueSamZone].Groups, groupName)
end
end
end
---@private
function Database:loadMissionzoneUnits()
local all_groups = getAvailableGroups()
for _, missionZoneName in pairs(self._tables.MissionZones) do
self._tables.MissionZoneData[missionZoneName] = {
Groups = {}
}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(self._tables.MissionZoneData[missionZoneName].Groups, groupName)
end
end
end
---@private
function Database:loadRandomMissionzoneUnits()
local all_groups = getAvailableGroups()
for _, missionZoneName in pairs(self._tables.RandomMissionZones) do
self._tables.MissionZoneData[missionZoneName] = {
Groups = {}
}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(self._tables.MissionZoneData[missionZoneName].Groups, groupName)
end
end
end
---@private
function Database:loadFarpGroups()
local all_groups = getAvailableGroups()
for _, farpZone in pairs(self._tables.AllFarpZones) do
self._tables.FarpZoneData[farpZone] = {
Groups = {}
}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, farpZone)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(self._tables.FarpZoneData[farpZone].Groups, groupName)
end
end
end
function Database:loadAirbaseGroups()
local all_groups = getAvailableGroups()
for _, stageZone in pairs(self._tables.StageZones) do
for _, baseName in pairs(stageZone.AirbaseNames) do
local base = Airbase.getByName(baseName)
if base then
local basedata = self:getOrCreateAirbaseData(baseName)
local baseId = base:getID()
local point = base:getPoint()
local airbaseZone = Spearhead.DcsUtil.getAirbaseZoneById(baseId) or { x = point.x, z = point.z, radius = 4000 }
if airbaseZone and base:getDesc().category == Airbase.Category.AIRDROME then
local groups = Spearhead.DcsUtil.areGroupsInCustomZone(all_groups, airbaseZone)
for _, groupName in pairs(groups) do
if Spearhead.DcsUtil.IsGroupStatic(groupName) == true then
local object = StaticObject.getByName(groupName)
if object then
if object:getCoalition() == coalition.side.RED then
table.insert(basedata.RedGroups, groupName)
is_group_taken[groupName] = true
elseif object:getCoalition() == coalition.side.BLUE then
table.insert(basedata.BlueGroups, groupName)
is_group_taken[groupName] = true
end
end
else
local group = Group.getByName(groupName)
if group then
if group:getCoalition() == coalition.side.RED then
table.insert(basedata.RedGroups, groupName)
is_group_taken[groupName] = true
elseif group:getCoalition() == coalition.side.BLUE then
table.insert(basedata.BlueGroups, groupName)
is_group_taken[groupName] = true
end
end
end
end
end
end
end
end
end
---@private
function Database:loadMiscGroupsInStages()
local all_groups = getAvailableGroups()
for _, stageZone in pairs(self._tables.StageZones) do
stageZone.MiscGroups = {}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, stageZone.StageZoneName)
for _, groupName in pairs(groups) do
if Spearhead.DcsUtil.IsGroupStatic(groupName) == true then
local object = StaticObject.getByName(groupName)
if object and object:getCoalition() ~= coalition.side.NEUTRAL then
is_group_taken[groupName] = true
table.insert(stageZone.MiscGroups, groupName)
end
else
local group = Group.getByName(groupName)
if group and group:getCoalition() ~= coalition.side.NEUTRAL then
is_group_taken[groupName] = true
table.insert(stageZone.MiscGroups, groupName)
end
end
end
end
end
self:loadCapUnits() self:loadCapUnits()
self:loadBlueSamUnits() self:loadBlueSamUnits()
@@ -526,10 +342,200 @@ function Database.New(Logger, debug)
end end
end end
self._logger:info("initiated the database with amount of zones: ")
self._logger:info("Stages: " .. Spearhead.Util.tableLength(self._tables.StageZones))
self._logger:info("Total Missions: " .. Spearhead.Util.tableLength(self._tables.MissionZoneData))
self._logger:info("Random Missions: " .. Spearhead.Util.tableLength(self._tables.RandomMissionZones))
self._logger:info("Farps: " .. Spearhead.Util.tableLength(self._tables.AllFarpZones))
self._logger:info("Airbases: " .. Spearhead.Util.tableLength(self._tables.AirbaseDataPerAirfield))
return self return self
end end
local is_group_taken = {}
do
local all_groups = Spearhead.DcsUtil.getAllGroupNames()
for _, value in pairs(all_groups) do
is_group_taken[value] = false
end
end
local getAvailableGroups = function()
local result = {}
for name, value in pairs(is_group_taken) do
if value == false then
table.insert(result, name)
end
end
return result
end
local getAvailableCAPGroups = function()
local result = {}
for name, value in pairs(is_group_taken) do
if value == false and Spearhead.Util.startswith(name, "CAP") then
table.insert(result, name)
end
end
return result
end
---@private
function Database:loadCapUnits()
local all_groups = getAvailableCAPGroups()
local airbases = world.getAirbases()
for _, airbase in pairs(airbases) do
local baseId = airbase:getID()
local point = airbase:getPoint()
local zone = Spearhead.DcsUtil.getAirbaseZoneById(baseId) or { x = point.x, z = point.z, radius = 4000 }
local baseData = self:getOrCreateAirbaseData(airbase:getName())
local groups = Spearhead.DcsUtil.areGroupsInCustomZone(all_groups, zone)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(baseData.CapGroups, groupName)
end
self._tables.AirbaseDataPerAirfield[airbase:getName()] = baseData
end
end
---@private
function Database:loadBlueSamUnits()
local all_groups = Spearhead.DcsUtil.getAllGroupNames()
for _, blueSamZone in pairs(self._tables.BlueSams) do
self._tables.BlueSamDataPerZone[blueSamZone] = {
Groups = {}
}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, blueSamZone)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(self._tables.BlueSamDataPerZone[blueSamZone].Groups, groupName)
end
end
end
---@private
function Database:loadMissionzoneUnits()
local all_groups = getAvailableGroups()
for _, missionZoneName in pairs(self._tables.MissionZones) do
self._tables.MissionZoneData[missionZoneName] = {
Groups = {}
}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(self._tables.MissionZoneData[missionZoneName].Groups, groupName)
end
end
end
---@private
function Database:loadRandomMissionzoneUnits()
local all_groups = getAvailableGroups()
for _, missionZoneName in pairs(self._tables.RandomMissionZones) do
self._tables.MissionZoneData[missionZoneName] = {
Groups = {}
}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(self._tables.MissionZoneData[missionZoneName].Groups, groupName)
end
end
end
---@private
function Database:loadFarpGroups()
local all_groups = getAvailableGroups()
for _, farpZone in pairs(self._tables.AllFarpZones) do
self._tables.FarpZoneData[farpZone] = {
Groups = {}
}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, farpZone)
for _, groupName in pairs(groups) do
is_group_taken[groupName] = true
table.insert(self._tables.FarpZoneData[farpZone].Groups, groupName)
end
end
end
function Database:loadAirbaseGroups()
local all_groups = getAvailableGroups()
for _, stageZone in pairs(self._tables.StageZones) do
for _, baseName in pairs(stageZone.AirbaseNames) do
local base = Airbase.getByName(baseName)
if base then
local basedata = self:getOrCreateAirbaseData(baseName)
local baseId = base:getID()
local point = base:getPoint()
local airbaseZone = Spearhead.DcsUtil.getAirbaseZoneById(baseId) or { x = point.x, z = point.z, radius = 4000 }
if airbaseZone and base:getDesc().category == Airbase.Category.AIRDROME then
local groups = Spearhead.DcsUtil.areGroupsInCustomZone(all_groups, airbaseZone)
for _, groupName in pairs(groups) do
if Spearhead.DcsUtil.IsGroupStatic(groupName) == true then
local object = StaticObject.getByName(groupName)
if object then
if object:getCoalition() == coalition.side.RED then
table.insert(basedata.RedGroups, groupName)
is_group_taken[groupName] = true
elseif object:getCoalition() == coalition.side.BLUE then
table.insert(basedata.BlueGroups, groupName)
is_group_taken[groupName] = true
end
end
else
local group = Group.getByName(groupName)
if group then
if group:getCoalition() == coalition.side.RED then
table.insert(basedata.RedGroups, groupName)
is_group_taken[groupName] = true
elseif group:getCoalition() == coalition.side.BLUE then
table.insert(basedata.BlueGroups, groupName)
is_group_taken[groupName] = true
end
end
end
end
end
end
end
end
end
---@private
function Database:loadMiscGroupsInStages()
local all_groups = getAvailableGroups()
for _, stageZone in pairs(self._tables.StageZones) do
stageZone.MiscGroups = {}
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, stageZone.StageZoneName)
for _, groupName in pairs(groups) do
if Spearhead.DcsUtil.IsGroupStatic(groupName) == true then
local object = StaticObject.getByName(groupName)
if object and object:getCoalition() ~= coalition.side.NEUTRAL then
is_group_taken[groupName] = true
table.insert(stageZone.MiscGroups, groupName)
end
else
local group = Group.getByName(groupName)
if group and group:getCoalition() ~= coalition.side.NEUTRAL then
is_group_taken[groupName] = true
table.insert(stageZone.MiscGroups, groupName)
end
end
end
end
end
function Database:GetDescriptionForMission(missionZoneName) function Database:GetDescriptionForMission(missionZoneName)
return self._tables.DescriptionsByMission[missionZoneName] return self._tables.DescriptionsByMission[missionZoneName]
@@ -595,7 +601,7 @@ end
---@return table result a list of stage zone names ---@return table result a list of stage zone names
function Database:getStagezoneNames() function Database:getStagezoneNames()
return self._tables.AllZoneNames return self._tables.StageZoneNames
end end
function Database:getCarrierRouteZones() function Database:getCarrierRouteZones()
@@ -628,19 +634,22 @@ function Database:getMissionBriefingForMissionZone(missionZoneName)
return self._tables.DescriptionsByMission[missionZoneName] return self._tables.DescriptionsByMission[missionZoneName]
end end
---@param self table
---@param stageName string ---@param stageName string
---@return table result airbase Names ---@return table result airbase Names
function Database:getAirbaseIdsInStage(stageName) function Database:getAirbaseNamesInStage(stageName)
return self.tables.airbasesPerStage[stageName] or {}
local stageData = self._tables.StageZones[stageName]
if not stageData then return {} end
return stageData.AirbaseNames or {}
end end
---@param airbaseName string ---@param airbaseName string
---@return Array<string>? ---@return Array<string>
function Database:getCapGroupsAtAirbase(airbaseName) function Database:getCapGroupsAtAirbase(airbaseName)
local airbaseData = self._tables.AirbaseDataPerAirfield[airbaseName] local airbaseData = self._tables.AirbaseDataPerAirfield[airbaseName]
if not airbaseData then return nil end if not airbaseData then return {} end
return airbaseData.CapGroups return airbaseData.CapGroups
end end
@@ -682,15 +691,13 @@ function Database:getMiscGroupsAtStage(stageName)
return stageZone.MiscGroups return stageZone.MiscGroups
end end
---comment
---@param self table
---@return integer|nil ---@return integer|nil
function Database:GetNewMissionCode(self) function Database:GetNewMissionCode()
local code = nil local code = nil
local tries = 0 local tries = 0
while code == nil and tries < 10 do while code == nil and tries < 10 do
local random = math.random(1000, 9999) local random = math.random(1000, 9999)
if self.tables.missionCodes[random] == nil then if self._tables.missionCodes[random] == nil then
code = random code = random
end end
tries = tries + 1 tries = tries + 1
+2 -2
View File
@@ -7,7 +7,7 @@ do
---@param logLevel LogLevel ---@param logLevel LogLevel
SpearheadEvents.Init = function(logLevel) SpearheadEvents.Init = function(logLevel)
logger = Spearhead.LoggerTemplate:new("Events", logLevel) logger = Spearhead.LoggerTemplate.new("Events", logLevel)
end end
@@ -68,7 +68,7 @@ do
logError(err) logError(err)
end end
end end
Spearhead.LoggerTemplate.new("Events", "INFO"):info("Published stage number changed to: " .. tostring(newStageNumber))
Spearhead.StageNumber = newStageNumber Spearhead.StageNumber = newStageNumber
end end
end end
+4
View File
@@ -303,6 +303,10 @@ do --setup route util
local group = Group.getByName(groupName) local group = Group.getByName(groupName)
local pos; local pos;
local i = 1 local i = 1
if group == nil then
return nil, "No group found for name " .. groupName
end
local units = group:getUnits() local units = group:getUnits()
while pos == nil and i <= Spearhead.Util.tableLength(units) do while pos == nil and i <= Spearhead.Util.tableLength(units) do
local unit = units[i] local unit = units[i]
+6 -5
View File
@@ -21,7 +21,7 @@ GlobalStageManager = {}
---@param stageConfig StageConfig ---@param stageConfig StageConfig
---@return nil ---@return nil
function GlobalStageManager:NewAndStart(database, stageConfig) function GlobalStageManager:NewAndStart(database, stageConfig)
local logger = Spearhead.LoggerTemplate:new("StageManager", stageConfig.logLevel) local logger = Spearhead.LoggerTemplate.new("StageManager", stageConfig.logLevel)
logger:info("Using Stage Log Level: " .. stageConfig.logLevel) logger:info("Using Stage Log Level: " .. stageConfig.logLevel)
local o = {} local o = {}
setmetatable(o, { __index = self }) setmetatable(o, { __index = self })
@@ -86,7 +86,9 @@ function GlobalStageManager:NewAndStart(database, stageConfig)
end end
} }
for _, stageName in pairs(database:getStagezoneNames()) do for _, stageName in pairs(database:getStagezoneNames()) do
logger:debug("Found stage zone with name: " .. stageName)
if Spearhead.Util.startswith(stageName, "missionstage", true) then if Spearhead.Util.startswith(stageName, "missionstage", true) then
local valid = true local valid = true
@@ -98,7 +100,6 @@ function GlobalStageManager:NewAndStart(database, stageConfig)
if Spearhead.Util.tableLength(split) < 3 then if Spearhead.Util.tableLength(split) < 3 then
Spearhead.AddMissionEditorWarning("Stage zone with name " .. stageName .. " does not have a stage name") Spearhead.AddMissionEditorWarning("Stage zone with name " .. stageName .. " does not have a stage name")
valid = false
end end
local orderNumber = nil local orderNumber = nil
@@ -108,7 +109,7 @@ function GlobalStageManager:NewAndStart(database, stageConfig)
if Spearhead.Util.startswith(orderNumberString, "x") == true then if Spearhead.Util.startswith(orderNumberString, "x") == true then
isSideStage = true isSideStage = true
local orderNumberString = string.gsub(orderNumberString, "x", "") orderNumberString = string.gsub(orderNumberString, "x", "")
orderNumber = tonumber(orderNumberString) orderNumber = tonumber(orderNumberString)
else else
orderNumber = tonumber(split[2]) orderNumber = tonumber(split[2])
@@ -121,7 +122,7 @@ function GlobalStageManager:NewAndStart(database, stageConfig)
end end
local stageDisplayName = split[3] local stageDisplayName = split[3]
local stagelogger = Spearhead.LoggerTemplate:new(stageName, stageConfig.logLevel) local stagelogger = Spearhead.LoggerTemplate.new(stageName, stageConfig.logLevel)
if valid == true and orderNumber then if valid == true and orderNumber then
---@type StageInitData ---@type StageInitData
@@ -174,7 +175,7 @@ function GlobalStageManager:NewAndStart(database, stageConfig)
end end
if valid == true then if valid == true then
local stagelogger = Spearhead.LoggerTemplate:new(stageName, stageConfig.logLevel) local stagelogger = Spearhead.LoggerTemplate.new(stageName, stageConfig.logLevel)
---@type WaitingStageInitData ---@type WaitingStageInitData
local initData = { local initData = {
+17 -3
View File
@@ -17,6 +17,7 @@ function SpearheadGroup.New(groupName)
self.isStatic = Spearhead.DcsUtil.IsGroupStatic(groupName) == true self.isStatic = Spearhead.DcsUtil.IsGroupStatic(groupName) == true
self.groupName = groupName self.groupName = groupName
self.isSpawned = false self.isSpawned = false
return self return self
end end
@@ -44,9 +45,9 @@ function SpearheadGroup:Spawn()
if self.isSpawned == true then return end if self.isSpawned == true then return end
local group = Spearhead.DcsUtil.SpawnGroupTemplate(self.groupName) local spawned, isStatic = Spearhead.DcsUtil.SpawnGroupTemplate(self.groupName)
if group then if spawned and isStatic == false then
for _, unit in pairs(group:getUnits()) do for _, unit in pairs(spawned:getUnits()) do
local deathState = Spearhead.classes.persistence.Persistence.UnitDeadState(unit:getName()) local deathState = Spearhead.classes.persistence.Persistence.UnitDeadState(unit:getName())
if deathState and deathState.isDead == true then if deathState and deathState.isDead == true then
@@ -58,6 +59,12 @@ function SpearheadGroup:Spawn()
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self) Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self)
end end
elseif spawned and isStatic == true then
if spawned then
Spearhead.Events.addOnUnitLostEventListener(spawned:getName(), self)
end
else
Spearhead.LoggerTemplate.new("SPEARHEADGROUP", "ERROR"):error("Failed to spawn group: " .. self.groupName)
end end
self.isSpawned = true self.isSpawned = true
@@ -73,9 +80,15 @@ end
function SpearheadGroup:GetCoalition() function SpearheadGroup:GetCoalition()
if self.isStatic == true then if self.isStatic == true then
local object = StaticObject.getByName(self.groupName) local object = StaticObject.getByName(self.groupName)
if object == nil then
return 0
end
return object:getCoalition() return object:getCoalition()
else else
local group = Group.getByName(self.groupName) local group = Group.getByName(self.groupName)
if group == nil then
return 0
end
return group:getCoalition() return group:getCoalition()
end end
end end
@@ -102,6 +115,7 @@ function SpearheadGroup:GetUnits()
end end
else else
local group = Group.getByName(self.groupName) local group = Group.getByName(self.groupName)
if not group then return {} end
for _, unit in pairs(group:getUnits()) do for _, unit in pairs(group:getUnits()) do
table.insert(result, unit) table.insert(result, unit)
end end
+10 -10
View File
@@ -6,16 +6,16 @@
---@field private _red_groups Array<SpearheadGroup> ---@field private _red_groups Array<SpearheadGroup>
---@field private _blue_groups Array<SpearheadGroup> ---@field private _blue_groups Array<SpearheadGroup>
---@field private _cleanup_units table<string, boolean> ---@field private _cleanup_units table<string, boolean>
---@field private _airbase table? ---@field private _airbase Airbase?
---@field private _initialSide number? ---@field private _initialSide number?
local StageBase = {} local StageBase = {}
---comment ---comment
---@param databaseManager table ---@param databaseManager Database
---@param logger table ---@param logger table
---@param airbaseId integer ---@param airbaseName string
---@return StageBase ---@return StageBase
function StageBase.New(databaseManager, logger, airbaseId) function StageBase.New(databaseManager, logger, airbaseName)
StageBase.__index = StageBase StageBase.__index = StageBase
local self = setmetatable({}, StageBase) local self = setmetatable({}, StageBase)
@@ -27,21 +27,21 @@ function StageBase.New(databaseManager, logger, airbaseId)
self._blue_groups = {} self._blue_groups = {}
self._cleanup_units = {} self._cleanup_units = {}
self._airbase = Spearhead.DcsUtil.getAirbaseById(airbaseId) self._airbase = Airbase.getByName(airbaseName)
self._initialSide = Spearhead.DcsUtil.getStartingCoalition(airbaseId) self._initialSide = Spearhead.DcsUtil.getStartingCoalition(self._airbase)
do --init do --init
local redUnitsPos = {} local redUnitsPos = {}
local blueUnitsPos = {} local blueUnitsPos = {}
do -- fill tables do -- fill tables
local redGroups = databaseManager:getRedGroupsAtAirbase(airbaseId) local redGroups = databaseManager:getRedGroupsAtAirbase(airbaseName)
if redGroups then if redGroups then
for _, groupName in pairs(redGroups) do for _, groupName in pairs(redGroups) do
local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName) local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName)
table.insert(self._red_groups, shGroup) table.insert(self._red_groups, shGroup)
for _, unit in shGroup:GetUnits() do for _, unit in pairs(shGroup:GetUnits()) do
redUnitsPos[unit:getName()] = unit:getPoint() redUnitsPos[unit:getName()] = unit:getPoint()
end end
@@ -49,13 +49,13 @@ function StageBase.New(databaseManager, logger, airbaseId)
end end
end end
local blueGroups = databaseManager:getBlueGroupsAtAirbase(airbaseId) local blueGroups = databaseManager:getBlueGroupsAtAirbase(airbaseName)
if blueGroups then if blueGroups then
for _, groupName in pairs(blueGroups) do for _, groupName in pairs(blueGroups) do
local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName) local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName)
table.insert(self._blue_groups, shGroup) table.insert(self._blue_groups, shGroup)
for _, unit in shGroup:GetUnits() do for _, unit in pairs(shGroup:GetUnits()) do
blueUnitsPos[unit:getName()] = unit:getPoint() blueUnitsPos[unit:getName()] = unit:getPoint()
end end
@@ -43,23 +43,16 @@
--- @field protected OnPostBlueActivated fun(self:Stage)? --- @field protected OnPostBlueActivated fun(self:Stage)?
local Stage = {} local Stage = {}
Stage.__index = Stage
local stageDrawingId = 100 local stageDrawingId = 100
---comment function Stage:superNew(database, stageConfig, logger, initData, missionPriority)
---@param database Database
---@param stageConfig StageConfig logger:debug("[BaseStage] Initiating stage with name: " .. initData.stageZoneName)
---@param logger any
---@param initData StageInitData
---@param missionPriority MissionPriority
---@return Stage
function Stage.New(database, stageConfig, logger, initData, missionPriority)
local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup
Stage.__index = Stage
local o = {}
local self = setmetatable(o, Stage)
self.zoneName = initData.stageZoneName self.zoneName = initData.stageZoneName
self.stageNumber = initData.stageNumber self.stageNumber = initData.stageNumber
self._isActive = false self._isActive = false
@@ -148,10 +141,10 @@ function Stage.New(database, stageConfig, logger, initData, missionPriority)
mission:AddMissionCompleteListener(self) mission:AddMissionCompleteListener(self)
end end
local airbaseIds = database:getAirbaseIdsInStage(self.zoneName) local airbaseNames = database:getAirbaseNamesInStage(self.zoneName)
if airbaseIds ~= nil and type(airbaseIds) == "table" then if airbaseNames ~= nil and type(airbaseNames) == "table" then
for _, airbaseId in pairs(airbaseIds) do for _, airbaseName in pairs(airbaseNames) do
local airbase = Spearhead.classes.stageClasses.SpecialZones.StageBase.New(database, logger, airbaseId) local airbase = Spearhead.classes.stageClasses.SpecialZones.StageBase.New(database, logger, airbaseName)
table.insert(self._db.airbases, airbase) table.insert(self._db.airbases, airbase)
end end
end end
+7 -8
View File
@@ -2,6 +2,10 @@
---@class ExtraStage : Stage ---@class ExtraStage : Stage
local ExtraStage = {} local ExtraStage = {}
ExtraStage.__index = ExtraStage
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
setmetatable(ExtraStage, Stage)
---comment ---comment
---@param database Database ---@param database Database
---@param stageConfig StageConfig ---@param stageConfig StageConfig
@@ -10,20 +14,15 @@ local ExtraStage = {}
---@return ExtraStage ---@return ExtraStage
function ExtraStage.New(database, stageConfig, logger, initData) function ExtraStage.New(database, stageConfig, logger, initData)
-- "Import" local self = setmetatable({}, { __index = ExtraStage }) --[[@as ExtraStage]]
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage self:superNew(database, stageConfig, logger, initData)
setmetatable(ExtraStage, Stage)
ExtraStage.__index = ExtraStage
local self = Stage.New(database, stageConfig, logger, initData, "secondary") --[[@as ExtraStage]]
setmetatable(self, ExtraStage)
self.OnPostBlueActivated = function (selfStage) self.OnPostBlueActivated = function (selfStage)
selfStage:MarkStage("GRAY") selfStage:MarkStage("GRAY")
end end
self.OnPostStageComplete = function (selfStage) self.OnPostStageComplete = function (selfStage)
self:ActivateBlueStage() selfStage:ActivateBlueStage()
end end
return self return self
+7 -7
View File
@@ -2,6 +2,10 @@
---@class PrimaryStage : Stage ---@class PrimaryStage : Stage
local PrimaryStage = {} local PrimaryStage = {}
PrimaryStage.__index = PrimaryStage
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
setmetatable(PrimaryStage, Stage)
---comment ---comment
---@param database Database ---@param database Database
---@param stageConfig StageConfig ---@param stageConfig StageConfig
@@ -10,14 +14,10 @@ local PrimaryStage = {}
---@return PrimaryStage ---@return PrimaryStage
function PrimaryStage.New(database, stageConfig, logger, initData) function PrimaryStage.New(database, stageConfig, logger, initData)
-- "Import" local self = setmetatable({}, { __index = PrimaryStage }) --[[@as PrimaryStage]]
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage self:superNew(database, stageConfig, logger, initData)
setmetatable(PrimaryStage, Stage) return self
PrimaryStage.__index = PrimaryStage
setmetatable(PrimaryStage, {__index = Stage})
local o = Stage.New(database, stageConfig, logger, initData, "primary") --[[@as PrimaryStage]]
return o
end end
if not Spearhead.classes then Spearhead.classes = {} end if not Spearhead.classes then Spearhead.classes = {} end
+5 -8
View File
@@ -4,6 +4,9 @@
---@field private _startTime number ---@field private _startTime number
local WaitingStage = {} local WaitingStage = {}
WaitingStage.__index = WaitingStage
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
setmetatable(WaitingStage, Stage)
---@class WaitingStageInitData : StageInitData ---@class WaitingStageInitData : StageInitData
---@field waitingSeconds integer ---@field waitingSeconds integer
@@ -17,14 +20,8 @@ local WaitingStageInitData = {}
---@return WaitingStage ---@return WaitingStage
function WaitingStage.New(database, stageConfig, logger, initData) function WaitingStage.New(database, stageConfig, logger, initData)
-- "Import" local self = setmetatable({}, { __index = WaitingStage }) --[[@as WaitingStage]]
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage self:superNew(database, stageConfig, logger, initData)
setmetatable(WaitingStage, Stage)
WaitingStage.__index = WaitingStage
setmetatable(WaitingStage, {__index = Stage})
local self = Stage.New(database, stageConfig, logger, initData, "primary") --[[@as WaitingStage]]
setmetatable(self, WaitingStage)
self._waitTimeSeconds = 5 self._waitTimeSeconds = 5
if initData.waitingSeconds and initData.waitingSeconds > 5 then self._waitTimeSeconds = initData.waitingSeconds end if initData.waitingSeconds and initData.waitingSeconds > 5 then self._waitTimeSeconds = initData.waitingSeconds end
+4 -4
View File
@@ -12,9 +12,9 @@ local startTime = timer.getTime() * 1000
Spearhead.Events.Init("DEBUG") Spearhead.Events.Init("DEBUG")
local dbLogger = Spearhead.LoggerTemplate:new("database", "INFO") local dbLogger = Spearhead.LoggerTemplate.new("database", "INFO")
local standardLogger = Spearhead.LoggerTemplate:new("", "INFO") local standardLogger = Spearhead.LoggerTemplate.new("", "INFO")
local databaseManager = Spearhead.DB.New(dbLogger, debug) local databaseManager = Spearhead.DB.New(dbLogger)
local capConfig = Spearhead.internal.configuration.CapConfig:new(); local capConfig = Spearhead.internal.configuration.CapConfig:new();
local stageConfig = Spearhead.internal.configuration.StageConfig:new(); local stageConfig = Spearhead.internal.configuration.StageConfig:new();
@@ -22,7 +22,7 @@ local stageConfig = Spearhead.internal.configuration.StageConfig:new();
local startingStage = stageConfig.startingStage or 1 local startingStage = stageConfig.startingStage or 1
if SpearheadConfig and SpearheadConfig.Persistence and SpearheadConfig.Persistence.enabled == true then if SpearheadConfig and SpearheadConfig.Persistence and SpearheadConfig.Persistence.enabled == true then
standardLogger:info("Persistence enabled") standardLogger:info("Persistence enabled")
local persistenceLogger = Spearhead.LoggerTemplate:new("Persistence", "INFO") local persistenceLogger = Spearhead.LoggerTemplate.new("Persistence", "INFO")
Spearhead.classes.persistence.Persistence.Init(persistenceLogger) Spearhead.classes.persistence.Persistence.Init(persistenceLogger)
local persistanceStage = Spearhead.classes.persistence.Persistence.GetActiveStage() local persistanceStage = Spearhead.classes.persistence.Persistence.GetActiveStage()