Refactored Persistance managed by SpawnManager for groups, and added … (#53)
* Refactored Persistance managed by SpawnManager for groups, and added Persistence for buildables * get last file based on the iteration number * Working persistence of everything as a MVP version
This commit is contained in:
Binary file not shown.
@@ -32,8 +32,9 @@ end
|
||||
---@param stageConfig table
|
||||
---@param runwayBombingTracker RunwayBombingTracker
|
||||
---@param detectionManager DetectionManager
|
||||
---@param spawnManager SpawnManager
|
||||
---@return CapBase
|
||||
function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runwayBombingTracker, detectionManager)
|
||||
function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||
CapBase.__index = CapBase
|
||||
local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]]
|
||||
|
||||
@@ -53,7 +54,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
||||
local baseData = database:getAirbaseDataForZone(airbaseName)
|
||||
if baseData and baseData.CapGroups then
|
||||
for key, name in pairs(baseData.CapGroups) do
|
||||
local capGroup = Spearhead.classes.capClasses.airGroups.CapGroup.New(name, capConfig, logger)
|
||||
local capGroup = Spearhead.classes.capClasses.airGroups.CapGroup.New(name, capConfig, logger, spawnManager)
|
||||
if capGroup then
|
||||
self.capGroupsByName[name] = capGroup
|
||||
end
|
||||
@@ -62,7 +63,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
||||
|
||||
if baseData and baseData.SweepGroups then
|
||||
for key, name in pairs(baseData.SweepGroups) do
|
||||
local sweepGroup = Spearhead.classes.capClasses.airGroups.SweepGroup.New(name, capConfig, logger)
|
||||
local sweepGroup = Spearhead.classes.capClasses.airGroups.SweepGroup.New(name, capConfig, logger, spawnManager)
|
||||
if sweepGroup then
|
||||
self.sweepGroupsByName[name] = sweepGroup
|
||||
end
|
||||
@@ -71,7 +72,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
||||
|
||||
if baseData and baseData.InterceptGroups then
|
||||
for key, name in pairs(baseData.InterceptGroups) do
|
||||
local interceptGroup = Spearhead.classes.capClasses.airGroups.InterceptGroup.New(name, capConfig, logger, detectionManager)
|
||||
local interceptGroup = Spearhead.classes.capClasses.airGroups.InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
|
||||
if interceptGroup then
|
||||
self.interceptGroupsByName[name] = interceptGroup
|
||||
end
|
||||
|
||||
@@ -13,7 +13,8 @@ do
|
||||
---@param stageConfig StageConfig
|
||||
---@param detectionManager DetectionManager
|
||||
---@param logLevel LogLevel
|
||||
function GlobalCapManager.start(database, capConfig, detectionManager, stageConfig, logLevel)
|
||||
---@param spawnManager SpawnManager
|
||||
function GlobalCapManager.start(database, capConfig, detectionManager, stageConfig, logLevel, spawnManager)
|
||||
if initiated == true then return end
|
||||
|
||||
local logger = Spearhead.LoggerTemplate.new("AirbaseManager", logLevel)
|
||||
@@ -32,7 +33,9 @@ do
|
||||
for _, airbaseName in pairs(airbaseNames) do
|
||||
if airbaseName then
|
||||
local airbaseSpecificLogger = Spearhead.LoggerTemplate.new("CAP_" .. airbaseName, logLevel)
|
||||
local airbase = Spearhead.classes.capClasses.CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig, runwayBombingTracker, detectionManager)
|
||||
|
||||
local airbase = Spearhead.classes.capClasses.CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||
|
||||
if airbase then
|
||||
table.insert(airbasesPerStage[stageName], airbase)
|
||||
allAirbasesByName[airbaseName] = airbase
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
---@field protected _isSpawned boolean
|
||||
---@field protected _config CapConfig
|
||||
---@field protected _checkLivenessNumber number
|
||||
---@field protected _spawnManager SpawnManager
|
||||
local AirGroup = {}
|
||||
AirGroup.__index = AirGroup
|
||||
|
||||
@@ -13,13 +14,15 @@ AirGroup.__index = AirGroup
|
||||
---@param groupName string
|
||||
---@param groupType AirGroupType
|
||||
---@param config CapConfig
|
||||
function AirGroup:New(groupName, groupType, config, logger)
|
||||
---@param spawnManager SpawnManager
|
||||
function AirGroup:New(groupName, groupType, config, logger, spawnManager)
|
||||
self._groupName = groupName
|
||||
self._groupType = groupType
|
||||
self._isSpawned = false
|
||||
self._state = "UnSpawned" -- Default state
|
||||
self._config = config
|
||||
self._logger = logger
|
||||
self._spawnManager = spawnManager
|
||||
|
||||
local group = Group.getByName(self._groupName)
|
||||
if group then
|
||||
@@ -31,7 +34,8 @@ function AirGroup:New(groupName, groupType, config, logger)
|
||||
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self)
|
||||
Spearhead.Events.addOnUnitLandEventListener(unit:getName(), self)
|
||||
end
|
||||
Spearhead.DcsUtil.DestroyGroup(self._groupName)
|
||||
|
||||
spawnManager:DestroyGroup(groupName)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -135,13 +139,19 @@ function AirGroup:SpawnInternal(force, withoutLoadout)
|
||||
|
||||
if self._isSpawned and force ~= true then return end
|
||||
|
||||
local group, isStatic = Spearhead.DcsUtil.SpawnGroupTemplate(self._groupName, nil, nil, true, nil, withoutLoadout)
|
||||
---@type SpawnOverrides
|
||||
local overrides = {
|
||||
emptyLoadouts = withoutLoadout,
|
||||
uncontrolled = true
|
||||
}
|
||||
|
||||
local group, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, false)
|
||||
if isStatic == true then
|
||||
--- If For Some reaons someone tries to schedule static units as CAP classes
|
||||
self._state = "UnSpawned"
|
||||
return
|
||||
end
|
||||
|
||||
group = group --[[@as Group]]
|
||||
if group then
|
||||
self._group = group
|
||||
self._isSpawned = true
|
||||
|
||||
@@ -10,12 +10,13 @@ CapGroup.__index = CapGroup
|
||||
---@param groupName string
|
||||
---@param config CapConfig
|
||||
---@param logger Logger
|
||||
---@param spawnManager SpawnManager
|
||||
---@return CapGroup
|
||||
function CapGroup.New(groupName, config, logger)
|
||||
function CapGroup.New(groupName, config, logger, spawnManager)
|
||||
|
||||
setmetatable(CapGroup, Spearhead.classes.capClasses.airGroups.AirGroup)
|
||||
local self = setmetatable({}, CapGroup) --[[@as CapGroup]]
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "CAP", config, logger)
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "CAP", config, logger, spawnManager)
|
||||
|
||||
self._targetZoneIdPerStage = {}
|
||||
|
||||
|
||||
@@ -18,12 +18,13 @@ InterceptGroup.__index = InterceptGroup
|
||||
---@param config CapConfig
|
||||
---@param logger Logger
|
||||
---@param detectionManager DetectionManager
|
||||
---@param spawnManager SpawnManager
|
||||
---@return InterceptGroup?
|
||||
function InterceptGroup.New(groupName, config, logger, detectionManager)
|
||||
function InterceptGroup.New(groupName, config, logger, detectionManager, spawnManager)
|
||||
|
||||
setmetatable(InterceptGroup, Spearhead.classes.capClasses.airGroups.AirGroup)
|
||||
local self = setmetatable({}, InterceptGroup)
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "INTERCEPT", config, logger)
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "INTERCEPT", config, logger, spawnManager)
|
||||
|
||||
local group = Group.getByName(groupName)
|
||||
if not group then
|
||||
|
||||
@@ -8,11 +8,12 @@ SweepGroup.__index = SweepGroup
|
||||
---@param groupName string
|
||||
---@param config CapConfig
|
||||
---@param logger Logger
|
||||
---@param spawnManager SpawnManager
|
||||
---@return SweepGroup
|
||||
function SweepGroup.New(groupName, config, logger)
|
||||
function SweepGroup.New(groupName, config, logger, spawnManager)
|
||||
setmetatable(SweepGroup, Spearhead.classes.capClasses.airGroups.AirGroup)
|
||||
local self = setmetatable({}, SweepGroup) --[[@as SweepGroup]]
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "SWEEP", config, logger)
|
||||
Spearhead.classes.capClasses.airGroups.AirGroup.New(self, groupName, "SWEEP", config, logger, spawnManager)
|
||||
|
||||
self._targetZoneIdPerStage = {}
|
||||
self:InitWithName(groupName)
|
||||
|
||||
@@ -8,7 +8,7 @@ GlobalFleetManager.start = function(database)
|
||||
|
||||
local logger = Spearhead.LoggerTemplate.new("CARRIERFLEET", "INFO")
|
||||
|
||||
local all_groups = Spearhead.DcsUtil.getAllGroupNames()
|
||||
local all_groups = Spearhead.classes.helpers.MizGroupsManager.getAllGroupNames()
|
||||
for _, groupName in pairs(all_groups) do
|
||||
if Spearhead.Util.startswith(string.lower(groupName), "carriergroup" ) == true then
|
||||
logger:info("Registering " .. groupName .. " as a managed fleet")
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
---@class SpawnData
|
||||
---@field groupTemplate table
|
||||
---@field isStatic boolean
|
||||
---@field category number
|
||||
---@field country number
|
||||
|
||||
---@class MizGroupsManager
|
||||
---@field private _groupNames Array<string>
|
||||
---@field private _spawnTemplateData table<string, SpawnData>
|
||||
local MizGroupsManager = {}
|
||||
|
||||
MizGroupsManager._groupNames = {}
|
||||
MizGroupsManager._spawnTemplateData = {}
|
||||
|
||||
do --init
|
||||
for coalition_name, coalition_data in pairs(env.mission.coalition) do
|
||||
local coalition_nr = Spearhead.DcsUtil.stringToCoalition(coalition_name)
|
||||
if coalition_data.country then
|
||||
for country_index, country_data in pairs(coalition_data.country) do
|
||||
for category_name, categorydata in pairs(country_data) do
|
||||
local category_id = Spearhead.DcsUtil.stringToGroupCategory(category_name)
|
||||
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
|
||||
local name = group.name
|
||||
local skippable = false
|
||||
local isStatic = false
|
||||
if category_id == Spearhead.DcsUtil.GroupCategory.STATIC then
|
||||
isStatic = true
|
||||
local unit = group.units[1]
|
||||
if unit and unit.category == "Heliports" then
|
||||
skippable = true
|
||||
elseif unit and unit.name then
|
||||
name = unit.name
|
||||
else
|
||||
env.error("Group " .. name .. " has no units, skipping it.")
|
||||
skippable = true
|
||||
end
|
||||
end
|
||||
|
||||
if skippable == false then
|
||||
MizGroupsManager._spawnTemplateData[name] =
|
||||
{
|
||||
isStatic = isStatic,
|
||||
country = country_data.id,
|
||||
category = category_id,
|
||||
groupTemplate = group
|
||||
}
|
||||
table.insert(MizGroupsManager._groupNames, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@return Array<string>
|
||||
function MizGroupsManager.getAllGroupNames()
|
||||
return MizGroupsManager._groupNames
|
||||
end
|
||||
|
||||
---@return boolean?
|
||||
---@param groupName string
|
||||
function MizGroupsManager.IsGroupStatic(groupName)
|
||||
local spawnData = MizGroupsManager._spawnTemplateData[groupName]
|
||||
if spawnData then
|
||||
return spawnData.isStatic
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
---@return SpawnData?
|
||||
function MizGroupsManager.getSpawnTemplateData(groupName)
|
||||
return MizGroupsManager._spawnTemplateData[groupName]
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.helpers then Spearhead.classes.helpers = {} end
|
||||
Spearhead.classes.helpers.MizGroupsManager = MizGroupsManager
|
||||
@@ -0,0 +1,348 @@
|
||||
---@class SpawnManager : OnUnitLostListener
|
||||
---@field private _persistedUnits table<string,boolean>
|
||||
---@field private _logger Logger
|
||||
local SpawnManager = {}
|
||||
SpawnManager.__index = SpawnManager
|
||||
|
||||
---@class SpawnOverrides
|
||||
---@field countryID number?
|
||||
---@field emptyLoadouts boolean? if true, the group will spawn with empty loadouts
|
||||
---@field route table? route of the group. If nil will be the default route.
|
||||
---@field uncontrolled boolean? Sets the group to be uncontrolled on spawn
|
||||
|
||||
---@param logger Logger
|
||||
function SpawnManager.new(logger)
|
||||
local self = setmetatable({}, SpawnManager)
|
||||
|
||||
self._logger = logger
|
||||
|
||||
self._persistedUnits = {} -- Stores units that should be persisted by name
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param groupName string
|
||||
---@param overrides SpawnOverrides? overrides for the spawn
|
||||
---@param isGroupPersistant boolean? whether or not a group and all its units should be persisted.
|
||||
---@return StaticObject|Group|nil spawned
|
||||
---@return boolean isStatic
|
||||
function SpawnManager:SpawnGroup(groupName, overrides, isGroupPersistant)
|
||||
|
||||
local spawnData = Spearhead.classes.helpers.MizGroupsManager.getSpawnTemplateData(groupName)
|
||||
|
||||
if spawnData == nil then
|
||||
env.error("SpawnManager:SpawnGroup - No spawn template found for group: " .. groupName)
|
||||
return nil, false
|
||||
end
|
||||
|
||||
if spawnData.isStatic == true then
|
||||
return self:SpawnStaticInternal(groupName, spawnData, overrides, isGroupPersistant), true
|
||||
else
|
||||
return self:SpawnGroupInternal(groupName, spawnData, overrides, isGroupPersistant), false
|
||||
end
|
||||
end
|
||||
|
||||
function SpawnManager:DestroyGroup(groupName)
|
||||
if groupName == nil then return end
|
||||
|
||||
if self:IsGroupStatic(groupName) == true then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
if object ~= nil then
|
||||
object:destroy()
|
||||
else
|
||||
env.error("SpawnManager:DestroyGroup - Static object not found: " .. groupName)
|
||||
end
|
||||
else
|
||||
local group = Group.getByName(groupName)
|
||||
if group and group:isExist() then
|
||||
group:destroy()
|
||||
else
|
||||
env.error("SpawnManager:DestroyGroup - Group not found or does not exist: " .. groupName)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param groupName string
|
||||
---@return boolean
|
||||
function SpawnManager:IsGroupStatic(groupName)
|
||||
local isStatic = Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName)
|
||||
if isStatic ~= nil then return isStatic end
|
||||
|
||||
return StaticObject.getByName(groupName) ~= nil
|
||||
end
|
||||
|
||||
|
||||
---@param object Object
|
||||
function SpawnManager:OnUnitLost(object)
|
||||
local name = object:getName()
|
||||
|
||||
if self._persistedUnits[name] then
|
||||
local heading = 0
|
||||
local pos = object:getPosition()
|
||||
if pos then
|
||||
heading = math.atan2(pos.x.z, pos.x.x)
|
||||
if heading < 0 then
|
||||
heading = heading + 2*math.pi
|
||||
end
|
||||
heading = heading
|
||||
end
|
||||
|
||||
Spearhead.classes.persistence.Persistence.UnitKilled(
|
||||
name,
|
||||
object:getPoint(),
|
||||
heading,
|
||||
object:getTypeName()
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function SpawnManager:SpawnCorpsesOnly(groupName)
|
||||
|
||||
end
|
||||
|
||||
do --- privates
|
||||
|
||||
---@private
|
||||
---@param groupName string
|
||||
---@param spawnData SpawnData
|
||||
---@param override SpawnOverrides?
|
||||
---@param isPersistent boolean?
|
||||
---@return Group|nil
|
||||
function SpawnManager:SpawnGroupInternal(groupName, spawnData, override, isPersistent)
|
||||
|
||||
if not spawnData then return end
|
||||
|
||||
local country = spawnData.country
|
||||
if override then
|
||||
country = override.countryID or spawnData.country
|
||||
end
|
||||
|
||||
local spawnTemplate = Spearhead.Util.deepCopyTable(spawnData.groupTemplate)
|
||||
---@type Array<string>
|
||||
local removeableUnitNames = {}
|
||||
--[[
|
||||
TODO: Spawn units at "current"/LastKnown position with them going to the next waypoint.
|
||||
ONLY when perstable data is found.
|
||||
]]
|
||||
|
||||
if spawnTemplate and spawnTemplate["units"] then
|
||||
for _, unit in pairs(spawnTemplate["units"]) do
|
||||
local name = unit["name"]
|
||||
|
||||
Spearhead.Events.addOnUnitLostEventListener(name, self)
|
||||
local state = Spearhead.classes.persistence.Persistence.UnitState(name)
|
||||
if state then
|
||||
if state.isDead == true then
|
||||
removeableUnitNames[#removeableUnitNames+1] = name
|
||||
end
|
||||
end
|
||||
|
||||
if override and override.emptyLoadouts == true then
|
||||
if unit["payload"] and unit["payload"]["pylons"] then
|
||||
unit["payload"]["pylons"] = {}
|
||||
end
|
||||
end
|
||||
|
||||
if unit["parking"] then
|
||||
unit["parking_landing"] = unit["parking"]
|
||||
end
|
||||
|
||||
if unit["parking_id"] then
|
||||
unit["parking_landing_id"] = unit["parking_id"]
|
||||
end
|
||||
end
|
||||
|
||||
if override and override.route ~= nil then
|
||||
spawnTemplate["route"] = override.route
|
||||
end
|
||||
|
||||
if override and override.uncontrolled ~= nil then
|
||||
spawnTemplate["uncontrolled"] = override.uncontrolled
|
||||
end
|
||||
|
||||
local group = coalition.addGroup(country, spawnData.category, spawnTemplate)
|
||||
|
||||
|
||||
for _, unit in pairs(group:getUnits()) do
|
||||
self:CheckUnitAndReplaceIfPersistentDead(unit)
|
||||
if isPersistent == true then
|
||||
self._persistedUnits[unit:getName()] = true
|
||||
end
|
||||
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self)
|
||||
end
|
||||
|
||||
return group
|
||||
end
|
||||
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param groupName string
|
||||
---@param spawnData SpawnData
|
||||
---@param isPersistent any
|
||||
---@param overrides SpawnOverrides?
|
||||
---@return StaticObject?
|
||||
function SpawnManager:SpawnStaticInternal(groupName, spawnData, overrides, isPersistent)
|
||||
|
||||
if not spawnData then return end
|
||||
|
||||
local country = spawnData.country
|
||||
if overrides then
|
||||
country = overrides.countryID or spawnData.country
|
||||
end
|
||||
|
||||
local spawnTemplate = Spearhead.Util.deepCopyTable(spawnData.groupTemplate)
|
||||
|
||||
--for static Objecst groupNames and unit names are the same and is always 1:1
|
||||
local persistentState = Spearhead.classes.persistence.Persistence.UnitState(groupName)
|
||||
if persistentState then
|
||||
if persistentState.isDead == true then
|
||||
spawnTemplate["dead"] = true
|
||||
if persistentState.pos then
|
||||
spawnTemplate["x"] = persistentState.pos.x
|
||||
spawnTemplate["y"] = persistentState.pos.z
|
||||
if spawnTemplate["units"] and spawnTemplate["units"][1] then
|
||||
spawnTemplate["units"][1]["x"] = persistentState.pos.x
|
||||
spawnTemplate["units"][1]["y"] = persistentState.pos.z
|
||||
spawnTemplate["units"][1]["heading"] = persistentState.heading or 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---disable diagnostic as -1 is actually valid
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
coalition.addGroup(country, -1, spawnTemplate)
|
||||
|
||||
local object = StaticObject.getByName(groupName)
|
||||
if object == nil then
|
||||
env.error("Could not retrieve spawned static object after spawning with name: " .. groupName)
|
||||
return nil
|
||||
end
|
||||
|
||||
if isPersistent == true then
|
||||
self._persistedUnits[groupName] = true
|
||||
Spearhead.Events.addOnUnitLostEventListener(groupName, self)
|
||||
end
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param unit Unit
|
||||
function SpawnManager:CheckUnitAndReplaceIfPersistentDead(unit)
|
||||
|
||||
if not unit then return end
|
||||
|
||||
local deadState = Spearhead.classes.persistence.Persistence.UnitState(unit:getName())
|
||||
if deadState and deadState.isDead == true then
|
||||
unit:destroy() -- Destroy the unit if it is dead
|
||||
local staticObject = {
|
||||
["heading"] = deadState.heading or 0,
|
||||
["type"] = deadState.type or unit:getTypeName(),
|
||||
["name"] = unit:getName() .. "_dead",
|
||||
["x"] = deadState.pos.x,
|
||||
["y"] = deadState.pos.z,
|
||||
["dead"] = true,
|
||||
}
|
||||
coalition.addStaticObject(unit:getCountry(), staticObject)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
if not Spearhead.classes then Spearhead.classes = {} end
|
||||
if not Spearhead.classes.helpers then Spearhead.classes.helpers = {} end
|
||||
Spearhead.classes.helpers.SpawnManager = SpawnManager
|
||||
|
||||
--Old Spawn Method
|
||||
|
||||
-- --- spawns the units as specified in the mission file itself
|
||||
-- --- location and route can be nil and will then use default route
|
||||
-- ---@param groupName string
|
||||
-- ---@param location table? vector 3 data. { x , z, alt }
|
||||
-- ---@param route table? route of the group. If nil wil be the default route.
|
||||
-- ---@param uncontrolled boolean? Sets the group to be uncontrolled on spawn
|
||||
-- ---@param countryId CountryID? Overwrites the country
|
||||
-- ---@param emptyLoadouts boolean? If true, the group will spawn with empty loadouts
|
||||
-- ---@return table? new_group the Group class that was spawned
|
||||
-- ---@return boolean? isStatic whether the group is a static or not
|
||||
-- function DCS_UTIL.SpawnGroupTemplate(groupName, location, route, uncontrolled, countryId, emptyLoadouts)
|
||||
-- if groupName == nil then
|
||||
-- return nil, nil
|
||||
-- end
|
||||
|
||||
-- local template = DCS_UTIL.GetMizGroupOrDefault(groupName, nil)
|
||||
-- if template == nil then
|
||||
-- return nil, nil
|
||||
-- end
|
||||
-- if template.category == DCS_UTIL.GroupCategory.STATIC then
|
||||
-- --TODO: Implement location and route stuff
|
||||
-- local spawn_template = template.group_template
|
||||
-- local country = countryId or template.country_id
|
||||
|
||||
-- ---disable diagnostic as -1 is actually valid
|
||||
-- ---@diagnostic disable-next-line: param-type-mismatch
|
||||
-- coalition.addGroup(country, -1, spawn_template)
|
||||
|
||||
-- local object = StaticObject.getByName(spawn_template.name)
|
||||
-- if object then
|
||||
-- return object, true
|
||||
-- end
|
||||
-- else
|
||||
-- local spawn_template = Spearhead.Util.deepCopyTable(template.group_template)
|
||||
-- if location ~= nil then
|
||||
-- local x_offset
|
||||
-- if location.x ~= nil then x_offset = spawn_template.x - location.x end
|
||||
|
||||
-- local y_offset
|
||||
-- if location.z ~= nil then y_offset = spawn_template.y - location.z end
|
||||
|
||||
-- spawn_template.x = location.x
|
||||
-- spawn_template.y = location.z
|
||||
|
||||
-- for i, unit in pairs(spawn_template.units) do
|
||||
-- unit.x = unit.x - x_offset
|
||||
-- unit.y = unit.y - y_offset
|
||||
-- unit.alt = location.alt
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if spawn_template.units then
|
||||
-- for _, unit in pairs(spawn_template.units) do
|
||||
-- if unit["parking"] then
|
||||
-- unit["parking_landing"] = unit["parking"]
|
||||
-- end
|
||||
|
||||
-- if unit["parking_id"] then
|
||||
-- unit["parking_landing_id"] = unit["parking_id"]
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if emptyLoadouts == true then
|
||||
-- for _, unit in pairs(spawn_template.units) do
|
||||
-- if unit["payload"] and unit["payload"]["pylons"] then
|
||||
-- unit["payload"]["pylons"] = {}
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if route ~= nil then
|
||||
-- spawn_template.route = route
|
||||
-- end
|
||||
|
||||
-- if uncontrolled ~= nil then
|
||||
-- spawn_template.uncontrolled = uncontrolled
|
||||
-- end
|
||||
|
||||
-- local country = countryId or template.country_id
|
||||
-- local new_group = coalition.addGroup(country, template.category, spawn_template)
|
||||
-- return new_group, false
|
||||
-- end
|
||||
-- end
|
||||
@@ -1,43 +1,54 @@
|
||||
|
||||
---@class Perstistence
|
||||
---@field private _path string
|
||||
---@field private _updateRequired boolean
|
||||
local Persistence = {}
|
||||
do
|
||||
local EXTENSION = "spearhead"
|
||||
|
||||
---@class PersistentData
|
||||
---@field dead_units table<string, DeathState>
|
||||
---@field version string
|
||||
---@field unitsStates table<string, UnitState>
|
||||
---@field random_missions table<string, MissionState>
|
||||
---@field deliveredKilos table<string, number>
|
||||
---@field activeStage integer|nil
|
||||
|
||||
---@class DeathState
|
||||
---@class UnitState
|
||||
---@field isDead boolean
|
||||
---@field pos Vec3
|
||||
---@field heading number
|
||||
---@field type string
|
||||
---@field country_id integer
|
||||
---@field pos Vec3?
|
||||
---@field heading number?
|
||||
---@field type string?
|
||||
|
||||
|
||||
local persistanceWriteIntervalSeconds = 15
|
||||
local enabled = false
|
||||
|
||||
local version = "1.0.0"
|
||||
|
||||
---@type PersistentData
|
||||
local tables = {
|
||||
dead_units = {},
|
||||
version = version,
|
||||
unitsStates = {},
|
||||
random_missions = {},
|
||||
deliveredKilos = {},
|
||||
activeStage = nil
|
||||
}
|
||||
|
||||
|
||||
local logger = {}
|
||||
|
||||
if SpearheadConfig == nil then SpearheadConfig = {} end
|
||||
if SpearheadConfig.Persistence == nil then SpearheadConfig.Persistence = {} end
|
||||
|
||||
local path = nil
|
||||
local updateRequired = false
|
||||
|
||||
local createFileIfNotExists = function()
|
||||
if not path then return end
|
||||
local createFileIfNotExists = function(path)
|
||||
if not path or path == "" then
|
||||
logger:error("Persistence file path is not set, cannot create file")
|
||||
return
|
||||
end
|
||||
|
||||
local f = io.open(path, "r")
|
||||
if f == nil then
|
||||
logger:info("Persistence file does not exist, creating new one at: " .. path)
|
||||
f = io.open(path, "w+")
|
||||
if f == nil then
|
||||
logger:error("Could not create a file")
|
||||
@@ -45,53 +56,42 @@ do
|
||||
f:write("{}")
|
||||
f:close()
|
||||
end
|
||||
logger:info("Created new persistence file at: " .. path)
|
||||
else
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
local loadTablesFromFile = function()
|
||||
---@param path string
|
||||
local loadTablesFromFile = function(path)
|
||||
if not path then return end
|
||||
|
||||
logger:info("Loading data from persistance file...")
|
||||
local f = io.open(path, "r")
|
||||
if f == nil then
|
||||
logger:error("Could not open persistence file for reading: " .. path)
|
||||
return
|
||||
end
|
||||
|
||||
local json = f:read("*a")
|
||||
f:close()
|
||||
|
||||
logger:debug("Loaded persistence file content: " .. json)
|
||||
local lua = net.json2lua(json) --[[@as PersistentData]]
|
||||
|
||||
if lua.activeStage then
|
||||
logger:info("Found active stage from save: " .. lua.activeStage)
|
||||
tables.activeStage = lua.activeStage
|
||||
if lua then
|
||||
tables = lua
|
||||
logger:debug("Loaded persistence data: " .. Spearhead.Util.toString(lua))
|
||||
else
|
||||
logger:error("Could not load persistence file, using default tables")
|
||||
end
|
||||
|
||||
if lua.dead_units then
|
||||
logger:debug("Found saved dead units")
|
||||
for name, deadState in pairs(lua.dead_units) do
|
||||
logger:debug("Found saved dead unit: " .. name)
|
||||
|
||||
if type(deadState) == "table" then
|
||||
tables.dead_units[name] = {
|
||||
isDead = deadState.isDead == true,
|
||||
pos = deadState.pos,
|
||||
heading = deadState.heading,
|
||||
type = deadState.type,
|
||||
country_id = deadState.country_id
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if tables.version == nil then tables.version = version end
|
||||
end
|
||||
|
||||
local writeToFile = function()
|
||||
if not path then return end
|
||||
|
||||
if not Persistence._path then return end
|
||||
local path = Persistence._path
|
||||
local f = io.open(path, "w+")
|
||||
if f == nil then
|
||||
error("Could not open file for writing")
|
||||
@@ -104,11 +104,13 @@ do
|
||||
if f ~= nil then
|
||||
f:close()
|
||||
end
|
||||
Persistence._updateRequired = false
|
||||
logger:info("Wrote persistence data to file")
|
||||
end
|
||||
|
||||
local UpdateContinuous = function(null, time)
|
||||
|
||||
if updateRequired then
|
||||
env.info("[Spearhead][Persistence] Checking up on persistence state...")
|
||||
if Persistence._updateRequired == true then
|
||||
local status, result = pcall(writeToFile)
|
||||
if status == false then
|
||||
env.error("[Spearhead][Persistence] Could not write state to file: " .. result)
|
||||
@@ -129,33 +131,107 @@ do
|
||||
end
|
||||
|
||||
|
||||
local warnForNonPersistenceContinous = function(null, 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)
|
||||
return time + 9
|
||||
end
|
||||
|
||||
---@param dir string @BaseDirectory
|
||||
---@return string
|
||||
local getLastFileOrDefault = function(dir, startsWith, default)
|
||||
|
||||
local latestFile, lastNumber = default, 0
|
||||
for file in lfs.dir(dir) do
|
||||
|
||||
local split = Spearhead.Util.split_string(file, ".")
|
||||
local doesStartWith = Spearhead.Util.startswith(file, startsWith, true)
|
||||
if split and #split > 0 and split[#split] == EXTENSION and doesStartWith == true then
|
||||
local numberString = split[#split-1]
|
||||
local number = tonumber(numberString)
|
||||
if number ~= nil and number > lastNumber then
|
||||
lastNumber = number
|
||||
latestFile = file
|
||||
end
|
||||
end
|
||||
end
|
||||
return latestFile
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param persistenceLogger Logger
|
||||
Persistence.Init = function(persistenceLogger)
|
||||
logger = persistenceLogger
|
||||
|
||||
logger:info("Initiating Persistence Manager")
|
||||
logger:debug("Initiating Persistence Manager")
|
||||
|
||||
if lfs == nil or io == nil then
|
||||
logger:error("lfs and io seem to be sanitized. Persistence is skipped and disabled")
|
||||
enabled = false
|
||||
timer.scheduleFunction(warnForNonPersistenceContinous, nil, timer.getTime() + 10)
|
||||
return
|
||||
end
|
||||
|
||||
path = (SpearheadConfig.Persistence.directory or (lfs.writedir() .. "\\Data" )) .. "\\" .. (SpearheadConfig.Persistence.fileName or "Spearhead_Persistence.json")
|
||||
---@type string
|
||||
local dir = lfs.writedir() .. "\\Data"
|
||||
local fileName = "Spearhead_Persistence.0.spearhead"
|
||||
if SpearheadConfig and SpearheadConfig.Persistence then
|
||||
if SpearheadConfig.Persistence.fileName then
|
||||
|
||||
logger:info("Persistence file path: " .. path)
|
||||
local userFileName = SpearheadConfig.Persistence.fileName
|
||||
local split = Spearhead.Util.split_string(userFileName, ".")
|
||||
|
||||
createFileIfNotExists()
|
||||
loadTablesFromFile()
|
||||
if not split and #split < 3 then
|
||||
split[#split+1] = "0"
|
||||
split[#split+1] = "spearhead"
|
||||
end
|
||||
|
||||
if tonumber(split[#split-1]) == nil then
|
||||
split[#split+1] = "0"
|
||||
split[#split+1] = "spearhead"
|
||||
end
|
||||
|
||||
fileName = table.concat(split, ".")
|
||||
end
|
||||
|
||||
if SpearheadConfig.Persistence.directory ~= nil then
|
||||
dir = SpearheadConfig.Persistence.directory
|
||||
end
|
||||
end
|
||||
|
||||
local split = Spearhead.Util.split_string(fileName, ".")
|
||||
local matchingPart = table.concat(Spearhead.Util.sublist(split, 1, #split-2), ".")
|
||||
|
||||
local lastFile = getLastFileOrDefault(dir--[[@as string]], matchingPart, fileName)
|
||||
|
||||
local fileSplit = Spearhead.Util.split_string(lastFile, ".")
|
||||
fileSplit[#fileSplit-1] = tostring(tonumber(fileSplit[#fileSplit-1]) + 1)
|
||||
fileName = table.concat(fileSplit, ".")
|
||||
|
||||
if lastFile ~= fileName then
|
||||
logger:info("Found last persistence file: " .. lastFile)
|
||||
else
|
||||
logger:info("No previous persistence file found, using default: " .. fileName)
|
||||
end
|
||||
|
||||
|
||||
logger:info("New Persistence file name: " .. tostring(fileName))
|
||||
local lastPath = dir .. "\\" .. lastFile
|
||||
local path = dir .. "\\" .. fileName
|
||||
Persistence._path = path
|
||||
|
||||
createFileIfNotExists(path)
|
||||
loadTablesFromFile(lastPath)
|
||||
timer.scheduleFunction(UpdateContinuous, nil, timer.getTime() + 120)
|
||||
enabled = true
|
||||
Persistence.UpdateNow()
|
||||
end
|
||||
|
||||
---Sets the stage in the persistence table
|
||||
---@param stageNumber number
|
||||
Persistence.SetActiveStage = function(stageNumber)
|
||||
tables.activeStage = stageNumber
|
||||
updateRequired = true
|
||||
Persistence._updateRequired = true
|
||||
end
|
||||
|
||||
---comment
|
||||
@@ -166,7 +242,7 @@ do
|
||||
|
||||
if tables.random_missions == nil then tables.random_missions = {} end
|
||||
tables.random_missions[string.lower(missionName)] = pickedZone
|
||||
updateRequired = true
|
||||
Persistence._updateRequired = true
|
||||
end
|
||||
|
||||
---Get the picked random mission from the persistence file
|
||||
@@ -186,19 +262,49 @@ do
|
||||
return nil
|
||||
end
|
||||
|
||||
---Check if the unit was dead during the last save. Nil if persitance not enabled
|
||||
---comment
|
||||
---@param zoneName string
|
||||
---@param kilos number
|
||||
Persistence.SetZoneDeliveredKilos = function(zoneName, kilos)
|
||||
if enabled == false then return end
|
||||
|
||||
if tables.deliveredKilos == nil then
|
||||
tables.deliveredKilos = {}
|
||||
end
|
||||
|
||||
tables.deliveredKilos[zoneName] = kilos
|
||||
Persistence._updateRequired = true
|
||||
end
|
||||
|
||||
Persistence.GetZoneDeliveredKilos = function(zoneName)
|
||||
if enabled == false then return 0 end
|
||||
|
||||
if tables.deliveredKilos == nil then
|
||||
tables.deliveredKilos = {}
|
||||
end
|
||||
|
||||
return tables.deliveredKilos[zoneName] or 0
|
||||
end
|
||||
|
||||
|
||||
|
||||
---Check if the unit was dead during the last save. Nil if persitance not enabled or no state is found
|
||||
---@param unitName string name
|
||||
---@return DeathState|nil { isDead, pos = {x,y,z}, heading, type, country_id }
|
||||
Persistence.UnitDeadState = function(unitName)
|
||||
---@return UnitState|nil { isDead, pos = {x,y,z}, heading, type, country_id }
|
||||
Persistence.UnitState = function(unitName)
|
||||
if Persistence.isEnabled() == false then
|
||||
return nil
|
||||
end
|
||||
|
||||
local entry = tables.dead_units[unitName]
|
||||
local entry = tables.unitsStates[unitName]
|
||||
if entry then
|
||||
return entry
|
||||
else
|
||||
return { isDead = false }
|
||||
---@type UnitState
|
||||
local state = {
|
||||
isDead = false
|
||||
}
|
||||
return state
|
||||
end
|
||||
end
|
||||
|
||||
@@ -207,19 +313,19 @@ do
|
||||
---@param position Vec3 { x, y ,z }
|
||||
---@param heading number
|
||||
---@param type string
|
||||
---@param country_id number
|
||||
Persistence.UnitKilled = function (name, position, heading, type, country_id)
|
||||
Persistence.UnitKilled = function (name, position, heading, type)
|
||||
if enabled == false then return end
|
||||
|
||||
tables.dead_units[name] = {
|
||||
isDead = true,
|
||||
pos = position,
|
||||
heading = heading,
|
||||
type = type,
|
||||
country_id = country_id,
|
||||
logger:debug("Unit killed: " .. name .. ".. => persistenting")
|
||||
|
||||
tables.unitsStates[name] = {
|
||||
isDead = true,
|
||||
pos = position,
|
||||
heading = heading,
|
||||
type = type,
|
||||
isCleaned = false
|
||||
}
|
||||
updateRequired = true
|
||||
Persistence._updateRequired = true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+14
-227
@@ -67,6 +67,18 @@ do -- INIT UTIL
|
||||
return list[random]
|
||||
end
|
||||
|
||||
---@param list Array
|
||||
---@param start number start
|
||||
---@param n number length
|
||||
---@return Array
|
||||
function UTIL.sublist(list, start, n)
|
||||
local result = {}
|
||||
for i = start, n do
|
||||
result[#result + 1] = list[i]
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
---@param str string
|
||||
---@param find string
|
||||
---@param replace string
|
||||
@@ -504,17 +516,6 @@ do -- INIT DCS_UTIL
|
||||
}
|
||||
]] --
|
||||
|
||||
---@class MizGroupData
|
||||
---@field category GroupCategory
|
||||
---@field country_id integer
|
||||
---@field group_template table
|
||||
|
||||
---@type table<string, MizGroupData>
|
||||
DCS_UTIL.__miz_groups = {}
|
||||
|
||||
DCS_UTIL.__groupNames = {}
|
||||
DCS_UTIL.__blueGroupNames = {}
|
||||
DCS_UTIL.__redGroupNames = {}
|
||||
--[[
|
||||
zone = {
|
||||
name,
|
||||
@@ -574,54 +575,6 @@ do -- INIT DCS_UTIL
|
||||
DCS_UTIL.__warehouseStartingCoalition = {}
|
||||
function DCS_UTIL.__INIT()
|
||||
do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment
|
||||
do -- init group tables
|
||||
for coalition_name, coalition_data in pairs(env.mission.coalition) do
|
||||
local coalition_nr = DCS_UTIL.stringToCoalition(coalition_name)
|
||||
if coalition_data.country then
|
||||
for country_index, country_data in pairs(coalition_data.country) do
|
||||
for category_name, categorydata in pairs(country_data) do
|
||||
local category_id = DCS_UTIL.stringToGroupCategory(category_name)
|
||||
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
|
||||
local name = group.name
|
||||
|
||||
local skippable = false
|
||||
|
||||
if category_id == DCS_UTIL.GroupCategory.STATIC then
|
||||
local unit = group.units[1]
|
||||
|
||||
if unit and unit.category == "Heliports" then
|
||||
skippable = true
|
||||
elseif unit then
|
||||
name = unit.name
|
||||
else
|
||||
env.error("Group " .. name .. " has no units, skipping it.")
|
||||
skippable = true
|
||||
end
|
||||
end
|
||||
|
||||
if skippable == false then
|
||||
table.insert(DCS_UTIL.__groupNames, name)
|
||||
DCS_UTIL.__miz_groups[name] =
|
||||
{
|
||||
category = category_id,
|
||||
country_id = country_data.id,
|
||||
group_template = group
|
||||
}
|
||||
|
||||
if coalition_nr == 1 then
|
||||
table.insert(DCS_UTIL.__redGroupNames, name)
|
||||
elseif coalition_nr == 2 then
|
||||
table.insert(DCS_UTIL.__blueGroupNames, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do --init trigger zones
|
||||
for i, trigger_zone in pairs(env.mission.triggers.zones) do
|
||||
@@ -750,31 +703,6 @@ do -- INIT DCS_UTIL
|
||||
return -1
|
||||
end
|
||||
|
||||
---checks if the groupname is a static group
|
||||
---@param groupName string
|
||||
function DCS_UTIL.IsGroupStatic(groupName)
|
||||
if DCS_UTIL.__miz_groups[groupName] then
|
||||
return DCS_UTIL.__miz_groups[groupName].category == DCS_UTIL.GroupCategory.STATIC
|
||||
end
|
||||
|
||||
return StaticObject.getByName(groupName) ~= nil
|
||||
end
|
||||
|
||||
---destroy the given group
|
||||
---@param groupName string
|
||||
function DCS_UTIL.DestroyGroup(groupName)
|
||||
if DCS_UTIL.IsGroupStatic(groupName) then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
if object ~= nil then
|
||||
object:destroy()
|
||||
end
|
||||
else
|
||||
local group = Group.getByName(groupName)
|
||||
if group and group:isExist() then
|
||||
group:destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---destroy the given unit
|
||||
---@param unitName string
|
||||
@@ -1049,43 +977,7 @@ do -- INIT DCS_UTIL
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- get the group config as per start of the mission
|
||||
--- group = {
|
||||
--- category,
|
||||
--- country_id,
|
||||
--- group_template
|
||||
--- }
|
||||
---@param groupname string groupName you're looking for
|
||||
function DCS_UTIL.GetMizGroupOrDefault(groupname, default)
|
||||
local group = DCS_UTIL.__miz_groups[groupname]
|
||||
if group == nil then
|
||||
return default
|
||||
end
|
||||
return group
|
||||
end
|
||||
|
||||
---comment Get all group names. Can be a LOT
|
||||
---Includes statics
|
||||
---@return table groups
|
||||
function DCS_UTIL.getAllGroupNames()
|
||||
return DCS_UTIL.__groupNames
|
||||
end
|
||||
|
||||
---comment Get all BLUE group names. Can be a LOT
|
||||
---Includes statics
|
||||
---@return table groups
|
||||
function DCS_UTIL.getAllBlueGroupNames()
|
||||
return DCS_UTIL.__blueGroupNames
|
||||
end
|
||||
|
||||
---comment Get all RED group names. Can be a LOT
|
||||
---Includes statics
|
||||
---@return table groups
|
||||
function DCS_UTIL.getAllRedGroupNames()
|
||||
return DCS_UTIL.__redGroupNames
|
||||
end
|
||||
|
||||
|
||||
---comment Get all units that are players
|
||||
---@return Array<Unit> units
|
||||
function DCS_UTIL.getAllPlayerUnits()
|
||||
@@ -1134,27 +1026,6 @@ do -- INIT DCS_UTIL
|
||||
return result
|
||||
end
|
||||
|
||||
---Spawn an corpse
|
||||
---@param countryId number countryId
|
||||
---@param unitType string
|
||||
---@param location table { z, y, z}
|
||||
---@param heading number
|
||||
function DCS_UTIL.SpawnCorpse(countryId, unitName, unitType, location, heading)
|
||||
local name = "dead_" .. unitName
|
||||
|
||||
local staticObj = {
|
||||
["heading"] = heading,
|
||||
--["shape_name"] = "stolovaya",
|
||||
["type"] = unitType,
|
||||
["name"] = name,
|
||||
["y"] = location.z,
|
||||
["x"] = location.x,
|
||||
["dead"] = true,
|
||||
}
|
||||
|
||||
coalition.addStaticObject(countryId, staticObj)
|
||||
end
|
||||
|
||||
function DCS_UTIL.CleanCorpse(unitName)
|
||||
local unitName = "dead_" .. unitName
|
||||
|
||||
@@ -1296,90 +1167,6 @@ do -- INIT DCS_UTIL
|
||||
end
|
||||
end
|
||||
|
||||
--- spawns the units as specified in the mission file itself
|
||||
--- location and route can be nil and will then use default route
|
||||
---@param groupName string
|
||||
---@param location table? vector 3 data. { x , z, alt }
|
||||
---@param route table? route of the group. If nil wil be the default route.
|
||||
---@param uncontrolled boolean? Sets the group to be uncontrolled on spawn
|
||||
---@param countryId CountryID? Overwrites the country
|
||||
---@param emptyLoadouts boolean? If true, the group will spawn with empty loadouts
|
||||
---@return table? new_group the Group class that was spawned
|
||||
---@return boolean? isStatic whether the group is a static or not
|
||||
function DCS_UTIL.SpawnGroupTemplate(groupName, location, route, uncontrolled, countryId, emptyLoadouts)
|
||||
if groupName == nil then
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
local template = DCS_UTIL.GetMizGroupOrDefault(groupName, nil)
|
||||
if template == nil then
|
||||
return nil, nil
|
||||
end
|
||||
if template.category == DCS_UTIL.GroupCategory.STATIC then
|
||||
--TODO: Implement location and route stuff
|
||||
local spawn_template = template.group_template
|
||||
local country = countryId or template.country_id
|
||||
|
||||
---disable diagnostic as -1 is actually valid
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
coalition.addGroup(country, -1, spawn_template)
|
||||
|
||||
local object = StaticObject.getByName(spawn_template.name)
|
||||
if object then
|
||||
return object, true
|
||||
end
|
||||
else
|
||||
local spawn_template = Spearhead.Util.deepCopyTable(template.group_template)
|
||||
if location ~= nil then
|
||||
local x_offset
|
||||
if location.x ~= nil then x_offset = spawn_template.x - location.x end
|
||||
|
||||
local y_offset
|
||||
if location.z ~= nil then y_offset = spawn_template.y - location.z end
|
||||
|
||||
spawn_template.x = location.x
|
||||
spawn_template.y = location.z
|
||||
|
||||
for i, unit in pairs(spawn_template.units) do
|
||||
unit.x = unit.x - x_offset
|
||||
unit.y = unit.y - y_offset
|
||||
unit.alt = location.alt
|
||||
end
|
||||
end
|
||||
|
||||
if spawn_template.units then
|
||||
for _, unit in pairs(spawn_template.units) do
|
||||
if unit["parking"] then
|
||||
unit["parking_landing"] = unit["parking"]
|
||||
end
|
||||
|
||||
if unit["parking_id"] then
|
||||
unit["parking_landing_id"] = unit["parking_id"]
|
||||
end
|
||||
end
|
||||
|
||||
if emptyLoadouts == true then
|
||||
for _, unit in pairs(spawn_template.units) do
|
||||
if unit["payload"] and unit["payload"]["pylons"] then
|
||||
unit["payload"]["pylons"] = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if route ~= nil then
|
||||
spawn_template.route = route
|
||||
end
|
||||
|
||||
if uncontrolled ~= nil then
|
||||
spawn_template.uncontrolled = uncontrolled
|
||||
end
|
||||
|
||||
local country = countryId or template.country_id
|
||||
local new_group = coalition.addGroup(country, template.category, spawn_template)
|
||||
return new_group, false
|
||||
end
|
||||
end
|
||||
|
||||
---@return number? id
|
||||
function DCS_UTIL.GetNeutralCountry()
|
||||
@@ -1393,7 +1180,7 @@ do -- INIT DCS_UTIL
|
||||
|
||||
function DCS_UTIL.NeedsRTBInTen(groupName, fuelOffset)
|
||||
|
||||
local isBingo = Spearhead.DcsUtil.IsBingoFuel(groupName, fuelOffset)
|
||||
local isBingo = DCS_UTIL.IsBingoFuel(groupName, fuelOffset)
|
||||
if isBingo then return true end
|
||||
|
||||
local aliveUnits = 0
|
||||
|
||||
@@ -470,7 +470,7 @@ end
|
||||
---@private
|
||||
function Database:initAvailableUnits()
|
||||
do
|
||||
local all_groups = Spearhead.DcsUtil.getAllGroupNames()
|
||||
local all_groups = Spearhead.classes.helpers.MizGroupsManager.getAllGroupNames()
|
||||
for _, value in pairs(all_groups) do
|
||||
is_group_taken[value] = false
|
||||
end
|
||||
@@ -637,7 +637,7 @@ end
|
||||
|
||||
---@private
|
||||
function Database:loadBlueSamUnits()
|
||||
local all_groups = Spearhead.DcsUtil.getAllGroupNames()
|
||||
local all_groups = Spearhead.classes.helpers.MizGroupsManager.getAllGroupNames()
|
||||
for _, blueSamZone in pairs(self._tables.BlueSams) do
|
||||
local samData = self:getOrCreateBlueSamDataForZone(blueSamZone)
|
||||
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, blueSamZone)
|
||||
@@ -659,7 +659,7 @@ function Database:loadMissionzoneUnits()
|
||||
|
||||
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName)
|
||||
for _, groupName in pairs(groups) do
|
||||
if Spearhead.DcsUtil.IsGroupStatic(groupName) == true then
|
||||
if Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
|
||||
if object and object:getCoalition() == coalition.side.RED then
|
||||
@@ -691,7 +691,7 @@ function Database:loadRandomMissionzoneUnits()
|
||||
}
|
||||
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName)
|
||||
for _, groupName in pairs(groups) do
|
||||
if Spearhead.DcsUtil.IsGroupStatic(groupName) == true then
|
||||
if Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
|
||||
if object and object:getCoalition() == coalition.side.RED then
|
||||
@@ -752,7 +752,7 @@ function Database:loadAirbaseGroups()
|
||||
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
|
||||
if Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
if object then
|
||||
if object:getCoalition() == coalition.side.RED then
|
||||
@@ -790,7 +790,7 @@ function Database:loadMiscGroupsInStages()
|
||||
|
||||
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, stageZone.StageZoneName)
|
||||
for _, groupName in pairs(groups) do
|
||||
if Spearhead.DcsUtil.IsGroupStatic(groupName) == true then
|
||||
if Spearhead.classes.helpers.MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||
local object = StaticObject.getByName(groupName)
|
||||
if object and object:getCoalition() ~= coalition.side.NEUTRAL then
|
||||
is_group_taken[groupName] = true
|
||||
|
||||
@@ -355,17 +355,17 @@ do
|
||||
local AI_GROUPS = {}
|
||||
|
||||
local function CheckAndTriggerSpawnAsync(unit, time)
|
||||
|
||||
local function isPlayer(unit)
|
||||
if unit == 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 Object.getCategory(unit) ~= Object.Category.UNIT then
|
||||
return false, "object is not a unit"
|
||||
end
|
||||
|
||||
if unit:isExist() ~= true then return false, "unit does not exist" end
|
||||
local group = unit:getGroup()
|
||||
if group ~= nil then
|
||||
if Spearhead.DcsUtil.IsGroupStatic(group:getName()) == true then
|
||||
return false
|
||||
end
|
||||
|
||||
if AI_GROUPS[group:getName()] == true then
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -20,8 +20,9 @@ GlobalStageManager = {}
|
||||
---@param database Database
|
||||
---@param stageConfig StageConfig
|
||||
---@param logLevel LogLevel
|
||||
---@param spawnManager SpawnManager
|
||||
---@return nil
|
||||
function GlobalStageManager:NewAndStart(database, stageConfig, logLevel)
|
||||
function GlobalStageManager:NewAndStart(database, stageConfig, logLevel, spawnManager)
|
||||
local logger = Spearhead.LoggerTemplate.new("StageManager", logLevel)
|
||||
logger:info("Using Stage Log Level: " .. logLevel)
|
||||
local o = {}
|
||||
@@ -134,13 +135,13 @@ function GlobalStageManager:NewAndStart(database, stageConfig, logLevel)
|
||||
}
|
||||
|
||||
if isSideStage == true then
|
||||
local stage = Spearhead.classes.stageClasses.Stages.ExtraStage.New(database, stageConfig, stagelogger, initData)
|
||||
local stage = Spearhead.classes.stageClasses.Stages.ExtraStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
stage:AddStageCompleteListener(OnStageCompleteListener)
|
||||
|
||||
if SideStageByIndex[tostring(orderNumber)] == nil then SideStageByIndex[tostring(orderNumber)] = {} end
|
||||
table.insert(SideStageByIndex[tostring(orderNumber)], stage)
|
||||
else
|
||||
local stage = Spearhead.classes.stageClasses.Stages.PrimaryStage.New(database, stageConfig, stagelogger, initData)
|
||||
local stage = Spearhead.classes.stageClasses.Stages.PrimaryStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
stage:AddStageCompleteListener(OnStageCompleteListener)
|
||||
|
||||
if StagesByIndex[tostring(orderNumber)] == nil then StagesByIndex[tostring(orderNumber)] = {} end
|
||||
@@ -185,7 +186,7 @@ function GlobalStageManager:NewAndStart(database, stageConfig, logLevel)
|
||||
stageZoneName = stageName,
|
||||
waitingSeconds = waitingSeconds --[[@as integer]]
|
||||
}
|
||||
local waitingStage = Spearhead.classes.stageClasses.Stages.WaitingStage.New(database, stageConfig, stagelogger, initData)
|
||||
local waitingStage = Spearhead.classes.stageClasses.Stages.WaitingStage.New(database, stageConfig, stagelogger, initData, spawnManager)
|
||||
|
||||
if WaitingStagesByIndex[tostring(stageIndex)] == nil then
|
||||
WaitingStagesByIndex[tostring(stageIndex)] = {}
|
||||
|
||||
@@ -2,22 +2,38 @@
|
||||
|
||||
|
||||
---@class SpearheadGroup : OnUnitLostListener
|
||||
---@field groupName string
|
||||
---@field private _groupName string
|
||||
---@field private _isStatic boolean
|
||||
---@field private _isSpawned boolean
|
||||
---@field private _spawnManager SpawnManager
|
||||
---@field private _isPersistent boolean
|
||||
local SpearheadGroup = {}
|
||||
SpearheadGroup.__index = SpearheadGroup
|
||||
|
||||
function SpearheadGroup.New(groupName)
|
||||
---comment
|
||||
---@param groupName string
|
||||
---@param spawnManager SpawnManager
|
||||
---@param isPersistent boolean?
|
||||
---@return SpearheadGroup
|
||||
function SpearheadGroup.New(groupName, spawnManager, isPersistent)
|
||||
local self = setmetatable({}, SpearheadGroup)
|
||||
|
||||
self._isStatic = Spearhead.DcsUtil.IsGroupStatic(groupName) == true
|
||||
self.groupName = groupName
|
||||
if isPersistent == nil then isPersistent = false end
|
||||
|
||||
self._spawnManager = spawnManager
|
||||
self._isStatic = spawnManager:IsGroupStatic(groupName) == true
|
||||
self._groupName = groupName
|
||||
self._isSpawned = false
|
||||
self._isPersistent = isPersistent
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function SpearheadGroup:GetName()
|
||||
return self._groupName
|
||||
end
|
||||
|
||||
function SpearheadGroup:IsSpawned()
|
||||
return self._isSpawned
|
||||
end
|
||||
@@ -25,27 +41,8 @@ end
|
||||
function SpearheadGroup:SpawnCorpsesOnly()
|
||||
|
||||
if self._isSpawned == true then return end
|
||||
|
||||
local group, isStatic = Spearhead.DcsUtil.SpawnGroupTemplate(self.groupName)
|
||||
if isStatic == true then
|
||||
self._isStatic = true
|
||||
local deathState = Spearhead.classes.persistence.Persistence.UnitDeadState(self.groupName)
|
||||
if deathState and deathState.isDead == true then
|
||||
Spearhead.DcsUtil.DestroyGroup(self.groupName)
|
||||
Spearhead.DcsUtil.SpawnCorpse(deathState.country_id, self.groupName, deathState.type, deathState.pos, deathState.heading)
|
||||
end
|
||||
else
|
||||
if group then
|
||||
for _, unit in pairs(group:getUnits()) do
|
||||
local deathState = Spearhead.classes.persistence.Persistence.UnitDeadState(unit:getName())
|
||||
Spearhead.DcsUtil.DestroyUnit(unit:getName())
|
||||
if deathState and deathState.isDead == true then
|
||||
Spearhead.DcsUtil.SpawnCorpse(deathState.country_id, unit:getName(), deathState.type, deathState.pos, deathState.heading)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
self._spawnManager:SpawnCorpsesOnly(self._groupName)
|
||||
self._isSpawned = true
|
||||
|
||||
end
|
||||
@@ -55,52 +52,19 @@ function SpearheadGroup:Spawn(lateStart)
|
||||
|
||||
if self._isSpawned == true then return end
|
||||
|
||||
local spawned, isStatic = Spearhead.DcsUtil.SpawnGroupTemplate(self.groupName, nil, nil, lateStart)
|
||||
if spawned and isStatic == false then
|
||||
for _, unit in pairs(spawned:getUnits()) do
|
||||
local deathState = Spearhead.classes.persistence.Persistence.UnitDeadState(unit:getName())
|
||||
|
||||
if deathState and deathState.isDead == true then
|
||||
Spearhead.DcsUtil.DestroyUnit(self.groupName, unit:getName())
|
||||
Spearhead.DcsUtil.SpawnCorpse(deathState.country_id, unit:getName(), deathState.type, deathState.pos, deathState.heading)
|
||||
else
|
||||
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self)
|
||||
end
|
||||
|
||||
Spearhead.Events.addOnUnitLostEventListener(unit:getName(), self)
|
||||
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
|
||||
---@type SpawnOverrides
|
||||
local overrides = {
|
||||
uncontrolled = lateStart or false,
|
||||
}
|
||||
|
||||
local spawnedObject, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
|
||||
self._isStatic = isStatic
|
||||
self._isSpawned = true
|
||||
end
|
||||
|
||||
function SpearheadGroup:Activate()
|
||||
|
||||
if self._isStatic == true then return end
|
||||
|
||||
local group = Group.getByName(self.groupName)
|
||||
if group then
|
||||
group:activate()
|
||||
|
||||
local controller = group:getController()
|
||||
if controller then
|
||||
controller:setCommand({
|
||||
id = 'Start',
|
||||
params = {}
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SpearheadGroup:Destroy()
|
||||
self._isSpawned = false
|
||||
Spearhead.DcsUtil.DestroyGroup(self.groupName)
|
||||
self._spawnManager:DestroyGroup(self._groupName)
|
||||
end
|
||||
|
||||
---@return boolean
|
||||
@@ -112,13 +76,13 @@ end
|
||||
---@return integer
|
||||
function SpearheadGroup:GetCoalition()
|
||||
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()
|
||||
else
|
||||
local group = Group.getByName(self.groupName)
|
||||
local group = Group.getByName(self._groupName)
|
||||
if group == nil then
|
||||
return 0
|
||||
end
|
||||
@@ -126,28 +90,18 @@ function SpearheadGroup:GetCoalition()
|
||||
end
|
||||
end
|
||||
|
||||
function SpearheadGroup:OnUnitLost(object)
|
||||
local name = object:getName()
|
||||
local pos = object:getPoint()
|
||||
local type = object:getDesc().typeName
|
||||
local position = object:getPosition()
|
||||
local heading = math.atan2(position.x.z, position.x.x)
|
||||
local country_id = object:getCountry()
|
||||
Spearhead.classes.persistence.Persistence.UnitKilled(name, pos, heading, type, country_id)
|
||||
end
|
||||
|
||||
---comment
|
||||
---@return table result list of objects
|
||||
function SpearheadGroup:GetObjects()
|
||||
|
||||
local result = {}
|
||||
if self._isStatic == true then
|
||||
local staticObject = StaticObject.getByName(self.groupName)
|
||||
local staticObject = StaticObject.getByName(self._groupName)
|
||||
if staticObject then
|
||||
table.insert(result, staticObject)
|
||||
end
|
||||
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
|
||||
table.insert(result, unit)
|
||||
@@ -165,7 +119,7 @@ function SpearheadGroup:GetAsUnits()
|
||||
end
|
||||
|
||||
local result = {}
|
||||
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
|
||||
table.insert(result, unit)
|
||||
@@ -178,12 +132,12 @@ function SpearheadGroup:GetAllUnitPositions()
|
||||
|
||||
local result = {}
|
||||
if self._isStatic == true then
|
||||
local staticObject = StaticObject.getByName(self.groupName)
|
||||
local staticObject = StaticObject.getByName(self._groupName)
|
||||
if staticObject then
|
||||
table.insert(result, staticObject:getPoint())
|
||||
end
|
||||
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
|
||||
table.insert(result, unit:getPoint())
|
||||
@@ -196,9 +150,15 @@ function SpearheadGroup:SetInvisible()
|
||||
|
||||
if self._isStatic == true then
|
||||
local country = Spearhead.DcsUtil.GetNeutralCountry()
|
||||
Spearhead.DcsUtil.SpawnGroupTemplate(self.groupName, nil, nil, nil, country)
|
||||
|
||||
---@type SpawnOverrides
|
||||
local overrides = {
|
||||
countryID = country
|
||||
}
|
||||
|
||||
self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
|
||||
else
|
||||
local group = Group.getByName(self.groupName)
|
||||
local group = Group.getByName(self._groupName)
|
||||
if group then
|
||||
local setInvisible = {
|
||||
id = 'SetInvisible',
|
||||
@@ -215,7 +175,7 @@ end
|
||||
|
||||
function SpearheadGroup:SetVisible()
|
||||
|
||||
local group = Group.getByName(self.groupName)
|
||||
local group = Group.getByName(self._groupName)
|
||||
if group then
|
||||
local setInvisible = {
|
||||
id = 'SetInvisible',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
---@class BlueSam : OnCrateDroppedListener, MissionCompleteListener
|
||||
---@class BlueSam : BuildableZone
|
||||
---@field Activate fun(self: BlueSam)
|
||||
---@field private _database Database
|
||||
---@field private _logger Logger
|
||||
@@ -11,13 +11,16 @@
|
||||
---@field private _unitsPerCrate number?
|
||||
---@field private _buildableMission BuildableMission?
|
||||
local BlueSam = {}
|
||||
BlueSam.__index = BlueSam
|
||||
|
||||
---@param database Database
|
||||
---@param logger Logger
|
||||
---@param zoneName string
|
||||
---@param spawnManager SpawnManager
|
||||
---@return BlueSam?
|
||||
function BlueSam.New(database, logger, zoneName)
|
||||
BlueSam.__index = BlueSam
|
||||
function BlueSam.New(database, logger, zoneName, spawnManager)
|
||||
|
||||
setmetatable(BlueSam, Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone)
|
||||
local self = setmetatable({}, BlueSam)
|
||||
|
||||
self._database = database
|
||||
@@ -44,15 +47,19 @@ function BlueSam.New(database, logger, zoneName)
|
||||
local redUnitsPos = {}
|
||||
|
||||
|
||||
local buildable = false
|
||||
if self._buildableCrateKilos and self._buildableCrateKilos > 0 then
|
||||
buildable = true
|
||||
end
|
||||
|
||||
for _, groupName in pairs(blueSamData.groups) do
|
||||
local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName)
|
||||
local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName, spawnManager, true)
|
||||
if SpearheadGroup then
|
||||
|
||||
if SpearheadGroup:GetCoalition() == 2 then
|
||||
if SpearheadGroup:GetCoalition() == 2 or SpearheadGroup:GetCoalition() == 0 then
|
||||
table.insert(self._blueGroups, SpearheadGroup)
|
||||
end
|
||||
|
||||
|
||||
for _, unit in pairs(SpearheadGroup:GetObjects()) do
|
||||
if SpearheadGroup:GetCoalition() == 1 then
|
||||
table.insert(blueUnitsPos, unit:getPoint())
|
||||
@@ -76,21 +83,11 @@ function BlueSam.New(database, logger, zoneName)
|
||||
end
|
||||
end
|
||||
|
||||
if self._buildableCrateKilos ~= nil and self._buildableCrateKilos ~= 0 then
|
||||
self._logger:debug("Buildable mission creating for zone: " .. zoneName .. " with crates: " .. self._buildableCrateKilos)
|
||||
|
||||
local noLandingZone = self:GetNoLandingZone()
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(zoneName)
|
||||
if zone then
|
||||
self._buildableMission = Spearhead.classes.stageClasses.missions.BuildableMission.new(database, logger, zone, noLandingZone, self._buildableCrateKilos, "SAM_CRATE")
|
||||
self._buildableMission:AddOnCrateDroppedOfListener(self)
|
||||
self._buildableMission:AddMissionCompleteListener(self)
|
||||
end
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(zoneName)
|
||||
if zone then
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone.New(self, zone, self._buildableCrateKilos or 0, "SAM_CRATE", self._blueGroups, logger, database)
|
||||
end
|
||||
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -132,21 +129,14 @@ function BlueSam:Activate()
|
||||
if self._buildableMission == nil then
|
||||
self:SpawnGroups()
|
||||
else
|
||||
self._buildableMission:SpawnActive()
|
||||
self:StartBuildable()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function BlueSam:SpawnGroups()
|
||||
for unitName, needsCleanup in pairs(self._cleanupUnits) do
|
||||
if needsCleanup == true then
|
||||
Spearhead.DcsUtil.DestroyUnit(unitName)
|
||||
else
|
||||
local deathState = Spearhead.classes.persistence.Persistence.UnitDeadState(unitName)
|
||||
if deathState and deathState.isDead == true then
|
||||
Spearhead.DcsUtil.SpawnCorpse(deathState.country_id, unitName, deathState.type, deathState.pos, deathState.heading)
|
||||
end
|
||||
end
|
||||
Spearhead.DcsUtil.DestroyUnit(unitName)
|
||||
end
|
||||
|
||||
for _, group in pairs(self._blueGroups) do
|
||||
@@ -154,25 +144,12 @@ function BlueSam:SpawnGroups()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param buildableMission BuildableMission
|
||||
---@param kilos number
|
||||
function BlueSam:OnCrateDroppedOff(buildableMission, kilos)
|
||||
|
||||
self._logger:debug("Crate dropped off in zone: " .. self._zoneName)
|
||||
self._receivedKilos = self._receivedKilos + kilos
|
||||
|
||||
end
|
||||
|
||||
---@param buildableMission Mission
|
||||
function BlueSam:OnMissionComplete(buildableMission)
|
||||
self._logger:debug("Buildable mission complete for zone: " .. self._zoneName)
|
||||
|
||||
function BlueSam:OnBuildingComplete()
|
||||
self:SpawnGroups()
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
|
||||
|
||||
---@class FarpZone : OnCrateDroppedListener, MissionCompleteListener
|
||||
---@class FarpZone: BuildableZone
|
||||
---@field private _startingFarp boolean
|
||||
---@field private _groups Array<SpearheadGroup>
|
||||
---@field private _padNames Array<string>
|
||||
---@field private _database Database
|
||||
---@field private _logger Logger
|
||||
---@field private _zoneName string
|
||||
---@field private _requiredBuildingKilos number
|
||||
---@field private _receivedBuildingKilos number
|
||||
---@field private _groupsPerKilo number
|
||||
---@field private _buildableMission BuildableMission?
|
||||
---@field private _supplyHubs Array<SupplyHub>
|
||||
local FarpZone = {}
|
||||
FarpZone.__index = FarpZone
|
||||
@@ -19,10 +15,10 @@ FarpZone.__index = FarpZone
|
||||
---@param database Database
|
||||
---@param logger Logger
|
||||
---@param zoneName string
|
||||
---@param spawnManager SpawnManager
|
||||
---@return FarpZone
|
||||
function FarpZone.New(database, logger, zoneName)
|
||||
|
||||
FarpZone.__index = FarpZone
|
||||
function FarpZone.New(database, logger, zoneName, spawnManager)
|
||||
setmetatable(FarpZone, Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone)
|
||||
local self = setmetatable({}, FarpZone)
|
||||
|
||||
self._database = database
|
||||
@@ -54,34 +50,18 @@ function FarpZone.New(database, logger, zoneName)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
for _, groupName in pairs(farpData.groups) do
|
||||
local group = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName)
|
||||
local group = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName, spawnManager, true)
|
||||
table.insert(self._groups, group)
|
||||
group:Destroy()
|
||||
end
|
||||
|
||||
self._requiredBuildingKilos = farpData.buildingKilos
|
||||
self._receivedBuildingKilos = 0
|
||||
|
||||
if self._requiredBuildingKilos ~= nil and self._requiredBuildingKilos > 0 then
|
||||
self._logger:debug("FARP zone " .. zoneName .. " requires " .. self._requiredBuildingKilos .. " crates to be dropped off")
|
||||
local noLandingZone = self:GetNoLandingZone()
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(zoneName)
|
||||
if zone then
|
||||
self._buildableMission = Spearhead.classes.stageClasses.missions.BuildableMission.new(database, logger, zone, noLandingZone, self._requiredBuildingKilos, "FARP_CRATE")
|
||||
if self._buildableMission then
|
||||
self._buildableMission:AddOnCrateDroppedOfListener(self)
|
||||
self._buildableMission:AddMissionCompleteListener(self)
|
||||
end
|
||||
|
||||
local totalGroups = Spearhead.Util.tableLength(self._groups)
|
||||
self._groupsPerKilo = totalGroups / self._requiredBuildingKilos
|
||||
end
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(zoneName)
|
||||
if zone then
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone.New(self, zone, farpData.buildingKilos or 0, "FARP_CRATE", self._groups, logger, database)
|
||||
end
|
||||
end
|
||||
if self._buildableMission == nil then
|
||||
self._logger:debug("No buildable mission for zone: " .. zoneName)
|
||||
end
|
||||
self:Deactivate()
|
||||
|
||||
return self
|
||||
@@ -101,7 +81,7 @@ function FarpZone:Activate()
|
||||
self:SetPadsBlue()
|
||||
self:ActivateSupplyHubs()
|
||||
else
|
||||
self._buildableMission:SpawnActive()
|
||||
self:StartBuildable()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -109,101 +89,13 @@ function FarpZone:Deactivate()
|
||||
self:NeutralisePads()
|
||||
end
|
||||
|
||||
---@class UnpackCrateParam
|
||||
---@field self FarpZone
|
||||
---@field kilos number
|
||||
---@field groupsPerKilo number
|
||||
---@field kilosPerSecond number
|
||||
---@field unpackedItems number
|
||||
---@field unpackedKilos number
|
||||
|
||||
---@param params UnpackCrateParam
|
||||
---@param time number
|
||||
local startUnpackingCrate = function(params, time)
|
||||
local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2)
|
||||
local alreadySpawned = params.unpackedItems / params.groupsPerKilo
|
||||
local diff = unpacked - alreadySpawned
|
||||
|
||||
local amount = math.floor(diff * params.groupsPerKilo)
|
||||
local spawned = params.self:SpawnAmount(amount)
|
||||
|
||||
params.unpackedItems = params.unpackedItems + amount
|
||||
params.unpackedKilos = unpacked
|
||||
if params.unpackedKilos >= params.kilos or spawned == false then
|
||||
params.self:FinaliseCrate(params.kilos)
|
||||
return
|
||||
end
|
||||
|
||||
return time + 2
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param amount number
|
||||
---@return boolean
|
||||
function FarpZone:SpawnAmount(amount)
|
||||
|
||||
local function spawnOne()
|
||||
for _, group in pairs(self._groups) do
|
||||
if group:IsSpawned() == false then
|
||||
group:Spawn()
|
||||
return true
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
for i = 1, amount do
|
||||
local spawned = spawnOne()
|
||||
if spawned ~= true then
|
||||
self._logger:debug("No more groups to spawn in zone: " .. self._zoneName)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---@param buildableMission BuildableMission
|
||||
function FarpZone:OnCrateDroppedOff(buildableMission, kilos)
|
||||
|
||||
self._logger:debug("Crate dropped off in zone: " .. self._zoneName)
|
||||
|
||||
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)
|
||||
|
||||
end
|
||||
|
||||
---@param kilos number
|
||||
function FarpZone:FinaliseCrate(kilos)
|
||||
self._receivedBuildingKilos = self._receivedBuildingKilos + kilos
|
||||
if self._receivedBuildingKilos >= self._requiredBuildingKilos then
|
||||
self:BuildUp()
|
||||
self:SetPadsBlue()
|
||||
self:ActivateSupplyHubs()
|
||||
end
|
||||
end
|
||||
|
||||
---@param buildableMission Mission
|
||||
function FarpZone:OnMissionComplete(buildableMission)
|
||||
self._logger:debug("Buildable mission complete for zone: " .. self._zoneName)
|
||||
|
||||
-- self:BuildUp()
|
||||
-- self:SetPadsBlue()
|
||||
-- self:ActivateSupplyHubs()
|
||||
|
||||
function FarpZone:OnBuildingComplete()
|
||||
self:BuildUp()
|
||||
self:SetPadsBlue()
|
||||
self:ActivateSupplyHubs()
|
||||
end
|
||||
|
||||
---@private
|
||||
function FarpZone:BuildUp()
|
||||
for _, group in pairs(self._groups) do
|
||||
group:Spawn()
|
||||
@@ -239,40 +131,6 @@ function FarpZone:SetPadsBlue()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@private
|
||||
---@return SpearheadTriggerZone?
|
||||
function FarpZone:GetNoLandingZone()
|
||||
|
||||
---@type Array<Vec2>
|
||||
local points = {}
|
||||
|
||||
for _, group in pairs(self._groups) do
|
||||
for _, unitPos in pairs(group:GetAllUnitPositions()) do
|
||||
table.insert(points, { x = unitPos.x, y = unitPos.z })
|
||||
end
|
||||
end
|
||||
|
||||
local vecs = Spearhead.Util.getConvexHull(points)
|
||||
|
||||
local zone = Spearhead.DcsUtil.getZoneByName(self._zoneName)
|
||||
if zone == nil then
|
||||
self._logger:error("Zone not found: " .. self._zoneName)
|
||||
return nil
|
||||
end
|
||||
|
||||
---@type SpearheadTriggerZone
|
||||
local spearheadZone = {
|
||||
name = self._zoneName .. "_noland",
|
||||
location = zone.location,
|
||||
verts = vecs,
|
||||
radius = 0,
|
||||
zone_type = "Polygon"
|
||||
}
|
||||
|
||||
return spearheadZone
|
||||
end
|
||||
|
||||
if Spearhead == nil then Spearhead = {} end
|
||||
if Spearhead.classes == nil then Spearhead.classes = {} end
|
||||
if Spearhead.classes.stageClasses == nil then Spearhead.classes.stageClasses = {} end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
---@class StageBase : OnCrateDroppedListener, MissionCompleteListener
|
||||
---@class StageBase : BuildableZone
|
||||
---@field private _database Database
|
||||
---@field private _logger Logger
|
||||
---@field private _red_groups Array<SpearheadGroup>
|
||||
@@ -12,14 +12,16 @@
|
||||
---@field private _receivedBuildingKilos number
|
||||
---@field private _buildableMission BuildableMission?
|
||||
local StageBase = {}
|
||||
StageBase.__index = StageBase
|
||||
|
||||
---comment
|
||||
---@param databaseManager Database
|
||||
---@param logger table
|
||||
---@param airbaseName string
|
||||
---@param spawnManager SpawnManager
|
||||
---@return StageBase?
|
||||
function StageBase.New(databaseManager, logger, airbaseName)
|
||||
StageBase.__index = StageBase
|
||||
function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
setmetatable(StageBase, Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone)
|
||||
local self = setmetatable({}, StageBase)
|
||||
|
||||
self._database = databaseManager
|
||||
@@ -47,7 +49,7 @@ function StageBase.New(databaseManager, logger, airbaseName)
|
||||
local blueUnitsPos = {}
|
||||
|
||||
for _, groupName in pairs(airbaseData.RedGroups) do
|
||||
local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName)
|
||||
local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName, spawnManager, true)
|
||||
table.insert(self._red_groups, shGroup)
|
||||
|
||||
for _, unit in pairs(shGroup:GetObjects()) do
|
||||
@@ -58,7 +60,7 @@ function StageBase.New(databaseManager, logger, airbaseName)
|
||||
end
|
||||
|
||||
for _, groupName in pairs(airbaseData.BlueGroups) do
|
||||
local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName)
|
||||
local shGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup.New(groupName, spawnManager, true)
|
||||
table.insert(self._blue_groups, shGroup)
|
||||
|
||||
for _, unit in pairs(shGroup:GetObjects()) do
|
||||
@@ -92,22 +94,9 @@ function StageBase.New(databaseManager, logger, airbaseName)
|
||||
end
|
||||
end
|
||||
|
||||
if airbaseData.buildingKilos ~= nil and airbaseData.buildingKilos > 0 then
|
||||
self._logger:debug("Airbase " .. airbaseName .. " requires " .. tostring(airbaseData.buildingKilos) .. " kilos to be dropped off")
|
||||
self._requiredBuildingKilos = airbaseData.buildingKilos
|
||||
self._receivedBuildingKilos = 0
|
||||
self._groupsPerKilo = Spearhead.Util.tableLength(self._blue_groups) / self._requiredBuildingKilos
|
||||
local zone = Spearhead.DcsUtil.getAirbaseZoneByName(airbaseName)
|
||||
if zone then
|
||||
self._buildableMission = Spearhead.classes.stageClasses.missions.BuildableMission.new(databaseManager, logger, zone, self:GetNoLandingZone(), self._requiredBuildingKilos, "AIRBASE_CRATE")
|
||||
end
|
||||
|
||||
|
||||
if self._buildableMission then
|
||||
self._buildableMission:AddOnCrateDroppedOfListener(self)
|
||||
else
|
||||
self._logger:error("Failed to create buildable mission for airbase: " .. airbaseName)
|
||||
end
|
||||
local zone = Spearhead.DcsUtil.getAirbaseZoneByName(airbaseName)
|
||||
if zone then
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone.New(self, zone, airbaseData.buildingKilos or 0, "AIRBASE_CRATE", self._blue_groups, logger, databaseManager)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -172,11 +161,12 @@ function StageBase:ActivateBlueStage()
|
||||
|
||||
self:CleanRedUnits()
|
||||
|
||||
if self._buildableMission and self._buildableMission:getState() ~= "COMPLETED" then
|
||||
self._buildableMission:SpawnActive()
|
||||
return
|
||||
if self._buildableMission then
|
||||
self:StartBuildable()
|
||||
else
|
||||
self:FinaliseBlueStage()
|
||||
end
|
||||
self:FinaliseBlueStage()
|
||||
|
||||
end
|
||||
|
||||
function StageBase:FinaliseBlueStage()
|
||||
@@ -192,119 +182,9 @@ function StageBase:FinaliseBlueStage()
|
||||
end
|
||||
end
|
||||
|
||||
do ---Building parts
|
||||
---@class UnpackAirbaseCrateParam
|
||||
---@field self StageBase
|
||||
---@field kilos number
|
||||
---@field groupsPerKilo number
|
||||
---@field kilosPerSecond number
|
||||
---@field unpackedItems number
|
||||
---@field unpackedKilos number
|
||||
|
||||
---@param params UnpackAirbaseCrateParam
|
||||
---@param time number
|
||||
local startUnpackingCrate = function(params, time)
|
||||
local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2)
|
||||
local alreadySpawned = params.unpackedItems / params.groupsPerKilo
|
||||
local diff = unpacked - alreadySpawned
|
||||
|
||||
local amount = math.floor(diff * params.groupsPerKilo)
|
||||
local spawned = params.self:SpawnAmount(amount)
|
||||
|
||||
params.unpackedItems = params.unpackedItems + amount
|
||||
params.unpackedKilos = unpacked
|
||||
if params.unpackedKilos >= params.kilos or spawned == false then
|
||||
params.self:FinaliseCrate(params.kilos)
|
||||
return
|
||||
end
|
||||
|
||||
return time + 2
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param amount number
|
||||
---@return boolean
|
||||
function StageBase:SpawnAmount(amount)
|
||||
local function spawnOne()
|
||||
for _, group in pairs(self._blue_groups) do
|
||||
if group:IsSpawned() == false then
|
||||
group:Spawn()
|
||||
return true
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
for i = 1, amount do
|
||||
local spawned = spawnOne()
|
||||
if spawned ~= true then
|
||||
self._logger:debug("No more groups to spawn at base: " .. self._airbase:getName())
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---@param buildableMission BuildableMission
|
||||
function StageBase:OnCrateDroppedOff(buildableMission, kilos)
|
||||
self._logger:debug("Crate dropped off at base: " .. self._airbase:getName())
|
||||
|
||||
local timeToUnpack = (kilos / 500) * 30
|
||||
|
||||
---@type UnpackAirbaseCrateParam
|
||||
local params = {
|
||||
self = self,
|
||||
groupsPerKilo = self._groupsPerKilo,
|
||||
unpackedItems = 0,
|
||||
kilosPerSecond = kilos / timeToUnpack,
|
||||
unpackedKilos = 0,
|
||||
kilos = kilos
|
||||
}
|
||||
|
||||
timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 2)
|
||||
end
|
||||
|
||||
---@private
|
||||
---@return SpearheadTriggerZone?
|
||||
function StageBase:GetNoLandingZone()
|
||||
---@type Array<Vec2>
|
||||
local points = {}
|
||||
|
||||
for _, group in pairs(self._blue_groups) do
|
||||
for _, unitPos in pairs(group:GetAllUnitPositions()) do
|
||||
table.insert(points, { x = unitPos.x, y = unitPos.z })
|
||||
end
|
||||
end
|
||||
|
||||
local vecs = Spearhead.Util.getConvexHull(points)
|
||||
|
||||
local pos = self._airbase:getPoint()
|
||||
local location = {
|
||||
x = pos.x,
|
||||
y = pos.z
|
||||
}
|
||||
|
||||
---@type SpearheadTriggerZone
|
||||
local spearheadZone = {
|
||||
name = self._airbase:getName() .. "_noland",
|
||||
location = location,
|
||||
verts = vecs,
|
||||
radius = 0,
|
||||
zone_type = "Polygon"
|
||||
}
|
||||
|
||||
return spearheadZone
|
||||
end
|
||||
|
||||
|
||||
---@param kilos number
|
||||
function StageBase:FinaliseCrate(kilos)
|
||||
self._receivedBuildingKilos = self._receivedBuildingKilos + kilos
|
||||
if self._receivedBuildingKilos >= self._requiredBuildingKilos then
|
||||
self:FinaliseBlueStage()
|
||||
end
|
||||
end
|
||||
function StageBase:OnBuildingComplete()
|
||||
self:FinaliseBlueStage()
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
|
||||
---@class BuildableZone : OnCrateDroppedListener
|
||||
---@field protected _targetZone SpearheadTriggerZone
|
||||
---@field protected _requiredKilos number
|
||||
---@field protected _buildableMission BuildableMission?
|
||||
---@field protected _buildableGroups Array<SpearheadGroup>
|
||||
---@field private _groupsPerKilo number
|
||||
---@field private _receivedBuildingKilos number
|
||||
---@field private _buildableLogger Logger
|
||||
---@field protected OnBuildingComplete fun(self:BuildableZone)
|
||||
local BuildableZone = {}
|
||||
BuildableZone.__index = BuildableZone
|
||||
|
||||
---@param targetZone SpearheadTriggerZone
|
||||
---@param kilosRequired number
|
||||
---@param buildableGroups Array<SpearheadGroup>
|
||||
---@param database Database
|
||||
---@param crateType SupplyType
|
||||
---@param logger Logger
|
||||
function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroups, logger, database)
|
||||
self._targetZone = targetZone
|
||||
self._requiredKilos = kilosRequired or 0
|
||||
self._buildableGroups = buildableGroups or {}
|
||||
self._buildableLogger = logger
|
||||
local totalGroups = Spearhead.Util.tableLength(self._buildableGroups)
|
||||
self._groupsPerKilo = totalGroups / self._requiredKilos
|
||||
|
||||
self._receivedBuildingKilos = 0
|
||||
local persistedKilos = Spearhead.classes.persistence.Persistence.GetZoneDeliveredKilos(targetZone.name)
|
||||
if persistedKilos and persistedKilos > 0 then
|
||||
self._receivedBuildingKilos = persistedKilos
|
||||
|
||||
---@param params UnpackCrateParam
|
||||
---@param time number
|
||||
local startUnpackingCrate = function(params, time)
|
||||
local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2)
|
||||
local alreadySpawned = params.unpackedItems / params.groupsPerKilo
|
||||
local diff = unpacked - alreadySpawned
|
||||
|
||||
local amount = math.floor(diff * params.groupsPerKilo)
|
||||
local spawned = params.self:SpawnAmount(amount)
|
||||
|
||||
params.unpackedItems = params.unpackedItems + amount
|
||||
params.unpackedKilos = unpacked
|
||||
if params.unpackedKilos >= params.kilos or spawned == false then
|
||||
return
|
||||
end
|
||||
|
||||
return time + 0.5
|
||||
end
|
||||
|
||||
---@type UnpackCrateParam
|
||||
local params = {
|
||||
self = self,
|
||||
groupsPerKilo = self._groupsPerKilo,
|
||||
unpackedItems = 0,
|
||||
kilosPerSecond = persistedKilos/30,
|
||||
unpackedKilos = 0,
|
||||
kilos = persistedKilos
|
||||
}
|
||||
|
||||
timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 5)
|
||||
kilosRequired = kilosRequired - persistedKilos
|
||||
end
|
||||
|
||||
local noLandingZone = self:GetNoLandingZone()
|
||||
if kilosRequired and kilosRequired > 0 then
|
||||
self._buildableMission = Spearhead.classes.stageClasses.missions.BuildableMission.new(database, logger, targetZone, noLandingZone, kilosRequired, crateType)
|
||||
self._buildableMission:AddOnCrateDroppedOfListener(self)
|
||||
else
|
||||
self._buildableMission = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
if self._buildableMission == nil then
|
||||
self._buildableLogger:debug("No buildable mission for zone: " .. targetZone.name)
|
||||
end
|
||||
end
|
||||
|
||||
---@protected
|
||||
function BuildableZone:StartBuildable()
|
||||
self._buildableMission:SpawnActive()
|
||||
end
|
||||
|
||||
---@protected
|
||||
function BuildableZone:OnBuildingComplete() end
|
||||
|
||||
---@class UnpackCrateParam
|
||||
---@field self BuildableZone
|
||||
---@field kilos number
|
||||
---@field groupsPerKilo number
|
||||
---@field kilosPerSecond number
|
||||
---@field unpackedItems number
|
||||
---@field unpackedKilos number
|
||||
|
||||
---@param mission BuildableMission?
|
||||
---@param kilos number
|
||||
function BuildableZone:OnCrateDroppedOff(mission, kilos)
|
||||
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 time number
|
||||
local startUnpackingCrate = function(params, time)
|
||||
local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2)
|
||||
local alreadySpawned = params.unpackedItems / params.groupsPerKilo
|
||||
local diff = unpacked - alreadySpawned
|
||||
|
||||
local amount = math.floor(diff * params.groupsPerKilo)
|
||||
local spawned = params.self:SpawnAmount(amount)
|
||||
|
||||
params.unpackedItems = params.unpackedItems + amount
|
||||
params.unpackedKilos = unpacked
|
||||
if params.unpackedKilos >= params.kilos or spawned == false then
|
||||
params.self:FinaliseCrate(params.kilos)
|
||||
return
|
||||
end
|
||||
|
||||
return time + 2
|
||||
end
|
||||
|
||||
timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 2)
|
||||
end
|
||||
|
||||
---@param kilos number
|
||||
function BuildableZone:FinaliseCrate(kilos)
|
||||
self._receivedBuildingKilos = self._receivedBuildingKilos + kilos
|
||||
Spearhead.classes.persistence.Persistence.SetZoneDeliveredKilos(self._targetZone.name, self._receivedBuildingKilos)
|
||||
if self._receivedBuildingKilos >= self._requiredKilos then
|
||||
self:OnBuildingComplete()
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
---@return SpearheadTriggerZone?
|
||||
function BuildableZone:GetNoLandingZone()
|
||||
|
||||
---@type Array<Vec2>
|
||||
local points = {}
|
||||
|
||||
for _, group in pairs(self._buildableGroups) do
|
||||
for _, unitPos in pairs(group:GetAllUnitPositions()) do
|
||||
table.insert(points, { x = unitPos.x, y = unitPos.z })
|
||||
end
|
||||
end
|
||||
|
||||
local vecs = Spearhead.Util.getConvexHull(points)
|
||||
|
||||
---@type SpearheadTriggerZone
|
||||
local spearheadZone = {
|
||||
name = self._targetZone.name .. "_noland",
|
||||
location = self._targetZone.location,
|
||||
verts = vecs,
|
||||
radius = 0,
|
||||
zone_type = "Polygon"
|
||||
}
|
||||
|
||||
return spearheadZone
|
||||
end
|
||||
|
||||
|
||||
---comment
|
||||
---@param amount number
|
||||
---@return boolean
|
||||
function BuildableZone:SpawnAmount(amount)
|
||||
local function spawnOne()
|
||||
for _, group in pairs(self._buildableGroups) do
|
||||
if group:IsSpawned() == false then
|
||||
group:Spawn()
|
||||
return true
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
for i = 1, amount do
|
||||
local spawned = spawnOne()
|
||||
if spawned ~= true then
|
||||
self._buildableLogger:debug("No more groups to spawn in zone: " .. self._targetZone.name)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if not Spearhead then Spearhead = {} end
|
||||
Spearhead.classes = Spearhead.classes or {}
|
||||
Spearhead.classes.stageClasses = Spearhead.classes.stageClasses or {}
|
||||
Spearhead.classes.stageClasses.SpecialZones = Spearhead.classes.stageClasses.SpecialZones or {}
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract = Spearhead.classes.stageClasses.SpecialZones.abstract or {}
|
||||
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone = BuildableZone
|
||||
@@ -63,8 +63,9 @@ Stage.StageColors = {
|
||||
---@param logger Logger
|
||||
---@param initData StageInitData
|
||||
---@param missionPriority MissionPriority
|
||||
---@param spawnManager SpawnManager
|
||||
---@return Stage
|
||||
function Stage:superNew(database, stageConfig, logger, initData, missionPriority)
|
||||
function Stage:superNew(database, stageConfig, logger, initData, missionPriority, spawnManager)
|
||||
|
||||
logger:debug("[BaseStage] Initiating stage with name: " .. initData.stageZoneName)
|
||||
|
||||
@@ -109,7 +110,7 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
|
||||
local farpNames = database:getFarpNamesInStage(self.zoneName)
|
||||
for _, farpName in pairs(farpNames) do
|
||||
local farp = Spearhead.classes.stageClasses.SpecialZones.FarpZone.New(database, logger, farpName)
|
||||
local farp = Spearhead.classes.stageClasses.SpecialZones.FarpZone.New(database, logger, farpName, spawnManager)
|
||||
table.insert(self._db.farps, farp)
|
||||
end
|
||||
|
||||
@@ -141,7 +142,7 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
self._logger:debug("Found " .. Spearhead.Util.tableLength(missionZones) .. " mission zones for stage: " .. self.zoneName)
|
||||
for _, missionZone in pairs(missionZones) do
|
||||
|
||||
local mission = Spearhead.classes.stageClasses.missions.ZoneMission.new(missionZone, self._missionPriority, database, logger, self)
|
||||
local mission = Spearhead.classes.stageClasses.missions.ZoneMission.new(missionZone, self._missionPriority, database, logger, self, spawnManager)
|
||||
if mission then
|
||||
self._db.missionsByCode[mission.code] = mission
|
||||
|
||||
@@ -164,7 +165,7 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
---@type table<string, Array<Mission>>
|
||||
local randomMissionByName = {}
|
||||
for _, missionZoneName in pairs(randomMissionNames) do
|
||||
local mission = Spearhead.classes.stageClasses.missions.ZoneMission.new(missionZoneName, self._missionPriority, database, logger, self)
|
||||
local mission = Spearhead.classes.stageClasses.missions.ZoneMission.new(missionZoneName, self._missionPriority, database, logger, self, spawnManager)
|
||||
if mission then
|
||||
if randomMissionByName[mission.name] == nil then
|
||||
randomMissionByName[mission.name] = {}
|
||||
@@ -217,22 +218,22 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
|
||||
local airbaseNames = database:getAirbaseNamesInStage(self.zoneName)
|
||||
if airbaseNames ~= nil and type(airbaseNames) == "table" then
|
||||
for _, airbaseName in pairs(airbaseNames) do
|
||||
local airbase = Spearhead.classes.stageClasses.SpecialZones.StageBase.New(database, logger, airbaseName)
|
||||
local airbase = Spearhead.classes.stageClasses.SpecialZones.StageBase.New(database, logger, airbaseName, spawnManager)
|
||||
table.insert(self._db.airbases, airbase)
|
||||
end
|
||||
end
|
||||
|
||||
for _, samZoneName in pairs(database:getBlueSamsInStage(self.zoneName)) do
|
||||
local blueSam = Spearhead.classes.stageClasses.SpecialZones.BlueSam.New(database, logger, samZoneName)
|
||||
local blueSam = Spearhead.classes.stageClasses.SpecialZones.BlueSam.New(database, logger, samZoneName, spawnManager)
|
||||
table.insert(self._db.blueSams, blueSam)
|
||||
end
|
||||
|
||||
local miscGroups = database:getMiscGroupsAtStage(self.zoneName)
|
||||
for _, groupName in pairs(miscGroups) do
|
||||
local miscGroup = SpearheadGroup.New(groupName)
|
||||
local miscGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
|
||||
table.insert(self._db.miscGroups, miscGroup)
|
||||
Spearhead.DcsUtil.DestroyGroup(groupName)
|
||||
miscGroup:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -9,14 +9,15 @@ ExtraStage.__index = ExtraStage
|
||||
---@param stageConfig StageConfig
|
||||
---@param logger any
|
||||
---@param initData StageInitData
|
||||
---@param spawnManager SpawnManager
|
||||
---@return ExtraStage
|
||||
function ExtraStage.New(database, stageConfig, logger, initData)
|
||||
function ExtraStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||
|
||||
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
|
||||
setmetatable(ExtraStage, Stage)
|
||||
|
||||
local self = setmetatable({}, { __index = ExtraStage }) --[[@as ExtraStage]]
|
||||
self:superNew(database, stageConfig, logger, initData, "secondary")
|
||||
self:superNew(database, stageConfig, logger, initData, "secondary", spawnManager)
|
||||
|
||||
self.OnPostBlueActivated = function (selfStage)
|
||||
|
||||
|
||||
@@ -9,14 +9,15 @@ PrimaryStage.__index = PrimaryStage
|
||||
---@param stageConfig StageConfig
|
||||
---@param logger any
|
||||
---@param initData StageInitData
|
||||
---@param spawnManager SpawnManager
|
||||
---@return PrimaryStage
|
||||
function PrimaryStage.New(database, stageConfig, logger, initData)
|
||||
function PrimaryStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||
|
||||
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
|
||||
setmetatable(PrimaryStage, Stage)
|
||||
|
||||
local self = setmetatable({}, { __index = PrimaryStage }) --[[@as PrimaryStage]]
|
||||
self:superNew(database, stageConfig, logger, initData, "primary")
|
||||
self:superNew(database, stageConfig, logger, initData, "primary", spawnManager)
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
@@ -15,14 +15,15 @@ local WaitingStageInitData = {}
|
||||
---@param stageConfig StageConfig
|
||||
---@param logger any
|
||||
---@param initData WaitingStageInitData
|
||||
---@param spawnManager SpawnManager
|
||||
---@return WaitingStage
|
||||
function WaitingStage.New(database, stageConfig, logger, initData)
|
||||
function WaitingStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||
|
||||
local Stage = Spearhead.classes.stageClasses.Stages.BaseStage.Stage
|
||||
setmetatable(WaitingStage, Stage)
|
||||
|
||||
local self = setmetatable({}, { __index = WaitingStage }) --[[@as WaitingStage]]
|
||||
self:superNew(database, stageConfig, logger, initData, "none")
|
||||
self:superNew(database, stageConfig, logger, initData, "none", spawnManager)
|
||||
|
||||
self._waitTimeSeconds = 5
|
||||
if initData.waitingSeconds and initData.waitingSeconds > 5 then self._waitTimeSeconds = initData.waitingSeconds end
|
||||
|
||||
@@ -155,7 +155,7 @@ function BuildableMission:SpawnActive()
|
||||
self._logger:debug("Spawning buildable mission: " .. self.code)
|
||||
|
||||
if self._noLandingZone == nil then
|
||||
self._logger:error("No no landing zone found for mission: " .. self.code)
|
||||
self._logger:error("No nolanding zone found for mission: " .. self.code)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -65,8 +65,9 @@ MINIMAL_UNITS_ALIVE_RATIO = 0.21
|
||||
---@param database Database
|
||||
---@param logger Logger
|
||||
---@param parentStage Stage
|
||||
---@param spawnManager SpawnManager
|
||||
---@return ZoneMission?
|
||||
function ZoneMission.new(zoneName, priority, database, logger, parentStage)
|
||||
function ZoneMission.new(zoneName, priority, database, logger, parentStage, spawnManager)
|
||||
local Mission = Spearhead.classes.stageClasses.missions.baseMissions.Mission
|
||||
ZoneMission.__index = ZoneMission
|
||||
setmetatable(ZoneMission, Mission)
|
||||
@@ -128,7 +129,7 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage)
|
||||
if not missionData then return end
|
||||
|
||||
for _, groupName in pairs(missionData.BlueGroups) do
|
||||
local spearheadGroup = SpearheadGroup.New(groupName)
|
||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
if spearheadGroup then
|
||||
table.insert(self._missionGroups.blueGroups, spearheadGroup)
|
||||
end
|
||||
@@ -136,7 +137,7 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage)
|
||||
end
|
||||
|
||||
for _, groupName in pairs(missionData.RedGroups) do
|
||||
local spearheadGroup = SpearheadGroup.New(groupName)
|
||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
table.insert(self._missionGroups.redGroups, spearheadGroup)
|
||||
|
||||
local isGroupTarget = Spearhead.Util.startswith(string.lower(groupName), "tgt_")
|
||||
|
||||
+3
-3
@@ -86,9 +86,9 @@ SpearheadConfig = {
|
||||
--- enables or disables the persistence logic in spearhead
|
||||
enabled = false,
|
||||
|
||||
--- sets the directory where the persistence file is stored
|
||||
--- if nil then lfs.writedir() will be used.
|
||||
--- which will
|
||||
--- sets the directory where the persistence file is stored <br>
|
||||
--- if nil then lfs.writedir()/Data will be used. <br>
|
||||
--- which will Result in <Saved Games>/<DCS Saved Games Folder>/Data/
|
||||
directory = nil ,
|
||||
|
||||
--- the filename of the persistence file. Should end with .json for convention, but any text extension should do.
|
||||
|
||||
@@ -16,6 +16,9 @@ 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"))()
|
||||
|
||||
@@ -39,6 +42,7 @@ 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"))()
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@ SpearheadConfig = {
|
||||
--- io and lfs cannot be sanitized in the MissionScripting.lua
|
||||
|
||||
--- enables or disables the persistence logic in spearhead
|
||||
enabled = false,
|
||||
enabled = true,
|
||||
|
||||
--- sets the directory where the persistence file is stored
|
||||
--- if nil then lfs.writedir() will be used.
|
||||
@@ -72,7 +72,7 @@ SpearheadConfig = {
|
||||
directory = nil ,
|
||||
|
||||
--- the filename of the persistence file. Should end with .json for convention, but any text extension should do.
|
||||
fileName = "Spearhead_Persistence_Dev.json"
|
||||
fileName = "Spearhead_Persistence_Dev"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,11 +33,14 @@ else
|
||||
standardLogger:info("Persistence disabled")
|
||||
end
|
||||
|
||||
local spawnLogger = Spearhead.LoggerTemplate.new("SpawnManager", defaultLogLevel)
|
||||
local spawnManager = Spearhead.classes.helpers.SpawnManager.new(spawnLogger)
|
||||
local detectionLogger = Spearhead.LoggerTemplate.new("DetectionManager", defaultLogLevel)
|
||||
local detectionManager = Spearhead.classes.capClasses.detection.DetectionManager.New(detectionLogger)
|
||||
|
||||
Spearhead.classes.capClasses.GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel)
|
||||
Spearhead.internal.GlobalStageManager:NewAndStart(databaseManager, stageConfig, defaultLogLevel)
|
||||
Spearhead.classes.capClasses.GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager)
|
||||
Spearhead.internal.GlobalStageManager:NewAndStart(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
||||
|
||||
Spearhead.internal.GlobalFleetManager.start(databaseManager)
|
||||
|
||||
local SetStageDelayed = function(number, time)
|
||||
|
||||
Reference in New Issue
Block a user