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:
Binary file not shown.
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 146 KiB |
@@ -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>© 2025 Spearhead Project</p>
|
</div>
|
||||||
</footer>
|
|
||||||
</body>
|
</main>
|
||||||
|
<footer>
|
||||||
</html>
|
<p>© 2025 Spearhead Project</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
```
|
```
|
||||||
Binary file not shown.
@@ -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
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user