From 05d47aa96927a97bedf4c74027f14ef75df8068c Mon Sep 17 00:00:00 2001 From: dutchie031 Date: Sat, 19 Sep 2026 22:27:57 +0200 Subject: [PATCH] All luals findings solved --- src/classes/capClasses/GlobalCapManager.lua | 2 + src/classes/capClasses/airGroups/AirGroup.lua | 2 +- .../capClasses/airGroups/InterceptGroup.lua | 4 ++ .../capClasses/airGroups/SweepGroup.lua | 2 +- .../runwayBombing/RunwayBombingTracker.lua | 5 +- src/classes/capClasses/taskings/CAP.lua | 4 ++ src/classes/capClasses/taskings/INTERCEPT.lua | 2 +- src/classes/capClasses/taskings/RTB.lua | 2 + src/classes/capClasses/taskings/SWEEP.lua | 5 ++ src/classes/debug/DebugMenu.lua | 2 +- src/classes/fleetClasses/FleetGroup.lua | 18 +++-- src/classes/helpers/MizGroupsManager.lua | 37 ++++++++-- src/classes/helpers/SpawnManager.lua | 22 +++--- src/classes/persistence/Persistence.lua | 3 +- src/classes/spearhead_db.lua | 33 ++++++--- src/classes/spearhead_events.lua | 60 +++++++++++----- src/classes/spearhead_routeutil.lua | 15 ++-- .../stageClasses/GlobalStageManager.lua | 13 +++- .../stageClasses/Groups/SpearheadGroup.lua | 4 +- .../stageClasses/SpecialZones/StageBase.lua | 2 + .../SpecialZones/abstract/BuildableZone.lua | 2 + src/classes/stageClasses/StageLane.lua | 21 +++--- .../stageClasses/Stages/BaseStage/Stage.lua | 4 ++ .../drawings/helper/DrawingHelper.lua | 7 +- .../stageClasses/helpers/BattleManager.lua | 8 ++- .../helpers/MissionCommandsHelper.lua | 4 +- .../helpers/SupplyConfigHelper.lua | 3 +- .../helpers/SupplyUnitsTracker.lua | 42 ++++++----- .../missions/BuildableMission.lua | 16 +++-- .../missions/RunwayStrikeMission.lua | 12 +++- .../stageClasses/missions/ZoneMission.lua | 10 ++- .../missions/baseMissions/Mission.lua | 1 + src/classes/util/DcsUtil.lua | 71 +++++++++++++------ src/classes/util/MissionEditorWarnings.lua | 10 ++- src/classes/util/Util.lua | 57 ++++++++++----- 35 files changed, 356 insertions(+), 149 deletions(-) diff --git a/src/classes/capClasses/GlobalCapManager.lua b/src/classes/capClasses/GlobalCapManager.lua index 94c9014..e5ed0f0 100644 --- a/src/classes/capClasses/GlobalCapManager.lua +++ b/src/classes/capClasses/GlobalCapManager.lua @@ -6,7 +6,9 @@ local CapAirbase = require("classes.capClasses.CapAirbase") ---@class GlobalCapManager local GlobalCapManager = {} do + ---@type table local airbasesPerStage = {} + ---@type table local allAirbasesByName = {} local initiated = false diff --git a/src/classes/capClasses/airGroups/AirGroup.lua b/src/classes/capClasses/airGroups/AirGroup.lua index 79b3d58..c0c272c 100644 --- a/src/classes/capClasses/airGroups/AirGroup.lua +++ b/src/classes/capClasses/airGroups/AirGroup.lua @@ -5,7 +5,7 @@ local GlobalConfig = require("classes.configuration.GlobalConfig") local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing") local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper") ----@class AirGroup : OnUnitLostListener +---@class AirGroup : OnUnitLostListener, OnGroupRTBListener, OnGroupRTBInTenListener, OnLandEventListener, OnGroupOnStationListener ---@field protected _logger Logger ---@field protected _groupName string ---@field protected _groupType AirGroupType diff --git a/src/classes/capClasses/airGroups/InterceptGroup.lua b/src/classes/capClasses/airGroups/InterceptGroup.lua index bee6313..652ca5b 100644 --- a/src/classes/capClasses/airGroups/InterceptGroup.lua +++ b/src/classes/capClasses/airGroups/InterceptGroup.lua @@ -93,6 +93,9 @@ function InterceptGroup:SetTargetUnits(unitNames) end) end + ---@param selfA InterceptGroup + ---@param time number + ---@return number? local updateContinous = function(selfA, time) local next = selfA:UpdateTask() if next then @@ -104,6 +107,7 @@ function InterceptGroup:SetTargetUnits(unitNames) self._updateTaskID = timer.scheduleFunction(updateContinous, self, timer.getTime() + 30) end +---@param unit Unit function InterceptGroup:RemoveTargetUnit(unit) if not unit then return end diff --git a/src/classes/capClasses/airGroups/SweepGroup.lua b/src/classes/capClasses/airGroups/SweepGroup.lua index 9e18b69..bfc1d0b 100644 --- a/src/classes/capClasses/airGroups/SweepGroup.lua +++ b/src/classes/capClasses/airGroups/SweepGroup.lua @@ -4,7 +4,7 @@ local Util = require("classes.util.Util") local MissionEditorWarner = require("classes.util.MissionEditorWarnings") ---@class SweepGroup : AirGroup ----@field _targetZoneIdPerStage table +---@field _targetZoneIdPerStage table ---@field _currentTargetZoneID string? local SweepGroup = {} SweepGroup.__index = SweepGroup diff --git a/src/classes/capClasses/runwayBombing/RunwayBombingTracker.lua b/src/classes/capClasses/runwayBombing/RunwayBombingTracker.lua index 0d8e907..185f8d2 100644 --- a/src/classes/capClasses/runwayBombing/RunwayBombingTracker.lua +++ b/src/classes/capClasses/runwayBombing/RunwayBombingTracker.lua @@ -104,11 +104,10 @@ function RunwayBombingTracker:OnWeaponImpact(weaponDesc, impactPoint) self._logger:debug("RunwayBombingTracker:OnWeaponImpact") - local warhead = weaponDesc.warhead - local explosiveMass = warhead.explosiveMass or warhead.shapedExplosiveMass + local warhead = weaponDesc.warhead --[[@as table]] + local explosiveMass = (warhead.explosiveMass or warhead.shapedExplosiveMass) --[[@as number]] for _, strikeMission in pairs(self.trackedRunways) do - local zone= strikeMission:GetRunwayZone() if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then diff --git a/src/classes/capClasses/taskings/CAP.lua b/src/classes/capClasses/taskings/CAP.lua index 16f2da2..174b8d3 100644 --- a/src/classes/capClasses/taskings/CAP.lua +++ b/src/classes/capClasses/taskings/CAP.lua @@ -7,6 +7,7 @@ local CAP = {} ---@param attackHelos boolean ---@return table local function GetCAPTargetTypes(attackHelos) + ---@type Array local targetTypes = { [1] = "Planes", } @@ -53,7 +54,10 @@ local function GetCAPPointFromTriggerZone(airBase, capZone) ---@type Vec2 local baseVec2 = { x = baseVec3.x, y = baseVec3.z } + ---@type Vec2 local pointA = capZone.verts[furthestA] + + ---@type Vec2 local pointB = capZone.verts[furthestB] local furthest = pointA local closest = pointB diff --git a/src/classes/capClasses/taskings/INTERCEPT.lua b/src/classes/capClasses/taskings/INTERCEPT.lua index b780f51..d801f38 100644 --- a/src/classes/capClasses/taskings/INTERCEPT.lua +++ b/src/classes/capClasses/taskings/INTERCEPT.lua @@ -93,7 +93,7 @@ end ---@param currentPoint Vec2 ---@param targetPosition Vec2 ---@param targetUnit Unit ----@param airbase any +---@param airbase Airbase ---@param config any ---@param speed number? ---@param alt number? diff --git a/src/classes/capClasses/taskings/RTB.lua b/src/classes/capClasses/taskings/RTB.lua index 859cd32..dda92b7 100644 --- a/src/classes/capClasses/taskings/RTB.lua +++ b/src/classes/capClasses/taskings/RTB.lua @@ -173,6 +173,8 @@ function RTB.getInitialPoint(airbase) } end +---@param airbase Airbase +---@return table function RTB.getLandingPoint(airbase) local basePoint = airbase:getPoint() return { diff --git a/src/classes/capClasses/taskings/SWEEP.lua b/src/classes/capClasses/taskings/SWEEP.lua index 61e12aa..a77425a 100644 --- a/src/classes/capClasses/taskings/SWEEP.lua +++ b/src/classes/capClasses/taskings/SWEEP.lua @@ -7,6 +7,7 @@ local SWEEP = {} ---@param attackHelos boolean ---@return table local function GetCAPTargetTypes(attackHelos) + ---@type Array local targetTypes = { [1] = "Planes", } @@ -49,7 +50,9 @@ local function GetCAPPointFromTriggerZone(airBase, capZone) ---@type Vec2 local baseVec2 = { x = baseVec3.x, y = baseVec3.z } + ---@type Vec2 local pointA = capZone.verts[furthestA] + ---@type Vec2 local pointB = capZone.verts[furthestB] local furthest = pointA local closest = pointB @@ -80,6 +83,7 @@ end ---@param airbase Airbase ---@param capZone SpearheadTriggerZone ---@param capConfig CapConfig +---@return table local GetOutboundTask = function(airbase, capZone, capConfig) local airbaseVec3 = airbase:getPoint() local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z } @@ -121,6 +125,7 @@ end ---@param airbase Airbase ---@param capZone SpearheadTriggerZone ---@param capConfig CapConfig +---@return table function SWEEP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig) local pointA, pointB, pointC = SWEEP.getAsTasking(groupName, airbase, capZone, capConfig) diff --git a/src/classes/debug/DebugMenu.lua b/src/classes/debug/DebugMenu.lua index 97539a2..b6002ad 100644 --- a/src/classes/debug/DebugMenu.lua +++ b/src/classes/debug/DebugMenu.lua @@ -21,7 +21,7 @@ function DebugMenu:RegisterMenus() missionCommands.addSubMenu(menuName, {}) local refresh = function(params) - local selfA = params.self + local selfA = params.self --[[@as DebugMenu]] selfA:RefreshMenu() end missionCommands.addCommand("Refresh Menu", debugMenuPath, refresh, { self = self }) diff --git a/src/classes/fleetClasses/FleetGroup.lua b/src/classes/fleetClasses/FleetGroup.lua index 12b63b3..28f124d 100644 --- a/src/classes/fleetClasses/FleetGroup.lua +++ b/src/classes/fleetClasses/FleetGroup.lua @@ -10,7 +10,7 @@ local SpearheadEvents = require("classes.spearhead_events") ---@field private fleetNameIdentifier string ---@field private targetZonePerStage table ---@field private currentTargetZone string ----@field private pointsPerZone table +---@field private pointsPerZone table local FleetGroup = {} FleetGroup.__index = FleetGroup @@ -108,7 +108,13 @@ function FleetGroup.new(fleetGroupName, database, logger) for i = first, second do self.targetZonePerStage[tostring(i)] = zoneName end - self.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} } + ---@type {pointA: Vec3, pointB: Vec3} + local entry = { + pointA = {x = pointA.x, z = pointA.y, y = 0}, + pointB = {x = pointB.x, z = pointB.y, y = 0} + } + + self.pointsPerZone[zoneName] = entry else MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[-]: " .. zoneName) end @@ -125,10 +131,10 @@ function FleetGroup.new(fleetGroupName, database, logger) end local SetTaskAsync = function(input, _) - local targetZone = input.targetZone - local task = input.task - local groupName = input.groupName - local l_logger = input.logger + local targetZone = input.targetZone --[[@as string]] + local task = input.task --[[@as table]] + local groupName = input.groupName --[[@as string]] + local l_logger = input.logger --[[@as Logger]] local group = Group.getByName(groupName) if group then diff --git a/src/classes/helpers/MizGroupsManager.lua b/src/classes/helpers/MizGroupsManager.lua index f33a723..c5aef3a 100644 --- a/src/classes/helpers/MizGroupsManager.lua +++ b/src/classes/helpers/MizGroupsManager.lua @@ -15,23 +15,45 @@ MizGroupsManager._groupNames = {} MizGroupsManager._spawnTemplateData = {} do --init - for _, coalition_data in pairs(env.mission.coalition) do + + ---@param coalition_name string + ---@return Coalition + local getCoalitionData = function(coalition_name) + return env.mission.coalition[coalition_name] + end + + ---@param country Country + ---@param key string + ---@return Groups? + local getGroupsData = function(country, key) + if key == "planes" then return country.plane end + if key == "helicopters" then return country.helicopter end + if key == "ground" then return country.vehicle end + if key == "ships" then return country.ship end + if key == "statics" then return country.static end + return nil + end + + for _, coalition_name in ipairs({"neutral", "blue", "red"}) do + local coalition_data = getCoalitionData(coalition_name) if coalition_data.country then for _, country_data in pairs(coalition_data.country) do - for category_name, categorydata in pairs(country_data) do + for _, category_name in pairs(DcsUtil.getAllGroupCategoryNames()) do local category_id = DcsUtil.stringToGroupCategory(category_name) - if category_id ~= nil and type(categorydata) == "table" and categorydata.group ~= nil and type(categorydata.group) == "table" then - for _, group in pairs(categorydata.group) do - local name = group.name + local groups_data = getGroupsData(country_data, category_name) + + if category_id ~= nil and type(groups_data) == "table" and groups_data.group ~= nil and type(groups_data.group) == "table" then + for _, group in pairs(groups_data.group) do + local name = group.name --[[@as string]] local skippable = false local isStatic = false if category_id == DcsUtil.GroupCategory.STATIC then isStatic = true - local unit = group.units[1] + local unit = group.units[1] --[[@as table]] if unit and unit.category == "Heliports" then skippable = true elseif unit and unit.name then - name = unit.name + name = unit.name --[[@as string]] else env.error("Group " .. name .. " has no units, skipping it.") skippable = true @@ -71,6 +93,7 @@ function MizGroupsManager.IsGroupStatic(groupName) return nil end +---@param groupName string ---@return SpawnData? function MizGroupsManager.getSpawnTemplateData(groupName) return MizGroupsManager._spawnTemplateData[groupName] diff --git a/src/classes/helpers/SpawnManager.lua b/src/classes/helpers/SpawnManager.lua index 812faf4..1ac88c9 100644 --- a/src/classes/helpers/SpawnManager.lua +++ b/src/classes/helpers/SpawnManager.lua @@ -16,11 +16,11 @@ SpawnManager.__index = SpawnManager ---@field uncontrolled boolean? Sets the group to be uncontrolled on spawn ---@param logger Logger +---@return SpawnManager function SpawnManager.new(logger) local self = setmetatable({}, SpawnManager) self._logger = logger - self._persistedUnits = {} -- Stores units that should be persisted by name return self @@ -133,8 +133,9 @@ do --- privates ]] if spawnTemplate and spawnTemplate["units"] then - for _, unit in pairs(spawnTemplate["units"]) do - local name = unit["name"] + local units = spawnTemplate["units"] --[[@as Array]] + for _, unit in pairs(units) do + local name = unit["name"] --[[@as string]] SpearheadEvents.addOnUnitLostEventListener(name, self) local state = Persistence.UnitState(name) @@ -146,16 +147,17 @@ do --- privates if override and override.emptyLoadouts == true then if unit["payload"] and unit["payload"]["pylons"] then - unit["payload"]["pylons"] = {} + local payload = unit["payload"] --[[@as table]] + payload["pylons"] = {} --[[@as table]] end end if unit["parking"] then - unit["parking_landing"] = unit["parking"] + unit["parking_landing"] = unit["parking"] --[[@as number]] end if unit["parking_id"] then - unit["parking_landing_id"] = unit["parking_id"] + unit["parking_landing_id"] = unit["parking_id"] --[[@as number]] end end @@ -210,9 +212,11 @@ do --- privates 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 + local units = spawnTemplate["units"] --[[@as Array
]] + local firstUnit = units[1] --[[@as table]] + firstUnit["x"] = persistentState.pos.x --[[@as number]] + firstUnit["y"] = persistentState.pos.z --[[@as number]] + firstUnit["heading"] = persistentState.heading or 0 --[[@as number]] end end end diff --git a/src/classes/persistence/Persistence.lua b/src/classes/persistence/Persistence.lua index a127e80..2684f90 100644 --- a/src/classes/persistence/Persistence.lua +++ b/src/classes/persistence/Persistence.lua @@ -187,7 +187,8 @@ do local userFileName = SpearheadConfig.Persistence.fileName local split = Util.split_string(userFileName, ".") - if not split and #split < 3 then + if not split or #split < 3 then + split = split or {} split[#split+1] = "0" split[#split+1] = "spearhead" end diff --git a/src/classes/spearhead_db.lua b/src/classes/spearhead_db.lua index 2c1b1e9..e62312a 100644 --- a/src/classes/spearhead_db.lua +++ b/src/classes/spearhead_db.lua @@ -215,8 +215,11 @@ function Database.New(Logger) local airbaseData = self:getAirbaseDataForDrawLayer(layer_object) if airbaseData then self._logger:debug("found airbase data for " .. layer_object.name) - local number = tonumber(layer_object.text) - airbaseData.buildingKilos = number + if layer_object.primitiveType == "TextBox" then + layer_object = layer_object --[[@as TextBox]] + local number = tonumber(layer_object.text) + airbaseData.buildingKilos = number + end end end end @@ -263,9 +266,12 @@ function Database.New(Logger) local zone = DcsUtil.getZoneByName(stageZoneName) local vec2 = { x = layer_object.mapX, y = layer_object.mapY } if zone and Util.is2dPointInZone(vec2, zone) == true then - local description = layer_object.text - if description and description ~= "" then - stageData.StageBriefing = description + if layer_object.primitiveType == "TextBox" then + layer_object = layer_object --[[@as TextBox]] + local description = layer_object.text + if description and description ~= "" then + stageData.StageBriefing = description + end end end end @@ -468,6 +474,7 @@ function Database.New(Logger) return self end +---@type table local is_group_taken = {} local getAvailableGroups = function() @@ -625,8 +632,9 @@ function Database:loadBlueSamUnits() for _, layer_object in pairs(layer.objects) do local vec2 = { x = layer_object.mapX, y = layer_object.mapY } - if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then + if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then if layer_object.name and Util.startswith(layer_object.name, "supplybriefing_", true) then + layer_object = layer_object --[[@as TextBox]] local description = layer_object.text if description and description ~= "" then samData.briefing = description @@ -725,8 +733,9 @@ function Database:LoadZoneData(missionZoneName) for _, layer_object in pairs(layer.objects) do local vec2 = { x = layer_object.mapX, y = layer_object.mapY } - if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then + if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then if layer_object.name and Util.startswith(layer_object.name, "briefing_", true) then + layer_object = layer_object --[[@as TextBox]] local description = layer_object.text if description and description ~= "" then self._tables.MissionZoneData[missionZoneName].description = description @@ -781,7 +790,8 @@ function Database:loadFarpData() for _, layer_object in pairs(layer.objects) do local vec2 = { x = layer_object.mapX, y = layer_object.mapY } - if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then + if layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then + layer_object = layer_object --[[@as TextBox]] if layer_object.name and Util.startswith(layer_object.name, "supplybriefing_", true) then local description = layer_object.text if description and description ~= "" then @@ -950,6 +960,7 @@ function Database:getBriefingForStage(stagename) return stageZone.StageBriefing or "" end +---@param stagename string ---@return Array function Database:getMissionsForStage(stagename) local stageZone = self._tables.StageZones[stagename] @@ -957,6 +968,7 @@ function Database:getMissionsForStage(stagename) return stageZone.MissionZones end +---@param stagename string ---@return Array function Database:getRandomMissionsForStage(stagename) local stageZone = self._tables.StageZones[stagename] @@ -964,13 +976,14 @@ function Database:getRandomMissionsForStage(stagename) return stageZone.RandomMissionZones end +---@param missionZoneName string ---@return MissionZoneData? function Database:getMissionDataForZone(missionZoneName) return self._tables.MissionZoneData[missionZoneName] end ---@param stageName string ----@return table result airbase Names +---@return Array result airbase Names function Database:getAirbaseNamesInStage(stageName) local stageData = self._tables.StageZones[stageName] if not stageData then return {} end @@ -984,6 +997,7 @@ function Database:getFarpNamesInStage(stageName) return stageData.FarpZones or {} end +---@param farpZoneName string ---@return FarpZoneData? function Database:getFarpDataForZone(farpZoneName) local farpData = self._tables.FarpZoneData[farpZoneName] @@ -999,6 +1013,7 @@ function Database:getAirbaseDataForZone(baseName) return baseData end +---@param stageName string ---@return string? function Database:getStageBriefingForStage(stageName) local stageData = self._tables.StageZones[stageName] diff --git a/src/classes/spearhead_events.lua b/src/classes/spearhead_events.lua index ab7f495..83fb992 100644 --- a/src/classes/spearhead_events.lua +++ b/src/classes/spearhead_events.lua @@ -32,7 +32,9 @@ do ---@field OnStageNumberChanged fun(self:OnStageChangedListener, number:integer, laneIdentifier:string?) do -- STAGE NUMBER CHANGED + ---@type Array local OnStageNumberChangedListeners = {} + ---@type Array local OnStageNumberChangedHandlers = {} ---Add a stage zone number changed listener ---@param listener OnStageChangedListener object with function OnStageNumberChanged(self, number, stageLaneIdentifier) @@ -47,6 +49,7 @@ do ---@class OnStageNumberChangeCompleteListener ---@field OnStageNumberChangeComplete fun(self:OnStageNumberChangeCompleteListener, number:integer, laneIdentifier:string?) + ---@type Array local OnStageNumberChangeCompleteListeners = {} ---@param listener OnStageNumberChangeCompleteListener SpearheadEvents.AddStageNumberChangeCompleteListener = function(listener) @@ -110,6 +113,9 @@ do table.insert(onWeaponFiredListeners, weaponFiredListener) end + ---@param unit Unit + ---@param weapon Weapon + ---@param target Unit? local triggerWeaponFired = function(unit, weapon, target) for _, callable in pairs(onWeaponFiredListeners) do local _, err = pcall(function() @@ -122,11 +128,14 @@ do end end + ---@class OnLandEventListener + ---@field OnUnitLanded fun(self:OnLandEventListener, initiatorUnit:Unit, airbase:Airbase) + ---@type table> local onLandEventListeners = {} ---Add an event listener to a specific unit ---@param unitName string to call when the unit lands - ---@param landListener table table with function OnUnitLanded(self, initiatorUnit, airbase) + ---@param landListener OnLandEventListener table with function OnUnitLanded(self, initiatorUnit, airbase) SpearheadEvents.addOnUnitLandEventListener = function(unitName, landListener) if type(landListener) ~= "table" then warn("Event handler not of type table/object") @@ -162,6 +171,11 @@ do end do -- ON RTB + + ---@class OnGroupRTBListener + ---@field OnGroupRTB fun(self:OnGroupRTBListener, groupName:string) + + ---@type table> local OnGroupRTBListeners = {} ---Adds a function to the events listener that triggers when a group publishes themselves RTB. ---This is only available when a ROUTE is created via the Spearhead.RouteUtil @@ -197,11 +211,15 @@ do end end + ---@class OnGroupRTBInTenListener + ---@field OnGroupRTBInTen fun(self:OnGroupRTBInTenListener, groupName:string) + + ---@type table> local OnGroupRTBInTenListeners = {} ---Adds a function to the events listener that triggers when a group publishes themselves RTB. ---This is only available when a ROUTE is created via the Spearhead.RouteUtil ---@param groupName string the groupname to expect - ---@param handlingObject table object with OnGroupRTBInTen(self, groupName) + ---@param handlingObject OnGroupRTBInTenListener object with OnGroupRTBInTen(self, groupName) SpearheadEvents.addOnGroupRTBInTenListener = function(groupName, handlingObject) if type(handlingObject) ~= "table" then warn("Event handler not of type table/object") @@ -234,10 +252,17 @@ do end do -- ON Station + + ---@class OnGroupOnStationListener + ---@field OnGroupOnStation fun(self:OnGroupOnStationListener, groupName:string) + + ---@type table> local OnGroupOnStationListeners = {} + ---Adds a function to the events listener that triggers when a group publishes themselves RTB. ---This is only available when a ROUTE is created via the Spearhead.RouteUtil ---@param groupName string the groupname to expect + ---@param handlingObject OnGroupOnStationListener object with OnGroupOnStation(self, groupName) SpearheadEvents.addOnGroupOnStationListener = function(groupName, handlingObject) if type(handlingObject) ~= "table" then warn("Event handler not of type table/object") @@ -270,15 +295,18 @@ do end do -- PLAYER ENTER UNIT + ---@class OnPlayerEnterUnitListener + ---@field OnPlayerEntersUnit fun(self:OnPlayerEnterUnitListener, unit:Unit) + + ---@type Array local playerEnterUnitListeners = {} ---comment - ---@param listener table object with OnPlayerEntersUnit(self, unit) + ---@param listener OnPlayerEnterUnitListener object with OnPlayerEntersUnit(self, unit) SpearheadEvents.AddOnPlayerEnterUnitListener = function(listener) if type(listener) ~= "table" then warn("Unit lost Event listener not of type table/object") return end - table.insert(playerEnterUnitListeners, listener) end @@ -315,8 +343,8 @@ do local e = {} function e:onEvent(event) if event.id == world.event.S_EVENT_LAND or event.id == world.event.S_EVENT_RUNWAY_TOUCH then - local unit = event.initiator - local airbase = event.place + local unit = event.initiator --[[@as Unit]] + local airbase = event.place --[[@as Airbase]] if unit ~= nil then local name = unit:getName() if onLandEventListeners[name] then @@ -336,7 +364,7 @@ do event.id == world.event.S_EVENT_CRASH or event.id == world.event.S_EVENT_EJECTION or event.id == world.event.S_EVENT_UNIT_LOST then - local object = event.initiator + local object = event.initiator --[[@as Unit]] if object and object.getName then logDebug("Receiving death event from: " .. object:getName()) @@ -355,15 +383,11 @@ do end end - if event.id == world.event.S_EVENT_EJECTION then - - end - if event.id == world.event.S_EVENT_SHOT then - local shooter = event.initiator - local weapon = event.weapon - local target = event.target + local shooter = event.initiator --[[@as Unit]] + local weapon = event.weapon --[[@as Weapon]] + local target = event.target --[[@as Unit?]] triggerWeaponFired(shooter, weapon, target) end @@ -372,10 +396,14 @@ do Persistence.UpdateNow() end + ---@type table local AI_GROUPS = {} + ---@param unit Unit + ---@param _ any local function CheckAndTriggerSpawnAsync(unit, _) - + ---@param checkUnit Unit + ---@return boolean, string? local function isPlayer(checkUnit) if checkUnit == nil then return false, "unit is nil" end if checkUnit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end @@ -405,8 +433,6 @@ do if isPlayer(unit) == true then SpearheadEvents.TriggerPlayerEntersUnit(unit) end - - return nil end if event.id == world.event.S_EVENT_BIRTH then diff --git a/src/classes/spearhead_routeutil.lua b/src/classes/spearhead_routeutil.lua index 717ee5b..82c7c47 100644 --- a/src/classes/spearhead_routeutil.lua +++ b/src/classes/spearhead_routeutil.lua @@ -8,6 +8,7 @@ do --setup route util ---@param attackHelos boolean ---@return table local function GetCAPTargetTypes(attackHelos) + ---@type table local targetTypes = { [1] = "Planes", } @@ -53,8 +54,9 @@ do --setup route util ---comment ---@param groupName string - ---@param position table { x, y} + ---@param position Vec3 ---@param altitude number + ---@param deviationdistance number ---@param speed number ---@param duration number ---@param engageHelos boolean @@ -181,7 +183,7 @@ do --setup route util end ---comment - ---@param position table { x, y} + ---@param position Vec3 ---@param altitude number ---@param speed number ---@param childTasks table @@ -210,7 +212,8 @@ do --setup route util ---comment ---@param groupName string groupName you're creating this route for ---@param airdromeId number airdromeId - ---@param capPoint table { x, z } + ---@param capPoint Vec3 + ---@param racetrackSecondPoint Vec3? ---@param altitude number ---@param speed number ---@param durationOnStation number @@ -304,6 +307,7 @@ do --setup route util end local group = Group.getByName(groupName) + ---@type Vec3? local pos; local i = 1 if group == nil then @@ -393,6 +397,9 @@ do --setup route util }, "" end + ---@param pointA Vec3 + ---@param pointB Vec3 + ---@return table, string? ROUTE_UTIL.CreateCarrierRacetrack = function(pointA, pointB) return { id = "Mission", @@ -461,7 +468,7 @@ do --setup route util } } } - }, "" + }, nil end end diff --git a/src/classes/stageClasses/GlobalStageManager.lua b/src/classes/stageClasses/GlobalStageManager.lua index 7b08a85..879ea93 100644 --- a/src/classes/stageClasses/GlobalStageManager.lua +++ b/src/classes/stageClasses/GlobalStageManager.lua @@ -327,12 +327,13 @@ function GlobalStageManager:OnStageNumberChangeComplete(stageNumber, stageLaneId if stageLaneIdentifier ~= nil then return end self.logger:debug("Stage number change complete to: " .. tostring(stageNumber)) + ---@type Array local groups = {} for _, player in pairs(DcsUtil.getAllPlayerUnits()) do local group = player:getGroup() if group then - groups[group:getID()] = group + table.insert(groups, group) end end @@ -369,8 +370,11 @@ end function GlobalStageManager:PrintMermaidStage() local lanes = self._stageRepository:getAllStageLanes() + ---@type table local nodes = {} + ---@type table local edges = {} + ---@type table> local stageIndicesByLane = {} -- Track all stage indices per lane local mainLaneId = "default" @@ -403,7 +407,9 @@ function GlobalStageManager:PrintMermaidStage() "#9B59B6", -- 25: Amethyst "#1ABC9C", -- 26: Turquoise } + ---@type table local laneColorMap = {} -- Map lane ID to color + ---@type number local colorIndex = 1 -- Build nodes and collect all stage indices per lane @@ -430,6 +436,7 @@ function GlobalStageManager:PrintMermaidStage() local stageName = stage.stageName or stage.zoneName -- Generate bracket label: [1], [2] for default, [w1], [e2] for other lanes + ---@type string local bracketLabel if laneId == "default" then bracketLabel = "[" .. stageIndex .. "]" @@ -496,7 +503,7 @@ function GlobalStageManager:PrintMermaidStage() for _, lane in ipairs(lanes) do if lane:IsDefaultStageLane() == false then local sideId = lane:GetStageLaneIdentifier() - local sideIndices = stageIndicesByLane[sideId] + local sideIndices = stageIndicesByLane[sideId] or {} --[[@as Array]] -- For each stage in the side lane for _, stageIdx in ipairs(sideIndices) do @@ -528,7 +535,7 @@ function GlobalStageManager:PrintMermaidStage() for _, lane in ipairs(lanes) do if lane:IsDefaultStageLane() == false then local sideId = lane:GetStageLaneIdentifier() - local sideIndices = stageIndicesByLane[sideId] + local sideIndices = stageIndicesByLane[sideId] or {} --[[@as Array]] -- Find the appropriate gate node for this side lane -- Use first stage >= nextIdx if it exists, otherwise use the highest stage diff --git a/src/classes/stageClasses/Groups/SpearheadGroup.lua b/src/classes/stageClasses/Groups/SpearheadGroup.lua index c5f8d41..a1e17d2 100644 --- a/src/classes/stageClasses/Groups/SpearheadGroup.lua +++ b/src/classes/stageClasses/Groups/SpearheadGroup.lua @@ -91,9 +91,9 @@ function SpearheadGroup:GetCoalition() end ---comment ----@return table result list of objects +---@return Array result list of objects function SpearheadGroup:GetObjects() - + ---@type Array local result = {} if self._isStatic == true then local staticObject = StaticObject.getByName(self._groupName) diff --git a/src/classes/stageClasses/SpecialZones/StageBase.lua b/src/classes/stageClasses/SpecialZones/StageBase.lua index c738f43..7e35f69 100644 --- a/src/classes/stageClasses/SpecialZones/StageBase.lua +++ b/src/classes/stageClasses/SpecialZones/StageBase.lua @@ -113,6 +113,7 @@ end function StageBase:SpawnRedUnits() ---comment ---@param groups Array + ---@return number|nil local spawnAsync = function(groups) for _, group in pairs(groups) do group:Spawn() @@ -142,6 +143,7 @@ end function StageBase:SpawnBlueUnits() ---comment ---@param groups Array + ---@return number|nil local spawnAsync = function(groups) for _, group in pairs(groups) do group:Spawn() diff --git a/src/classes/stageClasses/SpecialZones/abstract/BuildableZone.lua b/src/classes/stageClasses/SpecialZones/abstract/BuildableZone.lua index fe1296f..abff446 100644 --- a/src/classes/stageClasses/SpecialZones/abstract/BuildableZone.lua +++ b/src/classes/stageClasses/SpecialZones/abstract/BuildableZone.lua @@ -37,6 +37,7 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup ---@param params UnpackCrateParam ---@param time number + ---@return number|nil local startUnpackingCrate = function(params, time) local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2) local alreadySpawned = params.unpackedItems / params.groupsPerKilo @@ -104,6 +105,7 @@ function BuildableZone:OnCrateDroppedOff(_, kilos) ---@param params UnpackCrateParam ---@param time number + ---@return number|nil local startUnpackingCrate = function(params, time) local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2) local alreadySpawned = params.unpackedItems / params.groupsPerKilo diff --git a/src/classes/stageClasses/StageLane.lua b/src/classes/stageClasses/StageLane.lua index c8a6441..74448ba 100644 --- a/src/classes/stageClasses/StageLane.lua +++ b/src/classes/stageClasses/StageLane.lua @@ -4,8 +4,8 @@ ---@field private _isDefaultStageLane boolean ---@field private _stageLaneIdentifier string ---@field private _activeStageIndex number ----@field private _stagesInLaneByIndex table> ----@field private _chapterStarts table? +---@field private _stagesInLaneByIndex table> +---@field private _chapterStarts table? ---@field private _stageLaneState StageLaneState ---@field private _maxStageIndex number local StageLane = {} @@ -16,6 +16,7 @@ StageLane.__index = StageLane ---| "BetweenChapters" ---| "Completed" +---@type string? StageLane.DefaultLaneKey = nil function StageLane.New(laneIdentifier) @@ -37,21 +38,21 @@ end ---@param stage Stage function StageLane:AddStage(stage) local stageIndex = stage:GetStageIndex() - if not self._stagesInLaneByIndex[stageIndex] then - self._stagesInLaneByIndex[stageIndex] = {} + if not self._stagesInLaneByIndex[tostring(stageIndex)] then + self._stagesInLaneByIndex[tostring(stageIndex)] = {} end if not self._maxStageIndex or stageIndex > self._maxStageIndex then self._maxStageIndex = stageIndex end - table.insert(self._stagesInLaneByIndex[stageIndex], stage) + table.insert(self._stagesInLaneByIndex[tostring(stageIndex)], stage) end ---@param stageNumber number ---@return boolean? function StageLane:IsStageIndexComplete(stageNumber) - local stages = self._stagesInLaneByIndex[stageNumber] + local stages = self._stagesInLaneByIndex[tostring(stageNumber)] if not stages then return nil end @@ -88,7 +89,7 @@ end ---@param stageNumber number function StageLane:SetActiveStageIndex(stageNumber) - if self._stagesInLaneByIndex[stageNumber] == nil then + if self._stagesInLaneByIndex[tostring(stageNumber)] == nil then self._stageLaneState = "BetweenChapters" -- stage number is not in this lane, so we are between chapters elseif stageNumber > self._maxStageIndex then self._stageLaneState = "Completed" -- stage number is beyond the max stage index @@ -108,6 +109,7 @@ end --- Chapter starts are the first StageIndex after a gap in stage numbers.
--- For example, if the stage numbers are 1, 2, 3, 5, 6, 7, then stage number 5 is a chapter start because there is a gap between 3 and 5.
---@param stageNumber number +---@return boolean function StageLane:IsChapterStart(stageNumber) if self._chapterStarts == nil then @@ -123,13 +125,14 @@ end function StageLane:FillChapterStarts() local previousIndex = nil + ---@type table local stageIndices = {} for stageIndex, _ in pairs(self._stagesInLaneByIndex) do table.insert(stageIndices, tonumber(stageIndex)) end table.sort(stageIndices) - self._chapterStarts = self._chapterStarts or {} + if self._chapterStarts == nil then self._chapterStarts = {} end for _, stageIndex in ipairs(stageIndices) do if previousIndex == nil then -- First stage is always a chapter start @@ -158,7 +161,7 @@ end ---@param stageIndex number ---@return Array? function StageLane:GetStagesAtIndex(stageIndex) - return self._stagesInLaneByIndex[stageIndex] + return self._stagesInLaneByIndex[tostring(stageIndex)] end ---@return number? diff --git a/src/classes/stageClasses/Stages/BaseStage/Stage.lua b/src/classes/stageClasses/Stages/BaseStage/Stage.lua index 21bd59c..2a14a3d 100644 --- a/src/classes/stageClasses/Stages/BaseStage/Stage.lua +++ b/src/classes/stageClasses/Stages/BaseStage/Stage.lua @@ -162,6 +162,7 @@ function Stage:superNew(database, stageConfig, logger, initData, stageType, miss ---comment ---@param selfA Stage ---@param time number? + ---@return number|nil self.CheckContinuousAsync = function (selfA, time) selfA:CheckAndUpdateSelf() @@ -325,7 +326,9 @@ function Stage:GetStageName() return self.stageName end +---@return Array function Stage:GetMissions() + ---@type Array local missions = {} for _, mission in pairs(self._db.missions) do table.insert(missions, mission) @@ -674,6 +677,7 @@ function Stage:ActivateBlueStage() end ---@param selfA Stage + ---@return number|nil local ActivateBlueAsync = function(selfA) pcall(function() selfA:MarkStage() diff --git a/src/classes/stageClasses/drawings/helper/DrawingHelper.lua b/src/classes/stageClasses/drawings/helper/DrawingHelper.lua index aa90234..8c7a59c 100644 --- a/src/classes/stageClasses/drawings/helper/DrawingHelper.lua +++ b/src/classes/stageClasses/drawings/helper/DrawingHelper.lua @@ -54,7 +54,7 @@ local function MarkupToAll(shapeID, drawID, points, fillColor, lineColor, lineS if lineThickness == nil or lineThickness <= 0 then lineStyle = 0 end - + ---@type string local functionString = "trigger.action.markupToAll(" .. shapeID .. ", -1, " .. drawID .. "," for _, point in pairs(points) do @@ -125,14 +125,14 @@ function DrawingHelper.DrawPolygon(object) local fillColor = DrawingHelper.ColorToColorTable(free.fillColorString) local color = DrawingHelper.ColorToColorTable(free.colorString) local lineStyle = DrawingHelper.ToLineStyleInteger(free.style) - + ---@type Array local keys = {} for k, _ in pairs(free.points) do table.insert(keys, k) end table.sort(keys, function(a, b) return a < b end) - + ---@type Array local points = {} for _, k in ipairs(keys) do local point = free.points[k] @@ -274,6 +274,7 @@ function DrawingHelper.ColorTableToColorString(rgba) end ---@param lineStyle string +---@return integer function DrawingHelper.ToLineStyleInteger(lineStyle) lineStyle = lineStyle:lower() if lineStyle == "no line" then diff --git a/src/classes/stageClasses/helpers/BattleManager.lua b/src/classes/stageClasses/helpers/BattleManager.lua index 951767a..1af72fd 100644 --- a/src/classes/stageClasses/helpers/BattleManager.lua +++ b/src/classes/stageClasses/helpers/BattleManager.lua @@ -36,6 +36,7 @@ end ---@param self BattleManager ---@param time number +---@return number? local function CheckTask(self, time) local interval = self:Update() if not interval then return end @@ -148,7 +149,7 @@ end ---@return number function BattleManager:getBestAmmo(unit) - local ammo = unit:getAmmo() + local ammo = unit:getAmmo() --[[@as table]] if not ammo then return 3221225470, 1 end -- Default ammo if no ammo is found @@ -162,9 +163,9 @@ function BattleManager:getBestAmmo(unit) end end - local entry = Util.randomFromList(shells) + local entry = Util.randomFromList(shells) --[[@as table]] if entry and entry.desc and entry.desc.warhead then - local caliber = entry.desc.warhead.caliber + local caliber = entry.desc.warhead.caliber --[[@as number]] if caliber > 50 then return 258503344128, 1 else @@ -209,6 +210,7 @@ function BattleManager:ToShootingHulls(groups) end local hulls = Util.getSeparatedConvexHulls(points, 50) + ---@type Array> local enlargedHulls = {} for _, hull in pairs(hulls) do local enlarged = Util.enlargeConvexHull(hull, 25) diff --git a/src/classes/stageClasses/helpers/MissionCommandsHelper.lua b/src/classes/stageClasses/helpers/MissionCommandsHelper.lua index 9311bb6..ff7798c 100644 --- a/src/classes/stageClasses/helpers/MissionCommandsHelper.lua +++ b/src/classes/stageClasses/helpers/MissionCommandsHelper.lua @@ -7,7 +7,7 @@ local SupplyConfigHelper = require("classes.stageClasses.helpers.SupplyConfigHel local StageConfig = require("classes.configuration.StageConfig") ----@class MissionCommandsHelper +---@class MissionCommandsHelper : OnPlayerEnterUnitListener ---@field missionsByCode table @table of missions by their code ---@field enabledByCode table @table of enabled missions by their code ---@field updateNeeded boolean @flag to indicate if an update is needed @@ -369,7 +369,7 @@ function MissionCommandsHelper:AddAllMissionCommandsToGroup(groupID) do --- secondary missions local count = 0 local path = { [1] = folderNames.secondary } - + ---@type Array local secondaryMissions = {} for code, enabled in pairs(self.enabledByCode) do if enabled == true then diff --git a/src/classes/stageClasses/helpers/SupplyConfigHelper.lua b/src/classes/stageClasses/helpers/SupplyConfigHelper.lua index 885bd87..379a795 100644 --- a/src/classes/stageClasses/helpers/SupplyConfigHelper.lua +++ b/src/classes/stageClasses/helpers/SupplyConfigHelper.lua @@ -83,7 +83,8 @@ function SupplyConfigHelper.fromObjectName(name) return nil end ----@param type CrateType +---@param type CrateType +---@return SupplyConfig? function SupplyConfigHelper.getSupplyConfig(type) return SupplyConfig[type] end diff --git a/src/classes/stageClasses/helpers/SupplyUnitsTracker.lua b/src/classes/stageClasses/helpers/SupplyUnitsTracker.lua index 3256f8d..092bbc0 100644 --- a/src/classes/stageClasses/helpers/SupplyUnitsTracker.lua +++ b/src/classes/stageClasses/helpers/SupplyUnitsTracker.lua @@ -10,7 +10,7 @@ local SupplyLoadConfig = require("classes.stageClasses.helpers.SupplyLoadConfig" ---@field enteredSupplyHub fun(self:SupplyUnitEventListener, unit:Unit, hub:SupplyHub) | nil ---@field exitedSupplyHub fun(self:SupplyUnitEventListener, unit:Unit, hub:SupplyHub) | nil ----@class SupplyUnitsTracker +---@class SupplyUnitsTracker : OnPlayerEnterUnitListener ---@field private _supplyUnitsByName table ---@field private _cargoInUnits table> ---@field private _logger Logger @@ -43,6 +43,8 @@ function SupplyUnitsTracker.getOrCreate() SpearheadEvents.AddOnPlayerEnterUnitListener(singleton) ---@param selfA SupplyUnitsTracker + ---@param time number + ---@return number? local function updateTask(selfA, time) selfA:Update() @@ -134,6 +136,7 @@ end ---@private ---@param unit Unit +---@return boolean function SupplyUnitsTracker:IsSupplyUnit(unit) if unit == nil then return false end @@ -158,15 +161,17 @@ function SupplyUnitsTracker:AddCargoToUnit(unitID, crateType) local unit = DcsUtil.GetPlayerUnitByID(unitID) if unit == nil then return end - if self._cargoInUnits[unitID] == nil then - self._cargoInUnits[unitID] = {} + local unitIdStr = tostring(unitID) + + if self._cargoInUnits[unitIdStr] == nil then + self._cargoInUnits[unitIdStr] = {} end - if self._cargoInUnits[unitID][crateType] == nil then - self._cargoInUnits[unitID][crateType] = 0 + if self._cargoInUnits[unitIdStr][crateType] == nil then + self._cargoInUnits[unitIdStr][crateType] = 0 end - self._cargoInUnits[unitID][crateType] = self._cargoInUnits[unitID][crateType] + 1 + self._cargoInUnits[unitIdStr][crateType] = self._cargoInUnits[unitIdStr][crateType] + 1 end @@ -253,7 +258,7 @@ function SupplyUnitsTracker:CheckUnitsInZones() end end - self._unitPositions[unit:getID()] = pos + self._unitPositions[tostring(unit:getID())] = pos end end end @@ -323,6 +328,7 @@ function SupplyUnitsTracker:UnloadRequested(unitID, crateType, missionCommandsHe self:UpdateWeightForUnit(unit) cargoCount = cargoCount + 1 + ---@type {name: string, type: string, x: number, y: number} local cargoSpawnObject = { name = crateType .. "_" .. cargoCount, type = cargoConfig.staticType, @@ -484,7 +490,7 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject) end local objPos = foundObject:getPoint() - local box = desc.box + local box = desc.box --[[@type table]] local heading = 0 -- Try to get object heading from position vector's forward direction @@ -497,10 +503,10 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject) end) -- For rotated objects, we need to rotate the bounding box - local minX = box.min.x - local maxX = box.max.x - local minZ = box.min.z - local maxZ = box.max.z + local minX = box.min.x --[[@as number]] + local maxX = box.max.x --[[@as number]] + local minZ = box.min.z --[[@as number]] + local maxZ = box.max.z --[[@as number]] -- If object has significant rotation, apply rotation to bbox corners if math.abs(heading) > 0.1 then @@ -517,8 +523,8 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject) minZ, maxZ = math.huge, -math.huge for _, corner in ipairs(corners) do - local rotX = corner[1] * math.cos(heading) - corner[2] * math.sin(heading) - local rotZ = corner[1] * math.sin(heading) + corner[2] * math.cos(heading) + local rotX = corner[1] * math.cos(heading) - corner[2] * math.sin(heading) --[[@as number]] + local rotZ = corner[1] * math.sin(heading) + corner[2] * math.cos(heading) --[[@as number]] minX = math.min(minX, rotX) maxX = math.max(maxX, rotX) minZ = math.min(minZ, rotZ) @@ -587,7 +593,7 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName) return nil end - local crateRelativeBBox = crateDesc.box + local crateRelativeBBox = crateDesc.box --[[@as table]] -- Get drop zone config for this unit local dropZones = { @@ -610,8 +616,11 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName) radius = 100 -- Search a large area } } - + ---@type Array<{ pos: { x: number, y: number, z: number }, bbox: { min: { x: number, y: number, z: number }, max: { x: number, y: number, z: number } } }> local occupiedObjects = {} + + ---@param foundItem Object + ---@param _ any local found = function(foundItem, _) local bbox = self:GetBoundingBoxes(foundItem) if bbox then @@ -660,6 +669,7 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName) local candidateY = land.getHeight({ x = candidateX, y = candidateZ }) -- Convert crate's relative bbox to world space at this position + ---@type { min: { x: number, y: number, z: number }, max: { x: number, y: number, z: number } } local crateBBoxWorldSpace = { min = { x = candidateX + crateRelativeBBox.min.x, diff --git a/src/classes/stageClasses/missions/BuildableMission.lua b/src/classes/stageClasses/missions/BuildableMission.lua index e90202c..b8d0948 100644 --- a/src/classes/stageClasses/missions/BuildableMission.lua +++ b/src/classes/stageClasses/missions/BuildableMission.lua @@ -25,6 +25,8 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe local BuildableMission = {} BuildableMission.__index = BuildableMission +---@param siteType string +---@param coords string ---@return string local function getDefaultBriefing(siteType, coords) return "We've dispatched forward units to find a proper spot for a new " .. siteType .. "." .. @@ -43,6 +45,7 @@ end ---@param noLandingZone SpearheadTriggerZone? ---@param logger Logger ---@param briefing string? +---@return BuildableMission function BuildableMission.new(database, logger, targetZone, noLandingZone, requiredKilos, requiredCrateType, briefing) setmetatable(BuildableMission, Mission) @@ -117,6 +120,7 @@ function BuildableMission:ShowBriefing(groupID) local unitType = DcsUtil.getUnitTypeFromGroup(group) local coords = DcsUtil.convertVec2ToUnitUsableType(self.location, unitType) + if coords == nil then coords = "Could not make conversion" end local siteType = "FARP" if self._crateType == "SAM_CRATE" then @@ -143,17 +147,20 @@ function BuildableMission:ShowBriefing(groupID) trigger.action.outTextForGroup(groupID, briefing, GlobalConfig:getBriefingTime()) end +---@param groupID number function BuildableMission:MarkMissionAreaToGroup(groupID) - if self._markIDsPerGroup[groupID] then - DcsUtil.RemoveMark(self._markIDsPerGroup[groupID]) - end + local groupIdStr = tostring(groupID) + if self._markIDsPerGroup[groupIdStr] then + DcsUtil.RemoveMark(self._markIDsPerGroup[groupIdStr]) + end + ---@type string local text = "[" .. self.code .. "] " .. self.name .. " | " .. self._crateType local location = { x= self.location.x, y=land.getHeight(self.location), z=self.location.y } local markID = DcsUtil.AddMarkToGroup(groupID, text, location) - self._markIDsPerGroup[groupID] = markID + self._markIDsPerGroup[groupIdStr] = markID end ---@private @@ -197,6 +204,7 @@ function BuildableMission:SpawnActive() ---@param selfA BuildableMission ---@param time number + ---@return number? local checkForCrateTasks = function (selfA, time) selfA:CheckCratesInZone() diff --git a/src/classes/stageClasses/missions/RunwayStrikeMission.lua b/src/classes/stageClasses/missions/RunwayStrikeMission.lua index 0d6e658..4cbd019 100644 --- a/src/classes/stageClasses/missions/RunwayStrikeMission.lua +++ b/src/classes/stageClasses/missions/RunwayStrikeMission.lua @@ -24,6 +24,7 @@ local RunwayStrikeMission = {} ---@param runway Runway ---@param database Database ---@param logger Logger +---@param airbaseName string ---@param runwayBombingTracker RunwayBombingTracker ---@return RunwayStrikeMission? function RunwayStrikeMission.new(runway, airbaseName, database, logger, runwayBombingTracker) @@ -205,8 +206,9 @@ function RunwayStrikeMission:StartRepair() self._repairInProgress = true self._logger:debug("Starting repair of runway strike mission " .. self._airportName .. ":" .. self._runway.Name) ---comment - ---@param selfA any - ---@return unknown + ---@param selfA RunwayStrikeMission + ---@param time number + ---@return number? local repairTask = function (selfA, time) local interval = selfA:DoRepairCycle() if interval == nil then return nil end @@ -215,6 +217,7 @@ function RunwayStrikeMission:StartRepair() timer.scheduleFunction(repairTask, self, timer.getTime() + 5) end +---@return number? function RunwayStrikeMission:DoRepairCycle() local interval = 5 @@ -247,12 +250,14 @@ function RunwayStrikeMission:DoRepairCycle() end ----@class StaticSpawn +---@class StaticSpawn : table ---@field category string ---@field type string ---@field y number ---@field x number ---@field heading number +---@field name string? +---@field hidden boolean? local counter = 1 @@ -441,6 +446,7 @@ end ---@private ---@param runway Runway +---@param numSections number ---@return Array function RunwayStrikeMission:ToSections(runway, numSections) diff --git a/src/classes/stageClasses/missions/ZoneMission.lua b/src/classes/stageClasses/missions/ZoneMission.lua index c87ce14..5139a8b 100644 --- a/src/classes/stageClasses/missions/ZoneMission.lua +++ b/src/classes/stageClasses/missions/ZoneMission.lua @@ -240,7 +240,7 @@ function ZoneMission:UpdateState(checkHealth, messageIfDone) local staticObject = StaticObject.getByName(unitName) if staticObject then if staticObject:isExist() == true then - local life0 = staticObject:getDesc().life + local life0 = staticObject:getDesc().life --[[@as number]] if staticObject:getLife() / life0 < 0.3 then self._logger:debug("exploding unit") trigger.action.explosion(staticObject:getPoint(), 100) @@ -286,7 +286,9 @@ function ZoneMission:UpdateState(checkHealth, messageIfDone) end if self._missionGroups.hasTargets == true then + ---@type number local total = 0 + ---@type number local alive = 0 for _, units in pairs(self._missionGroups.targetsAlive) do @@ -299,13 +301,13 @@ function ZoneMission:UpdateState(checkHealth, messageIfDone) end for _, sceneryObject in pairs(self._missionGroups.sceneryTargets) do - total = total + 1 + total = total + 1 --[[@as number]] if sceneryObject:IsAlive() == true then alive = alive + 1 end end - local deadRatio = (total - alive) / total + local deadRatio = (total - alive) / total --[[@as number]] if deadRatio >= self._completeAtIndex then self._logger:debug("Dead ratio " .. self.zoneName .. deadRatio .. " >= " .. self._completeAtIndex) self._state = "COMPLETED" @@ -477,6 +479,7 @@ function ZoneMission:OnUnitLost(object) local category = Object.getCategory(object) if category == Object.Category.UNIT then + object = object --[[@as Unit]] local unitName = object:getName() self._logger:debug("UnitName:" .. unitName) @@ -487,6 +490,7 @@ function ZoneMission:OnUnitLost(object) self._missionGroups.targetsAlive[groupName][unitName] = false end elseif category == Object.Category.STATIC then + object = object --[[@as StaticObject]] local name = object:getName() self._missionGroups.unitsAlive[name][name] = false diff --git a/src/classes/stageClasses/missions/baseMissions/Mission.lua b/src/classes/stageClasses/missions/baseMissions/Mission.lua index 9fdabfb..8890a3a 100644 --- a/src/classes/stageClasses/missions/baseMissions/Mission.lua +++ b/src/classes/stageClasses/missions/baseMissions/Mission.lua @@ -86,6 +86,7 @@ function Mission:ShowBriefing(groupId) local unitType = DcsUtil.getUnitTypeFromGroup(group) local coords = DcsUtil.convertVec2ToUnitUsableType(self.location, unitType) + if coords == nil then coords = "Could not make conversion" end self._logger:debug("Coords converted: " .. coords) local stateString = self:ToStateString() diff --git a/src/classes/util/DcsUtil.lua b/src/classes/util/DcsUtil.lua index a59ffd9..434f585 100644 --- a/src/classes/util/DcsUtil.lua +++ b/src/classes/util/DcsUtil.lua @@ -40,7 +40,7 @@ do -- INIT DCS_UTIL ---@field zone_type SpearheadTriggerZoneType ---@field properties Array? - ---@type Array + ---@type table DCS_UTIL.__trigger_zones = {} end @@ -66,12 +66,15 @@ do -- INIT DCS_UTIL STATIC = 5 --CUSTOM CATEGORY } + ---@type table DCS_UTIL.__airbaseNamesById = {} ---@type table DCS_UTIL.__airbaseZonesByName = {} + ---@type table DCS_UTIL.__airportsStartingCoalition = {} + ---@type table DCS_UTIL.__warehouseStartingCoalition = {} function DCS_UTIL.__INIT() do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment @@ -104,8 +107,8 @@ do -- INIT DCS_UTIL if trigger_zone.properties then for _, kvPair in pairs(trigger_zone.properties) do - local key = kvPair["key"] - local value = kvPair["value"] + local key = kvPair.key + local value = kvPair.value zone.properties[#zone.properties + 1] = { key = key, value = value } end end @@ -116,6 +119,7 @@ do -- INIT DCS_UTIL do -- init airports and warehouses if env.warehouses.airports then + env.warehouses.airports = env.warehouses.airports --[[@as table]] for warehouse_id, value in pairs(env.warehouses.airports) do if warehouse_id ~= nil then warehouse_id = tostring(warehouse_id) or "nil" @@ -126,12 +130,12 @@ do -- INIT DCS_UTIL end if env.warehouses.warehouses then - DCS_UTIL.__warehouseStartingCoalition[-1] = "placeholder" + env.warehouses.warehouses = env.warehouses.warehouses --[[@as table]] for warehouse_id, value in pairs(env.warehouses.warehouses) do if warehouse_id ~= nil then - warehouse_id = tostring(warehouse_id) or "nil" + local warehouse_id_str = tostring(warehouse_id) or "nil" local coalitionNumber = DCS_UTIL.stringToCoalition(value.coalition) - DCS_UTIL.__warehouseStartingCoalition[warehouse_id] = coalitionNumber + DCS_UTIL.__warehouseStartingCoalition[warehouse_id_str] = coalitionNumber end end end @@ -218,11 +222,13 @@ do -- INIT DCS_UTIL end end + --- takes a list of units and returns all the units that are in any of the zones - ---@param unit_names table unit names - ---@param zone_names table zone names - ---@return table unit list of objects { unit = UNIT, zone_name = zoneName} + ---@param unit_names Array unit names + ---@param zone_names Array zone names + ---@return table function DCS_UTIL.getUnitsInZones(unit_names, zone_names) + ---@type Array local units = {} ---@type Array @@ -241,14 +247,19 @@ do -- INIT DCS_UTIL zones[#zones + 1] = zone end end - + ---@type table local in_zone_units = {} for units_ind = 1, #units do local lUnit = units[units_ind] - local unit_pos = lUnit:getPosition().p + local isActive = true local lCat = Object.getCategory(lUnit) - for _, zone in pairs(zones) do - if unit_pos and ((lCat == 1 and lUnit:isActive() == true) or lCat ~= 1) then -- it is a unit and is active or it is not a unit + if lCat == Object.Category.UNIT then + local unit = lUnit --[[@as Unit]] + isActive = unit:isActive() == true + end + local unit_pos = lUnit:getPosition().p + for _, zone in pairs(zones) do + if unit_pos and isActive == true then -- it is a unit and is active or it is not a unit local isInZone = Util.is3dPointInZone(unit_pos, zone) if isInZone == true then in_zone_units[#in_zone_units + 1] = { unit = lUnit, zone_name = zone.name } @@ -262,9 +273,9 @@ do -- INIT DCS_UTIL --- takes a list of groups and returns all the group leaders that are in any of the zones ---@param group_names table unit names ---@param zone_name string zone names - ---@return table groupnames list of group names + ---@return Array groupnames list of group names function DCS_UTIL.getGroupsInZone(group_names, zone_name) - local zone = DCS_UTIL.__trigger_zones[zone_name] + local zone = DCS_UTIL.__trigger_zones[zone_name] --[[@as SpearheadTriggerZone?]] if zone == nil then return {} end @@ -277,6 +288,7 @@ do -- INIT DCS_UTIL ---@param zone SpearheadTriggerZone ---@return Array groupnames list of groups that are in the zone function DCS_UTIL.areGroupsInCustomZone(group_names, zone) + ---@type Array<{ unit : Unit|StaticObject, groupname: string }> local units = {} if Util.tableLength(group_names) < 1 then return {} end @@ -308,8 +320,8 @@ do -- INIT DCS_UTIL --- takes a x, y poistion and checks if it is inside any of the zones ---@param x number North South position ---@param z number West East position - ---@param zone_names table zone names - ---@return table zones list of objects { zone_name = zoneName} + ---@param zone_names Array zone names + ---@return Array zones list of objects { zone_name = zoneName} function DCS_UTIL.isPositionInZones(x, z, zone_names) ---@type Array local zones = {} @@ -319,7 +331,7 @@ do -- INIT DCS_UTIL zones[#zones + 1] = zone end end - + ---@type Array local result_zones = {} for _, zone in pairs(zones) do if Util.is3dPointInZone({ x = x, z = z, y = 0 }, zone) == true then @@ -396,6 +408,18 @@ do -- INIT DCS_UTIL return nil; end + ---@return Array + function DCS_UTIL.getAllGroupCategoryNames() + return { + "airplane", + "helicopter", + "ground", + "ship", + "train", + "static" + } + end + ---@type table local config = { @@ -408,7 +432,8 @@ do -- INIT DCS_UTIL ---@param location Vec2 - ---@param unitType string + ---@param unitType string? + ---@return string? function DCS_UTIL.convertVec2ToUnitUsableType(location, unitType) local height = land.getHeight(location) @@ -429,6 +454,7 @@ do -- INIT DCS_UTIL ---@private ---@param location Vec3 ---@param coordType CoordType + ---@return string? function DCS_UTIL.convertToDisplayCoord(location, coordType) local lattitude, longitude, altitude = coord.LOtoLL(location) @@ -440,7 +466,7 @@ do -- INIT DCS_UTIL -- Convert DD to DDM (Degrees Decimal Minutes) local function dd_to_ddm(dd) local degrees = math.floor(math.abs(dd)) - local minutes = (math.abs(dd) - degrees) * 60 + local minutes = (math.abs(dd) - degrees) * 60 --[[@as number]] local sign = dd >= 0 and 1 or -1 return degrees * sign, minutes end @@ -559,6 +585,7 @@ do -- INIT DCS_UTIL end ---@param group Group + ---@return string? unit type name function DCS_UTIL.getUnitTypeFromGroup(group) for _, unit in pairs(group:getUnits()) do if unit and unit:isExist() then @@ -571,6 +598,7 @@ do -- INIT DCS_UTIL ---comment Get all units that are players ---@return Array units function DCS_UTIL.getAllPlayerUnits() + ---@type Array local units = {} for i = 0, 2 do local players = coalition.getPlayers(i) @@ -616,6 +644,7 @@ do -- INIT DCS_UTIL return result end + ---@param unitName string function DCS_UTIL.CleanCorpse(unitName) unitName = "dead_" .. unitName local object = StaticObject.getByName(unitName) @@ -734,6 +763,8 @@ do -- INIT DCS_UTIL return false end + ---@param groupName string + ---@param offset number? ---@return boolean function DCS_UTIL.IsBingoFuel(groupName, offset) if offset == nil then offset = 0 end diff --git a/src/classes/util/MissionEditorWarnings.lua b/src/classes/util/MissionEditorWarnings.lua index a5ff7ea..88b1fdd 100644 --- a/src/classes/util/MissionEditorWarnings.lua +++ b/src/classes/util/MissionEditorWarnings.lua @@ -1,8 +1,12 @@ ---@class MissionEditingWarnings local MissionEditingWarnings = {} + +---@type table +MissionEditingWarnings.warnings = {} + function MissionEditingWarnings.Add(warningMessage) - table.insert(MissionEditingWarnings, warningMessage or "skip") + table.insert(MissionEditingWarnings.warnings, warningMessage or "skip") end ---@param logger Logger @@ -12,12 +16,12 @@ function MissionEditingWarnings.WriteAll(logger) return end - if not MissionEditingWarnings or #MissionEditingWarnings == 0 then + if not MissionEditingWarnings.warnings or #MissionEditingWarnings.warnings == 0 then return end logger:warn("Mission Editor Warnings:") - for _, warning in ipairs(MissionEditingWarnings) do + for _, warning in ipairs(MissionEditingWarnings.warnings) do logger:warn("- " .. warning) end diff --git a/src/classes/util/Util.lua b/src/classes/util/Util.lua index d6a80d9..23688c3 100644 --- a/src/classes/util/Util.lua +++ b/src/classes/util/Util.lua @@ -22,7 +22,7 @@ do -- INIT UTIL end ---comment - ---@param table any + ---@param table table ---@return number function UTIL.tableLength(table) if table == nil then return 0 end @@ -35,23 +35,34 @@ do -- INIT UTIL ---@param orig table ---@return table copy function UTIL.deepCopyTable(orig) - local orig_type = type(orig) - local copy - if orig_type == 'table' then - copy = {} - for orig_key, orig_value in next, orig, nil do - copy[UTIL.deepCopyTable(orig_key)] = UTIL.deepCopyTable(orig_value) + + ---@param original any + ---@return any + local function deepCopy(original) + local orig_type = type(original) + ---@type any + local copy + if orig_type == 'table' then + original = original --[[@as table]] + copy = {} --[[@as table]] + for orig_key, orig_value in pairs(original) do + local copiedKey = deepCopy(orig_key) --[[@as any]] + copy[copiedKey] = deepCopy(orig_value) + end + setmetatable(copy, deepCopy(getmetatable(original))) + else -- number, string, boolean, etc + copy = original --[[@as any]] end - setmetatable(copy, UTIL.deepCopyTable(getmetatable(orig))) - else -- number, string, boolean, etc - copy = orig + return copy end - return copy + + return deepCopy(orig) end ---Gets a random from the list - ---@param list Array - ---@return any @random element from the list + ---@generic T + ---@param list Array + ---@return T @random element from the list function UTIL.randomFromList(list) local max = #list @@ -65,11 +76,13 @@ do -- INIT UTIL return list[random] end - ---@param list Array + ---@generic T + ---@param list Array ---@param start number start ---@param n number length - ---@return Array + ---@return Array function UTIL.sublist(list, start, n) + ---@type table local result = {} for i = start, n do result[#result + 1] = list[i] @@ -90,9 +103,10 @@ do -- INIT UTIL end local function table_print(tt, indent, done) - done = done or {} + done = done or {} --[[@as table]] indent = indent or 0 if type(tt) == "table" then + tt = tt --[[@as table]] local sb = {} for key, value in pairs(tt) do table.insert(sb, string.rep(" ", indent)) -- indent it @@ -146,7 +160,7 @@ do -- INIT UTIL ---comment ---@param str string - ---@param findableTable table + ---@param findableTable table ---@return boolean UTIL.startswithAny = function(str, findableTable) for _, value in pairs(findableTable) do @@ -244,6 +258,7 @@ do -- INIT UTIL ---@return boolean local function isInComplexPolygon(polygon, x, y) ---@param poly Array of pairs { x, y } + ---@return Array<{ x1: number, z1: number, x2: number, z2: number }> local function getEdges(poly) local result = {} for i = 1, #poly do @@ -280,6 +295,7 @@ do -- INIT UTIL ---@param point Vec3 ---@param zone SpearheadTriggerZone + ---@return boolean function UTIL.is3dPointInZone(point, zone) if zone.zone_type == "Polygon" and zone.verts then if UTIL.IsPointInPolygon(zone.verts, point.x, point.z) == true then @@ -296,6 +312,7 @@ do -- INIT UTIL ---@param point Vec2 ---@param zone SpearheadTriggerZone + ---@return boolean function UTIL.is2dPointInZone(point, zone) if zone.zone_type == "Polygon" and zone.verts then if UTIL.IsPointInPolygon(zone.verts, point.x, point.y) == true then @@ -447,6 +464,8 @@ do -- INIT UTIL end ---@param points Array + ---@param meters number + ---@return Array function UTIL.enlargeConvexHull(points, meters) if points == nil or #points == 0 then return {} @@ -524,6 +543,10 @@ function UTIL.GetTangentHullPointsFromOrigin(hull, origin) return {} end + ---@param a Vec2 + ---@param b Vec2 + ---@param c Vec2 + ---@return number local function orientation(a, b, c) -- Returns >0 if c is to the left of ab, <0 if to the right, 0 if colinear return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)