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> <!DOCTYPE html>
<html lang="en" data-theme="dark"> <html lang="en" data-theme="dark">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spearhead Missions</title> <title>Spearhead Missions</title>
<link rel="stylesheet" href="/style/style.css"> <link rel="stylesheet" href="/style/style.css">
<script src="/js/site.js"></script> <script src="/js/site.js"></script>
<style> <style>
.side-nav a.active { .side-nav a.active {
font-weight: bold; font-weight: bold;
color: #4fc3f7; color: #4fc3f7;
} }
</style> </style>
<script type="module" src="/js/components.js"></script> <script type="module" src="/js/components.js"></script>
</head> </head>
<body> <body>
<header> <header>
<app-header></app-header> <app-header></app-header>
</header> </header>
<main> <main>
<div class="reference-container"> <div class="reference-container">
<app-sidebar></app-sidebar> <app-sidebar></app-sidebar>
<div class="content-wrapper"> <div class="content-wrapper">
<h1>Advanced Tutorial: Missions</h1> <h1>Advanced Tutorial: Missions</h1>
<h2 id="strike">Strike</h2> <h2 id="strike">Strike</h2>
<p> <p>
Naming: <span class="inline-lua"><span class="lua-variable">MISSION_STRIKE_[Name]</span></span> <br> Naming: <span class="inline-lua"><span class="lua-variable">MISSION_STRIKE_[Name]</span></span> <br>
</p> </p>
<h3 id="specific_targets">Specific Targets</h3> <h3 id="specific_targets">Specific Targets</h3>
<p>TBD</p> <p>TBD</p>
<h3 id="scenery_targets">Scenery Targets</h3> <h3 id="scenery_targets">Scenery Targets</h3>
<p> <p>
Bridges, buildings or other type of targets that are baked into the map are awesome targets.<br> 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. We wanted to make sure they were easily integrated in Spearhead.
</p>
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> <note-box type="info" title="Implementation details">
It's best not to edit the triggerzone, but you can rename it however you like. <br> 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
Scenery objects will always be a specific "target" in the mission. will be added as mission scenery targets.
</note-box>
</p>
<p>
<note-box type="warning" title="Changing IDs"> Scenery targets are treated like mission targets: they are included in the mission completion calculation
Be aware that Object IDs can change when maps are updated and edited and the "Assign as..." action will have to be performed again. (their `IsAlive()` state is checked) and their state is persisted/updated when missions spawn or resume.
</note-box> </p>
<note-box type="warning" title="Changing IDs">
<p>Here's two images showing how a bridge is added to a mission.</p> Due to Object IDs changing when maps are updated and edited the "Assign as..." functionality does not work for scenery targets.
<img src="/img/bridge.png" style="max-height: 35remrem;"/> Hence the need to use trigger zones to define them.
<img src="/img/bridge_added.png" style="max-height: 35remrem;"/> </note-box>
</div>
</div>
<p>Here's two images showing how a bridge is added to a mission.</p>
</main> <img src="/img/bridge.png" style="max-height: 35remrem;"/>
<footer> </div>
<p>&copy; 2025 Spearhead Project</p> </div>
</footer>
</body> </main>
<footer>
</html> <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 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 ---@param group Group
function DCS_UTIL.getUnitTypeFromGroup(group) function DCS_UTIL.getUnitTypeFromGroup(group)
for _, unit in pairs(group:getUnits()) do 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) table.insert(self._tables.SupplyHubZones, zone_name)
end end
if zone_data.properties then if lowered == "scenerytarget" or lowered == "scenerytargets" then
for _, kvPair in pairs(zone_data.properties) do local sceneryObjects = Spearhead.DcsUtil.getSceneryObjectsInZone(zone_data)
if kvPair.key and kvPair.key == "OBJECT ID" then for _, sceneryObject in pairs(sceneryObjects) do
local objectID = tonumber(kvPair.value) table.insert(self._tables.AllSceneryObjects, sceneryObject)
if objectID then
local sceneryObject = Spearhead.classes.stageClasses.Groups.SpearheadSceneryObject.New(objectID)
table.insert(self._tables.AllSceneryObjects, sceneryObject)
end
end
end end
end end
end end
end end
@@ -1,77 +1,77 @@
---@class SpearheadSceneryObject ---@class SpearheadSceneryObject
---@field private persistentName string The persistent name of the scenery object ---@field private persistentName string The persistent name of the scenery object
---@field private objectID number The ID of the scenery object ---@field private objectID number The ID of the scenery object
---@field private internalObj table ---@field private internalObj table
---@field private isDead boolean Indicates if the scenery object is dead ---@field private isDead boolean Indicates if the scenery object is dead
local SpearheadSceneryObject = {} local SpearheadSceneryObject = {}
SpearheadSceneryObject.__index = SpearheadSceneryObject SpearheadSceneryObject.__index = SpearheadSceneryObject
---comment ---comment
---@param objectID number ---@param objectID number
---@return SpearheadSceneryObject? ---@return SpearheadSceneryObject?
function SpearheadSceneryObject.New(objectID) function SpearheadSceneryObject.New(objectID)
local self = setmetatable({}, SpearheadSceneryObject) local self = setmetatable({}, SpearheadSceneryObject)
if objectID == nil then if objectID == nil then
return nil return nil
end end
self.persistentName = "SpearheadSceneryObject_" .. objectID self.persistentName = "SpearheadSceneryObject_" .. objectID
self.objectID = objectID self.objectID = objectID
self.isDead = false self.isDead = false
self.internalObj = { self.internalObj = {
["id_"] = objectID ["id_"] = objectID
} }
return self return self
end end
---@return boolean ---@return boolean
function SpearheadSceneryObject:IsAlive() function SpearheadSceneryObject:IsAlive()
if Object.isExist(self.internalObj) == false then if Object.isExist(self.internalObj) == false then
self:MarkDead() self:MarkDead()
return false return false
end end
if SceneryObject.getLife(self.internalObj) <= 0.10 then if SceneryObject.getLife(self.internalObj) <= 0.10 then
self:MarkDead() self:MarkDead()
return false return false
end end
return true return true
end end
---@private ---@private
function SpearheadSceneryObject:MarkDead() function SpearheadSceneryObject:MarkDead()
if self.isDead == true then return end if self.isDead == true then return end
self.isDead = true self.isDead = true
Spearhead.classes.persistence.Persistence.UnitKilled(self.persistentName, self:GetPoint(), 0, "Scenery") Spearhead.classes.persistence.Persistence.UnitKilled(self.persistentName, self:GetPoint(), 0, "Scenery")
end end
function SpearheadSceneryObject:UpdateStatePersistently() function SpearheadSceneryObject:UpdateStatePersistently()
if self.isDead == true then if self.isDead == true then
return return
end end
local state = Spearhead.classes.persistence.Persistence.UnitState(self.persistentName) local state = Spearhead.classes.persistence.Persistence.UnitState(self.persistentName)
if state and state.isDead == true then if state and state.isDead == true then
trigger.action.explosion(self:GetPoint(), 1000) trigger.action.explosion(self:GetPoint(), 1000)
self.isDead = true self.isDead = true
end end
end end
function SpearheadSceneryObject:GetPersistentName() function SpearheadSceneryObject:GetPersistentName()
return self.persistentName return self.persistentName
end end
function SpearheadSceneryObject:GetPoint() function SpearheadSceneryObject:GetPoint()
return Object.getPoint(self.internalObj) return Object.getPoint(self.internalObj)
end end
if not Spearhead.classes then Spearhead.classes = {} end if not Spearhead.classes then Spearhead.classes = {} end
if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end if not Spearhead.classes.stageClasses then Spearhead.classes.stageClasses = {} end
if not Spearhead.classes.stageClasses.Groups then Spearhead.classes.stageClasses.Groups = {} end if not Spearhead.classes.stageClasses.Groups then Spearhead.classes.stageClasses.Groups = {} end
Spearhead.classes.stageClasses.Groups.SpearheadSceneryObject = SpearheadSceneryObject Spearhead.classes.stageClasses.Groups.SpearheadSceneryObject = SpearheadSceneryObject
File diff suppressed because it is too large Load Diff