Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a351c45b73 | ||
|
|
e081b8e446 | ||
|
|
4b3d87f589 | ||
|
|
1fde8ec3b1 | ||
|
|
68e8d1c9ac | ||
|
|
ccd38078f3 | ||
|
|
de1e6ffae9 | ||
|
|
2a76df1e21 | ||
|
|
a55cd2bf2a | ||
|
|
d16e25531a | ||
|
|
30c7124a86 | ||
|
|
514a9a9c55 | ||
|
|
96fab864c3 | ||
|
|
0346f8a7a8 | ||
|
|
ba240db310 | ||
|
|
50f2a0eea0 | ||
|
|
70d18f4ac3 | ||
|
|
341590e981 | ||
|
|
233310209b | ||
|
|
2cae676a10 | ||
|
|
de81fdf419 | ||
|
|
a1355ff05d | ||
|
|
2e636b2ded | ||
|
|
488a492e39 |
@@ -64,7 +64,7 @@
|
|||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
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>';
|
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 || '';
|
document.getElementById('beta-box-div').innerHTML = betaHtml || '';
|
||||||
|
|||||||
@@ -49,17 +49,6 @@ class DownloadScript extends HTMLElement {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
async connectedCallback() {
|
||||||
|
|
||||||
@@ -72,10 +61,9 @@ class DownloadScript extends HTMLElement {
|
|||||||
if (latestRelease) {
|
if (latestRelease) {
|
||||||
version = latestRelease.tag_name;
|
version = latestRelease.tag_name;
|
||||||
timestamp = new Date(latestRelease.published_at).toLocaleDateString('en-CA');
|
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) {
|
if (assets && assets.length > 0) {
|
||||||
const spearheadAsset = assets.find(asset => asset.name.includes('spearhead'));
|
const spearheadAsset = assets.find(asset => asset.name.includes('spearhead.v'));
|
||||||
if (spearheadAsset) {
|
if (spearheadAsset) {
|
||||||
size = (spearheadAsset.size / 1024).toFixed(2) + 'kb';
|
size = (spearheadAsset.size / 1024).toFixed(2) + 'kb';
|
||||||
href = spearheadAsset.browser_download_url;
|
href = spearheadAsset.browser_download_url;
|
||||||
@@ -105,7 +93,7 @@ class DownloadScript extends HTMLElement {
|
|||||||
<p>
|
<p>
|
||||||
<span class="version-text">${version}</span> (${timestamp}) <br>
|
<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="${href}">Download</a> (${size}) <br>
|
||||||
<a style="text-decoration: underline;" target="_blank" href="https://git.dutchie031.com/api/v1/repos/Spearhead/spearhead/releases">See All Versions here</a>
|
<a style="text-decoration: underline;" target="_blank" href="https://git.dutchie031.com/Spearhead/spearhead/releases">See All Versions here</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -169,13 +169,16 @@ class Sidebar extends HTMLElement {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
var betaHtml = '';
|
var betaHtml = '';
|
||||||
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>';
|
betaHtml = '<note-box type="warning" title="Beta Version">You are looking at docs that are released with the beta version.</note-box>';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.innerHTML = `
|
this.innerHTML = `
|
||||||
<div class="side-nav">
|
<div class="side-nav">
|
||||||
${betaHtml}
|
<div style="width:100%">
|
||||||
|
${betaHtml}
|
||||||
|
</div>
|
||||||
|
|
||||||
<h4 class="side-nav-title"></h4>
|
<h4 class="side-nav-title"></h4>
|
||||||
<ul>
|
<ul>
|
||||||
<!-- Navigation items will be populated automatically -->
|
<!-- Navigation items will be populated automatically -->
|
||||||
|
|||||||
@@ -80,17 +80,12 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
<note-box type="info" title="Combining Tasks">
|
<note-box type="info" title="Combining Tasks">
|
||||||
Currently a group can do 1 thing. Either be Primary, Seconday, Sweep or Intercept. <br>
|
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
|
If you want to have different types during different stages, it's best to copy paste groups and
|
||||||
rename them accordingly. <br>
|
rename them accordingly. <br>
|
||||||
</note-box>
|
</note-box>
|
||||||
|
|
||||||
<note-box type="info" title="Airfield Defenses">
|
|
||||||
|
|
||||||
</note-box>
|
|
||||||
|
|
||||||
<h3 id="cap-zones-ref">Zones</h3>
|
<h3 id="cap-zones-ref">Zones</h3>
|
||||||
<table class="table-no-style">
|
<table class="table-no-style">
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -99,6 +94,7 @@
|
|||||||
<td>=></td>
|
<td>=></td>
|
||||||
<td>A Cap ROUTE. The two most outer points are used to define the fly-over points.</td>
|
<td>A Cap ROUTE. The two most outer points are used to define the fly-over points.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr><td>______________________</td><td></td><td></td> </tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code-inline>INTERCEPTZONE_[ZoneID]_[NAME]</code-inline></td>
|
<td><code-inline>INTERCEPTZONE_[ZoneID]_[NAME]</code-inline></td>
|
||||||
<td>=></td>
|
<td>=></td>
|
||||||
@@ -112,6 +108,19 @@
|
|||||||
</p>
|
</p>
|
||||||
<h2 id="setup">Setting up groups</h2>
|
<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>
|
<h3 id="types-explained">Types explained</h3>
|
||||||
<p>
|
<p>
|
||||||
Before we go into depth on each type it's best to first look at the types briefly and what we
|
Before we go into depth on each type it's best to first look at the types briefly and what we
|
||||||
@@ -140,7 +149,7 @@
|
|||||||
The ground attack units mentioned are not in yet and thus escort groups are not either. <br>
|
The ground attack units mentioned are not in yet and thus escort groups are not either. <br>
|
||||||
|
|
||||||
<note-box type="warning" title="Overriding Taskings">
|
<note-box type="warning" title="Overriding Taskings">
|
||||||
Each tasking has very specific waypoints, both for departure, arrical and ofcourse all point in between. <br>
|
Each tasking has very specific waypoints, both for departure, arrival 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 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.
|
Overriding these waypoints and taskings will break the management by Spearhead.
|
||||||
</note-box>
|
</note-box>
|
||||||
@@ -154,7 +163,7 @@
|
|||||||
The way the trigger zone is mapped to a route is as follows: <br>
|
The way the trigger zone is mapped to a route is as follows: <br>
|
||||||
<br>
|
<br>
|
||||||
The 2 points that are furthest apart from each other are chosen as the "leg" of the route. <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. <br>
|
The other 2 points are discarded at this time. <br>
|
||||||
<br>
|
<br>
|
||||||
The Orbit route is then created with an "Anchored" task. With the closest point being the starting
|
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>
|
point with an outbound leg to the furthest point. <br>
|
||||||
|
|||||||
@@ -337,6 +337,7 @@ main {
|
|||||||
|
|
||||||
.side-nav {
|
.side-nav {
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
|
max-width: 200px;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
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
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -15,7 +15,7 @@ SpearheadConfig = {
|
|||||||
--quickly enable of disable the entire CAP Logic
|
--quickly enable of disable the entire CAP Logic
|
||||||
--(you can also just rename all units to not be named "CAP_")
|
--(you can also just rename all units to not be named "CAP_")
|
||||||
enabled = true, -- default true
|
enabled = true, -- default true
|
||||||
|
|
||||||
--min ground speed for CAP aircraft during patrol
|
--min ground speed for CAP aircraft during patrol
|
||||||
-- unit: knots
|
-- unit: knots
|
||||||
minSpeed = 400, -- default 400
|
minSpeed = 400, -- default 400
|
||||||
@@ -62,7 +62,7 @@ SpearheadConfig = {
|
|||||||
deathDelay = 1800, -- default 1800
|
deathDelay = 1800, -- default 1800
|
||||||
},
|
},
|
||||||
StageConfig = {
|
StageConfig = {
|
||||||
|
|
||||||
-- management of stages and its missions.
|
-- management of stages and its missions.
|
||||||
-- This is not related to CAP managers which will continue to work even if stage management is disabled
|
-- This is not related to CAP managers which will continue to work even if stage management is disabled
|
||||||
enabled = true, -- default true
|
enabled = true, -- default true
|
||||||
@@ -98,7 +98,7 @@ SpearheadConfig = {
|
|||||||
},
|
},
|
||||||
Persistence = {
|
Persistence = {
|
||||||
--- io and lfs cannot be sanitized in the MissionScripting.lua
|
--- io and lfs cannot be sanitized in the MissionScripting.lua
|
||||||
|
|
||||||
--- enables or disables the persistence logic in spearhead
|
--- enables or disables the persistence logic in spearhead
|
||||||
enabled = false,
|
enabled = false,
|
||||||
|
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
--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"))()
|
|
||||||
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
|
|
||||||
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,7 +2,6 @@ local Util = require("classes.util.Util")
|
|||||||
local CapGroup = require("classes.capClasses.airGroups.CapGroup")
|
local CapGroup = require("classes.capClasses.airGroups.CapGroup")
|
||||||
local SweepGroup = require("classes.capClasses.airGroups.SweepGroup")
|
local SweepGroup = require("classes.capClasses.airGroups.SweepGroup")
|
||||||
local InterceptGroup = require("classes.capClasses.airGroups.InterceptGroup")
|
local InterceptGroup = require("classes.capClasses.airGroups.InterceptGroup")
|
||||||
local RunwayBombingTracker = require("classes.capClasses.runwayBombing.RunwayBombingTracker")
|
|
||||||
local SpearheadEvents = require("classes.spearhead_events")
|
local SpearheadEvents = require("classes.spearhead_events")
|
||||||
local RunwayStrikeMission = require("classes.stageClasses.missions.RunwayStrikeMission")
|
local RunwayStrikeMission = require("classes.stageClasses.missions.RunwayStrikeMission")
|
||||||
|
|
||||||
@@ -37,12 +36,11 @@ end
|
|||||||
---@param database Database
|
---@param database Database
|
||||||
---@param logger table
|
---@param logger table
|
||||||
---@param capConfig table
|
---@param capConfig table
|
||||||
---@param stageConfig table
|
|
||||||
---@param runwayBombingTracker RunwayBombingTracker
|
---@param runwayBombingTracker RunwayBombingTracker
|
||||||
---@param detectionManager DetectionManager
|
---@param detectionManager DetectionManager
|
||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
---@return CapBase
|
---@return CapBase
|
||||||
function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
function CapBase.new(airbaseName, database, logger, capConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||||
CapBase.__index = CapBase
|
CapBase.__index = CapBase
|
||||||
local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]]
|
local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]]
|
||||||
|
|
||||||
@@ -61,7 +59,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
|||||||
|
|
||||||
local baseData = database:getAirbaseDataForZone(airbaseName)
|
local baseData = database:getAirbaseDataForZone(airbaseName)
|
||||||
if baseData and baseData.CapGroups then
|
if baseData and baseData.CapGroups then
|
||||||
for key, name in pairs(baseData.CapGroups) do
|
for _, name in pairs(baseData.CapGroups) do
|
||||||
local capGroup = CapGroup.New(name, capConfig, logger, spawnManager)
|
local capGroup = CapGroup.New(name, capConfig, logger, spawnManager)
|
||||||
if capGroup then
|
if capGroup then
|
||||||
self.capGroupsByName[name] = capGroup
|
self.capGroupsByName[name] = capGroup
|
||||||
@@ -70,7 +68,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
|||||||
end
|
end
|
||||||
|
|
||||||
if baseData and baseData.SweepGroups then
|
if baseData and baseData.SweepGroups then
|
||||||
for key, name in pairs(baseData.SweepGroups) do
|
for _, name in pairs(baseData.SweepGroups) do
|
||||||
local sweepGroup = SweepGroup.New(name, capConfig, logger, spawnManager)
|
local sweepGroup = SweepGroup.New(name, capConfig, logger, spawnManager)
|
||||||
if sweepGroup then
|
if sweepGroup then
|
||||||
self.sweepGroupsByName[name] = sweepGroup
|
self.sweepGroupsByName[name] = sweepGroup
|
||||||
@@ -79,7 +77,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
|||||||
end
|
end
|
||||||
|
|
||||||
if baseData and baseData.InterceptGroups then
|
if baseData and baseData.InterceptGroups then
|
||||||
for key, name in pairs(baseData.InterceptGroups) do
|
for _, name in pairs(baseData.InterceptGroups) do
|
||||||
local interceptGroup = InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
|
local interceptGroup = InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
|
||||||
if interceptGroup then
|
if interceptGroup then
|
||||||
self.interceptGroupsByName[name] = interceptGroup
|
self.interceptGroupsByName[name] = interceptGroup
|
||||||
@@ -97,7 +95,6 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
|||||||
SpearheadEvents.AddStageNumberChangedListener(self)
|
SpearheadEvents.AddStageNumberChangedListener(self)
|
||||||
|
|
||||||
timer.scheduleFunction(CheckStateContinuous, self, timer.getTime() + 15)
|
timer.scheduleFunction(CheckStateContinuous, self, timer.getTime() + 15)
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -127,7 +124,7 @@ end
|
|||||||
|
|
||||||
function CapBase:SpawnIfApplicable()
|
function CapBase:SpawnIfApplicable()
|
||||||
self.logger:debug("Check spawns for airbase " .. self.airbaseName)
|
self.logger:debug("Check spawns for airbase " .. self.airbaseName)
|
||||||
for groupName, capGroup in pairs(self.capGroupsByName) do
|
for _, capGroup in pairs(self.capGroupsByName) do
|
||||||
local targetStage = capGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
local targetStage = capGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||||
|
|
||||||
if targetStage ~= nil and capGroup:GetState() == "UnSpawned" then
|
if targetStage ~= nil and capGroup:GetState() == "UnSpawned" then
|
||||||
@@ -135,7 +132,7 @@ function CapBase:SpawnIfApplicable()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for groupName, sweepGroup in pairs(self.sweepGroupsByName) do
|
for _, sweepGroup in pairs(self.sweepGroupsByName) do
|
||||||
local targetStage = sweepGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
local targetStage = sweepGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||||
|
|
||||||
if targetStage ~= nil and sweepGroup:GetState() == "UnSpawned" then
|
if targetStage ~= nil and sweepGroup:GetState() == "UnSpawned" then
|
||||||
@@ -143,7 +140,7 @@ function CapBase:SpawnIfApplicable()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for groupName, interceptGroup in pairs(self.interceptGroupsByName) do
|
for _, interceptGroup in pairs(self.interceptGroupsByName) do
|
||||||
local targetStage = interceptGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
local targetStage = interceptGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||||
|
|
||||||
if targetStage ~= nil and interceptGroup:GetState() == "UnSpawned" then
|
if targetStage ~= nil and interceptGroup:GetState() == "UnSpawned" then
|
||||||
@@ -154,8 +151,9 @@ end
|
|||||||
|
|
||||||
function CapBase:CheckAndScheduleCAP()
|
function CapBase:CheckAndScheduleCAP()
|
||||||
self.logger:debug("Check taskings for airbase " .. self.airbaseName)
|
self.logger:debug("Check taskings for airbase " .. self.airbaseName)
|
||||||
|
---@type table<string, number>
|
||||||
local countPerStage = {}
|
local countPerStage = {}
|
||||||
|
---@type table<string, number>
|
||||||
local requiredPerStage = {}
|
local requiredPerStage = {}
|
||||||
|
|
||||||
local airbase = Airbase.getByName(self.airbaseName)
|
local airbase = Airbase.getByName(self.airbaseName)
|
||||||
@@ -170,7 +168,7 @@ function CapBase:CheckAndScheduleCAP()
|
|||||||
if group:IsBackup() == true then
|
if group:IsBackup() == true then
|
||||||
local state = group:GetState()
|
local state = group:GetState()
|
||||||
if state == "InTransit" or state == "OnStation" or state == "RtbInTen" then
|
if state == "InTransit" or state == "OnStation" or state == "RtbInTen" then
|
||||||
|
|
||||||
local supposedTargetZoneID = group:GetZoneIDWhenStageID(activeStageID)
|
local supposedTargetZoneID = group:GetZoneIDWhenStageID(activeStageID)
|
||||||
local currentTargetZone = group:GetCurrentTargetZoneID()
|
local currentTargetZone = group:GetCurrentTargetZoneID()
|
||||||
|
|
||||||
@@ -192,7 +190,7 @@ function CapBase:CheckAndScheduleCAP()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if countPerStage[supposedTargetZoneID] == nil then
|
if countPerStage[supposedTargetZoneID] == nil then
|
||||||
countPerStage[supposedTargetZoneID] = 0
|
countPerStage[supposedTargetZoneID] = 0
|
||||||
end
|
end
|
||||||
@@ -231,7 +229,7 @@ function CapBase:CheckAndScheduleCAP()
|
|||||||
countPerStage[supposedZone] = countPerStage[supposedZone] + 1
|
countPerStage[supposedZone] = countPerStage[supposedZone] + 1
|
||||||
end
|
end
|
||||||
elseif state == "InTransit" or state == "OnStation" then
|
elseif state == "InTransit" or state == "OnStation" then
|
||||||
|
|
||||||
if supposedZone ~= group:GetCurrentTargetZoneID() then
|
if supposedZone ~= group:GetCurrentTargetZoneID() then
|
||||||
if countPerStage[supposedZone] < requiredPerStage[supposedZone] then
|
if countPerStage[supposedZone] < requiredPerStage[supposedZone] then
|
||||||
local triggerZone = self.database:GetCapZoneForZoneID(supposedZone)
|
local triggerZone = self.database:GetCapZoneForZoneID(supposedZone)
|
||||||
@@ -273,7 +271,7 @@ function CapBase:CheckAndScheduleCAP()
|
|||||||
if triggerZone then
|
if triggerZone then
|
||||||
group:SendToZone(triggerZone, supposedZone, airbase)
|
group:SendToZone(triggerZone, supposedZone, airbase)
|
||||||
end
|
end
|
||||||
|
|
||||||
countPerStage[supposedZone] = countPerStage[supposedZone] + 1
|
countPerStage[supposedZone] = countPerStage[supposedZone] + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -312,8 +310,7 @@ function CapBase:CheckAndScheduleIntercept()
|
|||||||
|
|
||||||
self.logger:debug("Check intercept taskings for airbase " .. self.airbaseName)
|
self.logger:debug("Check intercept taskings for airbase " .. self.airbaseName)
|
||||||
|
|
||||||
local interceptZoneIDs = {}
|
---@type table<string, boolean>
|
||||||
|
|
||||||
local interceptZoneIDs = {}
|
local interceptZoneIDs = {}
|
||||||
|
|
||||||
local airbase = Airbase.getByName(self.airbaseName)
|
local airbase = Airbase.getByName(self.airbaseName)
|
||||||
@@ -321,7 +318,7 @@ function CapBase:CheckAndScheduleIntercept()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
for name, group in pairs(self.interceptGroupsByName) do
|
for _, group in pairs(self.interceptGroupsByName) do
|
||||||
local targetZoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
|
local targetZoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||||
if targetZoneID then
|
if targetZoneID then
|
||||||
interceptZoneIDs[targetZoneID] = true
|
interceptZoneIDs[targetZoneID] = true
|
||||||
@@ -357,7 +354,7 @@ function CapBase:CheckAndScheduleIntercept()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---RATIO. Amount of enemy fighters required per zone before another group gets added.
|
---RATIO. Amount of enemy fighters required per zone before another group gets added.
|
||||||
local ratio = 4 -- Ratio of units to intercept per zone, can be adjusted
|
local ratio = 4 -- Ratio of units to intercept per zone, can be adjusted
|
||||||
|
|
||||||
@@ -379,7 +376,6 @@ function CapBase:CheckAndScheduleIntercept()
|
|||||||
if total < required then
|
if total < required then
|
||||||
for _, group in pairs(self.interceptGroupsByName) do
|
for _, group in pairs(self.interceptGroupsByName) do
|
||||||
if total < required then
|
if total < required then
|
||||||
local zoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
|
|
||||||
if group:GetState() == "ReadyOnTheRamp" then
|
if group:GetState() == "ReadyOnTheRamp" then
|
||||||
group:SendToInterceptUnits(targets, name, airbase)
|
group:SendToInterceptUnits(targets, name, airbase)
|
||||||
total = total + 1
|
total = total + 1
|
||||||
|
|||||||
@@ -8,19 +8,15 @@ local GlobalCapManager = {}
|
|||||||
do
|
do
|
||||||
local airbasesPerStage = {}
|
local airbasesPerStage = {}
|
||||||
local allAirbasesByName = {}
|
local allAirbasesByName = {}
|
||||||
local activeAirbasesPerActiveStage = {}
|
|
||||||
local unitsPerzonePerStage = {}
|
|
||||||
|
|
||||||
local initiated = false
|
local initiated = false
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param database Database
|
---@param database Database
|
||||||
---@param capConfig table
|
---@param capConfig table
|
||||||
---@param stageConfig StageConfig
|
|
||||||
---@param detectionManager DetectionManager
|
---@param detectionManager DetectionManager
|
||||||
---@param logLevel LogLevel
|
---@param logLevel LogLevel
|
||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
function GlobalCapManager.start(database, capConfig, detectionManager, stageConfig, logLevel, spawnManager)
|
function GlobalCapManager.start(database, capConfig, detectionManager, logLevel, spawnManager)
|
||||||
if initiated == true then return end
|
if initiated == true then return end
|
||||||
|
|
||||||
local logger = Logger.new("AirbaseManager", logLevel)
|
local logger = Logger.new("AirbaseManager", logLevel)
|
||||||
@@ -29,7 +25,7 @@ do
|
|||||||
|
|
||||||
local zones = database:getStagezoneNames()
|
local zones = database:getStagezoneNames()
|
||||||
if zones then
|
if zones then
|
||||||
for key, stageName in pairs(zones) do
|
for _, stageName in pairs(zones) do
|
||||||
if airbasesPerStage[stageName] == nil then
|
if airbasesPerStage[stageName] == nil then
|
||||||
airbasesPerStage[stageName] = {}
|
airbasesPerStage[stageName] = {}
|
||||||
end
|
end
|
||||||
@@ -39,9 +35,8 @@ do
|
|||||||
for _, airbaseName in pairs(airbaseNames) do
|
for _, airbaseName in pairs(airbaseNames) do
|
||||||
if airbaseName then
|
if airbaseName then
|
||||||
local airbaseSpecificLogger = Logger.new("CAP_" .. airbaseName, logLevel)
|
local airbaseSpecificLogger = Logger.new("CAP_" .. airbaseName, logLevel)
|
||||||
|
|
||||||
local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||||
|
|
||||||
if airbase then
|
if airbase then
|
||||||
table.insert(airbasesPerStage[stageName], airbase)
|
table.insert(airbasesPerStage[stageName], airbase)
|
||||||
allAirbasesByName[airbaseName] = airbase
|
allAirbasesByName[airbaseName] = airbase
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
local SpearheadEvents = require("classes.spearhead_events")
|
local SpearheadEvents = require("classes.spearhead_events")
|
||||||
local RTBMission = require("classes.capClasses.taskings.RTB")
|
local RTBMission = require("classes.capClasses.taskings.RTB")
|
||||||
local Util = require("classes.util.Util")
|
local Util = require("classes.util.Util")
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
|
||||||
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
||||||
local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing")
|
local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing")
|
||||||
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
||||||
@@ -81,7 +80,7 @@ function AirGroup:SetMission(mission)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local setMissionDelayed = function(data, time)
|
local setMissionDelayed = function(data, _)
|
||||||
data.self:SetMissionPrivate(data.mission)
|
data.self:SetMissionPrivate(data.mission)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -357,7 +356,7 @@ do --- RESPAWN FUNCTIONS
|
|||||||
self:SetState("Dead")
|
self:SetState("Dead")
|
||||||
|
|
||||||
---@param selfA AirGroup
|
---@param selfA AirGroup
|
||||||
local respawnTask = function(selfA, time)
|
local respawnTask = function(selfA, _)
|
||||||
selfA:StartRepair()
|
selfA:StartRepair()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -376,8 +375,7 @@ do --- RESPAWN FUNCTIONS
|
|||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param selfA AirGroup
|
local rearmTask = function(_, _)
|
||||||
local rearmTask = function(selfA, time)
|
|
||||||
self:StartRearm()
|
self:StartRearm()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -402,7 +400,7 @@ do --- RESPAWN FUNCTIONS
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param selfA AirGroup
|
---@param selfA AirGroup
|
||||||
local rearmTask = function(selfA, time)
|
local rearmTask = function(selfA, _)
|
||||||
selfA:MarkRearmComplete()
|
selfA:MarkRearmComplete()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -415,6 +413,7 @@ end
|
|||||||
do --EVENT LISTENERS
|
do --EVENT LISTENERS
|
||||||
---@param unit Unit
|
---@param unit Unit
|
||||||
function AirGroup:OnUnitLost(unit)
|
function AirGroup:OnUnitLost(unit)
|
||||||
|
if unit == nil then return end
|
||||||
self:CheckLiveness()
|
self:CheckLiveness()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -434,7 +433,7 @@ do --EVENT LISTENERS
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function AirGroup:OnUnitLanded(unit, airbase)
|
function AirGroup:OnUnitLanded(_, _)
|
||||||
local anyInAir = false
|
local anyInAir = false
|
||||||
local group = Group.getByName(self._groupName)
|
local group = Group.getByName(self._groupName)
|
||||||
if group then
|
if group then
|
||||||
|
|||||||
@@ -103,17 +103,17 @@ function CapGroup:InitWithName(groupName)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local subsplit = Util.split_string(configPart, "|")
|
local subsplit = Util.split_string(configPart, "|")
|
||||||
if subsplit then
|
if subsplit then
|
||||||
for key, value in pairs(subsplit) do
|
for _, value in pairs(subsplit) do
|
||||||
local keySplit = Util.split_string(value, "]")
|
local keySplit = Util.split_string(value, "]")
|
||||||
local targetZone = keySplit[2]
|
local targetZone = keySplit[2]
|
||||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||||
local commaSeperated = Util.split_string(allActives, ",")
|
local commaSeperated = Util.split_string(allActives, ",")
|
||||||
for _, value in pairs(commaSeperated) do
|
for _, childValue in pairs(commaSeperated) do
|
||||||
local dashSeperated = Util.split_string(value, "-")
|
local dashSeperated = Util.split_string(childValue, "-")
|
||||||
if Util.tableLength(dashSeperated) > 1 then
|
if Util.tableLength(dashSeperated) > 1 then
|
||||||
local from = tonumber(dashSeperated[1])
|
local from = tonumber(dashSeperated[1])
|
||||||
local till = tonumber(dashSeperated[2])
|
local till = tonumber(dashSeperated[2])
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ function InterceptGroup:UpdateTask()
|
|||||||
self:SendRTB(self._airbase)
|
self:SendRTB(self._airbase)
|
||||||
return nil -- Return to base if bingo fuel
|
return nil -- Return to base if bingo fuel
|
||||||
end
|
end
|
||||||
|
|
||||||
if selfDetected and self:IsInAir() == true then
|
if selfDetected and self:IsInAir() == true then
|
||||||
if self._currentTargetName and self._currentTargetName == closestUnit:getName() then
|
if self._currentTargetName and self._currentTargetName == closestUnit:getName() then
|
||||||
local distance = Util.VectorDistance3d(closestUnit:getPoint(), groupPoint)
|
local distance = Util.VectorDistance3d(closestUnit:getPoint(), groupPoint)
|
||||||
@@ -213,8 +213,6 @@ function InterceptGroup:UpdateTask()
|
|||||||
self._currentTargetName = nil
|
self._currentTargetName = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local speed = self._config:getMaxSpeed()
|
local speed = self._config:getMaxSpeed()
|
||||||
local interceptPoint = self:GetInterceptPoint(groupPoint, speed, closestUnit)
|
local interceptPoint = self:GetInterceptPoint(groupPoint, speed, closestUnit)
|
||||||
|
|
||||||
@@ -323,13 +321,13 @@ function InterceptGroup:InitWithName(groupName)
|
|||||||
configPart = string.sub(configPart, 2, #configPart)
|
configPart = string.sub(configPart, 2, #configPart)
|
||||||
local subsplit = Util.split_string(configPart, "|")
|
local subsplit = Util.split_string(configPart, "|")
|
||||||
if subsplit then
|
if subsplit then
|
||||||
for key, value in pairs(subsplit) do
|
for _, value in pairs(subsplit) do
|
||||||
local keySplit = Util.split_string(value, "]")
|
local keySplit = Util.split_string(value, "]")
|
||||||
local targetZone = keySplit[2]
|
local targetZone = keySplit[2]
|
||||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||||
local commaSeperated = Util.split_string(allActives, ",")
|
local commaSeperated = Util.split_string(allActives, ",")
|
||||||
for _, value in pairs(commaSeperated) do
|
for _, childValue in pairs(commaSeperated) do
|
||||||
local dashSeperated = Util.split_string(value, "-")
|
local dashSeperated = Util.split_string(childValue, "-")
|
||||||
if Util.tableLength(dashSeperated) > 1 then
|
if Util.tableLength(dashSeperated) > 1 then
|
||||||
local from = tonumber(dashSeperated[1])
|
local from = tonumber(dashSeperated[1])
|
||||||
local till = tonumber(dashSeperated[2])
|
local till = tonumber(dashSeperated[2])
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ end
|
|||||||
---@field self SweepGroup
|
---@field self SweepGroup
|
||||||
|
|
||||||
---@param params SetTaskParams
|
---@param params SetTaskParams
|
||||||
local setMissionDelayedTask = function(params, time)
|
local setMissionDelayedTask = function(params, _)
|
||||||
params.self:SetMissionPrivate(params.task)
|
params.self:SetMissionPrivate(params.task)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -50,8 +50,6 @@ function SweepGroup:SendToZone(zone, targetZoneID, airbase)
|
|||||||
|
|
||||||
self._currentTargetZoneID = targetZoneID
|
self._currentTargetZoneID = targetZoneID
|
||||||
|
|
||||||
local group = Group.getByName(self._groupName)
|
|
||||||
|
|
||||||
local mission = SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
local mission = SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
||||||
if mission then
|
if mission then
|
||||||
---@type SetTaskParams
|
---@type SetTaskParams
|
||||||
@@ -79,16 +77,16 @@ function SweepGroup:InitWithName(groupName)
|
|||||||
|
|
||||||
local configPart = split_string[2]
|
local configPart = split_string[2]
|
||||||
configPart = string.sub(configPart, 2, #configPart)
|
configPart = string.sub(configPart, 2, #configPart)
|
||||||
|
|
||||||
local subsplit = Util.split_string(configPart, "|")
|
local subsplit = Util.split_string(configPart, "|")
|
||||||
if subsplit then
|
if subsplit then
|
||||||
for key, value in pairs(subsplit) do
|
for _, value in pairs(subsplit) do
|
||||||
local keySplit = Util.split_string(value, "]")
|
local keySplit = Util.split_string(value, "]")
|
||||||
local targetZone = keySplit[2]
|
local targetZone = keySplit[2]
|
||||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||||
local commaSeperated = Util.split_string(allActives, ",")
|
local commaSeperated = Util.split_string(allActives, ",")
|
||||||
for _, value in pairs(commaSeperated) do
|
for _, childValue in pairs(commaSeperated) do
|
||||||
local dashSeperated = Util.split_string(value, "-")
|
local dashSeperated = Util.split_string(childValue, "-")
|
||||||
if Util.tableLength(dashSeperated) > 1 then
|
if Util.tableLength(dashSeperated) > 1 then
|
||||||
local from = tonumber(dashSeperated[1])
|
local from = tonumber(dashSeperated[1])
|
||||||
local till = tonumber(dashSeperated[2])
|
local till = tonumber(dashSeperated[2])
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ function DetectionManager.New(logger)
|
|||||||
return time + 10
|
return time + 10
|
||||||
end
|
end
|
||||||
timer.scheduleFunction(updateDetected, self, timer.getTime() + 130)
|
timer.scheduleFunction(updateDetected, self, timer.getTime() + 130)
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ end
|
|||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param weapon Weapon
|
---@param weapon Weapon
|
||||||
function RunwayBombingTracker:OnWeaponFired(unit, weapon, target)
|
function RunwayBombingTracker:OnWeaponFired(_, weapon, _)
|
||||||
|
|
||||||
if weapon == nil then
|
if weapon == nil then
|
||||||
return
|
return
|
||||||
@@ -30,7 +30,7 @@ function RunwayBombingTracker:OnWeaponFired(unit, weapon, target)
|
|||||||
local desc = weapon:getDesc()
|
local desc = weapon:getDesc()
|
||||||
local isTrackable = desc.category == Weapon.Category.BOMB or (desc.category == Weapon.Category.MISSILE and desc.missileCategory == Weapon.MissileCategory.CRUISE)
|
local isTrackable = desc.category == Weapon.Category.BOMB or (desc.category == Weapon.Category.MISSILE and desc.missileCategory == Weapon.MissileCategory.CRUISE)
|
||||||
if isTrackable == true then
|
if isTrackable == true then
|
||||||
|
|
||||||
---@type WeaponTrackingArgs
|
---@type WeaponTrackingArgs
|
||||||
local weaponTrackingArgs = {
|
local weaponTrackingArgs = {
|
||||||
weapon = weapon,
|
weapon = weapon,
|
||||||
@@ -61,7 +61,7 @@ function RunwayBombingTracker.trackWeaponTask(weaponTrackingArgs, time)
|
|||||||
|
|
||||||
local weapon = weaponTrackingArgs.weapon
|
local weapon = weaponTrackingArgs.weapon
|
||||||
local self = weaponTrackingArgs.self
|
local self = weaponTrackingArgs.self
|
||||||
|
|
||||||
if not weapon or weapon:isExist() == false then return nil end
|
if not weapon or weapon:isExist() == false then return nil end
|
||||||
|
|
||||||
local pos = weapon:getPoint()
|
local pos = weapon:getPoint()
|
||||||
@@ -83,11 +83,7 @@ function RunwayBombingTracker.trackWeaponTask(weaponTrackingArgs, time)
|
|||||||
x = pos.x + velocity.x * nextInterval,
|
x = pos.x + velocity.x * nextInterval,
|
||||||
y = pos.z + velocity.z * nextInterval
|
y = pos.z + velocity.z * nextInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
self:OnWeaponImpact(weapon:getDesc(), impactPoint)
|
self:OnWeaponImpact(weapon:getDesc(), impactPoint)
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -109,7 +105,7 @@ function RunwayBombingTracker:OnWeaponImpact(weaponDesc, impactPoint)
|
|||||||
local warhead = weaponDesc.warhead
|
local warhead = weaponDesc.warhead
|
||||||
local explosiveMass = warhead.explosiveMass or warhead.shapedExplosiveMass
|
local explosiveMass = warhead.explosiveMass or warhead.shapedExplosiveMass
|
||||||
|
|
||||||
for runway, strikeMission in pairs(self.trackedRunways) do
|
for _, strikeMission in pairs(self.trackedRunways) do
|
||||||
|
|
||||||
local zone= strikeMission:GetRunwayZone()
|
local zone= strikeMission:GetRunwayZone()
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
|||||||
local furthestA = nil
|
local furthestA = nil
|
||||||
local furthestB = nil
|
local furthestB = nil
|
||||||
|
|
||||||
local furthestFromBase = nil
|
|
||||||
local furthestFromBaseDistance = 0
|
|
||||||
|
|
||||||
local furthestDistance = 0
|
local furthestDistance = 0
|
||||||
|
|
||||||
for indexA, pointA in ipairs(capZone.verts) do
|
for indexA, pointA in ipairs(capZone.verts) do
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ function INTERCEPT.getMissionFromAirbase(groupName, interceptPoint, airbase, con
|
|||||||
id = 'Mission',
|
id = 'Mission',
|
||||||
params = {
|
params = {
|
||||||
airborne = true,
|
airborne = true,
|
||||||
route = {
|
route = {
|
||||||
points = points
|
points = points
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,10 +159,10 @@ function INTERCEPT.getInterceptTaskPoint(groupName, currentPoint, targetPoint, a
|
|||||||
params = {
|
params = {
|
||||||
tasks = {
|
tasks = {
|
||||||
id = 'EngageTargetsInZone',
|
id = 'EngageTargetsInZone',
|
||||||
params = {
|
params = {
|
||||||
point = targetPoint,
|
point = targetPoint,
|
||||||
zoneRadius = 10 * 1852, -- 10 NM, point will be updated, so target should be in this zone.
|
zoneRadius = 10 * 1852, -- 10 NM, point will be updated, so target should be in this zone.
|
||||||
targetTypes = {
|
targetTypes = {
|
||||||
[1] = "Planes",
|
[1] = "Planes",
|
||||||
},
|
},
|
||||||
priority = 0
|
priority = 0
|
||||||
@@ -188,10 +188,10 @@ function INTERCEPT.getInterceptTaskPoint(groupName, currentPoint, targetPoint, a
|
|||||||
params = {
|
params = {
|
||||||
tasks = {
|
tasks = {
|
||||||
id = 'EngageTargetsInZone',
|
id = 'EngageTargetsInZone',
|
||||||
params = {
|
params = {
|
||||||
point = targetPoint,
|
point = targetPoint,
|
||||||
zoneRadius = 10 * 1852, -- 10 NM, point will be updated, so target should be in this zone.
|
zoneRadius = 10 * 1852, -- 10 NM, point will be updated, so target should be in this zone.
|
||||||
targetTypes = {
|
targetTypes = {
|
||||||
[1] = "Planes",
|
[1] = "Planes",
|
||||||
},
|
},
|
||||||
priority = 0
|
priority = 0
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ local getRunwayIntoWindCourseRad = function(airbase)
|
|||||||
else
|
else
|
||||||
rad = 0 - rad
|
rad = 0 - rad
|
||||||
end
|
end
|
||||||
|
|
||||||
local runwayVec = {x = math.cos(rad), z = math.sin(rad), y = 0}
|
local runwayVec = {x = math.cos(rad), z = math.sin(rad), y = 0}
|
||||||
local alignment = Util.vectorAlignment(windVec, runwayVec)
|
local alignment = Util.vectorAlignment(windVec, runwayVec)
|
||||||
|
|
||||||
@@ -60,14 +60,14 @@ local getRunwayIntoWindCourseRad = function(airbase)
|
|||||||
do --inverse
|
do --inverse
|
||||||
local degree = math.deg(runway.course)
|
local degree = math.deg(runway.course)
|
||||||
degree = (degree + 180) % 360
|
degree = (degree + 180) % 360
|
||||||
|
|
||||||
local rad = math.rad(degree)
|
local rad = math.rad(degree)
|
||||||
if rad < 0 then
|
if rad < 0 then
|
||||||
rad = math.abs(rad)
|
rad = math.abs(rad)
|
||||||
else
|
else
|
||||||
rad = 0 - rad
|
rad = 0 - rad
|
||||||
end
|
end
|
||||||
|
|
||||||
local runwayVec = {x = math.cos(rad), z = math.sin(rad), y = 0}
|
local runwayVec = {x = math.cos(rad), z = math.sin(rad), y = 0}
|
||||||
local alignment = Util.vectorAlignment(windVec, runwayVec)
|
local alignment = Util.vectorAlignment(windVec, runwayVec)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
local briefingMessageTime = nil
|
|
||||||
|
|
||||||
---@class GlobalConfig
|
---@class GlobalConfig
|
||||||
---@field private _briefingTime number
|
---@field private _briefingTime number
|
||||||
---@field private _debugEnabled boolean
|
---@field private _debugEnabled boolean
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ local _logger = Logger.new("StageConfig", Logger.LogLevel)
|
|||||||
---@return StageConfig
|
---@return StageConfig
|
||||||
local function new()
|
local function new()
|
||||||
|
|
||||||
if SpearheadConfig == nil then
|
if SpearheadConfig == nil then
|
||||||
_logger:warn("SpearheadConfig is nil, creating default SpearheadConfig")
|
_logger:warn("SpearheadConfig is nil, creating default SpearheadConfig")
|
||||||
SpearheadConfig = {}
|
SpearheadConfig = {}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local Util = require("classes.util.Util")
|
|
||||||
local StageRepository = require("classes.stageClasses.StageRepository")
|
local StageRepository = require("classes.stageClasses.StageRepository")
|
||||||
|
|
||||||
---@class DebugMenu
|
---@class DebugMenu
|
||||||
|
|||||||
@@ -4,37 +4,43 @@ local MissionEditorWarning = require("classes.util.MissionEditorWarnings")
|
|||||||
local RouteUtil = require("classes.spearhead_routeutil")
|
local RouteUtil = require("classes.spearhead_routeutil")
|
||||||
local SpearheadEvents = require("classes.spearhead_events")
|
local SpearheadEvents = require("classes.spearhead_events")
|
||||||
|
|
||||||
---@class FleetGroup
|
---@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}>
|
||||||
local FleetGroup = {}
|
local FleetGroup = {}
|
||||||
|
FleetGroup.__index = FleetGroup
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param fleetGroupName string
|
---@param fleetGroupName string
|
||||||
---@param database Database
|
---@param database Database
|
||||||
---@param logger Logger
|
---@param logger Logger
|
||||||
---@return nil
|
---@return FleetGroup?
|
||||||
function FleetGroup:new(fleetGroupName, database, logger)
|
function FleetGroup.new(fleetGroupName, database, logger)
|
||||||
local o = {}
|
|
||||||
|
|
||||||
setmetatable(o, { __index = self })
|
local self = setmetatable({}, FleetGroup)
|
||||||
|
|
||||||
o.fleetGroupName = fleetGroupName
|
self.fleetGroupName = fleetGroupName
|
||||||
o.logger = logger
|
self.logger = logger
|
||||||
|
|
||||||
local split_name = Util.split_string(fleetGroupName, "_")
|
local split_name = Util.split_string(fleetGroupName, "_")
|
||||||
if Util.tableLength(split_name) < 2 then
|
if Util.tableLength(split_name) < 2 then
|
||||||
MissionEditorWarning.Add("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>")
|
MissionEditorWarning.Add("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
o.fleetNameIdentifier = split_name[2]
|
self.fleetNameIdentifier = split_name[2]
|
||||||
|
|
||||||
o.targetZonePerStage = {}
|
self.targetZonePerStage = {}
|
||||||
o.currentTargetZone = nil
|
self.currentTargetZone = nil
|
||||||
o.pointsPerZone = {}
|
self.pointsPerZone = {}
|
||||||
|
|
||||||
do --INIT
|
do --INIT
|
||||||
local carrierRouteZones = database:getCarrierRouteZones()
|
local carrierRouteZones = database:getCarrierRouteZones()
|
||||||
for _, zoneName in pairs(carrierRouteZones) do
|
for _, zoneName in pairs(carrierRouteZones) do
|
||||||
if Util.strContains(string.lower(zoneName), "_".. string.lower(o.fleetNameIdentifier) .. "_" ) == true then
|
if Util.strContains(string.lower(zoneName), "_".. string.lower(self.fleetNameIdentifier) .. "_" ) == true then
|
||||||
local zone = DcsUtil.getZoneByName(zoneName)
|
local zone = DcsUtil.getZoneByName(zoneName)
|
||||||
if zone and zone.zone_type == DcsUtil.ZoneType.Polygon then
|
if zone and zone.zone_type == DcsUtil.ZoneType.Polygon then
|
||||||
local split_string = Util.split_string(zoneName, "_")
|
local split_string = Util.split_string(zoneName, "_")
|
||||||
@@ -43,18 +49,18 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
|||||||
"CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName)
|
"CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName)
|
||||||
else
|
else
|
||||||
|
|
||||||
---@param zone SpearheadTriggerZone
|
---@param zoneA SpearheadTriggerZone
|
||||||
---@return Vec2, Vec2
|
---@return Vec2, Vec2
|
||||||
local function GetTwoFurthestPoints(zone)
|
local function GetTwoFurthestPoints(zoneA)
|
||||||
|
|
||||||
local biggest = nil
|
local biggest = nil
|
||||||
local biggestA = zone.verts[1]
|
local biggestA = zoneA.verts[1]
|
||||||
local biggestB = zone.verts[2]
|
local biggestB = zoneA.verts[2]
|
||||||
|
|
||||||
for i = 1, 3 do
|
for i = 1, 3 do
|
||||||
for ii = i + 1, 4 do
|
for ii = i + 1, 4 do
|
||||||
local a = zone.verts[i]
|
local a = zoneA.verts[i]
|
||||||
local b = zone.verts[ii]
|
local b = zoneA.verts[ii]
|
||||||
local dist = Util.VectorDistance2d(a, b)
|
local dist = Util.VectorDistance2d(a, b)
|
||||||
|
|
||||||
if biggest == nil or dist > biggest then
|
if biggest == nil or dist > biggest then
|
||||||
@@ -100,9 +106,9 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
|||||||
local first, second = getMinMaxStage(split_string[3])
|
local first, second = getMinMaxStage(split_string[3])
|
||||||
if first ~= nil and second ~= nil then
|
if first ~= nil and second ~= nil then
|
||||||
for i = first, second do
|
for i = first, second do
|
||||||
o.targetZonePerStage[tostring(i)] = zoneName
|
self.targetZonePerStage[tostring(i)] = zoneName
|
||||||
end
|
end
|
||||||
o.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} }
|
self.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} }
|
||||||
else
|
else
|
||||||
MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
MissionEditorWarning.Add("CARRIERROUTE zone stage numbers not in the format _[<number>-<number>]: " .. zoneName)
|
||||||
end
|
end
|
||||||
@@ -114,32 +120,32 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local SetTaskAsync = function(input, time)
|
SpearheadEvents.AddStageNumberChangedListener(self)
|
||||||
local targetZone = input.targetZone
|
return self
|
||||||
local task = input.task
|
end
|
||||||
local groupName = input.groupName
|
|
||||||
local logger = input.logger
|
|
||||||
|
|
||||||
local group = Group.getByName(groupName)
|
local SetTaskAsync = function(input, _)
|
||||||
if group then
|
local targetZone = input.targetZone
|
||||||
logger:info("Sending " .. groupName .. " to " .. targetZone)
|
local task = input.task
|
||||||
group:getController():setTask(task)
|
local groupName = input.groupName
|
||||||
end
|
local l_logger = input.logger
|
||||||
|
|
||||||
|
local group = Group.getByName(groupName)
|
||||||
|
if group then
|
||||||
|
l_logger:info("Sending " .. groupName .. " to " .. targetZone)
|
||||||
|
group:getController():setTask(task)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
o.OnStageNumberChanged = function(self, number, laneIdentifier)
|
function FleetGroup:OnStageNumberChanged(number, laneIdentifier)
|
||||||
-- only react on "main" lane changes, ignore other lanes for now
|
-- only react on "main" lane changes, ignore other lanes for now
|
||||||
if laneIdentifier ~= nil then return end
|
if laneIdentifier ~= nil then return end
|
||||||
local targetZone = self.targetZonePerStage[tostring(number)]
|
local targetZone = self.targetZonePerStage[tostring(number)]
|
||||||
if targetZone and targetZone ~= self.currentTargetZone then
|
if targetZone and targetZone ~= self.currentTargetZone then
|
||||||
local points = self.pointsPerZone[targetZone]
|
local points = self.pointsPerZone[targetZone]
|
||||||
local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
|
local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
|
||||||
timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5)
|
timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
SpearheadEvents.AddStageNumberChangedListener(o)
|
|
||||||
return o
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return FleetGroup
|
return FleetGroup
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ GlobalFleetManager.start = function(database)
|
|||||||
for _, groupName in pairs(all_groups) do
|
for _, groupName in pairs(all_groups) do
|
||||||
if Util.startswith(string.lower(groupName), "carriergroup" ) == true then
|
if Util.startswith(string.lower(groupName), "carriergroup" ) == true then
|
||||||
logger:info("Registering " .. groupName .. " as a managed fleet")
|
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)
|
table.insert(fleetGroups, carrierGroup)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,14 +15,13 @@ MizGroupsManager._groupNames = {}
|
|||||||
MizGroupsManager._spawnTemplateData = {}
|
MizGroupsManager._spawnTemplateData = {}
|
||||||
|
|
||||||
do --init
|
do --init
|
||||||
for coalition_name, coalition_data in pairs(env.mission.coalition) do
|
for _, coalition_data in pairs(env.mission.coalition) do
|
||||||
local coalition_nr = DcsUtil.stringToCoalition(coalition_name)
|
|
||||||
if coalition_data.country then
|
if coalition_data.country then
|
||||||
for country_index, country_data in pairs(coalition_data.country) do
|
for _, country_data in pairs(coalition_data.country) do
|
||||||
for category_name, categorydata in pairs(country_data) do
|
for category_name, categorydata in pairs(country_data) do
|
||||||
local category_id = DcsUtil.stringToGroupCategory(category_name)
|
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
|
if category_id ~= nil and type(categorydata) == "table" and categorydata.group ~= nil and type(categorydata.group) == "table" then
|
||||||
for group_index, group in pairs(categorydata.group) do
|
for _, group in pairs(categorydata.group) do
|
||||||
local name = group.name
|
local name = group.name
|
||||||
local skippable = false
|
local skippable = false
|
||||||
local isStatic = false
|
local isStatic = false
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ end
|
|||||||
---@return StaticObject|Group|nil spawned
|
---@return StaticObject|Group|nil spawned
|
||||||
---@return boolean isStatic
|
---@return boolean isStatic
|
||||||
function SpawnManager:SpawnGroup(groupName, overrides, isGroupPersistant)
|
function SpawnManager:SpawnGroup(groupName, overrides, isGroupPersistant)
|
||||||
|
|
||||||
local spawnData = MizGroupsManager.getSpawnTemplateData(groupName)
|
local spawnData = MizGroupsManager.getSpawnTemplateData(groupName)
|
||||||
|
|
||||||
if spawnData == nil then
|
if spawnData == nil then
|
||||||
@@ -44,13 +44,13 @@ function SpawnManager:SpawnGroup(groupName, overrides, isGroupPersistant)
|
|||||||
if spawnData.isStatic == true then
|
if spawnData.isStatic == true then
|
||||||
return self:SpawnStaticInternal(groupName, spawnData, overrides, isGroupPersistant), true
|
return self:SpawnStaticInternal(groupName, spawnData, overrides, isGroupPersistant), true
|
||||||
else
|
else
|
||||||
return self:SpawnGroupInternal(groupName, spawnData, overrides, isGroupPersistant), false
|
return self:SpawnGroupInternal(spawnData, overrides, isGroupPersistant), false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function SpawnManager:DestroyGroup(groupName)
|
function SpawnManager:DestroyGroup(groupName)
|
||||||
if groupName == nil then return end
|
if groupName == nil then return end
|
||||||
|
|
||||||
if self:IsGroupStatic(groupName) == true then
|
if self:IsGroupStatic(groupName) == true then
|
||||||
local object = StaticObject.getByName(groupName)
|
local object = StaticObject.getByName(groupName)
|
||||||
if object ~= nil then
|
if object ~= nil then
|
||||||
@@ -103,20 +103,20 @@ function SpawnManager:OnUnitLost(object)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param groupName string
|
||||||
function SpawnManager:SpawnCorpsesOnly(groupName)
|
function SpawnManager:SpawnCorpsesOnly(groupName)
|
||||||
|
if groupName == nil then return end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do --- privates
|
do --- privates
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
---@param groupName string
|
|
||||||
---@param spawnData SpawnData
|
---@param spawnData SpawnData
|
||||||
---@param override SpawnOverrides?
|
---@param override SpawnOverrides?
|
||||||
---@param isPersistent boolean?
|
---@param isPersistent boolean?
|
||||||
---@return Group|nil
|
---@return Group|nil
|
||||||
function SpawnManager:SpawnGroupInternal(groupName, spawnData, override, isPersistent)
|
function SpawnManager:SpawnGroupInternal(spawnData, override, isPersistent)
|
||||||
|
|
||||||
if not spawnData then return end
|
if not spawnData then return end
|
||||||
|
|
||||||
local country = spawnData.country
|
local country = spawnData.country
|
||||||
@@ -181,7 +181,6 @@ do --- privates
|
|||||||
return group
|
return group
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ do
|
|||||||
else
|
else
|
||||||
logger:error("Could not load persistence file, using default tables")
|
logger:error("Could not load persistence file, using default tables")
|
||||||
end
|
end
|
||||||
|
|
||||||
if tables.version == nil then tables.version = version end
|
if tables.version == nil then tables.version = version end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -112,9 +112,9 @@ do
|
|||||||
logger:info("Wrote persistence data to file")
|
logger:info("Wrote persistence data to file")
|
||||||
end
|
end
|
||||||
|
|
||||||
local UpdateContinuous = function(null, time)
|
local UpdateContinuous = function(_, time)
|
||||||
env.info("[Spearhead][Persistence] Checking up on persistence state...")
|
env.info("[Spearhead][Persistence] Checking up on persistence state...")
|
||||||
if Persistence._updateRequired == true then
|
if Persistence._updateRequired == true then
|
||||||
local status, result = pcall(writeToFile)
|
local status, result = pcall(writeToFile)
|
||||||
if status == false then
|
if status == false then
|
||||||
env.error("[Spearhead][Persistence] Could not write state to file: " .. result)
|
env.error("[Spearhead][Persistence] Could not write state to file: " .. result)
|
||||||
@@ -135,7 +135,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local warnForNonPersistenceContinous = function(null, time)
|
local warnForNonPersistenceContinous = function(_, 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)
|
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
|
return time + 9
|
||||||
end
|
end
|
||||||
@@ -194,7 +194,7 @@ do
|
|||||||
split[#split+1] = "0"
|
split[#split+1] = "0"
|
||||||
split[#split+1] = "spearhead"
|
split[#split+1] = "spearhead"
|
||||||
end
|
end
|
||||||
|
|
||||||
fileName = table.concat(split, ".")
|
fileName = table.concat(split, ".")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -218,12 +218,12 @@ do
|
|||||||
logger:info("No previous persistence file found, using default: " .. fileName)
|
logger:info("No previous persistence file found, using default: " .. fileName)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
logger:info("New Persistence file name: " .. tostring(fileName))
|
logger:info("New Persistence file name: " .. tostring(fileName))
|
||||||
local lastPath = dir .. "\\" .. lastFile
|
local lastPath = dir .. "\\" .. lastFile
|
||||||
local path = dir .. "\\" .. fileName
|
local path = dir .. "\\" .. fileName
|
||||||
Persistence._path = path
|
Persistence._path = path
|
||||||
|
|
||||||
createFileIfNotExists(path)
|
createFileIfNotExists(path)
|
||||||
loadTablesFromFile(lastPath)
|
loadTablesFromFile(lastPath)
|
||||||
timer.scheduleFunction(UpdateContinuous, nil, timer.getTime() + 120)
|
timer.scheduleFunction(UpdateContinuous, nil, timer.getTime() + 120)
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ function Database.New(Logger)
|
|||||||
self._logger:debug("Initiating tables")
|
self._logger:debug("Initiating tables")
|
||||||
|
|
||||||
do -- INIT ZONE TABLES
|
do -- INIT ZONE TABLES
|
||||||
for zone_ind, zone_data in pairs(DcsUtil.__trigger_zones) do
|
for _, zone_data in pairs(DcsUtil.__trigger_zones) do
|
||||||
local zone_name = zone_data.name
|
local zone_name = zone_data.name
|
||||||
|
|
||||||
---@type Vec2
|
---@type Vec2
|
||||||
@@ -208,9 +208,9 @@ function Database.New(Logger)
|
|||||||
self._logger:debug("initiated zone tables, continuing with descriptions")
|
self._logger:debug("initiated zone tables, continuing with descriptions")
|
||||||
do --load markers
|
do --load markers
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startswith(string.lower(layer_object.name), "buildable", true) == true then
|
if Util.startswith(string.lower(layer_object.name), "buildable", true) == true then
|
||||||
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
|
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
|
||||||
if airbaseData then
|
if airbaseData then
|
||||||
@@ -228,9 +228,9 @@ function Database.New(Logger)
|
|||||||
---@type table<integer, boolean>
|
---@type table<integer, boolean>
|
||||||
do -- custom drawings
|
do -- custom drawings
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startswith(layer_object.name, "drawing_", true) then
|
if Util.startswith(layer_object.name, "drawing_", true) then
|
||||||
local object = layer_object --[[@as DrawingObject]]
|
local object = layer_object --[[@as DrawingObject]]
|
||||||
local stageDrawing = StageDrawing.New(object)
|
local stageDrawing = StageDrawing.New(object)
|
||||||
@@ -256,9 +256,9 @@ function Database.New(Logger)
|
|||||||
|
|
||||||
-- Find and add Briefing
|
-- Find and add Briefing
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
if Util.startswith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
||||||
local zone = DcsUtil.getZoneByName(stageZoneName)
|
local zone = DcsUtil.getZoneByName(stageZoneName)
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
@@ -339,14 +339,14 @@ function Database.New(Logger)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- fill missions
|
-- fill missions
|
||||||
for key, missionZone in pairs(self._tables.MissionZones) do
|
for _, missionZone in pairs(self._tables.MissionZones) do
|
||||||
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||||
table.insert(stageData.MissionZones, missionZone)
|
table.insert(stageData.MissionZones, missionZone)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- fill random missions
|
-- fill random missions
|
||||||
for key, missionZone in pairs(self._tables.RandomMissionZones) do
|
for _, missionZone in pairs(self._tables.RandomMissionZones) do
|
||||||
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||||
table.insert(stageData.RandomMissionZones, missionZone)
|
table.insert(stageData.RandomMissionZones, missionZone)
|
||||||
end
|
end
|
||||||
@@ -620,9 +620,9 @@ function Database:loadBlueSamUnits()
|
|||||||
samData.buildingKilos = number
|
samData.buildingKilos = number
|
||||||
|
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
|
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
@@ -637,7 +637,7 @@ function Database:loadBlueSamUnits()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
MissionEditorWarnings.Add("Buildable number for " .. blueSamZone .. " is invalid")
|
MissionEditorWarnings.Add("Buildable number for " .. blueSamZone .. " is invalid")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -670,13 +670,13 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
for _, groupName in pairs(groups) do
|
for _, groupName in pairs(groups) do
|
||||||
if MizGroupsManager.IsGroupStatic(groupName) == true then
|
if MizGroupsManager.IsGroupStatic(groupName) == true then
|
||||||
local object = StaticObject.getByName(groupName)
|
local object = StaticObject.getByName(groupName)
|
||||||
|
|
||||||
if object and object:getCoalition() == coalition.side.RED then
|
if object and object:getCoalition() == coalition.side.RED then
|
||||||
table.insert(self._tables.MissionZoneData[missionZoneName].RedGroups, groupName)
|
table.insert(self._tables.MissionZoneData[missionZoneName].RedGroups, groupName)
|
||||||
elseif object then
|
elseif object then
|
||||||
table.insert(self._tables.MissionZoneData[missionZoneName].BlueGroups, groupName)
|
table.insert(self._tables.MissionZoneData[missionZoneName].BlueGroups, groupName)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
local group = Group.getByName(groupName)
|
local group = Group.getByName(groupName)
|
||||||
if group and group:getCoalition() == coalition.side.RED then
|
if group and group:getCoalition() == coalition.side.RED then
|
||||||
@@ -720,9 +720,9 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
|
|
||||||
---Adds Briefings
|
---Adds Briefings
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
|
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
@@ -776,9 +776,9 @@ function Database:loadFarpData()
|
|||||||
|
|
||||||
-- check briefings
|
-- check briefings
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
|
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
@@ -796,8 +796,6 @@ function Database:loadFarpData()
|
|||||||
else
|
else
|
||||||
MissionEditorWarnings.Add("Buildable number for " .. farpZone .. " is invalid.")
|
MissionEditorWarnings.Add("Buildable number for " .. farpZone .. " is invalid.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ do
|
|||||||
|
|
||||||
---@class OnStageNumberChangeCompleteListener
|
---@class OnStageNumberChangeCompleteListener
|
||||||
---@field OnStageNumberChangeComplete fun(self:OnStageNumberChangeCompleteListener, number:integer, laneIdentifier:string?)
|
---@field OnStageNumberChangeComplete fun(self:OnStageNumberChangeCompleteListener, number:integer, laneIdentifier:string?)
|
||||||
|
|
||||||
local OnStageNumberChangeCompleteListeners = {}
|
local OnStageNumberChangeCompleteListeners = {}
|
||||||
---@param listener OnStageNumberChangeCompleteListener
|
---@param listener OnStageNumberChangeCompleteListener
|
||||||
SpearheadEvents.AddStageNumberChangeCompleteListener = function(listener)
|
SpearheadEvents.AddStageNumberChangeCompleteListener = function(listener)
|
||||||
@@ -65,7 +65,7 @@ do
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
for _, callable in pairs(OnStageNumberChangedListeners) do
|
for _, callable in pairs(OnStageNumberChangedListeners) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnStageNumberChanged(newStageNumber, laneIdentifier)
|
callable:OnStageNumberChanged(newStageNumber, laneIdentifier)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -74,14 +74,14 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, callable in pairs(OnStageNumberChangedHandlers) do
|
for _, callable in pairs(OnStageNumberChangedHandlers) do
|
||||||
local succ, err = pcall(callable, newStageNumber, laneIdentifier)
|
local _, err = pcall(callable, newStageNumber, laneIdentifier)
|
||||||
if err then
|
if err then
|
||||||
logError(err)
|
logError(err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, callable in pairs(OnStageNumberChangeCompleteListeners) do
|
for _, callable in pairs(OnStageNumberChangeCompleteListeners) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnStageNumberChangeComplete(newStageNumber, laneIdentifier)
|
callable:OnStageNumberChangeComplete(newStageNumber, laneIdentifier)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -112,7 +112,7 @@ do
|
|||||||
|
|
||||||
local triggerWeaponFired = function(unit, weapon, target)
|
local triggerWeaponFired = function(unit, weapon, target)
|
||||||
for _, callable in pairs(onWeaponFiredListeners) do
|
for _, callable in pairs(onWeaponFiredListeners) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnWeaponFired(unit, weapon, target)
|
callable:OnWeaponFired(unit, weapon, target)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local onLandEventListeners = {}
|
local onLandEventListeners = {}
|
||||||
---Add an event listener to a specific unit
|
---Add an event listener to a specific unit
|
||||||
@@ -186,7 +186,7 @@ do
|
|||||||
if groupName ~= nil then
|
if groupName ~= nil then
|
||||||
if OnGroupRTBListeners[groupName] then
|
if OnGroupRTBListeners[groupName] then
|
||||||
for _, callable in pairs(OnGroupRTBListeners[groupName]) do
|
for _, callable in pairs(OnGroupRTBListeners[groupName]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnGroupRTB(groupName)
|
callable:OnGroupRTB(groupName)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -221,7 +221,7 @@ do
|
|||||||
if groupName ~= nil then
|
if groupName ~= nil then
|
||||||
if OnGroupRTBInTenListeners[groupName] then
|
if OnGroupRTBInTenListeners[groupName] then
|
||||||
for _, callable in pairs(OnGroupRTBInTenListeners[groupName]) do
|
for _, callable in pairs(OnGroupRTBInTenListeners[groupName]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnGroupRTBInTen(groupName)
|
callable:OnGroupRTBInTen(groupName)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -257,7 +257,7 @@ do
|
|||||||
if groupName ~= nil then
|
if groupName ~= nil then
|
||||||
if OnGroupOnStationListeners[groupName] then
|
if OnGroupOnStationListeners[groupName] then
|
||||||
for _, callable in pairs(OnGroupOnStationListeners[groupName]) do
|
for _, callable in pairs(OnGroupOnStationListeners[groupName]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnGroupOnStation(groupName)
|
callable:OnGroupOnStation(groupName)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -286,7 +286,7 @@ do
|
|||||||
if unit ~= nil then
|
if unit ~= nil then
|
||||||
if playerEnterUnitListeners then
|
if playerEnterUnitListeners then
|
||||||
for _, callable in pairs(playerEnterUnitListeners) do
|
for _, callable in pairs(playerEnterUnitListeners) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnPlayerEntersUnit(unit)
|
callable:OnPlayerEntersUnit(unit)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -299,7 +299,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- Ejection events
|
do -- Ejection events
|
||||||
|
|
||||||
local unitEjectListeners = {}
|
local unitEjectListeners = {}
|
||||||
SpearheadEvents.AddOnUnitEjectedListener = function(listener)
|
SpearheadEvents.AddOnUnitEjectedListener = function(listener)
|
||||||
if type(listener) ~= "table" then
|
if type(listener) ~= "table" then
|
||||||
@@ -321,7 +321,7 @@ do
|
|||||||
local name = unit:getName()
|
local name = unit:getName()
|
||||||
if onLandEventListeners[name] then
|
if onLandEventListeners[name] then
|
||||||
for _, callable in pairs(onLandEventListeners[name]) do
|
for _, callable in pairs(onLandEventListeners[name]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnUnitLanded(unit, airbase)
|
callable:OnUnitLanded(unit, airbase)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -341,10 +341,10 @@ do
|
|||||||
if object and object.getName then
|
if object and object.getName then
|
||||||
logDebug("Receiving death event from: " .. object:getName())
|
logDebug("Receiving death event from: " .. object:getName())
|
||||||
end
|
end
|
||||||
|
|
||||||
if object and object.getName and OnUnitLostListeners[object:getName()] then
|
if object and object.getName and OnUnitLostListeners[object:getName()] then
|
||||||
for _, callable in pairs(OnUnitLostListeners[object:getName()]) do
|
for _, callable in pairs(OnUnitLostListeners[object:getName()]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnUnitLost(object)
|
callable:OnUnitLost(object)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -356,11 +356,11 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
if event.id == world.event.S_EVENT_EJECTION then
|
if event.id == world.event.S_EVENT_EJECTION then
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if event.id == world.event.S_EVENT_SHOT then
|
if event.id == world.event.S_EVENT_SHOT then
|
||||||
|
|
||||||
local shooter = event.initiator
|
local shooter = event.initiator
|
||||||
local weapon = event.weapon
|
local weapon = event.weapon
|
||||||
local target = event.target
|
local target = event.target
|
||||||
@@ -374,26 +374,26 @@ do
|
|||||||
|
|
||||||
local AI_GROUPS = {}
|
local AI_GROUPS = {}
|
||||||
|
|
||||||
local function CheckAndTriggerSpawnAsync(unit, time)
|
local function CheckAndTriggerSpawnAsync(unit, _)
|
||||||
|
|
||||||
local function isPlayer(unit)
|
local function isPlayer(checkUnit)
|
||||||
if unit == nil then return false, "unit is nil" end
|
if checkUnit == 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 checkUnit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end
|
||||||
if Object.getCategory(unit) ~= Object.Category.UNIT then
|
if Object.getCategory(checkUnit) ~= Object.Category.UNIT then
|
||||||
return false, "object is not a unit"
|
return false, "object is not a unit"
|
||||||
end
|
end
|
||||||
|
|
||||||
if unit:isExist() ~= true then return false, "unit does not exist" end
|
if checkUnit:isExist() ~= true then return false, "unit does not exist" end
|
||||||
local group = unit:getGroup()
|
local group = checkUnit:getGroup()
|
||||||
if group ~= nil then
|
if group ~= nil then
|
||||||
if AI_GROUPS[group:getName()] == true then
|
if AI_GROUPS[group:getName()] == true then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local players = DcsUtil.getAllPlayerUnits()
|
local players = DcsUtil.getAllPlayerUnits()
|
||||||
local unitName = unit:getName()
|
local unitName = checkUnit:getName()
|
||||||
for i, unit in pairs(players) do
|
for _, playerUnit in pairs(players) do
|
||||||
if unit:getName() == unitName then
|
if playerUnit:getName() == unitName then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -403,7 +403,6 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
if isPlayer(unit) == true then
|
if isPlayer(unit) == true then
|
||||||
local groupId = unit:getGroup():getID()
|
|
||||||
SpearheadEvents.TriggerPlayerEntersUnit(unit)
|
SpearheadEvents.TriggerPlayerEntersUnit(unit)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ local Events = require("classes.spearhead_events")
|
|||||||
local Util = require("classes.util.Util")
|
local Util = require("classes.util.Util")
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
local DcsUtil = require("classes.util.DcsUtil")
|
||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
|
||||||
local PersistenceConfig = require("classes.configuration.PersistenceConfig")
|
local PersistenceConfig = require("classes.configuration.PersistenceConfig")
|
||||||
local ExtraStage = require("classes.stageClasses.Stages.ExtraStage")
|
local ExtraStage = require("classes.stageClasses.Stages.ExtraStage")
|
||||||
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
|
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
|
||||||
@@ -35,7 +34,6 @@ local singletonInstance = nil
|
|||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
---@return GlobalStageManager
|
---@return GlobalStageManager
|
||||||
function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
||||||
|
|
||||||
if singletonInstance ~= nil then
|
if singletonInstance ~= nil then
|
||||||
return singletonInstance
|
return singletonInstance
|
||||||
end
|
end
|
||||||
@@ -44,7 +42,7 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
|||||||
logger:info("Using Stage Log Level: " .. logLevel)
|
logger:info("Using Stage Log Level: " .. logLevel)
|
||||||
local self = setmetatable({}, GlobalStageManager)
|
local self = setmetatable({}, GlobalStageManager)
|
||||||
singletonInstance = self
|
singletonInstance = self
|
||||||
|
|
||||||
self.database = database
|
self.database = database
|
||||||
self.stageConfig = stageConfig
|
self.stageConfig = stageConfig
|
||||||
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate()
|
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate()
|
||||||
@@ -52,14 +50,15 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
|||||||
|
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
if stageConfig.isAutoStages ~= true then
|
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
|
end
|
||||||
|
|
||||||
Events.AddStageNumberChangedListener(self)
|
Events.AddStageNumberChangedListener(self)
|
||||||
|
|
||||||
for _, stageName in pairs(database:getStagezoneNames()) do
|
for _, stageName in pairs(database:getStagezoneNames()) do
|
||||||
logger:debug("Found stage zone with name: " .. stageName)
|
logger:debug("Found stage zone with name: " .. stageName)
|
||||||
|
|
||||||
local parseResult = self:ParseStageName(stageName)
|
local parseResult = self:ParseStageName(stageName)
|
||||||
if parseResult.isValid == false then
|
if parseResult.isValid == false then
|
||||||
logger:warn("Stage zone with name " .. stageName .. " is not valid: " .. parseResult.invalidReason)
|
logger:warn("Stage zone with name " .. stageName .. " is not valid: " .. parseResult.invalidReason)
|
||||||
@@ -81,12 +80,12 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
|||||||
stage:AddStageCompleteListener(self)
|
stage:AddStageCompleteListener(self)
|
||||||
self._stageRepository:AddStage(stage)
|
self._stageRepository:AddStage(stage)
|
||||||
elseif parseResult.stageType == "WaitingStage" then
|
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)
|
waitingStage:AddStageCompleteListener(self)
|
||||||
self._stageRepository:AddStage(waitingStage)
|
self._stageRepository:AddStage(waitingStage)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
singletonInstance = self
|
singletonInstance = self
|
||||||
@@ -103,11 +102,11 @@ function GlobalStageManager:Start()
|
|||||||
|
|
||||||
local stageLanes = self._stageRepository:getAllStageLanes()
|
local stageLanes = self._stageRepository:getAllStageLanes()
|
||||||
for _, stageLane in pairs(stageLanes) do
|
for _, stageLane in pairs(stageLanes) do
|
||||||
|
|
||||||
local stageLaneIdentifier = stageLane:GetStageLaneIdentifier()
|
local stageLaneIdentifier = stageLane:GetStageLaneIdentifier()
|
||||||
local persistedStage = Persistence.GetActiveStage(stageLaneIdentifier)
|
local persistedStage = Persistence.GetActiveStage(stageLaneIdentifier)
|
||||||
if persistedStage then
|
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)
|
stageLane:SetActiveStageIndex(persistedStage)
|
||||||
Events.PublishStageNumberChanged(persistedStage, stageLaneIdentifier)
|
Events.PublishStageNumberChanged(persistedStage, stageLaneIdentifier)
|
||||||
else
|
else
|
||||||
@@ -139,17 +138,16 @@ end
|
|||||||
---@param stageName string
|
---@param stageName string
|
||||||
---@return StageNameParseResult
|
---@return StageNameParseResult
|
||||||
function GlobalStageManager:ParseStageName(stageName)
|
function GlobalStageManager:ParseStageName(stageName)
|
||||||
|
|
||||||
local split = Util.split_string(stageName, "_")
|
local split = Util.split_string(stageName, "_")
|
||||||
|
|
||||||
if Util.tableLength(split) < 3 then
|
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
|
end
|
||||||
|
|
||||||
local typePart = string.lower(split[1])
|
local typePart = string.lower(split[1])
|
||||||
|
|
||||||
if typePart == "missionstage" then
|
if typePart == "missionstage" then
|
||||||
|
|
||||||
local orderNumberString = string.lower(split[2])
|
local orderNumberString = string.lower(split[2])
|
||||||
---@type StageType
|
---@type StageType
|
||||||
local stageType = "PrimaryStage"
|
local stageType = "PrimaryStage"
|
||||||
@@ -161,15 +159,16 @@ function GlobalStageManager:ParseStageName(stageName)
|
|||||||
local first = orderNumberString:sub(1, 1)
|
local first = orderNumberString:sub(1, 1)
|
||||||
if tonumber(first) == nil then -- first character is the lane identifier only if it's not a number
|
if tonumber(first) == nil then -- first character is the lane identifier only if it's not a number
|
||||||
stageLaneIdentifier = string.lower(first)
|
stageLaneIdentifier = string.lower(first)
|
||||||
|
|
||||||
orderNumberString = orderNumberString:sub(2)
|
orderNumberString = orderNumberString:sub(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local orderNumber = tonumber(orderNumberString)
|
local orderNumber = tonumber(orderNumberString)
|
||||||
if orderNumber == nil then
|
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
|
end
|
||||||
|
|
||||||
local stageDisplayName = split[3]
|
local stageDisplayName = split[3]
|
||||||
---@type StageNameParseResult
|
---@type StageNameParseResult
|
||||||
local result = {
|
local result = {
|
||||||
@@ -182,18 +181,19 @@ function GlobalStageManager:ParseStageName(stageName)
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
elseif typePart == "waitingstage" then
|
elseif typePart == "waitingstage" then
|
||||||
|
|
||||||
local stageType = "WaitingStage"
|
local stageType = "WaitingStage"
|
||||||
local orderNumberString = split[2]
|
local orderNumberString = split[2]
|
||||||
local orderNumber = tonumber(orderNumberString)
|
local orderNumber = tonumber(orderNumberString)
|
||||||
if orderNumber == nil then
|
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
|
end
|
||||||
|
|
||||||
local waitingSecondsString = split[3]
|
local waitingSecondsString = split[3]
|
||||||
local waitingSeconds = tonumber(waitingSecondsString)
|
local waitingSeconds = tonumber(waitingSecondsString)
|
||||||
if waitingSeconds == nil then
|
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
|
end
|
||||||
|
|
||||||
local stageDisplayName = "Waiting Stage " .. orderNumber
|
local stageDisplayName = "Waiting Stage " .. orderNumber
|
||||||
@@ -209,9 +209,9 @@ function GlobalStageManager:ParseStageName(stageName)
|
|||||||
waitingStageSeconds = waitingSeconds
|
waitingStageSeconds = waitingSeconds
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
---@param stage Stage
|
---@param stage Stage
|
||||||
@@ -223,7 +223,8 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
|
|
||||||
local stageLane = self._stageRepository:getStageLane(laneIdentifier)
|
local stageLane = self._stageRepository:getStageLane(laneIdentifier)
|
||||||
if not stageLane or not stageLane:IsCurrentStageIndexComplete() then
|
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
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -234,7 +235,7 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
stageLane:SetActiveStageIndex(nextStageIndex)
|
stageLane:SetActiveStageIndex(nextStageIndex)
|
||||||
|
|
||||||
if stageLane:IsDefaultStageLane() then
|
if stageLane:IsDefaultStageLane() then
|
||||||
-- COMPLETION IN THE DEFAULT LANE
|
-- COMPLETION IN THE DEFAULT LANE
|
||||||
|
|
||||||
-- 1. Check if any lane is at status "BetweenChapters" and the next chapter start is "next stage index"
|
-- 1. Check if any lane is at status "BetweenChapters" and the next chapter start is "next stage index"
|
||||||
local allLanes = self._stageRepository:getAllStageLanes()
|
local allLanes = self._stageRepository:getAllStageLanes()
|
||||||
@@ -242,7 +243,9 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey and lane:GetStageLaneState() == "BetweenChapters" then
|
if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey and lane:GetStageLaneState() == "BetweenChapters" then
|
||||||
local nextChapterStart = lane:GetNextChapterStart()
|
local nextChapterStart = lane:GetNextChapterStart()
|
||||||
if nextChapterStart == nextStageIndex then
|
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())
|
Events.PublishStageNumberChanged(nextStageIndex, lane:GetStageLaneIdentifier())
|
||||||
lane:SetActiveStageIndex(nextStageIndex)
|
lane:SetActiveStageIndex(nextStageIndex)
|
||||||
end
|
end
|
||||||
@@ -256,7 +259,6 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
if defaultStageLane and defaultStageLane:GetStageLaneState() == "BetweenChapters" then
|
if defaultStageLane and defaultStageLane:GetStageLaneState() == "BetweenChapters" then
|
||||||
local nextChapterStart = defaultStageLane:GetNextChapterStart()
|
local nextChapterStart = defaultStageLane:GetNextChapterStart()
|
||||||
if nextChapterStart == nextStageIndex then
|
if nextChapterStart == nextStageIndex then
|
||||||
|
|
||||||
-- 2. Check if all side lanes are at or beyond the next chapter starts
|
-- 2. Check if all side lanes are at or beyond the next chapter starts
|
||||||
local allLanes = self._stageRepository:getAllStageLanes()
|
local allLanes = self._stageRepository:getAllStageLanes()
|
||||||
local allSideLanesReady = true
|
local allSideLanesReady = true
|
||||||
@@ -265,15 +267,19 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
-- Check if the lane is at or beyond the next chapter starts when "InChapter" eq "Active"
|
-- 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
|
if lane:GetStageLaneState() == "InChapter" and lane:GetActiveStageIndex() < nextStageIndex then
|
||||||
allSideLanesReady = false
|
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
|
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
|
elseif lane:GetStageLaneState() == "BetweenChapters" then
|
||||||
local nextChapter = lane:GetNextChapterStart()
|
local nextChapter = lane:GetNextChapterStart()
|
||||||
if nextChapter and nextChapter < nextStageIndex then
|
if nextChapter and nextChapter < nextStageIndex then
|
||||||
allSideLanesReady = false
|
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
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -281,13 +287,14 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if allSideLanesReady then
|
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)
|
Events.PublishStageNumberChanged(nextStageIndex, nil)
|
||||||
defaultStageLane:SetActiveStageIndex(nextStageIndex)
|
defaultStageLane:SetActiveStageIndex(nextStageIndex)
|
||||||
else
|
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -308,7 +315,6 @@ end
|
|||||||
|
|
||||||
---@public
|
---@public
|
||||||
function GlobalStageManager:OnStageNumberChanged(stageNumber, stageLaneIdentifier)
|
function GlobalStageManager:OnStageNumberChanged(stageNumber, stageLaneIdentifier)
|
||||||
|
|
||||||
-- only react on "main" lane changes, ignore other lanes for now
|
-- only react on "main" lane changes, ignore other lanes for now
|
||||||
if stageLaneIdentifier ~= nil then return end
|
if stageLaneIdentifier ~= nil then return end
|
||||||
|
|
||||||
@@ -321,7 +327,6 @@ function GlobalStageManager:OnStageNumberChangeComplete(stageNumber, stageLaneId
|
|||||||
if stageLaneIdentifier ~= nil then return end
|
if stageLaneIdentifier ~= nil then return end
|
||||||
|
|
||||||
self.logger:debug("Stage number change complete to: " .. tostring(stageNumber))
|
self.logger:debug("Stage number change complete to: " .. tostring(stageNumber))
|
||||||
|
|
||||||
local groups = {}
|
local groups = {}
|
||||||
|
|
||||||
for _, player in pairs(DcsUtil.getAllPlayerUnits()) do
|
for _, player in pairs(DcsUtil.getAllPlayerUnits()) do
|
||||||
@@ -349,80 +354,81 @@ function GlobalStageManager:UpdateDrawings(stageNumber, stageLaneIdentifier)
|
|||||||
|
|
||||||
if laneIdentifier == stageLaneIdentifier then
|
if laneIdentifier == stageLaneIdentifier then
|
||||||
if stageNumber >= startStage and stageNumber < stopStage 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()
|
drawing:Draw()
|
||||||
else
|
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()
|
drawing:Remove()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function GlobalStageManager:PrintMermaidStage()
|
function GlobalStageManager:PrintMermaidStage()
|
||||||
local lanes = self._stageRepository:getAllStageLanes()
|
local lanes = self._stageRepository:getAllStageLanes()
|
||||||
|
|
||||||
local nodes = {}
|
local nodes = {}
|
||||||
local edges = {}
|
local edges = {}
|
||||||
local stageIndicesByLane = {} -- Track all stage indices per lane
|
local stageIndicesByLane = {} -- Track all stage indices per lane
|
||||||
local mainLaneId = "default"
|
local mainLaneId = "default"
|
||||||
|
|
||||||
-- Color palette for lanes (26 vibrant colors optimized for dark mode)
|
-- Color palette for lanes (26 vibrant colors optimized for dark mode)
|
||||||
local laneColors = {
|
local laneColors = {
|
||||||
"#FF6B6B", -- 1: Red
|
"#FF6B6B", -- 1: Red
|
||||||
"#4ECDC4", -- 2: Teal
|
"#4ECDC4", -- 2: Teal
|
||||||
"#45B7D1", -- 3: Blue
|
"#45B7D1", -- 3: Blue
|
||||||
"#FFA502", -- 4: Orange
|
"#FFA502", -- 4: Orange
|
||||||
"#95E1D3", -- 5: Mint
|
"#95E1D3", -- 5: Mint
|
||||||
"#F38181", -- 6: Coral
|
"#F38181", -- 6: Coral
|
||||||
"#AA96DA", -- 7: Purple
|
"#AA96DA", -- 7: Purple
|
||||||
"#FCBAD3", -- 8: Pink
|
"#FCBAD3", -- 8: Pink
|
||||||
"#A8E6CF", -- 9: Light green
|
"#A8E6CF", -- 9: Light green
|
||||||
"#FFD3B6", -- 10: Peach
|
"#FFD3B6", -- 10: Peach
|
||||||
"#FFAAA5", -- 11: Light red
|
"#FFAAA5", -- 11: Light red
|
||||||
"#FF8B94", -- 12: Rose
|
"#FF8B94", -- 12: Rose
|
||||||
"#FFEAA7", -- 13: Butter
|
"#FFEAA7", -- 13: Butter
|
||||||
"#DFE6E9", -- 14: Gray
|
"#DFE6E9", -- 14: Gray
|
||||||
"#00B894", -- 15: Emerald
|
"#00B894", -- 15: Emerald
|
||||||
"#0984E3", -- 16: Cobalt
|
"#0984E3", -- 16: Cobalt
|
||||||
"#6C5CE7", -- 17: Indigo
|
"#6C5CE7", -- 17: Indigo
|
||||||
"#A29BFE", -- 18: Lavender
|
"#A29BFE", -- 18: Lavender
|
||||||
"#FD79A8", -- 19: Magenta
|
"#FD79A8", -- 19: Magenta
|
||||||
"#FDCB6E", -- 20: Gold
|
"#FDCB6E", -- 20: Gold
|
||||||
"#6C757D", -- 21: Slate
|
"#6C757D", -- 21: Slate
|
||||||
"#20C997", -- 22: Seafoam
|
"#20C997", -- 22: Seafoam
|
||||||
"#E74C3C", -- 23: Scarlet
|
"#E74C3C", -- 23: Scarlet
|
||||||
"#3498DB", -- 24: Dodger blue
|
"#3498DB", -- 24: Dodger blue
|
||||||
"#9B59B6", -- 25: Amethyst
|
"#9B59B6", -- 25: Amethyst
|
||||||
"#1ABC9C", -- 26: Turquoise
|
"#1ABC9C", -- 26: Turquoise
|
||||||
}
|
}
|
||||||
local laneColorMap = {} -- Map lane ID to color
|
local laneColorMap = {} -- Map lane ID to color
|
||||||
local colorIndex = 1
|
local colorIndex = 1
|
||||||
|
|
||||||
-- Build nodes and collect all stage indices per lane
|
-- Build nodes and collect all stage indices per lane
|
||||||
for _, lane in ipairs(lanes) do
|
for _, lane in ipairs(lanes) do
|
||||||
local laneId = lane:GetStageLaneIdentifier() or "default"
|
local laneId = lane:GetStageLaneIdentifier() or "default"
|
||||||
local stageIndices = lane:GetAllStageIndices()
|
local stageIndices = lane:GetAllStageIndices()
|
||||||
stageIndicesByLane[laneId] = stageIndices
|
stageIndicesByLane[laneId] = stageIndices
|
||||||
|
|
||||||
-- Assign color to this lane
|
-- Assign color to this lane
|
||||||
laneColorMap[laneId] = laneColors[colorIndex]
|
laneColorMap[laneId] = laneColors[colorIndex]
|
||||||
colorIndex = colorIndex + 1
|
colorIndex = colorIndex + 1
|
||||||
if colorIndex > #laneColors then
|
if colorIndex > #laneColors then
|
||||||
colorIndex = 1
|
colorIndex = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create nodes for each stage index in this lane
|
-- Create nodes for each stage index in this lane
|
||||||
for _, stageIndex in ipairs(stageIndices) do
|
for _, stageIndex in ipairs(stageIndices) do
|
||||||
local stages = lane:GetStagesAtIndex(stageIndex)
|
local stages = lane:GetStagesAtIndex(stageIndex)
|
||||||
|
|
||||||
if stages then
|
if stages then
|
||||||
for _, stage in ipairs(stages) do
|
for _, stage in ipairs(stages) do
|
||||||
local nodeId = laneId .. "_" .. stageIndex
|
local nodeId = laneId .. "_" .. stageIndex
|
||||||
local stageType = stage:GetStageType()
|
local stageType = stage:GetStageType()
|
||||||
local stageName = stage.stageName or stage.zoneName
|
local stageName = stage.stageName or stage.zoneName
|
||||||
|
|
||||||
-- Generate bracket label: [1], [2] for default, [w1], [e2] for other lanes
|
-- Generate bracket label: [1], [2] for default, [w1], [e2] for other lanes
|
||||||
local bracketLabel
|
local bracketLabel
|
||||||
if laneId == "default" then
|
if laneId == "default" then
|
||||||
@@ -430,10 +436,10 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
else
|
else
|
||||||
bracketLabel = "[" .. laneId .. stageIndex .. "]"
|
bracketLabel = "[" .. laneId .. stageIndex .. "]"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Combined label: [bracket] Name
|
-- Combined label: [bracket] Name
|
||||||
local label = bracketLabel .. " " .. stageName
|
local label = bracketLabel .. " " .. stageName
|
||||||
|
|
||||||
-- Different node shapes for different stage types
|
-- Different node shapes for different stage types
|
||||||
local nodeShape = "["
|
local nodeShape = "["
|
||||||
local nodeEnd = "]"
|
local nodeEnd = "]"
|
||||||
@@ -444,14 +450,14 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
nodeShape = "[["
|
nodeShape = "[["
|
||||||
nodeEnd = "]]"
|
nodeEnd = "]]"
|
||||||
end
|
end
|
||||||
|
|
||||||
nodes[nodeId] = string.format(' %s%s"%s"%s',
|
nodes[nodeId] = string.format(' %s%s"%s"%s',
|
||||||
nodeId, nodeShape, label, nodeEnd)
|
nodeId, nodeShape, label, nodeEnd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add edges for sequential stages within the same lane
|
-- Add edges for sequential stages within the same lane
|
||||||
for laneId, stageIndices in pairs(stageIndicesByLane) do
|
for laneId, stageIndices in pairs(stageIndicesByLane) do
|
||||||
for i = 1, #stageIndices - 1 do
|
for i = 1, #stageIndices - 1 do
|
||||||
@@ -459,7 +465,7 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
local toIdx = stageIndices[i + 1]
|
local toIdx = stageIndices[i + 1]
|
||||||
local fromNodeId = laneId .. "_" .. fromIdx
|
local fromNodeId = laneId .. "_" .. fromIdx
|
||||||
local toNodeId = laneId .. "_" .. toIdx
|
local toNodeId = laneId .. "_" .. toIdx
|
||||||
|
|
||||||
-- Check if this is a chapter boundary (gap)
|
-- Check if this is a chapter boundary (gap)
|
||||||
local isChapter = false
|
local isChapter = false
|
||||||
for _, lane in ipairs(lanes) do
|
for _, lane in ipairs(lanes) do
|
||||||
@@ -469,12 +475,12 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local label = isChapter and "|chapter|" or ""
|
local label = isChapter and "|chapter|" or ""
|
||||||
table.insert(edges, string.format(' %s -->%s %s', fromNodeId, label, toNodeId))
|
table.insert(edges, string.format(' %s -->%s %s', fromNodeId, label, toNodeId))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get main lane reference
|
-- Get main lane reference
|
||||||
local mainStageLane = nil
|
local mainStageLane = nil
|
||||||
for _, lane in ipairs(lanes) do
|
for _, lane in ipairs(lanes) do
|
||||||
@@ -483,7 +489,7 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add dependencies from DEFAULT lane to SIDE lanes at chapter starts
|
-- Add dependencies from DEFAULT lane to SIDE lanes at chapter starts
|
||||||
-- Side lanes activate when main completes the stage BEFORE the chapter start
|
-- Side lanes activate when main completes the stage BEFORE the chapter start
|
||||||
if mainStageLane then
|
if mainStageLane then
|
||||||
@@ -491,7 +497,7 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
if lane:IsDefaultStageLane() == false then
|
if lane:IsDefaultStageLane() == false then
|
||||||
local sideId = lane:GetStageLaneIdentifier()
|
local sideId = lane:GetStageLaneIdentifier()
|
||||||
local sideIndices = stageIndicesByLane[sideId]
|
local sideIndices = stageIndicesByLane[sideId]
|
||||||
|
|
||||||
-- For each stage in the side lane
|
-- For each stage in the side lane
|
||||||
for _, stageIdx in ipairs(sideIndices) do
|
for _, stageIdx in ipairs(sideIndices) do
|
||||||
-- Check if this is a chapter start in the side lane
|
-- Check if this is a chapter start in the side lane
|
||||||
@@ -506,16 +512,16 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add dependencies from SIDE lanes gating the MAIN lane at chapter boundaries
|
-- Add dependencies from SIDE lanes gating the MAIN lane at chapter boundaries
|
||||||
-- Main cannot advance to the next chapter until ALL side lanes are at or above that chapter index
|
-- Main cannot advance to the next chapter until ALL side lanes are at or above that chapter index
|
||||||
if mainStageLane then
|
if mainStageLane then
|
||||||
local mainIndices = stageIndicesByLane[mainLaneId]
|
local mainIndices = stageIndicesByLane[mainLaneId]
|
||||||
|
|
||||||
-- For each chapter start in main lane (skip first one)
|
-- For each chapter start in main lane (skip first one)
|
||||||
for i = 2, #mainIndices do
|
for i = 2, #mainIndices do
|
||||||
local nextIdx = mainIndices[i]
|
local nextIdx = mainIndices[i]
|
||||||
|
|
||||||
-- Check if nextIdx is a chapter start (there's a gap before it)
|
-- Check if nextIdx is a chapter start (there's a gap before it)
|
||||||
if mainStageLane:IsChapterStart(nextIdx) then
|
if mainStageLane:IsChapterStart(nextIdx) then
|
||||||
-- Before main can progress to nextIdx, all side lanes must be at >= nextIdx
|
-- Before main can progress to nextIdx, all side lanes must be at >= nextIdx
|
||||||
@@ -523,23 +529,23 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
if lane:IsDefaultStageLane() == false then
|
if lane:IsDefaultStageLane() == false then
|
||||||
local sideId = lane:GetStageLaneIdentifier()
|
local sideId = lane:GetStageLaneIdentifier()
|
||||||
local sideIndices = stageIndicesByLane[sideId]
|
local sideIndices = stageIndicesByLane[sideId]
|
||||||
|
|
||||||
-- Find the appropriate gate node for this side lane
|
-- Find the appropriate gate node for this side lane
|
||||||
-- Use first stage >= nextIdx if it exists, otherwise use the highest stage
|
-- Use first stage >= nextIdx if it exists, otherwise use the highest stage
|
||||||
local gateStageIdx = nil
|
local gateStageIdx = nil
|
||||||
|
|
||||||
for _, idx in ipairs(sideIndices) do
|
for _, idx in ipairs(sideIndices) do
|
||||||
if idx >= nextIdx then
|
if idx >= nextIdx then
|
||||||
gateStageIdx = idx
|
gateStageIdx = idx
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If no stage >= nextIdx, use the highest stage in this lane
|
-- If no stage >= nextIdx, use the highest stage in this lane
|
||||||
if gateStageIdx == nil and #sideIndices > 0 then
|
if gateStageIdx == nil and #sideIndices > 0 then
|
||||||
gateStageIdx = sideIndices[#sideIndices]
|
gateStageIdx = sideIndices[#sideIndices]
|
||||||
end
|
end
|
||||||
|
|
||||||
if gateStageIdx then
|
if gateStageIdx then
|
||||||
local fromNodeId = sideId .. "_" .. gateStageIdx
|
local fromNodeId = sideId .. "_" .. gateStageIdx
|
||||||
local toNodeId = mainLaneId .. "_" .. nextIdx
|
local toNodeId = mainLaneId .. "_" .. nextIdx
|
||||||
@@ -550,25 +556,26 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Build complete Mermaid diagram
|
-- Build complete Mermaid diagram
|
||||||
local diagramLines = {"graph TD"}
|
local diagramLines = { "graph TD" }
|
||||||
|
|
||||||
-- Add class definitions for each lane with colors and contrasting text
|
-- Add class definitions for each lane with colors and contrasting text
|
||||||
for laneId, color in pairs(laneColorMap) do
|
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
|
end
|
||||||
|
|
||||||
-- Add nodes
|
-- Add nodes
|
||||||
for _, nodeStr in pairs(nodes) do
|
for _, nodeStr in pairs(nodes) do
|
||||||
table.insert(diagramLines, nodeStr)
|
table.insert(diagramLines, nodeStr)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add edges
|
-- Add edges
|
||||||
for _, edgeStr in pairs(edges) do
|
for _, edgeStr in pairs(edges) do
|
||||||
table.insert(diagramLines, edgeStr)
|
table.insert(diagramLines, edgeStr)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Apply classes to nodes
|
-- Apply classes to nodes
|
||||||
for nodeId in pairs(nodes) do
|
for nodeId in pairs(nodes) do
|
||||||
local laneId = nodeId:match("(.+)_[0-9]+$")
|
local laneId = nodeId:match("(.+)_[0-9]+$")
|
||||||
@@ -576,9 +583,10 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
table.insert(diagramLines, string.format(' class %s lane_%s', nodeId, laneId))
|
table.insert(diagramLines, string.format(' class %s lane_%s', nodeId, laneId))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Print as single multi-line message
|
-- 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)
|
self.logger:info(diagram)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -586,10 +594,10 @@ end
|
|||||||
---@param stageNumber number
|
---@param stageNumber number
|
||||||
---@param stageLaneIdentifier string? nil for default lan
|
---@param stageLaneIdentifier string? nil for default lan
|
||||||
---@return boolean | nil
|
---@return boolean | nil
|
||||||
GlobalStageManager.isStageComplete = function (stageNumber, stageLaneIdentifier)
|
GlobalStageManager.isStageComplete = function(stageNumber, stageLaneIdentifier)
|
||||||
|
|
||||||
if singletonInstance == nil then
|
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
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ end
|
|||||||
function SpearheadGroup:SpawnCorpsesOnly()
|
function SpearheadGroup:SpawnCorpsesOnly()
|
||||||
|
|
||||||
if self._isSpawned == true then return end
|
if self._isSpawned == true then return end
|
||||||
|
|
||||||
self._spawnManager:SpawnCorpsesOnly(self._groupName)
|
self._spawnManager:SpawnCorpsesOnly(self._groupName)
|
||||||
self._isSpawned = true
|
self._isSpawned = true
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ function SpearheadGroup:Spawn(lateStart)
|
|||||||
uncontrolled = lateStart,
|
uncontrolled = lateStart,
|
||||||
}
|
}
|
||||||
|
|
||||||
local spawnedObject, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
|
local _, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
|
||||||
self._isStatic = isStatic
|
self._isStatic = isStatic
|
||||||
self._isSpawned = true
|
self._isSpawned = true
|
||||||
end
|
end
|
||||||
@@ -97,7 +97,7 @@ function SpearheadGroup:GetObjects()
|
|||||||
local result = {}
|
local result = {}
|
||||||
if self._isStatic == true then
|
if self._isStatic == true then
|
||||||
local staticObject = StaticObject.getByName(self._groupName)
|
local staticObject = StaticObject.getByName(self._groupName)
|
||||||
if staticObject then
|
if staticObject then
|
||||||
table.insert(result, staticObject)
|
table.insert(result, staticObject)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -105,7 +105,7 @@ function SpearheadGroup:GetObjects()
|
|||||||
if not group then return {} end
|
if not group then return {} end
|
||||||
for _, unit in pairs(group:getUnits()) do
|
for _, unit in pairs(group:getUnits()) do
|
||||||
table.insert(result, unit)
|
table.insert(result, unit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
@@ -123,7 +123,7 @@ function SpearheadGroup:GetAsUnits()
|
|||||||
if not group then return {} end
|
if not group then return {} end
|
||||||
for _, unit in pairs(group:getUnits()) do
|
for _, unit in pairs(group:getUnits()) do
|
||||||
table.insert(result, unit)
|
table.insert(result, unit)
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ function SpearheadGroup:GetAllUnitPositions()
|
|||||||
local result = {}
|
local result = {}
|
||||||
if self._isStatic == true then
|
if self._isStatic == true then
|
||||||
local staticObject = StaticObject.getByName(self._groupName)
|
local staticObject = StaticObject.getByName(self._groupName)
|
||||||
if staticObject then
|
if staticObject then
|
||||||
table.insert(result, staticObject:getPoint())
|
table.insert(result, staticObject:getPoint())
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -141,7 +141,7 @@ function SpearheadGroup:GetAllUnitPositions()
|
|||||||
if not group then return {} end
|
if not group then return {} end
|
||||||
for _, unit in pairs(group:getUnits()) do
|
for _, unit in pairs(group:getUnits()) do
|
||||||
table.insert(result, unit:getPoint())
|
table.insert(result, unit:getPoint())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -50,16 +50,10 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
|
|||||||
---@type table<string, Vec3>
|
---@type table<string, Vec3>
|
||||||
local redUnitsPos = {}
|
local redUnitsPos = {}
|
||||||
|
|
||||||
|
|
||||||
local buildable = false
|
|
||||||
if self._buildableCrateKilos and self._buildableCrateKilos > 0 then
|
|
||||||
buildable = true
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, groupName in pairs(blueSamData.groups) do
|
for _, groupName in pairs(blueSamData.groups) do
|
||||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||||
if spearheadGroup then
|
if spearheadGroup then
|
||||||
|
|
||||||
if spearheadGroup:GetCoalition() == 2 or spearheadGroup:GetCoalition() == 0 then
|
if spearheadGroup:GetCoalition() == 2 or spearheadGroup:GetCoalition() == 0 then
|
||||||
table.insert(self._blueGroups, spearheadGroup)
|
table.insert(self._blueGroups, spearheadGroup)
|
||||||
end
|
end
|
||||||
@@ -78,7 +72,7 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
|
|||||||
|
|
||||||
--Cleanup units
|
--Cleanup units
|
||||||
local cleanup_distance = 5
|
local cleanup_distance = 5
|
||||||
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do
|
for _, blueUnitPos in pairs(blueUnitsPos) do
|
||||||
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
||||||
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||||
if distance <= cleanup_distance then
|
if distance <= cleanup_distance then
|
||||||
@@ -140,7 +134,9 @@ end
|
|||||||
|
|
||||||
function BlueSam:SpawnGroups()
|
function BlueSam:SpawnGroups()
|
||||||
for unitName, needsCleanup in pairs(self._cleanupUnits) do
|
for unitName, needsCleanup in pairs(self._cleanupUnits) do
|
||||||
DcsUtil.DestroyUnit(unitName)
|
if needsCleanup then
|
||||||
|
DcsUtil.DestroyUnit(unitName)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, group in pairs(self._blueGroups) do
|
for _, group in pairs(self._blueGroups) do
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ function FarpZone.New(database, logger, zoneName, spawnManager)
|
|||||||
self._groups = {}
|
self._groups = {}
|
||||||
self._padNames = {}
|
self._padNames = {}
|
||||||
self._supplyHubs = {}
|
self._supplyHubs = {}
|
||||||
|
|
||||||
|
|
||||||
if farpData then
|
if farpData then
|
||||||
self._padNames = farpData.padNames
|
self._padNames = farpData.padNames
|
||||||
|
|
||||||
for _, supplyHubName in pairs(farpData.supplyHubNames) do
|
for _, supplyHubName in pairs(farpData.supplyHubNames) do
|
||||||
local supplyHub = SupplyHub.new(database, logger, supplyHubName)
|
local supplyHub = SupplyHub.new(database, logger, supplyHubName)
|
||||||
if supplyHub then
|
if supplyHub then
|
||||||
@@ -55,7 +55,7 @@ function FarpZone.New(database, logger, zoneName, spawnManager)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
for _, groupName in pairs(farpData.groups) do
|
for _, groupName in pairs(farpData.groups) do
|
||||||
local group = SpearheadGroup.New(groupName, spawnManager, true)
|
local group = SpearheadGroup.New(groupName, spawnManager, true)
|
||||||
table.insert(self._groups, group)
|
table.insert(self._groups, group)
|
||||||
group:Destroy()
|
group:Destroy()
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
|||||||
|
|
||||||
local cleanup_distance = 5
|
local cleanup_distance = 5
|
||||||
|
|
||||||
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do
|
for _, blueUnitPos in pairs(blueUnitsPos) do
|
||||||
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
||||||
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||||
if distance <= cleanup_distance then
|
if distance <= cleanup_distance then
|
||||||
@@ -172,7 +172,7 @@ function StageBase:ActivateBlueStage()
|
|||||||
else
|
else
|
||||||
self:FinaliseBlueStage()
|
self:FinaliseBlueStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function StageBase:FinaliseBlueStage()
|
function StageBase:FinaliseBlueStage()
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ function SupplyHub.new(database, logger, zoneName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
self._zone = DcsUtil.getZoneByName(zoneName)
|
self._zone = DcsUtil.getZoneByName(zoneName)
|
||||||
|
|
||||||
self._supplyUnitsTracker = SupplyUnitsTracker.getOrCreate()
|
self._supplyUnitsTracker = SupplyUnitsTracker.getOrCreate()
|
||||||
self._inZone = {}
|
self._inZone = {}
|
||||||
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate()
|
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate()
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
|
|||||||
if params.unpackedKilos >= params.kilos or spawned == false then
|
if params.unpackedKilos >= params.kilos or spawned == false then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
return time + 0.5
|
return time + 0.5
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -76,8 +76,6 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
|
|||||||
self._buildableMission = nil
|
self._buildableMission = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if self._buildableMission == nil then
|
if self._buildableMission == nil then
|
||||||
self._buildableLogger:debug("No buildable mission for zone: " .. targetZone.name)
|
self._buildableLogger:debug("No buildable mission for zone: " .. targetZone.name)
|
||||||
end
|
end
|
||||||
@@ -99,23 +97,11 @@ function BuildableZone:OnBuildingComplete() end
|
|||||||
---@field unpackedItems number
|
---@field unpackedItems number
|
||||||
---@field unpackedKilos number
|
---@field unpackedKilos number
|
||||||
|
|
||||||
---@param mission BuildableMission?
|
---@param _ BuildableMission?
|
||||||
---@param kilos number
|
---@param kilos number
|
||||||
function BuildableZone:OnCrateDroppedOff(mission, kilos)
|
function BuildableZone:OnCrateDroppedOff(_, kilos)
|
||||||
self._buildableLogger:debug("Crate dropped off in zone: " .. self._targetZone.name)
|
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 params UnpackCrateParam
|
||||||
---@param time number
|
---@param time number
|
||||||
local startUnpackingCrate = function(params, time)
|
local startUnpackingCrate = function(params, time)
|
||||||
@@ -132,10 +118,21 @@ function BuildableZone:OnCrateDroppedOff(mission, kilos)
|
|||||||
params.self:FinaliseCrate(params.kilos)
|
params.self:FinaliseCrate(params.kilos)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
return time + 2
|
return time + 2
|
||||||
end
|
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)
|
timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -190,7 +187,7 @@ function BuildableZone:SpawnAmount(amount)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, amount do
|
for _ = 1, amount do
|
||||||
local spawned = spawnOne()
|
local spawned = spawnOne()
|
||||||
if spawned ~= true then
|
if spawned ~= true then
|
||||||
self._buildableLogger:debug("No more groups to spawn in zone: " .. self._targetZone.name)
|
self._buildableLogger:debug("No more groups to spawn in zone: " .. self._targetZone.name)
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ end
|
|||||||
function StageRepository:AddStage(stage)
|
function StageRepository:AddStage(stage)
|
||||||
|
|
||||||
local stageLaneIdentifier = stage:GetStageLaneIdentifier() or StageLane.DefaultLaneKey
|
local stageLaneIdentifier = stage:GetStageLaneIdentifier() or StageLane.DefaultLaneKey
|
||||||
|
|
||||||
if self.StageLanes[tostring(stageLaneIdentifier)] == nil then
|
if self.StageLanes[tostring(stageLaneIdentifier)] == nil then
|
||||||
self.StageLanes[tostring(stageLaneIdentifier)] = StageLane.New(stageLaneIdentifier)
|
self.StageLanes[tostring(stageLaneIdentifier)] = StageLane.New(stageLaneIdentifier)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ function Stage:superNew(database, stageConfig, logger, initData, stageType, miss
|
|||||||
end
|
end
|
||||||
self.stageName = initData.stageDisplayName
|
self.stageName = initData.stageDisplayName
|
||||||
self._stageType = stageType
|
self._stageType = stageType
|
||||||
|
|
||||||
self.OnPostStageComplete = nil
|
self.OnPostStageComplete = nil
|
||||||
self.OnPostBlueActivated = nil
|
self.OnPostBlueActivated = nil
|
||||||
|
|
||||||
@@ -160,25 +160,25 @@ function Stage:superNew(database, stageConfig, logger, initData, stageType, miss
|
|||||||
self._logger:info("Initiating new Stage with name: " .. self.zoneName)
|
self._logger:info("Initiating new Stage with name: " .. self.zoneName)
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param self Stage
|
---@param selfA Stage
|
||||||
---@param time number?
|
---@param time number?
|
||||||
self.CheckContinuousAsync = function (self, time)
|
self.CheckContinuousAsync = function (selfA, time)
|
||||||
|
|
||||||
self:CheckAndUpdateSelf()
|
selfA:CheckAndUpdateSelf()
|
||||||
if self:IsComplete() == true then
|
if selfA:IsComplete() == true then
|
||||||
self:NotifyComplete()
|
selfA:NotifyComplete()
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
return time + 20
|
return time + 20
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
do -- load tables
|
do -- load tables
|
||||||
local missionZones = database:getMissionsForStage(self.zoneName)
|
local missionZones = database:getMissionsForStage(self.zoneName)
|
||||||
self._logger:debug("Found " .. Util.tableLength(missionZones) .. " mission zones for stage: " .. self.zoneName)
|
self._logger:debug("Found " .. Util.tableLength(missionZones) .. " mission zones for stage: " .. self.zoneName)
|
||||||
for _, missionZone in pairs(missionZones) do
|
for _, missionZone in pairs(missionZones) do
|
||||||
|
|
||||||
local mission = ZoneMission.new(missionZone, self._missionPriority, database, logger, self, spawnManager)
|
local mission = ZoneMission.new(missionZone, self._missionPriority, database, logger, self, spawnManager)
|
||||||
if mission then
|
if mission then
|
||||||
self._db.missionsByCode[mission.code] = mission
|
self._db.missionsByCode[mission.code] = mission
|
||||||
@@ -233,7 +233,7 @@ function Stage:superNew(database, stageConfig, logger, initData, stageType, miss
|
|||||||
table.insert(self._db.missions, mission)
|
table.insert(self._db.missions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self._logger:info("Using persisted random mission with name: " .. missionName .. " and zone: " .. missionZonePicked)
|
self._logger:info("Using persisted random mission with name: " .. missionName .. " and zone: " .. missionZonePicked)
|
||||||
for _, mission in pairs(missions) do
|
for _, mission in pairs(missions) do
|
||||||
if string.lower(mission.zoneName) == string.lower(missionZonePicked) then
|
if string.lower(mission.zoneName) == string.lower(missionZonePicked) then
|
||||||
@@ -284,14 +284,14 @@ end
|
|||||||
function Stage:IsComplete()
|
function Stage:IsComplete()
|
||||||
if self._currentStageState >= StageState.Blue then return true end
|
if self._currentStageState >= StageState.Blue then return true end
|
||||||
|
|
||||||
for i, mission in pairs(self._db.sams) do
|
for _, mission in pairs(self._db.sams) do
|
||||||
local state = mission:getState()
|
local state = mission:getState()
|
||||||
if state == "ACTIVE" or state == "NEW" or state =="WAITING" then
|
if state == "ACTIVE" or state == "NEW" or state =="WAITING" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, mission in pairs(self._db.missions) do
|
for _, mission in pairs(self._db.missions) do
|
||||||
local state = mission:getState()
|
local state = mission:getState()
|
||||||
if state == "ACTIVE" or state == "NEW" then
|
if state == "ACTIVE" or state == "NEW" then
|
||||||
return false
|
return false
|
||||||
@@ -370,9 +370,9 @@ function Stage:CheckAndUpdateSelf()
|
|||||||
local availableMissionsCount = Util.tableLength(getAvailableMissions())
|
local availableMissionsCount = Util.tableLength(getAvailableMissions())
|
||||||
local activeCount = getActiveMissionsCount()
|
local activeCount = getActiveMissionsCount()
|
||||||
if activeCount < max and availableMissionsCount > 0 then
|
if activeCount < max and availableMissionsCount > 0 then
|
||||||
for i = activeCount+1, max do
|
for _ = activeCount+1, max do
|
||||||
if availableMissionsCount == 0 then
|
if availableMissionsCount == 0 then
|
||||||
i = max+1 --exits this loop
|
break
|
||||||
else
|
else
|
||||||
local mission = Util.randomFromList(getAvailableMissions()) --[[@as Mission]]
|
local mission = Util.randomFromList(getAvailableMissions()) --[[@as Mission]]
|
||||||
if mission then
|
if mission then
|
||||||
@@ -426,7 +426,7 @@ function Stage:PreActivate()
|
|||||||
end
|
end
|
||||||
|
|
||||||
self._currentStageState = StageState.PreActivated
|
self._currentStageState = StageState.PreActivated
|
||||||
for key, mission in pairs(self._db.sams) do
|
for _, mission in pairs(self._db.sams) do
|
||||||
if mission then
|
if mission then
|
||||||
mission:SpawnInactive()
|
mission:SpawnInactive()
|
||||||
end
|
end
|
||||||
@@ -473,7 +473,7 @@ function Stage:MarkStage()
|
|||||||
drawing.colorString = DrawingHelper.ColorTableToColorString(Stage.StageColors.INVISIBLE)
|
drawing.colorString = DrawingHelper.ColorTableToColorString(Stage.StageColors.INVISIBLE)
|
||||||
drawing.style = "no line"
|
drawing.style = "no line"
|
||||||
end
|
end
|
||||||
|
|
||||||
return drawing
|
return drawing
|
||||||
end)
|
end)
|
||||||
self._customDrawing:Draw()
|
self._customDrawing:Draw()
|
||||||
@@ -585,12 +585,12 @@ function Stage:OnStageNumberChanged(number, stageLaneIdentifier)
|
|||||||
if needsBlueActivation() == true then
|
if needsBlueActivation() == true then
|
||||||
self:ActivateBlueStage()
|
self:ActivateBlueStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param self Stage
|
---@param self Stage
|
||||||
---@param mission Mission
|
---@param _ Mission
|
||||||
Stage.OnMissionComplete = function(self, mission)
|
Stage.OnMissionComplete = function(self, _)
|
||||||
self:CheckAndUpdateSelf()
|
self:CheckAndUpdateSelf()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -645,7 +645,7 @@ function Stage:GetStageStats()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, mission in pairs(self._db.sams) do
|
for _, _ in pairs(self._db.sams) do
|
||||||
dead = dead + 1
|
dead = dead + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -673,13 +673,13 @@ function Stage:ActivateBlueStage()
|
|||||||
miscGroup:Spawn()
|
miscGroup:Spawn()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param self Stage
|
---@param selfA Stage
|
||||||
local ActivateBlueAsync = function(self)
|
local ActivateBlueAsync = function(selfA)
|
||||||
pcall(function()
|
pcall(function()
|
||||||
self:MarkStage()
|
selfA:MarkStage()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self:ActivateBlueGroups()
|
selfA:ActivateBlueGroups()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
||||||
local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
|
local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
|
||||||
|
local StageState = require("classes.stageClasses.Stages.BaseStage.StageState")
|
||||||
|
|
||||||
---@class ExtraStage : Stage
|
---@class ExtraStage : Stage
|
||||||
local ExtraStage = {}
|
local ExtraStage = {}
|
||||||
@@ -22,10 +23,9 @@ function ExtraStage.New(database, stageConfig, logger, initData, spawnManager)
|
|||||||
self:superNew(database, stageConfig, logger, initData, "ExtraStage", "secondary", spawnManager)
|
self:superNew(database, stageConfig, logger, initData, "ExtraStage", "secondary", spawnManager)
|
||||||
|
|
||||||
self.OnPostBlueActivated = function (selfStage)
|
self.OnPostBlueActivated = function (selfStage)
|
||||||
|
|
||||||
selfStage:MarkStage()
|
selfStage:MarkStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
self.OnPostStageComplete = function (selfStage)
|
self.OnPostStageComplete = function (selfStage)
|
||||||
selfStage:ActivateBlueStage()
|
selfStage:ActivateBlueStage()
|
||||||
end
|
end
|
||||||
@@ -47,7 +47,6 @@ function ExtraStage:OnStageNumberChanged(number, stageLaneIdentifier)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local previousActive = self._activeStage
|
|
||||||
self._activeStage = number
|
self._activeStage = number
|
||||||
|
|
||||||
if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then
|
if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then
|
||||||
@@ -61,7 +60,7 @@ function ExtraStage:OnStageNumberChanged(number, stageLaneIdentifier)
|
|||||||
self:ActivateStage()
|
self:ActivateStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
if self._currentStageState == Stage.CurrentStageState.BLUE then
|
if self._currentStageState == StageState.Blue then
|
||||||
self:ActivateBlueStage()
|
self:ActivateBlueStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function WaitingStage.New(database, stageConfig, logger, initData, waitingSecond
|
|||||||
self._startTime = nil
|
self._startTime = nil
|
||||||
|
|
||||||
self.CheckContinuousAsync = function (selfA, time)
|
self.CheckContinuousAsync = function (selfA, time)
|
||||||
|
|
||||||
if selfA:IsComplete() == true then
|
if selfA:IsComplete() == true then
|
||||||
selfA:NotifyComplete()
|
selfA:NotifyComplete()
|
||||||
return nil
|
return nil
|
||||||
@@ -47,7 +47,7 @@ function WaitingStage:ActivateStage()
|
|||||||
timer.scheduleFunction(self.CheckContinuousAsync, self, self._startTime + self._waitTimeSeconds)
|
timer.scheduleFunction(self.CheckContinuousAsync, self, self._startTime + self._waitTimeSeconds)
|
||||||
end
|
end
|
||||||
|
|
||||||
function WaitingStage:IsComplete()
|
function WaitingStage:IsComplete()
|
||||||
if timer.getTime() > (self._startTime + self._waitTimeSeconds) then return true end
|
if timer.getTime() > (self._startTime + self._waitTimeSeconds) then return true end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -56,12 +56,12 @@ function WaitingStage:OnStageNumberChanged()
|
|||||||
self._logger:debug("Waiting Stage OnStageNumberChanged override")
|
self._logger:debug("Waiting Stage OnStageNumberChanged override")
|
||||||
end
|
end
|
||||||
|
|
||||||
function WaitingStage:MarkStage(stageColor)
|
function WaitingStage:MarkStage(_)
|
||||||
self._logger:debug("Waiting Stage MarkStage override")
|
self._logger:debug("Waiting Stage MarkStage override")
|
||||||
end
|
end
|
||||||
|
|
||||||
function WaitingStage:GetExpectedTime()
|
function WaitingStage:GetExpectedTime()
|
||||||
return self._startTime + self._waitTimeSeconds
|
return self._startTime + self._waitTimeSeconds
|
||||||
end
|
end
|
||||||
|
|
||||||
return WaitingStage
|
return WaitingStage
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
||||||
local Util = require("classes.util.Util")
|
|
||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
|
||||||
local drawingLogger = Logger.new("CustomDrawing")
|
local drawingLogger = Logger.new("CustomDrawing")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
local Util = require("classes.util.Util")
|
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
local DcsUtil = require("classes.util.DcsUtil")
|
||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
||||||
@@ -78,7 +77,7 @@ local function MarkupToAll(shapeID, drawID, points, fillColor, lineColor, lineS
|
|||||||
end
|
end
|
||||||
trigger.action.setMarkupColor(drawID, lineColor)
|
trigger.action.setMarkupColor(drawID, lineColor)
|
||||||
trigger.action.setMarkupTypeLine(drawID, lineStyle)
|
trigger.action.setMarkupTypeLine(drawID, lineStyle)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
@@ -201,7 +200,7 @@ function DrawingHelper.DrawLine(object)
|
|||||||
|
|
||||||
---@type Array<Vec3>
|
---@type Array<Vec3>
|
||||||
local points = {}
|
local points = {}
|
||||||
local ids = {}
|
local ids = {}
|
||||||
|
|
||||||
for _, point in ipairs(object.points) do
|
for _, point in ipairs(object.points) do
|
||||||
table.insert(points, { x = object.mapX + point.x, y = 0, z = object.mapY + point.y } )
|
table.insert(points, { x = object.mapX + point.x, y = 0, z = object.mapY + point.y } )
|
||||||
@@ -265,7 +264,7 @@ function DrawingHelper.ColorTableToColorString(rgba)
|
|||||||
logger:warn("ColorTableToColorString called with invalid rgba table, returning default color string '0x00000000'")
|
logger:warn("ColorTableToColorString called with invalid rgba table, returning default color string '0x00000000'")
|
||||||
return "0x00000000"
|
return "0x00000000"
|
||||||
end
|
end
|
||||||
|
|
||||||
local r = string.format("%02X", math.floor(rgba[1] * 255))
|
local r = string.format("%02X", math.floor(rgba[1] * 255))
|
||||||
local g = string.format("%02X", math.floor(rgba[2] * 255))
|
local g = string.format("%02X", math.floor(rgba[2] * 255))
|
||||||
local b = string.format("%02X", math.floor(rgba[3] * 255))
|
local b = string.format("%02X", math.floor(rgba[3] * 255))
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local Util = require("classes.util.Util")
|
local Util = require("classes.util.Util")
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
|
||||||
|
|
||||||
---@class BattleManager
|
---@class BattleManager
|
||||||
---@field private _name string
|
---@field private _name string
|
||||||
@@ -13,8 +12,6 @@ local DcsUtil = require("classes.util.DcsUtil")
|
|||||||
local BattleManager = {}
|
local BattleManager = {}
|
||||||
BattleManager.__index = BattleManager
|
BattleManager.__index = BattleManager
|
||||||
|
|
||||||
local debugDrawing = false
|
|
||||||
|
|
||||||
---@param redGroups Array<SpearheadGroup>
|
---@param redGroups Array<SpearheadGroup>
|
||||||
---@param blueGroups Array<SpearheadGroup>
|
---@param blueGroups Array<SpearheadGroup>
|
||||||
---@param name string
|
---@param name string
|
||||||
@@ -30,8 +27,8 @@ function BattleManager.New(redGroups, blueGroups, name, logLevel)
|
|||||||
self._redGroups = redGroups
|
self._redGroups = redGroups
|
||||||
self._blueGroups = blueGroups
|
self._blueGroups = blueGroups
|
||||||
|
|
||||||
self._logger:debug("BattleManager created with name: " .. self._name
|
self._logger:debug("BattleManager created with name: " .. self._name
|
||||||
.. ", red groups: " .. #self._redGroups
|
.. ", red groups: " .. #self._redGroups
|
||||||
.. ", blue groups: " .. #self._blueGroups)
|
.. ", blue groups: " .. #self._blueGroups)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -90,8 +87,6 @@ function BattleManager:Update()
|
|||||||
|
|
||||||
self._logger:debug("BattleManager Update called for " .. self._name)
|
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._redGroups, self._blueGroups)
|
||||||
self:LetUnitsShoot(self._blueGroups, self._redGroups)
|
self:LetUnitsShoot(self._blueGroups, self._redGroups)
|
||||||
|
|
||||||
@@ -136,7 +131,7 @@ function BattleManager:LetUnitsShoot(groups, targetGroups)
|
|||||||
expendQtyEnabled = true
|
expendQtyEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local controller = unit:getController()
|
local controller = unit:getController()
|
||||||
if controller then
|
if controller then
|
||||||
controller:setTask(shootTask)
|
controller:setTask(shootTask)
|
||||||
@@ -146,7 +141,7 @@ function BattleManager:LetUnitsShoot(groups, targetGroups)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param unit Unit
|
---@param unit Unit
|
||||||
---@return number
|
---@return number
|
||||||
@@ -196,7 +191,7 @@ function BattleManager:IsUnitApplicable(unit)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
@@ -236,7 +231,7 @@ end
|
|||||||
---@param groupHulls Array<Array<Vec2>>
|
---@param groupHulls Array<Array<Vec2>>
|
||||||
---@return Vec2?
|
---@return Vec2?
|
||||||
function BattleManager:GetRandomPoint(origin, groupHulls)
|
function BattleManager:GetRandomPoint(origin, groupHulls)
|
||||||
|
|
||||||
local hull = Util.randomFromList(groupHulls) --[[@as Array<Vec2>]]
|
local hull = Util.randomFromList(groupHulls) --[[@as Array<Vec2>]]
|
||||||
if not hull then return nil end
|
if not hull then return nil end
|
||||||
local shootPoints = Util.GetTangentHullPointsFromOrigin(hull, origin)
|
local shootPoints = Util.GetTangentHullPointsFromOrigin(hull, origin)
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ local function sortMissions(list, groupPos)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local id = 0
|
|
||||||
|
|
||||||
local instance = nil
|
local instance = nil
|
||||||
|
|
||||||
---@return MissionCommandsHelper
|
---@return MissionCommandsHelper
|
||||||
@@ -57,16 +55,16 @@ function MissionCommandsHelper.getOrCreate()
|
|||||||
|
|
||||||
instance._supplyUnitsTracker:AddOnSupplyUnitEventListener(
|
instance._supplyUnitsTracker:AddOnSupplyUnitEventListener(
|
||||||
{
|
{
|
||||||
enteredSupplyHub = function(self, unit)
|
enteredSupplyHub = function(_, unit)
|
||||||
if unit == nil then return end
|
if unit == nil then return end
|
||||||
instance.updateNeeded = true
|
instance.updateNeeded = true
|
||||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||||
end,
|
end,
|
||||||
exitedSupplyHub = function(self, unit)
|
exitedSupplyHub = function(_, unit)
|
||||||
instance.updateNeeded = true
|
instance.updateNeeded = true
|
||||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||||
end,
|
end,
|
||||||
supplyUnitSpawned = function(self, unit)
|
supplyUnitSpawned = function(_, unit)
|
||||||
instance.updateNeeded = true
|
instance.updateNeeded = true
|
||||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||||
end
|
end
|
||||||
@@ -509,7 +507,6 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
|
|||||||
local unloadCargoCommand = function(params)
|
local unloadCargoCommand = function(params)
|
||||||
local unitID = params.unitID
|
local unitID = params.unitID
|
||||||
local crateType = params.crateType
|
local crateType = params.crateType
|
||||||
local supplyUnitsTracker = params.supplyUnitsTracker
|
|
||||||
params.supplyUnitsTracker:UnloadRequested(unitID, crateType, params.commandHelper)
|
params.supplyUnitsTracker:UnloadRequested(unitID, crateType, params.commandHelper)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -518,7 +515,7 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
|
|||||||
for cargoType, amount in pairs(cargo) do
|
for cargoType, amount in pairs(cargo) do
|
||||||
local cargoConfig = SupplyConfigHelper.getSupplyConfig(cargoType)
|
local cargoConfig = SupplyConfigHelper.getSupplyConfig(cargoType)
|
||||||
if cargoConfig then
|
if cargoConfig then
|
||||||
for i = 1, amount do
|
for _ = 1, amount do
|
||||||
local path = { [1] = folderNames.cargo }
|
local path = { [1] = folderNames.cargo }
|
||||||
---@type UnloadCargoCommandParams
|
---@type UnloadCargoCommandParams
|
||||||
local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self
|
local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ local SupplyLoadConfig = {
|
|||||||
{ centerAngle = 270, angleWidth = 60, minRadius = 15, maxRadius = 50, spacing = 5 },
|
{ centerAngle = 270, angleWidth = 60, minRadius = 15, maxRadius = 50, spacing = 5 },
|
||||||
{ centerAngle = 90, angleWidth = 60, minRadius = 15, maxRadius = 50, spacing = 5 },
|
{ centerAngle = 90, angleWidth = 60, minRadius = 15, maxRadius = 50, spacing = 5 },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
["UH-1H"] = {
|
["UH-1H"] = {
|
||||||
maxInternalLoad = 2000,
|
maxInternalLoad = 2000,
|
||||||
dropZones = {
|
dropZones = {
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ function SupplyUnitsTracker:RemoveCargoFromUnit(unitID, crateType)
|
|||||||
self._cargoInUnits[unitIDStr][crateType] = self._cargoInUnits[unitIDStr][crateType] - 1
|
self._cargoInUnits[unitIDStr][crateType] = self._cargoInUnits[unitIDStr][crateType] - 1
|
||||||
|
|
||||||
local hasCargo = false
|
local hasCargo = false
|
||||||
for type, count in pairs(self._cargoInUnits[unitIDStr]) do
|
for _, count in pairs(self._cargoInUnits[unitIDStr]) do
|
||||||
if count > 0 then
|
if count > 0 then
|
||||||
hasCargo = true
|
hasCargo = true
|
||||||
break
|
break
|
||||||
@@ -216,13 +216,11 @@ end
|
|||||||
|
|
||||||
function SupplyUnitsTracker:CheckUnitsInZones()
|
function SupplyUnitsTracker:CheckUnitsInZones()
|
||||||
|
|
||||||
for name, unit in pairs(self._supplyUnitsByName) do
|
for _, unit in pairs(self._supplyUnitsByName) do
|
||||||
if unit ~= nil and unit:isExist() == true then
|
if unit ~= nil and unit:isExist() == true then
|
||||||
self._logger:debug("Checking unit: " .. unit:getName())
|
self._logger:debug("Checking unit: " .. unit:getName())
|
||||||
local pos = unit:getPoint()
|
local pos = unit:getPoint()
|
||||||
|
|
||||||
local group = unit:getGroup()
|
|
||||||
|
|
||||||
for hub, enabled in pairs(self._registeredHubs) do
|
for hub, enabled in pairs(self._registeredHubs) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local zone = hub:GetZone()
|
local zone = hub:GetZone()
|
||||||
@@ -238,7 +236,7 @@ function SupplyUnitsTracker:CheckUnitsInZones()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
if self._unitInSupplyHub[tostring(unit:getID())] == true then
|
if self._unitInSupplyHub[tostring(unit:getID())] == true then
|
||||||
self._unitInSupplyHub[tostring(unit:getID())] = false
|
self._unitInSupplyHub[tostring(unit:getID())] = false
|
||||||
@@ -292,11 +290,11 @@ local cargoCount = 0
|
|||||||
---@param crateType CrateType
|
---@param crateType CrateType
|
||||||
---@param missionCommandsHelper MissionCommandsHelper
|
---@param missionCommandsHelper MissionCommandsHelper
|
||||||
function SupplyUnitsTracker:UnloadRequested(unitID, crateType, missionCommandsHelper)
|
function SupplyUnitsTracker:UnloadRequested(unitID, crateType, missionCommandsHelper)
|
||||||
|
|
||||||
self._logger:debug("Unload requested for unit: " .. unitID .. " crateType: " .. crateType)
|
self._logger:debug("Unload requested for unit: " .. unitID .. " crateType: " .. crateType)
|
||||||
|
|
||||||
local unit = DcsUtil.GetPlayerUnitByID(unitID)
|
local unit = DcsUtil.GetPlayerUnitByID(unitID)
|
||||||
if unit == nil or unit:isExist() == false then
|
if unit == nil or unit:isExist() == false then
|
||||||
self._logger:warn("Unload requested for non-existent unit: " .. unitID)
|
self._logger:warn("Unload requested for non-existent unit: " .. unitID)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -305,7 +303,7 @@ function SupplyUnitsTracker:UnloadRequested(unitID, crateType, missionCommandsHe
|
|||||||
self._logger:warn("Unload requested for unit with no group: " .. unit:getName())
|
self._logger:warn("Unload requested for unit with no group: " .. unit:getName())
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local cargoConfig = SupplyConfigHelper.getSupplyConfig(crateType)
|
local cargoConfig = SupplyConfigHelper.getSupplyConfig(crateType)
|
||||||
|
|
||||||
if cargoConfig == nil then
|
if cargoConfig == nil then
|
||||||
@@ -362,11 +360,11 @@ function SupplyUnitsTracker:UnitRequestCrateLoading(groupID, crateType, missionC
|
|||||||
end
|
end
|
||||||
|
|
||||||
local unit = group:getUnit(1)
|
local unit = group:getUnit(1)
|
||||||
|
|
||||||
if unit == nil then return end
|
if unit == nil then return end
|
||||||
if unit:isExist() == false then return end
|
if unit:isExist() == false then return end
|
||||||
|
|
||||||
|
|
||||||
if unit:inAir() == true then
|
if unit:inAir() == true then
|
||||||
trigger.action.outTextForUnit(unit:getID(), "Land first before crates can be loaded", 10)
|
trigger.action.outTextForUnit(unit:getID(), "Land first before crates can be loaded", 10)
|
||||||
return
|
return
|
||||||
@@ -383,7 +381,7 @@ function SupplyUnitsTracker:UnitRequestCrateLoading(groupID, crateType, missionC
|
|||||||
|
|
||||||
---@param params LoadCargoParams
|
---@param params LoadCargoParams
|
||||||
local LoadCrateTask = function(params)
|
local LoadCrateTask = function(params)
|
||||||
|
|
||||||
local loaded = params.self:TryLoadCrateInUnit(params.unit, params.crateType, params.commandHelper)
|
local loaded = params.self:TryLoadCrateInUnit(params.unit, params.crateType, params.commandHelper)
|
||||||
if loaded ~= false then
|
if loaded ~= false then
|
||||||
trigger.action.outTextForUnit(unit:getID(), "Loaded crate :" .. params.crateType, 10)
|
trigger.action.outTextForUnit(unit:getID(), "Loaded crate :" .. params.crateType, 10)
|
||||||
@@ -410,7 +408,7 @@ end
|
|||||||
---@param commandHelper MissionCommandsHelper
|
---@param commandHelper MissionCommandsHelper
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function SupplyUnitsTracker:TryLoadCrateInUnit(unit, crateType, commandHelper)
|
function SupplyUnitsTracker:TryLoadCrateInUnit(unit, crateType, commandHelper)
|
||||||
|
|
||||||
local crateConfigA = SupplyConfigHelper.getSupplyConfig(crateType)
|
local crateConfigA = SupplyConfigHelper.getSupplyConfig(crateType)
|
||||||
if crateConfigA == nil then
|
if crateConfigA == nil then
|
||||||
trigger.action.outTextForUnit(unit:getID(), "Invalid crate type: " .. crateType, 5)
|
trigger.action.outTextForUnit(unit:getID(), "Invalid crate type: " .. crateType, 5)
|
||||||
@@ -444,7 +442,7 @@ function SupplyUnitsTracker:TryLoadCrateInUnit(unit, crateType, commandHelper)
|
|||||||
if group == nil then return false end
|
if group == nil then return false end
|
||||||
local groupID = group:getID()
|
local groupID = group:getID()
|
||||||
commandHelper:updateCommandsForGroup(groupID)
|
commandHelper:updateCommandsForGroup(groupID)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -462,7 +460,7 @@ function SupplyUnitsTracker:UnitRequestCrateSpawn(groupID, crateType)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -484,11 +482,11 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject)
|
|||||||
if desc == nil or desc.box == nil then
|
if desc == nil or desc.box == nil then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local objPos = foundObject:getPoint()
|
local objPos = foundObject:getPoint()
|
||||||
local box = desc.box
|
local box = desc.box
|
||||||
local heading = 0
|
local heading = 0
|
||||||
|
|
||||||
-- Try to get object heading from position vector's forward direction
|
-- Try to get object heading from position vector's forward direction
|
||||||
-- This works for units and other objects that support getPosition
|
-- This works for units and other objects that support getPosition
|
||||||
pcall(function()
|
pcall(function()
|
||||||
@@ -497,13 +495,13 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject)
|
|||||||
heading = math.atan2(objPosition.x.z, objPosition.x.x)
|
heading = math.atan2(objPosition.x.z, objPosition.x.x)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- For rotated objects, we need to rotate the bounding box
|
-- For rotated objects, we need to rotate the bounding box
|
||||||
local minX = box.min.x
|
local minX = box.min.x
|
||||||
local maxX = box.max.x
|
local maxX = box.max.x
|
||||||
local minZ = box.min.z
|
local minZ = box.min.z
|
||||||
local maxZ = box.max.z
|
local maxZ = box.max.z
|
||||||
|
|
||||||
-- If object has significant rotation, apply rotation to bbox corners
|
-- If object has significant rotation, apply rotation to bbox corners
|
||||||
if math.abs(heading) > 0.1 then
|
if math.abs(heading) > 0.1 then
|
||||||
-- Get all 4 corners of bbox in local space
|
-- Get all 4 corners of bbox in local space
|
||||||
@@ -513,11 +511,11 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject)
|
|||||||
{maxX, minZ},
|
{maxX, minZ},
|
||||||
{maxX, maxZ}
|
{maxX, maxZ}
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Rotate corners and find new min/max
|
-- Rotate corners and find new min/max
|
||||||
minX, maxX = math.huge, -math.huge
|
minX, maxX = math.huge, -math.huge
|
||||||
minZ, maxZ = math.huge, -math.huge
|
minZ, maxZ = math.huge, -math.huge
|
||||||
|
|
||||||
for _, corner in ipairs(corners) do
|
for _, corner in ipairs(corners) do
|
||||||
local rotX = corner[1] * math.cos(heading) - corner[2] * math.sin(heading)
|
local rotX = corner[1] * math.cos(heading) - corner[2] * math.sin(heading)
|
||||||
local rotZ = corner[1] * math.sin(heading) + corner[2] * math.cos(heading)
|
local rotZ = corner[1] * math.sin(heading) + corner[2] * math.cos(heading)
|
||||||
@@ -527,7 +525,7 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject)
|
|||||||
maxZ = math.max(maxZ, rotZ)
|
maxZ = math.max(maxZ, rotZ)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Convert relative bbox to world space by adding object position
|
-- Convert relative bbox to world space by adding object position
|
||||||
---@type SupplyUnitsBoundingBox
|
---@type SupplyUnitsBoundingBox
|
||||||
return {
|
return {
|
||||||
@@ -551,7 +549,7 @@ end
|
|||||||
---@param safetyMargin number Safety margin around objects
|
---@param safetyMargin number Safety margin around objects
|
||||||
---@return boolean True if collision detected
|
---@return boolean True if collision detected
|
||||||
function SupplyUnitsTracker:CheckBBoxCollision(crateBBox, objBBox, safetyMargin)
|
function SupplyUnitsTracker:CheckBBoxCollision(crateBBox, objBBox, safetyMargin)
|
||||||
|
|
||||||
-- Apply safety margin to object bbox
|
-- Apply safety margin to object bbox
|
||||||
local objMin = {
|
local objMin = {
|
||||||
x = objBBox.min.x - safetyMargin,
|
x = objBBox.min.x - safetyMargin,
|
||||||
@@ -563,7 +561,7 @@ function SupplyUnitsTracker:CheckBBoxCollision(crateBBox, objBBox, safetyMargin)
|
|||||||
y = objBBox.max.y + safetyMargin,
|
y = objBBox.max.y + safetyMargin,
|
||||||
z = objBBox.max.z + safetyMargin
|
z = objBBox.max.z + safetyMargin
|
||||||
}
|
}
|
||||||
|
|
||||||
-- AABB collision detection
|
-- AABB collision detection
|
||||||
return crateBBox.min.x <= objMax.x and crateBBox.max.x >= objMin.x and
|
return crateBBox.min.x <= objMax.x and crateBBox.max.x >= objMin.x and
|
||||||
crateBBox.min.y <= objMax.y and crateBBox.max.y >= objMin.y and
|
crateBBox.min.y <= objMax.y and crateBBox.max.y >= objMin.y and
|
||||||
@@ -577,7 +575,7 @@ end
|
|||||||
function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
||||||
|
|
||||||
local unitPos = unit:getPosition()
|
local unitPos = unit:getPosition()
|
||||||
|
|
||||||
-- Get unit's heading from the forward vector (x component)
|
-- Get unit's heading from the forward vector (x component)
|
||||||
-- Heading is calculated as: atan2(forward.z, forward.x)
|
-- Heading is calculated as: atan2(forward.z, forward.x)
|
||||||
local unitHeading = math.atan2(unitPos.x.z, unitPos.x.x)
|
local unitHeading = math.atan2(unitPos.x.z, unitPos.x.x)
|
||||||
@@ -588,14 +586,14 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
|||||||
self._logger:error("Could not get bbox for crate type: " .. crateTypeName)
|
self._logger:error("Could not get bbox for crate type: " .. crateTypeName)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local crateRelativeBBox = crateDesc.box
|
local crateRelativeBBox = crateDesc.box
|
||||||
|
|
||||||
-- Get drop zone config for this unit
|
-- Get drop zone config for this unit
|
||||||
local dropZones = {
|
local dropZones = {
|
||||||
{ centerAngle = 180, angleWidth = 60, minRadius = 15, maxRadius = 50, spacing = 5 }
|
{ centerAngle = 180, angleWidth = 60, minRadius = 15, maxRadius = 50, spacing = 5 }
|
||||||
}
|
}
|
||||||
|
|
||||||
if SupplyLoadConfig[unit:getTypeName()] ~= nil then
|
if SupplyLoadConfig[unit:getTypeName()] ~= nil then
|
||||||
dropZones = SupplyLoadConfig[unit:getTypeName()].dropZones
|
dropZones = SupplyLoadConfig[unit:getTypeName()].dropZones
|
||||||
end
|
end
|
||||||
@@ -614,7 +612,7 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
local occupiedObjects = {}
|
local occupiedObjects = {}
|
||||||
local found = function(foundItem, val)
|
local found = function(foundItem, _)
|
||||||
local bbox = self:GetBoundingBoxes(foundItem)
|
local bbox = self:GetBoundingBoxes(foundItem)
|
||||||
if bbox then
|
if bbox then
|
||||||
self._logger:debug("Found object: " .. foundItem:getTypeName() .. " at (" .. foundItem:getPoint().x .. ", " .. foundItem:getPoint().z .. ")")
|
self._logger:debug("Found object: " .. foundItem:getTypeName() .. " at (" .. foundItem:getPoint().x .. ", " .. foundItem:getPoint().z .. ")")
|
||||||
@@ -648,15 +646,15 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
|||||||
for distance = zone.minRadius, zone.maxRadius, zone.spacing do
|
for distance = zone.minRadius, zone.maxRadius, zone.spacing do
|
||||||
-- Check multiple positions within the angular slice
|
-- Check multiple positions within the angular slice
|
||||||
local angleStep = math.min(15, zone.angleWidth / 3) -- Divide slice into sections
|
local angleStep = math.min(15, zone.angleWidth / 3) -- Divide slice into sections
|
||||||
|
|
||||||
for angle = minAngle, maxAngle, angleStep do
|
for angle = minAngle, maxAngle, angleStep do
|
||||||
local radians = math.rad(angle)
|
local radians = math.rad(angle)
|
||||||
|
|
||||||
-- Calculate position at this angle and distance, relative to unit's heading
|
-- Calculate position at this angle and distance, relative to unit's heading
|
||||||
-- Angle 0 = forward, 90 = right, 180 = rear, 270 = left
|
-- Angle 0 = forward, 90 = right, 180 = rear, 270 = left
|
||||||
-- Apply unit heading to make angles relative to unit orientation
|
-- Apply unit heading to make angles relative to unit orientation
|
||||||
local worldAngle = radians + unitHeading
|
local worldAngle = radians + unitHeading
|
||||||
|
|
||||||
local candidateX = unitPos.p.x + distance * math.sin(worldAngle)
|
local candidateX = unitPos.p.x + distance * math.sin(worldAngle)
|
||||||
local candidateZ = unitPos.p.z + distance * math.cos(worldAngle)
|
local candidateZ = unitPos.p.z + distance * math.cos(worldAngle)
|
||||||
local candidateY = land.getHeight({ x = candidateX, y = candidateZ })
|
local candidateY = land.getHeight({ x = candidateX, y = candidateZ })
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe
|
|||||||
local BuildableMission = {}
|
local BuildableMission = {}
|
||||||
BuildableMission.__index = BuildableMission
|
BuildableMission.__index = BuildableMission
|
||||||
|
|
||||||
|
---@return string
|
||||||
local function getDefaultBriefing(siteType, coords)
|
local function getDefaultBriefing(siteType, coords)
|
||||||
return "We've dispatched forward units to find a proper spot for a new " .. siteType .. "." ..
|
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." ..
|
"\nYou will need to drop off supplies so they can start building." ..
|
||||||
@@ -48,7 +48,7 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
|
|||||||
setmetatable(BuildableMission, Mission)
|
setmetatable(BuildableMission, Mission)
|
||||||
|
|
||||||
local self = setmetatable({}, { __index = BuildableMission })
|
local self = setmetatable({}, { __index = BuildableMission })
|
||||||
|
|
||||||
self._targetZone = targetZone
|
self._targetZone = targetZone
|
||||||
self._database = database
|
self._database = database
|
||||||
self._requiredKilos = requiredKilos
|
self._requiredKilos = requiredKilos
|
||||||
@@ -75,7 +75,7 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
|
|||||||
end
|
end
|
||||||
|
|
||||||
self.code = tostring(database:GetNewMissionCode())
|
self.code = tostring(database:GetNewMissionCode())
|
||||||
|
|
||||||
local splitTargetZoneName = Util.split_string(targetZone.name, "_")
|
local splitTargetZoneName = Util.split_string(targetZone.name, "_")
|
||||||
if splitTargetZoneName and splitTargetZoneName[3] and splitTargetZoneName[3] ~= "" then
|
if splitTargetZoneName and splitTargetZoneName[3] and splitTargetZoneName[3] ~= "" then
|
||||||
self.name = splitTargetZoneName[3]
|
self.name = splitTargetZoneName[3]
|
||||||
@@ -83,13 +83,6 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
|
|||||||
self.name = "Resupply"
|
self.name = "Resupply"
|
||||||
end
|
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.zoneName = targetZone.name .. "_supply"
|
||||||
self._logger = logger
|
self._logger = logger
|
||||||
self._onCrateDroppedOfListeners = {}
|
self._onCrateDroppedOfListeners = {}
|
||||||
@@ -139,7 +132,7 @@ function BuildableMission:ShowBriefing(groupID)
|
|||||||
briefingPart = getDefaultBriefing(siteType, coords)
|
briefingPart = getDefaultBriefing(siteType, coords)
|
||||||
end
|
end
|
||||||
|
|
||||||
local briefing = "Mission [" .. self.code .. "] " .. self.name ..
|
local briefing = "Mission [" .. self.code .. "] " .. self.name ..
|
||||||
"\n \n" ..
|
"\n \n" ..
|
||||||
briefingPart ..
|
briefingPart ..
|
||||||
"\n\n" ..
|
"\n\n" ..
|
||||||
@@ -201,7 +194,7 @@ function BuildableMission:SpawnActive()
|
|||||||
local fillColor2 = DrawingHelper.ColorTableToColorString({ 0, 0, 1, 0})
|
local fillColor2 = DrawingHelper.ColorTableToColorString({ 0, 0, 1, 0})
|
||||||
self._dropOffZoneDrawing = CustomDrawing.FromZone(self._dropOffZone, lineColor2, fillColor2, 2, 6)
|
self._dropOffZoneDrawing = CustomDrawing.FromZone(self._dropOffZone, lineColor2, fillColor2, 2, 6)
|
||||||
self._dropOffZoneDrawing:Draw()
|
self._dropOffZoneDrawing:Draw()
|
||||||
|
|
||||||
---@param selfA BuildableMission
|
---@param selfA BuildableMission
|
||||||
---@param time number
|
---@param time number
|
||||||
local checkForCrateTasks = function (selfA, time)
|
local checkForCrateTasks = function (selfA, time)
|
||||||
@@ -266,8 +259,8 @@ function BuildableMission:CheckCratesInZone()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, foundCrate in pairs(foundCrates) do
|
for _, foundCrate in pairs(foundCrates) do
|
||||||
local crateConfig = SupplyConfigHelper.fromObjectName(foundCrate:getName())
|
local crateConfig = SupplyConfigHelper.fromObjectName(foundCrate:getName())
|
||||||
if crateConfig then
|
if crateConfig then
|
||||||
self._droppedKilos = self._droppedKilos + crateConfig.weight
|
self._droppedKilos = self._droppedKilos + crateConfig.weight
|
||||||
@@ -282,7 +275,7 @@ function BuildableMission:CheckCratesInZone()
|
|||||||
self:NotifyMissionComplete()
|
self:NotifyMissionComplete()
|
||||||
self._state = "COMPLETED"
|
self._state = "COMPLETED"
|
||||||
end
|
end
|
||||||
|
|
||||||
if self._state == "COMPLETED" then
|
if self._state == "COMPLETED" then
|
||||||
for groupID, markID in pairs(self._markIDsPerGroup) do
|
for groupID, markID in pairs(self._markIDsPerGroup) do
|
||||||
if markID then
|
if markID then
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ function RunwayStrikeMission.new(runway, airbaseName, database, logger, runwayBo
|
|||||||
self._runwayZone = self:RunwayToSpearheadZone(runway)
|
self._runwayZone = self:RunwayToSpearheadZone(runway)
|
||||||
self._repairInProgress = false
|
self._repairInProgress = false
|
||||||
self._minKilosForDamage = 100
|
self._minKilosForDamage = 100
|
||||||
|
|
||||||
local sections = self:ToSections(runway, 5)
|
local sections = self:ToSections(runway, 5)
|
||||||
--[[
|
--[[
|
||||||
+-----------+-----------+-----------+-----------+-----------+
|
+-----------+-----------+-----------+-----------+-----------+
|
||||||
@@ -84,7 +84,6 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
|
|||||||
|
|
||||||
self._logger:debug("Runway hit: " .. self._airportName .. ":" .. self._runway.Name)
|
self._logger:debug("Runway hit: " .. self._airportName .. ":" .. self._runway.Name)
|
||||||
for _, section in pairs(self._runwaySections) do
|
for _, section in pairs(self._runwaySections) do
|
||||||
|
|
||||||
local zone = self:SectionToSpearheadZone(section)
|
local zone = self:SectionToSpearheadZone(section)
|
||||||
if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
||||||
if section.kilosHit == nil then
|
if section.kilosHit == nil then
|
||||||
@@ -96,7 +95,7 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param selfA RunwayStrikeMission
|
---@param selfA RunwayStrikeMission
|
||||||
local updateState = function(selfA, time)
|
local updateState = function(selfA, _)
|
||||||
selfA:UpdateState()
|
selfA:UpdateState()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -154,7 +153,7 @@ function RunwayStrikeMission:Draw()
|
|||||||
|
|
||||||
if runwaySection.drawID == nil then
|
if runwaySection.drawID == nil then
|
||||||
local zone = self:SectionToSpearheadZone(runwaySection)
|
local zone = self:SectionToSpearheadZone(runwaySection)
|
||||||
|
|
||||||
---@type Free
|
---@type Free
|
||||||
local drawObject = {
|
local drawObject = {
|
||||||
primitiveType = "Polygon",
|
primitiveType = "Polygon",
|
||||||
@@ -213,7 +212,6 @@ function RunwayStrikeMission:StartRepair()
|
|||||||
if interval == nil then return nil end
|
if interval == nil then return nil end
|
||||||
return time + interval
|
return time + interval
|
||||||
end
|
end
|
||||||
|
|
||||||
timer.scheduleFunction(repairTask, self, timer.getTime() + 5)
|
timer.scheduleFunction(repairTask, self, timer.getTime() + 5)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ end
|
|||||||
---@return boolean
|
---@return boolean
|
||||||
function ZoneMission:AllDependenciesMet()
|
function ZoneMission:AllDependenciesMet()
|
||||||
local allDependenciesMet = true
|
local allDependenciesMet = true
|
||||||
for missionName, value in pairs(self._dependencies) do
|
for missionName, _ in pairs(self._dependencies) do
|
||||||
if self._parentStage:IsMissionComplete(missionName) == false then
|
if self._parentStage:IsMissionComplete(missionName) == false then
|
||||||
allDependenciesMet = false
|
allDependenciesMet = false
|
||||||
self._dependencies[missionName] = false
|
self._dependencies[missionName] = false
|
||||||
@@ -503,12 +503,12 @@ end
|
|||||||
---@param unit Object
|
---@param unit Object
|
||||||
function ZoneMission:MarkLastContact(unit)
|
function ZoneMission:MarkLastContact(unit)
|
||||||
|
|
||||||
if not unit then
|
if not unit then
|
||||||
self._logger:error("MarkLastContact called with nil unit")
|
self._logger:error("MarkLastContact called with nil unit")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local point = unit:getPoint()
|
local point = unit:getPoint()
|
||||||
if not point then
|
if not point then
|
||||||
self._logger:error("MarkLastContact called with unit without point")
|
self._logger:error("MarkLastContact called with unit without point")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ function Mission.newSuper(self, zoneName, missionName, missionType, missionBrief
|
|||||||
|
|
||||||
self.location = database:GetLocationForMissionZone(zoneName)
|
self.location = database:GetLocationForMissionZone(zoneName)
|
||||||
self.missionTypeDisplay = self.missionType
|
self.missionTypeDisplay = self.missionType
|
||||||
|
|
||||||
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate()
|
self._missionCommandsHelper = MissionCommandsHelper.getOrCreate()
|
||||||
|
|
||||||
return true, "success"
|
return true, "success"
|
||||||
@@ -70,6 +70,7 @@ function Mission:SpawnActive() end
|
|||||||
---comment
|
---comment
|
||||||
---@param checkHealth boolean
|
---@param checkHealth boolean
|
||||||
---@param messageIfDone boolean
|
---@param messageIfDone boolean
|
||||||
|
---@diagnostic disable-next-line: unused-local
|
||||||
function Mission:UpdateState(checkHealth, messageIfDone) end
|
function Mission:UpdateState(checkHealth, messageIfDone) end
|
||||||
function Mission:StartCheckingContinuous() end
|
function Mission:StartCheckingContinuous() end
|
||||||
|
|
||||||
@@ -120,7 +121,7 @@ function Mission:NotifyMissionComplete()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local succ, err = pcall(function()
|
local _, _ = pcall(function()
|
||||||
SpearheadAPI.Internal.notifyMissionComplete(self.zoneName)
|
SpearheadAPI.Internal.notifyMissionComplete(self.zoneName)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -131,6 +132,8 @@ function Mission:ForceMissionComplete()
|
|||||||
self:NotifyMissionComplete()
|
self:NotifyMissionComplete()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param groupId number
|
||||||
|
---@diagnostic disable-next-line: unused-local
|
||||||
function Mission:MarkMissionAreaToGroup(groupId) end
|
function Mission:MarkMissionAreaToGroup(groupId) end
|
||||||
|
|
||||||
---endregion
|
---endregion
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ do -- INIT DCS_UTIL
|
|||||||
do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment
|
do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment
|
||||||
|
|
||||||
do --init trigger zones
|
do --init trigger zones
|
||||||
for i, trigger_zone in pairs(env.mission.triggers.zones) do
|
for _, trigger_zone in pairs(env.mission.triggers.zones) do
|
||||||
-- reorder verts as they are not ordered correctly in the ME
|
-- reorder verts as they are not ordered correctly in the ME
|
||||||
local verts = {}
|
local verts = {}
|
||||||
if Util.tableLength(trigger_zone.verticies) >= 4 then
|
if Util.tableLength(trigger_zone.verticies) >= 4 then
|
||||||
@@ -192,7 +192,7 @@ do -- INIT DCS_UTIL
|
|||||||
BLUE = 2
|
BLUE = 2
|
||||||
}
|
}
|
||||||
]] --
|
]] --
|
||||||
local input = string.lower(input)
|
input = string.lower(input)
|
||||||
if input == 'neutrals' or input == "neutral" or input == "0" then
|
if input == 'neutrals' or input == "neutral" or input == "0" then
|
||||||
return DCS_UTIL.Coalition.NEUTRAL
|
return DCS_UTIL.Coalition.NEUTRAL
|
||||||
end
|
end
|
||||||
@@ -235,7 +235,7 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for index, zone_name in pairs(zone_names) do
|
for _, zone_name in pairs(zone_names) do
|
||||||
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
||||||
if zone then
|
if zone then
|
||||||
zones[#zones + 1] = zone
|
zones[#zones + 1] = zone
|
||||||
@@ -247,7 +247,7 @@ do -- INIT DCS_UTIL
|
|||||||
local lUnit = units[units_ind]
|
local lUnit = units[units_ind]
|
||||||
local unit_pos = lUnit:getPosition().p
|
local unit_pos = lUnit:getPosition().p
|
||||||
local lCat = Object.getCategory(lUnit)
|
local lCat = Object.getCategory(lUnit)
|
||||||
for zone_name, zone in pairs(zones) do
|
for _, 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
|
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)
|
local isInZone = Util.is3dPointInZone(unit_pos, zone)
|
||||||
if isInZone == true then
|
if isInZone == true then
|
||||||
@@ -313,7 +313,7 @@ do -- INIT DCS_UTIL
|
|||||||
function DCS_UTIL.isPositionInZones(x, z, zone_names)
|
function DCS_UTIL.isPositionInZones(x, z, zone_names)
|
||||||
---@type Array<SpearheadTriggerZone>
|
---@type Array<SpearheadTriggerZone>
|
||||||
local zones = {}
|
local zones = {}
|
||||||
for index, zone_name in pairs(zone_names) do
|
for _, zone_name in pairs(zone_names) do
|
||||||
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
||||||
if zone then
|
if zone then
|
||||||
zones[#zones + 1] = zone
|
zones[#zones + 1] = zone
|
||||||
@@ -321,7 +321,7 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
local result_zones = {}
|
local result_zones = {}
|
||||||
for zone_name, zone in pairs(zones) do
|
for _, zone in pairs(zones) do
|
||||||
if Util.is3dPointInZone({ x = x, z = z, y = 0 }, zone) == true then
|
if Util.is3dPointInZone({ x = x, z = z, y = 0 }, zone) == true then
|
||||||
result_zones[#result_zones + 1] = zone.name
|
result_zones[#result_zones + 1] = zone.name
|
||||||
end
|
end
|
||||||
@@ -414,7 +414,7 @@ do -- INIT DCS_UTIL
|
|||||||
local height = land.getHeight(location)
|
local height = land.getHeight(location)
|
||||||
local vec3 = { x = location.x, y = height, z = location.y }
|
local vec3 = { x = location.x, y = height, z = location.y }
|
||||||
|
|
||||||
local unitType = string.lower(unitType or "")
|
unitType = string.lower(unitType or "")
|
||||||
local conversionType = config[unitType]
|
local conversionType = config[unitType]
|
||||||
|
|
||||||
if not conversionType then conversionType = "DDM" end
|
if not conversionType then conversionType = "DDM" end
|
||||||
@@ -471,7 +471,7 @@ do -- INIT DCS_UTIL
|
|||||||
lon_hemisphere, math.abs(lon_deg), lon_min_display, lon_sec_display,
|
lon_hemisphere, math.abs(lon_deg), lon_min_display, lon_sec_display,
|
||||||
altitude * 3,28084)
|
altitude * 3,28084)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param zone SpearheadTriggerZone
|
---@param zone SpearheadTriggerZone
|
||||||
@@ -574,7 +574,7 @@ do -- INIT DCS_UTIL
|
|||||||
local units = {}
|
local units = {}
|
||||||
for i = 0, 2 do
|
for i = 0, 2 do
|
||||||
local players = coalition.getPlayers(i)
|
local players = coalition.getPlayers(i)
|
||||||
for key, unit in pairs(players) do
|
for _, unit in pairs(players) do
|
||||||
units[#units + 1] = unit
|
units[#units + 1] = unit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -617,8 +617,7 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
function DCS_UTIL.CleanCorpse(unitName)
|
function DCS_UTIL.CleanCorpse(unitName)
|
||||||
local unitName = "dead_" .. unitName
|
unitName = "dead_" .. unitName
|
||||||
|
|
||||||
local object = StaticObject.getByName(unitName)
|
local object = StaticObject.getByName(unitName)
|
||||||
|
|
||||||
if object then
|
if object then
|
||||||
@@ -632,11 +631,11 @@ do -- INIT DCS_UTIL
|
|||||||
---@field b number
|
---@field b number
|
||||||
---@field a number
|
---@field a number
|
||||||
|
|
||||||
local drawID = 4210
|
local __drawID = 4210
|
||||||
|
|
||||||
function DCS_UTIL.GetNextDrawID()
|
function DCS_UTIL.GetNextDrawID()
|
||||||
drawID = drawID + 1
|
__drawID = __drawID + 1
|
||||||
return drawID
|
return __drawID
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param groupID number
|
---@param groupID number
|
||||||
@@ -644,9 +643,9 @@ do -- INIT DCS_UTIL
|
|||||||
---@param location Vec3
|
---@param location Vec3
|
||||||
---@return number markID
|
---@return number markID
|
||||||
function DCS_UTIL.AddMarkToGroup(groupID, text, location)
|
function DCS_UTIL.AddMarkToGroup(groupID, text, location)
|
||||||
local drawID = DCS_UTIL.GetNextDrawID()
|
local nextId = DCS_UTIL.GetNextDrawID()
|
||||||
trigger.action.markToGroup(drawID, text, location, groupID, true, nil)
|
trigger.action.markToGroup(nextId, text, location, groupID, true, nil)
|
||||||
return drawID
|
return nextId
|
||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
@@ -654,9 +653,9 @@ do -- INIT DCS_UTIL
|
|||||||
---@param location Vec3
|
---@param location Vec3
|
||||||
---@return integer
|
---@return integer
|
||||||
function DCS_UTIL.AddMarkToAll(text, location)
|
function DCS_UTIL.AddMarkToAll(text, location)
|
||||||
local drawID = DCS_UTIL.GetNextDrawID()
|
local nextId = DCS_UTIL.GetNextDrawID()
|
||||||
trigger.action.markToAll(drawID, text, location, true, nil)
|
trigger.action.markToAll(nextId, text, location, true, nil)
|
||||||
return drawID
|
return nextId
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param markId number
|
---@param markId number
|
||||||
@@ -705,7 +704,7 @@ do -- INIT DCS_UTIL
|
|||||||
|
|
||||||
---@return number? id
|
---@return number? id
|
||||||
function DCS_UTIL.GetNeutralCountry()
|
function DCS_UTIL.GetNeutralCountry()
|
||||||
for name, id in pairs(country.id) do
|
for _, id in pairs(country.id) do
|
||||||
if coalition.getCountryCoalition(id) == DCS_UTIL.Coalition.NEUTRAL then
|
if coalition.getCountryCoalition(id) == DCS_UTIL.Coalition.NEUTRAL then
|
||||||
return id
|
return id
|
||||||
end
|
end
|
||||||
@@ -759,7 +758,7 @@ do -- INIT DCS_UTIL
|
|||||||
function DCS_UTIL.GetPlayerGroupByGroupID(groupId)
|
function DCS_UTIL.GetPlayerGroupByGroupID(groupId)
|
||||||
for i = 0, 2 do
|
for i = 0, 2 do
|
||||||
local players = coalition.getPlayers(i)
|
local players = coalition.getPlayers(i)
|
||||||
for key, unit in pairs(players) do
|
for _, unit in pairs(players) do
|
||||||
if unit and unit:isExist() == true then
|
if unit and unit:isExist() == true then
|
||||||
local group = unit:getGroup()
|
local group = unit:getGroup()
|
||||||
if group and group:getID() == groupId then
|
if group and group:getID() == groupId then
|
||||||
@@ -775,7 +774,7 @@ do -- INIT DCS_UTIL
|
|||||||
function DCS_UTIL.GetPlayerUnitByID(unitID)
|
function DCS_UTIL.GetPlayerUnitByID(unitID)
|
||||||
for i = 0, 2 do
|
for i = 0, 2 do
|
||||||
local players = coalition.getPlayers(i)
|
local players = coalition.getPlayers(i)
|
||||||
for key, unit in pairs(players) do
|
for _, unit in pairs(players) do
|
||||||
if unit and unit:getID() == unitID then
|
if unit and unit:getID() == unitID then
|
||||||
return unit
|
return unit
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ do -- INIT UTIL
|
|||||||
---@param findableTable table
|
---@param findableTable table
|
||||||
---@return boolean
|
---@return boolean
|
||||||
UTIL.startswithAny = function(str, findableTable)
|
UTIL.startswithAny = function(str, findableTable)
|
||||||
for key, value in pairs(findableTable) do
|
for _, value in pairs(findableTable) do
|
||||||
if type(value) == "string" and UTIL.startswith(str, value) then return true end
|
if type(value) == "string" and UTIL.startswith(str, value) then return true end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
@@ -237,8 +237,13 @@ do -- INIT UTIL
|
|||||||
|
|
||||||
return ((vec1Norm.x * vec2Norm.x) + (vec1Norm.y * vec2Norm.y) + (vec1Norm.z * vec2Norm.z))
|
return ((vec1Norm.x * vec2Norm.x) + (vec1Norm.y * vec2Norm.y) + (vec1Norm.z * vec2Norm.z))
|
||||||
end
|
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)
|
local function isInComplexPolygon(polygon, x, y)
|
||||||
|
---@param poly Array<Vec2> of pairs { x, y }
|
||||||
local function getEdges(poly)
|
local function getEdges(poly)
|
||||||
local result = {}
|
local result = {}
|
||||||
for i = 1, #poly do
|
for i = 1, #poly do
|
||||||
@@ -399,7 +404,9 @@ do -- INIT UTIL
|
|||||||
if #points == 0 then return {} end
|
if #points == 0 then return {} end
|
||||||
|
|
||||||
-- Simple clustering: group points that are within minSeparation of each other
|
-- Simple clustering: group points that are within minSeparation of each other
|
||||||
|
---@type Array<Array<Vec2>>
|
||||||
local clusters = {}
|
local clusters = {}
|
||||||
|
---@type table<integer, boolean>
|
||||||
local assigned = {}
|
local assigned = {}
|
||||||
|
|
||||||
for i, p in ipairs(points) do
|
for i, p in ipairs(points) do
|
||||||
|
|||||||
+1
-2
@@ -1,7 +1,6 @@
|
|||||||
--Single player purpose
|
--Single player purpose
|
||||||
|
|
||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
|
||||||
local Database = require("classes.spearhead_db")
|
local Database = require("classes.spearhead_db")
|
||||||
local SpearheadEvents = require("classes.spearhead_events")
|
local SpearheadEvents = require("classes.spearhead_events")
|
||||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||||
@@ -47,7 +46,7 @@ local spawnManager = SpawnManager.new(spawnLogger)
|
|||||||
local detectionLogger = Logger.new("DetectionManager", defaultLogLevel)
|
local detectionLogger = Logger.new("DetectionManager", defaultLogLevel)
|
||||||
local detectionManager = DetectionManager.New(detectionLogger)
|
local detectionManager = DetectionManager.New(detectionLogger)
|
||||||
|
|
||||||
GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager)
|
GlobalCapManager.start(databaseManager, capConfig, detectionManager, defaultLogLevel, spawnManager)
|
||||||
local globalStageManager = GlobalStageManager.new(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
local globalStageManager = GlobalStageManager.new(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
||||||
GlobalFleetManager.start(databaseManager)
|
GlobalFleetManager.start(databaseManager)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user