Buildable (#36)
- Buildable missions now working. - FARPS and BLUESAM zones are now buildable. - Secondary Logistics missions are created as buildables become available. - Logistic missions can be "marked" with a MAP marker. - Supplies can only be picked up in a SUPPLYHUB zone. - SUPPLYHUB zones are active once their parents are active. A supplyhub parent can be oneof: FARP, AIRBASE, STAGE. - Required supplies for a zone can be configured in kilos. - Crates can be picked up with 1000 or 2000 kilo per crate. - Max load for a helicopter is set based on public data. - TO COME: Sling load options
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
|
||||
|
||||
---@class BuildableMission : Mission
|
||||
---@field private _requiredKilos number
|
||||
---@field private _droppedKilos number
|
||||
---@field private _crateType SupplyType
|
||||
---@field private _targetZoneName string
|
||||
---@field private _database Database
|
||||
---@field private _onCrateDroppedOfListeners Array<OnCrateDroppedListener>
|
||||
---@field private _markIDsPerGroup table<string, number>
|
||||
---@field private _supplyUnitsTracker SupplyUnitsTracker
|
||||
---@field private _noLandingZone SpearheadTriggerZone?
|
||||
---@field private _dropOffZone SpearheadTriggerZone?
|
||||
---@field private _noLandingZoneId number
|
||||
---@field private _dropOffZoneId number
|
||||
local BuildableMission = {}
|
||||
BuildableMission.__index = BuildableMission
|
||||
|
||||
---@class OnCrateDroppedListener
|
||||
---@field OnCrateDroppedOff fun(self:OnCrateDroppedListener, mission:BuildableMission, kilos:number)
|
||||
|
||||
---@param database Database
|
||||
---@param targetZoneName string
|
||||
---@param requiredKilos number
|
||||
---@param requiredCrateType SupplyType
|
||||
---@param noLandingZone SpearheadTriggerZone?
|
||||
---@param logger Logger
|
||||
function BuildableMission.new(database, logger, targetZoneName, noLandingZone, requiredKilos, requiredCrateType)
|
||||
|
||||
local Mission = Spearhead.classes.stageClasses.missions.baseMissions.Mission
|
||||
setmetatable(BuildableMission, Mission)
|
||||
|
||||
local self = setmetatable({}, { __index = BuildableMission })
|
||||
|
||||
self._targetZoneName = targetZoneName
|
||||
self._database = database
|
||||
self._requiredKilos = requiredKilos
|
||||
self._droppedKilos = 0
|
||||
|
||||
self._noLandingZone = noLandingZone
|
||||
|
||||
if noLandingZone then
|
||||
|
||||
local verts = noLandingZone.verts
|
||||
local enlarged = Spearhead.Util.enlargeConvexHull(verts, 300)
|
||||
|
||||
---@type SpearheadTriggerZone
|
||||
local dropOfZone = {
|
||||
name = targetZoneName .. "_dropZone",
|
||||
zone_type = "Polygon",
|
||||
radius = 0,
|
||||
verts = enlarged,
|
||||
location = noLandingZone.location,
|
||||
}
|
||||
|
||||
self._dropOffZone = dropOfZone
|
||||
end
|
||||
|
||||
self.code = tostring(database:GetNewMissionCode())
|
||||
self.name = "Resupply"
|
||||
|
||||
local type = "site"
|
||||
if requiredCrateType == "SAM_CRATE" then
|
||||
type = "SAM site"
|
||||
elseif requiredCrateType == "FARP_CRATE" then
|
||||
type = "FARP"
|
||||
end
|
||||
|
||||
self.zoneName = targetZoneName .. "_supply"
|
||||
self._logger = logger
|
||||
self._onCrateDroppedOfListeners = {}
|
||||
self._completeListeners = {}
|
||||
self._markIDsPerGroup = {}
|
||||
self._supplyUnitsTracker = Spearhead.classes.stageClasses.helpers.SupplyUnitsTracker.getOrCreate(logger.LogLevel)
|
||||
self._state = "NEW"
|
||||
|
||||
local spearheadZone = Spearhead.DcsUtil.getZoneByName(targetZoneName)
|
||||
if spearheadZone == nil then
|
||||
logger:error("Zone not found: " .. targetZoneName)
|
||||
return nil
|
||||
end
|
||||
|
||||
self.location = spearheadZone.location
|
||||
|
||||
self.missionType = "LOGISTICS"
|
||||
self.missionTypeDisplay = "LOGISTICS"
|
||||
|
||||
self.priority = "secondary"
|
||||
|
||||
self._missionCommandsHelper = Spearhead.classes.stageClasses.helpers.MissionCommandsHelper.getOrCreate(self._logger.LogLevel)
|
||||
|
||||
self._crateType = requiredCrateType
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---@param listener OnCrateDroppedListener
|
||||
function BuildableMission:AddOnCrateDroppedOfListener(listener)
|
||||
table.insert(self._onCrateDroppedOfListeners, listener)
|
||||
end
|
||||
|
||||
function BuildableMission:ShowBriefing(groupID)
|
||||
|
||||
local group = Spearhead.DcsUtil.GetPlayerGroupByGroupID(groupID)
|
||||
if group == nil then return end
|
||||
|
||||
local unitType = Spearhead.DcsUtil.getUnitTypeFromGroup(group)
|
||||
local coords = Spearhead.DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
||||
|
||||
local siteType = "FARP"
|
||||
if self._crateType == "SAM_CRATE" then
|
||||
siteType = "SAM site"
|
||||
end
|
||||
|
||||
local briefing = "Mission [" .. self.code .. "] " .. self.name ..
|
||||
"\n \n" ..
|
||||
"We've dispatched forward units to find a proper spot for a new " .. siteType .. "." ..
|
||||
"\nYou will need to drop off supplies so they can start building." ..
|
||||
"\nThe coords are: " .. coords ..
|
||||
"\n\n" ..
|
||||
"\nKilos still required: " .. self._requiredKilos - self._droppedKilos ..
|
||||
"\n\n" ..
|
||||
"NOTE: Do not land in the orange construction zone!"
|
||||
|
||||
trigger.action.outTextForGroup(groupID, briefing, 30)
|
||||
end
|
||||
|
||||
function BuildableMission:MarkMissionAreaToGroup(groupID)
|
||||
|
||||
local text = "[" .. self.code .. "] " .. self.name
|
||||
local location = { x= self.location.x, y=land.getHeight(self.location), z=self.location.y }
|
||||
local markID = Spearhead.DcsUtil.AddMarkToGroup(groupID, text, location)
|
||||
|
||||
self._markIDsPerGroup[groupID] = markID
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param crate SupplyConfig
|
||||
function BuildableMission:NotifyCrateDroppedOf(crate)
|
||||
for _, listener in ipairs(self._onCrateDroppedOfListeners) do
|
||||
if listener.OnCrateDroppedOff then
|
||||
listener:OnCrateDroppedOff(self, crate.weight)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function BuildableMission:SpawnActive()
|
||||
|
||||
self._logger:debug("Spawning buildable mission: " .. self.code)
|
||||
|
||||
if self._noLandingZone == nil then
|
||||
self._logger:error("No no landing zone found for mission: " .. self.code)
|
||||
return
|
||||
end
|
||||
|
||||
---@type DrawColor
|
||||
local lineColor = { r=230/255, g=93/255, b=49/255, a=1}
|
||||
---@type DrawColor
|
||||
local fillColor = { r=230/255, g=93/255, b=49/255, a=0.2}
|
||||
self._noLandingZoneId = Spearhead.DcsUtil.DrawZone(self._noLandingZone, lineColor, fillColor, 6)
|
||||
|
||||
if self._dropOffZone == nil then
|
||||
self._logger:error("No drop off zone found for mission: " .. self.code)
|
||||
return
|
||||
end
|
||||
|
||||
local lineColor2 = { r=0, g=0, b=1, a=1}
|
||||
local fillColor2 = { r=0, g=0, b=1, a=0}
|
||||
self._dropOffZoneId = Spearhead.DcsUtil.DrawZone(self._dropOffZone, lineColor2, fillColor2, 6)
|
||||
|
||||
---@param selfA BuildableMission
|
||||
---@param time number
|
||||
local checkForCrateTasks = function (selfA, time)
|
||||
selfA:CheckCratesInZone()
|
||||
return time + 10
|
||||
end
|
||||
|
||||
timer.scheduleFunction(checkForCrateTasks, self, timer.getTime() + 10)
|
||||
|
||||
self:SpawnForwardUnits()
|
||||
self._state = "ACTIVE"
|
||||
|
||||
self._missionCommandsHelper:AddMissionToCommands(self)
|
||||
|
||||
end
|
||||
|
||||
function BuildableMission:SpawnForwardUnits()
|
||||
|
||||
end
|
||||
|
||||
function BuildableMission:CheckCratesInZone()
|
||||
|
||||
---@type Array<Object>
|
||||
local foundCrates = {}
|
||||
|
||||
local crates = self._supplyUnitsTracker:GetCargoCratesDropped()
|
||||
for _, staticObject in pairs(crates) do
|
||||
if staticObject and staticObject:isExist() and Spearhead.Util.startswith(staticObject:getName(), self._crateType, true) then
|
||||
local pos = staticObject:getPoint()
|
||||
|
||||
if Spearhead.Util.is3dPointInZone(pos, self._dropOffZone) then
|
||||
table.insert(foundCrates, staticObject)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, foundCrate in pairs(foundCrates) do
|
||||
local crateConfig = Spearhead.classes.stageClasses.helpers.supplies.SupplyConfigHelper.fromObjectName(foundCrate:getName())
|
||||
if crateConfig then
|
||||
self._droppedKilos = self._droppedKilos + crateConfig.weight
|
||||
foundCrate:destroy()
|
||||
self:NotifyCrateDroppedOf(crateConfig)
|
||||
end
|
||||
end
|
||||
|
||||
if self._droppedKilos >= self._requiredKilos then
|
||||
Spearhead.DcsUtil.RemoveMark(self._noLandingZoneId)
|
||||
Spearhead.DcsUtil.RemoveMark(self._dropOffZoneId)
|
||||
self:NotifyMissionComplete()
|
||||
self._state = "COMPLETED"
|
||||
end
|
||||
|
||||
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.BuildableMission = BuildableMission
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
|
||||
|
||||
---@class Mission
|
||||
---@field name string
|
||||
---@field zoneName string
|
||||
@@ -120,6 +121,8 @@ function Mission:NotifyMissionComplete()
|
||||
|
||||
end
|
||||
|
||||
function Mission:MarkMissionAreaToGroup(groupId) end
|
||||
|
||||
---endregion
|
||||
|
||||
--region PROTECTED
|
||||
@@ -155,6 +158,7 @@ do --aliases
|
||||
--- | "DEAD"
|
||||
--- | "SAM"
|
||||
--- | "OCA"
|
||||
--- | "LOGISTICS"
|
||||
|
||||
--- @alias MissionState
|
||||
--- | "NEW"
|
||||
|
||||
Reference in New Issue
Block a user