diff --git a/.github/workflows/compile-artifact.yml b/.github/workflows/compile-artifact.yml new file mode 100644 index 0000000..ed2cade --- /dev/null +++ b/.github/workflows/compile-artifact.yml @@ -0,0 +1,24 @@ +name: Compile Artifact + +on: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run SpearheadCompile + run: | + mkdir -p ./output + python3 SpearheadCompile.py . ./output/spearhead.lua + + - name: Upload spearhead.lua artifact + uses: actions/upload-artifact@v4 + with: + name: spearhead-lua + path: ./output/spearhead.lua diff --git a/classes/spearhead_db.lua b/classes/spearhead_db.lua index ec0a8b6..aedd02e 100644 --- a/classes/spearhead_db.lua +++ b/classes/spearhead_db.lua @@ -29,6 +29,7 @@ ---@class MissionAnnotations ---@field description string? ---@field dependsOn Array +---@field completeAt number? ---@class StageZoneData ---@field StageZoneName string @@ -169,7 +170,26 @@ function Database.New(Logger) for i, layer in pairs(env.mission.drawings.layers) do if string.lower(layer.name) == "author" then for key, layer_object in pairs(layer.objects) do - if Spearhead.Util.startswith(string.lower(layer_object.name), "dependson", true) == true then + if Spearhead.Util.startswith(string.lower(layer_object.name), "completeat", true) == true then + for _, zonename in pairs(self._tables.MissionZones) do + if Spearhead.DcsUtil.isPositionInZone(layer_object.mapX, layer_object.mapY, zonename) == true then + if self._tables.MissionAnnotations[zonename] == nil then + self._tables.MissionAnnotations[zonename] = { + description = nil, + dependsOn = {} + } + end + + local missionAnnotation = self._tables.MissionAnnotations[zonename] + local number = tonumber(layer_object.text) + + if number and number > 1 then + number = number / 100 + end + missionAnnotation.completeAt = number + end + end + elseif Spearhead.Util.startswith(string.lower(layer_object.name), "dependson", true) == true then for _, zonename in pairs(self._tables.MissionZones) do if Spearhead.DcsUtil.isPositionInZone(layer_object.mapX, layer_object.mapY, zonename) == true then @@ -621,6 +641,15 @@ function Database:getMissionDependencies(missionZoneName) return self._tables.MissionAnnotations[missionZoneName].dependsOn end +---@return number? +function Database:getMissionCompleteAt(missionZoneName) + if not self._tables.MissionAnnotations[missionZoneName] then + return nil + end + + return self._tables.MissionAnnotations[missionZoneName].completeAt +end + ---comment ---@param missionZoneName any ---@return Vec2? diff --git a/classes/stageClasses/Groups/SpearheadGroup.lua b/classes/stageClasses/Groups/SpearheadGroup.lua index ca213d0..ee5defd 100644 --- a/classes/stageClasses/Groups/SpearheadGroup.lua +++ b/classes/stageClasses/Groups/SpearheadGroup.lua @@ -93,7 +93,12 @@ function SpearheadGroup:Destroy() Spearhead.DcsUtil.DestroyGroup(self.groupName) end ----comment +---@return boolean +function SpearheadGroup:IsStatic() + return self._isStatic +end + + ---@return integer function SpearheadGroup:GetCoalition() if self._isStatic == true then diff --git a/classes/stageClasses/missions/ZoneMission.lua b/classes/stageClasses/missions/ZoneMission.lua index b925aa3..4c3bbe3 100644 --- a/classes/stageClasses/missions/ZoneMission.lua +++ b/classes/stageClasses/missions/ZoneMission.lua @@ -1,10 +1,9 @@ - - --- ZoneMission is missions that are defined by zones in the ME ---@class ZoneMission : Mission, OnUnitLostListener ---@field private _state MissionState ---@field private _missionGroups MissionGroups ---@field private _dependencies table +---@field private _completeAtIndex number ---@field private _parentStage Stage local ZoneMission = {} @@ -15,7 +14,7 @@ local ZoneMission = {} --- @field targetsAlive table> --- @field groupNamesPerunit table ----@class ParsedMissionName +---@class ParsedMissionName ---@field missionName string ---@field type MissionType @@ -43,7 +42,8 @@ local function ParseZoneName(input) if inputType == "sam" then parsedType = "SAM" end if parsedType == "nil" then - Spearhead.AddMissionEditorWarning("Mission with zonename '" .. input .. "' has an unsupported type '" .. (type or "nil" )) + Spearhead.AddMissionEditorWarning("Mission with zonename '" .. + input .. "' has an unsupported type '" .. (type or "nil")) return nil end local name = split_name[3] @@ -77,7 +77,8 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage) local missionBriefing = database:getMissionBriefingForMissionZone(zoneName) or "no briefing provided" - local success, error = Mission.newSuper(self, zoneName, parsed.missionName, parsed.type, missionBriefing, priority, database, logger) + local success, error = Mission.newSuper(self, zoneName, parsed.missionName, parsed.type, missionBriefing, priority, + database, logger) if not success then logger:error("Failed to create ZoneMission " .. zoneName .. " => " .. error) return nil @@ -105,6 +106,14 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage) self._dependencies[dependency] = false end + local completeAtIndex = database:getMissionCompleteAt(zoneName) + if completeAtIndex == nil and self.missionType == "BAI" then + self._completeAtIndex = 0.8 + elseif completeAtIndex == nil then + self._completeAtIndex = 1 + else + self._completeAtIndex = completeAtIndex + end local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup local groupNames = database:getGroupsForMissionZone(zoneName) @@ -147,8 +156,6 @@ end ---@private function ZoneMission:StartCheckingDependencies() - - self._state = "WAITING" ---comment @@ -156,7 +163,6 @@ function ZoneMission:StartCheckingDependencies() ---@param time any ---@return unknown local function CheckDependencies(mission, time) - if mission:AllDependenciesMet() == true then mission:SpawnActive() return nil @@ -226,62 +232,57 @@ function ZoneMission:UpdateState(checkHealth, messageIfDone) end end - for groupName, unitNameDict in pairs(self._missionGroups.unitsAlive) do - for unitName, isAlive in pairs(unitNameDict) do - if isAlive == true then - self._missionGroups.unitsAlive[groupName][unitName] = unitAliveState(unitName) + if self._missionGroups.hasTargets == true then + for groupName, unitNameDict in pairs(self._missionGroups.targetsAlive) do + for unitName, isAlive in pairs(unitNameDict) do + if isAlive == true then + self._missionGroups.targetsAlive[groupName][unitName] = unitAliveState(unitName) + end end end - end - - for groupName, unitNameDict in pairs(self._missionGroups.targetsAlive) do - for unitName, isAlive in pairs(unitNameDict) do - if isAlive == true then - self._missionGroups.targetsAlive[groupName][unitName] = unitAliveState(unitName) + else + for groupName, unitNameDict in pairs(self._missionGroups.unitsAlive) do + for unitName, isAlive in pairs(unitNameDict) do + if isAlive == true then + self._missionGroups.unitsAlive[groupName][unitName] = unitAliveState(unitName) + end end end end end if self._missionGroups.hasTargets == true then - local anyTargetAlive = function() - for _, units in pairs(self._missionGroups.targetsAlive) do - for _, isAlive in pairs(units) do - if isAlive == true then - return true - end + local total = 0 + local alive = 0 + + for _, units in pairs(self._missionGroups.targetsAlive) do + for _, isAlive in pairs(units) do + total = total + 1 + if isAlive == true then + alive = alive + 1 end end - return false end - if anyTargetAlive() ~= true then + local deadRatio = (total-alive) / total + if deadRatio >= self._completeAtIndex then self._state = "COMPLETED" end else - local function CountAliveGroups() - local aliveGroups = 0 + local total = 0 + local alive = 0 - for _, group in pairs(self._missionGroups.unitsAlive) do - local groupTotal = 0 - local groupDeath = 0 - for _, isAlive in pairs(group) do - if isAlive ~= true then - groupDeath = groupDeath + 1 - end - groupTotal = groupTotal + 1 - end - - local aliveRatio = (groupTotal - groupDeath) / groupTotal - if aliveRatio >= MINIMAL_UNITS_ALIVE_RATIO then - aliveGroups = aliveGroups + 1 + for _, units in pairs(self._missionGroups.unitsAlive) do + for _, isAlive in pairs(units) do + total = total + 1 + if isAlive == true then + alive = alive + 1 end end - - return aliveGroups end - if CountAliveGroups() == 0 then + local deadRatio = (total-alive) / total + if deadRatio >= self._completeAtIndex then self._state = "COMPLETED" end end @@ -293,7 +294,7 @@ function ZoneMission:SpawnPersistedState() end end ----spawns the mission, but doesn't add +---spawns the mission, but doesn't add function ZoneMission:SpawnInactive() self._logger:info("PreActivating " .. self.name) @@ -303,7 +304,6 @@ function ZoneMission:SpawnInactive() end function ZoneMission:SpawnActive() - if self:AllDependenciesMet() == false then self:SpawnInactive() self:StartCheckingDependencies() @@ -327,10 +327,8 @@ function ZoneMission:SpawnActive() self:StartCheckingContinuous() end - ---@private function ZoneMission:StartCheckingContinuous() - ---comment ---@param mission Mission ---@param time any @@ -418,9 +416,7 @@ function ZoneMission:OnUnitLost(object) self:UpdateState(false, true) end - - if not Spearhead.classes then Spearhead.classes = {} end if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end if not Spearhead.classes.stageClasses.missions then Spearhead.classes.stageClasses.missions = {} end -Spearhead.classes.stageClasses.missions.ZoneMission = ZoneMission \ No newline at end of file +Spearhead.classes.stageClasses.missions.ZoneMission = ZoneMission