Scenery targets refactored and updated (#65)

Changed scenery targets to now be taken from trigger zones instead based on object ID
This commit is contained in:
2025-12-22 15:43:56 +01:00
committed by GitHub
parent f0aee49de2
commit 64a66e2e95
7 changed files with 2530 additions and 154 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 146 KiB

+71 -67
View File
@@ -1,68 +1,72 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spearhead Missions</title>
<link rel="stylesheet" href="/style/style.css">
<script src="/js/site.js"></script>
<style>
.side-nav a.active {
font-weight: bold;
color: #4fc3f7;
}
</style>
<script type="module" src="/js/components.js"></script>
</head>
<body>
<header>
<app-header></app-header>
</header>
<main>
<div class="reference-container">
<app-sidebar></app-sidebar>
<div class="content-wrapper">
<h1>Advanced Tutorial: Missions</h1>
<h2 id="strike">Strike</h2>
<p>
Naming: <span class="inline-lua"><span class="lua-variable">MISSION_STRIKE_[Name]</span></span> <br>
</p>
<h3 id="specific_targets">Specific Targets</h3>
<p>TBD</p>
<h3 id="scenery_targets">Scenery Targets</h3>
<p>
Bridges, buildings or other type of targets that are baked into the map are awesome targets.<br>
We wanted to make sure they were easily integrated in Spearhead.
All you will need to do is right click on the scenery object you want added. <br>
You will then get the option to "Assign as...", click this and you'll see a new trigger zone created. <br>
It's best not to edit the triggerzone, but you can rename it however you like. <br>
Scenery objects will always be a specific "target" in the mission.
</p>
<note-box type="warning" title="Changing IDs">
Be aware that Object IDs can change when maps are updated and edited and the "Assign as..." action will have to be performed again.
</note-box>
<p>Here's two images showing how a bridge is added to a mission.</p>
<img src="/img/bridge.png" style="max-height: 35remrem;"/>
<img src="/img/bridge_added.png" style="max-height: 35remrem;"/>
</div>
</div>
</main>
<footer>
<p>&copy; 2025 Spearhead Project</p>
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spearhead Missions</title>
<link rel="stylesheet" href="/style/style.css">
<script src="/js/site.js"></script>
<style>
.side-nav a.active {
font-weight: bold;
color: #4fc3f7;
}
</style>
<script type="module" src="/js/components.js"></script>
</head>
<body>
<header>
<app-header></app-header>
</header>
<main>
<div class="reference-container">
<app-sidebar></app-sidebar>
<div class="content-wrapper">
<h1>Advanced Tutorial: Missions</h1>
<h2 id="strike">Strike</h2>
<p>
Naming: <span class="inline-lua"><span class="lua-variable">MISSION_STRIKE_[Name]</span></span> <br>
</p>
<h3 id="specific_targets">Specific Targets</h3>
<p>TBD</p>
<h3 id="scenery_targets">Scenery Targets</h3>
<p>
Bridges, buildings or other type of targets that are baked into the map are awesome targets.<br>
We wanted to make sure they were easily integrated in Spearhead.
</p>
<note-box type="info" title="Implementation details">
Spearhead detects scenery targets by the trigger zone name. A zone named <strong>scenerytarget_[freeform]</strong> or
<strong>scenerytargets</strong> (case-insensitive) will be scanned and any scenery objects that has the attribute "Buildings" inside the zone
will be added as mission scenery targets.
</note-box>
<p>
Scenery targets are treated like mission targets: they are included in the mission completion calculation
(their `IsAlive()` state is checked) and their state is persisted/updated when missions spawn or resume.
</p>
<note-box type="warning" title="Changing IDs">
Due to Object IDs changing when maps are updated and edited the "Assign as..." functionality does not work for scenery targets.
Hence the need to use trigger zones to define them.
</note-box>
<p>Here's two images showing how a bridge is added to a mission.</p>
<img src="/img/bridge.png" style="max-height: 35remrem;"/>
</div>
</div>
</main>
<footer>
<p>&copy; 2025 Spearhead Project</p>
</footer>
</body>
</html>
```
Binary file not shown.
+84
View File
@@ -979,6 +979,90 @@ do -- INIT DCS_UTIL
end
---@param zone SpearheadTriggerZone
---@return Array<SpearheadSceneryObject> sceneryObjects
function DCS_UTIL.getSceneryObjectsInZone(zone)
---@type Volume
local volume
if(zone.zone_type == "Cilinder") then
local y = land.getHeight({ x = zone.location.x, y = zone.location.y })
---@type Sphere
local sphere = {
id = world.VolumeType.SPHERE,
params = {
point = { x = zone.location.x, y = y, z = zone.location.y },
radius = zone.radius
}
}
volume = sphere
else
local minX = nil
local maxX = nil
local minZ = nil
local maxZ = nil
for _, point in pairs(zone.verts) do
if minX == nil or point.x < minX then
minX = point.x
end
if maxX == nil or point.x > maxX then
maxX = point.x
end
if minZ == nil or point.y < minZ then
minZ = point.y
end
if maxZ == nil or point.y > maxZ then
maxZ = point.y
end
end
if(minX == nil or maxX == nil or minZ == nil or maxZ == nil) then
return {}
end
---@type Vec3
local min = {
x = minX,
y = land.getHeight({ x = minX, y = minZ }) - 100,
z = minZ
}
---@type Vec3
local max = {
x = maxX,
y = land.getHeight({ x = maxX, y = maxZ }) + 500,
z = maxZ
}
---@type Box
local box = {
id = world.VolumeType.BOX,
params = {
min = min,
max = max
}
}
volume = box
end
---@type Array<SpearheadSceneryObject>
local sceneryObjects = {}
---@param object SceneryObject
local onFound = function(object)
if object and object:isExist() and
object:hasAttribute("Buildings")
then
local obj = Spearhead.classes.stageClasses.Groups.SpearheadSceneryObject.New(object["id_"])
table.insert(sceneryObjects, obj)
end
end
world.searchObjects(Object.Category.SCENERY, volume, onFound)
return sceneryObjects
end
---@param group Group
function DCS_UTIL.getUnitTypeFromGroup(group)
for _, unit in pairs(group:getUnits()) do
+4 -10
View File
@@ -186,18 +186,12 @@ function Database.New(Logger)
table.insert(self._tables.SupplyHubZones, zone_name)
end
if zone_data.properties then
for _, kvPair in pairs(zone_data.properties) do
if kvPair.key and kvPair.key == "OBJECT ID" then
local objectID = tonumber(kvPair.value)
if objectID then
local sceneryObject = Spearhead.classes.stageClasses.Groups.SpearheadSceneryObject.New(objectID)
table.insert(self._tables.AllSceneryObjects, sceneryObject)
end
end
if lowered == "scenerytarget" or lowered == "scenerytargets" then
local sceneryObjects = Spearhead.DcsUtil.getSceneryObjectsInZone(zone_data)
for _, sceneryObject in pairs(sceneryObjects) do
table.insert(self._tables.AllSceneryObjects, sceneryObject)
end
end
end
end
@@ -1,77 +1,77 @@
---@class SpearheadSceneryObject
---@field private persistentName string The persistent name of the scenery object
---@field private objectID number The ID of the scenery object
---@field private internalObj table
---@field private isDead boolean Indicates if the scenery object is dead
local SpearheadSceneryObject = {}
SpearheadSceneryObject.__index = SpearheadSceneryObject
---comment
---@param objectID number
---@return SpearheadSceneryObject?
function SpearheadSceneryObject.New(objectID)
local self = setmetatable({}, SpearheadSceneryObject)
if objectID == nil then
return nil
end
self.persistentName = "SpearheadSceneryObject_" .. objectID
self.objectID = objectID
self.isDead = false
self.internalObj = {
["id_"] = objectID
}
return self
end
---@return boolean
function SpearheadSceneryObject:IsAlive()
if Object.isExist(self.internalObj) == false then
self:MarkDead()
return false
end
if SceneryObject.getLife(self.internalObj) <= 0.10 then
self:MarkDead()
return false
end
return true
end
---@private
function SpearheadSceneryObject:MarkDead()
if self.isDead == true then return end
self.isDead = true
Spearhead.classes.persistence.Persistence.UnitKilled(self.persistentName, self:GetPoint(), 0, "Scenery")
end
function SpearheadSceneryObject:UpdateStatePersistently()
if self.isDead == true then
return
end
local state = Spearhead.classes.persistence.Persistence.UnitState(self.persistentName)
if state and state.isDead == true then
trigger.action.explosion(self:GetPoint(), 1000)
self.isDead = true
end
end
function SpearheadSceneryObject:GetPersistentName()
return self.persistentName
end
function SpearheadSceneryObject:GetPoint()
return Object.getPoint(self.internalObj)
end
if not Spearhead.classes then Spearhead.classes = {} end
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
if not Spearhead.classes.stageClasses.Groups then Spearhead.classes.stageClasses.Groups = {} end
Spearhead.classes.stageClasses.Groups.SpearheadSceneryObject = SpearheadSceneryObject
---@class SpearheadSceneryObject
---@field private persistentName string The persistent name of the scenery object
---@field private objectID number The ID of the scenery object
---@field private internalObj table
---@field private isDead boolean Indicates if the scenery object is dead
local SpearheadSceneryObject = {}
SpearheadSceneryObject.__index = SpearheadSceneryObject
---comment
---@param objectID number
---@return SpearheadSceneryObject?
function SpearheadSceneryObject.New(objectID)
local self = setmetatable({}, SpearheadSceneryObject)
if objectID == nil then
return nil
end
self.persistentName = "SpearheadSceneryObject_" .. objectID
self.objectID = objectID
self.isDead = false
self.internalObj = {
["id_"] = objectID
}
return self
end
---@return boolean
function SpearheadSceneryObject:IsAlive()
if Object.isExist(self.internalObj) == false then
self:MarkDead()
return false
end
if SceneryObject.getLife(self.internalObj) <= 0.10 then
self:MarkDead()
return false
end
return true
end
---@private
function SpearheadSceneryObject:MarkDead()
if self.isDead == true then return end
self.isDead = true
Spearhead.classes.persistence.Persistence.UnitKilled(self.persistentName, self:GetPoint(), 0, "Scenery")
end
function SpearheadSceneryObject:UpdateStatePersistently()
if self.isDead == true then
return
end
local state = Spearhead.classes.persistence.Persistence.UnitState(self.persistentName)
if state and state.isDead == true then
trigger.action.explosion(self:GetPoint(), 1000)
self.isDead = true
end
end
function SpearheadSceneryObject:GetPersistentName()
return self.persistentName
end
function SpearheadSceneryObject:GetPoint()
return Object.getPoint(self.internalObj)
end
if not Spearhead.classes then Spearhead.classes = {} end
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
if not Spearhead.classes.stageClasses.Groups then Spearhead.classes.stageClasses.Groups = {} end
Spearhead.classes.stageClasses.Groups.SpearheadSceneryObject = SpearheadSceneryObject
File diff suppressed because it is too large Load Diff