443 lines
17 KiB
Lua
443 lines
17 KiB
Lua
|
|
local Stage = {}
|
|
do --init STAGE DIRECTOR
|
|
|
|
|
|
local stageDrawingId = 0
|
|
|
|
---comment
|
|
---@param stagezone_name string
|
|
---@param database table
|
|
---@param logger table
|
|
---@return table?
|
|
function Stage:new(stagezone_name, database, logger, stageConfig)
|
|
local o = {}
|
|
setmetatable(o, { __index = self })
|
|
|
|
o.zoneName = stagezone_name
|
|
|
|
local split = Spearhead.Util.split_string(stagezone_name, "_")
|
|
if Spearhead.Util.tableLength(split) < 2 then
|
|
Spearhead.AddMissionEditorWarning("Stage zone with name " .. stagezone_name .. " does not have a order number or valid format")
|
|
return nil
|
|
end
|
|
|
|
local orderNumber = tonumber(split[2])
|
|
if orderNumber == nil then
|
|
Spearhead.AddMissionEditorWarning("Stage zone with name " .. stagezone_name .. " does not have a valid order number : " .. split[2])
|
|
return nil
|
|
end
|
|
|
|
o.stageNumber = orderNumber
|
|
o.database = database
|
|
o.logger = logger
|
|
o.db = {}
|
|
o.db.missionsByCode = {}
|
|
o.db.missions = {}
|
|
o.db.sams = {}
|
|
o.db.redAirbasegroups = {}
|
|
o.db.blueAirbasegroups = {}
|
|
o.db.airbaseIds = {}
|
|
o.db.farps = {}
|
|
o.activeStage = 0
|
|
o.preActivated = false
|
|
o.stageConfig = stageConfig or {}
|
|
o.stageDrawingId = stageDrawingId + 1
|
|
|
|
stageDrawingId = stageDrawingId + 1
|
|
|
|
do --Init Stage
|
|
logger:info("Initiating new Stage with name: " .. stagezone_name)
|
|
|
|
local missionZones = database:getMissionsForStage(stagezone_name)
|
|
for _, missionZone in pairs(missionZones) do
|
|
local mission = Spearhead.internal.Mission:new(missionZone, database, logger)
|
|
if mission then
|
|
o.db.missionsByCode[mission.code] = mission
|
|
if mission.missionType == Spearhead.internal.Mission.MissionType.SAM then
|
|
table.insert(o.db.sams, mission)
|
|
else
|
|
table.insert(o.db.missions, mission)
|
|
end
|
|
end
|
|
end
|
|
|
|
local randomMissionNames = database:getRandomMissionsForStage(stagezone_name)
|
|
|
|
local randomMissionByName = {}
|
|
for _, missionZoneName in pairs(randomMissionNames) do
|
|
local mission = Spearhead.internal.Mission:new(missionZoneName, database, logger)
|
|
if mission then
|
|
if randomMissionByName[mission.name] == nil then
|
|
randomMissionByName[mission.name] = {}
|
|
end
|
|
table.insert(randomMissionByName[mission.name], mission)
|
|
end
|
|
end
|
|
|
|
for _, missions in pairs(randomMissionByName) do
|
|
local mission = Spearhead.Util.randomFromList(missions)
|
|
if mission then
|
|
o.db.missionsByCode[mission.code] = mission
|
|
if mission.missionType == Spearhead.internal.Mission.MissionType.SAM then
|
|
table.insert(o.db.sams, mission)
|
|
else
|
|
table.insert(o.db.missions, mission)
|
|
end
|
|
end
|
|
end
|
|
|
|
local airbaseIds = database:getAirbaseIdsInStage(o.zoneName)
|
|
if airbaseIds ~= nil and type(airbaseIds) == "table" then
|
|
o.db.airbaseIds = airbaseIds
|
|
for _, airbaseId in pairs(airbaseIds) do
|
|
|
|
for _, groupName in pairs(database:getRedGroupsAtAirbase(airbaseId)) do
|
|
table.insert(o.db.redAirbasegroups, groupName)
|
|
end
|
|
|
|
for _, groupName in pairs(database:getBlueGroupsAtAirbase(airbaseId)) do
|
|
table.insert(o.db.blueAirbasegroups, groupName)
|
|
end
|
|
end
|
|
end
|
|
|
|
local farps = database:getFarpZonesInStage(o.zoneName)
|
|
if farps ~= nil and type(farps) == "table" then o.db.farps = farps end
|
|
end
|
|
|
|
o.IsComplete = function(self)
|
|
for i, mission in pairs(self.db.missions) do
|
|
local state = mission:GetState()
|
|
if state == Spearhead.Mission.MissionState.ACTIVE or state == Spearhead.Mission.MissionState.NEW then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
---Activates all SAMS, Airbase units etc all at once.
|
|
---@param self table
|
|
o.PreActivate = function(self)
|
|
if self.preActivated == false then
|
|
self.preActivated = true
|
|
for key, mission in pairs(self.db.sams) do
|
|
if mission and mission.Activate then
|
|
mission:Activate()
|
|
end
|
|
end
|
|
self.logger:debug("Pre-activating stage with airbase groups amount: " .. Spearhead.Util.tableLength(self.db.redAirbasegroups))
|
|
|
|
for _ , groupName in pairs(self.db.redAirbasegroups) do
|
|
Spearhead.DcsUtil.SpawnGroupTemplate(groupName)
|
|
end
|
|
end
|
|
|
|
if self.activeStage == self.stageNumber then
|
|
for _, mission in pairs(self.db.sams) do
|
|
self:AddCommmandsForMissionToAllPlayers(mission)
|
|
end
|
|
end
|
|
end
|
|
|
|
local activateMissionsIfApplicableAsync = function(self)
|
|
self:ActivateMissionsIfApplicable(self)
|
|
end
|
|
|
|
o.MarkStage = function(self, blue)
|
|
local fillColor = {1, 0, 0, 0.1}
|
|
local line ={ 1, 0,0, 1 }
|
|
if blue == true then
|
|
fillColor = {0, 0, 1, 0.1}
|
|
line ={ 0, 0,1, 1 }
|
|
end
|
|
|
|
local zone = Spearhead.DcsUtil.getZoneByName(self.zoneName)
|
|
if zone then
|
|
self.logger:debug("drawing stage")
|
|
if zone.zone_type == Spearhead.DcsUtil.ZoneType.Cilinder then
|
|
trigger.action.circleToAll(-1, self.stageDrawingId, {x = zone.x, y = 0 , z = zone.z}, zone.radius, {0,0,0,0}, {0,0,0,0},4, true)
|
|
else
|
|
--trigger.action.circleToAll(-1, self.stageDrawingId, {x = zone.x, y = 0 , z = zone.z}, zone.radius, { 1, 0,0, 1 }, {1,0,0,1},4, true)
|
|
trigger.action.quadToAll( -1, self.stageDrawingId, zone.verts[2], zone.verts[1], zone.verts[4], zone.verts[3], {0,0,0,0}, {0,0,0,0}, 4, true)
|
|
end
|
|
|
|
trigger.action.setMarkupColorFill(self.stageDrawingId, fillColor)
|
|
trigger.action.setMarkupColor(self.stageDrawingId, line)
|
|
end
|
|
end
|
|
|
|
o.ActivateStage = function(self)
|
|
pcall(function()
|
|
self:MarkStage()
|
|
end)
|
|
|
|
self:PreActivate()
|
|
|
|
local miscGroups = self.database:getMiscGroupsAtStage(self.zoneName)
|
|
self.logger:debug("Activating Misc groups for zone: " .. Spearhead.Util.tableLength(miscGroups))
|
|
for _, groupName in pairs(miscGroups) do
|
|
Spearhead.DcsUtil.SpawnGroupTemplate(groupName)
|
|
end
|
|
|
|
for _, mission in pairs(self.db.missions) do
|
|
if mission.missionType == Spearhead.internal.Mission.MissionType.DEAD then
|
|
mission:Activate()
|
|
self:AddCommmandsForMissionToAllPlayers(mission)
|
|
end
|
|
end
|
|
timer.scheduleFunction(activateMissionsIfApplicableAsync, self, timer.getTime() + 5)
|
|
end
|
|
|
|
o.ActivateMissionsIfApplicable = function (self)
|
|
local activeCount = 0
|
|
|
|
local availableMissions = {}
|
|
for _, mission in pairs(self.db.missionsByCode) do
|
|
if mission.missionState == Spearhead.internal.Mission.MissionState.ACTIVE then
|
|
activeCount = activeCount + 1
|
|
end
|
|
|
|
if mission.missionState == Spearhead.internal.Mission.MissionState.NEW then
|
|
table.insert(availableMissions, mission)
|
|
end
|
|
end
|
|
|
|
local max = self.stageConfig.maxMissionsInStage or 10
|
|
|
|
local availableMissionsCount = Spearhead.Util.tableLength(availableMissions)
|
|
if activeCount < max and availableMissionsCount > 0 then
|
|
for i = activeCount+1, max do
|
|
if availableMissionsCount == 0 then
|
|
i = max+1 --exits this loop
|
|
else
|
|
local index = math.random(1, availableMissionsCount)
|
|
local mission = table.remove(availableMissions, index)
|
|
if mission then
|
|
mission:Activate()
|
|
self:AddCommmandsForMissionToAllPlayers(mission)
|
|
end
|
|
availableMissionsCount = availableMissionsCount - 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
---Cleans up all missions
|
|
---@param self table
|
|
o.Clean = function(self)
|
|
for key, mission in pairs(self.db.missions) do
|
|
mission:Cleanup()
|
|
end
|
|
|
|
for key, samMission in pairs(self.db.sams) do
|
|
samMission:Cleanup()
|
|
end
|
|
|
|
for _, airbase in pairs(self.db.airbases) do
|
|
for _, redGroupName in pairs(airbase.redAirbaseGroupNames) do
|
|
Spearhead.DcsUtil.DcsUtil.DestroyGroup(redGroupName)
|
|
end
|
|
end
|
|
|
|
logger:debug("'" .. Spearhead.Util.toString(self.zoneName) .. "' cleaned")
|
|
end
|
|
|
|
local ActivateBlueAsync = function(self)
|
|
pcall(function()
|
|
self:MarkStage(true)
|
|
end)
|
|
|
|
for key, airbaseId in pairs(self.db.airbaseIds) do
|
|
local airbase = Spearhead.DcsUtil.getAirbaseById(airbaseId)
|
|
|
|
if airbase then
|
|
local startingCoalition = Spearhead.DcsUtil.getStartingCoalition(airbaseId)
|
|
if startingCoalition == coalition.side.BLUE then
|
|
airbase:setCoalition(2)
|
|
for _, blueGroupName in pairs(self.db.blueAirbasegroups) do
|
|
Spearhead.DcsUtil.SpawnGroupTemplate(blueGroupName)
|
|
end
|
|
else
|
|
airbase:setCoalition(0)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
---Sets airfields to blue and spawns friendly farps
|
|
o.ActivateBlueStage = function(self)
|
|
logger:debug("Setting stage '" .. Spearhead.Util.toString(self.zoneName) .. "' to blue")
|
|
|
|
for _, groupName in pairs(self.db.redAirbasegroups) do
|
|
Spearhead.DcsUtil.DestroyGroup(groupName)
|
|
end
|
|
|
|
for _, mission in pairs(self.db.missions) do
|
|
mission:Cleanup()
|
|
end
|
|
|
|
for _, mission in pairs(self.db.sams) do
|
|
mission:Cleanup()
|
|
end
|
|
|
|
timer.scheduleFunction(ActivateBlueAsync, self, timer.getTime() + 3)
|
|
|
|
-- for key, farp in pairs(self.db.farps) do
|
|
-- if farp.helipadnames then
|
|
-- for _, helipadName in pairs(farp.helipadnames) do
|
|
-- local helipad = Airbase.getByName(helipadName)
|
|
-- if helipad then
|
|
-- logger:debug("Enabling: '" .. helipad:getName() .. "'")
|
|
-- helipad:setCoalition(2)
|
|
-- else
|
|
-- logger:warn(helipadName .. " not found when spawning farps")
|
|
-- end
|
|
-- end
|
|
-- end
|
|
|
|
-- if farp.group_names then
|
|
-- for _, groupName in pairs(farp.group_names) do
|
|
-- Spearhead.DcsUtil.SpawnGroupTemplate(groupName)
|
|
-- end
|
|
-- end
|
|
-- end
|
|
end
|
|
|
|
o.OnStatusRequestReceived = function(self, groupId)
|
|
if self.activeStage ~= self.stageNumber then
|
|
return
|
|
end
|
|
|
|
trigger.action.outTextForGroup(groupId, "Status Update incoming... ", 3)
|
|
|
|
local text = "Mission Status: \n"
|
|
|
|
local totalmissions = 0
|
|
local completedMissions = 0
|
|
for _, mission in pairs(self.db.missionsByCode) do
|
|
totalmissions = totalmissions + 1
|
|
if mission.missionState == Spearhead.internal.Mission.MissionState.ACTIVE then
|
|
|
|
text = text .. "\n [" .. mission.code .. "] " .. mission.name ..
|
|
" (" .. mission.missionTypeDisplayName .. ") \n"
|
|
end
|
|
|
|
if mission.missionState == Spearhead.internal.Mission.MissionState.COMPLETED then
|
|
completedMissions = completedMissions + 1
|
|
end
|
|
end
|
|
|
|
local completionPercentage = math.floor((completedMissions / totalmissions) * 100)
|
|
text = text .. " \n Missions Complete: " .. completionPercentage .. "%"
|
|
|
|
self.logger:debug(text)
|
|
trigger.action.outTextForGroup(groupId, text, 20)
|
|
end
|
|
|
|
o.OnStageNumberChanged = function (self, number)
|
|
|
|
if self.activeStage == number then --only activate once for a stage
|
|
return
|
|
end
|
|
|
|
local previousActive = self.activeStage
|
|
self.activeStage = number
|
|
if Spearhead.capInfo.IsCapActiveWhenZoneIsActive(self.zoneName, number) == true then
|
|
self:PreActivate()
|
|
end
|
|
|
|
if number == self.stageNumber then
|
|
self:ActivateStage()
|
|
end
|
|
|
|
if previousActive <= self.stageNumber then
|
|
if number > self.stageNumber then
|
|
self:ActivateBlueStage()
|
|
self:RemoveAllMissionCommands()
|
|
end
|
|
end
|
|
end
|
|
|
|
--- input = { self, groupId, missionCode }
|
|
local ShowBriefingClicked = function (input)
|
|
|
|
local self = input.self
|
|
local groupId = input.groupId
|
|
local missionCode = input.missionCode
|
|
|
|
local mission = self.db.missionsByCode[missionCode]
|
|
if mission then
|
|
mission:ShowBriefing(groupId)
|
|
end
|
|
end
|
|
|
|
o.RemoveMissionCommands = function (self, mission)
|
|
|
|
self.logger:debug("Removing commands for: " .. mission.name)
|
|
|
|
local folderName = mission.name .. "(" .. mission.missionTypeDisplayName .. ")"
|
|
for i = 0, 2 do
|
|
local players = coalition.getPlayers(i)
|
|
for _, playerUnit in pairs(players) do
|
|
local groupId = playerUnit:getGroup():getID()
|
|
missionCommands.removeItemForGroup(groupId, { "Missions", folderName })
|
|
end
|
|
end
|
|
end
|
|
|
|
o.RemoveAllMissionCommands = function (self)
|
|
for _, mission in pairs(self.db.missionsByCode) do
|
|
self:RemoveMissionCommands(mission)
|
|
end
|
|
end
|
|
|
|
o.AddCommandsForMissionToGroup = function (self, groupId, mission)
|
|
local folderName = mission.name .. "(" .. mission.missionTypeDisplayName .. ")"
|
|
missionCommands.addSubMenuForGroup(groupId, folderName, { "Missions"} )
|
|
missionCommands.addCommandForGroup(groupId, "Show Briefing", { "Missions", folderName }, ShowBriefingClicked, { self = self, groupId = groupId, missionCode = mission.code })
|
|
end
|
|
|
|
o.AddCommmandsForMissionToAllPlayers = function(self, mission)
|
|
for i = 0, 2 do
|
|
local players = coalition.getPlayers(i)
|
|
for _, playerUnit in pairs(players) do
|
|
local groupId = playerUnit:getGroup():getID()
|
|
self:AddCommandsForMissionToGroup(groupId, mission)
|
|
end
|
|
end
|
|
end
|
|
|
|
o.OnPlayerEntersUnit = function (self, unit)
|
|
if self.activeStage == self.stageNumber then
|
|
local groupId = unit:getGroup():getID()
|
|
for _, mission in pairs(self.db.missionsByCode) do
|
|
if mission.missionState == Spearhead.internal.Mission.MissionState.ACTIVE then
|
|
self:AddCommandsForMissionToGroup(groupId, mission)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local removeMissionCommandsDelayed = function(input)
|
|
local self = input.self
|
|
local mission = input.mission
|
|
self:RemoveMissionCommands(mission)
|
|
end
|
|
|
|
o.OnMissionComplete = function(self, mission)
|
|
timer.scheduleFunction(removeMissionCommandsDelayed, { self = self, mission = mission}, timer.getTime() + 20)
|
|
timer.scheduleFunction(activateMissionsIfApplicableAsync, self, timer.getTime() + 10)
|
|
end
|
|
|
|
for _, mission in pairs(o.db.missionsByCode) do
|
|
mission:AddMissionCompleteListener(o)
|
|
end
|
|
|
|
Spearhead.Events.AddOnStatusRequestReceivedListener(o)
|
|
Spearhead.Events.AddStageNumberChangedListener(o)
|
|
return o
|
|
end
|
|
end
|
|
|
|
Spearhead.internal.Stage = Stage |