Improved menu interaction and added pinning functionality (#23)
* Improved menu interaction * Added Overview message * Added Pinning functionality. Pinning a mission so you can easily pull up the briefing again. * Added "Clear View" command to get rid of the message on the screen.
This commit is contained in:
@@ -1,130 +1,276 @@
|
||||
|
||||
---@class MissionCommandsHelper
|
||||
---@field missionsByCode table<string, Mission> @table of missions by their code
|
||||
---@field enabledByCode table<string, boolean> @table of enabled missions by their code
|
||||
---@field updateNeeded boolean @flag to indicate if an update is needed
|
||||
---@field lastUpdate number @last update time
|
||||
---@field updateContinuous fun(self: MissionCommandsHelper, time: number): number @function to update commands continuously
|
||||
---@field pinnedByGroup table<string, Mission> @table of pinned missions by group ID
|
||||
---@field private _logger Logger @logger instance for logging
|
||||
local MissionCommandsHelper = {}
|
||||
do
|
||||
---@type table<string, Mission>
|
||||
local missionsByCode = {}
|
||||
MissionCommandsHelper.__index = MissionCommandsHelper
|
||||
|
||||
---@type table<string, boolean>
|
||||
local enabledByCode = {}
|
||||
|
||||
local updateNeeded = false
|
||||
local instance = nil
|
||||
|
||||
---Add a mission to the F10 commands menu
|
||||
---@param mission Mission
|
||||
MissionCommandsHelper.AddMissionToCommands = function (mission)
|
||||
missionsByCode[tostring(mission.code)] = mission
|
||||
enabledByCode[tostring(mission.code)] = true
|
||||
updateNeeded = true
|
||||
end
|
||||
---@return MissionCommandsHelper
|
||||
---@param logLevel string @log level for the logger
|
||||
function MissionCommandsHelper.getOrCreate(logLevel)
|
||||
if instance == nil then
|
||||
local self = setmetatable({}, MissionCommandsHelper)
|
||||
|
||||
---Removes a mission from the F10 commands menu
|
||||
---@param mission Mission
|
||||
MissionCommandsHelper.RemoveMissionToCommands = function (mission)
|
||||
enabledByCode[tostring(mission.code)] = false
|
||||
updateNeeded = true
|
||||
end
|
||||
self._logger = Spearhead.LoggerTemplate.new("MissionCommandsHelper", logLevel)
|
||||
|
||||
local folderNames = {
|
||||
primary = "Primary Missions",
|
||||
secondary = "Secondary Missions"
|
||||
}
|
||||
self.missionsByCode = {}
|
||||
self.enabledByCode = {}
|
||||
self.updateNeeded = false
|
||||
self.pinnedByGroup = {}
|
||||
self.lastUpdate = 0
|
||||
|
||||
---Add Base Folder
|
||||
---@param groupId integer
|
||||
local addMissionFolders = function(groupId)
|
||||
missionCommands.addSubMenuForGroup(groupId, folderNames.primary)
|
||||
missionCommands.addSubMenuForGroup(groupId, folderNames.secondary)
|
||||
end
|
||||
---comment
|
||||
---@param selfA MissionCommandsHelper
|
||||
---@param time number
|
||||
---@return number
|
||||
self.updateContinuous = function(selfA, time)
|
||||
if selfA.updateNeeded == false and timer.getTime() - selfA.lastUpdate < 10 then
|
||||
return time + 2
|
||||
end
|
||||
|
||||
---Add Mission Folder
|
||||
---@param groupId integer
|
||||
local removeMissionFolders = function(groupId)
|
||||
missionCommands.removeItemForGroup(groupId , { folderNames.primary } )
|
||||
missionCommands.removeItemForGroup(groupId , { folderNames.secondary } )
|
||||
end
|
||||
for _, unit in pairs(Spearhead.DcsUtil.getAllPlayerUnits()) do
|
||||
if unit and unit:isExist() then
|
||||
local group = unit:getGroup()
|
||||
if group then
|
||||
selfA:updateCommandsForGroup(group:getID())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local missionBriefingRequested = function(args)
|
||||
---@type Mission
|
||||
local mission = args.mission
|
||||
local groupID = args.groupId
|
||||
|
||||
mission:ShowBriefing(groupID)
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param groupId integer
|
||||
---@param mission Mission
|
||||
local addMissionCommands = function(groupId, mission)
|
||||
|
||||
local path = nil
|
||||
|
||||
if mission.priority == "primary" then
|
||||
path = { [1] = folderNames.primary }
|
||||
elseif mission.priority == "secondary" then
|
||||
path = { [1] = folderNames.secondary }
|
||||
selfA.lastUpdate = timer.getTime()
|
||||
selfA.updateNeeded = false
|
||||
return time + 3
|
||||
end
|
||||
|
||||
if path then
|
||||
local missionFolderName = "[" .. mission.code .. "]" .. mission.name
|
||||
missionCommands.addSubMenuForGroup(groupId, missionFolderName, path)
|
||||
table.insert(path, missionFolderName)
|
||||
missionCommands.addCommandForGroup(groupId, "Briefing" , path , missionBriefingRequested, { groupId = groupId, mission = mission })
|
||||
end
|
||||
timer.scheduleFunction(self.updateContinuous, self, timer.getTime() + 5)
|
||||
Spearhead.Events.AddOnPlayerEnterUnitListener(self)
|
||||
instance = self
|
||||
end
|
||||
|
||||
local updateCommandsForGroup = function(group)
|
||||
local groupID = group:getID()
|
||||
return instance
|
||||
end
|
||||
|
||||
-- Cleanup mission folder
|
||||
removeMissionFolders(groupID)
|
||||
|
||||
-- Add mission folders
|
||||
addMissionFolders(groupID)
|
||||
---@class MissionBriefingRequestedArgs
|
||||
---@field mission Mission @the mission object
|
||||
---@field groupId integer @the group ID of the player requesting the briefing
|
||||
|
||||
for code, enabled in pairs(enabledByCode) do
|
||||
---comment
|
||||
---@param args MissionBriefingRequestedArgs
|
||||
local missionBriefingRequested = function(args)
|
||||
---@type Mission
|
||||
local mission = args.mission
|
||||
local groupID = args.groupId
|
||||
|
||||
mission:ShowBriefing(groupID)
|
||||
end
|
||||
|
||||
|
||||
---@class PinMissionCommandArgs
|
||||
---@field self MissionCommandsHelper @the MissionCommandsHelper instance
|
||||
---@field groupId integer @the group ID of the player requesting the briefing
|
||||
---@field mission Mission @the mission object
|
||||
|
||||
local pinMissionCommand = function(args)
|
||||
---@type MissionCommandsHelper
|
||||
local self = args.self
|
||||
local groupID = args.groupId
|
||||
local mission = args.mission
|
||||
|
||||
if mission then
|
||||
self:PinMission(mission, groupID)
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
function MissionCommandsHelper:AddOverviewCommand(groupID)
|
||||
|
||||
local MissionsOverviewToGroup = function (id)
|
||||
|
||||
local text = "Missions Overview\n\n"
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(id)
|
||||
|
||||
---comment
|
||||
---@param mission Mission
|
||||
---@return string
|
||||
local function formatLine(mission)
|
||||
|
||||
local distanceText = "?"
|
||||
if group then
|
||||
local lead = group:getUnit(1)
|
||||
if lead and lead:isExist() == true then
|
||||
local pos = lead:getPoint()
|
||||
local Vec2Pos = { x= pos.x, y=pos.z }
|
||||
local distance = Spearhead.Util.VectorDistance2d(Vec2Pos, mission.location) / 1852
|
||||
distanceText = string.format("~%d", math.floor(distance))
|
||||
end
|
||||
end
|
||||
|
||||
return string.format("[%s] %-15s %-20s %10s nM\n", mission.code, mission.displayMissionType, mission.name, distanceText)
|
||||
end
|
||||
|
||||
---Primary missions
|
||||
text = text .. "Primary Missions\n"
|
||||
for code, enabled in pairs(self.enabledByCode) do
|
||||
|
||||
if enabled == true then
|
||||
local mission = missionsByCode[code]
|
||||
if mission then
|
||||
addMissionCommands(groupID, mission)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local UpdateContinuous = function(none, time)
|
||||
if updateNeeded == false then
|
||||
return time + 15
|
||||
end
|
||||
|
||||
for _, unit in pairs(Spearhead.DcsUtil.getAllPlayerUnits()) do
|
||||
if unit and unit:isExist() then
|
||||
local group = unit:getGroup()
|
||||
if group then
|
||||
updateCommandsForGroup(group)
|
||||
local mission = self.missionsByCode[code]
|
||||
if mission and mission.priority == "primary" then
|
||||
text = text .. formatLine(mission)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
updateNeeded = false
|
||||
return time + 15
|
||||
end
|
||||
|
||||
timer.scheduleFunction(UpdateContinuous, {}, timer.getTime() + 10)
|
||||
|
||||
do -- Player enter unit listener
|
||||
local onPlayerEnterUnit = function(unit)
|
||||
if unit then
|
||||
local group = unit:getGroup()
|
||||
if group then updateCommandsForGroup(group) end
|
||||
---Secondary missions
|
||||
text = text .. "\nSecondary Missions\n"
|
||||
for code, enabled in pairs(self.enabledByCode) do
|
||||
|
||||
if enabled == true then
|
||||
local mission = self.missionsByCode[code]
|
||||
if mission and mission.priority == "secondary" then
|
||||
text = text .. formatLine(mission)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
trigger.action.outTextForGroup(id, text, 20, true)
|
||||
end
|
||||
|
||||
local OnPlayerEnterUnitListener = {
|
||||
OnPlayerEntersUnit = function (self, unit)
|
||||
onPlayerEnterUnit(unit)
|
||||
end,
|
||||
}
|
||||
Spearhead.Events.AddOnPlayerEnterUnitListener(OnPlayerEnterUnitListener)
|
||||
missionCommands.removeItemForGroup(groupID, { "Overview" } )
|
||||
missionCommands.addCommandForGroup(groupID, "Overview", nil, MissionsOverviewToGroup, groupID)
|
||||
end
|
||||
|
||||
---@private
|
||||
function MissionCommandsHelper:AddPinnedMission(groupID)
|
||||
|
||||
local pinndedMission = self.pinnedByGroup[tostring(groupID)]
|
||||
missionCommands.removeItemForGroup(groupID, { "Pinned Mission" })
|
||||
|
||||
if pinndedMission and self.enabledByCode[tostring(pinndedMission.code)] == true then
|
||||
missionCommands.addCommandForGroup(groupID, "Pinned Mission", nil, missionBriefingRequested, { groupId = groupID, mission = pinndedMission })
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
---comment
|
||||
---@param groupID number
|
||||
function MissionCommandsHelper:updateCommandsForGroup(groupID)
|
||||
|
||||
self:AddPinnedMission(groupID)
|
||||
self:AddOverviewCommand(groupID)
|
||||
|
||||
self:ResetFolders(groupID)
|
||||
|
||||
for code, enabled in pairs(self.enabledByCode) do
|
||||
if enabled == true then
|
||||
local mission = self.missionsByCode[code]
|
||||
if mission then
|
||||
self:addMissionCommands(groupID, mission)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param id number
|
||||
local clearView = function(id)
|
||||
trigger.action.outTextForGroup(id, "clearing...", 1, true)
|
||||
end
|
||||
|
||||
missionCommands.removeItemForGroup(groupID, { "Clear View" } )
|
||||
missionCommands.addCommandForGroup(groupID, "Clear View", nil, clearView, groupID)
|
||||
|
||||
end
|
||||
|
||||
local folderNames = {
|
||||
primary = "Primary Missions",
|
||||
secondary = "Secondary Missions"
|
||||
}
|
||||
|
||||
|
||||
function MissionCommandsHelper:PinMission(mission, groupID)
|
||||
self._logger:debug("Pinning mission: [" .. mission.code .. "]" .. mission.name)
|
||||
self.pinnedByGroup[tostring(groupID)] = mission
|
||||
trigger.action.outTextForGroup(groupID, "Pinned mission: [" .. mission.code .. "]" .. mission.name, 3, true)
|
||||
|
||||
self:updateCommandsForGroup(groupID)
|
||||
end
|
||||
|
||||
---comment
|
||||
---@private
|
||||
---@param groupId integer
|
||||
---@param mission Mission
|
||||
function MissionCommandsHelper:addMissionCommands(groupId, mission)
|
||||
local path = nil
|
||||
|
||||
if mission.priority == "primary" then
|
||||
path = { [1] = folderNames.primary }
|
||||
elseif mission.priority == "secondary" then
|
||||
path = { [1] = folderNames.secondary }
|
||||
end
|
||||
|
||||
|
||||
if path then
|
||||
self._logger:debug("Registering command: [" .. mission.code .. "]" .. mission.name)
|
||||
local missionFolderName = "[" .. mission.code .. "]" .. mission.name
|
||||
missionCommands.addSubMenuForGroup(groupId, missionFolderName, path)
|
||||
table.insert(path, missionFolderName)
|
||||
missionCommands.addCommandForGroup(groupId, "Briefing", path, missionBriefingRequested,{ groupId = groupId, mission = mission })
|
||||
missionCommands.addCommandForGroup(groupId, "Pin", path, pinMissionCommand, { self = self, groupId = groupId, mission = mission })
|
||||
end
|
||||
end
|
||||
|
||||
---@param mission Mission
|
||||
function MissionCommandsHelper:AddMissionToCommands(mission)
|
||||
self._logger:debug("Adding mission to commands: [" .. mission.code .. "]" .. mission.name)
|
||||
self.missionsByCode[tostring(mission.code)] = mission
|
||||
self.enabledByCode[tostring(mission.code)] = true
|
||||
self.updateNeeded = true
|
||||
end
|
||||
|
||||
---Removes a mission from the F10 commands menu
|
||||
---@param mission Mission
|
||||
function MissionCommandsHelper:RemoveMissionToCommands(mission)
|
||||
self.enabledByCode[tostring(mission.code)] = false
|
||||
self.updateNeeded = true
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param groupId integer
|
||||
function MissionCommandsHelper:addMissionFolders(groupId)
|
||||
missionCommands.addSubMenuForGroup(groupId, folderNames.primary)
|
||||
missionCommands.addSubMenuForGroup(groupId, folderNames.secondary)
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param groupId integer
|
||||
function MissionCommandsHelper:removeMissionFolders(groupId)
|
||||
missionCommands.removeItemForGroup(groupId, { folderNames.primary })
|
||||
missionCommands.removeItemForGroup(groupId, { folderNames.secondary })
|
||||
end
|
||||
|
||||
---@private
|
||||
function MissionCommandsHelper:ResetFolders(groupID)
|
||||
-- Cleanup mission folder
|
||||
self:removeMissionFolders(groupID)
|
||||
|
||||
-- Add mission folders
|
||||
self:addMissionFolders(groupID)
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param unit Unit
|
||||
function MissionCommandsHelper:OnPlayerEntersUnit(unit)
|
||||
if unit then
|
||||
local group = unit:getGroup()
|
||||
if group then self:updateCommandsForGroup(group:getID()) end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user