Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95fe7e1058 | ||
|
|
b8fe242c43 | ||
|
|
61ba4de338 | ||
|
|
674160abbf | ||
|
|
8ff25ffeb0 | ||
|
|
428fe75a12 | ||
|
|
2e5a31faef |
@@ -64,7 +64,7 @@
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
if (window.location.hostname.toLowerCase() == 'beta.spearhead.rocks') {
|
||||
if (true || window.location.hostname.toLowerCase() == 'beta.spearhead.rocks') {
|
||||
betaHtml = '<note-box type="warning" title="Beta Version">You are looking at docs that are released with the beta version.</note-box>';
|
||||
}
|
||||
document.getElementById('beta-box-div').innerHTML = betaHtml || '';
|
||||
|
||||
@@ -50,6 +50,17 @@ class DownloadScript extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
async fetchReleaseAssets(url){
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error fetching release assets:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
|
||||
var version = "?";
|
||||
@@ -61,9 +72,10 @@ class DownloadScript extends HTMLElement {
|
||||
if (latestRelease) {
|
||||
version = latestRelease.tag_name;
|
||||
timestamp = new Date(latestRelease.published_at).toLocaleDateString('en-CA');
|
||||
const assets = latestRelease.assets;
|
||||
|
||||
const assets = await this.fetchReleaseAssets(latestRelease.assets_url);
|
||||
if (assets && assets.length > 0) {
|
||||
const spearheadAsset = assets.find(asset => asset.name.includes('spearhead.v'));
|
||||
const spearheadAsset = assets.find(asset => asset.name.includes('spearhead'));
|
||||
if (spearheadAsset) {
|
||||
size = (spearheadAsset.size / 1024).toFixed(2) + 'kb';
|
||||
href = spearheadAsset.browser_download_url;
|
||||
@@ -93,7 +105,7 @@ class DownloadScript extends HTMLElement {
|
||||
<p>
|
||||
<span class="version-text">${version}</span> (${timestamp}) <br>
|
||||
<a style="text-decoration: underline;" target="_blank" href="${href}">Download</a> (${size}) <br>
|
||||
<a style="text-decoration: underline;" target="_blank" href="https://git.dutchie031.com/Spearhead/spearhead/releases">See All Versions here</a>
|
||||
<a style="text-decoration: underline;" target="_blank" href="https://git.dutchie031.com/api/v1/repos/Spearhead/spearhead/releases">See All Versions here</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -169,16 +169,13 @@ class Sidebar extends HTMLElement {
|
||||
|
||||
render() {
|
||||
var betaHtml = '';
|
||||
if (true || window.location.hostname.toLowerCase() == 'beta.spearhead.rocks') {
|
||||
if (window.location.hostname.toLowerCase() == 'beta.spearhead.rocks') {
|
||||
betaHtml = '<note-box type="warning" title="Beta Version">You are looking at docs that are released with the beta version.</note-box>';
|
||||
}
|
||||
|
||||
this.innerHTML = `
|
||||
<div class="side-nav">
|
||||
<div style="width:100%">
|
||||
${betaHtml}
|
||||
</div>
|
||||
|
||||
${betaHtml}
|
||||
<h4 class="side-nav-title"></h4>
|
||||
<ul>
|
||||
<!-- Navigation items will be populated automatically -->
|
||||
|
||||
@@ -80,12 +80,17 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<note-box type="info" title="Combining Tasks">
|
||||
Currently a group can do 1 thing. Either be Primary, Seconday, Sweep or Intercept. <br>
|
||||
If you want to have different types during different stages, it's best to copy paste groups and
|
||||
rename them accordingly. <br>
|
||||
</note-box>
|
||||
|
||||
<note-box type="info" title="Airfield Defenses">
|
||||
|
||||
</note-box>
|
||||
|
||||
<h3 id="cap-zones-ref">Zones</h3>
|
||||
<table class="table-no-style">
|
||||
<tbody>
|
||||
@@ -94,7 +99,6 @@
|
||||
<td>=></td>
|
||||
<td>A Cap ROUTE. The two most outer points are used to define the fly-over points.</td>
|
||||
</tr>
|
||||
<tr><td>______________________</td><td></td><td></td> </tr>
|
||||
<tr>
|
||||
<td><code-inline>INTERCEPTZONE_[ZoneID]_[NAME]</code-inline></td>
|
||||
<td>=></td>
|
||||
@@ -108,19 +112,6 @@
|
||||
</p>
|
||||
<h2 id="setup">Setting up groups</h2>
|
||||
|
||||
<h3 id="airbases-grouping">Airbases</h3>
|
||||
<p>
|
||||
Before talking about the groups, it's good to mention that groups are currently logically grouped and managed by an Airbase. <br>
|
||||
Meaning, Airbase A does not know how many flights Airbase B is sending out. <br>
|
||||
This might change in the future where multiple Airbases can work together.
|
||||
</p>
|
||||
|
||||
<note-box type="info" title="Airbase Defenses">
|
||||
When an Airbase is "active" and thus has aircraft being scheduled for taskings, all RED groups at that airfield will also be spawned. <br>
|
||||
Additionally, all missions of type <code-inline>SAM</code-inline> will be spawned (without being available in Primary Missions). <br>
|
||||
This should hopefully give you all the tools to make distance CAP airbases still feel very well defended.
|
||||
</note-box>
|
||||
|
||||
<h3 id="types-explained">Types explained</h3>
|
||||
<p>
|
||||
Before we go into depth on each type it's best to first look at the types briefly and what we
|
||||
@@ -149,7 +140,7 @@
|
||||
The ground attack units mentioned are not in yet and thus escort groups are not either. <br>
|
||||
|
||||
<note-box type="warning" title="Overriding Taskings">
|
||||
Each tasking has very specific waypoints, both for departure, arrival and ofcourse all point in between. <br>
|
||||
Each tasking has very specific waypoints, both for departure, arrical and ofcourse all point in between. <br>
|
||||
Overriding the "tasking" will break part of the cap flow as "RTBInTen" and RTB events are triggered by waypoints. <br>
|
||||
Overriding these waypoints and taskings will break the management by Spearhead.
|
||||
</note-box>
|
||||
@@ -163,7 +154,7 @@
|
||||
The way the trigger zone is mapped to a route is as follows: <br>
|
||||
<br>
|
||||
The 2 points that are furthest apart from each other are chosen as the "leg" of the route. <br>
|
||||
The other 2 points are discarded at this time. <br>
|
||||
The other 2 points are discarded. <br>
|
||||
<br>
|
||||
The Orbit route is then created with an "Anchored" task. With the closest point being the starting
|
||||
point with an outbound leg to the furthest point. <br>
|
||||
|
||||
@@ -337,7 +337,6 @@ main {
|
||||
|
||||
.side-nav {
|
||||
min-width: 200px;
|
||||
max-width: 200px;
|
||||
padding-left: 0;
|
||||
overflow-y: auto;
|
||||
border-right: none;
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
name: PR Prerequisites
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
|
||||
env:
|
||||
LUA_VERSION: "5.1"
|
||||
LUA_LANGUAGE_SERVER_VERSION: "3.19.1"
|
||||
|
||||
jobs:
|
||||
bundles_without_error:
|
||||
runs-on: ubuntu-latest
|
||||
name: Bundles Without Errors
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Lua
|
||||
uses: leafo/gh-actions-lua@v13
|
||||
with:
|
||||
luaVersion: ${{ env.LUA_VERSION }}
|
||||
|
||||
- name: Compile Spearhead
|
||||
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-action@action/v0
|
||||
with:
|
||||
source-root: ./src
|
||||
output-file: ./output/spearhead.lua
|
||||
|
||||
- name: Verify Compiled Lua Syntax
|
||||
run: lua -e "assert(loadfile('./output/spearhead.lua'))"
|
||||
|
||||
- name: Set up Luarocks
|
||||
uses: leafo/gh-actions-luarocks@v4
|
||||
|
||||
- name: Install luacheck
|
||||
run: luarocks install luacheck
|
||||
|
||||
- name: Lint Compiled Output
|
||||
run: luacheck ./output/spearhead.lua
|
||||
|
||||
lua_check:
|
||||
runs-on: ubuntu-latest
|
||||
name: Lua Check
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Lua
|
||||
uses: leafo/gh-actions-lua@v13
|
||||
with:
|
||||
luaVersion: ${{ env.LUA_VERSION }}
|
||||
|
||||
- name: Install lua-language-server
|
||||
run: |
|
||||
mkdir -p ./luals
|
||||
# For Ubuntu/Debian
|
||||
wget https://github.com/LuaLS/lua-language-server/releases/download/${{ env.LUA_LANGUAGE_SERVER_VERSION }}/lua-language-server-${{ env.LUA_LANGUAGE_SERVER_VERSION }}-linux-x64.tar.gz
|
||||
tar -xzf lua-language-server-*.tar.gz -C ./luals
|
||||
rm lua-language-server-*.tar.gz
|
||||
|
||||
- name: Verify Lua Language Server Installation
|
||||
run: ./luals/bin/lua-language-server --version
|
||||
|
||||
- name: Run Lua Language Server
|
||||
run: ./luals/bin/lua-language-server --check ./src --checklevel=Warning
|
||||
|
||||
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"Lua": {
|
||||
"runtime": {
|
||||
"version": "Lua 5.1"
|
||||
},
|
||||
"workspace": {
|
||||
"library": [
|
||||
"./src",
|
||||
"./DcsTypes.lua"
|
||||
],
|
||||
"checkThirdParty": false
|
||||
},
|
||||
"diagnostics": {
|
||||
"enable": true,
|
||||
"globals": [
|
||||
"lfs"
|
||||
],
|
||||
"severity": {
|
||||
"undefined-field": "Warning",
|
||||
"unused-local": "Warning"
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"enable": false
|
||||
},
|
||||
"completion": {
|
||||
"enable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
|
||||
|
||||
|
||||
--assert(loadfile("C:\\Repos\\DCS\\Spearhead\\dev\\dev_classes.lua"))()
|
||||
|
||||
local basePath = "C:\\Repos\\DCS\\Spearhead\\"
|
||||
local classPath = basePath .. "classes\\"
|
||||
|
||||
assert(loadfile(classPath .. "_baseClasses\\Queue.lua"))()
|
||||
|
||||
assert(loadfile(classPath .. "spearhead_base.lua"))()
|
||||
assert(loadfile(classPath .. "spearhead_routeutil.lua"))()
|
||||
assert(loadfile(classPath .. "spearhead_events.lua"))()
|
||||
assert(loadfile(classPath .. "spearhead_db.lua"))()
|
||||
|
||||
assert(loadfile(classPath .. "fleetClasses\\FleetGroup.lua"))()
|
||||
assert(loadfile(classPath .. "fleetClasses\\GlobalFleetManager.lua"))()
|
||||
|
||||
assert(loadfile(classPath .. "helpers\\MizGroupsManager.lua"))()
|
||||
assert(loadfile(classPath .. "helpers\\SpawnManager.lua"))()
|
||||
|
||||
assert(loadfile(classPath .. "configuration\\CapConfig.lua"))()
|
||||
assert(loadfile(classPath .. "configuration\\StageConfig.lua"))()
|
||||
|
||||
assert(loadfile(classPath .. "stageClasses\\GlobalStageManager.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\missions\\baseMissions\\Mission.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\missions\\ZoneMission.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\missions\\RunwayStrikeMission.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\missions\\BuildableMission.lua"))()
|
||||
|
||||
|
||||
assert(loadfile(classPath .. "stageClasses\\Stages\\BaseStage\\Stage.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\Stages\\PrimaryStage.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\Stages\\ExtraStage.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\Stages\\WaitingStage.lua"))()
|
||||
|
||||
|
||||
assert(loadfile(classPath .. "stageClasses\\Groups\\SpearheadGroup.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\Groups\\SpearheadSceneryObject.lua"))()
|
||||
|
||||
|
||||
assert(loadfile(classPath .. "stageClasses\\helpers\\MissionCommandsHelper.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\helpers\\SupplyConfig.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\helpers\\SupplyUnitsTracker.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\helpers\\BattleManager.lua"))()
|
||||
|
||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\abstract\\BuildableZone.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\StageBase.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\BlueSam.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\FarpZone.lua"))()
|
||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\SupplyHub.lua"))()
|
||||
|
||||
assert(loadfile(classPath .. "capClasses\\taskings\\RTB.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\taskings\\CAP.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\taskings\\SWEEP.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\taskings\\INTERCEPT.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\airGroups\\AirGroup.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\airGroups\\CapGroup.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\airGroups\\SweepGroup.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\airGroups\\InterceptGroup.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\detection\\DetectionManager.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\GlobalCapManager.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\CapAirbase.lua"))()
|
||||
assert(loadfile(classPath .. "capClasses\\runwayBombing\\RunwayBombingTracker.lua"))()
|
||||
|
||||
assert(loadfile(classPath .. "persistence\\Persistence.lua"))()
|
||||
|
||||
-- Startup:
|
||||
|
||||
|
||||
|
||||
assert(loadfile(basePath .. "main.lua"))()
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
|
||||
SpearheadConfig = {
|
||||
|
||||
debugEnabled = true,
|
||||
CapConfig = {
|
||||
--quickly enable of disable the entire CAP Logic
|
||||
--(you can also just rename all units to not be named "CAP_")
|
||||
enabled = true, -- default true
|
||||
|
||||
--min ground speed for CAP aircraft during patrol
|
||||
-- unit: knots
|
||||
minSpeed = 400, -- default 400
|
||||
|
||||
--max speed for CAP aircraft during patrol
|
||||
-- unit: knots
|
||||
maxSpeed = 500, -- default 500
|
||||
|
||||
--minAlt for aircraft on patrol
|
||||
-- unit: feet
|
||||
minAlt = 18000, -- default 18000
|
||||
|
||||
--maxAlt for aircraft on patrol
|
||||
-- unit: feet
|
||||
maxAlt = 28000, -- default 28000
|
||||
|
||||
--Delay for aircraft from touchdown to off the chocks.
|
||||
-- unit: seconds
|
||||
rearmDelay = 180, -- default 600
|
||||
repairDelay = 600, -- default 600
|
||||
--Delay for aircraft from death to takeoff.
|
||||
--When the seconds remaining is the same at the rearmDelay it will be spawned on the ramp and follow the rearm logic.
|
||||
-- !! Can not be lower than rearmDelay
|
||||
-- unit: seconds
|
||||
deathDelay = 1800, -- default 1800
|
||||
},
|
||||
StageConfig = {
|
||||
|
||||
-- management of stages and its missions.
|
||||
-- This is not related to CAP managers which will continue to work even if stage management is disabled
|
||||
enabled = true, -- default true
|
||||
|
||||
--Will draw the active and the next stage
|
||||
drawStages = true, -- default true
|
||||
drawPreActivated = true,
|
||||
markLastContact = true,
|
||||
|
||||
--AutoStages will continue to the next stage automatically on completion of the missions within the stage.
|
||||
-- If you want to make it so the next stage triggers only when you want to disable it here and manually implement the actions needed.
|
||||
--[[
|
||||
TODO: Add manual stage transition documentation
|
||||
]]
|
||||
autoStages = true, --default true
|
||||
|
||||
--Maximum missions per stage (includes all types of missions)
|
||||
maxMissionStage = 100,
|
||||
|
||||
--Stage starting number
|
||||
startingStage = 1,
|
||||
|
||||
---DEBUG logging. Consider keeping this disabled
|
||||
debugEnabled = true
|
||||
},
|
||||
Persistence = {
|
||||
--- io and lfs cannot be sanitized in the MissionScripting.lua
|
||||
|
||||
--- enables or disables the persistence logic in spearhead
|
||||
enabled = true,
|
||||
|
||||
--- sets the directory where the persistence file is stored
|
||||
--- if nil then lfs.writedir() will be used.
|
||||
--- which will
|
||||
directory = nil ,
|
||||
|
||||
--- the filename of the persistence file. Should end with .json for convention, but any text extension should do.
|
||||
fileName = "Spearhead_Persistence_Dev"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ local Util = require("classes.util.Util")
|
||||
local CapGroup = require("classes.capClasses.airGroups.CapGroup")
|
||||
local SweepGroup = require("classes.capClasses.airGroups.SweepGroup")
|
||||
local InterceptGroup = require("classes.capClasses.airGroups.InterceptGroup")
|
||||
local RunwayBombingTracker = require("classes.capClasses.runwayBombing.RunwayBombingTracker")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local RunwayStrikeMission = require("classes.stageClasses.missions.RunwayStrikeMission")
|
||||
|
||||
@@ -36,11 +37,12 @@ end
|
||||
---@param database Database
|
||||
---@param logger table
|
||||
---@param capConfig table
|
||||
---@param stageConfig table
|
||||
---@param runwayBombingTracker RunwayBombingTracker
|
||||
---@param detectionManager DetectionManager
|
||||
---@param spawnManager SpawnManager
|
||||
---@return CapBase
|
||||
function CapBase.new(airbaseName, database, logger, capConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||
function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||
CapBase.__index = CapBase
|
||||
local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]]
|
||||
|
||||
@@ -59,7 +61,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, runwayBombingTrac
|
||||
|
||||
local baseData = database:getAirbaseDataForZone(airbaseName)
|
||||
if baseData and baseData.CapGroups then
|
||||
for _, name in pairs(baseData.CapGroups) do
|
||||
for key, name in pairs(baseData.CapGroups) do
|
||||
local capGroup = CapGroup.New(name, capConfig, logger, spawnManager)
|
||||
if capGroup then
|
||||
self.capGroupsByName[name] = capGroup
|
||||
@@ -68,7 +70,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, runwayBombingTrac
|
||||
end
|
||||
|
||||
if baseData and baseData.SweepGroups then
|
||||
for _, name in pairs(baseData.SweepGroups) do
|
||||
for key, name in pairs(baseData.SweepGroups) do
|
||||
local sweepGroup = SweepGroup.New(name, capConfig, logger, spawnManager)
|
||||
if sweepGroup then
|
||||
self.sweepGroupsByName[name] = sweepGroup
|
||||
@@ -77,7 +79,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, runwayBombingTrac
|
||||
end
|
||||
|
||||
if baseData and baseData.InterceptGroups then
|
||||
for _, name in pairs(baseData.InterceptGroups) do
|
||||
for key, name in pairs(baseData.InterceptGroups) do
|
||||
local interceptGroup = InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
|
||||
if interceptGroup then
|
||||
self.interceptGroupsByName[name] = interceptGroup
|
||||
@@ -96,6 +98,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, runwayBombingTrac
|
||||
|
||||
timer.scheduleFunction(CheckStateContinuous, self, timer.getTime() + 15)
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -124,7 +127,7 @@ end
|
||||
|
||||
function CapBase:SpawnIfApplicable()
|
||||
self.logger:debug("Check spawns for airbase " .. self.airbaseName)
|
||||
for _, capGroup in pairs(self.capGroupsByName) do
|
||||
for groupName, capGroup in pairs(self.capGroupsByName) do
|
||||
local targetStage = capGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||
|
||||
if targetStage ~= nil and capGroup:GetState() == "UnSpawned" then
|
||||
@@ -132,7 +135,7 @@ function CapBase:SpawnIfApplicable()
|
||||
end
|
||||
end
|
||||
|
||||
for _, sweepGroup in pairs(self.sweepGroupsByName) do
|
||||
for groupName, sweepGroup in pairs(self.sweepGroupsByName) do
|
||||
local targetStage = sweepGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||
|
||||
if targetStage ~= nil and sweepGroup:GetState() == "UnSpawned" then
|
||||
@@ -140,7 +143,7 @@ function CapBase:SpawnIfApplicable()
|
||||
end
|
||||
end
|
||||
|
||||
for _, interceptGroup in pairs(self.interceptGroupsByName) do
|
||||
for groupName, interceptGroup in pairs(self.interceptGroupsByName) do
|
||||
local targetStage = interceptGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||
|
||||
if targetStage ~= nil and interceptGroup:GetState() == "UnSpawned" then
|
||||
@@ -151,9 +154,8 @@ end
|
||||
|
||||
function CapBase:CheckAndScheduleCAP()
|
||||
self.logger:debug("Check taskings for airbase " .. self.airbaseName)
|
||||
---@type table<string, number>
|
||||
|
||||
local countPerStage = {}
|
||||
---@type table<string, number>
|
||||
local requiredPerStage = {}
|
||||
|
||||
local airbase = Airbase.getByName(self.airbaseName)
|
||||
@@ -310,7 +312,8 @@ function CapBase:CheckAndScheduleIntercept()
|
||||
|
||||
self.logger:debug("Check intercept taskings for airbase " .. self.airbaseName)
|
||||
|
||||
---@type table<string, boolean>
|
||||
local interceptZoneIDs = {}
|
||||
|
||||
local interceptZoneIDs = {}
|
||||
|
||||
local airbase = Airbase.getByName(self.airbaseName)
|
||||
@@ -318,7 +321,7 @@ function CapBase:CheckAndScheduleIntercept()
|
||||
return nil
|
||||
end
|
||||
|
||||
for _, group in pairs(self.interceptGroupsByName) do
|
||||
for name, group in pairs(self.interceptGroupsByName) do
|
||||
local targetZoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||
if targetZoneID then
|
||||
interceptZoneIDs[targetZoneID] = true
|
||||
@@ -376,6 +379,7 @@ function CapBase:CheckAndScheduleIntercept()
|
||||
if total < required then
|
||||
for _, group in pairs(self.interceptGroupsByName) do
|
||||
if total < required then
|
||||
local zoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||
if group:GetState() == "ReadyOnTheRamp" then
|
||||
group:SendToInterceptUnits(targets, name, airbase)
|
||||
total = total + 1
|
||||
|
||||
@@ -8,15 +8,19 @@ local GlobalCapManager = {}
|
||||
do
|
||||
local airbasesPerStage = {}
|
||||
local allAirbasesByName = {}
|
||||
local activeAirbasesPerActiveStage = {}
|
||||
local unitsPerzonePerStage = {}
|
||||
|
||||
local initiated = false
|
||||
|
||||
---comment
|
||||
---@param database Database
|
||||
---@param capConfig table
|
||||
---@param stageConfig StageConfig
|
||||
---@param detectionManager DetectionManager
|
||||
---@param logLevel LogLevel
|
||||
---@param spawnManager SpawnManager
|
||||
function GlobalCapManager.start(database, capConfig, detectionManager, logLevel, spawnManager)
|
||||
function GlobalCapManager.start(database, capConfig, detectionManager, stageConfig, logLevel, spawnManager)
|
||||
if initiated == true then return end
|
||||
|
||||
local logger = Logger.new("AirbaseManager", logLevel)
|
||||
@@ -25,7 +29,7 @@ do
|
||||
|
||||
local zones = database:getStagezoneNames()
|
||||
if zones then
|
||||
for _, stageName in pairs(zones) do
|
||||
for key, stageName in pairs(zones) do
|
||||
if airbasesPerStage[stageName] == nil then
|
||||
airbasesPerStage[stageName] = {}
|
||||
end
|
||||
@@ -36,7 +40,8 @@ do
|
||||
if airbaseName then
|
||||
local airbaseSpecificLogger = Logger.new("CAP_" .. airbaseName, logLevel)
|
||||
|
||||
local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||
local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||
|
||||
if airbase then
|
||||
table.insert(airbasesPerStage[stageName], airbase)
|
||||
allAirbasesByName[airbaseName] = airbase
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local RTBMission = require("classes.capClasses.taskings.RTB")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
||||
local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing")
|
||||
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
||||
@@ -80,7 +81,7 @@ function AirGroup:SetMission(mission)
|
||||
end
|
||||
end
|
||||
|
||||
local setMissionDelayed = function(data, _)
|
||||
local setMissionDelayed = function(data, time)
|
||||
data.self:SetMissionPrivate(data.mission)
|
||||
end
|
||||
|
||||
@@ -356,7 +357,7 @@ do --- RESPAWN FUNCTIONS
|
||||
self:SetState("Dead")
|
||||
|
||||
---@param selfA AirGroup
|
||||
local respawnTask = function(selfA, _)
|
||||
local respawnTask = function(selfA, time)
|
||||
selfA:StartRepair()
|
||||
end
|
||||
|
||||
@@ -375,7 +376,8 @@ do --- RESPAWN FUNCTIONS
|
||||
end
|
||||
|
||||
---comment
|
||||
local rearmTask = function(_, _)
|
||||
---@param selfA AirGroup
|
||||
local rearmTask = function(selfA, time)
|
||||
self:StartRearm()
|
||||
end
|
||||
|
||||
@@ -400,7 +402,7 @@ do --- RESPAWN FUNCTIONS
|
||||
end
|
||||
|
||||
---@param selfA AirGroup
|
||||
local rearmTask = function(selfA, _)
|
||||
local rearmTask = function(selfA, time)
|
||||
selfA:MarkRearmComplete()
|
||||
end
|
||||
|
||||
@@ -413,7 +415,6 @@ end
|
||||
do --EVENT LISTENERS
|
||||
---@param unit Unit
|
||||
function AirGroup:OnUnitLost(unit)
|
||||
if unit == nil then return end
|
||||
self:CheckLiveness()
|
||||
end
|
||||
|
||||
@@ -433,7 +434,7 @@ do --EVENT LISTENERS
|
||||
end
|
||||
end
|
||||
|
||||
function AirGroup:OnUnitLanded(_, _)
|
||||
function AirGroup:OnUnitLanded(unit, airbase)
|
||||
local anyInAir = false
|
||||
local group = Group.getByName(self._groupName)
|
||||
if group then
|
||||
|
||||
@@ -107,13 +107,13 @@ function CapGroup:InitWithName(groupName)
|
||||
|
||||
local subsplit = Util.split_string(configPart, "|")
|
||||
if subsplit then
|
||||
for _, value in pairs(subsplit) do
|
||||
for key, value in pairs(subsplit) do
|
||||
local keySplit = Util.split_string(value, "]")
|
||||
local targetZone = keySplit[2]
|
||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||
local commaSeperated = Util.split_string(allActives, ",")
|
||||
for _, childValue in pairs(commaSeperated) do
|
||||
local dashSeperated = Util.split_string(childValue, "-")
|
||||
for _, value in pairs(commaSeperated) do
|
||||
local dashSeperated = Util.split_string(value, "-")
|
||||
if Util.tableLength(dashSeperated) > 1 then
|
||||
local from = tonumber(dashSeperated[1])
|
||||
local till = tonumber(dashSeperated[2])
|
||||
|
||||
@@ -213,6 +213,8 @@ function InterceptGroup:UpdateTask()
|
||||
self._currentTargetName = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
local speed = self._config:getMaxSpeed()
|
||||
local interceptPoint = self:GetInterceptPoint(groupPoint, speed, closestUnit)
|
||||
|
||||
@@ -321,13 +323,13 @@ function InterceptGroup:InitWithName(groupName)
|
||||
configPart = string.sub(configPart, 2, #configPart)
|
||||
local subsplit = Util.split_string(configPart, "|")
|
||||
if subsplit then
|
||||
for _, value in pairs(subsplit) do
|
||||
for key, value in pairs(subsplit) do
|
||||
local keySplit = Util.split_string(value, "]")
|
||||
local targetZone = keySplit[2]
|
||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||
local commaSeperated = Util.split_string(allActives, ",")
|
||||
for _, childValue in pairs(commaSeperated) do
|
||||
local dashSeperated = Util.split_string(childValue, "-")
|
||||
for _, value in pairs(commaSeperated) do
|
||||
local dashSeperated = Util.split_string(value, "-")
|
||||
if Util.tableLength(dashSeperated) > 1 then
|
||||
local from = tonumber(dashSeperated[1])
|
||||
local till = tonumber(dashSeperated[2])
|
||||
|
||||
@@ -41,7 +41,7 @@ end
|
||||
---@field self SweepGroup
|
||||
|
||||
---@param params SetTaskParams
|
||||
local setMissionDelayedTask = function(params, _)
|
||||
local setMissionDelayedTask = function(params, time)
|
||||
params.self:SetMissionPrivate(params.task)
|
||||
end
|
||||
|
||||
@@ -50,6 +50,8 @@ function SweepGroup:SendToZone(zone, targetZoneID, airbase)
|
||||
|
||||
self._currentTargetZoneID = targetZoneID
|
||||
|
||||
local group = Group.getByName(self._groupName)
|
||||
|
||||
local mission = SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
||||
if mission then
|
||||
---@type SetTaskParams
|
||||
@@ -80,13 +82,13 @@ function SweepGroup:InitWithName(groupName)
|
||||
|
||||
local subsplit = Util.split_string(configPart, "|")
|
||||
if subsplit then
|
||||
for _, value in pairs(subsplit) do
|
||||
for key, value in pairs(subsplit) do
|
||||
local keySplit = Util.split_string(value, "]")
|
||||
local targetZone = keySplit[2]
|
||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||
local commaSeperated = Util.split_string(allActives, ",")
|
||||
for _, childValue in pairs(commaSeperated) do
|
||||
local dashSeperated = Util.split_string(childValue, "-")
|
||||
for _, value in pairs(commaSeperated) do
|
||||
local dashSeperated = Util.split_string(value, "-")
|
||||
if Util.tableLength(dashSeperated) > 1 then
|
||||
local from = tonumber(dashSeperated[1])
|
||||
local till = tonumber(dashSeperated[2])
|
||||
|
||||
@@ -38,6 +38,7 @@ function DetectionManager.New(logger)
|
||||
end
|
||||
timer.scheduleFunction(updateDetected, self, timer.getTime() + 130)
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ end
|
||||
|
||||
---comment
|
||||
---@param weapon Weapon
|
||||
function RunwayBombingTracker:OnWeaponFired(_, weapon, _)
|
||||
function RunwayBombingTracker:OnWeaponFired(unit, weapon, target)
|
||||
|
||||
if weapon == nil then
|
||||
return
|
||||
@@ -83,7 +83,11 @@ function RunwayBombingTracker.trackWeaponTask(weaponTrackingArgs, time)
|
||||
x = pos.x + velocity.x * nextInterval,
|
||||
y = pos.z + velocity.z * nextInterval
|
||||
}
|
||||
|
||||
|
||||
self:OnWeaponImpact(weapon:getDesc(), impactPoint)
|
||||
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -105,7 +109,7 @@ function RunwayBombingTracker:OnWeaponImpact(weaponDesc, impactPoint)
|
||||
local warhead = weaponDesc.warhead
|
||||
local explosiveMass = warhead.explosiveMass or warhead.shapedExplosiveMass
|
||||
|
||||
for _, strikeMission in pairs(self.trackedRunways) do
|
||||
for runway, strikeMission in pairs(self.trackedRunways) do
|
||||
|
||||
local zone= strikeMission:GetRunwayZone()
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
||||
local furthestA = nil
|
||||
local furthestB = nil
|
||||
|
||||
local furthestFromBase = nil
|
||||
local furthestFromBaseDistance = 0
|
||||
|
||||
local furthestDistance = 0
|
||||
|
||||
for indexA, pointA in ipairs(capZone.verts) do
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
|
||||
|
||||
local briefingMessageTime = nil
|
||||
|
||||
---@class GlobalConfig
|
||||
---@field private _briefingTime number
|
||||
---@field private _debugEnabled boolean
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local Logger = require("classes.util.Logger")
|
||||
local Util = require("classes.util.Util")
|
||||
local StageRepository = require("classes.stageClasses.StageRepository")
|
||||
|
||||
---@class DebugMenu
|
||||
|
||||
@@ -4,43 +4,37 @@ local MissionEditorWarning = require("classes.util.MissionEditorWarnings")
|
||||
local RouteUtil = require("classes.spearhead_routeutil")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
|
||||
---@class FleetGroup : OnStageChangedListener
|
||||
---@field private fleetGroupName string
|
||||
---@field private logger Logger
|
||||
---@field private fleetNameIdentifier string
|
||||
---@field private targetZonePerStage table<string, string>
|
||||
---@field private currentTargetZone string
|
||||
---@field private pointsPerZone table<string, {pointA: Vec2, pointB: Vec2}>
|
||||
---@class FleetGroup
|
||||
local FleetGroup = {}
|
||||
FleetGroup.__index = FleetGroup
|
||||
|
||||
---comment
|
||||
---@param fleetGroupName string
|
||||
---@param database Database
|
||||
---@param logger Logger
|
||||
---@return FleetGroup?
|
||||
function FleetGroup.new(fleetGroupName, database, logger)
|
||||
---@return nil
|
||||
function FleetGroup:new(fleetGroupName, database, logger)
|
||||
local o = {}
|
||||
|
||||
local self = setmetatable({}, FleetGroup)
|
||||
setmetatable(o, { __index = self })
|
||||
|
||||
self.fleetGroupName = fleetGroupName
|
||||
self.logger = logger
|
||||
o.fleetGroupName = fleetGroupName
|
||||
o.logger = logger
|
||||
|
||||
local split_name = Util.split_string(fleetGroupName, "_")
|
||||
if Util.tableLength(split_name) < 2 then
|
||||
MissionEditorWarning.Add("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>")
|
||||
return nil
|
||||
end
|
||||
self.fleetNameIdentifier = split_name[2]
|
||||
o.fleetNameIdentifier = split_name[2]
|
||||
|
||||
self.targetZonePerStage = {}
|
||||
self.currentTargetZone = nil
|
||||
self.pointsPerZone = {}
|
||||
o.targetZonePerStage = {}
|
||||
o.currentTargetZone = nil
|
||||
o.pointsPerZone = {}
|
||||
|
||||
do --INIT
|
||||
local carrierRouteZones = database:getCarrierRouteZones()
|
||||
for _, zoneName in pairs(carrierRouteZones) do
|
||||
if Util.strContains(string.lower(zoneName), "_".. string.lower(self.fleetNameIdentifier) .. "_" ) == true then
|
||||
if Util.strContains(string.lower(zoneName), "_".. string.lower(o.fleetNameIdentifier) .. "_" ) == true then
|
||||
local zone = DcsUtil.getZoneByName(zoneName)
|
||||
if zone and zone.zone_type == DcsUtil.ZoneType.Polygon then
|
||||
local split_string = Util.split_string(zoneName, "_")
|
||||
@@ -49,18 +43,18 @@ function FleetGroup.new(fleetGroupName, database, logger)
|
||||
"CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName)
|
||||
else
|
||||
|
||||
---@param zoneA SpearheadTriggerZone
|
||||
---@param zone SpearheadTriggerZone
|
||||
---@return Vec2, Vec2
|
||||
local function GetTwoFurthestPoints(zoneA)
|
||||
local function GetTwoFurthestPoints(zone)
|
||||
|
||||
local biggest = nil
|
||||
local biggestA = zoneA.verts[1]
|
||||
local biggestB = zoneA.verts[2]
|
||||
local biggestA = zone.verts[1]
|
||||
local biggestB = zone.verts[2]
|
||||
|
||||
for i = 1, 3 do
|
||||
for ii = i + 1, 4 do
|
||||
local a = zoneA.verts[i]
|
||||
local b = zoneA.verts[ii]
|
||||
local a = zone.verts[i]
|
||||
local b = zone.verts[ii]
|
||||
local dist = Util.VectorDistance2d(a, b)
|
||||
|
||||
if biggest == nil or dist > biggest then
|
||||
@@ -106,9 +100,9 @@ function FleetGroup.new(fleetGroupName, database, logger)
|
||||
local first, second = getMinMaxStage(split_string[3])
|
||||
if first ~= nil and second ~= nil then
|
||||
for i = first, second do
|
||||
self.targetZonePerStage[tostring(i)] = zoneName
|
||||
o.targetZonePerStage[tostring(i)] = zoneName
|
||||
end
|
||||
self.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} }
|
||||
o.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} }
|
||||
else
|
||||
MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
||||
end
|
||||
@@ -120,32 +114,32 @@ function FleetGroup.new(fleetGroupName, database, logger)
|
||||
end
|
||||
end
|
||||
|
||||
SpearheadEvents.AddStageNumberChangedListener(self)
|
||||
return self
|
||||
end
|
||||
local SetTaskAsync = function(input, time)
|
||||
local targetZone = input.targetZone
|
||||
local task = input.task
|
||||
local groupName = input.groupName
|
||||
local logger = input.logger
|
||||
|
||||
local SetTaskAsync = function(input, _)
|
||||
local targetZone = input.targetZone
|
||||
local task = input.task
|
||||
local groupName = input.groupName
|
||||
local l_logger = input.logger
|
||||
|
||||
local group = Group.getByName(groupName)
|
||||
if group then
|
||||
l_logger:info("Sending " .. groupName .. " to " .. targetZone)
|
||||
group:getController():setTask(task)
|
||||
local group = Group.getByName(groupName)
|
||||
if group then
|
||||
logger:info("Sending " .. groupName .. " to " .. targetZone)
|
||||
group:getController():setTask(task)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function FleetGroup:OnStageNumberChanged(number, laneIdentifier)
|
||||
-- only react on "main" lane changes, ignore other lanes for now
|
||||
if laneIdentifier ~= nil then return end
|
||||
local targetZone = self.targetZonePerStage[tostring(number)]
|
||||
if targetZone and targetZone ~= self.currentTargetZone then
|
||||
local points = self.pointsPerZone[targetZone]
|
||||
local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
|
||||
timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5)
|
||||
o.OnStageNumberChanged = function(self, number, laneIdentifier)
|
||||
-- only react on "main" lane changes, ignore other lanes for now
|
||||
if laneIdentifier ~= nil then return end
|
||||
local targetZone = self.targetZonePerStage[tostring(number)]
|
||||
if targetZone and targetZone ~= self.currentTargetZone then
|
||||
local points = self.pointsPerZone[targetZone]
|
||||
local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
|
||||
timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5)
|
||||
end
|
||||
end
|
||||
|
||||
SpearheadEvents.AddStageNumberChangedListener(o)
|
||||
return o
|
||||
end
|
||||
|
||||
return FleetGroup
|
||||
|
||||
@@ -17,7 +17,7 @@ GlobalFleetManager.start = function(database)
|
||||
for _, groupName in pairs(all_groups) do
|
||||
if Util.startswith(string.lower(groupName), "carriergroup" ) == true then
|
||||
logger:info("Registering " .. groupName .. " as a managed fleet")
|
||||
local carrierGroup = FleetGroup.new(groupName, database, logger)
|
||||
local carrierGroup = FleetGroup:new(groupName, database, logger)
|
||||
table.insert(fleetGroups, carrierGroup)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,13 +15,14 @@ MizGroupsManager._groupNames = {}
|
||||
MizGroupsManager._spawnTemplateData = {}
|
||||
|
||||
do --init
|
||||
for _, coalition_data in pairs(env.mission.coalition) do
|
||||
for coalition_name, coalition_data in pairs(env.mission.coalition) do
|
||||
local coalition_nr = DcsUtil.stringToCoalition(coalition_name)
|
||||
if coalition_data.country then
|
||||
for _, country_data in pairs(coalition_data.country) do
|
||||
for country_index, country_data in pairs(coalition_data.country) do
|
||||
for category_name, categorydata in pairs(country_data) do
|
||||
local category_id = DcsUtil.stringToGroupCategory(category_name)
|
||||
if category_id ~= nil and type(categorydata) == "table" and categorydata.group ~= nil and type(categorydata.group) == "table" then
|
||||
for _, group in pairs(categorydata.group) do
|
||||
for group_index, group in pairs(categorydata.group) do
|
||||
local name = group.name
|
||||
local skippable = false
|
||||
local isStatic = false
|
||||
|
||||
@@ -44,7 +44,7 @@ function SpawnManager:SpawnGroup(groupName, overrides, isGroupPersistant)
|
||||
if spawnData.isStatic == true then
|
||||
return self:SpawnStaticInternal(groupName, spawnData, overrides, isGroupPersistant), true
|
||||
else
|
||||
return self:SpawnGroupInternal(spawnData, overrides, isGroupPersistant), false
|
||||
return self:SpawnGroupInternal(groupName, spawnData, overrides, isGroupPersistant), false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -103,20 +103,20 @@ function SpawnManager:OnUnitLost(object)
|
||||
end
|
||||
end
|
||||
|
||||
---@param groupName string
|
||||
function SpawnManager:SpawnCorpsesOnly(groupName)
|
||||
if groupName == nil then return end
|
||||
|
||||
end
|
||||
|
||||
do --- privates
|
||||
|
||||
---@private
|
||||
---@param groupName string
|
||||
---@param spawnData SpawnData
|
||||
---@param override SpawnOverrides?
|
||||
---@param isPersistent boolean?
|
||||
---@return Group|nil
|
||||
function SpawnManager:SpawnGroupInternal(spawnData, override, isPersistent)
|
||||
function SpawnManager:SpawnGroupInternal(groupName, spawnData, override, isPersistent)
|
||||
|
||||
if not spawnData then return end
|
||||
|
||||
local country = spawnData.country
|
||||
@@ -181,6 +181,7 @@ do --- privates
|
||||
return group
|
||||
end
|
||||
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ do
|
||||
logger:info("Wrote persistence data to file")
|
||||
end
|
||||
|
||||
local UpdateContinuous = function(_, time)
|
||||
local UpdateContinuous = function(null, time)
|
||||
env.info("[Spearhead][Persistence] Checking up on persistence state...")
|
||||
if Persistence._updateRequired == true then
|
||||
local status, result = pcall(writeToFile)
|
||||
@@ -135,7 +135,7 @@ do
|
||||
end
|
||||
|
||||
|
||||
local warnForNonPersistenceContinous = function(_, time)
|
||||
local warnForNonPersistenceContinous = function(null, time)
|
||||
trigger.action.outText("Persistence was enabeld, however, io and lfs are not available and no persistence will be done. Make sure to either disable persistence or fix the issues before continuing.", 10)
|
||||
return time + 9
|
||||
end
|
||||
|
||||
@@ -121,7 +121,7 @@ function Database.New(Logger)
|
||||
self._logger:debug("Initiating tables")
|
||||
|
||||
do -- INIT ZONE TABLES
|
||||
for _, zone_data in pairs(DcsUtil.__trigger_zones) do
|
||||
for zone_ind, zone_data in pairs(DcsUtil.__trigger_zones) do
|
||||
local zone_name = zone_data.name
|
||||
|
||||
---@type Vec2
|
||||
@@ -208,9 +208,9 @@ function Database.New(Logger)
|
||||
self._logger:debug("initiated zone tables, continuing with descriptions")
|
||||
do --load markers
|
||||
if env.mission.drawings and env.mission.drawings.layers then
|
||||
for _, layer in pairs(env.mission.drawings.layers) do
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for _, layer_object in pairs(layer.objects) do
|
||||
for key, layer_object in pairs(layer.objects) do
|
||||
if Util.startswith(string.lower(layer_object.name), "buildable", true) == true then
|
||||
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
|
||||
if airbaseData then
|
||||
@@ -228,9 +228,9 @@ function Database.New(Logger)
|
||||
---@type table<integer, boolean>
|
||||
do -- custom drawings
|
||||
if env.mission.drawings and env.mission.drawings.layers then
|
||||
for _, layer in pairs(env.mission.drawings.layers) do
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for _, layer_object in pairs(layer.objects) do
|
||||
for key, layer_object in pairs(layer.objects) do
|
||||
if Util.startswith(layer_object.name, "drawing_", true) then
|
||||
local object = layer_object --[[@as DrawingObject]]
|
||||
local stageDrawing = StageDrawing.New(object)
|
||||
@@ -256,9 +256,9 @@ function Database.New(Logger)
|
||||
|
||||
-- Find and add Briefing
|
||||
if env.mission.drawings and env.mission.drawings.layers then
|
||||
for _, layer in pairs(env.mission.drawings.layers) do
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for _, layer_object in pairs(layer.objects) do
|
||||
for key, layer_object in pairs(layer.objects) do
|
||||
if Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
||||
local zone = DcsUtil.getZoneByName(stageZoneName)
|
||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||
@@ -339,14 +339,14 @@ function Database.New(Logger)
|
||||
end
|
||||
|
||||
-- fill missions
|
||||
for _, missionZone in pairs(self._tables.MissionZones) do
|
||||
for key, missionZone in pairs(self._tables.MissionZones) do
|
||||
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||
table.insert(stageData.MissionZones, missionZone)
|
||||
end
|
||||
end
|
||||
|
||||
-- fill random missions
|
||||
for _, missionZone in pairs(self._tables.RandomMissionZones) do
|
||||
for key, missionZone in pairs(self._tables.RandomMissionZones) do
|
||||
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||
table.insert(stageData.RandomMissionZones, missionZone)
|
||||
end
|
||||
@@ -620,9 +620,9 @@ function Database:loadBlueSamUnits()
|
||||
samData.buildingKilos = number
|
||||
|
||||
if env.mission.drawings and env.mission.drawings.layers then
|
||||
for _, layer in pairs(env.mission.drawings.layers) do
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for _, layer_object in pairs(layer.objects) do
|
||||
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
|
||||
@@ -720,9 +720,9 @@ function Database:LoadZoneData(missionZoneName)
|
||||
|
||||
---Adds Briefings
|
||||
if env.mission.drawings and env.mission.drawings.layers then
|
||||
for _, layer in pairs(env.mission.drawings.layers) do
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for _, layer_object in pairs(layer.objects) do
|
||||
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
|
||||
@@ -776,9 +776,9 @@ function Database:loadFarpData()
|
||||
|
||||
-- check briefings
|
||||
if env.mission.drawings and env.mission.drawings.layers then
|
||||
for _, layer in pairs(env.mission.drawings.layers) do
|
||||
for i, layer in pairs(env.mission.drawings.layers) do
|
||||
if string.lower(layer.name) == "author" then
|
||||
for _, layer_object in pairs(layer.objects) do
|
||||
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
|
||||
@@ -796,6 +796,8 @@ function Database:loadFarpData()
|
||||
else
|
||||
MissionEditorWarnings.Add("Buildable number for " .. farpZone .. " is invalid.")
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,7 +65,7 @@ do
|
||||
end)
|
||||
|
||||
for _, callable in pairs(OnStageNumberChangedListeners) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnStageNumberChanged(newStageNumber, laneIdentifier)
|
||||
end)
|
||||
if err then
|
||||
@@ -74,14 +74,14 @@ do
|
||||
end
|
||||
|
||||
for _, callable in pairs(OnStageNumberChangedHandlers) do
|
||||
local _, err = pcall(callable, newStageNumber, laneIdentifier)
|
||||
local succ, err = pcall(callable, newStageNumber, laneIdentifier)
|
||||
if err then
|
||||
logError(err)
|
||||
end
|
||||
end
|
||||
|
||||
for _, callable in pairs(OnStageNumberChangeCompleteListeners) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnStageNumberChangeComplete(newStageNumber, laneIdentifier)
|
||||
end)
|
||||
if err then
|
||||
@@ -112,7 +112,7 @@ do
|
||||
|
||||
local triggerWeaponFired = function(unit, weapon, target)
|
||||
for _, callable in pairs(onWeaponFiredListeners) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnWeaponFired(unit, weapon, target)
|
||||
end)
|
||||
|
||||
@@ -186,7 +186,7 @@ do
|
||||
if groupName ~= nil then
|
||||
if OnGroupRTBListeners[groupName] then
|
||||
for _, callable in pairs(OnGroupRTBListeners[groupName]) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnGroupRTB(groupName)
|
||||
end)
|
||||
if err then
|
||||
@@ -221,7 +221,7 @@ do
|
||||
if groupName ~= nil then
|
||||
if OnGroupRTBInTenListeners[groupName] then
|
||||
for _, callable in pairs(OnGroupRTBInTenListeners[groupName]) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnGroupRTBInTen(groupName)
|
||||
end)
|
||||
if err then
|
||||
@@ -257,7 +257,7 @@ do
|
||||
if groupName ~= nil then
|
||||
if OnGroupOnStationListeners[groupName] then
|
||||
for _, callable in pairs(OnGroupOnStationListeners[groupName]) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnGroupOnStation(groupName)
|
||||
end)
|
||||
if err then
|
||||
@@ -286,7 +286,7 @@ do
|
||||
if unit ~= nil then
|
||||
if playerEnterUnitListeners then
|
||||
for _, callable in pairs(playerEnterUnitListeners) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnPlayerEntersUnit(unit)
|
||||
end)
|
||||
if err then
|
||||
@@ -321,7 +321,7 @@ do
|
||||
local name = unit:getName()
|
||||
if onLandEventListeners[name] then
|
||||
for _, callable in pairs(onLandEventListeners[name]) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnUnitLanded(unit, airbase)
|
||||
end)
|
||||
if err then
|
||||
@@ -344,7 +344,7 @@ do
|
||||
|
||||
if object and object.getName and OnUnitLostListeners[object:getName()] then
|
||||
for _, callable in pairs(OnUnitLostListeners[object:getName()]) do
|
||||
local _, err = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
callable:OnUnitLost(object)
|
||||
end)
|
||||
|
||||
@@ -374,26 +374,26 @@ do
|
||||
|
||||
local AI_GROUPS = {}
|
||||
|
||||
local function CheckAndTriggerSpawnAsync(unit, _)
|
||||
local function CheckAndTriggerSpawnAsync(unit, time)
|
||||
|
||||
local function isPlayer(checkUnit)
|
||||
if checkUnit == nil then return false, "unit is nil" end
|
||||
if checkUnit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end
|
||||
if Object.getCategory(checkUnit) ~= Object.Category.UNIT then
|
||||
local function isPlayer(unit)
|
||||
if unit == nil then return false, "unit is nil" end
|
||||
if unit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end
|
||||
if Object.getCategory(unit) ~= Object.Category.UNIT then
|
||||
return false, "object is not a unit"
|
||||
end
|
||||
|
||||
if checkUnit:isExist() ~= true then return false, "unit does not exist" end
|
||||
local group = checkUnit:getGroup()
|
||||
if unit:isExist() ~= true then return false, "unit does not exist" end
|
||||
local group = unit:getGroup()
|
||||
if group ~= nil then
|
||||
if AI_GROUPS[group:getName()] == true then
|
||||
return false
|
||||
end
|
||||
|
||||
local players = DcsUtil.getAllPlayerUnits()
|
||||
local unitName = checkUnit:getName()
|
||||
for _, playerUnit in pairs(players) do
|
||||
if playerUnit:getName() == unitName then
|
||||
local unitName = unit:getName()
|
||||
for i, unit in pairs(players) do
|
||||
if unit:getName() == unitName then
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -403,6 +403,7 @@ do
|
||||
end
|
||||
|
||||
if isPlayer(unit) == true then
|
||||
local groupId = unit:getGroup():getID()
|
||||
SpearheadEvents.TriggerPlayerEntersUnit(unit)
|
||||
end
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ local Events = require("classes.spearhead_events")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local Logger = require("classes.util.Logger")
|
||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
||||
local PersistenceConfig = require("classes.configuration.PersistenceConfig")
|
||||
local ExtraStage = require("classes.stageClasses.Stages.ExtraStage")
|
||||
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
|
||||
@@ -34,6 +35,7 @@ local singletonInstance = nil
|
||||
---@param spawnManager SpawnManager
|
||||
---@return GlobalStageManager
|
||||
function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
||||
|
||||
if singletonInstance ~= nil then
|
||||
return singletonInstance
|
||||
end
|
||||
@@ -50,8 +52,7 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
||||
|
||||
self.logger = logger
|
||||
if stageConfig.isAutoStages ~= true then
|
||||
logger:warn(
|
||||
"Spearhead will not automatically progress stages due to the given settings. If you manually have implemented this, please ignore this message")
|
||||
logger:warn("Spearhead will not automatically progress stages due to the given settings. If you manually have implemented this, please ignore this message")
|
||||
end
|
||||
|
||||
Events.AddStageNumberChangedListener(self)
|
||||
@@ -80,12 +81,12 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
||||
stage:AddStageCompleteListener(self)
|
||||
self._stageRepository:AddStage(stage)
|
||||
elseif parseResult.stageType == "WaitingStage" then
|
||||
local waitingStage = WaitingStage.New(database, stageConfig, logger, initData,
|
||||
parseResult.waitingStageSeconds, spawnManager)
|
||||
local waitingStage = WaitingStage.New(database, stageConfig, logger, initData, parseResult.waitingStageSeconds, spawnManager)
|
||||
waitingStage:AddStageCompleteListener(self)
|
||||
self._stageRepository:AddStage(waitingStage)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
singletonInstance = self
|
||||
@@ -102,11 +103,11 @@ function GlobalStageManager:Start()
|
||||
|
||||
local stageLanes = self._stageRepository:getAllStageLanes()
|
||||
for _, stageLane in pairs(stageLanes) do
|
||||
|
||||
local stageLaneIdentifier = stageLane:GetStageLaneIdentifier()
|
||||
local persistedStage = Persistence.GetActiveStage(stageLaneIdentifier)
|
||||
if persistedStage then
|
||||
self.logger:info("Loaded persisted stage " ..
|
||||
persistedStage .. " for lane " .. (stageLaneIdentifier or "default"))
|
||||
self.logger:info("Loaded persisted stage " .. persistedStage .. " for lane " .. (stageLaneIdentifier or "default"))
|
||||
stageLane:SetActiveStageIndex(persistedStage)
|
||||
Events.PublishStageNumberChanged(persistedStage, stageLaneIdentifier)
|
||||
else
|
||||
@@ -138,16 +139,17 @@ end
|
||||
---@param stageName string
|
||||
---@return StageNameParseResult
|
||||
function GlobalStageManager:ParseStageName(stageName)
|
||||
|
||||
local split = Util.split_string(stageName, "_")
|
||||
|
||||
if Util.tableLength(split) < 3 then
|
||||
return { isValid = false, invalidReason = "Stage zone with name " ..
|
||||
stageName .. " does not have a order number or valid format" }
|
||||
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " does not have a order number or valid format" }
|
||||
end
|
||||
|
||||
local typePart = string.lower(split[1])
|
||||
|
||||
if typePart == "missionstage" then
|
||||
|
||||
local orderNumberString = string.lower(split[2])
|
||||
---@type StageType
|
||||
local stageType = "PrimaryStage"
|
||||
@@ -165,8 +167,7 @@ function GlobalStageManager:ParseStageName(stageName)
|
||||
|
||||
local orderNumber = tonumber(orderNumberString)
|
||||
if orderNumber == nil then
|
||||
return { isValid = false, invalidReason = "Stage zone with name " ..
|
||||
stageName .. " does not have a valid order number : " .. orderNumberString }
|
||||
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " does not have a valid order number : " .. orderNumberString }
|
||||
end
|
||||
|
||||
local stageDisplayName = split[3]
|
||||
@@ -181,19 +182,18 @@ function GlobalStageManager:ParseStageName(stageName)
|
||||
}
|
||||
return result
|
||||
elseif typePart == "waitingstage" then
|
||||
|
||||
local stageType = "WaitingStage"
|
||||
local orderNumberString = split[2]
|
||||
local orderNumber = tonumber(orderNumberString)
|
||||
if orderNumber == nil then
|
||||
return { isValid = false, invalidReason = "Waiting Stage zone with name " ..
|
||||
stageName .. " does not have a valid order number : " .. orderNumberString }
|
||||
return { isValid = false, invalidReason = "Waiting Stage zone with name " .. stageName .. " does not have a valid order number : " .. orderNumberString }
|
||||
end
|
||||
|
||||
local waitingSecondsString = split[3]
|
||||
local waitingSeconds = tonumber(waitingSecondsString)
|
||||
if waitingSeconds == nil then
|
||||
return { isValid = false, invalidReason = "Waiting Stage zone with name " ..
|
||||
stageName .. " does not have a valid amount of seconds parameter : " .. waitingSecondsString }
|
||||
return { isValid = false, invalidReason = "Waiting Stage zone with name " .. stageName .. " does not have a valid amount of seconds parameter : " .. waitingSecondsString }
|
||||
end
|
||||
|
||||
local stageDisplayName = "Waiting Stage " .. orderNumber
|
||||
@@ -209,9 +209,9 @@ function GlobalStageManager:ParseStageName(stageName)
|
||||
waitingStageSeconds = waitingSeconds
|
||||
}
|
||||
return result
|
||||
|
||||
end
|
||||
return { isValid = false, invalidReason = "Stage zone with name " ..
|
||||
stageName .. " has an unrecognized type: " .. typePart }
|
||||
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " has an unrecognized type: " .. typePart }
|
||||
end
|
||||
|
||||
---@param stage Stage
|
||||
@@ -223,8 +223,7 @@ function GlobalStageManager:OnStageComplete(stage)
|
||||
|
||||
local stageLane = self._stageRepository:getStageLane(laneIdentifier)
|
||||
if not stageLane or not stageLane:IsCurrentStageIndexComplete() then
|
||||
self.logger:debug("Stage lane " ..
|
||||
(laneIdentifier or "default") .. " is not complete for stage index " .. stageIndex)
|
||||
self.logger:debug("Stage lane " .. (laneIdentifier or "default") .. " is not complete for stage index " .. stageIndex)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -243,9 +242,7 @@ function GlobalStageManager:OnStageComplete(stage)
|
||||
if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey and lane:GetStageLaneState() == "BetweenChapters" then
|
||||
local nextChapterStart = lane:GetNextChapterStart()
|
||||
if nextChapterStart == nextStageIndex then
|
||||
self.logger:debug("Lane " ..
|
||||
(lane:GetStageLaneIdentifier() or "default") ..
|
||||
" is at chapter start for next stage index " .. nextStageIndex)
|
||||
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is at chapter start for next stage index " .. nextStageIndex)
|
||||
Events.PublishStageNumberChanged(nextStageIndex, lane:GetStageLaneIdentifier())
|
||||
lane:SetActiveStageIndex(nextStageIndex)
|
||||
end
|
||||
@@ -259,6 +256,7 @@ function GlobalStageManager:OnStageComplete(stage)
|
||||
if defaultStageLane and defaultStageLane:GetStageLaneState() == "BetweenChapters" then
|
||||
local nextChapterStart = defaultStageLane:GetNextChapterStart()
|
||||
if nextChapterStart == nextStageIndex then
|
||||
|
||||
-- 2. Check if all side lanes are at or beyond the next chapter starts
|
||||
local allLanes = self._stageRepository:getAllStageLanes()
|
||||
local allSideLanesReady = true
|
||||
@@ -267,19 +265,15 @@ function GlobalStageManager:OnStageComplete(stage)
|
||||
-- Check if the lane is at or beyond the next chapter starts when "InChapter" eq "Active"
|
||||
if lane:GetStageLaneState() == "InChapter" and lane:GetActiveStageIndex() < nextStageIndex then
|
||||
allSideLanesReady = false
|
||||
self.logger:debug("Lane " ..
|
||||
(lane:GetStageLaneIdentifier() or "default") ..
|
||||
" is not ready for next stage index " .. nextStageIndex)
|
||||
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is not ready for next stage index " .. nextStageIndex)
|
||||
break
|
||||
|
||||
-- When in between chapters, check if the next chapter start is less than the next stage index, meaning there is still stages to be completed before the main lane can be activated again
|
||||
-- When in between chapters, check if the next chapter start is less than the next stage index, meaning there is still stages to be completed before the main lane can be activated again
|
||||
elseif lane:GetStageLaneState() == "BetweenChapters" then
|
||||
local nextChapter = lane:GetNextChapterStart()
|
||||
if nextChapter and nextChapter < nextStageIndex then
|
||||
allSideLanesReady = false
|
||||
self.logger:debug("Lane " ..
|
||||
(lane:GetStageLaneIdentifier() or "default") ..
|
||||
" is not ready for next stage index " .. nextStageIndex)
|
||||
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is not ready for next stage index " .. nextStageIndex)
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -287,14 +281,13 @@ function GlobalStageManager:OnStageComplete(stage)
|
||||
end
|
||||
|
||||
if allSideLanesReady then
|
||||
self.logger:debug("All side lanes are ready for next stage index " ..
|
||||
nextStageIndex .. ", activating default lane")
|
||||
self.logger:debug("All side lanes are ready for next stage index " .. nextStageIndex .. ", activating default lane")
|
||||
Events.PublishStageNumberChanged(nextStageIndex, nil)
|
||||
defaultStageLane:SetActiveStageIndex(nextStageIndex)
|
||||
else
|
||||
self.logger:debug("Not all side lanes are ready for next stage index " ..
|
||||
nextStageIndex .. ", default lane will not be activated")
|
||||
self.logger:debug("Not all side lanes are ready for next stage index " .. nextStageIndex .. ", default lane will not be activated")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -315,6 +308,7 @@ end
|
||||
|
||||
---@public
|
||||
function GlobalStageManager:OnStageNumberChanged(stageNumber, stageLaneIdentifier)
|
||||
|
||||
-- only react on "main" lane changes, ignore other lanes for now
|
||||
if stageLaneIdentifier ~= nil then return end
|
||||
|
||||
@@ -327,6 +321,7 @@ function GlobalStageManager:OnStageNumberChangeComplete(stageNumber, stageLaneId
|
||||
if stageLaneIdentifier ~= nil then return end
|
||||
|
||||
self.logger:debug("Stage number change complete to: " .. tostring(stageNumber))
|
||||
|
||||
local groups = {}
|
||||
|
||||
for _, player in pairs(DcsUtil.getAllPlayerUnits()) do
|
||||
@@ -354,18 +349,17 @@ function GlobalStageManager:UpdateDrawings(stageNumber, stageLaneIdentifier)
|
||||
|
||||
if laneIdentifier == stageLaneIdentifier then
|
||||
if stageNumber >= startStage and stageNumber < stopStage then
|
||||
self.logger:debug("Drawing " ..
|
||||
drawing:GetName() .. " is active for stage number: " .. tostring(stageNumber))
|
||||
self.logger:debug("Drawing " .. drawing:GetName() .. " is active for stage number: " .. tostring(stageNumber))
|
||||
drawing:Draw()
|
||||
else
|
||||
self.logger:debug("Drawing " ..
|
||||
drawing:GetName() .. " is not active for stage number: " .. tostring(stageNumber))
|
||||
self.logger:debug("Drawing " .. drawing:GetName() .. " is not active for stage number: " .. tostring(stageNumber))
|
||||
drawing:Remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function GlobalStageManager:PrintMermaidStage()
|
||||
local lanes = self._stageRepository:getAllStageLanes()
|
||||
|
||||
@@ -376,32 +370,32 @@ function GlobalStageManager:PrintMermaidStage()
|
||||
|
||||
-- Color palette for lanes (26 vibrant colors optimized for dark mode)
|
||||
local laneColors = {
|
||||
"#FF6B6B", -- 1: Red
|
||||
"#4ECDC4", -- 2: Teal
|
||||
"#45B7D1", -- 3: Blue
|
||||
"#FFA502", -- 4: Orange
|
||||
"#95E1D3", -- 5: Mint
|
||||
"#F38181", -- 6: Coral
|
||||
"#AA96DA", -- 7: Purple
|
||||
"#FCBAD3", -- 8: Pink
|
||||
"#A8E6CF", -- 9: Light green
|
||||
"#FFD3B6", -- 10: Peach
|
||||
"#FFAAA5", -- 11: Light red
|
||||
"#FF8B94", -- 12: Rose
|
||||
"#FFEAA7", -- 13: Butter
|
||||
"#DFE6E9", -- 14: Gray
|
||||
"#00B894", -- 15: Emerald
|
||||
"#0984E3", -- 16: Cobalt
|
||||
"#6C5CE7", -- 17: Indigo
|
||||
"#A29BFE", -- 18: Lavender
|
||||
"#FD79A8", -- 19: Magenta
|
||||
"#FDCB6E", -- 20: Gold
|
||||
"#6C757D", -- 21: Slate
|
||||
"#20C997", -- 22: Seafoam
|
||||
"#E74C3C", -- 23: Scarlet
|
||||
"#3498DB", -- 24: Dodger blue
|
||||
"#9B59B6", -- 25: Amethyst
|
||||
"#1ABC9C", -- 26: Turquoise
|
||||
"#FF6B6B", -- 1: Red
|
||||
"#4ECDC4", -- 2: Teal
|
||||
"#45B7D1", -- 3: Blue
|
||||
"#FFA502", -- 4: Orange
|
||||
"#95E1D3", -- 5: Mint
|
||||
"#F38181", -- 6: Coral
|
||||
"#AA96DA", -- 7: Purple
|
||||
"#FCBAD3", -- 8: Pink
|
||||
"#A8E6CF", -- 9: Light green
|
||||
"#FFD3B6", -- 10: Peach
|
||||
"#FFAAA5", -- 11: Light red
|
||||
"#FF8B94", -- 12: Rose
|
||||
"#FFEAA7", -- 13: Butter
|
||||
"#DFE6E9", -- 14: Gray
|
||||
"#00B894", -- 15: Emerald
|
||||
"#0984E3", -- 16: Cobalt
|
||||
"#6C5CE7", -- 17: Indigo
|
||||
"#A29BFE", -- 18: Lavender
|
||||
"#FD79A8", -- 19: Magenta
|
||||
"#FDCB6E", -- 20: Gold
|
||||
"#6C757D", -- 21: Slate
|
||||
"#20C997", -- 22: Seafoam
|
||||
"#E74C3C", -- 23: Scarlet
|
||||
"#3498DB", -- 24: Dodger blue
|
||||
"#9B59B6", -- 25: Amethyst
|
||||
"#1ABC9C", -- 26: Turquoise
|
||||
}
|
||||
local laneColorMap = {} -- Map lane ID to color
|
||||
local colorIndex = 1
|
||||
@@ -558,12 +552,11 @@ function GlobalStageManager:PrintMermaidStage()
|
||||
end
|
||||
|
||||
-- Build complete Mermaid diagram
|
||||
local diagramLines = { "graph TD" }
|
||||
local diagramLines = {"graph TD"}
|
||||
|
||||
-- Add class definitions for each lane with colors and contrasting text
|
||||
for laneId, color in pairs(laneColorMap) do
|
||||
table.insert(diagramLines,
|
||||
string.format(' classDef lane_%s fill:%s,stroke:#333,stroke-width:2px,color:#000', laneId, color))
|
||||
table.insert(diagramLines, string.format(' classDef lane_%s fill:%s,stroke:#333,stroke-width:2px,color:#000', laneId, color))
|
||||
end
|
||||
|
||||
-- Add nodes
|
||||
@@ -585,8 +578,7 @@ function GlobalStageManager:PrintMermaidStage()
|
||||
end
|
||||
|
||||
-- Print as single multi-line message
|
||||
local diagram = "========== STAGE FLOW DIAGRAM ==========\n" ..
|
||||
table.concat(diagramLines, "\n") .. "\n========== END DIAGRAM =========="
|
||||
local diagram = "========== STAGE FLOW DIAGRAM ==========\n" .. table.concat(diagramLines, "\n") .. "\n========== END DIAGRAM =========="
|
||||
self.logger:info(diagram)
|
||||
end
|
||||
|
||||
@@ -594,10 +586,10 @@ end
|
||||
---@param stageNumber number
|
||||
---@param stageLaneIdentifier string? nil for default lan
|
||||
---@return boolean | nil
|
||||
GlobalStageManager.isStageComplete = function(stageNumber, stageLaneIdentifier)
|
||||
GlobalStageManager.isStageComplete = function (stageNumber, stageLaneIdentifier)
|
||||
|
||||
if singletonInstance == nil then
|
||||
Logger.new("StageManager", "INFO"):warn(
|
||||
"GlobalStageManager.isStageComplete called before GlobalStageManager was initialized. Returning nil")
|
||||
Logger.new("StageManager", "INFO"):warn("GlobalStageManager.isStageComplete called before GlobalStageManager was initialized. Returning nil")
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ function SpearheadGroup:Spawn(lateStart)
|
||||
uncontrolled = lateStart,
|
||||
}
|
||||
|
||||
local _, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
|
||||
local spawnedObject, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
|
||||
self._isStatic = isStatic
|
||||
self._isSpawned = true
|
||||
end
|
||||
|
||||
@@ -50,6 +50,12 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
|
||||
---@type table<string, Vec3>
|
||||
local redUnitsPos = {}
|
||||
|
||||
|
||||
local buildable = false
|
||||
if self._buildableCrateKilos and self._buildableCrateKilos > 0 then
|
||||
buildable = true
|
||||
end
|
||||
|
||||
for _, groupName in pairs(blueSamData.groups) do
|
||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||
if spearheadGroup then
|
||||
@@ -72,7 +78,7 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
|
||||
|
||||
--Cleanup units
|
||||
local cleanup_distance = 5
|
||||
for _, blueUnitPos in pairs(blueUnitsPos) do
|
||||
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do
|
||||
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
||||
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||
if distance <= cleanup_distance then
|
||||
@@ -134,9 +140,7 @@ end
|
||||
|
||||
function BlueSam:SpawnGroups()
|
||||
for unitName, needsCleanup in pairs(self._cleanupUnits) do
|
||||
if needsCleanup then
|
||||
DcsUtil.DestroyUnit(unitName)
|
||||
end
|
||||
DcsUtil.DestroyUnit(unitName)
|
||||
end
|
||||
|
||||
for _, group in pairs(self._blueGroups) do
|
||||
|
||||
@@ -90,7 +90,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
||||
|
||||
local cleanup_distance = 5
|
||||
|
||||
for _, blueUnitPos in pairs(blueUnitsPos) do
|
||||
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do
|
||||
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
||||
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||
if distance <= cleanup_distance then
|
||||
|
||||
@@ -76,6 +76,8 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
|
||||
self._buildableMission = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
if self._buildableMission == nil then
|
||||
self._buildableLogger:debug("No buildable mission for zone: " .. targetZone.name)
|
||||
end
|
||||
@@ -97,11 +99,23 @@ function BuildableZone:OnBuildingComplete() end
|
||||
---@field unpackedItems number
|
||||
---@field unpackedKilos number
|
||||
|
||||
---@param _ BuildableMission?
|
||||
---@param mission BuildableMission?
|
||||
---@param kilos number
|
||||
function BuildableZone:OnCrateDroppedOff(_, kilos)
|
||||
function BuildableZone:OnCrateDroppedOff(mission, kilos)
|
||||
self._buildableLogger:debug("Crate dropped off in zone: " .. self._targetZone.name)
|
||||
|
||||
local timeToUnpack = (kilos / 500) * 15
|
||||
|
||||
---@type UnpackCrateParam
|
||||
local params = {
|
||||
self = self,
|
||||
groupsPerKilo = self._groupsPerKilo,
|
||||
unpackedItems = 0,
|
||||
kilosPerSecond = kilos/timeToUnpack,
|
||||
unpackedKilos = 0,
|
||||
kilos = kilos
|
||||
}
|
||||
|
||||
---@param params UnpackCrateParam
|
||||
---@param time number
|
||||
local startUnpackingCrate = function(params, time)
|
||||
@@ -122,17 +136,6 @@ function BuildableZone:OnCrateDroppedOff(_, kilos)
|
||||
return time + 2
|
||||
end
|
||||
|
||||
local timeToUnpack = (kilos / 500) * 15
|
||||
---@type UnpackCrateParam
|
||||
local params = {
|
||||
self = self,
|
||||
groupsPerKilo = self._groupsPerKilo,
|
||||
unpackedItems = 0,
|
||||
kilosPerSecond = kilos/timeToUnpack,
|
||||
unpackedKilos = 0,
|
||||
kilos = kilos
|
||||
}
|
||||
|
||||
timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 2)
|
||||
end
|
||||
|
||||
@@ -187,7 +190,7 @@ function BuildableZone:SpawnAmount(amount)
|
||||
return nil
|
||||
end
|
||||
|
||||
for _ = 1, amount do
|
||||
for i = 1, amount do
|
||||
local spawned = spawnOne()
|
||||
if spawned ~= true then
|
||||
self._buildableLogger:debug("No more groups to spawn in zone: " .. self._targetZone.name)
|
||||
|
||||
@@ -49,6 +49,7 @@ end
|
||||
function StageRepository:AddStage(stage)
|
||||
|
||||
local stageLaneIdentifier = stage:GetStageLaneIdentifier() or StageLane.DefaultLaneKey
|
||||
|
||||
if self.StageLanes[tostring(stageLaneIdentifier)] == nil then
|
||||
self.StageLanes[tostring(stageLaneIdentifier)] = StageLane.New(stageLaneIdentifier)
|
||||
end
|
||||
|
||||
@@ -160,13 +160,13 @@ function Stage:superNew(database, stageConfig, logger, initData, stageType, miss
|
||||
self._logger:info("Initiating new Stage with name: " .. self.zoneName)
|
||||
|
||||
---comment
|
||||
---@param selfA Stage
|
||||
---@param self Stage
|
||||
---@param time number?
|
||||
self.CheckContinuousAsync = function (selfA, time)
|
||||
self.CheckContinuousAsync = function (self, time)
|
||||
|
||||
selfA:CheckAndUpdateSelf()
|
||||
if selfA:IsComplete() == true then
|
||||
selfA:NotifyComplete()
|
||||
self:CheckAndUpdateSelf()
|
||||
if self:IsComplete() == true then
|
||||
self:NotifyComplete()
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -284,14 +284,14 @@ end
|
||||
function Stage:IsComplete()
|
||||
if self._currentStageState >= StageState.Blue then return true end
|
||||
|
||||
for _, mission in pairs(self._db.sams) do
|
||||
for i, mission in pairs(self._db.sams) do
|
||||
local state = mission:getState()
|
||||
if state == "ACTIVE" or state == "NEW" or state =="WAITING" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
for _, mission in pairs(self._db.missions) do
|
||||
for i, mission in pairs(self._db.missions) do
|
||||
local state = mission:getState()
|
||||
if state == "ACTIVE" or state == "NEW" then
|
||||
return false
|
||||
@@ -370,9 +370,9 @@ function Stage:CheckAndUpdateSelf()
|
||||
local availableMissionsCount = Util.tableLength(getAvailableMissions())
|
||||
local activeCount = getActiveMissionsCount()
|
||||
if activeCount < max and availableMissionsCount > 0 then
|
||||
for _ = activeCount+1, max do
|
||||
for i = activeCount+1, max do
|
||||
if availableMissionsCount == 0 then
|
||||
break
|
||||
i = max+1 --exits this loop
|
||||
else
|
||||
local mission = Util.randomFromList(getAvailableMissions()) --[[@as Mission]]
|
||||
if mission then
|
||||
@@ -426,7 +426,7 @@ function Stage:PreActivate()
|
||||
end
|
||||
|
||||
self._currentStageState = StageState.PreActivated
|
||||
for _, mission in pairs(self._db.sams) do
|
||||
for key, mission in pairs(self._db.sams) do
|
||||
if mission then
|
||||
mission:SpawnInactive()
|
||||
end
|
||||
@@ -589,8 +589,8 @@ function Stage:OnStageNumberChanged(number, stageLaneIdentifier)
|
||||
end
|
||||
|
||||
---@param self Stage
|
||||
---@param _ Mission
|
||||
Stage.OnMissionComplete = function(self, _)
|
||||
---@param mission Mission
|
||||
Stage.OnMissionComplete = function(self, mission)
|
||||
self:CheckAndUpdateSelf()
|
||||
end
|
||||
|
||||
@@ -645,7 +645,7 @@ function Stage:GetStageStats()
|
||||
end
|
||||
end
|
||||
|
||||
for _, _ in pairs(self._db.sams) do
|
||||
for _, mission in pairs(self._db.sams) do
|
||||
dead = dead + 1
|
||||
end
|
||||
|
||||
@@ -673,13 +673,13 @@ function Stage:ActivateBlueStage()
|
||||
miscGroup:Spawn()
|
||||
end
|
||||
|
||||
---@param selfA Stage
|
||||
local ActivateBlueAsync = function(selfA)
|
||||
---@param self Stage
|
||||
local ActivateBlueAsync = function(self)
|
||||
pcall(function()
|
||||
selfA:MarkStage()
|
||||
self:MarkStage()
|
||||
end)
|
||||
|
||||
selfA:ActivateBlueGroups()
|
||||
self:ActivateBlueGroups()
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
||||
local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
|
||||
local StageState = require("classes.stageClasses.Stages.BaseStage.StageState")
|
||||
|
||||
---@class ExtraStage : Stage
|
||||
local ExtraStage = {}
|
||||
@@ -23,6 +22,7 @@ function ExtraStage.New(database, stageConfig, logger, initData, spawnManager)
|
||||
self:superNew(database, stageConfig, logger, initData, "ExtraStage", "secondary", spawnManager)
|
||||
|
||||
self.OnPostBlueActivated = function (selfStage)
|
||||
|
||||
selfStage:MarkStage()
|
||||
end
|
||||
|
||||
@@ -47,6 +47,7 @@ function ExtraStage:OnStageNumberChanged(number, stageLaneIdentifier)
|
||||
return
|
||||
end
|
||||
|
||||
local previousActive = self._activeStage
|
||||
self._activeStage = number
|
||||
|
||||
if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then
|
||||
@@ -60,7 +61,7 @@ function ExtraStage:OnStageNumberChanged(number, stageLaneIdentifier)
|
||||
self:ActivateStage()
|
||||
end
|
||||
|
||||
if self._currentStageState == StageState.Blue then
|
||||
if self._currentStageState == Stage.CurrentStageState.BLUE then
|
||||
self:ActivateBlueStage()
|
||||
end
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ function WaitingStage:OnStageNumberChanged()
|
||||
self._logger:debug("Waiting Stage OnStageNumberChanged override")
|
||||
end
|
||||
|
||||
function WaitingStage:MarkStage(_)
|
||||
function WaitingStage:MarkStage(stageColor)
|
||||
self._logger:debug("Waiting Stage MarkStage override")
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
||||
local Util = require("classes.util.Util")
|
||||
local Logger = require("classes.util.Logger")
|
||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
||||
local drawingLogger = Logger.new("CustomDrawing")
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local Logger = require("classes.util.Logger")
|
||||
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local Logger = require("classes.util.Logger")
|
||||
local Util = require("classes.util.Util")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
|
||||
---@class BattleManager
|
||||
---@field private _name string
|
||||
@@ -12,6 +13,8 @@ local Util = require("classes.util.Util")
|
||||
local BattleManager = {}
|
||||
BattleManager.__index = BattleManager
|
||||
|
||||
local debugDrawing = false
|
||||
|
||||
---@param redGroups Array<SpearheadGroup>
|
||||
---@param blueGroups Array<SpearheadGroup>
|
||||
---@param name string
|
||||
@@ -87,6 +90,8 @@ function BattleManager:Update()
|
||||
|
||||
self._logger:debug("BattleManager Update called for " .. self._name)
|
||||
|
||||
local shootChance = 1 -- Adjust this value to control the shooting probability (0.0 to 1.0)
|
||||
|
||||
self:LetUnitsShoot(self._redGroups, self._blueGroups)
|
||||
self:LetUnitsShoot(self._blueGroups, self._redGroups)
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ local function sortMissions(list, groupPos)
|
||||
end)
|
||||
end
|
||||
|
||||
local id = 0
|
||||
|
||||
local instance = nil
|
||||
|
||||
---@return MissionCommandsHelper
|
||||
@@ -55,16 +57,16 @@ function MissionCommandsHelper.getOrCreate()
|
||||
|
||||
instance._supplyUnitsTracker:AddOnSupplyUnitEventListener(
|
||||
{
|
||||
enteredSupplyHub = function(_, unit)
|
||||
enteredSupplyHub = function(self, unit)
|
||||
if unit == nil then return end
|
||||
instance.updateNeeded = true
|
||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||
end,
|
||||
exitedSupplyHub = function(_, unit)
|
||||
exitedSupplyHub = function(self, unit)
|
||||
instance.updateNeeded = true
|
||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||
end,
|
||||
supplyUnitSpawned = function(_, unit)
|
||||
supplyUnitSpawned = function(self, unit)
|
||||
instance.updateNeeded = true
|
||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||
end
|
||||
@@ -507,6 +509,7 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
|
||||
local unloadCargoCommand = function(params)
|
||||
local unitID = params.unitID
|
||||
local crateType = params.crateType
|
||||
local supplyUnitsTracker = params.supplyUnitsTracker
|
||||
params.supplyUnitsTracker:UnloadRequested(unitID, crateType, params.commandHelper)
|
||||
end
|
||||
|
||||
@@ -515,7 +518,7 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
|
||||
for cargoType, amount in pairs(cargo) do
|
||||
local cargoConfig = SupplyConfigHelper.getSupplyConfig(cargoType)
|
||||
if cargoConfig then
|
||||
for _ = 1, amount do
|
||||
for i = 1, amount do
|
||||
local path = { [1] = folderNames.cargo }
|
||||
---@type UnloadCargoCommandParams
|
||||
local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self
|
||||
|
||||
@@ -185,7 +185,7 @@ function SupplyUnitsTracker:RemoveCargoFromUnit(unitID, crateType)
|
||||
self._cargoInUnits[unitIDStr][crateType] = self._cargoInUnits[unitIDStr][crateType] - 1
|
||||
|
||||
local hasCargo = false
|
||||
for _, count in pairs(self._cargoInUnits[unitIDStr]) do
|
||||
for type, count in pairs(self._cargoInUnits[unitIDStr]) do
|
||||
if count > 0 then
|
||||
hasCargo = true
|
||||
break
|
||||
@@ -216,11 +216,13 @@ end
|
||||
|
||||
function SupplyUnitsTracker:CheckUnitsInZones()
|
||||
|
||||
for _, unit in pairs(self._supplyUnitsByName) do
|
||||
for name, unit in pairs(self._supplyUnitsByName) do
|
||||
if unit ~= nil and unit:isExist() == true then
|
||||
self._logger:debug("Checking unit: " .. unit:getName())
|
||||
local pos = unit:getPoint()
|
||||
|
||||
local group = unit:getGroup()
|
||||
|
||||
for hub, enabled in pairs(self._registeredHubs) do
|
||||
if enabled == true then
|
||||
local zone = hub:GetZone()
|
||||
@@ -612,7 +614,7 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
||||
}
|
||||
|
||||
local occupiedObjects = {}
|
||||
local found = function(foundItem, _)
|
||||
local found = function(foundItem, val)
|
||||
local bbox = self:GetBoundingBoxes(foundItem)
|
||||
if bbox then
|
||||
self._logger:debug("Found object: " .. foundItem:getTypeName() .. " at (" .. foundItem:getPoint().x .. ", " .. foundItem:getPoint().z .. ")")
|
||||
|
||||
@@ -25,7 +25,7 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe
|
||||
local BuildableMission = {}
|
||||
BuildableMission.__index = BuildableMission
|
||||
|
||||
---@return string
|
||||
|
||||
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." ..
|
||||
@@ -83,6 +83,13 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
|
||||
self.name = "Resupply"
|
||||
end
|
||||
|
||||
local type = "site"
|
||||
if requiredCrateType == "SAM_CRATE" then
|
||||
type = "SAM site"
|
||||
elseif requiredCrateType == "FARP_CRATE" then
|
||||
type = "FARP"
|
||||
end
|
||||
|
||||
self.zoneName = targetZone.name .. "_supply"
|
||||
self._logger = logger
|
||||
self._onCrateDroppedOfListeners = {}
|
||||
|
||||
@@ -84,6 +84,7 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
|
||||
|
||||
self._logger:debug("Runway hit: " .. self._airportName .. ":" .. self._runway.Name)
|
||||
for _, section in pairs(self._runwaySections) do
|
||||
|
||||
local zone = self:SectionToSpearheadZone(section)
|
||||
if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
||||
if section.kilosHit == nil then
|
||||
@@ -95,7 +96,7 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
|
||||
end
|
||||
|
||||
---@param selfA RunwayStrikeMission
|
||||
local updateState = function(selfA, _)
|
||||
local updateState = function(selfA, time)
|
||||
selfA:UpdateState()
|
||||
end
|
||||
|
||||
@@ -212,6 +213,7 @@ function RunwayStrikeMission:StartRepair()
|
||||
if interval == nil then return nil end
|
||||
return time + interval
|
||||
end
|
||||
|
||||
timer.scheduleFunction(repairTask, self, timer.getTime() + 5)
|
||||
end
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ end
|
||||
---@return boolean
|
||||
function ZoneMission:AllDependenciesMet()
|
||||
local allDependenciesMet = true
|
||||
for missionName, _ in pairs(self._dependencies) do
|
||||
for missionName, value in pairs(self._dependencies) do
|
||||
if self._parentStage:IsMissionComplete(missionName) == false then
|
||||
allDependenciesMet = false
|
||||
self._dependencies[missionName] = false
|
||||
|
||||
@@ -70,7 +70,6 @@ function Mission:SpawnActive() end
|
||||
---comment
|
||||
---@param checkHealth boolean
|
||||
---@param messageIfDone boolean
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
function Mission:UpdateState(checkHealth, messageIfDone) end
|
||||
function Mission:StartCheckingContinuous() end
|
||||
|
||||
@@ -121,7 +120,7 @@ function Mission:NotifyMissionComplete()
|
||||
end)
|
||||
end
|
||||
|
||||
local _, _ = pcall(function()
|
||||
local succ, err = pcall(function()
|
||||
SpearheadAPI.Internal.notifyMissionComplete(self.zoneName)
|
||||
end)
|
||||
|
||||
@@ -132,8 +131,6 @@ function Mission:ForceMissionComplete()
|
||||
self:NotifyMissionComplete()
|
||||
end
|
||||
|
||||
---@param groupId number
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
function Mission:MarkMissionAreaToGroup(groupId) end
|
||||
|
||||
---endregion
|
||||
|
||||
@@ -77,7 +77,7 @@ do -- INIT DCS_UTIL
|
||||
do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment
|
||||
|
||||
do --init trigger zones
|
||||
for _, trigger_zone in pairs(env.mission.triggers.zones) do
|
||||
for i, trigger_zone in pairs(env.mission.triggers.zones) do
|
||||
-- reorder verts as they are not ordered correctly in the ME
|
||||
local verts = {}
|
||||
if Util.tableLength(trigger_zone.verticies) >= 4 then
|
||||
@@ -192,7 +192,7 @@ do -- INIT DCS_UTIL
|
||||
BLUE = 2
|
||||
}
|
||||
]] --
|
||||
input = string.lower(input)
|
||||
local input = string.lower(input)
|
||||
if input == 'neutrals' or input == "neutral" or input == "0" then
|
||||
return DCS_UTIL.Coalition.NEUTRAL
|
||||
end
|
||||
@@ -235,7 +235,7 @@ do -- INIT DCS_UTIL
|
||||
end
|
||||
end
|
||||
|
||||
for _, zone_name in pairs(zone_names) do
|
||||
for index, zone_name in pairs(zone_names) do
|
||||
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
||||
if zone then
|
||||
zones[#zones + 1] = zone
|
||||
@@ -247,7 +247,7 @@ do -- INIT DCS_UTIL
|
||||
local lUnit = units[units_ind]
|
||||
local unit_pos = lUnit:getPosition().p
|
||||
local lCat = Object.getCategory(lUnit)
|
||||
for _, zone in pairs(zones) do
|
||||
for zone_name, zone in pairs(zones) do
|
||||
if unit_pos and ((lCat == 1 and lUnit:isActive() == true) or lCat ~= 1) then -- it is a unit and is active or it is not a unit
|
||||
local isInZone = Util.is3dPointInZone(unit_pos, zone)
|
||||
if isInZone == true then
|
||||
@@ -313,7 +313,7 @@ do -- INIT DCS_UTIL
|
||||
function DCS_UTIL.isPositionInZones(x, z, zone_names)
|
||||
---@type Array<SpearheadTriggerZone>
|
||||
local zones = {}
|
||||
for _, zone_name in pairs(zone_names) do
|
||||
for index, zone_name in pairs(zone_names) do
|
||||
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
||||
if zone then
|
||||
zones[#zones + 1] = zone
|
||||
@@ -321,7 +321,7 @@ do -- INIT DCS_UTIL
|
||||
end
|
||||
|
||||
local result_zones = {}
|
||||
for _, zone in pairs(zones) do
|
||||
for zone_name, zone in pairs(zones) do
|
||||
if Util.is3dPointInZone({ x = x, z = z, y = 0 }, zone) == true then
|
||||
result_zones[#result_zones + 1] = zone.name
|
||||
end
|
||||
@@ -414,7 +414,7 @@ do -- INIT DCS_UTIL
|
||||
local height = land.getHeight(location)
|
||||
local vec3 = { x = location.x, y = height, z = location.y }
|
||||
|
||||
unitType = string.lower(unitType or "")
|
||||
local unitType = string.lower(unitType or "")
|
||||
local conversionType = config[unitType]
|
||||
|
||||
if not conversionType then conversionType = "DDM" end
|
||||
@@ -574,7 +574,7 @@ do -- INIT DCS_UTIL
|
||||
local units = {}
|
||||
for i = 0, 2 do
|
||||
local players = coalition.getPlayers(i)
|
||||
for _, unit in pairs(players) do
|
||||
for key, unit in pairs(players) do
|
||||
units[#units + 1] = unit
|
||||
end
|
||||
end
|
||||
@@ -617,7 +617,8 @@ do -- INIT DCS_UTIL
|
||||
end
|
||||
|
||||
function DCS_UTIL.CleanCorpse(unitName)
|
||||
unitName = "dead_" .. unitName
|
||||
local unitName = "dead_" .. unitName
|
||||
|
||||
local object = StaticObject.getByName(unitName)
|
||||
|
||||
if object then
|
||||
@@ -631,11 +632,11 @@ do -- INIT DCS_UTIL
|
||||
---@field b number
|
||||
---@field a number
|
||||
|
||||
local __drawID = 4210
|
||||
local drawID = 4210
|
||||
|
||||
function DCS_UTIL.GetNextDrawID()
|
||||
__drawID = __drawID + 1
|
||||
return __drawID
|
||||
drawID = drawID + 1
|
||||
return drawID
|
||||
end
|
||||
|
||||
---@param groupID number
|
||||
@@ -643,9 +644,9 @@ do -- INIT DCS_UTIL
|
||||
---@param location Vec3
|
||||
---@return number markID
|
||||
function DCS_UTIL.AddMarkToGroup(groupID, text, location)
|
||||
local nextId = DCS_UTIL.GetNextDrawID()
|
||||
trigger.action.markToGroup(nextId, text, location, groupID, true, nil)
|
||||
return nextId
|
||||
local drawID = DCS_UTIL.GetNextDrawID()
|
||||
trigger.action.markToGroup(drawID, text, location, groupID, true, nil)
|
||||
return drawID
|
||||
end
|
||||
|
||||
---comment
|
||||
@@ -653,9 +654,9 @@ do -- INIT DCS_UTIL
|
||||
---@param location Vec3
|
||||
---@return integer
|
||||
function DCS_UTIL.AddMarkToAll(text, location)
|
||||
local nextId = DCS_UTIL.GetNextDrawID()
|
||||
trigger.action.markToAll(nextId, text, location, true, nil)
|
||||
return nextId
|
||||
local drawID = DCS_UTIL.GetNextDrawID()
|
||||
trigger.action.markToAll(drawID, text, location, true, nil)
|
||||
return drawID
|
||||
end
|
||||
|
||||
---@param markId number
|
||||
@@ -704,7 +705,7 @@ do -- INIT DCS_UTIL
|
||||
|
||||
---@return number? id
|
||||
function DCS_UTIL.GetNeutralCountry()
|
||||
for _, id in pairs(country.id) do
|
||||
for name, id in pairs(country.id) do
|
||||
if coalition.getCountryCoalition(id) == DCS_UTIL.Coalition.NEUTRAL then
|
||||
return id
|
||||
end
|
||||
@@ -758,7 +759,7 @@ do -- INIT DCS_UTIL
|
||||
function DCS_UTIL.GetPlayerGroupByGroupID(groupId)
|
||||
for i = 0, 2 do
|
||||
local players = coalition.getPlayers(i)
|
||||
for _, unit in pairs(players) do
|
||||
for key, unit in pairs(players) do
|
||||
if unit and unit:isExist() == true then
|
||||
local group = unit:getGroup()
|
||||
if group and group:getID() == groupId then
|
||||
@@ -774,7 +775,7 @@ do -- INIT DCS_UTIL
|
||||
function DCS_UTIL.GetPlayerUnitByID(unitID)
|
||||
for i = 0, 2 do
|
||||
local players = coalition.getPlayers(i)
|
||||
for _, unit in pairs(players) do
|
||||
for key, unit in pairs(players) do
|
||||
if unit and unit:getID() == unitID then
|
||||
return unit
|
||||
end
|
||||
|
||||
@@ -149,7 +149,7 @@ do -- INIT UTIL
|
||||
---@param findableTable table
|
||||
---@return boolean
|
||||
UTIL.startswithAny = function(str, findableTable)
|
||||
for _, value in pairs(findableTable) do
|
||||
for key, value in pairs(findableTable) do
|
||||
if type(value) == "string" and UTIL.startswith(str, value) then return true end
|
||||
end
|
||||
return false
|
||||
@@ -238,12 +238,7 @@ do -- INIT UTIL
|
||||
return ((vec1Norm.x * vec2Norm.x) + (vec1Norm.y * vec2Norm.y) + (vec1Norm.z * vec2Norm.z))
|
||||
end
|
||||
|
||||
---@param polygon Array<Vec2> of pairs { x, y }
|
||||
---@param x number X location
|
||||
---@param y number Y location
|
||||
---@return boolean
|
||||
local function isInComplexPolygon(polygon, x, y)
|
||||
---@param poly Array<Vec2> of pairs { x, y }
|
||||
local function getEdges(poly)
|
||||
local result = {}
|
||||
for i = 1, #poly do
|
||||
@@ -404,9 +399,7 @@ do -- INIT UTIL
|
||||
if #points == 0 then return {} end
|
||||
|
||||
-- Simple clustering: group points that are within minSeparation of each other
|
||||
---@type Array<Array<Vec2>>
|
||||
local clusters = {}
|
||||
---@type table<integer, boolean>
|
||||
local assigned = {}
|
||||
|
||||
for i, p in ipairs(points) do
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
--Single player purpose
|
||||
|
||||
local Logger = require("classes.util.Logger")
|
||||
local DcsUtil = require("classes.util.DcsUtil")
|
||||
local Database = require("classes.spearhead_db")
|
||||
local SpearheadEvents = require("classes.spearhead_events")
|
||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||
@@ -46,7 +47,7 @@ local spawnManager = SpawnManager.new(spawnLogger)
|
||||
local detectionLogger = Logger.new("DetectionManager", defaultLogLevel)
|
||||
local detectionManager = DetectionManager.New(detectionLogger)
|
||||
|
||||
GlobalCapManager.start(databaseManager, capConfig, detectionManager, defaultLogLevel, spawnManager)
|
||||
GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager)
|
||||
local globalStageManager = GlobalStageManager.new(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
||||
GlobalFleetManager.start(databaseManager)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user