diff --git a/.docs/web/pages/reference.html b/.docs/web/pages/reference.html
index 34a1228..0f782ee 100644
--- a/.docs/web/pages/reference.html
+++ b/.docs/web/pages/reference.html
@@ -253,6 +253,13 @@
To make an airbase buildable add a text box inside of the trigger zone and name it: buildable_[freeform]
Then in the text box type amount of kilo's you want to be transfered before the logistisc mission is complete.
+
+ To add a custom briefing for a buildable zone, include a text box inside the trigger zone and name it: supplybriefing_[freeform].
+ {{coords}} is highly recommended so the players can easily find their landing zone.
+ Additionally, the amount of kilos required and delivered are always shown on the bottom, as well as a note to not land in the construction zone.
+
+
+
The base or zone will slowly build up with each crate giving both a nice view of it happening AND it's good for performance as there's not a big addition of objects at once.
Right now a crate takes 15 seconds to unpack per 500kg. Meaning 2 crates of 1000kg will be faster than 1 crate of 2000kg.
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index f50f92b..d616329 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -15,6 +15,10 @@
These lanes can be used to create different stage progression flows and create different "side-stories".
#40
+- Issue: #37
+ Now enabled the mission editor to add a custom briefing to the "Buildable" missions.
+ #44
+
### Bug Fixes
## [0.13.0] 2026-08
diff --git a/src/classes/spearhead_db.lua b/src/classes/spearhead_db.lua
index 296e453..c60bc0b 100644
--- a/src/classes/spearhead_db.lua
+++ b/src/classes/spearhead_db.lua
@@ -58,6 +58,7 @@ local StageDrawing = require("classes.stageClasses.drawings.StageDrawing")
---@class BlueSamData
---@field groups Array
---@field buildingKilos number?
+---@field briefing string?
---@class MissionZoneData
---@field ZoneName string
@@ -74,6 +75,7 @@ local StageDrawing = require("classes.stageClasses.drawings.StageDrawing")
---@field padNames Array
---@field buildingKilos number?
---@field supplyHubNames Array
+---@field briefing string?
---@class Database
---@field private _tables DatabaseTables
@@ -616,6 +618,27 @@ function Database:loadBlueSamUnits()
local number = tonumber(kvPair.value)
if number and number > 0 then
samData.buildingKilos = number
+
+ if env.mission.drawings and env.mission.drawings.layers then
+ 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
+
+ local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
+ if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
+ if layer_object.name and Util.startswith(layer_object.name, "supplybriefing_", true) then
+ local description = layer_object.text
+ if description and description ~= "" then
+ samData.briefing = description
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ else
+ MissionEditorWarnings.Add("Buildable number for " .. blueSamZone .. " is invalid")
end
end
end
@@ -750,7 +773,31 @@ function Database:loadFarpData()
local number = tonumber(kvPair.value)
if number and number > 0 then
farpzoneData.buildingKilos = number
+
+ -- check briefings
+ if env.mission.drawings and env.mission.drawings.layers then
+ 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
+
+ local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
+ if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
+ if layer_object.name and Util.startswith(layer_object.name, "supplybriefing_", true) then
+ local description = layer_object.text
+ if description and description ~= "" then
+ farpzoneData.briefing = description
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ else
+ MissionEditorWarnings.Add("Buildable number for " .. farpZone .. " is invalid.")
end
+
+
end
end
end
diff --git a/src/classes/stageClasses/SpecialZones/BlueSam.lua b/src/classes/stageClasses/SpecialZones/BlueSam.lua
index bc8baf8..1723fec 100644
--- a/src/classes/stageClasses/SpecialZones/BlueSam.lua
+++ b/src/classes/stageClasses/SpecialZones/BlueSam.lua
@@ -89,7 +89,7 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
local zone = DcsUtil.getZoneByName(zoneName)
if zone then
- BuildableZone.New(self, zone, self._buildableCrateKilos or 0, "SAM_CRATE", self._blueGroups, logger, database)
+ BuildableZone.New(self, zone, self._buildableCrateKilos or 0, "SAM_CRATE", self._blueGroups, logger, database, blueSamData.briefing)
end
return self
diff --git a/src/classes/stageClasses/SpecialZones/FarpZone.lua b/src/classes/stageClasses/SpecialZones/FarpZone.lua
index ec82cdb..74b329d 100644
--- a/src/classes/stageClasses/SpecialZones/FarpZone.lua
+++ b/src/classes/stageClasses/SpecialZones/FarpZone.lua
@@ -64,7 +64,7 @@ function FarpZone.New(database, logger, zoneName, spawnManager)
local zone = DcsUtil.getZoneByName(zoneName)
if zone then
self._logger:debug("Creating Buildable zone: " .. zoneName .. " with " .. (farpData.buildingKilos or "nil") .. " kilos")
- BuildableZone.New(self, zone, farpData.buildingKilos or 0, "FARP_CRATE", self._groups, logger, database)
+ BuildableZone.New(self, zone, farpData.buildingKilos or 0, "FARP_CRATE", self._groups, logger, database, farpData.briefing)
end
end
self:Deactivate()
diff --git a/src/classes/stageClasses/SpecialZones/abstract/BuildableZone.lua b/src/classes/stageClasses/SpecialZones/abstract/BuildableZone.lua
index 5851d10..38fcada 100644
--- a/src/classes/stageClasses/SpecialZones/abstract/BuildableZone.lua
+++ b/src/classes/stageClasses/SpecialZones/abstract/BuildableZone.lua
@@ -20,7 +20,8 @@ BuildableZone.__index = BuildableZone
---@param database Database
---@param crateType SupplyType
---@param logger Logger
-function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroups, logger, database)
+---@param briefing string?
+function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroups, logger, database, briefing)
self._targetZone = targetZone
self._requiredKilos = kilosRequired or 0
self._buildableGroups = buildableGroups or {}
@@ -69,7 +70,7 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
local noLandingZone = self:GetNoLandingZone()
if kilosRequired and kilosRequired > 0 then
- self._buildableMission = BuildableMission.new(database, logger, targetZone, noLandingZone, kilosRequired, crateType)
+ self._buildableMission = BuildableMission.new(database, logger, targetZone, noLandingZone, kilosRequired, crateType, briefing)
self._buildableMission:AddOnCrateDroppedOfListener(self)
else
self._buildableMission = nil
diff --git a/src/classes/stageClasses/drawings/helper/DrawingHelper.lua b/src/classes/stageClasses/drawings/helper/DrawingHelper.lua
index d420c69..d356d59 100644
--- a/src/classes/stageClasses/drawings/helper/DrawingHelper.lua
+++ b/src/classes/stageClasses/drawings/helper/DrawingHelper.lua
@@ -15,7 +15,6 @@ local logger = Logger.new("DrawingHelper", level)
local DrawingHelper = {}
DrawingHelper.__index = DrawingHelper
-
---@param object DrawingObject
---@return Array id
function DrawingHelper.Draw(object)
diff --git a/src/classes/stageClasses/missions/BuildableMission.lua b/src/classes/stageClasses/missions/BuildableMission.lua
index 7707c0c..cc0b5b7 100644
--- a/src/classes/stageClasses/missions/BuildableMission.lua
+++ b/src/classes/stageClasses/missions/BuildableMission.lua
@@ -21,9 +21,18 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe
---@field private _dropOffZone SpearheadTriggerZone?
---@field private _noLandingZoneDrawing CustomDrawing?
---@field private _dropOffZoneDrawing CustomDrawing?
+---@field private _briefing string?
local BuildableMission = {}
BuildableMission.__index = BuildableMission
+
+local function getDefaultBriefing(siteType, coords)
+ return "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"
+end
+
---@class OnCrateDroppedListener
---@field OnCrateDroppedOff fun(self:OnCrateDroppedListener, mission:BuildableMission, kilos:number)
@@ -33,7 +42,8 @@ BuildableMission.__index = BuildableMission
---@param requiredCrateType SupplyType
---@param noLandingZone SpearheadTriggerZone?
---@param logger Logger
-function BuildableMission.new(database, logger, targetZone, noLandingZone, requiredKilos, requiredCrateType)
+---@param briefing string?
+function BuildableMission.new(database, logger, targetZone, noLandingZone, requiredKilos, requiredCrateType, briefing)
setmetatable(BuildableMission, Mission)
@@ -43,6 +53,7 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
self._database = database
self._requiredKilos = requiredKilos
self._droppedKilos = 0
+ self._briefing = briefing
self._noLandingZone = noLandingZone
@@ -64,7 +75,13 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
end
self.code = tostring(database:GetNewMissionCode())
- self.name = "Resupply"
+
+ local splitTargetZoneName = Util.split_string(targetZone.name, "_")
+ if splitTargetZoneName and splitTargetZoneName[3] and splitTargetZoneName[3] ~= "" then
+ self.name = splitTargetZoneName[3]
+ else
+ self.name = "Resupply"
+ end
local type = "site"
if requiredCrateType == "SAM_CRATE" then
@@ -81,7 +98,6 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
self._supplyUnitsTracker = SupplyUnitsTracker.getOrCreate()
self._state = "NEW"
-
self.location = targetZone.location
self.missionType = "LOGISTICS"
@@ -116,11 +132,16 @@ function BuildableMission:ShowBriefing(groupID)
siteType = "airbase"
end
+ local briefingPart = self._briefing
+ if briefingPart then
+ briefingPart = Util.replaceString(briefingPart, "{{coords}}", coords)
+ else
+ briefingPart = getDefaultBriefing(siteType, coords)
+ 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 ..
+ briefingPart ..
"\n\n" ..
"\nKilos still required: " .. self._requiredKilos - self._droppedKilos ..
"\n\n" ..
diff --git a/src/classes/util/DcsUtil.lua b/src/classes/util/DcsUtil.lua
index 4ee6e62..c314c0b 100644
--- a/src/classes/util/DcsUtil.lua
+++ b/src/classes/util/DcsUtil.lua
@@ -644,7 +644,7 @@ do -- INIT DCS_UTIL
---@param location Vec3
---@return number markID
function DCS_UTIL.AddMarkToGroup(groupID, text, location)
- drawID = drawID + 1
+ local drawID = DCS_UTIL.GetNextDrawID()
trigger.action.markToGroup(drawID, text, location, groupID, true, nil)
return drawID
end
@@ -654,7 +654,7 @@ do -- INIT DCS_UTIL
---@param location Vec3
---@return integer
function DCS_UTIL.AddMarkToAll(text, location)
- drawID = drawID + 1
+ local drawID = DCS_UTIL.GetNextDrawID()
trigger.action.markToAll(drawID, text, location, true, nil)
return drawID
end