Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4683fb80c | ||
|
|
60a4d6e88c | ||
|
|
a351c45b73 | ||
|
|
e081b8e446 | ||
|
|
4b3d87f589 | ||
|
|
1fde8ec3b1 | ||
|
|
68e8d1c9ac | ||
|
|
ccd38078f3 | ||
|
|
de1e6ffae9 | ||
|
|
2a76df1e21 | ||
|
|
a55cd2bf2a | ||
|
|
d16e25531a | ||
|
|
30c7124a86 | ||
|
|
514a9a9c55 | ||
|
|
96fab864c3 | ||
|
|
0346f8a7a8 | ||
|
|
ba240db310 | ||
|
|
50f2a0eea0 | ||
|
|
70d18f4ac3 | ||
|
|
341590e981 | ||
|
|
233310209b | ||
|
|
2cae676a10 | ||
|
|
de81fdf419 |
@@ -169,7 +169,7 @@ 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>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,14 +26,14 @@
|
|||||||
|
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<h1>Advanced Tutorial: Missions</h1>
|
<h1>Advanced Tutorial: Missions</h1>
|
||||||
<div id="strike-region">
|
|
||||||
<h2 id="strike">Strike</h2>
|
<h2 id="strike">Strike</h2>
|
||||||
<p>
|
<p>
|
||||||
Naming: <code-inline>MISSION_STRIKE_[Name]</code-inline> <br>
|
Naming: <span class="inline-lua"><span class="lua-variable">MISSION_STRIKE_[Name]</span></span> <br>
|
||||||
</p>
|
</p>
|
||||||
<h3 id="specific_targets">Specific Targets</h3>
|
<h3 id="specific_targets">Specific Targets</h3>
|
||||||
<p>TBD</p>
|
<p>TBD</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="scenery_targets">Scenery Targets</h3>
|
<h3 id="scenery_targets">Scenery Targets</h3>
|
||||||
<p>
|
<p>
|
||||||
Bridges, buildings or other type of targets that are baked into the map are awesome targets.<br>
|
Bridges, buildings or other type of targets that are baked into the map are awesome targets.<br>
|
||||||
@@ -41,100 +41,24 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<note-box type="info" title="Implementation details">
|
<note-box type="info" title="Implementation details">
|
||||||
Spearhead detects scenery targets by the trigger zone name. A zone named
|
Spearhead detects scenery targets by the trigger zone name. A zone named <strong>scenerytarget_[freeform]</strong> or
|
||||||
<strong>scenerytarget_[freeform]</strong> or
|
<strong>scenerytargets</strong> (case-insensitive) will be scanned and any scenery objects that has the attribute "Buildings" inside the zone
|
||||||
<strong>scenerytargets</strong> (case-insensitive) will be scanned and any scenery objects that
|
|
||||||
has the attribute "Buildings" inside the zone
|
|
||||||
will be added as mission scenery targets.
|
will be added as mission scenery targets.
|
||||||
</note-box>
|
</note-box>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Scenery targets are treated like mission targets: they are included in the mission completion
|
Scenery targets are treated like mission targets: they are included in the mission completion calculation
|
||||||
calculation
|
(their `IsAlive()` state is checked) and their state is persisted/updated when missions spawn or resume.
|
||||||
(their `IsAlive()` state is checked) and their state is persisted/updated when missions spawn or
|
|
||||||
resume.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<note-box type="warning" title="Changing IDs">
|
<note-box type="warning" title="Changing IDs">
|
||||||
Due to Object IDs changing when maps are updated and edited the "Assign as..." functionality
|
Due to Object IDs changing when maps are updated and edited the "Assign as..." functionality does not work for scenery targets.
|
||||||
does not work for scenery targets.
|
|
||||||
Hence the need to use trigger zones to define them.
|
Hence the need to use trigger zones to define them.
|
||||||
</note-box>
|
</note-box>
|
||||||
|
|
||||||
|
|
||||||
<p>Here's two images showing how a bridge is added to a mission.</p>
|
<p>Here's two images showing how a bridge is added to a mission.</p>
|
||||||
<img src="/img/bridge.png" style="max-height: 35remrem;" />
|
<img src="/img/bridge.png" style="max-height: 35remrem;"/>
|
||||||
</div>
|
|
||||||
<div id="cas-region">
|
|
||||||
<h2 id="cas">CAS</h2>
|
|
||||||
<p>
|
|
||||||
Naming: <code-inline>MISSION_CAS_[Name]</code-inline> <br>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="BattleManager">Battle Manager</h3>
|
|
||||||
<p>TBD</p>
|
|
||||||
</div>
|
|
||||||
<div id="dead-region">
|
|
||||||
<h2 id="dead">DEAD</h2>
|
|
||||||
<p>
|
|
||||||
Naming: <code-inline>MISSION_DEAD_[Name]</code-inline> <br>
|
|
||||||
Naming: <code-inline>MISSION_SAM_[Name]</code-inline> <br>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="sam-vs-dead">SAM vs DEAD</h3>
|
|
||||||
<p>TBD</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="bai-region">
|
|
||||||
<h2 id="bai">BAI</h2>
|
|
||||||
<p>
|
|
||||||
Naming: <code-inline>MISSION_BAI_[Name]</code-inline> <br>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="deepstrike-region">
|
|
||||||
<h2 id="deepstrike">DEEPSTRIKE</h2>
|
|
||||||
<p>
|
|
||||||
Naming: <code-inline>MISSION_DEEPSTRIKE_[Name]</code-inline> <br>
|
|
||||||
<br>
|
|
||||||
When you, as a mission editor, want to create a mission that's further away from the current front-line you can use the Deep Strike mission type. <br>
|
|
||||||
This allows you to plan missions that require more strategic positioning and timing. <br>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="activation">Activation</h3>
|
|
||||||
<p>
|
|
||||||
Deep Strike missions are activated when the Stage in which they are located becomes "PreActive" or "Active". <br>
|
|
||||||
"PreActive" is when either the current active StageNumber is a certain number of stages away OR the stage has "CAP" airbases active . <br>
|
|
||||||
<code-inline>SpearheadConfig.StageConfig.preactivateStage</code-inline> changes the configuration. <br>
|
|
||||||
<br>
|
|
||||||
For example: <br>
|
|
||||||
If the current active stage is <code-inline>MissionStage_2_[name]</code-inline> and preActivate config is set to 2. <br>
|
|
||||||
Then both <code-inline>MissionStage_3_[name]</code-inline> and <code-inline>MissionStage_4_[name]</code-inline> would become "PreActive".
|
|
||||||
</p>
|
|
||||||
<h3 id="primary-vs-secondary">Make Primary</h3>
|
|
||||||
<p>
|
|
||||||
By default DEEPSTRIKE missions are "Secondary" missions when spawned as a pre-activated stage.<br>
|
|
||||||
Then when the stage they are in is "Active", the mission becomes a "Primary" mission. <br>
|
|
||||||
<br>
|
|
||||||
If you want to make it a "Primary" mission from the start, you can overwrite it.<br>
|
|
||||||
Click the mission's trigger zone. Add a property named <code-inline>primary</code-inline> and set it to <code-inline>true</code-inline>.
|
|
||||||
This will make the mission "Primary" from the start. <br>
|
|
||||||
<br>
|
|
||||||
If you want it to "Secondary" even when its stage is the active stage, you can set "primary" to false. <br>
|
|
||||||
<br>
|
|
||||||
If you want to have it be "Secondary" when its stage is "Pre-Active" and "primary" when its stage is "Active" you don't have to do anything.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="future-additions">Future</h3>
|
|
||||||
<p>
|
|
||||||
In the future we're thinking it would be cool to make the Deep Strike missions
|
|
||||||
be more integrated with the CAP airbases and/or logistics. <br>
|
|
||||||
Eg. Completing a DEEPSTRIKE mission would disable CAP for X amount of minutes after completion. <br>
|
|
||||||
This still needs to be refined, but we've already have ideas.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
--color-bg-hover: rgba(120, 140, 255, 0.12); /* More visible hover */
|
--color-bg-hover: rgba(120, 140, 255, 0.12); /* More visible hover */
|
||||||
--color-bg-note-dark: rgba(40, 35, 30, 0.85); /* Slightly darker note box */
|
--color-bg-note-dark: rgba(40, 35, 30, 0.85); /* Slightly darker note box */
|
||||||
|
|
||||||
--color-text-primary: #b4b3b3; /* Brighter text */
|
--color-text-primary: #a5a5a5; /* Brighter text */
|
||||||
--color-text-secondary: #bfc8d8; /* Lighter secondary text */
|
--color-text-secondary: #bfc8d8; /* Lighter secondary text */
|
||||||
--color-text-accent: #7ecbff; /* Brighter accent */
|
--color-text-accent: #7ecbff; /* Brighter accent */
|
||||||
--color-text-light: #ffffff;
|
--color-text-light: #ffffff;
|
||||||
|
|||||||
+2
-66
@@ -24,7 +24,7 @@ jobs:
|
|||||||
luaVersion: ${{ env.LUA_VERSION }}
|
luaVersion: ${{ env.LUA_VERSION }}
|
||||||
|
|
||||||
- name: Compile Spearhead
|
- name: Compile Spearhead
|
||||||
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-actions/bundle-script@bundle-script/v1
|
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-action@action/v0
|
||||||
with:
|
with:
|
||||||
source-root: ./src
|
source-root: ./src
|
||||||
output-file: ./output/spearhead.lua
|
output-file: ./output/spearhead.lua
|
||||||
@@ -38,39 +38,6 @@ jobs:
|
|||||||
- name: Install luacheck
|
- name: Install luacheck
|
||||||
run: luarocks install luacheck
|
run: luarocks install luacheck
|
||||||
|
|
||||||
# "lfs",
|
|
||||||
# "setmetatable", "getmetatable", "table", "string", "math", "pairs", "ipairs",
|
|
||||||
# "require", "type", "tostring", "io", "error", "pcall", "tonumber",
|
|
||||||
# "loadstring",
|
|
||||||
|
|
||||||
- name: Create LuaCheck Config
|
|
||||||
run: |
|
|
||||||
cat << EOF > .luacheckrc
|
|
||||||
|
|
||||||
stds.spearhead_lib = {
|
|
||||||
globals = {
|
|
||||||
"SpearheadConfig", "SpearheadAPI", "GlobalCapCallBacks",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stds.dcs_lib = {
|
|
||||||
globals = {
|
|
||||||
"env", "net", "trigger", "timer", "Object", "land", "coord", "coalition",
|
|
||||||
"Unit", "Group", "Airbase", "StaticObject", "SceneryObject", "world",
|
|
||||||
"country", "missionCommands", "Controller", "Weapon", "atmosphere", "country",
|
|
||||||
"lfs", "AI"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std = "lua51c+spearhead_lib+dcs_lib"
|
|
||||||
self = false
|
|
||||||
|
|
||||||
max_line_length = false
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Show LuaCheck Config
|
|
||||||
run: cat .luacheckrc
|
|
||||||
|
|
||||||
- name: Lint Compiled Output
|
- name: Lint Compiled Output
|
||||||
run: luacheck ./output/spearhead.lua
|
run: luacheck ./output/spearhead.lua
|
||||||
|
|
||||||
@@ -91,9 +58,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
destination-path: "./.vscode/lua-addons" ##same as local so .luarc.json can be the same
|
destination-path: "./.vscode/lua-addons" ##same as local so .luarc.json can be the same
|
||||||
|
|
||||||
- name: Verify Dcs Plugins Installation
|
|
||||||
run: ls -la ./.vscode/lua-addons
|
|
||||||
|
|
||||||
- name: Install lua-language-server
|
- name: Install lua-language-server
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ./luals
|
mkdir -p ./luals
|
||||||
@@ -105,36 +69,8 @@ jobs:
|
|||||||
- name: Verify Lua Language Server Installation
|
- name: Verify Lua Language Server Installation
|
||||||
run: ./luals/bin/lua-language-server --version
|
run: ./luals/bin/lua-language-server --version
|
||||||
|
|
||||||
- name: Update Json
|
|
||||||
run: |
|
|
||||||
FULL_PATH=$(realpath ./.vscode/lua-addons)
|
|
||||||
echo "full-path: $FULL_PATH"
|
|
||||||
ls -R $FULL_PATH
|
|
||||||
|
|
||||||
echo "Updating .luarc.json with full path"
|
|
||||||
jq --arg full_path "$FULL_PATH" '.workspace.library[0] = $full_path' ./.luarc.json > ./.luarc.tmp.json
|
|
||||||
mv ./.luarc.tmp.json ./.luarc.json
|
|
||||||
|
|
||||||
- name: Show Config
|
|
||||||
run: cat ./.luarc.json
|
|
||||||
|
|
||||||
- name: Run Lua Language Server
|
- name: Run Lua Language Server
|
||||||
run: |
|
run: ./luals/bin/lua-language-server --check ./src --checklevel=Warning
|
||||||
CONFIG_FULL_PATH=$(realpath ./.luarc.json)
|
|
||||||
echo "Config full path: $CONFIG_FULL_PATH"
|
|
||||||
|
|
||||||
|
|
||||||
./luals/bin/lua-language-server \
|
|
||||||
--check ./src \
|
|
||||||
--checklevel=Warning \
|
|
||||||
--loglevel=trace \
|
|
||||||
--logpath="./luals/logs" \
|
|
||||||
--configpath="$CONFIG_FULL_PATH" \
|
|
||||||
# --develop
|
|
||||||
|
|
||||||
- name: Show Log
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
ls -R ./luals/logs
|
|
||||||
|
|
||||||
cat ./luals/logs/* || true
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Publish Beta Release
|
name: Publish Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
echo "EOF" >> "$GITHUB_OUTPUT"
|
echo "EOF" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Compile Spearhead
|
- name: Compile Spearhead
|
||||||
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-actions/bundle-script@bundle-script/v1
|
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-action@action/v0
|
||||||
with:
|
with:
|
||||||
source-root: ./src
|
source-root: ./src
|
||||||
output-file: ./output/spearhead.lua
|
output-file: ./output/spearhead.lua
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
echo "EOF" >> "$GITHUB_OUTPUT"
|
echo "EOF" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Compile Spearhead
|
- name: Compile Spearhead
|
||||||
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-actions/bundle-script@bundle-script/v1
|
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-action@action/v0
|
||||||
with:
|
with:
|
||||||
source-root: ./src
|
source-root: ./src
|
||||||
output-file: ./output/spearhead.lua
|
output-file: ./output/spearhead.lua
|
||||||
|
|||||||
+10
-21
@@ -1,30 +1,21 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
"Lua": {
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"version": "Lua 5.1"
|
"version": "Lua 5.1"
|
||||||
},
|
},
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"checkThirdParty": false,
|
"checkThirdParty": false
|
||||||
"maxPreload": 1600,
|
|
||||||
"preloadFileSize": 1000,
|
|
||||||
"ignoreDir": [ "config.lua" ]
|
|
||||||
},
|
},
|
||||||
"diagnostics": {
|
"diagnostics": {
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"globals": [
|
"globals": [
|
||||||
"lfs"
|
"lfs"
|
||||||
],
|
],
|
||||||
"groupSeverity": {
|
"severity": {
|
||||||
"duplicate": "Warning",
|
"undefined-field": "Warning",
|
||||||
"global":"Warning",
|
"unused-local": "Warning",
|
||||||
"luadoc": "Warning",
|
"unused-function": "Warning"
|
||||||
"redefined": "Warning",
|
|
||||||
"strong": "Warning",
|
|
||||||
"type-check": "Warning",
|
|
||||||
"unbalanced" : "Warning",
|
|
||||||
"ambiguity": "Warning",
|
|
||||||
"strict": "Warning",
|
|
||||||
"unused": "Warning"
|
|
||||||
},
|
},
|
||||||
"groupFileStatus": {
|
"groupFileStatus": {
|
||||||
"ambiguity": "Any",
|
"ambiguity": "Any",
|
||||||
@@ -36,11 +27,8 @@
|
|||||||
"strict": "Any",
|
"strict": "Any",
|
||||||
"type-check": "Any",
|
"type-check": "Any",
|
||||||
"unbalanced": "Any",
|
"unbalanced": "Any",
|
||||||
"unused": "Any",
|
"unused": "Any"
|
||||||
"strong": "Any"
|
}
|
||||||
},
|
|
||||||
"ignoredFiles": "Opened",
|
|
||||||
"libraryFiles": "Opened"
|
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"enable": false
|
"enable": false
|
||||||
@@ -48,4 +36,5 @@
|
|||||||
"completion": {
|
"completion": {
|
||||||
"enable": true
|
"enable": true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,43 +1,53 @@
|
|||||||
# Spearhead
|
# Spearhead
|
||||||
|
|
||||||
Hello and welcome to Spearhead!
|
|
||||||
|
|
||||||
If you're a developer that wants to contribute, look at the code or understand what we're doing, feel free to read on.
|
## Contributing.
|
||||||
|
|
||||||
If you're a mission maker that wants to see the documentation and build you mission with this framework. <br>
|
I'm always happy to see contributions! <br/>
|
||||||
It's best to go to our fully fledged documentation website:
|
Especially if you've found an issue, annoyance or feature that you know how to solve, fix or create! <br/>
|
||||||
- Stable/Main: https://spearhead.rocks
|
|
||||||
- Beta/Develop: https://beta.spearhead.rocks
|
|
||||||
|
|
||||||
## Project Structure
|
### Keep it small.
|
||||||
|
|
||||||
The Spearhead project is structured in a lot of separate files. <br>
|
Keeping your contributions small and to the point helps both me and yourself. <br/>
|
||||||
While Lua isn't specifically created for it, most of it has been written with the standards of OOP in mind. <br>
|
It'll help the PR review and the speed of improvements. <br/>
|
||||||
Classes, Objects and helper methods.
|
If you have a big feature in mind? Go for it! <br/>
|
||||||
|
Does it require an entire refactor of parts or all of the program? Maybe make sure to do step 0 first.
|
||||||
|
|
||||||
You're find in the `/src` folder all the files. <br>
|
### Steps (for first timers)
|
||||||
They are separated in a somewhat logical order, but some things might feel out of place. <br>
|
0. Reach out (Optional)
|
||||||
|
|
||||||
### Bundling, Intellisense, Linting
|
If you want to let me know you want to do something to contribute, please do! <br/>
|
||||||
|
Maybe I'm already working on the thing you wanted to build, or someone else is. <br/>
|
||||||
|
Creating an issue is even better! <br/>
|
||||||
|
|
||||||
In DCS the easiest way to import a script is with 1 single file, however, that's not as "maintainable".
|
|
||||||
In order to keep it maintainable we're using a self-built tool to bundle, validate and rewrite some of the lua in order to get it into a single file.
|
|
||||||
The tool is open-source here: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools. <br>
|
|
||||||
It has a `VSCode` extensions and two `Github Action` steps. <br>
|
|
||||||
If your favorite IDE isn't `VSCode` (I respect that), it might be very easy to create an extension for it, if it does allow that.
|
|
||||||
|
|
||||||
The `VSCode` extensions comes with Intellisense as well, in the form of a full file of DCS lua type annotations. <br>
|
1. Fork the repository
|
||||||
This gives the Lua Language Server by Sumneko (which can be used in `VSCode`) all the type definitions it needs.
|
|
||||||
When writing Spearhead code it is also important to keep our own LuaLS Annotations up to date and complete. <br>
|
|
||||||
Read all about those annotations here: https://luals.github.io/wiki/annotations/
|
|
||||||
|
|
||||||
When a pull-request to the `develop` or `main` branches is created, before it can be merged it requires to pass the linter checks.
|
By forking you can create your own working set of code. <br/>
|
||||||
The first linting check is done by the Lua Language Server. It checks for whitespace and formatting, but it also checks if all types, type-checking and casts are in order. It marks unused variables etc. `.luarc.json` has all the config for those checks. <br>
|
Whether you keep that fork public or private is up to you! <br/>
|
||||||
The second linter job is with `luacheck` which first "bundles" the script, and then runs a full linter check over the bundled script. <br>
|
|
||||||
This is to make sure that also the bundled script does not contain any errors.
|
|
||||||
|
|
||||||
## Contributing
|
Keep in mind, forking is alright, but it's best with the intent to contribute back. <br/>
|
||||||
|
After all, instead of having 5 slightly different versions and products, it might be nicer to have 1 much better version. <br/>
|
||||||
|
|
||||||
### Setting up the project
|
2. Create a Draft PR as soon as possible!
|
||||||
|
|
||||||
If you've kept on reading I assume you either want to brwose
|
As soon as you've found some times to create an initial version, please create a draft PR. <br/>
|
||||||
|
That way you can let me and everyone know it's being worked on and people can see what conflicts might arise with their own changes. <br/>
|
||||||
|
|
||||||
|
3. Test, test, test
|
||||||
|
|
||||||
|
With DCS and Lua there's a bunch of edge cases that are really hard to get to. <br/>
|
||||||
|
However, you kinda need to make sure most if not all cases are caught and tested. <br/>
|
||||||
|
Since automated testing for now doesn't seem feasible, please make sure to verify and test functionality after touching stuff. <br/>
|
||||||
|
|
||||||
|
4. Finalise and publish the PR.
|
||||||
|
|
||||||
|
Finalise the PR and let the maintainers know! <br/>
|
||||||
|
We can all have a look and discuss the changes. <br/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
|
||||||
|
- Would it be possible to generate optional markers on mission briefing locations for Tomcat / Phantom navigation? Then Jester can type it in for the pilots automatically.
|
||||||
|
|||||||
+8
-10
@@ -5,21 +5,19 @@
|
|||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
- Addresses #41
|
- Issue: #41
|
||||||
Adds Stage Complete debug methods for local testing of the Stage flow.
|
Adds Stage Complete debug methods for local testing of the Stage flow.
|
||||||
PR #40
|
#40
|
||||||
- Closes #35
|
|
||||||
|
- Issue: #35
|
||||||
Creating Lane option for stages.
|
Creating Lane option for stages.
|
||||||
Additionally to the primary stage lane, stages can now be created in different lanes.
|
Additionally to the primary stage lane, stages can now be created in different lanes.
|
||||||
These lanes can be used to create different stage progression flows and create different "side-stories".
|
These lanes can be used to create different stage progression flows and create different "side-stories".
|
||||||
PR #40
|
#40
|
||||||
- Closes #37
|
|
||||||
|
- Issue: #37
|
||||||
Now enabled the mission editor to add a custom briefing to the "Buildable" missions.
|
Now enabled the mission editor to add a custom briefing to the "Buildable" missions.
|
||||||
PR #44
|
#44
|
||||||
- Closes #42
|
|
||||||
DEEPSTRIKE now added as a possible feature.
|
|
||||||
This enables to have missions active in "Pre-Activated" Stages.
|
|
||||||
PR #48
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
---@class Queue
|
||||||
|
---@field private _items Array
|
||||||
|
---@field private _first number
|
||||||
|
---@field private _last number
|
||||||
|
local Queue = {}
|
||||||
|
Queue.__index = Queue
|
||||||
|
|
||||||
|
---@return Queue
|
||||||
|
function Queue.new()
|
||||||
|
|
||||||
|
local self = setmetatable({}, Queue)
|
||||||
|
self._items = {}
|
||||||
|
self._first = 1
|
||||||
|
self._last = 0
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return nil
|
||||||
|
function Queue:push(item)
|
||||||
|
self._last = self._last + 1
|
||||||
|
self._items[self._last] = item
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return any?
|
||||||
|
function Queue:pop()
|
||||||
|
if self._first > self._last then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local item = self._items[self._first]
|
||||||
|
self._items[self._first] = nil
|
||||||
|
self._first = self._first + 1
|
||||||
|
return item
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---@return Array<any>
|
||||||
|
function Queue:toList()
|
||||||
|
local items = {}
|
||||||
|
for i = self._first, self._last do
|
||||||
|
items[#items + 1] = self._items[i]
|
||||||
|
end
|
||||||
|
return items
|
||||||
|
end
|
||||||
|
|
||||||
|
return Queue
|
||||||
@@ -6,9 +6,7 @@ local CapAirbase = require("classes.capClasses.CapAirbase")
|
|||||||
---@class GlobalCapManager
|
---@class GlobalCapManager
|
||||||
local GlobalCapManager = {}
|
local GlobalCapManager = {}
|
||||||
do
|
do
|
||||||
---@type table<string, CapBase[]>
|
|
||||||
local airbasesPerStage = {}
|
local airbasesPerStage = {}
|
||||||
---@type table<string, CapBase>
|
|
||||||
local allAirbasesByName = {}
|
local allAirbasesByName = {}
|
||||||
local initiated = false
|
local initiated = false
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ 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")
|
||||||
|
|
||||||
---@class AirGroup : OnUnitLostListener, OnGroupRTBListener, OnGroupRTBInTenListener, OnLandEventListener, OnGroupOnStationListener
|
---@class AirGroup : OnUnitLostListener
|
||||||
---@field protected _logger Logger
|
---@field protected _logger Logger
|
||||||
---@field protected _groupName string
|
---@field protected _groupName string
|
||||||
---@field protected _groupType AirGroupType
|
---@field protected _groupType AirGroupType
|
||||||
@@ -107,9 +107,8 @@ function AirGroup:SetMissionPrivate(mission)
|
|||||||
|
|
||||||
local points = {}
|
local points = {}
|
||||||
if mission and mission.params and mission.params.route and mission.params.route.points then
|
if mission and mission.params and mission.params.route and mission.params.route.points then
|
||||||
local routePoints = mission.params.route.points --[[@as Array<Vec2> ]]
|
for _, wp in pairs(mission.params.route.points) do
|
||||||
for _, wp in pairs(routePoints) do
|
if wp.x and wp.y then
|
||||||
if wp and wp.x and wp.y then
|
|
||||||
table.insert(points, { x = wp.x, y = wp.y })
|
table.insert(points, { x = wp.x, y = wp.y })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -199,8 +198,6 @@ function AirGroup:SpawnInternal(force, withoutLoadout)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param selfA AirGroup
|
---@param selfA AirGroup
|
||||||
---@param time number
|
|
||||||
---@return number?
|
|
||||||
local function CheckLivenessTask(selfA, time)
|
local function CheckLivenessTask(selfA, time)
|
||||||
local interval = selfA:CheckLiveness()
|
local interval = selfA:CheckLiveness()
|
||||||
if not interval then return end
|
if not interval then return end
|
||||||
@@ -266,7 +263,6 @@ function AirGroup:OnLastUnitLanded()
|
|||||||
|
|
||||||
---@param data CheckGroupForRestartData
|
---@param data CheckGroupForRestartData
|
||||||
---@param time number
|
---@param time number
|
||||||
---@return number?
|
|
||||||
local checkGroupForRestart = function(data, time)
|
local checkGroupForRestart = function(data, time)
|
||||||
local group = Group.getByName(data.self:GetName())
|
local group = Group.getByName(data.self:GetName())
|
||||||
if not group then
|
if not group then
|
||||||
|
|||||||
@@ -34,10 +34,9 @@ function CapGroup:IsBackup()
|
|||||||
return self._isBackup
|
return self._isBackup
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stageID string
|
|
||||||
---@return string?
|
---@return string?
|
||||||
function CapGroup:GetZoneIDWhenStageID(stageID)
|
function CapGroup:GetZoneIDWhenStageID(stageID)
|
||||||
return self._targetZoneIdPerStage[tostring(stageID)]
|
return self._targetZoneIdPerStage[stageID]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return string?
|
---@return string?
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ end
|
|||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param units Array<string>
|
---@param units Array<string>
|
||||||
---@param zoneName string
|
|
||||||
---@param homeAirbase Airbase
|
---@param homeAirbase Airbase
|
||||||
function InterceptGroup:SendToInterceptUnits(units, zoneName, homeAirbase)
|
function InterceptGroup:SendToInterceptUnits(units, zoneName, homeAirbase)
|
||||||
|
|
||||||
@@ -69,10 +68,9 @@ function InterceptGroup:SendToInterceptUnits(units, zoneName, homeAirbase)
|
|||||||
self:SetTargetUnits(units)
|
self:SetTargetUnits(units)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stageID string
|
|
||||||
---@return string?
|
---@return string?
|
||||||
function InterceptGroup:GetZoneIDWhenStageID(stageID)
|
function InterceptGroup:GetZoneIDWhenStageID(stageID)
|
||||||
return self._targetZoneIdPerStage[tostring(stageID)]
|
return self._targetZoneIdPerStage[stageID]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return string?
|
---@return string?
|
||||||
@@ -93,9 +91,6 @@ function InterceptGroup:SetTargetUnits(unitNames)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param selfA InterceptGroup
|
|
||||||
---@param time number
|
|
||||||
---@return number?
|
|
||||||
local updateContinous = function(selfA, time)
|
local updateContinous = function(selfA, time)
|
||||||
local next = selfA:UpdateTask()
|
local next = selfA:UpdateTask()
|
||||||
if next then
|
if next then
|
||||||
@@ -107,7 +102,6 @@ function InterceptGroup:SetTargetUnits(unitNames)
|
|||||||
self._updateTaskID = timer.scheduleFunction(updateContinous, self, timer.getTime() + 30)
|
self._updateTaskID = timer.scheduleFunction(updateContinous, self, timer.getTime() + 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param unit Unit
|
|
||||||
function InterceptGroup:RemoveTargetUnit(unit)
|
function InterceptGroup:RemoveTargetUnit(unit)
|
||||||
|
|
||||||
if not unit then return end
|
if not unit then return end
|
||||||
@@ -226,8 +220,7 @@ function InterceptGroup:UpdateTask()
|
|||||||
return 30 -- Return to base if no intercept point could be calculated
|
return 30 -- Return to base if no intercept point could be calculated
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type table
|
local mission = nil
|
||||||
local mission
|
|
||||||
if self:IsInAir() == true then
|
if self:IsInAir() == true then
|
||||||
-- If the group is in the air, create an intercept mission
|
-- If the group is in the air, create an intercept mission
|
||||||
mission = INTERCEPT.getMissionFromInAir(
|
mission = INTERCEPT.getMissionFromInAir(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ local Util = require("classes.util.Util")
|
|||||||
local MissionEditorWarner = require("classes.util.MissionEditorWarnings")
|
local MissionEditorWarner = require("classes.util.MissionEditorWarnings")
|
||||||
|
|
||||||
---@class SweepGroup : AirGroup
|
---@class SweepGroup : AirGroup
|
||||||
---@field _targetZoneIdPerStage table<string, string>
|
---@field _targetZoneIdPerStage table<number, string>
|
||||||
---@field _currentTargetZoneID string?
|
---@field _currentTargetZoneID string?
|
||||||
local SweepGroup = {}
|
local SweepGroup = {}
|
||||||
SweepGroup.__index = SweepGroup
|
SweepGroup.__index = SweepGroup
|
||||||
@@ -26,10 +26,9 @@ function SweepGroup.New(groupName, config, logger, spawnManager)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stageID string
|
|
||||||
---@return string?
|
---@return string?
|
||||||
function SweepGroup:GetZoneIDWhenStageID(stageID)
|
function SweepGroup:GetZoneIDWhenStageID(stageID)
|
||||||
return self._targetZoneIdPerStage[tostring(stageID)]
|
return self._targetZoneIdPerStage[stageID]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return string?
|
---@return string?
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ DetectionManager.__index = DetectionManager
|
|||||||
|
|
||||||
|
|
||||||
---@param logger Logger
|
---@param logger Logger
|
||||||
---@return DetectionManager
|
|
||||||
function DetectionManager.New(logger)
|
function DetectionManager.New(logger)
|
||||||
local self = setmetatable({}, DetectionManager)
|
local self = setmetatable({}, DetectionManager)
|
||||||
|
|
||||||
@@ -25,7 +24,6 @@ function DetectionManager.New(logger)
|
|||||||
|
|
||||||
---@param selfA DetectionManager
|
---@param selfA DetectionManager
|
||||||
---@param time number
|
---@param time number
|
||||||
---@return number?
|
|
||||||
local updateDetectingUnitsTask = function(selfA, time)
|
local updateDetectingUnitsTask = function(selfA, time)
|
||||||
selfA:UpdateDetectingUnits()
|
selfA:UpdateDetectingUnits()
|
||||||
return time + 120
|
return time + 120
|
||||||
@@ -34,7 +32,6 @@ function DetectionManager.New(logger)
|
|||||||
|
|
||||||
---@param selfA DetectionManager
|
---@param selfA DetectionManager
|
||||||
---@param time number
|
---@param time number
|
||||||
---@return number?
|
|
||||||
local updateDetected = function(selfA, time)
|
local updateDetected = function(selfA, time)
|
||||||
selfA:UpdateDetectedUnits()
|
selfA:UpdateDetectedUnits()
|
||||||
return time + 10
|
return time + 10
|
||||||
@@ -46,7 +43,6 @@ end
|
|||||||
|
|
||||||
---@param unitName string
|
---@param unitName string
|
||||||
---@param coalitionSide CoalitionSide
|
---@param coalitionSide CoalitionSide
|
||||||
---@return boolean
|
|
||||||
function DetectionManager:IsUnitDetectedBy(unitName, coalitionSide)
|
function DetectionManager:IsUnitDetectedBy(unitName, coalitionSide)
|
||||||
local coalitionString = tostring(coalitionSide)
|
local coalitionString = tostring(coalitionSide)
|
||||||
if not self._detectedUnits[coalitionString] then
|
if not self._detectedUnits[coalitionString] then
|
||||||
@@ -60,8 +56,7 @@ function DetectionManager:IsUnitDetectedBy(unitName, coalitionSide)
|
|||||||
return timer.getTime() - self._detectedUnits[coalitionString][unitName] < 20
|
return timer.getTime() - self._detectedUnits[coalitionString][unitName] < 20
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param coalitionSide CoalitionSide
|
---@return Array<string>
|
||||||
---@return Array<string> detectedUnits
|
|
||||||
function DetectionManager:GetDetectedUnitsBy(coalitionSide)
|
function DetectionManager:GetDetectedUnitsBy(coalitionSide)
|
||||||
local coalitionString = tostring(coalitionSide)
|
local coalitionString = tostring(coalitionSide)
|
||||||
if not self._detectedUnits[coalitionString] then
|
if not self._detectedUnits[coalitionString] then
|
||||||
|
|||||||
@@ -56,9 +56,7 @@ end
|
|||||||
---@field self RunwayBombingTracker
|
---@field self RunwayBombingTracker
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
---@param time number
|
|
||||||
---@param weaponTrackingArgs WeaponTrackingArgs
|
---@param weaponTrackingArgs WeaponTrackingArgs
|
||||||
---@return number?
|
|
||||||
function RunwayBombingTracker.trackWeaponTask(weaponTrackingArgs, time)
|
function RunwayBombingTracker.trackWeaponTask(weaponTrackingArgs, time)
|
||||||
|
|
||||||
local weapon = weaponTrackingArgs.weapon
|
local weapon = weaponTrackingArgs.weapon
|
||||||
@@ -104,10 +102,11 @@ function RunwayBombingTracker:OnWeaponImpact(weaponDesc, impactPoint)
|
|||||||
|
|
||||||
self._logger:debug("RunwayBombingTracker:OnWeaponImpact")
|
self._logger:debug("RunwayBombingTracker:OnWeaponImpact")
|
||||||
|
|
||||||
local warhead = weaponDesc.warhead --[[@as table]]
|
local warhead = weaponDesc.warhead
|
||||||
local explosiveMass = (warhead.explosiveMass or warhead.shapedExplosiveMass) --[[@as number]]
|
local explosiveMass = warhead.explosiveMass or warhead.shapedExplosiveMass
|
||||||
|
|
||||||
for _, strikeMission in pairs(self.trackedRunways) do
|
for _, strikeMission in pairs(self.trackedRunways) do
|
||||||
|
|
||||||
local zone= strikeMission:GetRunwayZone()
|
local zone= strikeMission:GetRunwayZone()
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ local CAP = {}
|
|||||||
---@param attackHelos boolean
|
---@param attackHelos boolean
|
||||||
---@return table
|
---@return table
|
||||||
local function GetCAPTargetTypes(attackHelos)
|
local function GetCAPTargetTypes(attackHelos)
|
||||||
---@type Array<string>
|
|
||||||
local targetTypes = {
|
local targetTypes = {
|
||||||
[1] = "Planes",
|
[1] = "Planes",
|
||||||
}
|
}
|
||||||
@@ -54,10 +53,7 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
|||||||
---@type Vec2
|
---@type Vec2
|
||||||
local baseVec2 = { x = baseVec3.x, y = baseVec3.z }
|
local baseVec2 = { x = baseVec3.x, y = baseVec3.z }
|
||||||
|
|
||||||
---@type Vec2
|
|
||||||
local pointA = capZone.verts[furthestA]
|
local pointA = capZone.verts[furthestA]
|
||||||
|
|
||||||
---@type Vec2
|
|
||||||
local pointB = capZone.verts[furthestB]
|
local pointB = capZone.verts[furthestB]
|
||||||
local furthest = pointA
|
local furthest = pointA
|
||||||
local closest = pointB
|
local closest = pointB
|
||||||
@@ -88,7 +84,6 @@ end
|
|||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@param capZone SpearheadTriggerZone
|
---@param capZone SpearheadTriggerZone
|
||||||
---@param capConfig CapConfig
|
---@param capConfig CapConfig
|
||||||
---@return table
|
|
||||||
local GetOutboundTask = function(airbase, capZone, capConfig)
|
local GetOutboundTask = function(airbase, capZone, capConfig)
|
||||||
local airbaseVec3 = airbase:getPoint()
|
local airbaseVec3 = airbase:getPoint()
|
||||||
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
|
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
|
||||||
@@ -130,7 +125,6 @@ end
|
|||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@param capZone SpearheadTriggerZone
|
---@param capZone SpearheadTriggerZone
|
||||||
---@param capConfig CapConfig
|
---@param capConfig CapConfig
|
||||||
---@return table
|
|
||||||
function CAP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig)
|
function CAP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig)
|
||||||
local points = {
|
local points = {
|
||||||
[1] = GetOutboundTask(airbase, capZone, capConfig),
|
[1] = GetOutboundTask(airbase, capZone, capConfig),
|
||||||
@@ -158,7 +152,6 @@ end
|
|||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@param capZone SpearheadTriggerZone
|
---@param capZone SpearheadTriggerZone
|
||||||
---@param capConfig CapConfig
|
---@param capConfig CapConfig
|
||||||
---@return table
|
|
||||||
function CAP.getAsMission(groupName, airbase, capZone, capConfig)
|
function CAP.getAsMission(groupName, airbase, capZone, capConfig)
|
||||||
local points = {
|
local points = {
|
||||||
[1] = CAP.getAsTasking(groupName, airbase, capZone, capConfig),
|
[1] = CAP.getAsTasking(groupName, airbase, capZone, capConfig),
|
||||||
@@ -185,7 +178,6 @@ end
|
|||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@param capZone SpearheadTriggerZone
|
---@param capZone SpearheadTriggerZone
|
||||||
---@param capConfig CapConfig
|
---@param capConfig CapConfig
|
||||||
---@return table
|
|
||||||
function CAP.getAsTasking(groupName, airbase, capZone, capConfig)
|
function CAP.getAsTasking(groupName, airbase, capZone, capConfig)
|
||||||
local duration = math.random(capConfig:getMinDurationOnStation(), capConfig:getMaxDurationOnStation()) or 1500
|
local duration = math.random(capConfig:getMinDurationOnStation(), capConfig:getMaxDurationOnStation()) or 1500
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ local INTERCEPT = {}
|
|||||||
---@param speed number?
|
---@param speed number?
|
||||||
---@param alt number?
|
---@param alt number?
|
||||||
---@param config CapConfig
|
---@param config CapConfig
|
||||||
---@return table
|
|
||||||
function INTERCEPT.getMissionFromAirbase(groupName, interceptPoint, airbase, config, speed, alt)
|
function INTERCEPT.getMissionFromAirbase(groupName, interceptPoint, airbase, config, speed, alt)
|
||||||
|
|
||||||
local airbaseVec3 = airbase:getPoint()
|
local airbaseVec3 = airbase:getPoint()
|
||||||
@@ -93,7 +92,7 @@ end
|
|||||||
---@param currentPoint Vec2
|
---@param currentPoint Vec2
|
||||||
---@param targetPosition Vec2
|
---@param targetPosition Vec2
|
||||||
---@param targetUnit Unit
|
---@param targetUnit Unit
|
||||||
---@param airbase Airbase
|
---@param airbase any
|
||||||
---@param config any
|
---@param config any
|
||||||
---@param speed number?
|
---@param speed number?
|
||||||
---@param alt number?
|
---@param alt number?
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ local RTB = {}
|
|||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@param missionPoint Vec2
|
---@param missionPoint Vec2
|
||||||
---@param capConfig CapConfig
|
---@param capConfig CapConfig
|
||||||
---@return table
|
|
||||||
function RTB.getAsMission(airbase, missionPoint, capConfig)
|
function RTB.getAsMission(airbase, missionPoint, capConfig)
|
||||||
return {
|
return {
|
||||||
id = "Mission",
|
id = "Mission",
|
||||||
@@ -114,7 +113,6 @@ end
|
|||||||
---comment
|
---comment
|
||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@param missionPoint Vec2
|
---@param missionPoint Vec2
|
||||||
---@return table
|
|
||||||
---@param capConfig CapConfig
|
---@param capConfig CapConfig
|
||||||
function RTB.getApproachPoint(airbase, missionPoint, capConfig)
|
function RTB.getApproachPoint(airbase, missionPoint, capConfig)
|
||||||
|
|
||||||
@@ -149,7 +147,6 @@ function RTB.getApproachPoint(airbase, missionPoint, capConfig)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@return table
|
|
||||||
function RTB.getInitialPoint(airbase)
|
function RTB.getInitialPoint(airbase)
|
||||||
local point = calcInitialPoint(airbase)
|
local point = calcInitialPoint(airbase)
|
||||||
return {
|
return {
|
||||||
@@ -173,8 +170,6 @@ function RTB.getInitialPoint(airbase)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param airbase Airbase
|
|
||||||
---@return table
|
|
||||||
function RTB.getLandingPoint(airbase)
|
function RTB.getLandingPoint(airbase)
|
||||||
local basePoint = airbase:getPoint()
|
local basePoint = airbase:getPoint()
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ local SWEEP = {}
|
|||||||
---@param attackHelos boolean
|
---@param attackHelos boolean
|
||||||
---@return table
|
---@return table
|
||||||
local function GetCAPTargetTypes(attackHelos)
|
local function GetCAPTargetTypes(attackHelos)
|
||||||
---@type Array<string>
|
|
||||||
local targetTypes = {
|
local targetTypes = {
|
||||||
[1] = "Planes",
|
[1] = "Planes",
|
||||||
}
|
}
|
||||||
@@ -50,9 +49,7 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
|||||||
---@type Vec2
|
---@type Vec2
|
||||||
local baseVec2 = { x = baseVec3.x, y = baseVec3.z }
|
local baseVec2 = { x = baseVec3.x, y = baseVec3.z }
|
||||||
|
|
||||||
---@type Vec2
|
|
||||||
local pointA = capZone.verts[furthestA]
|
local pointA = capZone.verts[furthestA]
|
||||||
---@type Vec2
|
|
||||||
local pointB = capZone.verts[furthestB]
|
local pointB = capZone.verts[furthestB]
|
||||||
local furthest = pointA
|
local furthest = pointA
|
||||||
local closest = pointB
|
local closest = pointB
|
||||||
@@ -83,7 +80,6 @@ end
|
|||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@param capZone SpearheadTriggerZone
|
---@param capZone SpearheadTriggerZone
|
||||||
---@param capConfig CapConfig
|
---@param capConfig CapConfig
|
||||||
---@return table
|
|
||||||
local GetOutboundTask = function(airbase, capZone, capConfig)
|
local GetOutboundTask = function(airbase, capZone, capConfig)
|
||||||
local airbaseVec3 = airbase:getPoint()
|
local airbaseVec3 = airbase:getPoint()
|
||||||
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
|
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
|
||||||
@@ -125,7 +121,6 @@ end
|
|||||||
---@param airbase Airbase
|
---@param airbase Airbase
|
||||||
---@param capZone SpearheadTriggerZone
|
---@param capZone SpearheadTriggerZone
|
||||||
---@param capConfig CapConfig
|
---@param capConfig CapConfig
|
||||||
---@return table
|
|
||||||
function SWEEP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig)
|
function SWEEP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig)
|
||||||
|
|
||||||
local pointA, pointB, pointC = SWEEP.getAsTasking(groupName, airbase, capZone, capConfig)
|
local pointA, pointB, pointC = SWEEP.getAsTasking(groupName, airbase, capZone, capConfig)
|
||||||
|
|||||||
@@ -21,10 +21,6 @@ function CapConfig.new()
|
|||||||
if SpearheadConfig == nil then SpearheadConfig = {} end
|
if SpearheadConfig == nil then SpearheadConfig = {} end
|
||||||
if SpearheadConfig.CapConfig == nil then SpearheadConfig.CapConfig = {} end
|
if SpearheadConfig.CapConfig == nil then SpearheadConfig.CapConfig = {} end
|
||||||
|
|
||||||
if type(SpearheadConfig.CapConfig.enabled) ~= "boolean" then
|
|
||||||
SpearheadConfig.CapConfig.enabled = true
|
|
||||||
end
|
|
||||||
|
|
||||||
local enabled = SpearheadConfig.CapConfig.enabled
|
local enabled = SpearheadConfig.CapConfig.enabled
|
||||||
if enabled == nil then enabled = true end
|
if enabled == nil then enabled = true end
|
||||||
self._isEnabled = enabled
|
self._isEnabled = enabled
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function DebugMenu:RegisterMenus()
|
|||||||
missionCommands.addSubMenu(menuName, {})
|
missionCommands.addSubMenu(menuName, {})
|
||||||
|
|
||||||
local refresh = function(params)
|
local refresh = function(params)
|
||||||
local selfA = params.self --[[@as DebugMenu]]
|
local selfA = params.self
|
||||||
selfA:RefreshMenu()
|
selfA:RefreshMenu()
|
||||||
end
|
end
|
||||||
missionCommands.addCommand("Refresh Menu", debugMenuPath, refresh, { self = self })
|
missionCommands.addCommand("Refresh Menu", debugMenuPath, refresh, { self = self })
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
do -- mission aliases
|
||||||
|
|
||||||
|
--- @alias LogLevel
|
||||||
|
--- | "DEBUG"
|
||||||
|
--- | "INFO"
|
||||||
|
--- | "WARN"
|
||||||
|
--- | "ERROR"
|
||||||
|
--- | "NONE"
|
||||||
|
|
||||||
|
---@class Array<T>: { [integer]: T }
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class KeyValuePair
|
||||||
|
---@field key string
|
||||||
|
---@field value any
|
||||||
@@ -10,7 +10,7 @@ local SpearheadEvents = require("classes.spearhead_events")
|
|||||||
---@field private fleetNameIdentifier string
|
---@field private fleetNameIdentifier string
|
||||||
---@field private targetZonePerStage table<string, string>
|
---@field private targetZonePerStage table<string, string>
|
||||||
---@field private currentTargetZone string
|
---@field private currentTargetZone string
|
||||||
---@field private pointsPerZone table<string, {pointA: Vec3, pointB: Vec3}>
|
---@field private pointsPerZone table<string, {pointA: Vec2, pointB: Vec2}>
|
||||||
local FleetGroup = {}
|
local FleetGroup = {}
|
||||||
FleetGroup.__index = FleetGroup
|
FleetGroup.__index = FleetGroup
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ function FleetGroup.new(fleetGroupName, database, logger)
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if Util.startsWith(namePart, "%[") == true then
|
if Util.startswith(namePart, "%[") == true then
|
||||||
namePart = Util.split_string(namePart, "[")[1]
|
namePart = Util.split_string(namePart, "[")[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -108,13 +108,7 @@ function FleetGroup.new(fleetGroupName, database, logger)
|
|||||||
for i = first, second do
|
for i = first, second do
|
||||||
self.targetZonePerStage[tostring(i)] = zoneName
|
self.targetZonePerStage[tostring(i)] = zoneName
|
||||||
end
|
end
|
||||||
---@type {pointA: Vec3, pointB: Vec3}
|
self.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} }
|
||||||
local entry = {
|
|
||||||
pointA = {x = pointA.x, z = pointA.y, y = 0},
|
|
||||||
pointB = {x = pointB.x, z = pointB.y, y = 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.pointsPerZone[zoneName] = entry
|
|
||||||
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
|
||||||
@@ -131,10 +125,10 @@ function FleetGroup.new(fleetGroupName, database, logger)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local SetTaskAsync = function(input, _)
|
local SetTaskAsync = function(input, _)
|
||||||
local targetZone = input.targetZone --[[@as string]]
|
local targetZone = input.targetZone
|
||||||
local task = input.task --[[@as table]]
|
local task = input.task
|
||||||
local groupName = input.groupName --[[@as string]]
|
local groupName = input.groupName
|
||||||
local l_logger = input.logger --[[@as Logger]]
|
local l_logger = input.logger
|
||||||
|
|
||||||
local group = Group.getByName(groupName)
|
local group = Group.getByName(groupName)
|
||||||
if group then
|
if group then
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ GlobalFleetManager.start = function(database)
|
|||||||
|
|
||||||
local all_groups = MizGroupsManager.getAllGroupNames()
|
local all_groups = MizGroupsManager.getAllGroupNames()
|
||||||
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)
|
||||||
|
|||||||
@@ -15,45 +15,23 @@ MizGroupsManager._groupNames = {}
|
|||||||
MizGroupsManager._spawnTemplateData = {}
|
MizGroupsManager._spawnTemplateData = {}
|
||||||
|
|
||||||
do --init
|
do --init
|
||||||
|
for _, coalition_data in pairs(env.mission.coalition) do
|
||||||
---@param coalition_name string
|
|
||||||
---@return Coalition
|
|
||||||
local getCoalitionData = function(coalition_name)
|
|
||||||
return env.mission.coalition[coalition_name]
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param country Country
|
|
||||||
---@param key string
|
|
||||||
---@return Groups?
|
|
||||||
local getGroupsData = function(country, key)
|
|
||||||
if key == "planes" then return country.plane end
|
|
||||||
if key == "helicopters" then return country.helicopter end
|
|
||||||
if key == "ground" then return country.vehicle end
|
|
||||||
if key == "ships" then return country.ship end
|
|
||||||
if key == "statics" then return country.static end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, coalition_name in ipairs({"neutral", "blue", "red"}) do
|
|
||||||
local coalition_data = getCoalitionData(coalition_name)
|
|
||||||
if coalition_data.country then
|
if coalition_data.country then
|
||||||
for _, country_data in pairs(coalition_data.country) do
|
for _, country_data in pairs(coalition_data.country) do
|
||||||
for _, category_name in pairs(DcsUtil.getAllGroupCategoryNames()) do
|
for category_name, categorydata in pairs(country_data) do
|
||||||
local category_id = DcsUtil.stringToGroupCategory(category_name)
|
local category_id = DcsUtil.stringToGroupCategory(category_name)
|
||||||
local groups_data = getGroupsData(country_data, category_name)
|
if category_id ~= nil and type(categorydata) == "table" and categorydata.group ~= nil and type(categorydata.group) == "table" then
|
||||||
|
for _, group in pairs(categorydata.group) do
|
||||||
if category_id ~= nil and type(groups_data) == "table" and groups_data.group ~= nil and type(groups_data.group) == "table" then
|
local name = group.name
|
||||||
for _, group in pairs(groups_data.group) do
|
|
||||||
local name = group.name --[[@as string]]
|
|
||||||
local skippable = false
|
local skippable = false
|
||||||
local isStatic = false
|
local isStatic = false
|
||||||
if category_id == DcsUtil.GroupCategory.STATIC then
|
if category_id == DcsUtil.GroupCategory.STATIC then
|
||||||
isStatic = true
|
isStatic = true
|
||||||
local unit = group.units[1] --[[@as table]]
|
local unit = group.units[1]
|
||||||
if unit and unit.category == "Heliports" then
|
if unit and unit.category == "Heliports" then
|
||||||
skippable = true
|
skippable = true
|
||||||
elseif unit and unit.name then
|
elseif unit and unit.name then
|
||||||
name = unit.name --[[@as string]]
|
name = unit.name
|
||||||
else
|
else
|
||||||
env.error("Group " .. name .. " has no units, skipping it.")
|
env.error("Group " .. name .. " has no units, skipping it.")
|
||||||
skippable = true
|
skippable = true
|
||||||
@@ -93,7 +71,6 @@ function MizGroupsManager.IsGroupStatic(groupName)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param groupName string
|
|
||||||
---@return SpawnData?
|
---@return SpawnData?
|
||||||
function MizGroupsManager.getSpawnTemplateData(groupName)
|
function MizGroupsManager.getSpawnTemplateData(groupName)
|
||||||
return MizGroupsManager._spawnTemplateData[groupName]
|
return MizGroupsManager._spawnTemplateData[groupName]
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ SpawnManager.__index = SpawnManager
|
|||||||
---@field uncontrolled boolean? Sets the group to be uncontrolled on spawn
|
---@field uncontrolled boolean? Sets the group to be uncontrolled on spawn
|
||||||
|
|
||||||
---@param logger Logger
|
---@param logger Logger
|
||||||
---@return SpawnManager
|
|
||||||
function SpawnManager.new(logger)
|
function SpawnManager.new(logger)
|
||||||
local self = setmetatable({}, SpawnManager)
|
local self = setmetatable({}, SpawnManager)
|
||||||
|
|
||||||
self._logger = logger
|
self._logger = logger
|
||||||
|
|
||||||
self._persistedUnits = {} -- Stores units that should be persisted by name
|
self._persistedUnits = {} -- Stores units that should be persisted by name
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -125,31 +125,37 @@ do --- privates
|
|||||||
end
|
end
|
||||||
|
|
||||||
local spawnTemplate = Util.deepCopyTable(spawnData.groupTemplate)
|
local spawnTemplate = Util.deepCopyTable(spawnData.groupTemplate)
|
||||||
|
---@type Array<string>
|
||||||
|
local removeableUnitNames = {}
|
||||||
--[[
|
--[[
|
||||||
TODO: Spawn units at "current"/LastKnown position with them going to the next waypoint.
|
TODO: Spawn units at "current"/LastKnown position with them going to the next waypoint.
|
||||||
ONLY when perstable data is found.
|
ONLY when perstable data is found.
|
||||||
]]
|
]]
|
||||||
|
|
||||||
if spawnTemplate and spawnTemplate["units"] then
|
if spawnTemplate and spawnTemplate["units"] then
|
||||||
local units = spawnTemplate["units"] --[[@as Array<table>]]
|
for _, unit in pairs(spawnTemplate["units"]) do
|
||||||
for _, unit in pairs(units) do
|
local name = unit["name"]
|
||||||
local name = unit["name"] --[[@as string]]
|
|
||||||
|
|
||||||
SpearheadEvents.addOnUnitLostEventListener(name, self)
|
SpearheadEvents.addOnUnitLostEventListener(name, self)
|
||||||
|
local state = Persistence.UnitState(name)
|
||||||
|
if state then
|
||||||
|
if state.isDead == true then
|
||||||
|
removeableUnitNames[#removeableUnitNames+1] = name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if override and override.emptyLoadouts == true then
|
if override and override.emptyLoadouts == true then
|
||||||
if unit["payload"] and unit["payload"]["pylons"] then
|
if unit["payload"] and unit["payload"]["pylons"] then
|
||||||
local payload = unit["payload"] --[[@as table]]
|
unit["payload"]["pylons"] = {}
|
||||||
payload["pylons"] = {} --[[@as table]]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if unit["parking"] then
|
if unit["parking"] then
|
||||||
unit["parking_landing"] = unit["parking"] --[[@as number]]
|
unit["parking_landing"] = unit["parking"]
|
||||||
end
|
end
|
||||||
|
|
||||||
if unit["parking_id"] then
|
if unit["parking_id"] then
|
||||||
unit["parking_landing_id"] = unit["parking_id"] --[[@as number]]
|
unit["parking_landing_id"] = unit["parking_id"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -163,6 +169,7 @@ do --- privates
|
|||||||
|
|
||||||
local group = coalition.addGroup(country, spawnData.category, spawnTemplate)
|
local group = coalition.addGroup(country, spawnData.category, spawnTemplate)
|
||||||
|
|
||||||
|
|
||||||
for _, unit in pairs(group:getUnits()) do
|
for _, unit in pairs(group:getUnits()) do
|
||||||
self:CheckUnitAndReplaceIfPersistentDead(unit)
|
self:CheckUnitAndReplaceIfPersistentDead(unit)
|
||||||
if isPersistent == true then
|
if isPersistent == true then
|
||||||
@@ -203,11 +210,9 @@ do --- privates
|
|||||||
spawnTemplate["x"] = persistentState.pos.x
|
spawnTemplate["x"] = persistentState.pos.x
|
||||||
spawnTemplate["y"] = persistentState.pos.z
|
spawnTemplate["y"] = persistentState.pos.z
|
||||||
if spawnTemplate["units"] and spawnTemplate["units"][1] then
|
if spawnTemplate["units"] and spawnTemplate["units"][1] then
|
||||||
local units = spawnTemplate["units"] --[[@as Array<table>]]
|
spawnTemplate["units"][1]["x"] = persistentState.pos.x
|
||||||
local firstUnit = units[1] --[[@as table]]
|
spawnTemplate["units"][1]["y"] = persistentState.pos.z
|
||||||
firstUnit["x"] = persistentState.pos.x --[[@as number]]
|
spawnTemplate["units"][1]["heading"] = persistentState.heading or 0
|
||||||
firstUnit["y"] = persistentState.pos.z --[[@as number]]
|
|
||||||
firstUnit["heading"] = persistentState.heading or 0 --[[@as number]]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ do
|
|||||||
for file in lfs.dir(dir) do
|
for file in lfs.dir(dir) do
|
||||||
|
|
||||||
local split = Util.split_string(file, ".")
|
local split = Util.split_string(file, ".")
|
||||||
local doesStartWith = Util.startsWith(file, startsWith, true)
|
local doesStartWith = Util.startswith(file, startsWith, true)
|
||||||
if split and #split > 0 and split[#split] == EXTENSION and doesStartWith == true then
|
if split and #split > 0 and split[#split] == EXTENSION and doesStartWith == true then
|
||||||
local numberString = split[#split-1]
|
local numberString = split[#split-1]
|
||||||
local number = tonumber(numberString)
|
local number = tonumber(numberString)
|
||||||
@@ -183,14 +183,11 @@ do
|
|||||||
local fileName = "Spearhead_Persistence.0.spearhead"
|
local fileName = "Spearhead_Persistence.0.spearhead"
|
||||||
if SpearheadConfig and SpearheadConfig.Persistence then
|
if SpearheadConfig and SpearheadConfig.Persistence then
|
||||||
if SpearheadConfig.Persistence.fileName then
|
if SpearheadConfig.Persistence.fileName then
|
||||||
if type(SpearheadConfig.Persistence.fileName) ~= "string" then
|
|
||||||
SpearheadConfig.Persistence.fileName = "Spearhead_Persistence.0.spearhead"
|
|
||||||
end
|
|
||||||
local userFileName = SpearheadConfig.Persistence.fileName
|
local userFileName = SpearheadConfig.Persistence.fileName
|
||||||
local split = Util.split_string(userFileName, ".")
|
local split = Util.split_string(userFileName, ".")
|
||||||
|
|
||||||
if not split or #split < 3 then
|
if not split and #split < 3 then
|
||||||
split = split or {}
|
|
||||||
split[#split+1] = "0"
|
split[#split+1] = "0"
|
||||||
split[#split+1] = "spearhead"
|
split[#split+1] = "spearhead"
|
||||||
end
|
end
|
||||||
@@ -203,10 +200,7 @@ do
|
|||||||
fileName = table.concat(split, ".")
|
fileName = table.concat(split, ".")
|
||||||
end
|
end
|
||||||
|
|
||||||
if SpearheadConfig.Persistence.directory then
|
if SpearheadConfig.Persistence.directory ~= nil then
|
||||||
if type(SpearheadConfig.Persistence.directory) ~= "string" then
|
|
||||||
SpearheadConfig.Persistence.directory = lfs.writedir() .. "\\Data"
|
|
||||||
end
|
|
||||||
dir = SpearheadConfig.Persistence.directory
|
dir = SpearheadConfig.Persistence.directory
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -216,10 +210,6 @@ do
|
|||||||
|
|
||||||
local lastFile = getLastFileOrDefault(dir--[[@as string]], matchingPart, fileName)
|
local lastFile = getLastFileOrDefault(dir--[[@as string]], matchingPart, fileName)
|
||||||
|
|
||||||
if lastFile == nil then
|
|
||||||
lastFile = fileName
|
|
||||||
end
|
|
||||||
|
|
||||||
local fileSplit = Util.split_string(lastFile, ".")
|
local fileSplit = Util.split_string(lastFile, ".")
|
||||||
fileSplit[#fileSplit-1] = tostring(tonumber(fileSplit[#fileSplit-1]) + 1)
|
fileSplit[#fileSplit-1] = tostring(tonumber(fileSplit[#fileSplit-1]) + 1)
|
||||||
fileName = table.concat(fileSplit, ".")
|
fileName = table.concat(fileSplit, ".")
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ local StageDrawing = require("classes.stageClasses.drawings.StageDrawing")
|
|||||||
---@field descriptionLocation Vec2?
|
---@field descriptionLocation Vec2?
|
||||||
---@field dependsOn Array<string>
|
---@field dependsOn Array<string>
|
||||||
---@field completeAt number?
|
---@field completeAt number?
|
||||||
---@field primaryOverwrite boolean?
|
|
||||||
|
|
||||||
---@class FarpZoneData
|
---@class FarpZoneData
|
||||||
---@field groups Array<string>
|
---@field groups Array<string>
|
||||||
@@ -212,12 +211,10 @@ function Database.New(Logger)
|
|||||||
for _, 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 _, 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
|
||||||
self._logger:debug("found airbase data for " .. layer_object.name)
|
self._logger:debug("found airbase data for " .. layer_object.name)
|
||||||
if layer_object.primitiveType == "TextBox" then
|
|
||||||
layer_object = layer_object --[[@as TextBox]]
|
|
||||||
local number = tonumber(layer_object.text)
|
local number = tonumber(layer_object.text)
|
||||||
airbaseData.buildingKilos = number
|
airbaseData.buildingKilos = number
|
||||||
end
|
end
|
||||||
@@ -227,7 +224,6 @@ function Database.New(Logger)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
---@type table<integer, boolean>
|
---@type table<integer, boolean>
|
||||||
do -- custom drawings
|
do -- custom drawings
|
||||||
@@ -235,7 +231,7 @@ function Database.New(Logger)
|
|||||||
for _, 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 _, 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)
|
||||||
if stageDrawing then
|
if stageDrawing then
|
||||||
@@ -263,12 +259,10 @@ function Database.New(Logger)
|
|||||||
for _, 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 _, 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 }
|
||||||
if zone and Util.is2dPointInZone(vec2, zone) == true then
|
if zone and Util.is2dPointInZone(vec2, zone) == true then
|
||||||
if layer_object.primitiveType == "TextBox" then
|
|
||||||
layer_object = layer_object --[[@as TextBox]]
|
|
||||||
local description = layer_object.text
|
local description = layer_object.text
|
||||||
if description and description ~= "" then
|
if description and description ~= "" then
|
||||||
stageData.StageBriefing = description
|
stageData.StageBriefing = description
|
||||||
@@ -279,7 +273,6 @@ function Database.New(Logger)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
-- fill blue sams
|
-- fill blue sams
|
||||||
for _, blueSamStageName in pairs(self._tables.BlueSams) do
|
for _, blueSamStageName in pairs(self._tables.BlueSams) do
|
||||||
@@ -475,7 +468,6 @@ function Database.New(Logger)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type table<string, boolean>
|
|
||||||
local is_group_taken = {}
|
local is_group_taken = {}
|
||||||
|
|
||||||
local getAvailableGroups = function()
|
local getAvailableGroups = function()
|
||||||
@@ -492,7 +484,7 @@ end
|
|||||||
local getAvailableCAPGroups = function()
|
local getAvailableCAPGroups = function()
|
||||||
local result = {}
|
local result = {}
|
||||||
for name, value in pairs(is_group_taken) do
|
for name, value in pairs(is_group_taken) do
|
||||||
if value == false and Util.startsWith(name, "CAP") then
|
if value == false and Util.startswith(name, "CAP") then
|
||||||
table.insert(result, name)
|
table.insert(result, name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -595,11 +587,11 @@ function Database:loadCapUnits()
|
|||||||
for _, groupName in pairs(groups) do
|
for _, groupName in pairs(groups) do
|
||||||
is_group_taken[groupName] = true
|
is_group_taken[groupName] = true
|
||||||
|
|
||||||
if Util.startsWith(groupName, "CAP_A", true) or Util.startsWith(groupName, "CAP_B", true) then
|
if Util.startswith(groupName, "CAP_A", true) or Util.startswith(groupName, "CAP_B", true) then
|
||||||
table.insert(baseData.CapGroups, groupName)
|
table.insert(baseData.CapGroups, groupName)
|
||||||
elseif Util.startsWith(groupName, "CAP_I", true) then
|
elseif Util.startswith(groupName, "CAP_I", true) then
|
||||||
table.insert(baseData.InterceptGroups, groupName)
|
table.insert(baseData.InterceptGroups, groupName)
|
||||||
elseif Util.startsWith(groupName, "CAP_S", true) then
|
elseif Util.startswith(groupName, "CAP_S", true) then
|
||||||
table.insert(baseData.SweepGroups, groupName)
|
table.insert(baseData.SweepGroups, groupName)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -622,7 +614,7 @@ function Database:loadBlueSamUnits()
|
|||||||
local triggerZone = DcsUtil.getZoneByName(blueSamZone)
|
local triggerZone = DcsUtil.getZoneByName(blueSamZone)
|
||||||
if triggerZone then
|
if triggerZone then
|
||||||
for _, kvPair in pairs(triggerZone.properties) do
|
for _, kvPair in pairs(triggerZone.properties) do
|
||||||
if kvPair.key and Util.startsWith(kvPair.key, "buildable") then
|
if kvPair.key and Util.startswith(kvPair.key, "buildable") then
|
||||||
local number = tonumber(kvPair.value)
|
local number = tonumber(kvPair.value)
|
||||||
if number and number > 0 then
|
if number and number > 0 then
|
||||||
samData.buildingKilos = number
|
samData.buildingKilos = number
|
||||||
@@ -633,9 +625,8 @@ function Database:loadBlueSamUnits()
|
|||||||
for _, 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 layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
if layer_object.name and Util.startsWith(layer_object.name, "supplybriefing_", true) then
|
if layer_object.name and Util.startswith(layer_object.name, "supplybriefing_", true) then
|
||||||
layer_object = layer_object --[[@as TextBox]]
|
|
||||||
local description = layer_object.text
|
local description = layer_object.text
|
||||||
if description and description ~= "" then
|
if description and description ~= "" then
|
||||||
samData.briefing = description
|
samData.briefing = description
|
||||||
@@ -711,9 +702,9 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
if triggerZone and triggerZone.properties then
|
if triggerZone and triggerZone.properties then
|
||||||
for _, kvPair in pairs(triggerZone.properties) do
|
for _, kvPair in pairs(triggerZone.properties) do
|
||||||
local key = kvPair.key
|
local key = kvPair.key
|
||||||
if Util.startsWith(key, "dependson", true) == true then
|
if Util.startswith(key, "dependson", true) == true then
|
||||||
table.insert(self._tables.MissionZoneData[missionZoneName].dependsOn, kvPair.value)
|
table.insert(self._tables.MissionZoneData[missionZoneName].dependsOn, kvPair.value)
|
||||||
elseif Util.startsWith(key, "completeat") == true then
|
elseif Util.startswith(key, "completeat") == true then
|
||||||
local value = tonumber(kvPair.value)
|
local value = tonumber(kvPair.value)
|
||||||
if value then
|
if value then
|
||||||
if value > 1 and value <= 100 then
|
if value > 1 and value <= 100 then
|
||||||
@@ -723,14 +714,6 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
end
|
end
|
||||||
self._tables.MissionZoneData[missionZoneName].completeAt = value
|
self._tables.MissionZoneData[missionZoneName].completeAt = value
|
||||||
end
|
end
|
||||||
elseif Util.startsWith(key, "primary", true) == true then
|
|
||||||
if type(kvPair.value) == "string" then
|
|
||||||
if kvPair.value == "true" then
|
|
||||||
self._tables.MissionZoneData[missionZoneName].primaryOverwrite = true
|
|
||||||
elseif kvPair.value == "false" then
|
|
||||||
self._tables.MissionZoneData[missionZoneName].primaryOverwrite = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -742,9 +725,8 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
for _, 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 layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
if layer_object.name and Util.startsWith(layer_object.name, "briefing_", true) then
|
if layer_object.name and Util.startswith(layer_object.name, "briefing_", true) then
|
||||||
layer_object = layer_object --[[@as TextBox]]
|
|
||||||
local description = layer_object.text
|
local description = layer_object.text
|
||||||
if description and description ~= "" then
|
if description and description ~= "" then
|
||||||
self._tables.MissionZoneData[missionZoneName].description = description
|
self._tables.MissionZoneData[missionZoneName].description = description
|
||||||
@@ -787,7 +769,7 @@ function Database:loadFarpData()
|
|||||||
local triggerZone = DcsUtil.getZoneByName(farpZone)
|
local triggerZone = DcsUtil.getZoneByName(farpZone)
|
||||||
if triggerZone then
|
if triggerZone then
|
||||||
for _, kvPair in pairs(triggerZone.properties) do
|
for _, kvPair in pairs(triggerZone.properties) do
|
||||||
if kvPair.key and Util.startsWith(kvPair.key, "buildable", true) == true then
|
if kvPair.key and Util.startswith(kvPair.key, "buildable", true) == true then
|
||||||
local number = tonumber(kvPair.value)
|
local number = tonumber(kvPair.value)
|
||||||
if number and number > 0 then
|
if number and number > 0 then
|
||||||
farpzoneData.buildingKilos = number
|
farpzoneData.buildingKilos = number
|
||||||
@@ -799,9 +781,8 @@ function Database:loadFarpData()
|
|||||||
for _, 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 layer_object.primitiveType == "TextBox" and triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
||||||
layer_object = layer_object --[[@as TextBox]]
|
if layer_object.name and Util.startswith(layer_object.name, "supplybriefing_", true) then
|
||||||
if layer_object.name and Util.startsWith(layer_object.name, "supplybriefing_", true) then
|
|
||||||
local description = layer_object.text
|
local description = layer_object.text
|
||||||
if description and description ~= "" then
|
if description and description ~= "" then
|
||||||
farpzoneData.briefing = description
|
farpzoneData.briefing = description
|
||||||
@@ -969,7 +950,6 @@ function Database:getBriefingForStage(stagename)
|
|||||||
return stageZone.StageBriefing or ""
|
return stageZone.StageBriefing or ""
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stagename string
|
|
||||||
---@return Array<string>
|
---@return Array<string>
|
||||||
function Database:getMissionsForStage(stagename)
|
function Database:getMissionsForStage(stagename)
|
||||||
local stageZone = self._tables.StageZones[stagename]
|
local stageZone = self._tables.StageZones[stagename]
|
||||||
@@ -977,7 +957,6 @@ function Database:getMissionsForStage(stagename)
|
|||||||
return stageZone.MissionZones
|
return stageZone.MissionZones
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stagename string
|
|
||||||
---@return Array<string>
|
---@return Array<string>
|
||||||
function Database:getRandomMissionsForStage(stagename)
|
function Database:getRandomMissionsForStage(stagename)
|
||||||
local stageZone = self._tables.StageZones[stagename]
|
local stageZone = self._tables.StageZones[stagename]
|
||||||
@@ -985,14 +964,13 @@ function Database:getRandomMissionsForStage(stagename)
|
|||||||
return stageZone.RandomMissionZones
|
return stageZone.RandomMissionZones
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param missionZoneName string
|
|
||||||
---@return MissionZoneData?
|
---@return MissionZoneData?
|
||||||
function Database:getMissionDataForZone(missionZoneName)
|
function Database:getMissionDataForZone(missionZoneName)
|
||||||
return self._tables.MissionZoneData[missionZoneName]
|
return self._tables.MissionZoneData[missionZoneName]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stageName string
|
---@param stageName string
|
||||||
---@return Array<string> result airbase Names
|
---@return table result airbase Names
|
||||||
function Database:getAirbaseNamesInStage(stageName)
|
function Database:getAirbaseNamesInStage(stageName)
|
||||||
local stageData = self._tables.StageZones[stageName]
|
local stageData = self._tables.StageZones[stageName]
|
||||||
if not stageData then return {} end
|
if not stageData then return {} end
|
||||||
@@ -1006,7 +984,6 @@ function Database:getFarpNamesInStage(stageName)
|
|||||||
return stageData.FarpZones or {}
|
return stageData.FarpZones or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param farpZoneName string
|
|
||||||
---@return FarpZoneData?
|
---@return FarpZoneData?
|
||||||
function Database:getFarpDataForZone(farpZoneName)
|
function Database:getFarpDataForZone(farpZoneName)
|
||||||
local farpData = self._tables.FarpZoneData[farpZoneName]
|
local farpData = self._tables.FarpZoneData[farpZoneName]
|
||||||
@@ -1022,7 +999,6 @@ function Database:getAirbaseDataForZone(baseName)
|
|||||||
return baseData
|
return baseData
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stageName string
|
|
||||||
---@return string?
|
---@return string?
|
||||||
function Database:getStageBriefingForStage(stageName)
|
function Database:getStageBriefingForStage(stageName)
|
||||||
local stageData = self._tables.StageZones[stageName]
|
local stageData = self._tables.StageZones[stageName]
|
||||||
|
|||||||
@@ -32,9 +32,7 @@ do
|
|||||||
---@field OnStageNumberChanged fun(self:OnStageChangedListener, number:integer, laneIdentifier:string?)
|
---@field OnStageNumberChanged fun(self:OnStageChangedListener, number:integer, laneIdentifier:string?)
|
||||||
|
|
||||||
do -- STAGE NUMBER CHANGED
|
do -- STAGE NUMBER CHANGED
|
||||||
---@type Array<OnStageChangedListener>
|
|
||||||
local OnStageNumberChangedListeners = {}
|
local OnStageNumberChangedListeners = {}
|
||||||
---@type Array<fun(number:integer, laneIdentifier:string?)>
|
|
||||||
local OnStageNumberChangedHandlers = {}
|
local OnStageNumberChangedHandlers = {}
|
||||||
---Add a stage zone number changed listener
|
---Add a stage zone number changed listener
|
||||||
---@param listener OnStageChangedListener object with function OnStageNumberChanged(self, number, stageLaneIdentifier)
|
---@param listener OnStageChangedListener object with function OnStageNumberChanged(self, number, stageLaneIdentifier)
|
||||||
@@ -49,7 +47,6 @@ do
|
|||||||
---@class OnStageNumberChangeCompleteListener
|
---@class OnStageNumberChangeCompleteListener
|
||||||
---@field OnStageNumberChangeComplete fun(self:OnStageNumberChangeCompleteListener, number:integer, laneIdentifier:string?)
|
---@field OnStageNumberChangeComplete fun(self:OnStageNumberChangeCompleteListener, number:integer, laneIdentifier:string?)
|
||||||
|
|
||||||
---@type Array<OnStageNumberChangeCompleteListener>
|
|
||||||
local OnStageNumberChangeCompleteListeners = {}
|
local OnStageNumberChangeCompleteListeners = {}
|
||||||
---@param listener OnStageNumberChangeCompleteListener
|
---@param listener OnStageNumberChangeCompleteListener
|
||||||
SpearheadEvents.AddStageNumberChangeCompleteListener = function(listener)
|
SpearheadEvents.AddStageNumberChangeCompleteListener = function(listener)
|
||||||
@@ -113,9 +110,6 @@ do
|
|||||||
table.insert(onWeaponFiredListeners, weaponFiredListener)
|
table.insert(onWeaponFiredListeners, weaponFiredListener)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param unit Unit
|
|
||||||
---@param weapon Weapon
|
|
||||||
---@param target Unit?
|
|
||||||
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 _, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
@@ -128,14 +122,11 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class OnLandEventListener
|
|
||||||
---@field OnUnitLanded fun(self:OnLandEventListener, initiatorUnit:Unit, airbase:Airbase)
|
|
||||||
|
|
||||||
---@type table<string,Array<OnLandEventListener>>
|
|
||||||
local onLandEventListeners = {}
|
local onLandEventListeners = {}
|
||||||
---Add an event listener to a specific unit
|
---Add an event listener to a specific unit
|
||||||
---@param unitName string to call when the unit lands
|
---@param unitName string to call when the unit lands
|
||||||
---@param landListener OnLandEventListener table with function OnUnitLanded(self, initiatorUnit, airbase)
|
---@param landListener table table with function OnUnitLanded(self, initiatorUnit, airbase)
|
||||||
SpearheadEvents.addOnUnitLandEventListener = function(unitName, landListener)
|
SpearheadEvents.addOnUnitLandEventListener = function(unitName, landListener)
|
||||||
if type(landListener) ~= "table" then
|
if type(landListener) ~= "table" then
|
||||||
warn("Event handler not of type table/object")
|
warn("Event handler not of type table/object")
|
||||||
@@ -171,11 +162,6 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- ON RTB
|
do -- ON RTB
|
||||||
|
|
||||||
---@class OnGroupRTBListener
|
|
||||||
---@field OnGroupRTB fun(self:OnGroupRTBListener, groupName:string)
|
|
||||||
|
|
||||||
---@type table<string,Array<OnGroupRTBListener>>
|
|
||||||
local OnGroupRTBListeners = {}
|
local OnGroupRTBListeners = {}
|
||||||
---Adds a function to the events listener that triggers when a group publishes themselves RTB.
|
---Adds a function to the events listener that triggers when a group publishes themselves RTB.
|
||||||
---This is only available when a ROUTE is created via the Spearhead.RouteUtil
|
---This is only available when a ROUTE is created via the Spearhead.RouteUtil
|
||||||
@@ -211,15 +197,11 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class OnGroupRTBInTenListener
|
|
||||||
---@field OnGroupRTBInTen fun(self:OnGroupRTBInTenListener, groupName:string)
|
|
||||||
|
|
||||||
---@type table<string,Array<OnGroupRTBInTenListener>>
|
|
||||||
local OnGroupRTBInTenListeners = {}
|
local OnGroupRTBInTenListeners = {}
|
||||||
---Adds a function to the events listener that triggers when a group publishes themselves RTB.
|
---Adds a function to the events listener that triggers when a group publishes themselves RTB.
|
||||||
---This is only available when a ROUTE is created via the Spearhead.RouteUtil
|
---This is only available when a ROUTE is created via the Spearhead.RouteUtil
|
||||||
---@param groupName string the groupname to expect
|
---@param groupName string the groupname to expect
|
||||||
---@param handlingObject OnGroupRTBInTenListener object with OnGroupRTBInTen(self, groupName)
|
---@param handlingObject table object with OnGroupRTBInTen(self, groupName)
|
||||||
SpearheadEvents.addOnGroupRTBInTenListener = function(groupName, handlingObject)
|
SpearheadEvents.addOnGroupRTBInTenListener = function(groupName, handlingObject)
|
||||||
if type(handlingObject) ~= "table" then
|
if type(handlingObject) ~= "table" then
|
||||||
warn("Event handler not of type table/object")
|
warn("Event handler not of type table/object")
|
||||||
@@ -252,17 +234,10 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- ON Station
|
do -- ON Station
|
||||||
|
|
||||||
---@class OnGroupOnStationListener
|
|
||||||
---@field OnGroupOnStation fun(self:OnGroupOnStationListener, groupName:string)
|
|
||||||
|
|
||||||
---@type table<string,Array<OnGroupOnStationListener>>
|
|
||||||
local OnGroupOnStationListeners = {}
|
local OnGroupOnStationListeners = {}
|
||||||
|
|
||||||
---Adds a function to the events listener that triggers when a group publishes themselves RTB.
|
---Adds a function to the events listener that triggers when a group publishes themselves RTB.
|
||||||
---This is only available when a ROUTE is created via the Spearhead.RouteUtil
|
---This is only available when a ROUTE is created via the Spearhead.RouteUtil
|
||||||
---@param groupName string the groupname to expect
|
---@param groupName string the groupname to expect
|
||||||
---@param handlingObject OnGroupOnStationListener object with OnGroupOnStation(self, groupName)
|
|
||||||
SpearheadEvents.addOnGroupOnStationListener = function(groupName, handlingObject)
|
SpearheadEvents.addOnGroupOnStationListener = function(groupName, handlingObject)
|
||||||
if type(handlingObject) ~= "table" then
|
if type(handlingObject) ~= "table" then
|
||||||
warn("Event handler not of type table/object")
|
warn("Event handler not of type table/object")
|
||||||
@@ -295,18 +270,15 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- PLAYER ENTER UNIT
|
do -- PLAYER ENTER UNIT
|
||||||
---@class OnPlayerEnterUnitListener
|
|
||||||
---@field OnPlayerEntersUnit fun(self:OnPlayerEnterUnitListener, unit:Unit)
|
|
||||||
|
|
||||||
---@type Array<OnPlayerEnterUnitListener>
|
|
||||||
local playerEnterUnitListeners = {}
|
local playerEnterUnitListeners = {}
|
||||||
---comment
|
---comment
|
||||||
---@param listener OnPlayerEnterUnitListener object with OnPlayerEntersUnit(self, unit)
|
---@param listener table object with OnPlayerEntersUnit(self, unit)
|
||||||
SpearheadEvents.AddOnPlayerEnterUnitListener = function(listener)
|
SpearheadEvents.AddOnPlayerEnterUnitListener = function(listener)
|
||||||
if type(listener) ~= "table" then
|
if type(listener) ~= "table" then
|
||||||
warn("Unit lost Event listener not of type table/object")
|
warn("Unit lost Event listener not of type table/object")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(playerEnterUnitListeners, listener)
|
table.insert(playerEnterUnitListeners, listener)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -343,8 +315,8 @@ do
|
|||||||
local e = {}
|
local e = {}
|
||||||
function e:onEvent(event)
|
function e:onEvent(event)
|
||||||
if event.id == world.event.S_EVENT_LAND or event.id == world.event.S_EVENT_RUNWAY_TOUCH then
|
if event.id == world.event.S_EVENT_LAND or event.id == world.event.S_EVENT_RUNWAY_TOUCH then
|
||||||
local unit = event.initiator --[[@as Unit]]
|
local unit = event.initiator
|
||||||
local airbase = event.place --[[@as Airbase]]
|
local airbase = event.place
|
||||||
if unit ~= nil then
|
if unit ~= nil then
|
||||||
local name = unit:getName()
|
local name = unit:getName()
|
||||||
if onLandEventListeners[name] then
|
if onLandEventListeners[name] then
|
||||||
@@ -364,7 +336,7 @@ do
|
|||||||
event.id == world.event.S_EVENT_CRASH or
|
event.id == world.event.S_EVENT_CRASH or
|
||||||
event.id == world.event.S_EVENT_EJECTION or
|
event.id == world.event.S_EVENT_EJECTION or
|
||||||
event.id == world.event.S_EVENT_UNIT_LOST then
|
event.id == world.event.S_EVENT_UNIT_LOST then
|
||||||
local object = event.initiator --[[@as Unit]]
|
local object = event.initiator
|
||||||
|
|
||||||
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())
|
||||||
@@ -383,11 +355,15 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if event.id == world.event.S_EVENT_EJECTION then
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
if event.id == world.event.S_EVENT_SHOT then
|
if event.id == world.event.S_EVENT_SHOT then
|
||||||
|
|
||||||
local shooter = event.initiator --[[@as Unit]]
|
local shooter = event.initiator
|
||||||
local weapon = event.weapon --[[@as Weapon]]
|
local weapon = event.weapon
|
||||||
local target = event.target --[[@as Unit?]]
|
local target = event.target
|
||||||
triggerWeaponFired(shooter, weapon, target)
|
triggerWeaponFired(shooter, weapon, target)
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -396,14 +372,10 @@ do
|
|||||||
Persistence.UpdateNow()
|
Persistence.UpdateNow()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type table<string, boolean>
|
|
||||||
local AI_GROUPS = {}
|
local AI_GROUPS = {}
|
||||||
|
|
||||||
---@param unit Unit
|
|
||||||
---@param _ any
|
|
||||||
local function CheckAndTriggerSpawnAsync(unit, _)
|
local function CheckAndTriggerSpawnAsync(unit, _)
|
||||||
---@param checkUnit Unit
|
|
||||||
---@return boolean, string?
|
|
||||||
local function isPlayer(checkUnit)
|
local function isPlayer(checkUnit)
|
||||||
if checkUnit == nil then return false, "unit is nil" end
|
if checkUnit == nil then return false, "unit is nil" end
|
||||||
if checkUnit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end
|
if checkUnit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end
|
||||||
@@ -433,6 +405,8 @@ do
|
|||||||
if isPlayer(unit) == true then
|
if isPlayer(unit) == true then
|
||||||
SpearheadEvents.TriggerPlayerEntersUnit(unit)
|
SpearheadEvents.TriggerPlayerEntersUnit(unit)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if event.id == world.event.S_EVENT_BIRTH then
|
if event.id == world.event.S_EVENT_BIRTH then
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ do --setup route util
|
|||||||
---@param attackHelos boolean
|
---@param attackHelos boolean
|
||||||
---@return table
|
---@return table
|
||||||
local function GetCAPTargetTypes(attackHelos)
|
local function GetCAPTargetTypes(attackHelos)
|
||||||
---@type table<number, string>
|
|
||||||
local targetTypes = {
|
local targetTypes = {
|
||||||
[1] = "Planes",
|
[1] = "Planes",
|
||||||
}
|
}
|
||||||
@@ -54,9 +53,8 @@ do --setup route util
|
|||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param groupName string
|
---@param groupName string
|
||||||
---@param position Vec3
|
---@param position table { x, y}
|
||||||
---@param altitude number
|
---@param altitude number
|
||||||
---@param deviationdistance number
|
|
||||||
---@param speed number
|
---@param speed number
|
||||||
---@param duration number
|
---@param duration number
|
||||||
---@param engageHelos boolean
|
---@param engageHelos boolean
|
||||||
@@ -183,7 +181,7 @@ do --setup route util
|
|||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param position Vec3
|
---@param position table { x, y}
|
||||||
---@param altitude number
|
---@param altitude number
|
||||||
---@param speed number
|
---@param speed number
|
||||||
---@param childTasks table
|
---@param childTasks table
|
||||||
@@ -212,8 +210,7 @@ do --setup route util
|
|||||||
---comment
|
---comment
|
||||||
---@param groupName string groupName you're creating this route for
|
---@param groupName string groupName you're creating this route for
|
||||||
---@param airdromeId number airdromeId
|
---@param airdromeId number airdromeId
|
||||||
---@param capPoint Vec3
|
---@param capPoint table { x, z }
|
||||||
---@param racetrackSecondPoint Vec3?
|
|
||||||
---@param altitude number
|
---@param altitude number
|
||||||
---@param speed number
|
---@param speed number
|
||||||
---@param durationOnStation number
|
---@param durationOnStation number
|
||||||
@@ -261,8 +258,7 @@ do --setup route util
|
|||||||
if racetrackSecondPoint then orbitType = "Race-Track" end
|
if racetrackSecondPoint then orbitType = "Race-Track" end
|
||||||
|
|
||||||
local basePoint = base:getPoint()
|
local basePoint = base:getPoint()
|
||||||
---@type Array<table>
|
local points = {}
|
||||||
local points
|
|
||||||
if racetrackSecondPoint == nil then
|
if racetrackSecondPoint == nil then
|
||||||
points = {
|
points = {
|
||||||
[1] = FlyToPointTask(capPoint, altitude, speed, additionalFlyOverTasks),
|
[1] = FlyToPointTask(capPoint, altitude, speed, additionalFlyOverTasks),
|
||||||
@@ -308,7 +304,6 @@ do --setup route util
|
|||||||
end
|
end
|
||||||
|
|
||||||
local group = Group.getByName(groupName)
|
local group = Group.getByName(groupName)
|
||||||
---@type Vec3?
|
|
||||||
local pos;
|
local pos;
|
||||||
local i = 1
|
local i = 1
|
||||||
if group == nil then
|
if group == nil then
|
||||||
@@ -398,9 +393,6 @@ do --setup route util
|
|||||||
}, ""
|
}, ""
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param pointA Vec3
|
|
||||||
---@param pointB Vec3
|
|
||||||
---@return table, string?
|
|
||||||
ROUTE_UTIL.CreateCarrierRacetrack = function(pointA, pointB)
|
ROUTE_UTIL.CreateCarrierRacetrack = function(pointA, pointB)
|
||||||
return {
|
return {
|
||||||
id = "Mission",
|
id = "Mission",
|
||||||
@@ -469,7 +461,7 @@ do --setup route util
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, nil
|
}, ""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -327,13 +327,12 @@ 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))
|
||||||
---@type Array<Group>
|
|
||||||
local groups = {}
|
local groups = {}
|
||||||
|
|
||||||
for _, player in pairs(DcsUtil.getAllPlayerUnits()) do
|
for _, player in pairs(DcsUtil.getAllPlayerUnits()) do
|
||||||
local group = player:getGroup()
|
local group = player:getGroup()
|
||||||
if group then
|
if group then
|
||||||
table.insert(groups, group)
|
groups[group:getID()] = group
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -370,11 +369,8 @@ end
|
|||||||
function GlobalStageManager:PrintMermaidStage()
|
function GlobalStageManager:PrintMermaidStage()
|
||||||
local lanes = self._stageRepository:getAllStageLanes()
|
local lanes = self._stageRepository:getAllStageLanes()
|
||||||
|
|
||||||
---@type table<string, string>
|
|
||||||
local nodes = {}
|
local nodes = {}
|
||||||
---@type table<string, string>
|
|
||||||
local edges = {}
|
local edges = {}
|
||||||
---@type table<string, Array<number>>
|
|
||||||
local stageIndicesByLane = {} -- Track all stage indices per lane
|
local stageIndicesByLane = {} -- Track all stage indices per lane
|
||||||
local mainLaneId = "default"
|
local mainLaneId = "default"
|
||||||
|
|
||||||
@@ -407,9 +403,7 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
"#9B59B6", -- 25: Amethyst
|
"#9B59B6", -- 25: Amethyst
|
||||||
"#1ABC9C", -- 26: Turquoise
|
"#1ABC9C", -- 26: Turquoise
|
||||||
}
|
}
|
||||||
---@type table<string, string>
|
|
||||||
local laneColorMap = {} -- Map lane ID to color
|
local laneColorMap = {} -- Map lane ID to color
|
||||||
---@type number
|
|
||||||
local colorIndex = 1
|
local colorIndex = 1
|
||||||
|
|
||||||
-- Build nodes and collect all stage indices per lane
|
-- Build nodes and collect all stage indices per lane
|
||||||
@@ -436,7 +430,6 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
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
|
||||||
---@type string
|
|
||||||
local bracketLabel
|
local bracketLabel
|
||||||
if laneId == "default" then
|
if laneId == "default" then
|
||||||
bracketLabel = "[" .. stageIndex .. "]"
|
bracketLabel = "[" .. stageIndex .. "]"
|
||||||
@@ -503,7 +496,7 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
for _, lane in ipairs(lanes) do
|
for _, lane in ipairs(lanes) do
|
||||||
if lane:IsDefaultStageLane() == false then
|
if lane:IsDefaultStageLane() == false then
|
||||||
local sideId = lane:GetStageLaneIdentifier()
|
local sideId = lane:GetStageLaneIdentifier()
|
||||||
local sideIndices = stageIndicesByLane[sideId] or {} --[[@as Array<number>]]
|
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
|
||||||
@@ -535,7 +528,7 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
for _, lane in ipairs(lanes) do
|
for _, lane in ipairs(lanes) do
|
||||||
if lane:IsDefaultStageLane() == false then
|
if lane:IsDefaultStageLane() == false then
|
||||||
local sideId = lane:GetStageLaneIdentifier()
|
local sideId = lane:GetStageLaneIdentifier()
|
||||||
local sideIndices = stageIndicesByLane[sideId] or {} --[[@as Array<number>]]
|
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
|
||||||
|
|||||||
@@ -91,9 +91,9 @@ function SpearheadGroup:GetCoalition()
|
|||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@return Array<Unit|StaticObject> result list of objects
|
---@return table result list of objects
|
||||||
function SpearheadGroup:GetObjects()
|
function SpearheadGroup:GetObjects()
|
||||||
---@type Array<Unit|StaticObject>
|
|
||||||
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)
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ end
|
|||||||
function StageBase:SpawnRedUnits()
|
function StageBase:SpawnRedUnits()
|
||||||
---comment
|
---comment
|
||||||
---@param groups Array<SpearheadGroup>
|
---@param groups Array<SpearheadGroup>
|
||||||
---@return number|nil
|
|
||||||
local spawnAsync = function(groups)
|
local spawnAsync = function(groups)
|
||||||
for _, group in pairs(groups) do
|
for _, group in pairs(groups) do
|
||||||
group:Spawn()
|
group:Spawn()
|
||||||
@@ -143,7 +142,6 @@ end
|
|||||||
function StageBase:SpawnBlueUnits()
|
function StageBase:SpawnBlueUnits()
|
||||||
---comment
|
---comment
|
||||||
---@param groups Array<SpearheadGroup>
|
---@param groups Array<SpearheadGroup>
|
||||||
---@return number|nil
|
|
||||||
local spawnAsync = function(groups)
|
local spawnAsync = function(groups)
|
||||||
for _, group in pairs(groups) do
|
for _, group in pairs(groups) do
|
||||||
group:Spawn()
|
group:Spawn()
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
|
|||||||
|
|
||||||
---@param params UnpackCrateParam
|
---@param params UnpackCrateParam
|
||||||
---@param time number
|
---@param time number
|
||||||
---@return number|nil
|
|
||||||
local startUnpackingCrate = function(params, time)
|
local startUnpackingCrate = function(params, time)
|
||||||
local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2)
|
local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2)
|
||||||
local alreadySpawned = params.unpackedItems / params.groupsPerKilo
|
local alreadySpawned = params.unpackedItems / params.groupsPerKilo
|
||||||
@@ -105,7 +104,6 @@ function BuildableZone:OnCrateDroppedOff(_, kilos)
|
|||||||
|
|
||||||
---@param params UnpackCrateParam
|
---@param params UnpackCrateParam
|
||||||
---@param time number
|
---@param time number
|
||||||
---@return number|nil
|
|
||||||
local startUnpackingCrate = function(params, time)
|
local startUnpackingCrate = function(params, time)
|
||||||
local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2)
|
local unpacked = params.unpackedKilos + (params.kilosPerSecond * 2)
|
||||||
local alreadySpawned = params.unpackedItems / params.groupsPerKilo
|
local alreadySpawned = params.unpackedItems / params.groupsPerKilo
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
---@field private _isDefaultStageLane boolean
|
---@field private _isDefaultStageLane boolean
|
||||||
---@field private _stageLaneIdentifier string
|
---@field private _stageLaneIdentifier string
|
||||||
---@field private _activeStageIndex number
|
---@field private _activeStageIndex number
|
||||||
---@field private _stagesInLaneByIndex table<string, Array<Stage>>
|
---@field private _stagesInLaneByIndex table<number, Array<Stage>>
|
||||||
---@field private _chapterStarts table<string, boolean>?
|
---@field private _chapterStarts table<number, boolean>?
|
||||||
---@field private _stageLaneState StageLaneState
|
---@field private _stageLaneState StageLaneState
|
||||||
---@field private _maxStageIndex number
|
---@field private _maxStageIndex number
|
||||||
local StageLane = {}
|
local StageLane = {}
|
||||||
@@ -16,7 +16,6 @@ StageLane.__index = StageLane
|
|||||||
---| "BetweenChapters"
|
---| "BetweenChapters"
|
||||||
---| "Completed"
|
---| "Completed"
|
||||||
|
|
||||||
---@type string?
|
|
||||||
StageLane.DefaultLaneKey = nil
|
StageLane.DefaultLaneKey = nil
|
||||||
|
|
||||||
function StageLane.New(laneIdentifier)
|
function StageLane.New(laneIdentifier)
|
||||||
@@ -38,21 +37,21 @@ end
|
|||||||
---@param stage Stage
|
---@param stage Stage
|
||||||
function StageLane:AddStage(stage)
|
function StageLane:AddStage(stage)
|
||||||
local stageIndex = stage:GetStageIndex()
|
local stageIndex = stage:GetStageIndex()
|
||||||
if not self._stagesInLaneByIndex[tostring(stageIndex)] then
|
if not self._stagesInLaneByIndex[stageIndex] then
|
||||||
self._stagesInLaneByIndex[tostring(stageIndex)] = {}
|
self._stagesInLaneByIndex[stageIndex] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self._maxStageIndex or stageIndex > self._maxStageIndex then
|
if not self._maxStageIndex or stageIndex > self._maxStageIndex then
|
||||||
self._maxStageIndex = stageIndex
|
self._maxStageIndex = stageIndex
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self._stagesInLaneByIndex[tostring(stageIndex)], stage)
|
table.insert(self._stagesInLaneByIndex[stageIndex], stage)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stageNumber number
|
---@param stageNumber number
|
||||||
---@return boolean?
|
---@return boolean?
|
||||||
function StageLane:IsStageIndexComplete(stageNumber)
|
function StageLane:IsStageIndexComplete(stageNumber)
|
||||||
local stages = self._stagesInLaneByIndex[tostring(stageNumber)]
|
local stages = self._stagesInLaneByIndex[stageNumber]
|
||||||
if not stages then
|
if not stages then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -89,7 +88,7 @@ end
|
|||||||
---@param stageNumber number
|
---@param stageNumber number
|
||||||
function StageLane:SetActiveStageIndex(stageNumber)
|
function StageLane:SetActiveStageIndex(stageNumber)
|
||||||
|
|
||||||
if self._stagesInLaneByIndex[tostring(stageNumber)] == nil then
|
if self._stagesInLaneByIndex[stageNumber] == nil then
|
||||||
self._stageLaneState = "BetweenChapters" -- stage number is not in this lane, so we are between chapters
|
self._stageLaneState = "BetweenChapters" -- stage number is not in this lane, so we are between chapters
|
||||||
elseif stageNumber > self._maxStageIndex then
|
elseif stageNumber > self._maxStageIndex then
|
||||||
self._stageLaneState = "Completed" -- stage number is beyond the max stage index
|
self._stageLaneState = "Completed" -- stage number is beyond the max stage index
|
||||||
@@ -109,7 +108,6 @@ end
|
|||||||
--- Chapter starts are the first StageIndex after a gap in stage numbers. <br>
|
--- Chapter starts are the first StageIndex after a gap in stage numbers. <br>
|
||||||
--- For example, if the stage numbers are 1, 2, 3, 5, 6, 7, then stage number 5 is a chapter start because there is a gap between 3 and 5. <br>
|
--- For example, if the stage numbers are 1, 2, 3, 5, 6, 7, then stage number 5 is a chapter start because there is a gap between 3 and 5. <br>
|
||||||
---@param stageNumber number
|
---@param stageNumber number
|
||||||
---@return boolean
|
|
||||||
function StageLane:IsChapterStart(stageNumber)
|
function StageLane:IsChapterStart(stageNumber)
|
||||||
|
|
||||||
if self._chapterStarts == nil then
|
if self._chapterStarts == nil then
|
||||||
@@ -125,14 +123,13 @@ end
|
|||||||
function StageLane:FillChapterStarts()
|
function StageLane:FillChapterStarts()
|
||||||
|
|
||||||
local previousIndex = nil
|
local previousIndex = nil
|
||||||
---@type table<string, number>
|
|
||||||
local stageIndices = {}
|
local stageIndices = {}
|
||||||
for stageIndex, _ in pairs(self._stagesInLaneByIndex) do
|
for stageIndex, _ in pairs(self._stagesInLaneByIndex) do
|
||||||
table.insert(stageIndices, tonumber(stageIndex))
|
table.insert(stageIndices, tonumber(stageIndex))
|
||||||
end
|
end
|
||||||
table.sort(stageIndices)
|
table.sort(stageIndices)
|
||||||
|
|
||||||
if self._chapterStarts == nil then self._chapterStarts = {} end
|
self._chapterStarts = self._chapterStarts or {}
|
||||||
for _, stageIndex in ipairs(stageIndices) do
|
for _, stageIndex in ipairs(stageIndices) do
|
||||||
if previousIndex == nil then
|
if previousIndex == nil then
|
||||||
-- First stage is always a chapter start
|
-- First stage is always a chapter start
|
||||||
@@ -161,7 +158,7 @@ end
|
|||||||
---@param stageIndex number
|
---@param stageIndex number
|
||||||
---@return Array<Stage>?
|
---@return Array<Stage>?
|
||||||
function StageLane:GetStagesAtIndex(stageIndex)
|
function StageLane:GetStagesAtIndex(stageIndex)
|
||||||
return self._stagesInLaneByIndex[tostring(stageIndex)]
|
return self._stagesInLaneByIndex[stageIndex]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return number?
|
---@return number?
|
||||||
|
|||||||
@@ -162,7 +162,6 @@ function Stage:superNew(database, stageConfig, logger, initData, stageType, miss
|
|||||||
---comment
|
---comment
|
||||||
---@param selfA Stage
|
---@param selfA Stage
|
||||||
---@param time number?
|
---@param time number?
|
||||||
---@return number|nil
|
|
||||||
self.CheckContinuousAsync = function (selfA, time)
|
self.CheckContinuousAsync = function (selfA, time)
|
||||||
|
|
||||||
selfA:CheckAndUpdateSelf()
|
selfA:CheckAndUpdateSelf()
|
||||||
@@ -326,9 +325,7 @@ function Stage:GetStageName()
|
|||||||
return self.stageName
|
return self.stageName
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return Array<Mission>
|
|
||||||
function Stage:GetMissions()
|
function Stage:GetMissions()
|
||||||
---@type Array<Mission>
|
|
||||||
local missions = {}
|
local missions = {}
|
||||||
for _, mission in pairs(self._db.missions) do
|
for _, mission in pairs(self._db.missions) do
|
||||||
table.insert(missions, mission)
|
table.insert(missions, mission)
|
||||||
@@ -435,12 +432,6 @@ function Stage:PreActivate()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, mission in pairs(self._db.missions) do
|
|
||||||
if mission and mission.missionType == "DEEPSTRIKE" then
|
|
||||||
mission:SpawnInactive() --Not Really "inactive"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, airbase in pairs(self._db.airbases) do
|
for _, airbase in pairs(self._db.airbases) do
|
||||||
airbase:ActivateRedStage()
|
airbase:ActivateRedStage()
|
||||||
end
|
end
|
||||||
@@ -683,7 +674,6 @@ function Stage:ActivateBlueStage()
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param selfA Stage
|
---@param selfA Stage
|
||||||
---@return number|nil
|
|
||||||
local ActivateBlueAsync = function(selfA)
|
local ActivateBlueAsync = function(selfA)
|
||||||
pcall(function()
|
pcall(function()
|
||||||
selfA:MarkStage()
|
selfA:MarkStage()
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ local function MarkupToAll(shapeID, drawID, points, fillColor, lineColor, lineS
|
|||||||
if lineThickness == nil or lineThickness <= 0 then
|
if lineThickness == nil or lineThickness <= 0 then
|
||||||
lineStyle = 0
|
lineStyle = 0
|
||||||
end
|
end
|
||||||
---@type string
|
|
||||||
local functionString = "trigger.action.markupToAll(" .. shapeID .. ", -1, " .. drawID .. ","
|
local functionString = "trigger.action.markupToAll(" .. shapeID .. ", -1, " .. drawID .. ","
|
||||||
|
|
||||||
for _, point in pairs(points) do
|
for _, point in pairs(points) do
|
||||||
@@ -125,14 +125,14 @@ function DrawingHelper.DrawPolygon(object)
|
|||||||
local fillColor = DrawingHelper.ColorToColorTable(free.fillColorString)
|
local fillColor = DrawingHelper.ColorToColorTable(free.fillColorString)
|
||||||
local color = DrawingHelper.ColorToColorTable(free.colorString)
|
local color = DrawingHelper.ColorToColorTable(free.colorString)
|
||||||
local lineStyle = DrawingHelper.ToLineStyleInteger(free.style)
|
local lineStyle = DrawingHelper.ToLineStyleInteger(free.style)
|
||||||
---@type Array<number>
|
|
||||||
local keys = {}
|
local keys = {}
|
||||||
for k, _ in pairs(free.points) do
|
for k, _ in pairs(free.points) do
|
||||||
table.insert(keys, k)
|
table.insert(keys, k)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort(keys, function(a, b) return a < b end)
|
table.sort(keys, function(a, b) return a < b end)
|
||||||
---@type Array<Vec3>
|
|
||||||
local points = {}
|
local points = {}
|
||||||
for _, k in ipairs(keys) do
|
for _, k in ipairs(keys) do
|
||||||
local point = free.points[k]
|
local point = free.points[k]
|
||||||
@@ -274,7 +274,6 @@ function DrawingHelper.ColorTableToColorString(rgba)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param lineStyle string
|
---@param lineStyle string
|
||||||
---@return integer
|
|
||||||
function DrawingHelper.ToLineStyleInteger(lineStyle)
|
function DrawingHelper.ToLineStyleInteger(lineStyle)
|
||||||
lineStyle = lineStyle:lower()
|
lineStyle = lineStyle:lower()
|
||||||
if lineStyle == "no line" then
|
if lineStyle == "no line" then
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ end
|
|||||||
|
|
||||||
---@param self BattleManager
|
---@param self BattleManager
|
||||||
---@param time number
|
---@param time number
|
||||||
---@return number?
|
|
||||||
local function CheckTask(self, time)
|
local function CheckTask(self, time)
|
||||||
local interval = self:Update()
|
local interval = self:Update()
|
||||||
if not interval then return end
|
if not interval then return end
|
||||||
@@ -149,7 +148,7 @@ end
|
|||||||
---@return number
|
---@return number
|
||||||
function BattleManager:getBestAmmo(unit)
|
function BattleManager:getBestAmmo(unit)
|
||||||
|
|
||||||
local ammo = unit:getAmmo() --[[@as table<number, table>]]
|
local ammo = unit:getAmmo()
|
||||||
|
|
||||||
if not ammo then return 3221225470, 1 end -- Default ammo if no ammo is found
|
if not ammo then return 3221225470, 1 end -- Default ammo if no ammo is found
|
||||||
|
|
||||||
@@ -163,9 +162,9 @@ function BattleManager:getBestAmmo(unit)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local entry = Util.randomFromList(shells) --[[@as table]]
|
local entry = Util.randomFromList(shells)
|
||||||
if entry and entry.desc and entry.desc.warhead then
|
if entry and entry.desc and entry.desc.warhead then
|
||||||
local caliber = entry.desc.warhead.caliber --[[@as number]]
|
local caliber = entry.desc.warhead.caliber
|
||||||
if caliber > 50 then
|
if caliber > 50 then
|
||||||
return 258503344128, 1
|
return 258503344128, 1
|
||||||
else
|
else
|
||||||
@@ -210,7 +209,6 @@ function BattleManager:ToShootingHulls(groups)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local hulls = Util.getSeparatedConvexHulls(points, 50)
|
local hulls = Util.getSeparatedConvexHulls(points, 50)
|
||||||
---@type Array<Array<Vec2>>
|
|
||||||
local enlargedHulls = {}
|
local enlargedHulls = {}
|
||||||
for _, hull in pairs(hulls) do
|
for _, hull in pairs(hulls) do
|
||||||
local enlarged = Util.enlargeConvexHull(hull, 25)
|
local enlarged = Util.enlargeConvexHull(hull, 25)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ local SupplyConfigHelper = require("classes.stageClasses.helpers.SupplyConfigHel
|
|||||||
local StageConfig = require("classes.configuration.StageConfig")
|
local StageConfig = require("classes.configuration.StageConfig")
|
||||||
|
|
||||||
|
|
||||||
---@class MissionCommandsHelper : OnPlayerEnterUnitListener
|
---@class MissionCommandsHelper
|
||||||
---@field missionsByCode table<string, Mission> @table of missions by their code
|
---@field missionsByCode table<string, Mission> @table of missions by their code
|
||||||
---@field enabledByCode table<string, boolean> @table of enabled missions by their code
|
---@field enabledByCode table<string, boolean> @table of enabled missions by their code
|
||||||
---@field updateNeeded boolean @flag to indicate if an update is needed
|
---@field updateNeeded boolean @flag to indicate if an update is needed
|
||||||
@@ -210,7 +210,7 @@ function MissionCommandsHelper:OverviewToGroup(groupID)
|
|||||||
for code, enabled in pairs(self.enabledByCode) do
|
for code, enabled in pairs(self.enabledByCode) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local mission = self.missionsByCode[code]
|
local mission = self.missionsByCode[code]
|
||||||
if mission and mission:getState() == "ACTIVE" and mission:GetPriority() == "primary" then
|
if mission and mission:getState() == "ACTIVE" and mission.priority == "primary" then
|
||||||
table.insert(primaryMissions, mission)
|
table.insert(primaryMissions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -230,7 +230,7 @@ function MissionCommandsHelper:OverviewToGroup(groupID)
|
|||||||
for code, enabled in pairs(self.enabledByCode) do
|
for code, enabled in pairs(self.enabledByCode) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local mission = self.missionsByCode[code]
|
local mission = self.missionsByCode[code]
|
||||||
if mission and mission:getState() == "ACTIVE" and mission:GetPriority() == "secondary" then
|
if mission and mission:getState() == "ACTIVE" and mission.priority == "secondary" then
|
||||||
table.insert(secondaryMissions, mission)
|
table.insert(secondaryMissions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -345,7 +345,7 @@ function MissionCommandsHelper:AddAllMissionCommandsToGroup(groupID)
|
|||||||
for code, enabled in pairs(self.enabledByCode) do
|
for code, enabled in pairs(self.enabledByCode) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local mission = self.missionsByCode[code]
|
local mission = self.missionsByCode[code]
|
||||||
if mission and mission:GetPriority() == "primary" then
|
if mission and mission.priority == "primary" then
|
||||||
table.insert(primaryMissions, mission)
|
table.insert(primaryMissions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -369,12 +369,12 @@ function MissionCommandsHelper:AddAllMissionCommandsToGroup(groupID)
|
|||||||
do --- secondary missions
|
do --- secondary missions
|
||||||
local count = 0
|
local count = 0
|
||||||
local path = { [1] = folderNames.secondary }
|
local path = { [1] = folderNames.secondary }
|
||||||
---@type Array<Mission>
|
|
||||||
local secondaryMissions = {}
|
local secondaryMissions = {}
|
||||||
for code, enabled in pairs(self.enabledByCode) do
|
for code, enabled in pairs(self.enabledByCode) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local mission = self.missionsByCode[code]
|
local mission = self.missionsByCode[code]
|
||||||
if mission and mission:GetPriority() == "secondary" then
|
if mission and mission.priority == "secondary" then
|
||||||
table.insert(secondaryMissions, mission)
|
table.insert(secondaryMissions, mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -416,7 +416,7 @@ function MissionCommandsHelper:addMissionCommands(groupId, path, mission)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local missionFolderName = "[" ..
|
local missionFolderName = "[" ..
|
||||||
mission.code .. "]" .. distance .. mission.name .. "(" .. mission.missionTypeDisplay .. ")"
|
mission.code .. "]" .. distance .. mission.name .. "( " .. mission.missionTypeDisplay .. " )"
|
||||||
missionCommands.addSubMenuForGroup(groupId, missionFolderName, path)
|
missionCommands.addSubMenuForGroup(groupId, missionFolderName, path)
|
||||||
table.insert(path, missionFolderName)
|
table.insert(path, missionFolderName)
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ local SupplyConfigHelper = {}
|
|||||||
---@return SupplyConfig?
|
---@return SupplyConfig?
|
||||||
function SupplyConfigHelper.fromObjectName(name)
|
function SupplyConfigHelper.fromObjectName(name)
|
||||||
for configName, config in pairs(SupplyConfig) do
|
for configName, config in pairs(SupplyConfig) do
|
||||||
if Util.startsWith(name, configName, true) == true then
|
if Util.startswith(name, configName, true) == true then
|
||||||
return config
|
return config
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -84,7 +84,6 @@ function SupplyConfigHelper.fromObjectName(name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param type CrateType
|
---@param type CrateType
|
||||||
---@return SupplyConfig?
|
|
||||||
function SupplyConfigHelper.getSupplyConfig(type)
|
function SupplyConfigHelper.getSupplyConfig(type)
|
||||||
return SupplyConfig[type]
|
return SupplyConfig[type]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ local SupplyLoadConfig = require("classes.stageClasses.helpers.SupplyLoadConfig"
|
|||||||
---@field enteredSupplyHub fun(self:SupplyUnitEventListener, unit:Unit, hub:SupplyHub) | nil
|
---@field enteredSupplyHub fun(self:SupplyUnitEventListener, unit:Unit, hub:SupplyHub) | nil
|
||||||
---@field exitedSupplyHub fun(self:SupplyUnitEventListener, unit:Unit, hub:SupplyHub) | nil
|
---@field exitedSupplyHub fun(self:SupplyUnitEventListener, unit:Unit, hub:SupplyHub) | nil
|
||||||
|
|
||||||
---@class SupplyUnitsTracker : OnPlayerEnterUnitListener
|
---@class SupplyUnitsTracker
|
||||||
---@field private _supplyUnitsByName table<string, Unit>
|
---@field private _supplyUnitsByName table<string, Unit>
|
||||||
---@field private _cargoInUnits table<string, table<CrateType, number>>
|
---@field private _cargoInUnits table<string, table<CrateType, number>>
|
||||||
---@field private _logger Logger
|
---@field private _logger Logger
|
||||||
@@ -43,8 +43,6 @@ function SupplyUnitsTracker.getOrCreate()
|
|||||||
SpearheadEvents.AddOnPlayerEnterUnitListener(singleton)
|
SpearheadEvents.AddOnPlayerEnterUnitListener(singleton)
|
||||||
|
|
||||||
---@param selfA SupplyUnitsTracker
|
---@param selfA SupplyUnitsTracker
|
||||||
---@param time number
|
|
||||||
---@return number?
|
|
||||||
local function updateTask(selfA, time)
|
local function updateTask(selfA, time)
|
||||||
|
|
||||||
selfA:Update()
|
selfA:Update()
|
||||||
@@ -136,7 +134,6 @@ end
|
|||||||
|
|
||||||
---@private
|
---@private
|
||||||
---@param unit Unit
|
---@param unit Unit
|
||||||
---@return boolean
|
|
||||||
function SupplyUnitsTracker:IsSupplyUnit(unit)
|
function SupplyUnitsTracker:IsSupplyUnit(unit)
|
||||||
if unit == nil then return false end
|
if unit == nil then return false end
|
||||||
|
|
||||||
@@ -161,17 +158,15 @@ function SupplyUnitsTracker:AddCargoToUnit(unitID, crateType)
|
|||||||
local unit = DcsUtil.GetPlayerUnitByID(unitID)
|
local unit = DcsUtil.GetPlayerUnitByID(unitID)
|
||||||
if unit == nil then return end
|
if unit == nil then return end
|
||||||
|
|
||||||
local unitIdStr = tostring(unitID)
|
if self._cargoInUnits[unitID] == nil then
|
||||||
|
self._cargoInUnits[unitID] = {}
|
||||||
if self._cargoInUnits[unitIdStr] == nil then
|
|
||||||
self._cargoInUnits[unitIdStr] = {}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if self._cargoInUnits[unitIdStr][crateType] == nil then
|
if self._cargoInUnits[unitID][crateType] == nil then
|
||||||
self._cargoInUnits[unitIdStr][crateType] = 0
|
self._cargoInUnits[unitID][crateType] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
self._cargoInUnits[unitIdStr][crateType] = self._cargoInUnits[unitIdStr][crateType] + 1
|
self._cargoInUnits[unitID][crateType] = self._cargoInUnits[unitID][crateType] + 1
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -258,7 +253,7 @@ function SupplyUnitsTracker:CheckUnitsInZones()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self._unitPositions[tostring(unit:getID())] = pos
|
self._unitPositions[unit:getID()] = pos
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -328,7 +323,6 @@ function SupplyUnitsTracker:UnloadRequested(unitID, crateType, missionCommandsHe
|
|||||||
self:UpdateWeightForUnit(unit)
|
self:UpdateWeightForUnit(unit)
|
||||||
|
|
||||||
cargoCount = cargoCount + 1
|
cargoCount = cargoCount + 1
|
||||||
---@type {name: string, type: string, x: number, y: number}
|
|
||||||
local cargoSpawnObject = {
|
local cargoSpawnObject = {
|
||||||
name = crateType .. "_" .. cargoCount,
|
name = crateType .. "_" .. cargoCount,
|
||||||
type = cargoConfig.staticType,
|
type = cargoConfig.staticType,
|
||||||
@@ -490,7 +484,7 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local objPos = foundObject:getPoint()
|
local objPos = foundObject:getPoint()
|
||||||
local box = desc.box --[[@type table]]
|
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
|
||||||
@@ -503,10 +497,10 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject)
|
|||||||
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 --[[@as number]]
|
local minX = box.min.x
|
||||||
local maxX = box.max.x --[[@as number]]
|
local maxX = box.max.x
|
||||||
local minZ = box.min.z --[[@as number]]
|
local minZ = box.min.z
|
||||||
local maxZ = box.max.z --[[@as number]]
|
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
|
||||||
@@ -523,8 +517,8 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject)
|
|||||||
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) --[[@as number]]
|
local rotX = corner[1] * math.cos(heading) - corner[2] * math.sin(heading)
|
||||||
local rotZ = corner[1] * math.sin(heading) + corner[2] * math.cos(heading) --[[@as number]]
|
local rotZ = corner[1] * math.sin(heading) + corner[2] * math.cos(heading)
|
||||||
minX = math.min(minX, rotX)
|
minX = math.min(minX, rotX)
|
||||||
maxX = math.max(maxX, rotX)
|
maxX = math.max(maxX, rotX)
|
||||||
minZ = math.min(minZ, rotZ)
|
minZ = math.min(minZ, rotZ)
|
||||||
@@ -593,7 +587,7 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local crateRelativeBBox = crateDesc.box --[[@as table]]
|
local crateRelativeBBox = crateDesc.box
|
||||||
|
|
||||||
-- Get drop zone config for this unit
|
-- Get drop zone config for this unit
|
||||||
local dropZones = {
|
local dropZones = {
|
||||||
@@ -616,11 +610,8 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
|||||||
radius = 100 -- Search a large area
|
radius = 100 -- Search a large area
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
---@type Array<{ pos: { x: number, y: number, z: number }, bbox: { min: { x: number, y: number, z: number }, max: { x: number, y: number, z: number } } }>
|
|
||||||
local occupiedObjects = {}
|
|
||||||
|
|
||||||
---@param foundItem Object
|
local occupiedObjects = {}
|
||||||
---@param _ any
|
|
||||||
local found = function(foundItem, _)
|
local found = function(foundItem, _)
|
||||||
local bbox = self:GetBoundingBoxes(foundItem)
|
local bbox = self:GetBoundingBoxes(foundItem)
|
||||||
if bbox then
|
if bbox then
|
||||||
@@ -669,7 +660,6 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
|||||||
local candidateY = land.getHeight({ x = candidateX, y = candidateZ })
|
local candidateY = land.getHeight({ x = candidateX, y = candidateZ })
|
||||||
|
|
||||||
-- Convert crate's relative bbox to world space at this position
|
-- Convert crate's relative bbox to world space at this position
|
||||||
---@type { min: { x: number, y: number, z: number }, max: { x: number, y: number, z: number } }
|
|
||||||
local crateBBoxWorldSpace = {
|
local crateBBoxWorldSpace = {
|
||||||
min = {
|
min = {
|
||||||
x = candidateX + crateRelativeBBox.min.x,
|
x = candidateX + crateRelativeBBox.min.x,
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelpe
|
|||||||
local BuildableMission = {}
|
local BuildableMission = {}
|
||||||
BuildableMission.__index = BuildableMission
|
BuildableMission.__index = BuildableMission
|
||||||
|
|
||||||
---@param siteType string
|
|
||||||
---@param coords string
|
|
||||||
---@return string
|
---@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 .. "." ..
|
||||||
@@ -45,7 +43,6 @@ end
|
|||||||
---@param noLandingZone SpearheadTriggerZone?
|
---@param noLandingZone SpearheadTriggerZone?
|
||||||
---@param logger Logger
|
---@param logger Logger
|
||||||
---@param briefing string?
|
---@param briefing string?
|
||||||
---@return BuildableMission
|
|
||||||
function BuildableMission.new(database, logger, targetZone, noLandingZone, requiredKilos, requiredCrateType, briefing)
|
function BuildableMission.new(database, logger, targetZone, noLandingZone, requiredKilos, requiredCrateType, briefing)
|
||||||
|
|
||||||
setmetatable(BuildableMission, Mission)
|
setmetatable(BuildableMission, Mission)
|
||||||
@@ -120,7 +117,6 @@ function BuildableMission:ShowBriefing(groupID)
|
|||||||
|
|
||||||
local unitType = DcsUtil.getUnitTypeFromGroup(group)
|
local unitType = DcsUtil.getUnitTypeFromGroup(group)
|
||||||
local coords = DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
local coords = DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
||||||
if coords == nil then coords = "Could not make conversion" end
|
|
||||||
|
|
||||||
local siteType = "FARP"
|
local siteType = "FARP"
|
||||||
if self._crateType == "SAM_CRATE" then
|
if self._crateType == "SAM_CRATE" then
|
||||||
@@ -147,20 +143,17 @@ function BuildableMission:ShowBriefing(groupID)
|
|||||||
trigger.action.outTextForGroup(groupID, briefing, GlobalConfig:getBriefingTime())
|
trigger.action.outTextForGroup(groupID, briefing, GlobalConfig:getBriefingTime())
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param groupID number
|
|
||||||
function BuildableMission:MarkMissionAreaToGroup(groupID)
|
function BuildableMission:MarkMissionAreaToGroup(groupID)
|
||||||
|
|
||||||
local groupIdStr = tostring(groupID)
|
if self._markIDsPerGroup[groupID] then
|
||||||
|
DcsUtil.RemoveMark(self._markIDsPerGroup[groupID])
|
||||||
if self._markIDsPerGroup[groupIdStr] then
|
|
||||||
DcsUtil.RemoveMark(self._markIDsPerGroup[groupIdStr])
|
|
||||||
end
|
end
|
||||||
---@type string
|
|
||||||
local text = "[" .. self.code .. "] " .. self.name .. " | " .. self._crateType
|
local text = "[" .. self.code .. "] " .. self.name .. " | " .. self._crateType
|
||||||
local location = { x= self.location.x, y=land.getHeight(self.location), z=self.location.y }
|
local location = { x= self.location.x, y=land.getHeight(self.location), z=self.location.y }
|
||||||
local markID = DcsUtil.AddMarkToGroup(groupID, text, location)
|
local markID = DcsUtil.AddMarkToGroup(groupID, text, location)
|
||||||
|
|
||||||
self._markIDsPerGroup[groupIdStr] = markID
|
self._markIDsPerGroup[groupID] = markID
|
||||||
end
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
@@ -204,7 +197,6 @@ function BuildableMission:SpawnActive()
|
|||||||
|
|
||||||
---@param selfA BuildableMission
|
---@param selfA BuildableMission
|
||||||
---@param time number
|
---@param time number
|
||||||
---@return number?
|
|
||||||
local checkForCrateTasks = function (selfA, time)
|
local checkForCrateTasks = function (selfA, time)
|
||||||
selfA:CheckCratesInZone()
|
selfA:CheckCratesInZone()
|
||||||
|
|
||||||
@@ -259,7 +251,7 @@ function BuildableMission:CheckCratesInZone()
|
|||||||
|
|
||||||
local crates = self._supplyUnitsTracker:GetCargoCratesDropped()
|
local crates = self._supplyUnitsTracker:GetCargoCratesDropped()
|
||||||
for _, staticObject in pairs(crates) do
|
for _, staticObject in pairs(crates) do
|
||||||
if staticObject and staticObject:isExist() and Util.startsWith(staticObject:getName(), self._crateType, true) then
|
if staticObject and staticObject:isExist() and Util.startswith(staticObject:getName(), self._crateType, true) then
|
||||||
local pos = staticObject:getPoint()
|
local pos = staticObject:getPoint()
|
||||||
|
|
||||||
if Util.is3dPointInZone(pos, self._dropOffZone) then
|
if Util.is3dPointInZone(pos, self._dropOffZone) then
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ local RunwayStrikeMission = {}
|
|||||||
---@param runway Runway
|
---@param runway Runway
|
||||||
---@param database Database
|
---@param database Database
|
||||||
---@param logger Logger
|
---@param logger Logger
|
||||||
---@param airbaseName string
|
|
||||||
---@param runwayBombingTracker RunwayBombingTracker
|
---@param runwayBombingTracker RunwayBombingTracker
|
||||||
---@return RunwayStrikeMission?
|
---@return RunwayStrikeMission?
|
||||||
function RunwayStrikeMission.new(runway, airbaseName, database, logger, runwayBombingTracker)
|
function RunwayStrikeMission.new(runway, airbaseName, database, logger, runwayBombingTracker)
|
||||||
@@ -206,9 +205,8 @@ function RunwayStrikeMission:StartRepair()
|
|||||||
self._repairInProgress = true
|
self._repairInProgress = true
|
||||||
self._logger:debug("Starting repair of runway strike mission " .. self._airportName .. ":" .. self._runway.Name)
|
self._logger:debug("Starting repair of runway strike mission " .. self._airportName .. ":" .. self._runway.Name)
|
||||||
---comment
|
---comment
|
||||||
---@param selfA RunwayStrikeMission
|
---@param selfA any
|
||||||
---@param time number
|
---@return unknown
|
||||||
---@return number?
|
|
||||||
local repairTask = function (selfA, time)
|
local repairTask = function (selfA, time)
|
||||||
local interval = selfA:DoRepairCycle()
|
local interval = selfA:DoRepairCycle()
|
||||||
if interval == nil then return nil end
|
if interval == nil then return nil end
|
||||||
@@ -217,7 +215,6 @@ function RunwayStrikeMission:StartRepair()
|
|||||||
timer.scheduleFunction(repairTask, self, timer.getTime() + 5)
|
timer.scheduleFunction(repairTask, self, timer.getTime() + 5)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return number?
|
|
||||||
function RunwayStrikeMission:DoRepairCycle()
|
function RunwayStrikeMission:DoRepairCycle()
|
||||||
|
|
||||||
local interval = 5
|
local interval = 5
|
||||||
@@ -250,14 +247,12 @@ function RunwayStrikeMission:DoRepairCycle()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class StaticSpawn : table
|
---@class StaticSpawn
|
||||||
---@field category string
|
---@field category string
|
||||||
---@field type string
|
---@field type string
|
||||||
---@field y number
|
---@field y number
|
||||||
---@field x number
|
---@field x number
|
||||||
---@field heading number
|
---@field heading number
|
||||||
---@field name string?
|
|
||||||
---@field hidden boolean?
|
|
||||||
|
|
||||||
|
|
||||||
local counter = 1
|
local counter = 1
|
||||||
@@ -446,7 +441,6 @@ end
|
|||||||
|
|
||||||
---@private
|
---@private
|
||||||
---@param runway Runway
|
---@param runway Runway
|
||||||
---@param numSections number
|
|
||||||
---@return Array<RunwaySection>
|
---@return Array<RunwaySection>
|
||||||
function RunwayStrikeMission:ToSections(runway, numSections)
|
function RunwayStrikeMission:ToSections(runway, numSections)
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ local DcsUtil = require("classes.util.DcsUtil")
|
|||||||
---@field private _completeAtIndex number
|
---@field private _completeAtIndex number
|
||||||
---@field private _parentStage Stage
|
---@field private _parentStage Stage
|
||||||
---@field private _battleManager? BattleManager
|
---@field private _battleManager? BattleManager
|
||||||
---@field private _lastContactMarkerID number
|
---@field private _lastContactMarkerID number;
|
||||||
local ZoneMission = {}
|
local ZoneMission = {}
|
||||||
|
|
||||||
--- @class MissionGroups
|
--- @class MissionGroups
|
||||||
@@ -24,7 +24,7 @@ local ZoneMission = {}
|
|||||||
--- @field unitsAlive table<string, table<string, boolean>>
|
--- @field unitsAlive table<string, table<string, boolean>>
|
||||||
--- @field targetsAlive table<string, table<string, boolean>>
|
--- @field targetsAlive table<string, table<string, boolean>>
|
||||||
--- @field sceneryTargets Array<SpearheadSceneryObject>
|
--- @field sceneryTargets Array<SpearheadSceneryObject>
|
||||||
--- @field groupNamesPerUnit table<string,string>
|
--- @field groupNamesPerunit table<string,string>
|
||||||
|
|
||||||
---@class ParsedMissionName
|
---@class ParsedMissionName
|
||||||
---@field missionName string
|
---@field missionName string
|
||||||
@@ -36,7 +36,7 @@ local ZoneMission = {}
|
|||||||
local function ParseZoneName(input)
|
local function ParseZoneName(input)
|
||||||
local split_name = Util.split_string(input, "_")
|
local split_name = Util.split_string(input, "_")
|
||||||
local split_length = Util.tableLength(split_name)
|
local split_length = Util.tableLength(split_name)
|
||||||
if Util.startsWith(input, "RANDOMMISSION") == true and split_length < 4 then
|
if Util.startswith(input, "RANDOMMISSION") == true and split_length < 4 then
|
||||||
MissionEditorWarnings.Add("Random Mission with zonename " .. input .. " not in right format")
|
MissionEditorWarnings.Add("Random Mission with zonename " .. input .. " not in right format")
|
||||||
return nil
|
return nil
|
||||||
elseif split_length < 3 then
|
elseif split_length < 3 then
|
||||||
@@ -53,10 +53,9 @@ local function ParseZoneName(input)
|
|||||||
if inputType == "cas" then parsedType = "CAS" end
|
if inputType == "cas" then parsedType = "CAS" end
|
||||||
if inputType == "bai" then parsedType = "BAI" end
|
if inputType == "bai" then parsedType = "BAI" end
|
||||||
if inputType == "sam" then parsedType = "SAM" end
|
if inputType == "sam" then parsedType = "SAM" end
|
||||||
if inputType == "deepstrike" then parsedType = "DEEPSTRIKE" end
|
|
||||||
|
|
||||||
if parsedType == "nil" then
|
if parsedType == "nil" then
|
||||||
MissionEditorWarnings.Add("Mission with zoneName '" ..
|
MissionEditorWarnings.Add("Mission with zonename '" ..
|
||||||
input .. "' has an unsupported type '" .. (type or "nil"))
|
input .. "' has an unsupported type '" .. (type or "nil"))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -67,6 +66,8 @@ local function ParseZoneName(input)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
MINIMAL_UNITS_ALIVE_RATIO = 0.21
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param zoneName string
|
---@param zoneName string
|
||||||
---@param priority MissionPriority
|
---@param priority MissionPriority
|
||||||
@@ -111,7 +112,7 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
|||||||
unitsAlive = {},
|
unitsAlive = {},
|
||||||
targetsAlive = {},
|
targetsAlive = {},
|
||||||
hasTargets = false,
|
hasTargets = false,
|
||||||
groupNamesPerUnit = {},
|
groupNamesPerunit = {},
|
||||||
sceneryTargets = {}
|
sceneryTargets = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,17 +150,17 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
|||||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||||
table.insert(self._missionGroups.redGroups, spearheadGroup)
|
table.insert(self._missionGroups.redGroups, spearheadGroup)
|
||||||
|
|
||||||
local isGroupTarget = Util.startsWith(string.lower(groupName), "tgt_")
|
local isGroupTarget = Util.startswith(string.lower(groupName), "tgt_")
|
||||||
for _, unit in pairs(spearheadGroup:GetObjects()) do
|
for _, unit in pairs(spearheadGroup:GetObjects()) do
|
||||||
local unitName = unit:getName()
|
local unitName = unit:getName()
|
||||||
local isUnitTarget = Util.startsWith(string.lower(unitName), "tgt_")
|
local isUnitTarget = Util.startswith(string.lower(unitName), "tgt_")
|
||||||
|
|
||||||
if self._missionGroups.unitsAlive[groupName] == nil then
|
if self._missionGroups.unitsAlive[groupName] == nil then
|
||||||
self._missionGroups.unitsAlive[groupName] = {}
|
self._missionGroups.unitsAlive[groupName] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
self._missionGroups.unitsAlive[groupName][unitName] = true
|
self._missionGroups.unitsAlive[groupName][unitName] = true
|
||||||
self._missionGroups.groupNamesPerUnit[unitName] = groupName
|
self._missionGroups.groupNamesPerunit[unitName] = groupName
|
||||||
|
|
||||||
if isGroupTarget == true or isUnitTarget == true then
|
if isGroupTarget == true or isUnitTarget == true then
|
||||||
self._missionGroups.hasTargets = true
|
self._missionGroups.hasTargets = true
|
||||||
@@ -179,6 +180,7 @@ function ZoneMission.new(zoneName, priority, database, logger, parentStage, spaw
|
|||||||
|
|
||||||
if self.missionType == "CAS" then
|
if self.missionType == "CAS" then
|
||||||
self._battleManager = BattleManager.New(self._missionGroups.redGroups, self._missionGroups.blueGroups, self.zoneName, self._logger.LogLevel)
|
self._battleManager = BattleManager.New(self._missionGroups.redGroups, self._missionGroups.blueGroups, self.zoneName, self._logger.LogLevel)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self._logger:debug("Mission " .. self.name .. " group count: " .. Util.tableLength(missionData.RedGroups))
|
self._logger:debug("Mission " .. self.name .. " group count: " .. Util.tableLength(missionData.RedGroups))
|
||||||
@@ -227,9 +229,10 @@ end
|
|||||||
|
|
||||||
---@internal
|
---@internal
|
||||||
---@param checkHealth boolean
|
---@param checkHealth boolean
|
||||||
---@param _ boolean
|
---@param messageIfDone boolean
|
||||||
function ZoneMission:UpdateState(checkHealth, _)
|
function ZoneMission:UpdateState(checkHealth, messageIfDone)
|
||||||
if checkHealth == nil then checkHealth = false end
|
if checkHealth == nil then checkHealth = false end
|
||||||
|
if messageIfDone == false then messageIfDone = true end
|
||||||
|
|
||||||
|
|
||||||
if checkHealth == true then
|
if checkHealth == true then
|
||||||
@@ -237,7 +240,7 @@ function ZoneMission:UpdateState(checkHealth, _)
|
|||||||
local staticObject = StaticObject.getByName(unitName)
|
local staticObject = StaticObject.getByName(unitName)
|
||||||
if staticObject then
|
if staticObject then
|
||||||
if staticObject:isExist() == true then
|
if staticObject:isExist() == true then
|
||||||
local life0 = staticObject:getDesc().life --[[@as number]]
|
local life0 = staticObject:getDesc().life
|
||||||
if staticObject:getLife() / life0 < 0.3 then
|
if staticObject:getLife() / life0 < 0.3 then
|
||||||
self._logger:debug("exploding unit")
|
self._logger:debug("exploding unit")
|
||||||
trigger.action.explosion(staticObject:getPoint(), 100)
|
trigger.action.explosion(staticObject:getPoint(), 100)
|
||||||
@@ -283,9 +286,7 @@ function ZoneMission:UpdateState(checkHealth, _)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if self._missionGroups.hasTargets == true then
|
if self._missionGroups.hasTargets == true then
|
||||||
---@type number
|
|
||||||
local total = 0
|
local total = 0
|
||||||
---@type number
|
|
||||||
local alive = 0
|
local alive = 0
|
||||||
|
|
||||||
for _, units in pairs(self._missionGroups.targetsAlive) do
|
for _, units in pairs(self._missionGroups.targetsAlive) do
|
||||||
@@ -298,13 +299,13 @@ function ZoneMission:UpdateState(checkHealth, _)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, sceneryObject in pairs(self._missionGroups.sceneryTargets) do
|
for _, sceneryObject in pairs(self._missionGroups.sceneryTargets) do
|
||||||
total = total + 1 --[[@as number]]
|
total = total + 1
|
||||||
if sceneryObject:IsAlive() == true then
|
if sceneryObject:IsAlive() == true then
|
||||||
alive = alive + 1
|
alive = alive + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local deadRatio = (total - alive) / total --[[@as number]]
|
local deadRatio = (total - alive) / total
|
||||||
if deadRatio >= self._completeAtIndex then
|
if deadRatio >= self._completeAtIndex then
|
||||||
self._logger:debug("Dead ratio " .. self.zoneName .. deadRatio .. " >= " .. self._completeAtIndex)
|
self._logger:debug("Dead ratio " .. self.zoneName .. deadRatio .. " >= " .. self._completeAtIndex)
|
||||||
self._state = "COMPLETED"
|
self._state = "COMPLETED"
|
||||||
@@ -353,19 +354,6 @@ end
|
|||||||
function ZoneMission:SpawnInactive()
|
function ZoneMission:SpawnInactive()
|
||||||
self._logger:info("PreActivating " .. self.name)
|
self._logger:info("PreActivating " .. self.name)
|
||||||
|
|
||||||
if self.missionType == "DEEPSTRIKE" then
|
|
||||||
local missionData = self._database:getMissionDataForZone(self.zoneName)
|
|
||||||
---@type MissionPriority
|
|
||||||
local priority = "secondary"
|
|
||||||
if missionData and missionData.primaryOverwrite ~= nil then
|
|
||||||
if missionData.primaryOverwrite == true then
|
|
||||||
priority = "primary"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self._priority = priority
|
|
||||||
self._missionCommandsHelper:AddMissionToCommands(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, group in pairs(self._missionGroups.redGroups) do
|
for _, group in pairs(self._missionGroups.redGroups) do
|
||||||
group:Spawn()
|
group:Spawn()
|
||||||
end
|
end
|
||||||
@@ -402,17 +390,6 @@ function ZoneMission:SpawnActive()
|
|||||||
self._battleManager:Start()
|
self._battleManager:Start()
|
||||||
end
|
end
|
||||||
|
|
||||||
self._missionCommandsHelper:RemoveMissionToCommands(self) -- Remove first
|
|
||||||
if self.missionType == "DEEPSTRIKE" then
|
|
||||||
local missionData = self._database:getMissionDataForZone(self.zoneName)
|
|
||||||
local priority = "primary"
|
|
||||||
if missionData and missionData.primaryOverwrite ~= nil then
|
|
||||||
if missionData.primaryOverwrite == false then
|
|
||||||
priority = "secondary"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self._priority = priority
|
|
||||||
end
|
|
||||||
self._missionCommandsHelper:AddMissionToCommands(self)
|
self._missionCommandsHelper:AddMissionToCommands(self)
|
||||||
|
|
||||||
self:StartCheckingContinuous()
|
self:StartCheckingContinuous()
|
||||||
@@ -500,18 +477,16 @@ function ZoneMission:OnUnitLost(object)
|
|||||||
|
|
||||||
local category = Object.getCategory(object)
|
local category = Object.getCategory(object)
|
||||||
if category == Object.Category.UNIT then
|
if category == Object.Category.UNIT then
|
||||||
object = object --[[@as Unit]]
|
|
||||||
local unitName = object:getName()
|
local unitName = object:getName()
|
||||||
self._logger:debug("UnitName:" .. unitName)
|
self._logger:debug("UnitName:" .. unitName)
|
||||||
|
|
||||||
local groupName = self._missionGroups.groupNamesPerUnit[unitName]
|
local groupName = self._missionGroups.groupNamesPerunit[unitName]
|
||||||
self._missionGroups.unitsAlive[groupName][unitName] = false
|
self._missionGroups.unitsAlive[groupName][unitName] = false
|
||||||
|
|
||||||
if self._missionGroups.targetsAlive[groupName] and self._missionGroups.targetsAlive[groupName][unitName] then
|
if self._missionGroups.targetsAlive[groupName] and self._missionGroups.targetsAlive[groupName][unitName] then
|
||||||
self._missionGroups.targetsAlive[groupName][unitName] = false
|
self._missionGroups.targetsAlive[groupName][unitName] = false
|
||||||
end
|
end
|
||||||
elseif category == Object.Category.STATIC then
|
elseif category == Object.Category.STATIC then
|
||||||
object = object --[[@as StaticObject]]
|
|
||||||
local name = object:getName()
|
local name = object:getName()
|
||||||
self._missionGroups.unitsAlive[name][name] = false
|
self._missionGroups.unitsAlive[name][name] = false
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ local GlobalConfig = require("classes.configuration.GlobalConfig")
|
|||||||
---@field zoneName string
|
---@field zoneName string
|
||||||
---@field missionType MissionType
|
---@field missionType MissionType
|
||||||
---@field missionTypeDisplay string
|
---@field missionTypeDisplay string
|
||||||
---@field protected _priority MissionPriority
|
---@field priority MissionPriority
|
||||||
---@field location Vec2?
|
---@field location Vec2?
|
||||||
---@field code string
|
---@field code string
|
||||||
---@field protected _state MissionState
|
---@field protected _state MissionState
|
||||||
@@ -40,7 +40,7 @@ function Mission.newSuper(self, zoneName, missionName, missionType, missionBrief
|
|||||||
self.zoneName = zoneName
|
self.zoneName = zoneName
|
||||||
self.name = missionName
|
self.name = missionName
|
||||||
self.missionType = missionType
|
self.missionType = missionType
|
||||||
self._priority = priority
|
self.priority = priority
|
||||||
self._state = "NEW"
|
self._state = "NEW"
|
||||||
self._logger = logger
|
self._logger = logger
|
||||||
self._database = database
|
self._database = database
|
||||||
@@ -64,19 +64,14 @@ end
|
|||||||
|
|
||||||
--region PUBLIC
|
--region PUBLIC
|
||||||
|
|
||||||
---@return MissionPriority
|
|
||||||
function Mission:GetPriority()
|
|
||||||
return self._priority
|
|
||||||
end
|
|
||||||
|
|
||||||
function Mission:SpawnPersistedState() end
|
function Mission:SpawnPersistedState() end
|
||||||
function Mission:SpawnActive() end
|
function Mission:SpawnActive() end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param _checkHealth boolean
|
---@param checkHealth boolean
|
||||||
---@param _messageIfDone boolean
|
---@param messageIfDone boolean
|
||||||
---@diagnostic disable-next-line: unused-local
|
---@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
|
||||||
|
|
||||||
function Mission:PercentageComplete()
|
function Mission:PercentageComplete()
|
||||||
@@ -91,7 +86,6 @@ function Mission:ShowBriefing(groupId)
|
|||||||
|
|
||||||
local unitType = DcsUtil.getUnitTypeFromGroup(group)
|
local unitType = DcsUtil.getUnitTypeFromGroup(group)
|
||||||
local coords = DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
local coords = DcsUtil.convertVec2ToUnitUsableType(self.location, unitType)
|
||||||
if coords == nil then coords = "Could not make conversion" end
|
|
||||||
self._logger:debug("Coords converted: " .. coords)
|
self._logger:debug("Coords converted: " .. coords)
|
||||||
|
|
||||||
local stateString = self:ToStateString()
|
local stateString = self:ToStateString()
|
||||||
@@ -119,7 +113,7 @@ end
|
|||||||
function Mission:NotifyMissionComplete()
|
function Mission:NotifyMissionComplete()
|
||||||
self._missionCommandsHelper:RemoveMissionToCommands(self)
|
self._missionCommandsHelper:RemoveMissionToCommands(self)
|
||||||
self._logger:info("Mission Completed: " .. self.zoneName)
|
self._logger:info("Mission Completed: " .. self.zoneName)
|
||||||
trigger.action.outText("Mission " .. self.name .. " [" .. self.code .. "] was completed successfully", 20)
|
trigger.action.outText("Mission " .. self.name .. " [" .. self.code .. "] was completed succesfully", 20)
|
||||||
|
|
||||||
for _, listener in pairs(self._completeListeners) do
|
for _, listener in pairs(self._completeListeners) do
|
||||||
pcall(function()
|
pcall(function()
|
||||||
@@ -138,9 +132,9 @@ function Mission:ForceMissionComplete()
|
|||||||
self:NotifyMissionComplete()
|
self:NotifyMissionComplete()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param _groupId number
|
---@param groupId number
|
||||||
---@diagnostic disable-next-line: unused-local
|
---@diagnostic disable-next-line: unused-local
|
||||||
function Mission:MarkMissionAreaToGroup(_groupId) end
|
function Mission:MarkMissionAreaToGroup(groupId) end
|
||||||
|
|
||||||
---endregion
|
---endregion
|
||||||
|
|
||||||
@@ -152,27 +146,29 @@ function Mission:ToStateString() return "status: in progress" end
|
|||||||
|
|
||||||
--endregion
|
--endregion
|
||||||
|
|
||||||
--- @alias MissionPriority
|
do --aliases
|
||||||
--- | "none"
|
|
||||||
--- | "primary"
|
|
||||||
--- | "secondary"
|
|
||||||
|
|
||||||
--- @alias MissionType
|
--- @alias MissionPriority
|
||||||
--- | "nil"
|
--- | "none"
|
||||||
--- | "STRIKE"
|
--- | "primary"
|
||||||
--- | "DEEPSTRIKE"
|
--- | "secondary"
|
||||||
--- | "CAS"
|
|
||||||
--- | "BAI"
|
|
||||||
--- | "DEAD"
|
|
||||||
--- | "SAM"
|
|
||||||
--- | "OCA"
|
|
||||||
--- | "LOGISTICS"
|
|
||||||
---
|
|
||||||
--- @alias MissionState
|
|
||||||
--- | "NEW"
|
|
||||||
--- | "WAITING"
|
|
||||||
--- | "ACTIVE"
|
|
||||||
--- | "COMPLETED"
|
|
||||||
|
|
||||||
|
--- @alias MissionType
|
||||||
|
--- | "nil"
|
||||||
|
--- | "STRIKE"
|
||||||
|
--- | "CAS"
|
||||||
|
--- | "BAI"
|
||||||
|
--- | "DEAD"
|
||||||
|
--- | "SAM"
|
||||||
|
--- | "OCA"
|
||||||
|
--- | "LOGISTICS"
|
||||||
|
|
||||||
|
--- @alias MissionState
|
||||||
|
--- | "NEW"
|
||||||
|
--- | "WAITING"
|
||||||
|
--- | "ACTIVE"
|
||||||
|
--- | "COMPLETED"
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
return Mission
|
return Mission
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
local Logger = require("classes.util.Logger")
|
|
||||||
local logger = Logger.new("ImageDisplay")
|
|
||||||
|
|
||||||
---@class ImageDisplay
|
|
||||||
local ImageDisplay = {}
|
|
||||||
|
|
||||||
---@param unit Unit
|
|
||||||
---@param settings ImageDisplaySettings
|
|
||||||
function ImageDisplay.outImageToUnit(unit, settings)
|
|
||||||
if unit == nil then return end
|
|
||||||
settings:ValidateOrSetDefaults() --Overwrites wrong settings
|
|
||||||
if settings.picPath == nil then
|
|
||||||
logger:warn("No picture path provided for unit display.")
|
|
||||||
return -- Nothing to display
|
|
||||||
end
|
|
||||||
ImageDisplay.outImage("a_out_picture_u",
|
|
||||||
unit,
|
|
||||||
settings.picPath,
|
|
||||||
settings.duration,
|
|
||||||
settings.clearview,
|
|
||||||
settings.delay,
|
|
||||||
settings.horizontalAlignment,
|
|
||||||
settings.verticalAlignment,
|
|
||||||
settings.size,
|
|
||||||
settings.sizeUnits
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param group Group
|
|
||||||
---@param settings ImageDisplaySettings
|
|
||||||
function ImageDisplay.outImageToGroup(group, settings)
|
|
||||||
if group == nil then return end
|
|
||||||
settings:ValidateOrSetDefaults() --Overwrites wrong settings
|
|
||||||
if settings.picPath == nil then
|
|
||||||
logger:warn("No picture path provided for group display.")
|
|
||||||
return -- Nothing to display
|
|
||||||
end
|
|
||||||
ImageDisplay.outImage("a_out_picture_g",
|
|
||||||
group,
|
|
||||||
settings.picPath,
|
|
||||||
settings.duration,
|
|
||||||
settings.clearview,
|
|
||||||
settings.delay,
|
|
||||||
settings.horizontalAlignment,
|
|
||||||
settings.verticalAlignment,
|
|
||||||
settings.size,
|
|
||||||
settings.sizeUnits
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@alias OutPictureTriggerName
|
|
||||||
---| "a_out_picture_u"
|
|
||||||
---| "a_out_picture_g"
|
|
||||||
|
|
||||||
---@private
|
|
||||||
---@param object Unit|Group
|
|
||||||
---@param triggerName OutPictureTriggerName
|
|
||||||
---@param picPath string
|
|
||||||
---@param duration number
|
|
||||||
---@param clearview boolean
|
|
||||||
---@param delay number
|
|
||||||
---@param horizontalAlignment ImageDisplaySettings.HorizontalAlignment
|
|
||||||
---@param verticalAlignment ImageDisplaySettings.VerticalAlignment
|
|
||||||
---@param size number
|
|
||||||
---@param sizeUnits ImageDisplaySettings.SizeUnits
|
|
||||||
function ImageDisplay.outImage(triggerName, object, picPath, duration, clearview, delay, horizontalAlignment, verticalAlignment, size, sizeUnits)
|
|
||||||
|
|
||||||
---@type number
|
|
||||||
local id
|
|
||||||
if triggerName == "a_out_picture_u" then
|
|
||||||
object = object --[[@as Unit]]
|
|
||||||
id = object:getID()
|
|
||||||
elseif triggerName == "a_out_picture_g" then
|
|
||||||
object = object --[[@as Group]]
|
|
||||||
id = object:getID()
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[
|
|
||||||
a_out_picture_u(
|
|
||||||
unitID:number,
|
|
||||||
filePath:string,
|
|
||||||
showTime:number,
|
|
||||||
clearview:boolean,
|
|
||||||
startDelayTime:number,
|
|
||||||
horzAlignment:string,
|
|
||||||
vertAlignment:string,
|
|
||||||
size:number,
|
|
||||||
size_units:string
|
|
||||||
) -- args may not correct.
|
|
||||||
]]
|
|
||||||
|
|
||||||
local cmdString = string.format(triggerName .. '(%d, "%s", %d, %s, %d, "%d", "%d", %d, "%d")',
|
|
||||||
id,
|
|
||||||
picPath,
|
|
||||||
duration,
|
|
||||||
clearview,
|
|
||||||
delay,
|
|
||||||
horizontalAlignment,
|
|
||||||
verticalAlignment,
|
|
||||||
size,
|
|
||||||
sizeUnits)
|
|
||||||
|
|
||||||
local f, err = loadstring(cmdString)
|
|
||||||
if f then
|
|
||||||
f()
|
|
||||||
else
|
|
||||||
logger:error("Something failed when drawing complex drawing" .. err)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return ImageDisplay
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
---@class ImageDisplaySettings
|
|
||||||
---@field picPath string?
|
|
||||||
---@field duration number
|
|
||||||
---@field clearview boolean
|
|
||||||
---@field delay number
|
|
||||||
---@field horizontalAlignment ImageDisplaySettings.HorizontalAlignment
|
|
||||||
---@field verticalAlignment ImageDisplaySettings.VerticalAlignment
|
|
||||||
---@field size number
|
|
||||||
---@field sizeUnits ImageDisplaySettings.SizeUnits
|
|
||||||
local ImageDisplaySettings = {}
|
|
||||||
ImageDisplaySettings.__index = ImageDisplaySettings
|
|
||||||
|
|
||||||
---@enum ImageDisplaySettings.VerticalAlignment
|
|
||||||
ImageDisplaySettings.VerticalAlignment = {
|
|
||||||
Top = "0",
|
|
||||||
Center = "1",
|
|
||||||
Bottom = "2"
|
|
||||||
}
|
|
||||||
|
|
||||||
---@enum ImageDisplaySettings.HorizontalAlignment
|
|
||||||
ImageDisplaySettings.HorizontalAlignment = {
|
|
||||||
Left = "0",
|
|
||||||
Center = "1",
|
|
||||||
Right = "2"
|
|
||||||
}
|
|
||||||
|
|
||||||
---@enum ImageDisplaySettings.SizeUnits
|
|
||||||
ImageDisplaySettings.SizeUnits = {
|
|
||||||
OriginalSize = "0",
|
|
||||||
WindowSize = "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
function ImageDisplaySettings.new()
|
|
||||||
local self = setmetatable({}, ImageDisplaySettings)
|
|
||||||
self.picPath = nil
|
|
||||||
self.duration = 30
|
|
||||||
self.clearview = false
|
|
||||||
self.delay = 0
|
|
||||||
self.horizontalAlignment = ImageDisplaySettings.HorizontalAlignment.Center
|
|
||||||
self.verticalAlignment = ImageDisplaySettings.VerticalAlignment.Center
|
|
||||||
self.size = 100
|
|
||||||
self.sizeUnits = ImageDisplaySettings.SizeUnits.OriginalSize
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function ImageDisplaySettings:ValidateOrSetDefaults()
|
|
||||||
if self.picPath == "" then self.picPath = nil end
|
|
||||||
if self.duration == nil or self.duration <= 0 then self.duration = 30 end
|
|
||||||
if self.clearview == nil then self.clearview = false end
|
|
||||||
if self.delay == nil then self.delay = 0 end
|
|
||||||
if self.horizontalAlignment == nil then self.horizontalAlignment = ImageDisplaySettings.HorizontalAlignment.Center end
|
|
||||||
if self.verticalAlignment == nil then self.verticalAlignment = ImageDisplaySettings.VerticalAlignment.Center end
|
|
||||||
if self.size == nil or self.size <= 0 then self.size = 100 end
|
|
||||||
if self.sizeUnits == nil then self.sizeUnits = ImageDisplaySettings.SizeUnits.OriginalSize end
|
|
||||||
end
|
|
||||||
|
|
||||||
return ImageDisplaySettings
|
|
||||||
@@ -32,10 +32,6 @@ do -- INIT DCS_UTIL
|
|||||||
---| "Cilinder"
|
---| "Cilinder"
|
||||||
---| "Polygon"
|
---| "Polygon"
|
||||||
|
|
||||||
---@class KeyValuePair
|
|
||||||
---@field key string
|
|
||||||
---@field value any
|
|
||||||
|
|
||||||
---@class SpearheadTriggerZone
|
---@class SpearheadTriggerZone
|
||||||
---@field name string
|
---@field name string
|
||||||
---@field location Vec2
|
---@field location Vec2
|
||||||
@@ -44,7 +40,7 @@ do -- INIT DCS_UTIL
|
|||||||
---@field zone_type SpearheadTriggerZoneType
|
---@field zone_type SpearheadTriggerZoneType
|
||||||
---@field properties Array<KeyValuePair>?
|
---@field properties Array<KeyValuePair>?
|
||||||
|
|
||||||
---@type table<string, SpearheadTriggerZone>
|
---@type Array<SpearheadTriggerZone>
|
||||||
DCS_UTIL.__trigger_zones = {}
|
DCS_UTIL.__trigger_zones = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -70,15 +66,12 @@ do -- INIT DCS_UTIL
|
|||||||
STATIC = 5 --CUSTOM CATEGORY
|
STATIC = 5 --CUSTOM CATEGORY
|
||||||
}
|
}
|
||||||
|
|
||||||
---@type table<string, string>
|
|
||||||
DCS_UTIL.__airbaseNamesById = {}
|
DCS_UTIL.__airbaseNamesById = {}
|
||||||
|
|
||||||
---@type table<string, SpearheadTriggerZone>
|
---@type table<string, SpearheadTriggerZone>
|
||||||
DCS_UTIL.__airbaseZonesByName = {}
|
DCS_UTIL.__airbaseZonesByName = {}
|
||||||
|
|
||||||
---@type table<string, CoalitionSide>
|
|
||||||
DCS_UTIL.__airportsStartingCoalition = {}
|
DCS_UTIL.__airportsStartingCoalition = {}
|
||||||
---@type table<string, CoalitionSide>
|
|
||||||
DCS_UTIL.__warehouseStartingCoalition = {}
|
DCS_UTIL.__warehouseStartingCoalition = {}
|
||||||
function DCS_UTIL.__INIT()
|
function DCS_UTIL.__INIT()
|
||||||
do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment
|
do -- INITS ALL TABLES WITH DATA THAT's from the MIZ environment
|
||||||
@@ -111,8 +104,8 @@ do -- INIT DCS_UTIL
|
|||||||
|
|
||||||
if trigger_zone.properties then
|
if trigger_zone.properties then
|
||||||
for _, kvPair in pairs(trigger_zone.properties) do
|
for _, kvPair in pairs(trigger_zone.properties) do
|
||||||
local key = kvPair.key
|
local key = kvPair["key"]
|
||||||
local value = kvPair.value
|
local value = kvPair["value"]
|
||||||
zone.properties[#zone.properties + 1] = { key = key, value = value }
|
zone.properties[#zone.properties + 1] = { key = key, value = value }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -123,7 +116,6 @@ do -- INIT DCS_UTIL
|
|||||||
|
|
||||||
do -- init airports and warehouses
|
do -- init airports and warehouses
|
||||||
if env.warehouses.airports then
|
if env.warehouses.airports then
|
||||||
env.warehouses.airports = env.warehouses.airports --[[@as table<string, any>]]
|
|
||||||
for warehouse_id, value in pairs(env.warehouses.airports) do
|
for warehouse_id, value in pairs(env.warehouses.airports) do
|
||||||
if warehouse_id ~= nil then
|
if warehouse_id ~= nil then
|
||||||
warehouse_id = tostring(warehouse_id) or "nil"
|
warehouse_id = tostring(warehouse_id) or "nil"
|
||||||
@@ -134,12 +126,12 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
if env.warehouses.warehouses then
|
if env.warehouses.warehouses then
|
||||||
env.warehouses.warehouses = env.warehouses.warehouses --[[@as table<number, any>]]
|
DCS_UTIL.__warehouseStartingCoalition[-1] = "placeholder"
|
||||||
for warehouse_id, value in pairs(env.warehouses.warehouses) do
|
for warehouse_id, value in pairs(env.warehouses.warehouses) do
|
||||||
if warehouse_id ~= nil then
|
if warehouse_id ~= nil then
|
||||||
local warehouse_id_str = tostring(warehouse_id) or "nil"
|
warehouse_id = tostring(warehouse_id) or "nil"
|
||||||
local coalitionNumber = DCS_UTIL.stringToCoalition(value.coalition)
|
local coalitionNumber = DCS_UTIL.stringToCoalition(value.coalition)
|
||||||
DCS_UTIL.__warehouseStartingCoalition[warehouse_id_str] = coalitionNumber
|
DCS_UTIL.__warehouseStartingCoalition[warehouse_id] = coalitionNumber
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -226,13 +218,11 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- takes a list of units and returns all the units that are in any of the zones
|
--- takes a list of units and returns all the units that are in any of the zones
|
||||||
---@param unit_names Array<string> unit names
|
---@param unit_names table unit names
|
||||||
---@param zone_names Array<string> zone names
|
---@param zone_names table zone names
|
||||||
---@return table<number, { unit : Unit|StaticObject, zone_name: string }>
|
---@return table unit list of objects { unit = UNIT, zone_name = zoneName}
|
||||||
function DCS_UTIL.getUnitsInZones(unit_names, zone_names)
|
function DCS_UTIL.getUnitsInZones(unit_names, zone_names)
|
||||||
---@type Array<Unit|StaticObject>
|
|
||||||
local units = {}
|
local units = {}
|
||||||
|
|
||||||
---@type Array<SpearheadTriggerZone>
|
---@type Array<SpearheadTriggerZone>
|
||||||
@@ -251,19 +241,14 @@ do -- INIT DCS_UTIL
|
|||||||
zones[#zones + 1] = zone
|
zones[#zones + 1] = zone
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---@type table<number, { unit : Unit|StaticObject, zone_name: string }>
|
|
||||||
local in_zone_units = {}
|
local in_zone_units = {}
|
||||||
for units_ind = 1, #units do
|
for units_ind = 1, #units do
|
||||||
local lUnit = units[units_ind]
|
local lUnit = units[units_ind]
|
||||||
local isActive = true
|
|
||||||
local lCat = Object.getCategory(lUnit)
|
|
||||||
if lCat == Object.Category.UNIT then
|
|
||||||
local unit = lUnit --[[@as Unit]]
|
|
||||||
isActive = unit:isActive() == true
|
|
||||||
end
|
|
||||||
local unit_pos = lUnit:getPosition().p
|
local unit_pos = lUnit:getPosition().p
|
||||||
|
local lCat = Object.getCategory(lUnit)
|
||||||
for _, zone in pairs(zones) do
|
for _, zone in pairs(zones) do
|
||||||
if unit_pos and isActive == true 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
|
||||||
in_zone_units[#in_zone_units + 1] = { unit = lUnit, zone_name = zone.name }
|
in_zone_units[#in_zone_units + 1] = { unit = lUnit, zone_name = zone.name }
|
||||||
@@ -277,9 +262,9 @@ do -- INIT DCS_UTIL
|
|||||||
--- takes a list of groups and returns all the group leaders that are in any of the zones
|
--- takes a list of groups and returns all the group leaders that are in any of the zones
|
||||||
---@param group_names table unit names
|
---@param group_names table unit names
|
||||||
---@param zone_name string zone names
|
---@param zone_name string zone names
|
||||||
---@return Array<string> groupnames list of group names
|
---@return table groupnames list of group names
|
||||||
function DCS_UTIL.getGroupsInZone(group_names, zone_name)
|
function DCS_UTIL.getGroupsInZone(group_names, zone_name)
|
||||||
local zone = DCS_UTIL.__trigger_zones[zone_name] --[[@as SpearheadTriggerZone?]]
|
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
||||||
if zone == nil then
|
if zone == nil then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
@@ -292,13 +277,11 @@ do -- INIT DCS_UTIL
|
|||||||
---@param zone SpearheadTriggerZone
|
---@param zone SpearheadTriggerZone
|
||||||
---@return Array<string> groupnames list of groups that are in the zone
|
---@return Array<string> groupnames list of groups that are in the zone
|
||||||
function DCS_UTIL.areGroupsInCustomZone(group_names, zone)
|
function DCS_UTIL.areGroupsInCustomZone(group_names, zone)
|
||||||
---@type Array<{ unit : Unit|StaticObject, groupname: string }>
|
|
||||||
local units = {}
|
local units = {}
|
||||||
if Util.tableLength(group_names) < 1 then return {} end
|
if Util.tableLength(group_names) < 1 then return {} end
|
||||||
|
|
||||||
for k = 1, #group_names do
|
for k = 1, #group_names do
|
||||||
---@type { unit : Unit|StaticObject|nil, groupname: string }|nil
|
local entry = nil
|
||||||
local entry
|
|
||||||
local group = Group.getByName(group_names[k])
|
local group = Group.getByName(group_names[k])
|
||||||
if group ~= nil then
|
if group ~= nil then
|
||||||
entry = { unit = group:getUnit(1), groupname = group_names[k] }
|
entry = { unit = group:getUnit(1), groupname = group_names[k] }
|
||||||
@@ -307,7 +290,7 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
if entry and entry.unit and entry.unit:isExist() == true then
|
if entry and entry.unit and entry.unit:isExist() == true then
|
||||||
units[#units + 1] = { groupname = entry.groupname, unit = entry.unit }
|
units[#units + 1] = entry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -325,8 +308,8 @@ do -- INIT DCS_UTIL
|
|||||||
--- takes a x, y poistion and checks if it is inside any of the zones
|
--- takes a x, y poistion and checks if it is inside any of the zones
|
||||||
---@param x number North South position
|
---@param x number North South position
|
||||||
---@param z number West East position
|
---@param z number West East position
|
||||||
---@param zone_names Array<string> zone names
|
---@param zone_names table zone names
|
||||||
---@return Array<string> zones list of objects { zone_name = zoneName}
|
---@return table zones list of objects { zone_name = zoneName}
|
||||||
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 = {}
|
||||||
@@ -336,7 +319,7 @@ do -- INIT DCS_UTIL
|
|||||||
zones[#zones + 1] = zone
|
zones[#zones + 1] = zone
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---@type Array<string>
|
|
||||||
local result_zones = {}
|
local result_zones = {}
|
||||||
for _, 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
|
||||||
@@ -413,18 +396,6 @@ do -- INIT DCS_UTIL
|
|||||||
return nil;
|
return nil;
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return Array<string>
|
|
||||||
function DCS_UTIL.getAllGroupCategoryNames()
|
|
||||||
return {
|
|
||||||
"airplane",
|
|
||||||
"helicopter",
|
|
||||||
"ground",
|
|
||||||
"ship",
|
|
||||||
"train",
|
|
||||||
"static"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
---@type table<string, CoordType>
|
---@type table<string, CoordType>
|
||||||
local config =
|
local config =
|
||||||
{
|
{
|
||||||
@@ -437,8 +408,7 @@ do -- INIT DCS_UTIL
|
|||||||
|
|
||||||
|
|
||||||
---@param location Vec2
|
---@param location Vec2
|
||||||
---@param unitType string?
|
---@param unitType string
|
||||||
---@return string?
|
|
||||||
function DCS_UTIL.convertVec2ToUnitUsableType(location, unitType)
|
function DCS_UTIL.convertVec2ToUnitUsableType(location, unitType)
|
||||||
|
|
||||||
local height = land.getHeight(location)
|
local height = land.getHeight(location)
|
||||||
@@ -459,7 +429,6 @@ do -- INIT DCS_UTIL
|
|||||||
---@private
|
---@private
|
||||||
---@param location Vec3
|
---@param location Vec3
|
||||||
---@param coordType CoordType
|
---@param coordType CoordType
|
||||||
---@return string?
|
|
||||||
function DCS_UTIL.convertToDisplayCoord(location, coordType)
|
function DCS_UTIL.convertToDisplayCoord(location, coordType)
|
||||||
local lattitude, longitude, altitude = coord.LOtoLL(location)
|
local lattitude, longitude, altitude = coord.LOtoLL(location)
|
||||||
|
|
||||||
@@ -471,7 +440,7 @@ do -- INIT DCS_UTIL
|
|||||||
-- Convert DD to DDM (Degrees Decimal Minutes)
|
-- Convert DD to DDM (Degrees Decimal Minutes)
|
||||||
local function dd_to_ddm(dd)
|
local function dd_to_ddm(dd)
|
||||||
local degrees = math.floor(math.abs(dd))
|
local degrees = math.floor(math.abs(dd))
|
||||||
local minutes = (math.abs(dd) - degrees) * 60 --[[@as number]]
|
local minutes = (math.abs(dd) - degrees) * 60
|
||||||
local sign = dd >= 0 and 1 or -1
|
local sign = dd >= 0 and 1 or -1
|
||||||
return degrees * sign, minutes
|
return degrees * sign, minutes
|
||||||
end
|
end
|
||||||
@@ -590,7 +559,6 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param group Group
|
---@param group Group
|
||||||
---@return string? unit type name
|
|
||||||
function DCS_UTIL.getUnitTypeFromGroup(group)
|
function DCS_UTIL.getUnitTypeFromGroup(group)
|
||||||
for _, unit in pairs(group:getUnits()) do
|
for _, unit in pairs(group:getUnits()) do
|
||||||
if unit and unit:isExist() then
|
if unit and unit:isExist() then
|
||||||
@@ -603,7 +571,6 @@ do -- INIT DCS_UTIL
|
|||||||
---comment Get all units that are players
|
---comment Get all units that are players
|
||||||
---@return Array<Unit> units
|
---@return Array<Unit> units
|
||||||
function DCS_UTIL.getAllPlayerUnits()
|
function DCS_UTIL.getAllPlayerUnits()
|
||||||
---@type Array<Unit>
|
|
||||||
local units = {}
|
local units = {}
|
||||||
for i = 0, 2 do
|
for i = 0, 2 do
|
||||||
local players = coalition.getPlayers(i)
|
local players = coalition.getPlayers(i)
|
||||||
@@ -649,7 +616,6 @@ do -- INIT DCS_UTIL
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param unitName string
|
|
||||||
function DCS_UTIL.CleanCorpse(unitName)
|
function DCS_UTIL.CleanCorpse(unitName)
|
||||||
unitName = "dead_" .. unitName
|
unitName = "dead_" .. unitName
|
||||||
local object = StaticObject.getByName(unitName)
|
local object = StaticObject.getByName(unitName)
|
||||||
@@ -768,8 +734,6 @@ do -- INIT DCS_UTIL
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param groupName string
|
|
||||||
---@param offset number?
|
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function DCS_UTIL.IsBingoFuel(groupName, offset)
|
function DCS_UTIL.IsBingoFuel(groupName, offset)
|
||||||
if offset == nil then offset = 0 end
|
if offset == nil then offset = 0 end
|
||||||
|
|||||||
@@ -3,13 +3,6 @@ local Util = require("classes.util.Util")
|
|||||||
local SpearheadConfig = require("classes.configuration.GlobalConfig")
|
local SpearheadConfig = require("classes.configuration.GlobalConfig")
|
||||||
|
|
||||||
|
|
||||||
--- @alias LogLevel
|
|
||||||
--- | "DEBUG"
|
|
||||||
--- | "INFO"
|
|
||||||
--- | "WARN"
|
|
||||||
--- | "ERROR"
|
|
||||||
--- | "NONE"
|
|
||||||
|
|
||||||
---@type LogLevel
|
---@type LogLevel
|
||||||
local defaultLogLevel = "INFO"
|
local defaultLogLevel = "INFO"
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
|
|
||||||
---@class MissionEditingWarnings
|
---@class MissionEditingWarnings
|
||||||
local MissionEditingWarnings = {}
|
local MissionEditingWarnings = {}
|
||||||
|
|
||||||
---@type table<number, string>
|
|
||||||
MissionEditingWarnings.warnings = {}
|
|
||||||
|
|
||||||
function MissionEditingWarnings.Add(warningMessage)
|
function MissionEditingWarnings.Add(warningMessage)
|
||||||
table.insert(MissionEditingWarnings.warnings, warningMessage or "skip")
|
table.insert(MissionEditingWarnings, warningMessage or "skip")
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param logger Logger
|
---@param logger Logger
|
||||||
@@ -16,12 +12,12 @@ function MissionEditingWarnings.WriteAll(logger)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not MissionEditingWarnings.warnings or #MissionEditingWarnings.warnings == 0 then
|
if not MissionEditingWarnings or #MissionEditingWarnings == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
logger:warn("Mission Editor Warnings:")
|
logger:warn("Mission Editor Warnings:")
|
||||||
for _, warning in ipairs(MissionEditingWarnings.warnings) do
|
for _, warning in ipairs(MissionEditingWarnings) do
|
||||||
logger:warn("- " .. warning)
|
logger:warn("- " .. warning)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+22
-45
@@ -1,13 +1,13 @@
|
|||||||
---@class Util
|
---@class Util
|
||||||
local UTIL = {}
|
local UTIL = {}
|
||||||
do -- INIT UTIL
|
do -- INIT UTIL
|
||||||
---splits a string in sub parts by separator
|
---splits a string in sub parts by seperator
|
||||||
---@param input string
|
---@param input string
|
||||||
---@param separator string
|
---@param seperator string
|
||||||
---@return Array<string> result list of strings
|
---@return table result list of strings
|
||||||
function UTIL.split_string(input, separator)
|
function UTIL.split_string(input, seperator)
|
||||||
if separator == nil then
|
if seperator == nil then
|
||||||
separator = " "
|
seperator = " "
|
||||||
end
|
end
|
||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
@@ -15,14 +15,14 @@ do -- INIT UTIL
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
for str in string.gmatch(input, "[^" .. separator .. "]+") do
|
for str in string.gmatch(input, "[^" .. seperator .. "]+") do
|
||||||
table.insert(result, str)
|
table.insert(result, str)
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param table table<any, any>
|
---@param table any
|
||||||
---@return number
|
---@return number
|
||||||
function UTIL.tableLength(table)
|
function UTIL.tableLength(table)
|
||||||
if table == nil then return 0 end
|
if table == nil then return 0 end
|
||||||
@@ -35,34 +35,23 @@ do -- INIT UTIL
|
|||||||
---@param orig table
|
---@param orig table
|
||||||
---@return table copy
|
---@return table copy
|
||||||
function UTIL.deepCopyTable(orig)
|
function UTIL.deepCopyTable(orig)
|
||||||
|
local orig_type = type(orig)
|
||||||
---@param original any
|
|
||||||
---@return any
|
|
||||||
local function deepCopy(original)
|
|
||||||
local orig_type = type(original)
|
|
||||||
---@type any
|
|
||||||
local copy
|
local copy
|
||||||
if orig_type == 'table' then
|
if orig_type == 'table' then
|
||||||
original = original --[[@as table<any, any>]]
|
copy = {}
|
||||||
copy = {} --[[@as table<any, any>]]
|
for orig_key, orig_value in next, orig, nil do
|
||||||
for orig_key, orig_value in pairs(original) do
|
copy[UTIL.deepCopyTable(orig_key)] = UTIL.deepCopyTable(orig_value)
|
||||||
local copiedKey = deepCopy(orig_key) --[[@as any]]
|
|
||||||
copy[copiedKey] = deepCopy(orig_value)
|
|
||||||
end
|
end
|
||||||
setmetatable(copy, deepCopy(getmetatable(original)))
|
setmetatable(copy, UTIL.deepCopyTable(getmetatable(orig)))
|
||||||
else -- number, string, boolean, etc
|
else -- number, string, boolean, etc
|
||||||
copy = original --[[@as any]]
|
copy = orig
|
||||||
end
|
end
|
||||||
return copy
|
return copy
|
||||||
end
|
end
|
||||||
|
|
||||||
return deepCopy(orig)
|
|
||||||
end
|
|
||||||
|
|
||||||
---Gets a random from the list
|
---Gets a random from the list
|
||||||
---@generic T
|
---@param list Array
|
||||||
---@param list Array<T>
|
---@return any @random element from the list
|
||||||
---@return T @random element from the list
|
|
||||||
function UTIL.randomFromList(list)
|
function UTIL.randomFromList(list)
|
||||||
local max = #list
|
local max = #list
|
||||||
|
|
||||||
@@ -76,13 +65,11 @@ do -- INIT UTIL
|
|||||||
return list[random]
|
return list[random]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@generic T
|
---@param list Array
|
||||||
---@param list Array<T>
|
|
||||||
---@param start number start
|
---@param start number start
|
||||||
---@param n number length
|
---@param n number length
|
||||||
---@return Array<T>
|
---@return Array
|
||||||
function UTIL.sublist(list, start, n)
|
function UTIL.sublist(list, start, n)
|
||||||
---@type table<number, any>
|
|
||||||
local result = {}
|
local result = {}
|
||||||
for i = start, n do
|
for i = start, n do
|
||||||
result[#result + 1] = list[i]
|
result[#result + 1] = list[i]
|
||||||
@@ -103,10 +90,9 @@ do -- INIT UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function table_print(tt, indent, done)
|
local function table_print(tt, indent, done)
|
||||||
done = done or {} --[[@as table<any, boolean>]]
|
done = done or {}
|
||||||
indent = indent or 0
|
indent = indent or 0
|
||||||
if type(tt) == "table" then
|
if type(tt) == "table" then
|
||||||
tt = tt --[[@as table<any, any>]]
|
|
||||||
local sb = {}
|
local sb = {}
|
||||||
for key, value in pairs(tt) do
|
for key, value in pairs(tt) do
|
||||||
table.insert(sb, string.rep(" ", indent)) -- indent it
|
table.insert(sb, string.rep(" ", indent)) -- indent it
|
||||||
@@ -134,7 +120,7 @@ do -- INIT UTIL
|
|||||||
---@param findable string
|
---@param findable string
|
||||||
---@param ignoreCase boolean?
|
---@param ignoreCase boolean?
|
||||||
---@return boolean
|
---@return boolean
|
||||||
UTIL.startsWith = function(str, findable, ignoreCase)
|
UTIL.startswith = function(str, findable, ignoreCase)
|
||||||
if ignoreCase == true then
|
if ignoreCase == true then
|
||||||
return string.lower(str):find('^' .. string.lower(findable)) ~= nil
|
return string.lower(str):find('^' .. string.lower(findable)) ~= nil
|
||||||
end
|
end
|
||||||
@@ -160,11 +146,11 @@ do -- INIT UTIL
|
|||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param str string
|
---@param str string
|
||||||
---@param findableTable table<any,any>
|
---@param findableTable table
|
||||||
---@return boolean
|
---@return boolean
|
||||||
UTIL.startswithAny = function(str, findableTable)
|
UTIL.startswithAny = function(str, findableTable)
|
||||||
for _, 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
|
||||||
end
|
end
|
||||||
@@ -258,7 +244,6 @@ do -- INIT UTIL
|
|||||||
---@return boolean
|
---@return boolean
|
||||||
local function isInComplexPolygon(polygon, x, y)
|
local function isInComplexPolygon(polygon, x, y)
|
||||||
---@param poly Array<Vec2> of pairs { x, y }
|
---@param poly Array<Vec2> of pairs { x, y }
|
||||||
---@return Array<{ x1: number, z1: number, x2: number, z2: number }>
|
|
||||||
local function getEdges(poly)
|
local function getEdges(poly)
|
||||||
local result = {}
|
local result = {}
|
||||||
for i = 1, #poly do
|
for i = 1, #poly do
|
||||||
@@ -295,7 +280,6 @@ do -- INIT UTIL
|
|||||||
|
|
||||||
---@param point Vec3
|
---@param point Vec3
|
||||||
---@param zone SpearheadTriggerZone
|
---@param zone SpearheadTriggerZone
|
||||||
---@return boolean
|
|
||||||
function UTIL.is3dPointInZone(point, zone)
|
function UTIL.is3dPointInZone(point, zone)
|
||||||
if zone.zone_type == "Polygon" and zone.verts then
|
if zone.zone_type == "Polygon" and zone.verts then
|
||||||
if UTIL.IsPointInPolygon(zone.verts, point.x, point.z) == true then
|
if UTIL.IsPointInPolygon(zone.verts, point.x, point.z) == true then
|
||||||
@@ -312,7 +296,6 @@ do -- INIT UTIL
|
|||||||
|
|
||||||
---@param point Vec2
|
---@param point Vec2
|
||||||
---@param zone SpearheadTriggerZone
|
---@param zone SpearheadTriggerZone
|
||||||
---@return boolean
|
|
||||||
function UTIL.is2dPointInZone(point, zone)
|
function UTIL.is2dPointInZone(point, zone)
|
||||||
if zone.zone_type == "Polygon" and zone.verts then
|
if zone.zone_type == "Polygon" and zone.verts then
|
||||||
if UTIL.IsPointInPolygon(zone.verts, point.x, point.y) == true then
|
if UTIL.IsPointInPolygon(zone.verts, point.x, point.y) == true then
|
||||||
@@ -464,8 +447,6 @@ do -- INIT UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param points Array<Vec2>
|
---@param points Array<Vec2>
|
||||||
---@param meters number
|
|
||||||
---@return Array<Vec2>
|
|
||||||
function UTIL.enlargeConvexHull(points, meters)
|
function UTIL.enlargeConvexHull(points, meters)
|
||||||
if points == nil or #points == 0 then
|
if points == nil or #points == 0 then
|
||||||
return {}
|
return {}
|
||||||
@@ -543,10 +524,6 @@ function UTIL.GetTangentHullPointsFromOrigin(hull, origin)
|
|||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param a Vec2
|
|
||||||
---@param b Vec2
|
|
||||||
---@param c Vec2
|
|
||||||
---@return number
|
|
||||||
local function orientation(a, b, c)
|
local function orientation(a, b, c)
|
||||||
-- Returns >0 if c is to the left of ab, <0 if to the right, 0 if colinear
|
-- Returns >0 if c is to the left of ab, <0 if to the right, 0 if colinear
|
||||||
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
|
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
|
||||||
|
|||||||
Reference in New Issue
Block a user