Zone configuration (#62)

* wip

* updates on trigger zone labels, mgrs fix, mission briefings

---------

Co-authored-by: ex61wi <tim.rorije@ing.com>
Co-authored-by: dutchie032 <dutchie032>
This commit is contained in:
2025-09-03 11:58:48 +02:00
committed by GitHub
co-authored by ex61wi dutchie032 <dutchie032>
parent 1d4c0a8313
commit bd023b46ac
10 changed files with 195 additions and 184 deletions
+31 -27
View File
@@ -54,21 +54,20 @@
<h3 id="stage-zones">Stage Zones</h3> <h3 id="stage-zones">Stage Zones</h3>
<p> <p>
<strong>Format:</strong> <span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_[OrderNumber]_[FreeForm]</span></span> <strong>Format:</strong> <code-inline>MISSIONSTAGE_[OrderNumber]_[FreeForm]</code-inline>
<br /> <br />
<strong>Example:</strong> <span class="inline-lua"><span class="lua-variable">MISSIONSTAGE_1_EAST</span></span> <strong>Example:</strong> <code-inline>MISSIONSTAGE_1_EAST</code-inline>
</p> </p>
<p> <p>
Stages are logical parts of a mission. They encapsulate multiple missions, airbases, and other Stages are logical parts of a mission. They encapsulate multiple missions, airbases, and other
objects. <br /> objects. <br />
Secondary stages can be defined using the format: <span Secondary stages can be defined using the format: <code-inline>MISSIONSTAGE_x[OrderNumber]</code-inline>.
class="inline-lua"><span class="lua-variable">MISSIONSTAGE_x[OrderNumber]</span></span>.
</p> </p>
<h3 id="waiting-stages">Waiting Stages</h3> <h3 id="waiting-stages">Waiting Stages</h3>
<p> <p>
<strong>Format:</strong> <span class="inline-lua"><span class="lua-variable">WAITINGSTAGE_[Order]_[Seconds]</span></span> <br /> <strong>Format:</strong> <code-inline>WAITINGSTAGE_[Order]_[Seconds]</code-inline> <br />
<strong>Example:</strong> <span class="inline-lua"><span class="lua-variable">WAITINGSTAGE_2_180</span></span> <strong>Example:</strong> <code-inline>WAITINGSTAGE_2_180</code-inline>
</p> </p>
<p> <p>
Waiting stages introduce delays between stages. They activate only after the previous stage is Waiting stages introduce delays between stages. They activate only after the previous stage is
@@ -77,8 +76,8 @@
<h3 id="mission-zones">Mission Zones</h3> <h3 id="mission-zones">Mission Zones</h3>
<p> <p>
<strong>Format:</strong> <span class="inline-lua"><span class="lua-variable">MISSION_[Type]_[Name]</span></span> <br /> <strong>Format:</strong> <code-inline>MISSION_[Type]_[Name]</code-inline> <br />
<strong>Example:</strong> <span class="inline-lua"><span class="lua-variable">MISSION_DEAD_BYRON</span></span> <strong>Example:</strong> <code-inline>MISSION_DEAD_BYRON</code-inline>
</p> </p>
<p> <p>
Missions are completable objectives with specific types, such as DEAD, BAI, STRIKE, or SAM. <br /> Missions are completable objectives with specific types, such as DEAD, BAI, STRIKE, or SAM. <br />
@@ -88,8 +87,8 @@
<h3 id="cap-routes">CAP Routes</h3> <h3 id="cap-routes">CAP Routes</h3>
<p> <p>
<strong>Format:</strong> <span class="inline-lua"><span class="lua-variable">CAPROUTE_[routeID]_[Name]</span></span> <br /> <strong>Format:</strong> <code-inline>CAPROUTE_[routeID]_[Name]</code-inline> <br />
<strong>Example:</strong> <span class="inline-lua"><span class="lua-variable">CAPROUTE_103_ALPHA</span></span> <strong>Example:</strong> <code-inline>CAPROUTE_103_ALPHA</code-inline>
</p> </p>
<p> <p>
CAP routes define the patrol paths for CAP units. They are tied to specific stages and zones. CAP routes define the patrol paths for CAP units. They are tied to specific stages and zones.
@@ -97,9 +96,9 @@
<h3 id="farp-zones">FARP Zones</h3> <h3 id="farp-zones">FARP Zones</h3>
<p> <p>
<strong>Format:</strong> <span class="inline-lua"><span class="lua-variable">FARP_A|B_[Name]</span></span> <br /> <strong>Format:</strong> <code-inline>FARP_A|B_[Name]</code-inline> <br />
<strong>Example:</strong> <span class="inline-lua"><span class="lua-variable">FARP_A_HOUSTON</span></span> <strong>Example:</strong> <code-inline>FARP_A_HOUSTON</code-inline>
<strong>Example:</strong> <span class="inline-lua"><span class="lua-variable">FARP_B_HOUSTON</span></span> <strong>Example:</strong> <code-inline>FARP_B_HOUSTON</code-inline>
</p> </p>
<p> <p>
FARP zones are spawned and activated based on the "activation parameter". <br/> FARP zones are spawned and activated based on the "activation parameter". <br/>
@@ -113,9 +112,9 @@
<h3 id="supply-hub">Supply Hub</h3> <h3 id="supply-hub">Supply Hub</h3>
<p> <p>
<strong>Format:</strong> <span class="inline-lua"><span class="lua-variable">SUPPLYHUB_[Name]</span></span> <br /> <strong>Format:</strong> <code-inline>SUPPLYHUB_[Name]</code-inline> <br />
<strong>Format:</strong> <span class="inline-lua"><span class="lua-variable">SUPPLYHUB_A_[Name]</span></span> <br /> <strong>Format:</strong> <code-inline>SUPPLYHUB_A_[Name]</code-inline> <br />
<strong>Example:</strong> <span class="inline-lua"><span class="lua-variable">SUPPLYHUB_HOUSTON</span></span> <br/> <br/> <strong>Example:</strong> <code-inline>SUPPLYHUB_HOUSTON</code-inline> <br/> <br/>
Supply hubs are used as zones to pick up logistics for logistic missions. <br/> Supply hubs are used as zones to pick up logistics for logistic missions. <br/>
They are activated when their parent is activated. <br/> They are activated when their parent is activated. <br/>
@@ -175,7 +174,7 @@
They are replaced with the corresponding values at the time a briefing is requested and can therefore show real time data. <br/> They are replaced with the corresponding values at the time a briefing is requested and can therefore show real time data. <br/>
<strong>Field:</strong> <span class="inline-lua"><span class="lua-variable">{{coords}}</span></span><br/> <strong>Field:</strong> <code-inline>{{coords}}</code-inline><br/>
Coords are taken from the location of the trigger zone. Then converted to the aircrafts preferred format. <br/> Coords are taken from the location of the trigger zone. Then converted to the aircrafts preferred format. <br/>
</p> </p>
@@ -186,12 +185,12 @@
<h3 id="cap-group-naming">CAP Group Naming</h3> <h3 id="cap-group-naming">CAP Group Naming</h3>
<p> <p>
<strong>Format:</strong> <span class="inline-lua"><span class="lua-variable">CAP_[A|B][Config]_[FreeForm]</span></span> <br /> <strong>Format:</strong> <code-inline>CAP_[A|B][Config]_[FreeForm]</code-inline> <br />
<strong>Example:</strong> <span class="inline-lua"><span class="lua-variable">CAP_A[1-4]5_SomeName</span></span> <strong>Example:</strong> <code-inline>CAP_A[1-4]5_SomeName</code-inline>
</p> </p>
<h3 id="cap-group-config">CAP Group Config</h3> <h3 id="cap-group-config">CAP Group Config</h3>
<pre> <code-block>
<span class="lua-comment">1 at x:</span> <span class="lua-variable">[&lt;activeStage&gt;]&lt;CapRouteID&gt;</span> <span class="lua-comment">1 at x:</span> <span class="lua-variable">[&lt;activeStage&gt;]&lt;CapRouteID&gt;</span>
<span class="lua-comment">n and n at x:</span> <span class="lua-variable">[&lt;activeStage&gt;,&lt;activeStage&gt;]&lt;CapRouteID&gt;</span> <span class="lua-comment">n and n at x:</span> <span class="lua-variable">[&lt;activeStage&gt;,&lt;activeStage&gt;]&lt;CapRouteID&gt;</span>
<span class="lua-comment">n till n at x:</span> <span class="lua-variable">[&lt;activeStage&gt;-&lt;activeStage&gt;]&lt;CapRouteID&gt;</span> <span class="lua-comment">n till n at x:</span> <span class="lua-variable">[&lt;activeStage&gt;-&lt;activeStage&gt;]&lt;CapRouteID&gt;</span>
@@ -202,7 +201,7 @@
<span class="lua-comment">Examples:</span> <span class="lua-comment">Examples:</span>
<span class="lua-variable">CAP_A[1-4,6]7|[5,7]8_SomeName</span> <span class="lua-comment">=&gt; Will fly CAP at stage 7 when stages 1 through 4 and 6 are active and will fly CAP at 8 when 5 and 7 are active.</span> <span class="lua-variable">CAP_A[1-4,6]7|[5,7]8_SomeName</span> <span class="lua-comment">=&gt; Will fly CAP at stage 7 when stages 1 through 4 and 6 are active and will fly CAP at 8 when 5 and 7 are active.</span>
<span class="lua-variable">CAP_A[2-5]5|[6]6_SomeName</span> <span class="lua-comment">=&gt; Will fly CAP at stage 5 when stages 2 through 5 are active and will fly CAP at CapRoute 6 when 6 is active.</span> <span class="lua-variable">CAP_A[2-5]5|[6]6_SomeName</span> <span class="lua-comment">=&gt; Will fly CAP at stage 5 when stages 2 through 5 are active and will fly CAP at CapRoute 6 when 6 is active.</span>
</pre> </code-block>
<h3 id="active-and-backup-cap">Active and Backup CAP</h3> <h3 id="active-and-backup-cap">Active and Backup CAP</h3>
<p> <p>
@@ -221,7 +220,7 @@
<p> <p>
If you want to have missions inside of a stage depends on each other you can. <br/> If you want to have missions inside of a stage depends on each other you can. <br/>
Add a text drawing box inside of the mission trigger zone with the name: Add a text drawing box inside of the mission trigger zone with the name:
<span class="inline-lua"><span class="lua-variable">dependson_[freeform]</span></span> <br/> <code-inline>dependson_[freeform]</code-inline> <br/>
And in the text add the "Name" of the mission zone you want the mission to depend on. <br/> And in the text add the "Name" of the mission zone you want the mission to depend on. <br/>
The mission will be "pre-activated" (spawned) but won't have a f10 mission menu until the mission(s) it depends on is completed. <br/> The mission will be "pre-activated" (spawned) but won't have a f10 mission menu until the mission(s) it depends on is completed. <br/>
</p> </p>
@@ -229,17 +228,22 @@
<h2 id="buildable">Buildables</h2> <h2 id="buildable">Buildables</h2>
<p> <p>
Current buildables: <br/> Current buildables: <br/>
<span class="inline-lua"><span class="lua-variable">FARP_</span></span> <br/> <code-inline>FARP_</code-inline> <br/>
<span class="inline-lua"><span class="lua-variable">BLUESAM_</span></span> <br/> <code-inline>BLUESAM_</code-inline> <br/>
<span class="inline-lua"><span class="lua-variable">Airbases</span></span> <br/> <code-inline>Airbases</code-inline> <br/>
<br/> <br/>
Buildables are zones or objects that first require logistics. <br/> Buildables are zones or objects that first require logistics. <br/>
Eg. A forward SAM site or FARP requires logistic crates before it can be built. <br/> Eg. A forward SAM site or FARP requires logistic crates before it can be built. <br/>
To make an item buildable add a text box inside of the trigger zone and name it: <span class="inline-lua"><span class="lua-variable">buildable_[freeform]</span></span> <br/> <br>
To make a zone buildable (farp, or bluesam): Select triggerzone -> below the property box hit "Add" -> Property Name should be <code-inline>buildable</code-inline> -> Value should be the kilos required eg. <code-inline>8000</code-inline>
<br>
To make an airbase buildable add a text box inside of the trigger zone and name it: <code-inline>buildable_[freeform]</code-inline> <br/>
Then in the text box type amount of kilo's you want to be transfered before the logistisc mission is complete. <br/> Then in the text box type amount of kilo's you want to be transfered before the logistisc mission is complete. <br/>
The base 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. <br/>
<br>
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. <br/>
Right now a crate takes 15 seconds to unpack per 500kg. Meaning 2 crates of 1000kg will be faster than 1 crate of 2000kg. <br/> Right now a crate takes 15 seconds to unpack per 500kg. Meaning 2 crates of 1000kg will be faster than 1 crate of 2000kg. <br/>
All helicopters have a max limit set based on quick google searches and cannot be changed but the ME at this point: <br/> All helicopters have a max limit set based on quick google searches and cannot be changed but the ME at this point: <br/>
Binary file not shown.
+1 -1
View File
@@ -939,7 +939,7 @@ do -- INIT DCS_UTIL
if coordType == "MGRS" then if coordType == "MGRS" then
local mgrs = coord.LLtoMGRS(lattitude, longitude) local mgrs = coord.LLtoMGRS(lattitude, longitude)
return string.format("%s %s %s %s", mgrs.UTMZone, mgrs.MGRSDigraph, mgrs.Northing, mgrs.Easting) return string.format("%s %s %s %s", mgrs.UTMZone, mgrs.MGRSDigraph, mgrs.Easting, mgrs.Northing)
end end
-- Convert DD to DDM (Degrees Decimal Minutes) -- Convert DD to DDM (Degrees Decimal Minutes)
+113 -134
View File
@@ -15,7 +15,6 @@
---@field CarrierRouteZones Array<string> All Carrier routes zones ---@field CarrierRouteZones Array<string> All Carrier routes zones
---@field BlueSams Array<string> All blue sam zones ---@field BlueSams Array<string> All blue sam zones
---@field SupplyHubZones Array<string> All supply hub zones ---@field SupplyHubZones Array<string> All supply hub zones
---@field MissionAnnotations table<string, MissionAnnotations> table<ZoneName, MissionAnnotations>
---@field AirbaseDataPerAirfield table<string, AirbaseData> ---@field AirbaseDataPerAirfield table<string, AirbaseData>
---@field BlueSamDataPerZone table<string, BlueSamData> ---@field BlueSamDataPerZone table<string, BlueSamData>
---@field MissionZoneData table<string, MissionZoneData> ---@field MissionZoneData table<string, MissionZoneData>
@@ -27,13 +26,9 @@
---@field zones Array<SpearheadTriggerZone> ---@field zones Array<SpearheadTriggerZone>
---@field current number ---@field current number
---@class MissionAnnotations
---@field description string?
---@field dependsOn Array<string>
---@field completeAt number?
---@class StageZoneData ---@class StageZoneData
---@field StageZoneName string ---@field StageZoneName string
---@field StageBriefing string?
---@field AirbaseNames Array<string> ---@field AirbaseNames Array<string>
---@field FarpZones Array<string> ---@field FarpZones Array<string>
---@field MissionZones Array<string> ---@field MissionZones Array<string>
@@ -58,9 +53,13 @@
---@field buildingKilos number? ---@field buildingKilos number?
---@class MissionZoneData ---@class MissionZoneData
---@field ZoneName string
---@field RedGroups Array<string> ---@field RedGroups Array<string>
---@field SceneryTargets Array<SpearheadSceneryObject> ---@field SceneryTargets Array<SpearheadSceneryObject>
---@field BlueGroups Array<string> ---@field BlueGroups Array<string>
---@field description string?
---@field dependsOn Array<string>
---@field completeAt number?
---@class FarpZoneData ---@class FarpZoneData
---@field groups Array<string> ---@field groups Array<string>
@@ -99,7 +98,6 @@ function Database.New(Logger)
MissionZoneData = {}, MissionZoneData = {},
FarpZoneData = {}, FarpZoneData = {},
missionCodes = {}, missionCodes = {},
MissionAnnotations = {},
SupplyHubZones = {} SupplyHubZones = {}
} }
@@ -209,47 +207,12 @@ function Database.New(Logger)
if string.lower(layer.name) == "author" then if string.lower(layer.name) == "author" then
for key, layer_object in pairs(layer.objects) do for key, layer_object in pairs(layer.objects) do
if Spearhead.Util.startswith(string.lower(layer_object.name), "buildable", true) == true then if Spearhead.Util.startswith(string.lower(layer_object.name), "buildable", true) == true then
local blueSamData = self:getBlueSamDataForDrawLayer(layer_object)
if blueSamData then
local number = tonumber(layer_object.text)
blueSamData.buildingKilos = number
end
local farpData = self:getFarpDataForDrawLayer(layer_object)
if farpData then
local number = tonumber(layer_object.text)
farpData.buildingKilos = number
end
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object) local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
if airbaseData then if airbaseData then
self._logger:debug("found airbase data for " .. layer_object.name) self._logger:debug("found airbase data for " .. layer_object.name)
local number = tonumber(layer_object.text) local number = tonumber(layer_object.text)
airbaseData.buildingKilos = number airbaseData.buildingKilos = number
end end
elseif Spearhead.Util.startswith(string.lower(layer_object.name), "completeat", true) == true then
local annotationData = self:getMissionMetaDataForDrawLayer(layer_object)
if annotationData then
local number = tonumber(layer_object.text)
if number and number > 1 then
number = number / 100
end
annotationData.completeAt = number
end
elseif Spearhead.Util.startswith(string.lower(layer_object.name), "dependson", true) == true then
local annotationData = self:getMissionMetaDataForDrawLayer(layer_object)
if annotationData then
table.insert(annotationData.dependsOn, layer_object.text)
end
elseif Spearhead.Util.startswith(layer_object.name, "stagebriefing", true) == true then
--[[
TODO: Stage Briefings
]]
else
local annotationData = self:getMissionMetaDataForDrawLayer(layer_object)
if annotationData then
annotationData.description = layer_object.text
end
end end
end end
end end
@@ -266,6 +229,27 @@ function Database.New(Logger)
for _, stageZoneName in pairs(self._tables.StageZoneNames) do for _, stageZoneName in pairs(self._tables.StageZoneNames) do
local stageData = self._tables.StageZones[stageZoneName] local stageData = self._tables.StageZones[stageZoneName]
if stageData then if stageData then
-- Find and add Briefing
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
if Spearhead.Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then
local zone = Spearhead.DcsUtil.getZoneByName(stageZoneName)
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
if zone and Spearhead.Util.is2dPointInZone(vec2, zone) == true then
local description = layer_object.text
if description and description ~= "" then
stageData.StageBriefing = description
end
end
end
end
end
end
end
-- fill blue sams -- fill blue sams
for _, blueSamStageName in pairs(self._tables.BlueSams) do for _, blueSamStageName in pairs(self._tables.BlueSams) do
if Spearhead.DcsUtil.isZoneInZone(blueSamStageName, stageZoneName) == true then if Spearhead.DcsUtil.isZoneInZone(blueSamStageName, stageZoneName) == true then
@@ -347,13 +331,13 @@ function Database.New(Logger)
end end
for _, missionZone in pairs(self._tables.MissionZones) do for _, missionZone in pairs(self._tables.MissionZones) do
if self._tables.MissionAnnotations[missionZone] == nil or self._tables.MissionAnnotations[missionZone].description == nil then if self._tables.MissionZoneData[missionZone] == nil or self._tables.MissionZoneData[missionZone].description == nil then
Spearhead.AddMissionEditorWarning("Mission with zonename: " .. missionZone .. " does not have a briefing") Spearhead.AddMissionEditorWarning("Mission with zonename: " .. missionZone .. " does not have a briefing")
end end
end end
for _, missionZone in pairs(self._tables.RandomMissionZones) do for _, missionZone in pairs(self._tables.RandomMissionZones) do
if self._tables.MissionAnnotations[missionZone] == nil or self._tables.MissionAnnotations[missionZone].description == nil then if self._tables.MissionZoneData[missionZone] == nil or self._tables.MissionZoneData[missionZone].description == nil then
Spearhead.AddMissionEditorWarning("Mission with zonename: " .. missionZone .. " does not have a briefing") Spearhead.AddMissionEditorWarning("Mission with zonename: " .. missionZone .. " does not have a briefing")
end end
end end
@@ -384,7 +368,7 @@ function Database.New(Logger)
self:loadBlueSamUnits() self:loadBlueSamUnits()
self:loadMissionzoneUnits() self:loadMissionzoneUnits()
self:loadRandomMissionzoneUnits() self:loadRandomMissionzoneUnits()
self:loadFarpGroups() self:loadFarpData()
self:loadAirbaseGroups() self:loadAirbaseGroups()
self:loadMiscGroupsInStages() self:loadMiscGroupsInStages()
@@ -490,31 +474,6 @@ function Database:initAvailableUnits()
end end
end end
---comment
---@private
---@param layer_object table
---@return BlueSamData?
function Database:getBlueSamDataForDrawLayer(layer_object)
for _, zonename in pairs(self._tables.BlueSams) do
if Spearhead.DcsUtil.isPositionInZone(layer_object.mapX, layer_object.mapY, zonename) == true then
return self:getOrCreateBlueSamDataForZone(zonename)
end
end
return nil
end
---@private
---@param layer_object table
---@return FarpZoneData?
function Database:getFarpDataForDrawLayer(layer_object)
for _, zonename in pairs(self._tables.AllFarpZones) do
if Spearhead.DcsUtil.isPositionInZone(layer_object.mapX, layer_object.mapY, zonename) == true then
return self:getOrCreateFarpDataForZone(zonename)
end
end
return nil
end
---comment ---comment
---@param layer_object table ---@param layer_object table
---@return AirbaseData? ---@return AirbaseData?
@@ -536,7 +495,6 @@ function Database:getOrCreateBlueSamDataForZone(zoneName)
if blueSamData == nil then if blueSamData == nil then
blueSamData = { blueSamData = {
groups = {}, groups = {},
buildingCrates = nil
} }
self._tables.BlueSamDataPerZone[zoneName] = blueSamData self._tables.BlueSamDataPerZone[zoneName] = blueSamData
end end
@@ -550,7 +508,6 @@ function Database:getOrCreateFarpDataForZone(zoneName)
farpData = { farpData = {
padNames = {}, padNames = {},
groups = {}, groups = {},
buildingCrates = nil,
supplyHubNames = {} supplyHubNames = {}
} }
self._tables.FarpZoneData[zoneName] = farpData self._tables.FarpZoneData[zoneName] = farpData
@@ -577,38 +534,6 @@ function Database:getOrCreateAirbaseData(baseName)
return baseData return baseData
end end
---@private
---@param layer_object table
---@return MissionAnnotations?
function Database:getMissionMetaDataForDrawLayer(layer_object)
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
return self._tables.MissionAnnotations[zonename]
end
end
for _, zonename in pairs(self._tables.RandomMissionZones) 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
return self._tables.MissionAnnotations[zonename]
end
end
return nil
end
---@private ---@private
function Database:loadCapUnits() function Database:loadCapUnits()
local all_groups = getAvailableCAPGroups() local all_groups = getAvailableCAPGroups()
@@ -658,16 +583,31 @@ function Database:loadBlueSamUnits()
is_group_taken[groupName] = true is_group_taken[groupName] = true
table.insert(samData.groups, groupName) table.insert(samData.groups, groupName)
end end
local triggerZone = Spearhead.DcsUtil.getZoneByName(blueSamZone)
if triggerZone then
for _, kvPair in pairs(triggerZone.properties) do
if kvPair.key and Spearhead.Util.startswith(kvPair.key, "buildable") then
local number = tonumber(kvPair.value)
if number and number > 0 then
samData.buildingKilos = number
end
end
end
end
end end
end end
---Loads all units, data and briefings
---@private ---@private
function Database:LoadZoneData(missionZoneName) function Database:LoadZoneData(missionZoneName)
local all_groups = getAvailableGroups() local all_groups = getAvailableGroups()
self._tables.MissionZoneData[missionZoneName] = { self._tables.MissionZoneData[missionZoneName] = {
RedGroups = {}, RedGroups = {},
BlueGroups = {}, BlueGroups = {},
SceneryTargets = {} SceneryTargets = {},
ZoneName = missionZoneName,
dependsOn = {}
} }
local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName) local groups = Spearhead.DcsUtil.getGroupsInZone(all_groups, missionZoneName)
@@ -700,6 +640,47 @@ function Database:LoadZoneData(missionZoneName)
end end
end end
end end
-- Check for properties and adds the settings to the mission data
local triggerZone = Spearhead.DcsUtil.getZoneByName(missionZoneName)
if triggerZone and triggerZone.properties then
for _, kvPair in pairs(triggerZone.properties) do
local key = kvPair.key
if Spearhead.Util.startswith(key, "dependson", true) == true then
table.insert(self._tables.MissionZoneData[missionZoneName].dependsOn, kvPair.value)
elseif Spearhead.Util.startswith(key, "completeat") == true then
local value = tonumber(kvPair.value)
if value then
if value > 1 and value <= 100 then
value = value / 100
elseif value > 100 then
Spearhead.AddMissionEditorWarning("Mission with zonename: " .. missionZoneName .. " has a complete at value of " .. value .. " which is higher than 100, this will not work as intended")
end
self._tables.MissionZoneData[missionZoneName].completeAt = value
end
end
end
end
---Adds 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 Spearhead.Util.is2dPointInZone(vec2, triggerZone) then
if layer_object.name and Spearhead.Util.startswith(layer_object.name, "briefing_", true) then
local description = layer_object.text
if description and description ~= "" then
self._tables.MissionZoneData[missionZoneName].description = description
end
end
end
end
end
end
end
end end
---@private ---@private
@@ -717,7 +698,7 @@ function Database:loadRandomMissionzoneUnits()
end end
---@private ---@private
function Database:loadFarpGroups() function Database:loadFarpData()
local all_groups = getAvailableGroups() local all_groups = getAvailableGroups()
for _, farpZone in pairs(self._tables.AllFarpZones) do for _, farpZone in pairs(self._tables.AllFarpZones) do
local farpzoneData = self:getOrCreateFarpDataForZone(farpZone) local farpzoneData = self:getOrCreateFarpDataForZone(farpZone)
@@ -727,6 +708,18 @@ function Database:loadFarpGroups()
is_group_taken[groupName] = true is_group_taken[groupName] = true
table.insert(farpzoneData.groups, groupName) table.insert(farpzoneData.groups, groupName)
end end
local triggerZone = Spearhead.DcsUtil.getZoneByName(farpZone)
if triggerZone then
for _, kvPair in pairs(triggerZone.properties) do
if kvPair.key and Spearhead.Util.startswith(kvPair.key, "buildable", true) == true then
local number = tonumber(kvPair.value)
if number and number > 0 then
farpzoneData.buildingKilos = number
end
end
end
end
end end
end end
@@ -810,34 +803,6 @@ function Database:loadMiscGroupsInStages()
end end
end end
---@return string?
function Database:getMissionBriefingForMissionZone(missionZoneName)
if not self._tables.MissionAnnotations[missionZoneName] then
return nil
end
return self._tables.MissionAnnotations[missionZoneName].description
end
---@param missionZoneName string
---@return Array<string>
function Database:getMissionDependencies(missionZoneName)
if not self._tables.MissionAnnotations[missionZoneName] then
return {}
end
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 ---comment
---@param missionZoneName any ---@param missionZoneName any
---@return Vec2? ---@return Vec2?
@@ -893,6 +858,14 @@ function Database:getCarrierRouteZones()
return self._tables.CarrierRouteZones return self._tables.CarrierRouteZones
end end
---@param stagename string
---@return string
function Database:getBriefingForStage(stagename)
local stageZone = self._tables.StageZones[stagename]
if not stageZone then return "" end
return stageZone.StageBriefing or ""
end
---@return Array<string> ---@return Array<string>
function Database:getMissionsForStage(stagename) function Database:getMissionsForStage(stagename)
local stageZone = self._tables.StageZones[stagename] local stageZone = self._tables.StageZones[stagename]
@@ -942,6 +915,12 @@ function Database:getAirbaseDataForZone(baseName)
return baseData return baseData
end end
---@return string?
function Database:getStageBriefingForStage(stageName)
local stageData = self._tables.StageZones[stageName]
if not stageData then return nil end
return stageData.StageBriefing or nil
end
---@param stageName string ---@param stageName string
---@return Array<string> ---@return Array<string>
@@ -54,7 +54,7 @@ function SpearheadGroup:Spawn(lateStart)
---@type SpawnOverrides ---@type SpawnOverrides
local overrides = { local overrides = {
uncontrolled = lateStart or false, uncontrolled = lateStart,
} }
local spawnedObject, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent) local spawnedObject, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
@@ -59,6 +59,7 @@ function FarpZone.New(database, logger, zoneName, spawnManager)
local zone = Spearhead.DcsUtil.getZoneByName(zoneName) local zone = Spearhead.DcsUtil.getZoneByName(zoneName)
if zone then if zone then
self._logger:debug("Creating Buildable zone: " .. zoneName .. " with " .. (farpData.buildingKilos or "nil") .. " kilos")
Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone.New(self, zone, farpData.buildingKilos or 0, "FARP_CRATE", self._groups, logger, database) Spearhead.classes.stageClasses.SpecialZones.abstract.BuildableZone.New(self, zone, farpData.buildingKilos or 0, "FARP_CRATE", self._groups, logger, database)
end end
end end
@@ -28,6 +28,7 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
self._receivedBuildingKilos = 0 self._receivedBuildingKilos = 0
local persistedKilos = Spearhead.classes.persistence.Persistence.GetZoneDeliveredKilos(targetZone.name) local persistedKilos = Spearhead.classes.persistence.Persistence.GetZoneDeliveredKilos(targetZone.name)
if persistedKilos and persistedKilos > 0 then if persistedKilos and persistedKilos > 0 then
self._buildableLogger:debug("Zone " .. targetZone.name .. " already has " .. persistedKilos .. " kilos delivered")
self._receivedBuildingKilos = persistedKilos self._receivedBuildingKilos = persistedKilos
---@param params UnpackCrateParam ---@param params UnpackCrateParam
@@ -5,6 +5,7 @@
---| "GRAY" ---| "GRAY"
--- @class StageData --- @class StageData
--- @field stageBriefing string?
--- @field missionsByCode table<string, Mission> --- @field missionsByCode table<string, Mission>
--- @field missionsByName table<string, Mission> --- @field missionsByName table<string, Mission>
--- @field missions Array<ZoneMission> --- @field missions Array<ZoneMission>
@@ -29,6 +30,7 @@
--- @field zoneName string --- @field zoneName string
--- @field stageName string? --- @field stageName string?
--- @field stageNumber number --- @field stageNumber number
--- @field protected _missionCommandsHelper MissionCommandsHelper
--- @field protected _isActive boolean --- @field protected _isActive boolean
--- @field protected _isComplete boolean --- @field protected _isComplete boolean
--- @field protected _missionPriority MissionPriority --- @field protected _missionPriority MissionPriority
@@ -83,6 +85,7 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
self._database = database self._database = database
self._logger = logger self._logger = logger
self._db = { self._db = {
stageBriefing = nil,
missionsByCode = {}, missionsByCode = {},
missions = {}, missions = {},
sams ={}, sams ={},
@@ -98,6 +101,7 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
self._activeStage = -99 self._activeStage = -99
self._preActivated = false self._preActivated = false
self._stageConfig = stageConfig or {} self._stageConfig = stageConfig or {}
self._missionCommandsHelper = Spearhead.classes.stageClasses.helpers.MissionCommandsHelper.getOrCreate(logger.LogLevel)
local zone = Spearhead.DcsUtil.getZoneByName(self.zoneName) local zone = Spearhead.DcsUtil.getZoneByName(self.zoneName)
if zone then if zone then
@@ -120,6 +124,7 @@ function Stage:superNew(database, stageConfig, logger, initData, missionPriority
table.insert(self._db.supplyHubs, supplyHub) table.insert(self._db.supplyHubs, supplyHub)
end end
self._db.stageBriefing = database:getStageBriefingForStage(self.zoneName)
self._logger:info("Initiating new Stage with name: " .. self.zoneName) self._logger:info("Initiating new Stage with name: " .. self.zoneName)
---comment ---comment
@@ -453,6 +458,10 @@ function Stage:OnStageNumberChanged(number)
if number == self.stageNumber then if number == self.stageNumber then
self:ActivateStage() self:ActivateStage()
if self._db and self._db.stageBriefing then
self._missionCommandsHelper:AddStageBriefing(self.zoneName, self._db.stageBriefing)
end
end end
if previousActive <= self.stageNumber then if previousActive <= self.stageNumber then
@@ -460,6 +469,10 @@ function Stage:OnStageNumberChanged(number)
self:ActivateBlueStage() self:ActivateBlueStage()
end end
end end
if number > self.stageNumber then
self._missionCommandsHelper:RemoveStageBriefing(self.zoneName)
end
end end
function Stage:GetBriefing() function Stage:GetBriefing()
@@ -6,6 +6,7 @@
---@field lastUpdate number @last update time ---@field lastUpdate number @last update time
---@field updateContinuous fun(self: MissionCommandsHelper, time: number): number @function to update commands continuously ---@field updateContinuous fun(self: MissionCommandsHelper, time: number): number @function to update commands continuously
---@field pinnedByGroup table<string, Mission> @table of pinned missions by group ID ---@field pinnedByGroup table<string, Mission> @table of pinned missions by group ID
---@field private _stageBriefings table<string, string> @table of stage briefings by stage name
---@field private _supplyHubGroups table<string, boolean> @table of supply hub groups by their ID ---@field private _supplyHubGroups table<string, boolean> @table of supply hub groups by their ID
---@field private _logger Logger @logger instance for logging ---@field private _logger Logger @logger instance for logging
---@field private _supplyUnitsTracker SupplyUnitsTracker @supply units tracker instance ---@field private _supplyUnitsTracker SupplyUnitsTracker @supply units tracker instance
@@ -32,6 +33,7 @@ function MissionCommandsHelper.getOrCreate(logLevel)
instance.pinnedByGroup = {} instance.pinnedByGroup = {}
instance.lastUpdate = 0 instance.lastUpdate = 0
instance._supplyHubGroups = {} instance._supplyHubGroups = {}
instance._stageBriefings = {}
instance._supplyUnitsTracker = Spearhead.classes.stageClasses.helpers.SupplyUnitsTracker.getOrCreate(logLevel) instance._supplyUnitsTracker = Spearhead.classes.stageClasses.helpers.SupplyUnitsTracker.getOrCreate(logLevel)
@@ -66,6 +68,14 @@ function MissionCommandsHelper.getOrCreate(logLevel)
return instance return instance
end end
function MissionCommandsHelper:AddStageBriefing(stageName, briefing)
self._stageBriefings[stageName] = briefing
end
function MissionCommandsHelper:RemoveStageBriefing(stageName)
self._stageBriefings[stageName] = nil
end
---@param mission Mission ---@param mission Mission
function MissionCommandsHelper:AddMissionToCommands(mission) function MissionCommandsHelper:AddMissionToCommands(mission)
self._logger:debug("Adding mission to commands: [" .. mission.code .. "]" .. mission.name) self._logger:debug("Adding mission to commands: [" .. mission.code .. "]" .. mission.name)
@@ -174,6 +184,10 @@ function MissionCommandsHelper:AddOverviewCommand(groupID)
return string.format("[%s]\t%s \t%s \t%s %% \t%s nM\n", mission.code, mission.missionTypeDisplay, mission.name, mission:PercentageComplete(), distanceText) return string.format("[%s]\t%s \t%s \t%s %% \t%s nM\n", mission.code, mission.missionTypeDisplay, mission.name, mission:PercentageComplete(), distanceText)
end end
for _, briefing in pairs(self._stageBriefings) do
text = text .. briefing .. "\n\n"
end
---Primary missions ---Primary missions
text = text .. "Primary Missions\n" text = text .. "Primary Missions\n"
for code, enabled in pairs(self.enabledByCode) do for code, enabled in pairs(self.enabledByCode) do
+18 -19
View File
@@ -81,7 +81,10 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
return nil return nil
end end
local missionBriefing = database:getMissionBriefingForMissionZone(zoneName) or "no briefing provided" local missionData = database:getMissionDataForZone(zoneName)
if not missionData then return end
local missionBriefing = missionData.description or "No briefing available"
local success, error = Mission.newSuper(self, zoneName, parsed.missionName, parsed.type, missionBriefing, priority, local success, error = Mission.newSuper(self, zoneName, parsed.missionName, parsed.type, missionBriefing, priority,
database, logger) database, logger)
@@ -109,26 +112,22 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
self._parentStage = parentStage self._parentStage = parentStage
self._dependencies = {} self._dependencies = {}
local dependencies = database:getMissionDependencies(zoneName)
for _, dependency in pairs(dependencies) do
self._dependencies[dependency] = false
end
local completeAtIndex = database:getMissionCompleteAt(zoneName)
if completeAtIndex == nil and self.missionType == "BAI" or self.missionType == "CAS" then
self._completeAtIndex = 0.8
elseif completeAtIndex == nil then
self._completeAtIndex = 1
else
self._completeAtIndex = completeAtIndex
end
self._logger:debug("Complete at index " .. self.zoneName .. ": " .. self._completeAtIndex)
local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup local SpearheadGroup = Spearhead.classes.stageClasses.Groups.SpearheadGroup
local missionData = database:getMissionDataForZone(zoneName) if missionData.dependsOn then
if not missionData then return end for _, dependency in pairs(missionData.dependsOn) do
self._dependencies[dependency] = false
end
end
if missionData.completeAt == nil and (self.missionType == "BAI" or self.missionType == "CAS") then
self._completeAtIndex = 0.8
elseif missionData.completeAt == nil then
self._completeAtIndex = 1
else
self._completeAtIndex = missionData.completeAt
end
self._missionGroups.sceneryTargets = missionData.SceneryTargets or {} self._missionGroups.sceneryTargets = missionData.SceneryTargets or {}
if Spearhead.Util.tableLength(self._missionGroups.sceneryTargets) > 0 then if Spearhead.Util.tableLength(self._missionGroups.sceneryTargets) > 0 then
self._missionGroups.hasTargets = true self._missionGroups.hasTargets = true