diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 11b0142..760529d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,10 +1,11 @@ #start -name: update newsletters +name: Release on: push: branches: - main + - develop jobs: buildandpush: @@ -61,8 +62,16 @@ jobs: - run: npm i markdown-to-html-cli -g - run: markdown-to-html --title 'Spearhead' --dark-mode auto --keywords "dcs,spearhead,tdcs,mission,campaign,tactical dcs,tactical" --no-dark-mode --markdown-style-theme dark --source ./spearhead/_docs/$sourcefileA.md --output ./$repo/Spearhead/$sourcefileA.html - run: markdown-to-html --title 'Spearhead' --dark-mode auto --keywords "dcs,spearhead,tdcs,mission,campaign,tactical dcs,tactical" --no-dark-mode --markdown-style-theme dark --source ./spearhead/_docs/$sourcefileB.md --output ./$repo/Spearhead/$sourcefileB.html + - run: python3 ./spearhead/SpearheadCompile.py "./spearhead" "./$repo/Spearhead/spearhead.lua" - - run: cp "./spearhead/config.lua" "./$repo/Spearhead/spearheadConfig.lua" + if: github.ref == 'refs/heads/master' + + - run: mkdir -p ./$repo/Spearhead/beta + if: github.ref == 'refs/heads/develop' + + - run: python3 ./spearhead/SpearheadCompile.py "./spearhead" "./$repo/Spearhead/beta/spearhead.lua" + if: github.ref == 'refs/heads/develop' + - run: cp -a ./spearhead/_docs/img/. ./$repo/Spearhead/img/ - name: ls run: ls diff --git a/_docs/GetStarted.md b/_docs/GetStarted.md index 795632a..cf7b631 100644 --- a/_docs/GetStarted.md +++ b/_docs/GetStarted.md @@ -14,6 +14,8 @@ In the example we'll show how you can create a simple island hopping mission Firstly include the script. Download Script +
Or if you want to use the latest beta version: +Download Beta Script Then run the script in the mission.
Please do exactly as it's done below.
diff --git a/_miz/SPEARHEADDEV.miz b/_miz/SPEARHEADDEV.miz index b12706e..aad247d 100644 Binary files a/_miz/SPEARHEADDEV.miz and b/_miz/SPEARHEADDEV.miz differ diff --git a/_miz/SPEARHEADEXAMPLE.miz b/_miz/SPEARHEADEXAMPLE.miz index d69c3eb..2b3ba55 100644 Binary files a/_miz/SPEARHEADEXAMPLE.miz and b/_miz/SPEARHEADEXAMPLE.miz differ diff --git a/classes/configuration/CapConfig.lua b/classes/configuration/CapConfig.lua index 22488b7..bb277c6 100644 --- a/classes/configuration/CapConfig.lua +++ b/classes/configuration/CapConfig.lua @@ -8,7 +8,8 @@ function CapConfig:new() if SpearheadConfig == nil then SpearheadConfig = {} end if SpearheadConfig.CapConfig == nil then SpearheadConfig.CapConfig = {} end - local enabled = SpearheadConfig.CapConfig.enabled or true + local enabled = SpearheadConfig.CapConfig.enabled + if enabled == nil then enabled = true end ---@return boolean o.isEnabled = function(self) return enabled == true end diff --git a/classes/configuration/StageConfig.lua b/classes/configuration/StageConfig.lua index e86b0fc..07afd90 100644 --- a/classes/configuration/StageConfig.lua +++ b/classes/configuration/StageConfig.lua @@ -7,22 +7,35 @@ function StageConfig:new() if SpearheadConfig == nil then SpearheadConfig = {} end if SpearheadConfig.StageConfig == nil then SpearheadConfig.StageConfig = {} end - local enabled = SpearheadConfig.StageConfig.enabled or true + local enabled = SpearheadConfig.StageConfig.enabled + if enabled == nil then enabled = true end ---@return boolean o.isEnabled = function(self) return enabled == true end - local drawStages = SpearheadConfig.StageConfig.drawStages or true + local drawStages = SpearheadConfig.StageConfig.drawStages + if drawStages == nil then drawStages = true end ---@return boolean o.isDrawStagesEnabled = function(self) return drawStages == true end local autoStages = SpearheadConfig.StageConfig.autoStages or true + if autoStages == nil then autoStages = true end ---@return boolean o.isAutoStages = function(self) return autoStages end local maxMissionsPerStage = SpearheadConfig.StageConfig.maxMissionStage o.getMaxMissionsPerStage = function(self) return maxMissionsPerStage end - o.logLevel = Spearhead.LoggerTemplate.LogLevelOptions.DEBUG + o.logLevel = Spearhead.LoggerTemplate.LogLevelOptions.INFO + + o.toString = function() + return Spearhead.Util.toString({ + maxMissionsPerStage = maxMissionsPerStage, + enabled = enabled, + drawStages = drawStages, + autoStages = autoStages + }) + end + return o; end diff --git a/classes/fleetClasses/GlobalFleetManager.lua b/classes/fleetClasses/GlobalFleetManager.lua index ec546a6..0a718f1 100644 --- a/classes/fleetClasses/GlobalFleetManager.lua +++ b/classes/fleetClasses/GlobalFleetManager.lua @@ -6,7 +6,7 @@ local fleetGroups = {} GlobalFleetManager.start = function(database) - local logger = Spearhead.LoggerTemplate:new("CARRIERFLEET", Spearhead.LoggerTemplate.LogLevelOptions.DEBUG) + local logger = Spearhead.LoggerTemplate:new("CARRIERFLEET", Spearhead.LoggerTemplate.LogLevelOptions.INFO) local all_groups = Spearhead.DcsUtil.getAllGroupNames() for _, groupName in pairs(all_groups) do @@ -18,4 +18,5 @@ GlobalFleetManager.start = function(database) end end +if not Spearhead.internal then Spearhead.internal = {} end Spearhead.internal.GlobalFleetManager = GlobalFleetManager \ No newline at end of file diff --git a/classes/spearhead_base.lua b/classes/spearhead_base.lua index 3d36cdb..afdd20d 100644 --- a/classes/spearhead_base.lua +++ b/classes/spearhead_base.lua @@ -445,7 +445,11 @@ do -- INIT DCS_UTIL ---checks if the groupname is a static group ---@param groupName any function DCS_UTIL.IsGroupStatic(groupName) - return DCS_UTIL.__miz_groups[groupName].category == 5; + if DCS_UTIL.__miz_groups[groupName] then + return DCS_UTIL.__miz_groups[groupName].category == 5; + end + + return StaticObject.getByName(groupName) ~= nil end ---comment @@ -739,8 +743,8 @@ do -- INIT DCS_UTIL ---@return table units function DCS_UTIL.getAllPlayerUnits() local units = {} - for key, value in pairs({ 1, 2, 3 }) do - local players = coalition.getPlayers(value) + for i = 0,2 do + local players = coalition.getPlayers(i) for key, unit in pairs(players) do units[#units + 1] = unit end @@ -782,29 +786,6 @@ do -- INIT DCS_UTIL return result end - ---Gets all groups that have players - ---@return table groups - function DCS_UTIL.getAllPlayerGroups() - local groupNames = {} - local result = {} - for key, value in pairs({ 1, 2, 3 }) do - local players = coalition.getPlayers(value) - for key, unit in pairs(players) do - local group = unit:getGroup() - if group ~= nil then - local name = group:getName() - if name ~= nil then - if groupNames[name] ~= nil then - groupNames[name] = 1 - table.insert(result, group) - end - end - end - end - end - return result - end - --- spawns the units as specified in the mission file itself --- location and route can be nil and will then use default route ---@param groupName string diff --git a/classes/spearhead_db.lua b/classes/spearhead_db.lua index 0a59114..a2420b1 100644 --- a/classes/spearhead_db.lua +++ b/classes/spearhead_db.lua @@ -358,6 +358,7 @@ do -- DB functionString = functionString .. "{0,1,0,1}, {0,1,0,1}, 1)" env.info(functionString) +---@diagnostic disable-next-line: deprecated local f, err = loadstring(functionString) if f then f() diff --git a/classes/spearhead_events.lua b/classes/spearhead_events.lua index bebb601..3adda59 100644 --- a/classes/spearhead_events.lua +++ b/classes/spearhead_events.lua @@ -1,18 +1,24 @@ local SpearheadEvents = {} do - local SpearheadLogger = Spearhead.LoggerTemplate:new("Spearhead Events", - Spearhead.LoggerTemplate.LogLevelOptions.INFO) - do -- STAGE NUMBER CHANGED local OnStageNumberChangedListeners = {} local OnStageNumberChangedHandlers = {} + + local warn = function(text) + env.warn("[Spearhead][Events] " .. (text or "nil")) + end + + local error = function(text) + env.error("[Spearhead][Events] " .. (text or "nil")) + end + ---Add a stage zone number changed listener ---@param listener table object with function OnStageNumberChanged(self, number) SpearheadEvents.AddStageNumberChangedListener = function(listener) if type(listener) ~= "table" then - SpearheadLogger:warn("Event listener not of type table, did you mean to use handler?") + warn("Event listener not of type table, did you mean to use handler?") return end table.insert(OnStageNumberChangedListeners, listener) @@ -22,7 +28,7 @@ do ---@param handler function function(number) SpearheadEvents.AddStageNumberChangedHandler = function(handler) if type(handler) ~= "function" then - SpearheadLogger:warn("Event handler not of type function, did you mean to use listener?") + warn("Event handler not of type function, did you mean to use listener?") return end table.insert(OnStageNumberChangedHandlers, handler) @@ -35,31 +41,31 @@ do callable:OnStageNumberChanged(newStageNumber) end) if err then - SpearheadLogger:error(err) + error(err) end end for _, callable in pairs(OnStageNumberChangedHandlers) do local succ, err = pcall(callable, newStageNumber) if err then - SpearheadLogger:error(err) + error(err) end end end end + + 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) SpearheadEvents.addOnUnitLandEventListener = function(unitName, landListener) if type(landListener) ~= "table" then - SpearheadLogger:warn("Event handler not of type table/object") + warn("Event handler not of type table/object") return end - SpearheadLogger:debug("Added Land event handler for unit: " .. unitName) - if onLandEventListeners[unitName] == nil then onLandEventListeners[unitName] = {} end @@ -73,7 +79,7 @@ do ---@param unitLostListener table Object with function: OnUnitLost(initiatorUnit) SpearheadEvents.addOnUnitLostEventListener = function(unitName, unitLostListener) if type(unitLostListener) ~= "table" then - SpearheadLogger:warn("Unit lost Event listener not of type table/object") + warn("Unit lost Event listener not of type table/object") return end @@ -92,7 +98,7 @@ do ---@param handlingObject table object with OnGroupRTB(self, groupName) SpearheadEvents.addOnGroupRTBListener = function(groupName, handlingObject) if type(handlingObject) ~= "table" then - SpearheadLogger:warn("Event handler not of type table/object") + warn("Event handler not of type table/object") return end @@ -106,7 +112,6 @@ do ---Publish the Group to RTB ---@param groupName string SpearheadEvents.PublishRTB = function(groupName) - SpearheadLogger:debug("Publishing RTB event for group " .. groupName) if groupName ~= nil then if OnGroupRTBListeners[groupName] then for _, callable in pairs(OnGroupRTBListeners[groupName]) do @@ -114,7 +119,7 @@ do callable:OnGroupRTB(groupName) end) if err then - SpearheadLogger:error(err) + error(err) end end end @@ -128,7 +133,7 @@ do ---@param handlingObject table object with OnGroupRTBInTen(self, groupName) SpearheadEvents.addOnGroupRTBInTenListener = function(groupName, handlingObject) if type(handlingObject) ~= "table" then - SpearheadLogger:warn("Event handler not of type table/object") + warn("Event handler not of type table/object") return end @@ -142,7 +147,6 @@ do ---Publish the Group is RTB ---@param groupName string SpearheadEvents.PublishRTBInTen = function(groupName) - SpearheadLogger:debug("Publishing RTB in TEN event for group " .. groupName) if groupName ~= nil then if OnGroupRTBInTenListeners[groupName] then for _, callable in pairs(OnGroupRTBInTenListeners[groupName]) do @@ -150,7 +154,7 @@ do callable:OnGroupRTBInTen(groupName) end) if err then - SpearheadLogger:error(err) + error(err) end end end @@ -165,7 +169,7 @@ do ---@param groupName string the groupname to expect SpearheadEvents.addOnGroupOnStationListener = function(groupName, handlingObject) if type(handlingObject) ~= "table" then - SpearheadLogger:warn("Event handler not of type table/object") + warn("Event handler not of type table/object") return end @@ -179,7 +183,6 @@ do ---Publish the Group to RTB ---@param groupName string SpearheadEvents.PublishOnStation = function(groupName) - SpearheadLogger:debug("Publishing onStation event for group " .. groupName) if groupName ~= nil then if OnGroupOnStationListeners[groupName] then for _, callable in pairs(OnGroupOnStationListeners[groupName]) do @@ -187,7 +190,7 @@ do callable:OnGroupOnStation(groupName) end) if err then - SpearheadLogger:error(err) + error(err) end end end @@ -202,7 +205,7 @@ do ---@param listener table object with OnStatusRequestReceived(self, groupId) SpearheadEvents.AddOnStatusRequestReceivedListener = function(listener) if type(listener) ~= "table" then - SpearheadLogger:warn("Unit lost Event listener not of type table/object") + warn("Unit lost Event listener not of type table/object") return end @@ -231,10 +234,10 @@ do do -- PLAYER ENTER UNIT local playerEnterUnitListeners = {} ---comment - ---@param listener table object with OnPlayerEnterUnit(self, unit) + ---@param listener table object with OnPlayerEntersUnit(self, unit) SpearheadEvents.AddOnPlayerEnterUnitListener = function(listener) if type(listener) ~= "table" then - SpearheadLogger:warn("Unit lost Event listener not of type table/object") + warn("Unit lost Event listener not of type table/object") return end @@ -246,10 +249,10 @@ do if playerEnterUnitListeners then for _, callable in pairs(playerEnterUnitListeners) do local succ, err = pcall(function() - callable:OnPlayerEnterUnit(unit) + callable:OnPlayerEntersUnit(unit) end) if err then - SpearheadLogger:error(err) + error(err) end end end @@ -270,7 +273,7 @@ do callable:OnUnitLanded(unit, airbase) end) if err then - SpearheadLogger:error(err) + error(err) end end end @@ -289,16 +292,51 @@ do end) if err then - SpearheadLogger:error(err) + error(err) end end end end - if event.id == world.event.S_EVENT_PLAYER_ENTER_UNIT then - env.info("blaat player entering unit") - local groupId = event.initiator:getGroup():getID() - SpearheadEvents.AddCommandsToGroup(groupId) + local AI_GROUPS = {} + + local function CheckAndTriggerSpawnAsync(unit, time) + local function isPlayer(unit) + if unit == nil then return false, "unit is nil" end + if unit:isExist() ~= true then return false, "unit does not exist" end + local group = unit:getGroup() + if group ~= nil then + if Spearhead.DcsUtil.IsGroupStatic(group:getName()) == true then + return false + end + + if AI_GROUPS[group:getName()] == true then + return false + end + + local players = Spearhead.DcsUtil.getAllPlayerUnits() + local unitName = unit:getName() + for i, unit in pairs(players) do + if unit:getName() == unitName then + return true + end + end + AI_GROUPS[group:getName()] = true + end + return false, "unit is nil or does not exist" + end + + if isPlayer(unit) == true then + local groupId = unit:getGroup():getID() + SpearheadEvents.AddCommandsToGroup(groupId) + SpearheadEvents.TriggerPlayerEntersUnit(unit) + end + + return nil + end + + if event.id == world.event.S_EVENT_BIRTH then + timer.scheduleFunction(CheckAndTriggerSpawnAsync, event.initiator, timer.getTime() + 3) end end diff --git a/classes/stageClasses/GlobalStageManager.lua b/classes/stageClasses/GlobalStageManager.lua index 767c8ff..30b41bd 100644 --- a/classes/stageClasses/GlobalStageManager.lua +++ b/classes/stageClasses/GlobalStageManager.lua @@ -6,12 +6,13 @@ local StagesByIndex = {} GlobalStageManager = {} function GlobalStageManager:NewAndStart(database, stageConfig) - + local logger = Spearhead.LoggerTemplate:new("StageManager", stageConfig.logLevel) local o = {} setmetatable(o, { __index = self }) - o.onStageCompleted = function(stage) + o.logger = logger + o.onStageCompleted = function(self, stage) local stageNumber = tostring(stage.stageNumber) local anyActive = false for _, stage in pairs(StagesByIndex[stageNumber] or {}) do @@ -24,8 +25,6 @@ function GlobalStageManager:NewAndStart(database, stageConfig) end - local logger = Spearhead.LoggerTemplate:new("StageManager", stageConfig.logLevel) - for _, stageName in pairs(database:getStagezoneNames()) do local stagelogger = Spearhead.LoggerTemplate:new(stageName, stageConfig.logLevel) diff --git a/classes/stageClasses/Mission.lua b/classes/stageClasses/Mission.lua index 9409d5b..aadc136 100644 --- a/classes/stageClasses/Mission.lua +++ b/classes/stageClasses/Mission.lua @@ -183,17 +183,35 @@ do -- INIT Mission Class timer.scheduleFunction(CheckAndUpdate, self, timer.getTime() + 300) end - local CleanupDelayedAsync = function (self, time) - self:Cleanup() - return nil - end - ---comment ---@param self table ---@param checkUnitHealth boolean? o.CheckAndUpdateSelf = function(self, checkUnitHealth) if not checkUnitHealth then checkUnitHealth = false end + if checkUnitHealth == true then + local function unitAliveState(unitName) + local unit = Unit.getByName(unitName) + return unit ~= nil and unit:isExist() == true and unit:getLife() > 0.1 + end + + for groupName, unitNameDict in pairs(self.groupUnitAliveDict) do + for unitName, isAlive in pairs(unitNameDict) do + if isAlive == true then + self.groupUnitAliveDict[groupName][unitName] = unitAliveState(unitName) + end + end + end + + for groupName, unitNameDict in pairs(self.targetAliveStates) do + for unitName, isAlive in pairs(unitNameDict) do + if isAlive == true then + self.targetAliveStates[groupName][unitName] = unitAliveState(unitName) + end + end + end + end + if self.missionState == Mission.MissionState.COMPLETED then return end diff --git a/classes/stageClasses/Stage.lua b/classes/stageClasses/Stage.lua index 84b0e17..ae05045 100644 --- a/classes/stageClasses/Stage.lua +++ b/classes/stageClasses/Stage.lua @@ -41,7 +41,7 @@ do --init STAGE DIRECTOR o.db.blueSamGroups = {} o.db.airbaseIds = {} o.db.farps = {} - o.activeStage = 0 + o.activeStage = -99 o.preActivated = false o.stageConfig = stageConfig or {} o.stageDrawingId = stageDrawingId + 1 @@ -146,7 +146,6 @@ do --init STAGE DIRECTOR end end - o.IsComplete = function(self) for i, mission in pairs(self.db.missions) do local state = mission:GetState() @@ -157,6 +156,19 @@ do --init STAGE DIRECTOR return true end + local CheckContinuousAsync = function(self, time) + self.logger:info("Checking stage completion for stage: " .. self.zoneName) + if self.activeStage == self.stageNumber then + return nil -- stop looping if this stage is not even active + end + + if self:IsComplete() == true then + triggerStageCompleteListeners(self) + return nil + end + return time + 60 + end + ---Activates all SAMS, Airbase units etc all at once. ---@param self table o.PreActivate = function(self) @@ -230,6 +242,8 @@ do --init STAGE DIRECTOR end end timer.scheduleFunction(activateMissionsIfApplicableAsync, self, timer.getTime() + 5) + + timer.scheduleFunction(CheckContinuousAsync, self, timer.getTime() + 60) end o.ActivateMissionsIfApplicable = function (self) @@ -267,6 +281,7 @@ do --init STAGE DIRECTOR end end end + end ---Cleans up all missions @@ -471,6 +486,7 @@ do --init STAGE DIRECTOR mission:AddMissionCompleteListener(o) end + Spearhead.Events.AddOnPlayerEnterUnitListener(o) Spearhead.Events.AddOnStatusRequestReceivedListener(o) Spearhead.Events.AddStageNumberChangedListener(o) return o diff --git a/config.lua b/config.lua index a63cec5..d4dde35 100644 --- a/config.lua +++ b/config.lua @@ -40,7 +40,7 @@ SpearheadConfig = { enabled = true, -- default true --Will draw the active and the next stage - drawStages = true, -- default true + drawStages = false, -- default true --AutoStages will continue to the next stage automatically on completion of the missions within the stage. -- If you want to make it so the next stage triggers only when you want to disable it here and manually implement the actions needed. diff --git a/main.lua b/main.lua index c9e671d..0b928dd 100644 --- a/main.lua +++ b/main.lua @@ -8,11 +8,15 @@ if id == 0 then end local dbLogger = Spearhead.LoggerTemplate:new("database", Spearhead.LoggerTemplate.LogLevelOptions.INFO) +local standardLogger = Spearhead.LoggerTemplate:new("", Spearhead.LoggerTemplate.LogLevelOptions.INFO) local databaseManager = Spearhead.DB:new(dbLogger, debug) local capConfig = Spearhead.internal.configuration.CapConfig:new(); local stageConfig = Spearhead.internal.configuration.StageConfig:new(); +standardLogger:info("Using StageConfig: ".. stageConfig:toString()) + + Spearhead.internal.GlobalCapManager.start(databaseManager, capConfig, stageConfig) Spearhead.internal.GlobalStageManager:NewAndStart(databaseManager, stageConfig) Spearhead.internal.GlobalFleetManager.start(databaseManager) @@ -29,9 +33,6 @@ Spearhead.LoadingDone() -- Get-ChildItem . -Include *.lua -Recurse | foreach {""+(Get-Content $_).Count + " => " + $_.name }; && GCI . -Include *.lua* -Recurse | foreach{(GC $_).Count} | measure-object -sum | % Sum -- find . -name '*.lua' | xargs wc -l - - - --- ==================== DEBUG ORDER OR ZONE VEC =========================== -- local zone = Spearhead.DcsUtil.getZoneByName("MISSIONSTAGE_99")