Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
446a98dc3b | ||
|
|
8cacad84a1 | ||
|
|
cbccedf710 | ||
|
|
e986887dd8 | ||
|
|
9549e8c48e | ||
|
|
9b2540d461 | ||
|
|
f3a38db5ca | ||
|
|
81d9aa7265 |
@@ -0,0 +1,140 @@
|
|||||||
|
name: PR Prerequisites
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- develop
|
||||||
|
|
||||||
|
env:
|
||||||
|
LUA_VERSION: "5.1"
|
||||||
|
LUA_LANGUAGE_SERVER_VERSION: "3.19.1"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
bundles_without_error:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Bundles Without Errors
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Lua
|
||||||
|
uses: leafo/gh-actions-lua@v13
|
||||||
|
with:
|
||||||
|
luaVersion: ${{ env.LUA_VERSION }}
|
||||||
|
|
||||||
|
- name: Compile Spearhead
|
||||||
|
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-actions/bundle-script@bundle-script/v1
|
||||||
|
with:
|
||||||
|
source-root: ./src
|
||||||
|
output-file: ./output/spearhead.lua
|
||||||
|
|
||||||
|
- name: Verify Compiled Lua Syntax
|
||||||
|
run: lua -e "assert(loadfile('./output/spearhead.lua'))"
|
||||||
|
|
||||||
|
- name: Set up Luarocks
|
||||||
|
uses: leafo/gh-actions-luarocks@v4
|
||||||
|
|
||||||
|
- name: Install luacheck
|
||||||
|
run: luarocks install luacheck
|
||||||
|
|
||||||
|
# "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
|
||||||
|
run: luacheck ./output/spearhead.lua
|
||||||
|
|
||||||
|
lua_check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Lua Check
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Lua
|
||||||
|
uses: leafo/gh-actions-lua@v13
|
||||||
|
with:
|
||||||
|
luaVersion: ${{ env.LUA_VERSION }}
|
||||||
|
|
||||||
|
- name: Install Dcs Plugins
|
||||||
|
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-actions/install-lua-addon@install-lua-addon/v1
|
||||||
|
with:
|
||||||
|
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
|
||||||
|
run: |
|
||||||
|
mkdir -p ./luals
|
||||||
|
# For Ubuntu/Debian
|
||||||
|
wget https://github.com/LuaLS/lua-language-server/releases/download/${{ env.LUA_LANGUAGE_SERVER_VERSION }}/lua-language-server-${{ env.LUA_LANGUAGE_SERVER_VERSION }}-linux-x64.tar.gz
|
||||||
|
tar -xzf lua-language-server-*.tar.gz -C ./luals
|
||||||
|
rm lua-language-server-*.tar.gz
|
||||||
|
|
||||||
|
- name: Verify Lua Language Server Installation
|
||||||
|
run: ./luals/bin/lua-language-server --version
|
||||||
|
|
||||||
|
- name: 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
|
||||||
|
run: |
|
||||||
|
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 Release
|
name: Publish Beta 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-action@action/v0
|
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-actions/bundle-script@bundle-script/v1
|
||||||
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-action@action/v0
|
uses: https://git.dutchie031.com/dutchie031/DcsMissionScriptingTools/github-actions/bundle-script@bundle-script/v1
|
||||||
with:
|
with:
|
||||||
source-root: ./src
|
source-root: ./src
|
||||||
output-file: ./output/spearhead.lua
|
output-file: ./output/spearhead.lua
|
||||||
|
|||||||
@@ -3,5 +3,6 @@
|
|||||||
|
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
|
.vscode/lua-addons
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
**\settings.json
|
**\settings.json
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
||||||
|
"runtime": {
|
||||||
|
"version": "Lua 5.1"
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"checkThirdParty": false,
|
||||||
|
"maxPreload": 1600,
|
||||||
|
"preloadFileSize": 1000,
|
||||||
|
"ignoreDir": [ "config.lua" ]
|
||||||
|
},
|
||||||
|
"diagnostics": {
|
||||||
|
"enable": true,
|
||||||
|
"globals": [
|
||||||
|
"lfs"
|
||||||
|
],
|
||||||
|
"groupSeverity": {
|
||||||
|
"duplicate": "Warning",
|
||||||
|
"global":"Warning",
|
||||||
|
"luadoc": "Warning",
|
||||||
|
"redefined": "Warning",
|
||||||
|
"strong": "Warning",
|
||||||
|
"type-check": "Warning",
|
||||||
|
"unbalanced" : "Warning",
|
||||||
|
"ambiguity": "Warning",
|
||||||
|
"strict": "Warning",
|
||||||
|
"unused": "Warning"
|
||||||
|
},
|
||||||
|
"groupFileStatus": {
|
||||||
|
"ambiguity": "Any",
|
||||||
|
"await": "Any",
|
||||||
|
"duplicate": "Any",
|
||||||
|
"global": "Any",
|
||||||
|
"luadoc": "Any",
|
||||||
|
"redefined": "Any",
|
||||||
|
"strict": "Any",
|
||||||
|
"type-check": "Any",
|
||||||
|
"unbalanced": "Any",
|
||||||
|
"unused": "Any",
|
||||||
|
"strong": "Any"
|
||||||
|
},
|
||||||
|
"ignoredFiles": "Opened",
|
||||||
|
"libraryFiles": "Opened"
|
||||||
|
},
|
||||||
|
"hint": {
|
||||||
|
"enable": false
|
||||||
|
},
|
||||||
|
"completion": {
|
||||||
|
"enable": true
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"sumneko.lua"
|
"dutchie031.dutchies-dcs-scripting-tools",
|
||||||
|
"sumneko.lua",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,11 @@
|
|||||||
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.
|
||||||
#44
|
#44
|
||||||
|
|
||||||
|
- Issue: #42
|
||||||
|
DEEPSTRIKE now added as a possible feature.
|
||||||
|
This enables to have missions active in "Pre-Activated" Stages.
|
||||||
|
#48
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
## [0.13.0] 2026-08
|
## [0.13.0] 2026-08
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
--assert(loadfile("C:\\Repos\\DCS\\Spearhead\\dev\\dev_classes.lua"))()
|
|
||||||
|
|
||||||
local basePath = "C:\\Repos\\DCS\\Spearhead\\"
|
|
||||||
local classPath = basePath .. "classes\\"
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "_baseClasses\\Queue.lua"))()
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "spearhead_base.lua"))()
|
|
||||||
assert(loadfile(classPath .. "spearhead_routeutil.lua"))()
|
|
||||||
assert(loadfile(classPath .. "spearhead_events.lua"))()
|
|
||||||
assert(loadfile(classPath .. "spearhead_db.lua"))()
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "fleetClasses\\FleetGroup.lua"))()
|
|
||||||
assert(loadfile(classPath .. "fleetClasses\\GlobalFleetManager.lua"))()
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "helpers\\MizGroupsManager.lua"))()
|
|
||||||
assert(loadfile(classPath .. "helpers\\SpawnManager.lua"))()
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "configuration\\CapConfig.lua"))()
|
|
||||||
assert(loadfile(classPath .. "configuration\\StageConfig.lua"))()
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\GlobalStageManager.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\missions\\baseMissions\\Mission.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\missions\\ZoneMission.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\missions\\RunwayStrikeMission.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\missions\\BuildableMission.lua"))()
|
|
||||||
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\Stages\\BaseStage\\Stage.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\Stages\\PrimaryStage.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\Stages\\ExtraStage.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\Stages\\WaitingStage.lua"))()
|
|
||||||
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\Groups\\SpearheadGroup.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\Groups\\SpearheadSceneryObject.lua"))()
|
|
||||||
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\helpers\\MissionCommandsHelper.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\helpers\\SupplyConfig.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\helpers\\SupplyUnitsTracker.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\helpers\\BattleManager.lua"))()
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\abstract\\BuildableZone.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\StageBase.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\BlueSam.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\FarpZone.lua"))()
|
|
||||||
assert(loadfile(classPath .. "stageClasses\\SpecialZones\\SupplyHub.lua"))()
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "capClasses\\taskings\\RTB.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\taskings\\CAP.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\taskings\\SWEEP.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\taskings\\INTERCEPT.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\airGroups\\AirGroup.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\airGroups\\CapGroup.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\airGroups\\SweepGroup.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\airGroups\\InterceptGroup.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\detection\\DetectionManager.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\GlobalCapManager.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\CapAirbase.lua"))()
|
|
||||||
assert(loadfile(classPath .. "capClasses\\runwayBombing\\RunwayBombingTracker.lua"))()
|
|
||||||
|
|
||||||
assert(loadfile(classPath .. "persistence\\Persistence.lua"))()
|
|
||||||
|
|
||||||
-- Startup:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assert(loadfile(basePath .. "main.lua"))()
|
|
||||||
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
|
|
||||||
SpearheadConfig = {
|
|
||||||
|
|
||||||
debugEnabled = true,
|
|
||||||
CapConfig = {
|
|
||||||
--quickly enable of disable the entire CAP Logic
|
|
||||||
--(you can also just rename all units to not be named "CAP_")
|
|
||||||
enabled = true, -- default true
|
|
||||||
|
|
||||||
--min ground speed for CAP aircraft during patrol
|
|
||||||
-- unit: knots
|
|
||||||
minSpeed = 400, -- default 400
|
|
||||||
|
|
||||||
--max speed for CAP aircraft during patrol
|
|
||||||
-- unit: knots
|
|
||||||
maxSpeed = 500, -- default 500
|
|
||||||
|
|
||||||
--minAlt for aircraft on patrol
|
|
||||||
-- unit: feet
|
|
||||||
minAlt = 18000, -- default 18000
|
|
||||||
|
|
||||||
--maxAlt for aircraft on patrol
|
|
||||||
-- unit: feet
|
|
||||||
maxAlt = 28000, -- default 28000
|
|
||||||
|
|
||||||
--Delay for aircraft from touchdown to off the chocks.
|
|
||||||
-- unit: seconds
|
|
||||||
rearmDelay = 180, -- default 600
|
|
||||||
repairDelay = 600, -- default 600
|
|
||||||
--Delay for aircraft from death to takeoff.
|
|
||||||
--When the seconds remaining is the same at the rearmDelay it will be spawned on the ramp and follow the rearm logic.
|
|
||||||
-- !! Can not be lower than rearmDelay
|
|
||||||
-- unit: seconds
|
|
||||||
deathDelay = 1800, -- default 1800
|
|
||||||
},
|
|
||||||
StageConfig = {
|
|
||||||
|
|
||||||
-- management of stages and its missions.
|
|
||||||
-- This is not related to CAP managers which will continue to work even if stage management is disabled
|
|
||||||
enabled = true, -- default true
|
|
||||||
|
|
||||||
--Will draw the active and the next stage
|
|
||||||
drawStages = true, -- default true
|
|
||||||
drawPreActivated = true,
|
|
||||||
markLastContact = true,
|
|
||||||
|
|
||||||
--AutoStages will continue to the next stage automatically on completion of the missions within the stage.
|
|
||||||
-- If you want to make it so the next stage triggers only when you want to disable it here and manually implement the actions needed.
|
|
||||||
--[[
|
|
||||||
TODO: Add manual stage transition documentation
|
|
||||||
]]
|
|
||||||
autoStages = true, --default true
|
|
||||||
|
|
||||||
--Maximum missions per stage (includes all types of missions)
|
|
||||||
maxMissionStage = 100,
|
|
||||||
|
|
||||||
--Stage starting number
|
|
||||||
startingStage = 1,
|
|
||||||
|
|
||||||
---DEBUG logging. Consider keeping this disabled
|
|
||||||
debugEnabled = true
|
|
||||||
},
|
|
||||||
Persistence = {
|
|
||||||
--- io and lfs cannot be sanitized in the MissionScripting.lua
|
|
||||||
|
|
||||||
--- enables or disables the persistence logic in spearhead
|
|
||||||
enabled = true,
|
|
||||||
|
|
||||||
--- sets the directory where the persistence file is stored
|
|
||||||
--- if nil then lfs.writedir() will be used.
|
|
||||||
--- which will
|
|
||||||
directory = nil ,
|
|
||||||
|
|
||||||
--- the filename of the persistence file. Should end with .json for convention, but any text extension should do.
|
|
||||||
fileName = "Spearhead_Persistence_Dev"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
---@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
|
|
||||||
@@ -2,7 +2,6 @@ local Util = require("classes.util.Util")
|
|||||||
local CapGroup = require("classes.capClasses.airGroups.CapGroup")
|
local CapGroup = require("classes.capClasses.airGroups.CapGroup")
|
||||||
local SweepGroup = require("classes.capClasses.airGroups.SweepGroup")
|
local SweepGroup = require("classes.capClasses.airGroups.SweepGroup")
|
||||||
local InterceptGroup = require("classes.capClasses.airGroups.InterceptGroup")
|
local InterceptGroup = require("classes.capClasses.airGroups.InterceptGroup")
|
||||||
local RunwayBombingTracker = require("classes.capClasses.runwayBombing.RunwayBombingTracker")
|
|
||||||
local SpearheadEvents = require("classes.spearhead_events")
|
local SpearheadEvents = require("classes.spearhead_events")
|
||||||
local RunwayStrikeMission = require("classes.stageClasses.missions.RunwayStrikeMission")
|
local RunwayStrikeMission = require("classes.stageClasses.missions.RunwayStrikeMission")
|
||||||
|
|
||||||
@@ -37,12 +36,11 @@ end
|
|||||||
---@param database Database
|
---@param database Database
|
||||||
---@param logger table
|
---@param logger table
|
||||||
---@param capConfig table
|
---@param capConfig table
|
||||||
---@param stageConfig table
|
|
||||||
---@param runwayBombingTracker RunwayBombingTracker
|
---@param runwayBombingTracker RunwayBombingTracker
|
||||||
---@param detectionManager DetectionManager
|
---@param detectionManager DetectionManager
|
||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
---@return CapBase
|
---@return CapBase
|
||||||
function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
function CapBase.new(airbaseName, database, logger, capConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||||
CapBase.__index = CapBase
|
CapBase.__index = CapBase
|
||||||
local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]]
|
local self = setmetatable({}, { __index = CapBase }) --[[@as CapBase]]
|
||||||
|
|
||||||
@@ -61,7 +59,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
|||||||
|
|
||||||
local baseData = database:getAirbaseDataForZone(airbaseName)
|
local baseData = database:getAirbaseDataForZone(airbaseName)
|
||||||
if baseData and baseData.CapGroups then
|
if baseData and baseData.CapGroups then
|
||||||
for key, name in pairs(baseData.CapGroups) do
|
for _, name in pairs(baseData.CapGroups) do
|
||||||
local capGroup = CapGroup.New(name, capConfig, logger, spawnManager)
|
local capGroup = CapGroup.New(name, capConfig, logger, spawnManager)
|
||||||
if capGroup then
|
if capGroup then
|
||||||
self.capGroupsByName[name] = capGroup
|
self.capGroupsByName[name] = capGroup
|
||||||
@@ -70,7 +68,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
|||||||
end
|
end
|
||||||
|
|
||||||
if baseData and baseData.SweepGroups then
|
if baseData and baseData.SweepGroups then
|
||||||
for key, name in pairs(baseData.SweepGroups) do
|
for _, name in pairs(baseData.SweepGroups) do
|
||||||
local sweepGroup = SweepGroup.New(name, capConfig, logger, spawnManager)
|
local sweepGroup = SweepGroup.New(name, capConfig, logger, spawnManager)
|
||||||
if sweepGroup then
|
if sweepGroup then
|
||||||
self.sweepGroupsByName[name] = sweepGroup
|
self.sweepGroupsByName[name] = sweepGroup
|
||||||
@@ -79,7 +77,7 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
|||||||
end
|
end
|
||||||
|
|
||||||
if baseData and baseData.InterceptGroups then
|
if baseData and baseData.InterceptGroups then
|
||||||
for key, name in pairs(baseData.InterceptGroups) do
|
for _, name in pairs(baseData.InterceptGroups) do
|
||||||
local interceptGroup = InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
|
local interceptGroup = InterceptGroup.New(name, capConfig, logger, detectionManager, spawnManager)
|
||||||
if interceptGroup then
|
if interceptGroup then
|
||||||
self.interceptGroupsByName[name] = interceptGroup
|
self.interceptGroupsByName[name] = interceptGroup
|
||||||
@@ -98,7 +96,6 @@ function CapBase.new(airbaseName, database, logger, capConfig, stageConfig, runw
|
|||||||
|
|
||||||
timer.scheduleFunction(CheckStateContinuous, self, timer.getTime() + 15)
|
timer.scheduleFunction(CheckStateContinuous, self, timer.getTime() + 15)
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -127,7 +124,7 @@ end
|
|||||||
|
|
||||||
function CapBase:SpawnIfApplicable()
|
function CapBase:SpawnIfApplicable()
|
||||||
self.logger:debug("Check spawns for airbase " .. self.airbaseName)
|
self.logger:debug("Check spawns for airbase " .. self.airbaseName)
|
||||||
for groupName, capGroup in pairs(self.capGroupsByName) do
|
for _, capGroup in pairs(self.capGroupsByName) do
|
||||||
local targetStage = capGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
local targetStage = capGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||||
|
|
||||||
if targetStage ~= nil and capGroup:GetState() == "UnSpawned" then
|
if targetStage ~= nil and capGroup:GetState() == "UnSpawned" then
|
||||||
@@ -135,7 +132,7 @@ function CapBase:SpawnIfApplicable()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for groupName, sweepGroup in pairs(self.sweepGroupsByName) do
|
for _, sweepGroup in pairs(self.sweepGroupsByName) do
|
||||||
local targetStage = sweepGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
local targetStage = sweepGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||||
|
|
||||||
if targetStage ~= nil and sweepGroup:GetState() == "UnSpawned" then
|
if targetStage ~= nil and sweepGroup:GetState() == "UnSpawned" then
|
||||||
@@ -143,7 +140,7 @@ function CapBase:SpawnIfApplicable()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for groupName, interceptGroup in pairs(self.interceptGroupsByName) do
|
for _, interceptGroup in pairs(self.interceptGroupsByName) do
|
||||||
local targetStage = interceptGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
local targetStage = interceptGroup:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||||
|
|
||||||
if targetStage ~= nil and interceptGroup:GetState() == "UnSpawned" then
|
if targetStage ~= nil and interceptGroup:GetState() == "UnSpawned" then
|
||||||
@@ -154,8 +151,9 @@ end
|
|||||||
|
|
||||||
function CapBase:CheckAndScheduleCAP()
|
function CapBase:CheckAndScheduleCAP()
|
||||||
self.logger:debug("Check taskings for airbase " .. self.airbaseName)
|
self.logger:debug("Check taskings for airbase " .. self.airbaseName)
|
||||||
|
---@type table<string, number>
|
||||||
local countPerStage = {}
|
local countPerStage = {}
|
||||||
|
---@type table<string, number>
|
||||||
local requiredPerStage = {}
|
local requiredPerStage = {}
|
||||||
|
|
||||||
local airbase = Airbase.getByName(self.airbaseName)
|
local airbase = Airbase.getByName(self.airbaseName)
|
||||||
@@ -312,8 +310,7 @@ function CapBase:CheckAndScheduleIntercept()
|
|||||||
|
|
||||||
self.logger:debug("Check intercept taskings for airbase " .. self.airbaseName)
|
self.logger:debug("Check intercept taskings for airbase " .. self.airbaseName)
|
||||||
|
|
||||||
local interceptZoneIDs = {}
|
---@type table<string, boolean>
|
||||||
|
|
||||||
local interceptZoneIDs = {}
|
local interceptZoneIDs = {}
|
||||||
|
|
||||||
local airbase = Airbase.getByName(self.airbaseName)
|
local airbase = Airbase.getByName(self.airbaseName)
|
||||||
@@ -321,7 +318,7 @@ function CapBase:CheckAndScheduleIntercept()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
for name, group in pairs(self.interceptGroupsByName) do
|
for _, group in pairs(self.interceptGroupsByName) do
|
||||||
local targetZoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
|
local targetZoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
|
||||||
if targetZoneID then
|
if targetZoneID then
|
||||||
interceptZoneIDs[targetZoneID] = true
|
interceptZoneIDs[targetZoneID] = true
|
||||||
@@ -379,7 +376,6 @@ function CapBase:CheckAndScheduleIntercept()
|
|||||||
if total < required then
|
if total < required then
|
||||||
for _, group in pairs(self.interceptGroupsByName) do
|
for _, group in pairs(self.interceptGroupsByName) do
|
||||||
if total < required then
|
if total < required then
|
||||||
local zoneID = group:GetZoneIDWhenStageID(tostring(self.activeStage))
|
|
||||||
if group:GetState() == "ReadyOnTheRamp" then
|
if group:GetState() == "ReadyOnTheRamp" then
|
||||||
group:SendToInterceptUnits(targets, name, airbase)
|
group:SendToInterceptUnits(targets, name, airbase)
|
||||||
total = total + 1
|
total = total + 1
|
||||||
|
|||||||
@@ -6,21 +6,19 @@ 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 activeAirbasesPerActiveStage = {}
|
|
||||||
local unitsPerzonePerStage = {}
|
|
||||||
|
|
||||||
local initiated = false
|
local initiated = false
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param database Database
|
---@param database Database
|
||||||
---@param capConfig table
|
---@param capConfig table
|
||||||
---@param stageConfig StageConfig
|
|
||||||
---@param detectionManager DetectionManager
|
---@param detectionManager DetectionManager
|
||||||
---@param logLevel LogLevel
|
---@param logLevel LogLevel
|
||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
function GlobalCapManager.start(database, capConfig, detectionManager, stageConfig, logLevel, spawnManager)
|
function GlobalCapManager.start(database, capConfig, detectionManager, logLevel, spawnManager)
|
||||||
if initiated == true then return end
|
if initiated == true then return end
|
||||||
|
|
||||||
local logger = Logger.new("AirbaseManager", logLevel)
|
local logger = Logger.new("AirbaseManager", logLevel)
|
||||||
@@ -29,7 +27,7 @@ do
|
|||||||
|
|
||||||
local zones = database:getStagezoneNames()
|
local zones = database:getStagezoneNames()
|
||||||
if zones then
|
if zones then
|
||||||
for key, stageName in pairs(zones) do
|
for _, stageName in pairs(zones) do
|
||||||
if airbasesPerStage[stageName] == nil then
|
if airbasesPerStage[stageName] == nil then
|
||||||
airbasesPerStage[stageName] = {}
|
airbasesPerStage[stageName] = {}
|
||||||
end
|
end
|
||||||
@@ -40,8 +38,7 @@ do
|
|||||||
if airbaseName then
|
if airbaseName then
|
||||||
local airbaseSpecificLogger = Logger.new("CAP_" .. airbaseName, logLevel)
|
local airbaseSpecificLogger = Logger.new("CAP_" .. airbaseName, logLevel)
|
||||||
|
|
||||||
local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, stageConfig, runwayBombingTracker, detectionManager, spawnManager)
|
local airbase = CapAirbase.new(airbaseName, database, airbaseSpecificLogger, capConfig, runwayBombingTracker, detectionManager, spawnManager)
|
||||||
|
|
||||||
if airbase then
|
if airbase then
|
||||||
table.insert(airbasesPerStage[stageName], airbase)
|
table.insert(airbasesPerStage[stageName], airbase)
|
||||||
allAirbasesByName[airbaseName] = airbase
|
allAirbasesByName[airbaseName] = airbase
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
local SpearheadEvents = require("classes.spearhead_events")
|
local SpearheadEvents = require("classes.spearhead_events")
|
||||||
local RTBMission = require("classes.capClasses.taskings.RTB")
|
local RTBMission = require("classes.capClasses.taskings.RTB")
|
||||||
local Util = require("classes.util.Util")
|
local Util = require("classes.util.Util")
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
|
||||||
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
||||||
local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing")
|
local CustomDrawing = require("classes.stageClasses.drawings.CustomDrawing")
|
||||||
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
||||||
|
|
||||||
---@class AirGroup : OnUnitLostListener
|
---@class AirGroup : OnUnitLostListener, OnGroupRTBListener, OnGroupRTBInTenListener, OnLandEventListener, OnGroupOnStationListener
|
||||||
---@field protected _logger Logger
|
---@field protected _logger Logger
|
||||||
---@field protected _groupName string
|
---@field protected _groupName string
|
||||||
---@field protected _groupType AirGroupType
|
---@field protected _groupType AirGroupType
|
||||||
@@ -81,7 +80,7 @@ function AirGroup:SetMission(mission)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local setMissionDelayed = function(data, time)
|
local setMissionDelayed = function(data, _)
|
||||||
data.self:SetMissionPrivate(data.mission)
|
data.self:SetMissionPrivate(data.mission)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -108,8 +107,9 @@ 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
|
||||||
for _, wp in pairs(mission.params.route.points) do
|
local routePoints = mission.params.route.points --[[@as Array<Vec2> ]]
|
||||||
if wp.x and wp.y then
|
for _, wp in pairs(routePoints) do
|
||||||
|
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,6 +199,8 @@ 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
|
||||||
@@ -264,6 +266,7 @@ 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
|
||||||
@@ -357,7 +360,7 @@ do --- RESPAWN FUNCTIONS
|
|||||||
self:SetState("Dead")
|
self:SetState("Dead")
|
||||||
|
|
||||||
---@param selfA AirGroup
|
---@param selfA AirGroup
|
||||||
local respawnTask = function(selfA, time)
|
local respawnTask = function(selfA, _)
|
||||||
selfA:StartRepair()
|
selfA:StartRepair()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -376,8 +379,7 @@ do --- RESPAWN FUNCTIONS
|
|||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param selfA AirGroup
|
local rearmTask = function(_, _)
|
||||||
local rearmTask = function(selfA, time)
|
|
||||||
self:StartRearm()
|
self:StartRearm()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -402,7 +404,7 @@ do --- RESPAWN FUNCTIONS
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param selfA AirGroup
|
---@param selfA AirGroup
|
||||||
local rearmTask = function(selfA, time)
|
local rearmTask = function(selfA, _)
|
||||||
selfA:MarkRearmComplete()
|
selfA:MarkRearmComplete()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -415,6 +417,7 @@ end
|
|||||||
do --EVENT LISTENERS
|
do --EVENT LISTENERS
|
||||||
---@param unit Unit
|
---@param unit Unit
|
||||||
function AirGroup:OnUnitLost(unit)
|
function AirGroup:OnUnitLost(unit)
|
||||||
|
if unit == nil then return end
|
||||||
self:CheckLiveness()
|
self:CheckLiveness()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -434,7 +437,7 @@ do --EVENT LISTENERS
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function AirGroup:OnUnitLanded(unit, airbase)
|
function AirGroup:OnUnitLanded(_, _)
|
||||||
local anyInAir = false
|
local anyInAir = false
|
||||||
local group = Group.getByName(self._groupName)
|
local group = Group.getByName(self._groupName)
|
||||||
if group then
|
if group then
|
||||||
|
|||||||
@@ -34,9 +34,10 @@ 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[stageID]
|
return self._targetZoneIdPerStage[tostring(stageID)]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return string?
|
---@return string?
|
||||||
@@ -107,13 +108,13 @@ function CapGroup:InitWithName(groupName)
|
|||||||
|
|
||||||
local subsplit = Util.split_string(configPart, "|")
|
local subsplit = Util.split_string(configPart, "|")
|
||||||
if subsplit then
|
if subsplit then
|
||||||
for key, value in pairs(subsplit) do
|
for _, value in pairs(subsplit) do
|
||||||
local keySplit = Util.split_string(value, "]")
|
local keySplit = Util.split_string(value, "]")
|
||||||
local targetZone = keySplit[2]
|
local targetZone = keySplit[2]
|
||||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||||
local commaSeperated = Util.split_string(allActives, ",")
|
local commaSeperated = Util.split_string(allActives, ",")
|
||||||
for _, value in pairs(commaSeperated) do
|
for _, childValue in pairs(commaSeperated) do
|
||||||
local dashSeperated = Util.split_string(value, "-")
|
local dashSeperated = Util.split_string(childValue, "-")
|
||||||
if Util.tableLength(dashSeperated) > 1 then
|
if Util.tableLength(dashSeperated) > 1 then
|
||||||
local from = tonumber(dashSeperated[1])
|
local from = tonumber(dashSeperated[1])
|
||||||
local till = tonumber(dashSeperated[2])
|
local till = tonumber(dashSeperated[2])
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ 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)
|
||||||
|
|
||||||
@@ -68,9 +69,10 @@ 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[stageID]
|
return self._targetZoneIdPerStage[tostring(stageID)]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return string?
|
---@return string?
|
||||||
@@ -91,6 +93,9 @@ 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
|
||||||
@@ -102,6 +107,7 @@ 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
|
||||||
@@ -213,8 +219,6 @@ function InterceptGroup:UpdateTask()
|
|||||||
self._currentTargetName = nil
|
self._currentTargetName = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local speed = self._config:getMaxSpeed()
|
local speed = self._config:getMaxSpeed()
|
||||||
local interceptPoint = self:GetInterceptPoint(groupPoint, speed, closestUnit)
|
local interceptPoint = self:GetInterceptPoint(groupPoint, speed, closestUnit)
|
||||||
|
|
||||||
@@ -222,7 +226,8 @@ 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
|
||||||
|
|
||||||
local mission = nil
|
---@type table
|
||||||
|
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(
|
||||||
@@ -323,13 +328,13 @@ function InterceptGroup:InitWithName(groupName)
|
|||||||
configPart = string.sub(configPart, 2, #configPart)
|
configPart = string.sub(configPart, 2, #configPart)
|
||||||
local subsplit = Util.split_string(configPart, "|")
|
local subsplit = Util.split_string(configPart, "|")
|
||||||
if subsplit then
|
if subsplit then
|
||||||
for key, value in pairs(subsplit) do
|
for _, value in pairs(subsplit) do
|
||||||
local keySplit = Util.split_string(value, "]")
|
local keySplit = Util.split_string(value, "]")
|
||||||
local targetZone = keySplit[2]
|
local targetZone = keySplit[2]
|
||||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||||
local commaSeperated = Util.split_string(allActives, ",")
|
local commaSeperated = Util.split_string(allActives, ",")
|
||||||
for _, value in pairs(commaSeperated) do
|
for _, childValue in pairs(commaSeperated) do
|
||||||
local dashSeperated = Util.split_string(value, "-")
|
local dashSeperated = Util.split_string(childValue, "-")
|
||||||
if Util.tableLength(dashSeperated) > 1 then
|
if Util.tableLength(dashSeperated) > 1 then
|
||||||
local from = tonumber(dashSeperated[1])
|
local from = tonumber(dashSeperated[1])
|
||||||
local till = tonumber(dashSeperated[2])
|
local till = tonumber(dashSeperated[2])
|
||||||
|
|||||||
@@ -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<number, string>
|
---@field _targetZoneIdPerStage table<string, string>
|
||||||
---@field _currentTargetZoneID string?
|
---@field _currentTargetZoneID string?
|
||||||
local SweepGroup = {}
|
local SweepGroup = {}
|
||||||
SweepGroup.__index = SweepGroup
|
SweepGroup.__index = SweepGroup
|
||||||
@@ -26,9 +26,10 @@ 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[stageID]
|
return self._targetZoneIdPerStage[tostring(stageID)]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return string?
|
---@return string?
|
||||||
@@ -41,7 +42,7 @@ end
|
|||||||
---@field self SweepGroup
|
---@field self SweepGroup
|
||||||
|
|
||||||
---@param params SetTaskParams
|
---@param params SetTaskParams
|
||||||
local setMissionDelayedTask = function(params, time)
|
local setMissionDelayedTask = function(params, _)
|
||||||
params.self:SetMissionPrivate(params.task)
|
params.self:SetMissionPrivate(params.task)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -50,8 +51,6 @@ function SweepGroup:SendToZone(zone, targetZoneID, airbase)
|
|||||||
|
|
||||||
self._currentTargetZoneID = targetZoneID
|
self._currentTargetZoneID = targetZoneID
|
||||||
|
|
||||||
local group = Group.getByName(self._groupName)
|
|
||||||
|
|
||||||
local mission = SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
local mission = SWEEP.getAsMissionFromAirbase(self._groupName, airbase, zone, self._config)
|
||||||
if mission then
|
if mission then
|
||||||
---@type SetTaskParams
|
---@type SetTaskParams
|
||||||
@@ -82,13 +81,13 @@ function SweepGroup:InitWithName(groupName)
|
|||||||
|
|
||||||
local subsplit = Util.split_string(configPart, "|")
|
local subsplit = Util.split_string(configPart, "|")
|
||||||
if subsplit then
|
if subsplit then
|
||||||
for key, value in pairs(subsplit) do
|
for _, value in pairs(subsplit) do
|
||||||
local keySplit = Util.split_string(value, "]")
|
local keySplit = Util.split_string(value, "]")
|
||||||
local targetZone = keySplit[2]
|
local targetZone = keySplit[2]
|
||||||
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
local allActives = string.sub(keySplit[1], 2, #keySplit[1])
|
||||||
local commaSeperated = Util.split_string(allActives, ",")
|
local commaSeperated = Util.split_string(allActives, ",")
|
||||||
for _, value in pairs(commaSeperated) do
|
for _, childValue in pairs(commaSeperated) do
|
||||||
local dashSeperated = Util.split_string(value, "-")
|
local dashSeperated = Util.split_string(childValue, "-")
|
||||||
if Util.tableLength(dashSeperated) > 1 then
|
if Util.tableLength(dashSeperated) > 1 then
|
||||||
local from = tonumber(dashSeperated[1])
|
local from = tonumber(dashSeperated[1])
|
||||||
local till = tonumber(dashSeperated[2])
|
local till = tonumber(dashSeperated[2])
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ 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)
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ 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
|
||||||
@@ -32,18 +34,19 @@ 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
|
||||||
end
|
end
|
||||||
timer.scheduleFunction(updateDetected, self, timer.getTime() + 130)
|
timer.scheduleFunction(updateDetected, self, timer.getTime() + 130)
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
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
|
||||||
@@ -57,7 +60,8 @@ function DetectionManager:IsUnitDetectedBy(unitName, coalitionSide)
|
|||||||
return timer.getTime() - self._detectedUnits[coalitionString][unitName] < 20
|
return timer.getTime() - self._detectedUnits[coalitionString][unitName] < 20
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return Array<string>
|
---@param coalitionSide CoalitionSide
|
||||||
|
---@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
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ end
|
|||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param weapon Weapon
|
---@param weapon Weapon
|
||||||
function RunwayBombingTracker:OnWeaponFired(unit, weapon, target)
|
function RunwayBombingTracker:OnWeaponFired(_, weapon, _)
|
||||||
|
|
||||||
if weapon == nil then
|
if weapon == nil then
|
||||||
return
|
return
|
||||||
@@ -56,7 +56,9 @@ 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
|
||||||
@@ -83,11 +85,7 @@ function RunwayBombingTracker.trackWeaponTask(weaponTrackingArgs, time)
|
|||||||
x = pos.x + velocity.x * nextInterval,
|
x = pos.x + velocity.x * nextInterval,
|
||||||
y = pos.z + velocity.z * nextInterval
|
y = pos.z + velocity.z * nextInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
self:OnWeaponImpact(weapon:getDesc(), impactPoint)
|
self:OnWeaponImpact(weapon:getDesc(), impactPoint)
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -106,11 +104,10 @@ function RunwayBombingTracker:OnWeaponImpact(weaponDesc, impactPoint)
|
|||||||
|
|
||||||
self._logger:debug("RunwayBombingTracker:OnWeaponImpact")
|
self._logger:debug("RunwayBombingTracker:OnWeaponImpact")
|
||||||
|
|
||||||
local warhead = weaponDesc.warhead
|
local warhead = weaponDesc.warhead --[[@as table]]
|
||||||
local explosiveMass = warhead.explosiveMass or warhead.shapedExplosiveMass
|
local explosiveMass = (warhead.explosiveMass or warhead.shapedExplosiveMass) --[[@as number]]
|
||||||
|
|
||||||
for runway, 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,6 +7,7 @@ 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",
|
||||||
}
|
}
|
||||||
@@ -33,9 +34,6 @@ local function GetCAPPointFromTriggerZone(airBase, capZone)
|
|||||||
local furthestA = nil
|
local furthestA = nil
|
||||||
local furthestB = nil
|
local furthestB = nil
|
||||||
|
|
||||||
local furthestFromBase = nil
|
|
||||||
local furthestFromBaseDistance = 0
|
|
||||||
|
|
||||||
local furthestDistance = 0
|
local furthestDistance = 0
|
||||||
|
|
||||||
for indexA, pointA in ipairs(capZone.verts) do
|
for indexA, pointA in ipairs(capZone.verts) do
|
||||||
@@ -56,7 +54,10 @@ 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
|
||||||
@@ -87,6 +88,7 @@ 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 }
|
||||||
@@ -128,6 +130,7 @@ 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),
|
||||||
@@ -155,6 +158,7 @@ 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),
|
||||||
@@ -181,6 +185,7 @@ 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,6 +11,7 @@ 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()
|
||||||
@@ -92,7 +93,7 @@ end
|
|||||||
---@param currentPoint Vec2
|
---@param currentPoint Vec2
|
||||||
---@param targetPosition Vec2
|
---@param targetPosition Vec2
|
||||||
---@param targetUnit Unit
|
---@param targetUnit Unit
|
||||||
---@param airbase any
|
---@param airbase Airbase
|
||||||
---@param config any
|
---@param config any
|
||||||
---@param speed number?
|
---@param speed number?
|
||||||
---@param alt number?
|
---@param alt number?
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ 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",
|
||||||
@@ -113,6 +114,7 @@ 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)
|
||||||
|
|
||||||
@@ -147,6 +149,7 @@ 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 {
|
||||||
@@ -170,6 +173,8 @@ 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,6 +7,7 @@ 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",
|
||||||
}
|
}
|
||||||
@@ -49,7 +50,9 @@ 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
|
||||||
@@ -80,6 +83,7 @@ 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 }
|
||||||
@@ -121,6 +125,7 @@ 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,6 +21,10 @@ 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
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
local briefingMessageTime = nil
|
|
||||||
|
|
||||||
---@class GlobalConfig
|
---@class GlobalConfig
|
||||||
---@field private _briefingTime number
|
---@field private _briefingTime number
|
||||||
---@field private _debugEnabled boolean
|
---@field private _debugEnabled boolean
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local Util = require("classes.util.Util")
|
|
||||||
local StageRepository = require("classes.stageClasses.StageRepository")
|
local StageRepository = require("classes.stageClasses.StageRepository")
|
||||||
|
|
||||||
---@class DebugMenu
|
---@class DebugMenu
|
||||||
@@ -22,7 +21,7 @@ function DebugMenu:RegisterMenus()
|
|||||||
missionCommands.addSubMenu(menuName, {})
|
missionCommands.addSubMenu(menuName, {})
|
||||||
|
|
||||||
local refresh = function(params)
|
local refresh = function(params)
|
||||||
local selfA = params.self
|
local selfA = params.self --[[@as DebugMenu]]
|
||||||
selfA:RefreshMenu()
|
selfA:RefreshMenu()
|
||||||
end
|
end
|
||||||
missionCommands.addCommand("Refresh Menu", debugMenuPath, refresh, { self = self })
|
missionCommands.addCommand("Refresh Menu", debugMenuPath, refresh, { self = self })
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
do -- mission aliases
|
|
||||||
|
|
||||||
--- @alias LogLevel
|
|
||||||
--- | "DEBUG"
|
|
||||||
--- | "INFO"
|
|
||||||
--- | "WARN"
|
|
||||||
--- | "ERROR"
|
|
||||||
--- | "NONE"
|
|
||||||
|
|
||||||
---@class Array<T>: { [integer]: T }
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
---@class KeyValuePair
|
|
||||||
---@field key string
|
|
||||||
---@field value any
|
|
||||||
@@ -4,37 +4,43 @@ local MissionEditorWarning = require("classes.util.MissionEditorWarnings")
|
|||||||
local RouteUtil = require("classes.spearhead_routeutil")
|
local RouteUtil = require("classes.spearhead_routeutil")
|
||||||
local SpearheadEvents = require("classes.spearhead_events")
|
local SpearheadEvents = require("classes.spearhead_events")
|
||||||
|
|
||||||
---@class FleetGroup
|
---@class FleetGroup : OnStageChangedListener
|
||||||
|
---@field private fleetGroupName string
|
||||||
|
---@field private logger Logger
|
||||||
|
---@field private fleetNameIdentifier string
|
||||||
|
---@field private targetZonePerStage table<string, string>
|
||||||
|
---@field private currentTargetZone string
|
||||||
|
---@field private pointsPerZone table<string, {pointA: Vec3, pointB: Vec3}>
|
||||||
local FleetGroup = {}
|
local FleetGroup = {}
|
||||||
|
FleetGroup.__index = FleetGroup
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param fleetGroupName string
|
---@param fleetGroupName string
|
||||||
---@param database Database
|
---@param database Database
|
||||||
---@param logger Logger
|
---@param logger Logger
|
||||||
---@return nil
|
---@return FleetGroup?
|
||||||
function FleetGroup:new(fleetGroupName, database, logger)
|
function FleetGroup.new(fleetGroupName, database, logger)
|
||||||
local o = {}
|
|
||||||
|
|
||||||
setmetatable(o, { __index = self })
|
local self = setmetatable({}, FleetGroup)
|
||||||
|
|
||||||
o.fleetGroupName = fleetGroupName
|
self.fleetGroupName = fleetGroupName
|
||||||
o.logger = logger
|
self.logger = logger
|
||||||
|
|
||||||
local split_name = Util.split_string(fleetGroupName, "_")
|
local split_name = Util.split_string(fleetGroupName, "_")
|
||||||
if Util.tableLength(split_name) < 2 then
|
if Util.tableLength(split_name) < 2 then
|
||||||
MissionEditorWarning.Add("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>")
|
MissionEditorWarning.Add("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_<fleetname>")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
o.fleetNameIdentifier = split_name[2]
|
self.fleetNameIdentifier = split_name[2]
|
||||||
|
|
||||||
o.targetZonePerStage = {}
|
self.targetZonePerStage = {}
|
||||||
o.currentTargetZone = nil
|
self.currentTargetZone = nil
|
||||||
o.pointsPerZone = {}
|
self.pointsPerZone = {}
|
||||||
|
|
||||||
do --INIT
|
do --INIT
|
||||||
local carrierRouteZones = database:getCarrierRouteZones()
|
local carrierRouteZones = database:getCarrierRouteZones()
|
||||||
for _, zoneName in pairs(carrierRouteZones) do
|
for _, zoneName in pairs(carrierRouteZones) do
|
||||||
if Util.strContains(string.lower(zoneName), "_".. string.lower(o.fleetNameIdentifier) .. "_" ) == true then
|
if Util.strContains(string.lower(zoneName), "_".. string.lower(self.fleetNameIdentifier) .. "_" ) == true then
|
||||||
local zone = DcsUtil.getZoneByName(zoneName)
|
local zone = DcsUtil.getZoneByName(zoneName)
|
||||||
if zone and zone.zone_type == DcsUtil.ZoneType.Polygon then
|
if zone and zone.zone_type == DcsUtil.ZoneType.Polygon then
|
||||||
local split_string = Util.split_string(zoneName, "_")
|
local split_string = Util.split_string(zoneName, "_")
|
||||||
@@ -43,18 +49,18 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
|||||||
"CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName)
|
"CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName)
|
||||||
else
|
else
|
||||||
|
|
||||||
---@param zone SpearheadTriggerZone
|
---@param zoneA SpearheadTriggerZone
|
||||||
---@return Vec2, Vec2
|
---@return Vec2, Vec2
|
||||||
local function GetTwoFurthestPoints(zone)
|
local function GetTwoFurthestPoints(zoneA)
|
||||||
|
|
||||||
local biggest = nil
|
local biggest = nil
|
||||||
local biggestA = zone.verts[1]
|
local biggestA = zoneA.verts[1]
|
||||||
local biggestB = zone.verts[2]
|
local biggestB = zoneA.verts[2]
|
||||||
|
|
||||||
for i = 1, 3 do
|
for i = 1, 3 do
|
||||||
for ii = i + 1, 4 do
|
for ii = i + 1, 4 do
|
||||||
local a = zone.verts[i]
|
local a = zoneA.verts[i]
|
||||||
local b = zone.verts[ii]
|
local b = zoneA.verts[ii]
|
||||||
local dist = Util.VectorDistance2d(a, b)
|
local dist = Util.VectorDistance2d(a, b)
|
||||||
|
|
||||||
if biggest == nil or dist > biggest then
|
if biggest == nil or dist > biggest then
|
||||||
@@ -100,9 +106,15 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
|||||||
local first, second = getMinMaxStage(split_string[3])
|
local first, second = getMinMaxStage(split_string[3])
|
||||||
if first ~= nil and second ~= nil then
|
if first ~= nil and second ~= nil then
|
||||||
for i = first, second do
|
for i = first, second do
|
||||||
o.targetZonePerStage[tostring(i)] = zoneName
|
self.targetZonePerStage[tostring(i)] = zoneName
|
||||||
end
|
end
|
||||||
o.pointsPerZone[zoneName] = { pointA = { x = pointA.x, z = pointA.y, y = 0 }, pointB = { x = pointB.x, z = pointB.y, y = 0} }
|
---@type {pointA: Vec3, pointB: Vec3}
|
||||||
|
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
|
||||||
@@ -114,20 +126,24 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local SetTaskAsync = function(input, time)
|
SpearheadEvents.AddStageNumberChangedListener(self)
|
||||||
local targetZone = input.targetZone
|
return self
|
||||||
local task = input.task
|
end
|
||||||
local groupName = input.groupName
|
|
||||||
local logger = input.logger
|
local SetTaskAsync = function(input, _)
|
||||||
|
local targetZone = input.targetZone --[[@as string]]
|
||||||
|
local task = input.task --[[@as table]]
|
||||||
|
local groupName = input.groupName --[[@as string]]
|
||||||
|
local l_logger = input.logger --[[@as Logger]]
|
||||||
|
|
||||||
local group = Group.getByName(groupName)
|
local group = Group.getByName(groupName)
|
||||||
if group then
|
if group then
|
||||||
logger:info("Sending " .. groupName .. " to " .. targetZone)
|
l_logger:info("Sending " .. groupName .. " to " .. targetZone)
|
||||||
group:getController():setTask(task)
|
group:getController():setTask(task)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
o.OnStageNumberChanged = function(self, number, laneIdentifier)
|
function FleetGroup:OnStageNumberChanged(number, laneIdentifier)
|
||||||
-- only react on "main" lane changes, ignore other lanes for now
|
-- only react on "main" lane changes, ignore other lanes for now
|
||||||
if laneIdentifier ~= nil then return end
|
if laneIdentifier ~= nil then return end
|
||||||
local targetZone = self.targetZonePerStage[tostring(number)]
|
local targetZone = self.targetZonePerStage[tostring(number)]
|
||||||
@@ -136,10 +152,6 @@ function FleetGroup:new(fleetGroupName, database, logger)
|
|||||||
local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
|
local task = RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB)
|
||||||
timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5)
|
timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
SpearheadEvents.AddStageNumberChangedListener(o)
|
|
||||||
return o
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return FleetGroup
|
return FleetGroup
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ GlobalFleetManager.start = function(database)
|
|||||||
for _, groupName in pairs(all_groups) do
|
for _, groupName in pairs(all_groups) do
|
||||||
if Util.startsWith(string.lower(groupName), "carriergroup" ) == true then
|
if Util.startsWith(string.lower(groupName), "carriergroup" ) == true then
|
||||||
logger:info("Registering " .. groupName .. " as a managed fleet")
|
logger:info("Registering " .. groupName .. " as a managed fleet")
|
||||||
local carrierGroup = FleetGroup:new(groupName, database, logger)
|
local carrierGroup = FleetGroup.new(groupName, database, logger)
|
||||||
table.insert(fleetGroups, carrierGroup)
|
table.insert(fleetGroups, carrierGroup)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,24 +15,45 @@ MizGroupsManager._groupNames = {}
|
|||||||
MizGroupsManager._spawnTemplateData = {}
|
MizGroupsManager._spawnTemplateData = {}
|
||||||
|
|
||||||
do --init
|
do --init
|
||||||
for coalition_name, coalition_data in pairs(env.mission.coalition) do
|
|
||||||
local coalition_nr = DcsUtil.stringToCoalition(coalition_name)
|
---@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_index, country_data in pairs(coalition_data.country) do
|
for _, country_data in pairs(coalition_data.country) do
|
||||||
for category_name, categorydata in pairs(country_data) do
|
for _, category_name in pairs(DcsUtil.getAllGroupCategoryNames()) do
|
||||||
local category_id = DcsUtil.stringToGroupCategory(category_name)
|
local category_id = DcsUtil.stringToGroupCategory(category_name)
|
||||||
if category_id ~= nil and type(categorydata) == "table" and categorydata.group ~= nil and type(categorydata.group) == "table" then
|
local groups_data = getGroupsData(country_data, category_name)
|
||||||
for group_index, group in pairs(categorydata.group) do
|
|
||||||
local name = group.name
|
if category_id ~= nil and type(groups_data) == "table" and groups_data.group ~= nil and type(groups_data.group) == "table" then
|
||||||
|
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]
|
local unit = group.units[1] --[[@as table]]
|
||||||
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
|
name = unit.name --[[@as string]]
|
||||||
else
|
else
|
||||||
env.error("Group " .. name .. " has no units, skipping it.")
|
env.error("Group " .. name .. " has no units, skipping it.")
|
||||||
skippable = true
|
skippable = true
|
||||||
@@ -72,6 +93,7 @@ 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
|
||||||
@@ -44,7 +44,7 @@ function SpawnManager:SpawnGroup(groupName, overrides, isGroupPersistant)
|
|||||||
if spawnData.isStatic == true then
|
if spawnData.isStatic == true then
|
||||||
return self:SpawnStaticInternal(groupName, spawnData, overrides, isGroupPersistant), true
|
return self:SpawnStaticInternal(groupName, spawnData, overrides, isGroupPersistant), true
|
||||||
else
|
else
|
||||||
return self:SpawnGroupInternal(groupName, spawnData, overrides, isGroupPersistant), false
|
return self:SpawnGroupInternal(spawnData, overrides, isGroupPersistant), false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -103,20 +103,20 @@ function SpawnManager:OnUnitLost(object)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param groupName string
|
||||||
function SpawnManager:SpawnCorpsesOnly(groupName)
|
function SpawnManager:SpawnCorpsesOnly(groupName)
|
||||||
|
if groupName == nil then return end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do --- privates
|
do --- privates
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
---@param groupName string
|
|
||||||
---@param spawnData SpawnData
|
---@param spawnData SpawnData
|
||||||
---@param override SpawnOverrides?
|
---@param override SpawnOverrides?
|
||||||
---@param isPersistent boolean?
|
---@param isPersistent boolean?
|
||||||
---@return Group|nil
|
---@return Group|nil
|
||||||
function SpawnManager:SpawnGroupInternal(groupName, spawnData, override, isPersistent)
|
function SpawnManager:SpawnGroupInternal(spawnData, override, isPersistent)
|
||||||
|
|
||||||
if not spawnData then return end
|
if not spawnData then return end
|
||||||
|
|
||||||
local country = spawnData.country
|
local country = spawnData.country
|
||||||
@@ -125,37 +125,31 @@ 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
|
||||||
for _, unit in pairs(spawnTemplate["units"]) do
|
local units = spawnTemplate["units"] --[[@as Array<table>]]
|
||||||
local name = unit["name"]
|
for _, unit in pairs(units) do
|
||||||
|
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
|
||||||
unit["payload"]["pylons"] = {}
|
local payload = unit["payload"] --[[@as table]]
|
||||||
|
payload["pylons"] = {} --[[@as table]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if unit["parking"] then
|
if unit["parking"] then
|
||||||
unit["parking_landing"] = unit["parking"]
|
unit["parking_landing"] = unit["parking"] --[[@as number]]
|
||||||
end
|
end
|
||||||
|
|
||||||
if unit["parking_id"] then
|
if unit["parking_id"] then
|
||||||
unit["parking_landing_id"] = unit["parking_id"]
|
unit["parking_landing_id"] = unit["parking_id"] --[[@as number]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -169,7 +163,6 @@ 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
|
||||||
@@ -181,7 +174,6 @@ do --- privates
|
|||||||
return group
|
return group
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -211,9 +203,11 @@ 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
|
||||||
spawnTemplate["units"][1]["x"] = persistentState.pos.x
|
local units = spawnTemplate["units"] --[[@as Array<table>]]
|
||||||
spawnTemplate["units"][1]["y"] = persistentState.pos.z
|
local firstUnit = units[1] --[[@as table]]
|
||||||
spawnTemplate["units"][1]["heading"] = persistentState.heading or 0
|
firstUnit["x"] = persistentState.pos.x --[[@as number]]
|
||||||
|
firstUnit["y"] = persistentState.pos.z --[[@as number]]
|
||||||
|
firstUnit["heading"] = persistentState.heading or 0 --[[@as number]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ do
|
|||||||
logger:info("Wrote persistence data to file")
|
logger:info("Wrote persistence data to file")
|
||||||
end
|
end
|
||||||
|
|
||||||
local UpdateContinuous = function(null, time)
|
local UpdateContinuous = function(_, time)
|
||||||
env.info("[Spearhead][Persistence] Checking up on persistence state...")
|
env.info("[Spearhead][Persistence] Checking up on persistence state...")
|
||||||
if Persistence._updateRequired == true then
|
if Persistence._updateRequired == true then
|
||||||
local status, result = pcall(writeToFile)
|
local status, result = pcall(writeToFile)
|
||||||
@@ -135,13 +135,15 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local warnForNonPersistenceContinous = function(null, time)
|
local warnForNonPersistenceContinous = function(_, time)
|
||||||
trigger.action.outText("Persistence was enabeld, however, io and lfs are not available and no persistence will be done. Make sure to either disable persistence or fix the issues before continuing.", 10)
|
trigger.action.outText("Persistence was enabeld, however, io and lfs are not available and no persistence will be done. Make sure to either disable persistence or fix the issues before continuing.", 10)
|
||||||
return time + 9
|
return time + 9
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param dir string @BaseDirectory
|
---@param dir string @BaseDirectory
|
||||||
---@return string
|
---@param startsWith string
|
||||||
|
---@param default string?
|
||||||
|
---@return string?
|
||||||
local getLastFileOrDefault = function(dir, startsWith, default)
|
local getLastFileOrDefault = function(dir, startsWith, default)
|
||||||
|
|
||||||
local latestFile, lastNumber = default, 0
|
local latestFile, lastNumber = default, 0
|
||||||
@@ -181,11 +183,14 @@ 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 and #split < 3 then
|
if not split or #split < 3 then
|
||||||
|
split = split or {}
|
||||||
split[#split+1] = "0"
|
split[#split+1] = "0"
|
||||||
split[#split+1] = "spearhead"
|
split[#split+1] = "spearhead"
|
||||||
end
|
end
|
||||||
@@ -198,7 +203,10 @@ do
|
|||||||
fileName = table.concat(split, ".")
|
fileName = table.concat(split, ".")
|
||||||
end
|
end
|
||||||
|
|
||||||
if SpearheadConfig.Persistence.directory ~= nil then
|
if SpearheadConfig.Persistence.directory 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
|
||||||
@@ -208,6 +216,10 @@ 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, ".")
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ function Database.New(Logger)
|
|||||||
self._logger:debug("Initiating tables")
|
self._logger:debug("Initiating tables")
|
||||||
|
|
||||||
do -- INIT ZONE TABLES
|
do -- INIT ZONE TABLES
|
||||||
for zone_ind, zone_data in pairs(DcsUtil.__trigger_zones) do
|
for _, zone_data in pairs(DcsUtil.__trigger_zones) do
|
||||||
local zone_name = zone_data.name
|
local zone_name = zone_data.name
|
||||||
|
|
||||||
---@type Vec2
|
---@type Vec2
|
||||||
@@ -209,13 +209,15 @@ function Database.New(Logger)
|
|||||||
self._logger:debug("initiated zone tables, continuing with descriptions")
|
self._logger:debug("initiated zone tables, continuing with descriptions")
|
||||||
do --load markers
|
do --load markers
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startsWith(string.lower(layer_object.name), "buildable", true) == true then
|
if Util.startsWith(string.lower(layer_object.name), "buildable", true) == true then
|
||||||
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
|
local airbaseData = self:getAirbaseDataForDrawLayer(layer_object)
|
||||||
if airbaseData then
|
if airbaseData then
|
||||||
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
|
||||||
@@ -225,13 +227,14 @@ 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
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startsWith(layer_object.name, "drawing_", true) then
|
if Util.startsWith(layer_object.name, "drawing_", true) then
|
||||||
local object = layer_object --[[@as DrawingObject]]
|
local object = layer_object --[[@as DrawingObject]]
|
||||||
local stageDrawing = StageDrawing.New(object)
|
local stageDrawing = StageDrawing.New(object)
|
||||||
@@ -257,13 +260,15 @@ function Database.New(Logger)
|
|||||||
|
|
||||||
-- Find and add Briefing
|
-- Find and add Briefing
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
if Util.startsWith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
if Util.startsWith(string.lower(layer_object.name), "stagebriefing_", true) == true then
|
||||||
local zone = DcsUtil.getZoneByName(stageZoneName)
|
local zone = DcsUtil.getZoneByName(stageZoneName)
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
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
|
||||||
@@ -274,6 +279,7 @@ 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
|
||||||
@@ -340,14 +346,14 @@ function Database.New(Logger)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- fill missions
|
-- fill missions
|
||||||
for key, missionZone in pairs(self._tables.MissionZones) do
|
for _, missionZone in pairs(self._tables.MissionZones) do
|
||||||
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||||
table.insert(stageData.MissionZones, missionZone)
|
table.insert(stageData.MissionZones, missionZone)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- fill random missions
|
-- fill random missions
|
||||||
for key, missionZone in pairs(self._tables.RandomMissionZones) do
|
for _, missionZone in pairs(self._tables.RandomMissionZones) do
|
||||||
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
if DcsUtil.isZoneInZone(missionZone, stageZoneName) == true then
|
||||||
table.insert(stageData.RandomMissionZones, missionZone)
|
table.insert(stageData.RandomMissionZones, missionZone)
|
||||||
end
|
end
|
||||||
@@ -469,6 +475,7 @@ 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()
|
||||||
@@ -621,13 +628,14 @@ function Database:loadBlueSamUnits()
|
|||||||
samData.buildingKilos = number
|
samData.buildingKilos = number
|
||||||
|
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
|
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if layer_object.primitiveType == "TextBox" and 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
|
||||||
@@ -729,13 +737,14 @@ function Database:LoadZoneData(missionZoneName)
|
|||||||
|
|
||||||
---Adds Briefings
|
---Adds Briefings
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
|
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if layer_object.primitiveType == "TextBox" and 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
|
||||||
@@ -785,12 +794,13 @@ function Database:loadFarpData()
|
|||||||
|
|
||||||
-- check briefings
|
-- check briefings
|
||||||
if env.mission.drawings and env.mission.drawings.layers then
|
if env.mission.drawings and env.mission.drawings.layers then
|
||||||
for i, layer in pairs(env.mission.drawings.layers) do
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
if string.lower(layer.name) == "author" then
|
if string.lower(layer.name) == "author" then
|
||||||
for key, layer_object in pairs(layer.objects) do
|
for _, layer_object in pairs(layer.objects) do
|
||||||
|
|
||||||
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
local vec2 = { x = layer_object.mapX, y = layer_object.mapY }
|
||||||
if triggerZone and Util.is2dPointInZone(vec2, triggerZone) then
|
if layer_object.primitiveType == "TextBox" and 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
|
||||||
@@ -805,8 +815,6 @@ function Database:loadFarpData()
|
|||||||
else
|
else
|
||||||
MissionEditorWarnings.Add("Buildable number for " .. farpZone .. " is invalid.")
|
MissionEditorWarnings.Add("Buildable number for " .. farpZone .. " is invalid.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -961,6 +969,7 @@ 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]
|
||||||
@@ -968,6 +977,7 @@ 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]
|
||||||
@@ -975,13 +985,14 @@ 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 table result airbase Names
|
---@return Array<string> 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
|
||||||
@@ -995,6 +1006,7 @@ 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]
|
||||||
@@ -1010,6 +1022,7 @@ 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,7 +32,9 @@ 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)
|
||||||
@@ -47,6 +49,7 @@ 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)
|
||||||
@@ -65,7 +68,7 @@ do
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
for _, callable in pairs(OnStageNumberChangedListeners) do
|
for _, callable in pairs(OnStageNumberChangedListeners) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnStageNumberChanged(newStageNumber, laneIdentifier)
|
callable:OnStageNumberChanged(newStageNumber, laneIdentifier)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -74,14 +77,14 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, callable in pairs(OnStageNumberChangedHandlers) do
|
for _, callable in pairs(OnStageNumberChangedHandlers) do
|
||||||
local succ, err = pcall(callable, newStageNumber, laneIdentifier)
|
local _, err = pcall(callable, newStageNumber, laneIdentifier)
|
||||||
if err then
|
if err then
|
||||||
logError(err)
|
logError(err)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, callable in pairs(OnStageNumberChangeCompleteListeners) do
|
for _, callable in pairs(OnStageNumberChangeCompleteListeners) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnStageNumberChangeComplete(newStageNumber, laneIdentifier)
|
callable:OnStageNumberChangeComplete(newStageNumber, laneIdentifier)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -110,9 +113,12 @@ 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 succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnWeaponFired(unit, weapon, target)
|
callable:OnWeaponFired(unit, weapon, target)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -122,11 +128,14 @@ 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 table table with function OnUnitLanded(self, initiatorUnit, airbase)
|
---@param landListener OnLandEventListener 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")
|
||||||
@@ -162,6 +171,11 @@ 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
|
||||||
@@ -186,7 +200,7 @@ do
|
|||||||
if groupName ~= nil then
|
if groupName ~= nil then
|
||||||
if OnGroupRTBListeners[groupName] then
|
if OnGroupRTBListeners[groupName] then
|
||||||
for _, callable in pairs(OnGroupRTBListeners[groupName]) do
|
for _, callable in pairs(OnGroupRTBListeners[groupName]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnGroupRTB(groupName)
|
callable:OnGroupRTB(groupName)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -197,11 +211,15 @@ 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 table object with OnGroupRTBInTen(self, groupName)
|
---@param handlingObject OnGroupRTBInTenListener 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")
|
||||||
@@ -221,7 +239,7 @@ do
|
|||||||
if groupName ~= nil then
|
if groupName ~= nil then
|
||||||
if OnGroupRTBInTenListeners[groupName] then
|
if OnGroupRTBInTenListeners[groupName] then
|
||||||
for _, callable in pairs(OnGroupRTBInTenListeners[groupName]) do
|
for _, callable in pairs(OnGroupRTBInTenListeners[groupName]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnGroupRTBInTen(groupName)
|
callable:OnGroupRTBInTen(groupName)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -234,10 +252,17 @@ 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")
|
||||||
@@ -257,7 +282,7 @@ do
|
|||||||
if groupName ~= nil then
|
if groupName ~= nil then
|
||||||
if OnGroupOnStationListeners[groupName] then
|
if OnGroupOnStationListeners[groupName] then
|
||||||
for _, callable in pairs(OnGroupOnStationListeners[groupName]) do
|
for _, callable in pairs(OnGroupOnStationListeners[groupName]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnGroupOnStation(groupName)
|
callable:OnGroupOnStation(groupName)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -270,15 +295,18 @@ 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 table object with OnPlayerEntersUnit(self, unit)
|
---@param listener OnPlayerEnterUnitListener 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
|
||||||
|
|
||||||
@@ -286,7 +314,7 @@ do
|
|||||||
if unit ~= nil then
|
if unit ~= nil then
|
||||||
if playerEnterUnitListeners then
|
if playerEnterUnitListeners then
|
||||||
for _, callable in pairs(playerEnterUnitListeners) do
|
for _, callable in pairs(playerEnterUnitListeners) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnPlayerEntersUnit(unit)
|
callable:OnPlayerEntersUnit(unit)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -315,13 +343,13 @@ 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
|
local unit = event.initiator --[[@as Unit]]
|
||||||
local airbase = event.place
|
local airbase = event.place --[[@as Airbase]]
|
||||||
if unit ~= nil then
|
if unit ~= nil then
|
||||||
local name = unit:getName()
|
local name = unit:getName()
|
||||||
if onLandEventListeners[name] then
|
if onLandEventListeners[name] then
|
||||||
for _, callable in pairs(onLandEventListeners[name]) do
|
for _, callable in pairs(onLandEventListeners[name]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnUnitLanded(unit, airbase)
|
callable:OnUnitLanded(unit, airbase)
|
||||||
end)
|
end)
|
||||||
if err then
|
if err then
|
||||||
@@ -336,7 +364,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
|
local object = event.initiator --[[@as Unit]]
|
||||||
|
|
||||||
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())
|
||||||
@@ -344,7 +372,7 @@ do
|
|||||||
|
|
||||||
if object and object.getName and OnUnitLostListeners[object:getName()] then
|
if object and object.getName and OnUnitLostListeners[object:getName()] then
|
||||||
for _, callable in pairs(OnUnitLostListeners[object:getName()]) do
|
for _, callable in pairs(OnUnitLostListeners[object:getName()]) do
|
||||||
local succ, err = pcall(function()
|
local _, err = pcall(function()
|
||||||
callable:OnUnitLost(object)
|
callable:OnUnitLost(object)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -355,15 +383,11 @@ 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
|
local shooter = event.initiator --[[@as Unit]]
|
||||||
local weapon = event.weapon
|
local weapon = event.weapon --[[@as Weapon]]
|
||||||
local target = event.target
|
local target = event.target --[[@as Unit?]]
|
||||||
triggerWeaponFired(shooter, weapon, target)
|
triggerWeaponFired(shooter, weapon, target)
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -372,28 +396,32 @@ do
|
|||||||
Persistence.UpdateNow()
|
Persistence.UpdateNow()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@type table<string, boolean>
|
||||||
local AI_GROUPS = {}
|
local AI_GROUPS = {}
|
||||||
|
|
||||||
local function CheckAndTriggerSpawnAsync(unit, time)
|
---@param unit Unit
|
||||||
|
---@param _ any
|
||||||
local function isPlayer(unit)
|
local function CheckAndTriggerSpawnAsync(unit, _)
|
||||||
if unit == nil then return false, "unit is nil" end
|
---@param checkUnit Unit
|
||||||
if unit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end
|
---@return boolean, string?
|
||||||
if Object.getCategory(unit) ~= Object.Category.UNIT then
|
local function isPlayer(checkUnit)
|
||||||
|
if checkUnit == nil then return false, "unit is nil" end
|
||||||
|
if checkUnit.getGroup == nil then return false, 'no get group function in unit object, most likely static' end
|
||||||
|
if Object.getCategory(checkUnit) ~= Object.Category.UNIT then
|
||||||
return false, "object is not a unit"
|
return false, "object is not a unit"
|
||||||
end
|
end
|
||||||
|
|
||||||
if unit:isExist() ~= true then return false, "unit does not exist" end
|
if checkUnit:isExist() ~= true then return false, "unit does not exist" end
|
||||||
local group = unit:getGroup()
|
local group = checkUnit:getGroup()
|
||||||
if group ~= nil then
|
if group ~= nil then
|
||||||
if AI_GROUPS[group:getName()] == true then
|
if AI_GROUPS[group:getName()] == true then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local players = DcsUtil.getAllPlayerUnits()
|
local players = DcsUtil.getAllPlayerUnits()
|
||||||
local unitName = unit:getName()
|
local unitName = checkUnit:getName()
|
||||||
for i, unit in pairs(players) do
|
for _, playerUnit in pairs(players) do
|
||||||
if unit:getName() == unitName then
|
if playerUnit:getName() == unitName then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -403,11 +431,8 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
if isPlayer(unit) == true then
|
if isPlayer(unit) == true then
|
||||||
local groupId = unit:getGroup():getID()
|
|
||||||
SpearheadEvents.TriggerPlayerEntersUnit(unit)
|
SpearheadEvents.TriggerPlayerEntersUnit(unit)
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if event.id == world.event.S_EVENT_BIRTH then
|
if event.id == world.event.S_EVENT_BIRTH then
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ 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",
|
||||||
}
|
}
|
||||||
@@ -53,8 +54,9 @@ do --setup route util
|
|||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param groupName string
|
---@param groupName string
|
||||||
---@param position table { x, y}
|
---@param position Vec3
|
||||||
---@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
|
||||||
@@ -181,7 +183,7 @@ do --setup route util
|
|||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param position table { x, y}
|
---@param position Vec3
|
||||||
---@param altitude number
|
---@param altitude number
|
||||||
---@param speed number
|
---@param speed number
|
||||||
---@param childTasks table
|
---@param childTasks table
|
||||||
@@ -210,7 +212,8 @@ 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 table { x, z }
|
---@param capPoint Vec3
|
||||||
|
---@param racetrackSecondPoint Vec3?
|
||||||
---@param altitude number
|
---@param altitude number
|
||||||
---@param speed number
|
---@param speed number
|
||||||
---@param durationOnStation number
|
---@param durationOnStation number
|
||||||
@@ -258,7 +261,8 @@ 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()
|
||||||
local points = {}
|
---@type Array<table>
|
||||||
|
local points
|
||||||
if racetrackSecondPoint == nil then
|
if racetrackSecondPoint == nil then
|
||||||
points = {
|
points = {
|
||||||
[1] = FlyToPointTask(capPoint, altitude, speed, additionalFlyOverTasks),
|
[1] = FlyToPointTask(capPoint, altitude, speed, additionalFlyOverTasks),
|
||||||
@@ -304,6 +308,7 @@ 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
|
||||||
@@ -393,6 +398,9 @@ 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",
|
||||||
@@ -461,7 +469,7 @@ do --setup route util
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, ""
|
}, nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ local Events = require("classes.spearhead_events")
|
|||||||
local Util = require("classes.util.Util")
|
local Util = require("classes.util.Util")
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
local DcsUtil = require("classes.util.DcsUtil")
|
||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
|
||||||
local PersistenceConfig = require("classes.configuration.PersistenceConfig")
|
local PersistenceConfig = require("classes.configuration.PersistenceConfig")
|
||||||
local ExtraStage = require("classes.stageClasses.Stages.ExtraStage")
|
local ExtraStage = require("classes.stageClasses.Stages.ExtraStage")
|
||||||
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
|
local PrimaryStage = require("classes.stageClasses.Stages.PrimaryStage")
|
||||||
@@ -35,7 +34,6 @@ local singletonInstance = nil
|
|||||||
---@param spawnManager SpawnManager
|
---@param spawnManager SpawnManager
|
||||||
---@return GlobalStageManager
|
---@return GlobalStageManager
|
||||||
function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
||||||
|
|
||||||
if singletonInstance ~= nil then
|
if singletonInstance ~= nil then
|
||||||
return singletonInstance
|
return singletonInstance
|
||||||
end
|
end
|
||||||
@@ -52,7 +50,8 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
|||||||
|
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
if stageConfig.isAutoStages ~= true then
|
if stageConfig.isAutoStages ~= true then
|
||||||
logger:warn("Spearhead will not automatically progress stages due to the given settings. If you manually have implemented this, please ignore this message")
|
logger:warn(
|
||||||
|
"Spearhead will not automatically progress stages due to the given settings. If you manually have implemented this, please ignore this message")
|
||||||
end
|
end
|
||||||
|
|
||||||
Events.AddStageNumberChangedListener(self)
|
Events.AddStageNumberChangedListener(self)
|
||||||
@@ -81,12 +80,12 @@ function GlobalStageManager.new(database, stageConfig, logLevel, spawnManager)
|
|||||||
stage:AddStageCompleteListener(self)
|
stage:AddStageCompleteListener(self)
|
||||||
self._stageRepository:AddStage(stage)
|
self._stageRepository:AddStage(stage)
|
||||||
elseif parseResult.stageType == "WaitingStage" then
|
elseif parseResult.stageType == "WaitingStage" then
|
||||||
local waitingStage = WaitingStage.New(database, stageConfig, logger, initData, parseResult.waitingStageSeconds, spawnManager)
|
local waitingStage = WaitingStage.New(database, stageConfig, logger, initData,
|
||||||
|
parseResult.waitingStageSeconds, spawnManager)
|
||||||
waitingStage:AddStageCompleteListener(self)
|
waitingStage:AddStageCompleteListener(self)
|
||||||
self._stageRepository:AddStage(waitingStage)
|
self._stageRepository:AddStage(waitingStage)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
singletonInstance = self
|
singletonInstance = self
|
||||||
@@ -103,11 +102,11 @@ function GlobalStageManager:Start()
|
|||||||
|
|
||||||
local stageLanes = self._stageRepository:getAllStageLanes()
|
local stageLanes = self._stageRepository:getAllStageLanes()
|
||||||
for _, stageLane in pairs(stageLanes) do
|
for _, stageLane in pairs(stageLanes) do
|
||||||
|
|
||||||
local stageLaneIdentifier = stageLane:GetStageLaneIdentifier()
|
local stageLaneIdentifier = stageLane:GetStageLaneIdentifier()
|
||||||
local persistedStage = Persistence.GetActiveStage(stageLaneIdentifier)
|
local persistedStage = Persistence.GetActiveStage(stageLaneIdentifier)
|
||||||
if persistedStage then
|
if persistedStage then
|
||||||
self.logger:info("Loaded persisted stage " .. persistedStage .. " for lane " .. (stageLaneIdentifier or "default"))
|
self.logger:info("Loaded persisted stage " ..
|
||||||
|
persistedStage .. " for lane " .. (stageLaneIdentifier or "default"))
|
||||||
stageLane:SetActiveStageIndex(persistedStage)
|
stageLane:SetActiveStageIndex(persistedStage)
|
||||||
Events.PublishStageNumberChanged(persistedStage, stageLaneIdentifier)
|
Events.PublishStageNumberChanged(persistedStage, stageLaneIdentifier)
|
||||||
else
|
else
|
||||||
@@ -139,17 +138,16 @@ end
|
|||||||
---@param stageName string
|
---@param stageName string
|
||||||
---@return StageNameParseResult
|
---@return StageNameParseResult
|
||||||
function GlobalStageManager:ParseStageName(stageName)
|
function GlobalStageManager:ParseStageName(stageName)
|
||||||
|
|
||||||
local split = Util.split_string(stageName, "_")
|
local split = Util.split_string(stageName, "_")
|
||||||
|
|
||||||
if Util.tableLength(split) < 3 then
|
if Util.tableLength(split) < 3 then
|
||||||
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " does not have a order number or valid format" }
|
return { isValid = false, invalidReason = "Stage zone with name " ..
|
||||||
|
stageName .. " does not have a order number or valid format" }
|
||||||
end
|
end
|
||||||
|
|
||||||
local typePart = string.lower(split[1])
|
local typePart = string.lower(split[1])
|
||||||
|
|
||||||
if typePart == "missionstage" then
|
if typePart == "missionstage" then
|
||||||
|
|
||||||
local orderNumberString = string.lower(split[2])
|
local orderNumberString = string.lower(split[2])
|
||||||
---@type StageType
|
---@type StageType
|
||||||
local stageType = "PrimaryStage"
|
local stageType = "PrimaryStage"
|
||||||
@@ -167,7 +165,8 @@ function GlobalStageManager:ParseStageName(stageName)
|
|||||||
|
|
||||||
local orderNumber = tonumber(orderNumberString)
|
local orderNumber = tonumber(orderNumberString)
|
||||||
if orderNumber == nil then
|
if orderNumber == nil then
|
||||||
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " does not have a valid order number : " .. orderNumberString }
|
return { isValid = false, invalidReason = "Stage zone with name " ..
|
||||||
|
stageName .. " does not have a valid order number : " .. orderNumberString }
|
||||||
end
|
end
|
||||||
|
|
||||||
local stageDisplayName = split[3]
|
local stageDisplayName = split[3]
|
||||||
@@ -182,18 +181,19 @@ function GlobalStageManager:ParseStageName(stageName)
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
elseif typePart == "waitingstage" then
|
elseif typePart == "waitingstage" then
|
||||||
|
|
||||||
local stageType = "WaitingStage"
|
local stageType = "WaitingStage"
|
||||||
local orderNumberString = split[2]
|
local orderNumberString = split[2]
|
||||||
local orderNumber = tonumber(orderNumberString)
|
local orderNumber = tonumber(orderNumberString)
|
||||||
if orderNumber == nil then
|
if orderNumber == nil then
|
||||||
return { isValid = false, invalidReason = "Waiting Stage zone with name " .. stageName .. " does not have a valid order number : " .. orderNumberString }
|
return { isValid = false, invalidReason = "Waiting Stage zone with name " ..
|
||||||
|
stageName .. " does not have a valid order number : " .. orderNumberString }
|
||||||
end
|
end
|
||||||
|
|
||||||
local waitingSecondsString = split[3]
|
local waitingSecondsString = split[3]
|
||||||
local waitingSeconds = tonumber(waitingSecondsString)
|
local waitingSeconds = tonumber(waitingSecondsString)
|
||||||
if waitingSeconds == nil then
|
if waitingSeconds == nil then
|
||||||
return { isValid = false, invalidReason = "Waiting Stage zone with name " .. stageName .. " does not have a valid amount of seconds parameter : " .. waitingSecondsString }
|
return { isValid = false, invalidReason = "Waiting Stage zone with name " ..
|
||||||
|
stageName .. " does not have a valid amount of seconds parameter : " .. waitingSecondsString }
|
||||||
end
|
end
|
||||||
|
|
||||||
local stageDisplayName = "Waiting Stage " .. orderNumber
|
local stageDisplayName = "Waiting Stage " .. orderNumber
|
||||||
@@ -209,9 +209,9 @@ function GlobalStageManager:ParseStageName(stageName)
|
|||||||
waitingStageSeconds = waitingSeconds
|
waitingStageSeconds = waitingSeconds
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
end
|
end
|
||||||
return { isValid = false, invalidReason = "Stage zone with name " .. stageName .. " has an unrecognized type: " .. typePart }
|
return { isValid = false, invalidReason = "Stage zone with name " ..
|
||||||
|
stageName .. " has an unrecognized type: " .. typePart }
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stage Stage
|
---@param stage Stage
|
||||||
@@ -223,7 +223,8 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
|
|
||||||
local stageLane = self._stageRepository:getStageLane(laneIdentifier)
|
local stageLane = self._stageRepository:getStageLane(laneIdentifier)
|
||||||
if not stageLane or not stageLane:IsCurrentStageIndexComplete() then
|
if not stageLane or not stageLane:IsCurrentStageIndexComplete() then
|
||||||
self.logger:debug("Stage lane " .. (laneIdentifier or "default") .. " is not complete for stage index " .. stageIndex)
|
self.logger:debug("Stage lane " ..
|
||||||
|
(laneIdentifier or "default") .. " is not complete for stage index " .. stageIndex)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -242,7 +243,9 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey and lane:GetStageLaneState() == "BetweenChapters" then
|
if lane:GetStageLaneIdentifier() ~= StageLane.DefaultLaneKey and lane:GetStageLaneState() == "BetweenChapters" then
|
||||||
local nextChapterStart = lane:GetNextChapterStart()
|
local nextChapterStart = lane:GetNextChapterStart()
|
||||||
if nextChapterStart == nextStageIndex then
|
if nextChapterStart == nextStageIndex then
|
||||||
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is at chapter start for next stage index " .. nextStageIndex)
|
self.logger:debug("Lane " ..
|
||||||
|
(lane:GetStageLaneIdentifier() or "default") ..
|
||||||
|
" is at chapter start for next stage index " .. nextStageIndex)
|
||||||
Events.PublishStageNumberChanged(nextStageIndex, lane:GetStageLaneIdentifier())
|
Events.PublishStageNumberChanged(nextStageIndex, lane:GetStageLaneIdentifier())
|
||||||
lane:SetActiveStageIndex(nextStageIndex)
|
lane:SetActiveStageIndex(nextStageIndex)
|
||||||
end
|
end
|
||||||
@@ -256,7 +259,6 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
if defaultStageLane and defaultStageLane:GetStageLaneState() == "BetweenChapters" then
|
if defaultStageLane and defaultStageLane:GetStageLaneState() == "BetweenChapters" then
|
||||||
local nextChapterStart = defaultStageLane:GetNextChapterStart()
|
local nextChapterStart = defaultStageLane:GetNextChapterStart()
|
||||||
if nextChapterStart == nextStageIndex then
|
if nextChapterStart == nextStageIndex then
|
||||||
|
|
||||||
-- 2. Check if all side lanes are at or beyond the next chapter starts
|
-- 2. Check if all side lanes are at or beyond the next chapter starts
|
||||||
local allLanes = self._stageRepository:getAllStageLanes()
|
local allLanes = self._stageRepository:getAllStageLanes()
|
||||||
local allSideLanesReady = true
|
local allSideLanesReady = true
|
||||||
@@ -265,7 +267,9 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
-- Check if the lane is at or beyond the next chapter starts when "InChapter" eq "Active"
|
-- Check if the lane is at or beyond the next chapter starts when "InChapter" eq "Active"
|
||||||
if lane:GetStageLaneState() == "InChapter" and lane:GetActiveStageIndex() < nextStageIndex then
|
if lane:GetStageLaneState() == "InChapter" and lane:GetActiveStageIndex() < nextStageIndex then
|
||||||
allSideLanesReady = false
|
allSideLanesReady = false
|
||||||
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is not ready for next stage index " .. nextStageIndex)
|
self.logger:debug("Lane " ..
|
||||||
|
(lane:GetStageLaneIdentifier() or "default") ..
|
||||||
|
" is not ready for next stage index " .. nextStageIndex)
|
||||||
break
|
break
|
||||||
|
|
||||||
-- When in between chapters, check if the next chapter start is less than the next stage index, meaning there is still stages to be completed before the main lane can be activated again
|
-- When in between chapters, check if the next chapter start is less than the next stage index, meaning there is still stages to be completed before the main lane can be activated again
|
||||||
@@ -273,7 +277,9 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
local nextChapter = lane:GetNextChapterStart()
|
local nextChapter = lane:GetNextChapterStart()
|
||||||
if nextChapter and nextChapter < nextStageIndex then
|
if nextChapter and nextChapter < nextStageIndex then
|
||||||
allSideLanesReady = false
|
allSideLanesReady = false
|
||||||
self.logger:debug("Lane " .. (lane:GetStageLaneIdentifier() or "default") .. " is not ready for next stage index " .. nextStageIndex)
|
self.logger:debug("Lane " ..
|
||||||
|
(lane:GetStageLaneIdentifier() or "default") ..
|
||||||
|
" is not ready for next stage index " .. nextStageIndex)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -281,13 +287,14 @@ function GlobalStageManager:OnStageComplete(stage)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if allSideLanesReady then
|
if allSideLanesReady then
|
||||||
self.logger:debug("All side lanes are ready for next stage index " .. nextStageIndex .. ", activating default lane")
|
self.logger:debug("All side lanes are ready for next stage index " ..
|
||||||
|
nextStageIndex .. ", activating default lane")
|
||||||
Events.PublishStageNumberChanged(nextStageIndex, nil)
|
Events.PublishStageNumberChanged(nextStageIndex, nil)
|
||||||
defaultStageLane:SetActiveStageIndex(nextStageIndex)
|
defaultStageLane:SetActiveStageIndex(nextStageIndex)
|
||||||
else
|
else
|
||||||
self.logger:debug("Not all side lanes are ready for next stage index " .. nextStageIndex .. ", default lane will not be activated")
|
self.logger:debug("Not all side lanes are ready for next stage index " ..
|
||||||
|
nextStageIndex .. ", default lane will not be activated")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -308,7 +315,6 @@ end
|
|||||||
|
|
||||||
---@public
|
---@public
|
||||||
function GlobalStageManager:OnStageNumberChanged(stageNumber, stageLaneIdentifier)
|
function GlobalStageManager:OnStageNumberChanged(stageNumber, stageLaneIdentifier)
|
||||||
|
|
||||||
-- only react on "main" lane changes, ignore other lanes for now
|
-- only react on "main" lane changes, ignore other lanes for now
|
||||||
if stageLaneIdentifier ~= nil then return end
|
if stageLaneIdentifier ~= nil then return end
|
||||||
|
|
||||||
@@ -321,13 +327,13 @@ 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
|
||||||
groups[group:getID()] = group
|
table.insert(groups, group)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -349,22 +355,26 @@ function GlobalStageManager:UpdateDrawings(stageNumber, stageLaneIdentifier)
|
|||||||
|
|
||||||
if laneIdentifier == stageLaneIdentifier then
|
if laneIdentifier == stageLaneIdentifier then
|
||||||
if stageNumber >= startStage and stageNumber < stopStage then
|
if stageNumber >= startStage and stageNumber < stopStage then
|
||||||
self.logger:debug("Drawing " .. drawing:GetName() .. " is active for stage number: " .. tostring(stageNumber))
|
self.logger:debug("Drawing " ..
|
||||||
|
drawing:GetName() .. " is active for stage number: " .. tostring(stageNumber))
|
||||||
drawing:Draw()
|
drawing:Draw()
|
||||||
else
|
else
|
||||||
self.logger:debug("Drawing " .. drawing:GetName() .. " is not active for stage number: " .. tostring(stageNumber))
|
self.logger:debug("Drawing " ..
|
||||||
|
drawing:GetName() .. " is not active for stage number: " .. tostring(stageNumber))
|
||||||
drawing:Remove()
|
drawing:Remove()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function GlobalStageManager:PrintMermaidStage()
|
function GlobalStageManager:PrintMermaidStage()
|
||||||
local lanes = self._stageRepository:getAllStageLanes()
|
local lanes = self._stageRepository:getAllStageLanes()
|
||||||
|
|
||||||
|
---@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"
|
||||||
|
|
||||||
@@ -397,7 +407,9 @@ 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
|
||||||
@@ -424,6 +436,7 @@ 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 .. "]"
|
||||||
@@ -490,7 +503,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]
|
local sideIndices = stageIndicesByLane[sideId] or {} --[[@as Array<number>]]
|
||||||
|
|
||||||
-- 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
|
||||||
@@ -522,7 +535,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]
|
local sideIndices = stageIndicesByLane[sideId] or {} --[[@as Array<number>]]
|
||||||
|
|
||||||
-- 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
|
||||||
@@ -552,11 +565,12 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Build complete Mermaid diagram
|
-- Build complete Mermaid diagram
|
||||||
local diagramLines = {"graph TD"}
|
local diagramLines = { "graph TD" }
|
||||||
|
|
||||||
-- Add class definitions for each lane with colors and contrasting text
|
-- Add class definitions for each lane with colors and contrasting text
|
||||||
for laneId, color in pairs(laneColorMap) do
|
for laneId, color in pairs(laneColorMap) do
|
||||||
table.insert(diagramLines, string.format(' classDef lane_%s fill:%s,stroke:#333,stroke-width:2px,color:#000', laneId, color))
|
table.insert(diagramLines,
|
||||||
|
string.format(' classDef lane_%s fill:%s,stroke:#333,stroke-width:2px,color:#000', laneId, color))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add nodes
|
-- Add nodes
|
||||||
@@ -578,7 +592,8 @@ function GlobalStageManager:PrintMermaidStage()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Print as single multi-line message
|
-- Print as single multi-line message
|
||||||
local diagram = "========== STAGE FLOW DIAGRAM ==========\n" .. table.concat(diagramLines, "\n") .. "\n========== END DIAGRAM =========="
|
local diagram = "========== STAGE FLOW DIAGRAM ==========\n" ..
|
||||||
|
table.concat(diagramLines, "\n") .. "\n========== END DIAGRAM =========="
|
||||||
self.logger:info(diagram)
|
self.logger:info(diagram)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -586,10 +601,10 @@ end
|
|||||||
---@param stageNumber number
|
---@param stageNumber number
|
||||||
---@param stageLaneIdentifier string? nil for default lan
|
---@param stageLaneIdentifier string? nil for default lan
|
||||||
---@return boolean | nil
|
---@return boolean | nil
|
||||||
GlobalStageManager.isStageComplete = function (stageNumber, stageLaneIdentifier)
|
GlobalStageManager.isStageComplete = function(stageNumber, stageLaneIdentifier)
|
||||||
|
|
||||||
if singletonInstance == nil then
|
if singletonInstance == nil then
|
||||||
Logger.new("StageManager", "INFO"):warn("GlobalStageManager.isStageComplete called before GlobalStageManager was initialized. Returning nil")
|
Logger.new("StageManager", "INFO"):warn(
|
||||||
|
"GlobalStageManager.isStageComplete called before GlobalStageManager was initialized. Returning nil")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ function SpearheadGroup:Spawn(lateStart)
|
|||||||
uncontrolled = lateStart,
|
uncontrolled = lateStart,
|
||||||
}
|
}
|
||||||
|
|
||||||
local spawnedObject, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
|
local _, isStatic = self._spawnManager:SpawnGroup(self._groupName, overrides, self._isPersistent)
|
||||||
self._isStatic = isStatic
|
self._isStatic = isStatic
|
||||||
self._isSpawned = true
|
self._isSpawned = true
|
||||||
end
|
end
|
||||||
@@ -91,9 +91,9 @@ function SpearheadGroup:GetCoalition()
|
|||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@return table result list of objects
|
---@return Array<Unit|StaticObject> 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)
|
||||||
|
|||||||
@@ -50,12 +50,6 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
|
|||||||
---@type table<string, Vec3>
|
---@type table<string, Vec3>
|
||||||
local redUnitsPos = {}
|
local redUnitsPos = {}
|
||||||
|
|
||||||
|
|
||||||
local buildable = false
|
|
||||||
if self._buildableCrateKilos and self._buildableCrateKilos > 0 then
|
|
||||||
buildable = true
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, groupName in pairs(blueSamData.groups) do
|
for _, groupName in pairs(blueSamData.groups) do
|
||||||
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
local spearheadGroup = SpearheadGroup.New(groupName, spawnManager, true)
|
||||||
if spearheadGroup then
|
if spearheadGroup then
|
||||||
@@ -78,7 +72,7 @@ function BlueSam.New(database, logger, zoneName, spawnManager)
|
|||||||
|
|
||||||
--Cleanup units
|
--Cleanup units
|
||||||
local cleanup_distance = 5
|
local cleanup_distance = 5
|
||||||
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do
|
for _, blueUnitPos in pairs(blueUnitsPos) do
|
||||||
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
||||||
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||||
if distance <= cleanup_distance then
|
if distance <= cleanup_distance then
|
||||||
@@ -140,8 +134,10 @@ end
|
|||||||
|
|
||||||
function BlueSam:SpawnGroups()
|
function BlueSam:SpawnGroups()
|
||||||
for unitName, needsCleanup in pairs(self._cleanupUnits) do
|
for unitName, needsCleanup in pairs(self._cleanupUnits) do
|
||||||
|
if needsCleanup then
|
||||||
DcsUtil.DestroyUnit(unitName)
|
DcsUtil.DestroyUnit(unitName)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for _, group in pairs(self._blueGroups) do
|
for _, group in pairs(self._blueGroups) do
|
||||||
group:Spawn()
|
group:Spawn()
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ function StageBase.New(databaseManager, logger, airbaseName, spawnManager)
|
|||||||
|
|
||||||
local cleanup_distance = 5
|
local cleanup_distance = 5
|
||||||
|
|
||||||
for blueUnitName, blueUnitPos in pairs(blueUnitsPos) do
|
for _, blueUnitPos in pairs(blueUnitsPos) do
|
||||||
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
for redUnitName, redUnitPos in pairs(redUnitsPos) do
|
||||||
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
local distance = Util.VectorDistance3d(blueUnitPos, redUnitPos)
|
||||||
if distance <= cleanup_distance then
|
if distance <= cleanup_distance then
|
||||||
@@ -113,6 +113,7 @@ 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()
|
||||||
@@ -142,6 +143,7 @@ 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,6 +37,7 @@ 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
|
||||||
@@ -76,8 +77,6 @@ function BuildableZone:New(targetZone, kilosRequired, crateType, buildableGroup
|
|||||||
self._buildableMission = nil
|
self._buildableMission = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if self._buildableMission == nil then
|
if self._buildableMission == nil then
|
||||||
self._buildableLogger:debug("No buildable mission for zone: " .. targetZone.name)
|
self._buildableLogger:debug("No buildable mission for zone: " .. targetZone.name)
|
||||||
end
|
end
|
||||||
@@ -99,25 +98,14 @@ function BuildableZone:OnBuildingComplete() end
|
|||||||
---@field unpackedItems number
|
---@field unpackedItems number
|
||||||
---@field unpackedKilos number
|
---@field unpackedKilos number
|
||||||
|
|
||||||
---@param mission BuildableMission?
|
---@param _ BuildableMission?
|
||||||
---@param kilos number
|
---@param kilos number
|
||||||
function BuildableZone:OnCrateDroppedOff(mission, kilos)
|
function BuildableZone:OnCrateDroppedOff(_, kilos)
|
||||||
self._buildableLogger:debug("Crate dropped off in zone: " .. self._targetZone.name)
|
self._buildableLogger:debug("Crate dropped off in zone: " .. self._targetZone.name)
|
||||||
|
|
||||||
local timeToUnpack = (kilos / 500) * 15
|
|
||||||
|
|
||||||
---@type UnpackCrateParam
|
|
||||||
local params = {
|
|
||||||
self = self,
|
|
||||||
groupsPerKilo = self._groupsPerKilo,
|
|
||||||
unpackedItems = 0,
|
|
||||||
kilosPerSecond = kilos/timeToUnpack,
|
|
||||||
unpackedKilos = 0,
|
|
||||||
kilos = kilos
|
|
||||||
}
|
|
||||||
|
|
||||||
---@param params UnpackCrateParam
|
---@param params UnpackCrateParam
|
||||||
---@param time number
|
---@param time number
|
||||||
|
---@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
|
||||||
@@ -136,6 +124,17 @@ function BuildableZone:OnCrateDroppedOff(mission, kilos)
|
|||||||
return time + 2
|
return time + 2
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local timeToUnpack = (kilos / 500) * 15
|
||||||
|
---@type UnpackCrateParam
|
||||||
|
local params = {
|
||||||
|
self = self,
|
||||||
|
groupsPerKilo = self._groupsPerKilo,
|
||||||
|
unpackedItems = 0,
|
||||||
|
kilosPerSecond = kilos/timeToUnpack,
|
||||||
|
unpackedKilos = 0,
|
||||||
|
kilos = kilos
|
||||||
|
}
|
||||||
|
|
||||||
timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 2)
|
timer.scheduleFunction(startUnpackingCrate, params, timer.getTime() + 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -190,7 +189,7 @@ function BuildableZone:SpawnAmount(amount)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, amount do
|
for _ = 1, amount do
|
||||||
local spawned = spawnOne()
|
local spawned = spawnOne()
|
||||||
if spawned ~= true then
|
if spawned ~= true then
|
||||||
self._buildableLogger:debug("No more groups to spawn in zone: " .. self._targetZone.name)
|
self._buildableLogger:debug("No more groups to spawn in zone: " .. self._targetZone.name)
|
||||||
|
|||||||
@@ -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<number, Array<Stage>>
|
---@field private _stagesInLaneByIndex table<string, Array<Stage>>
|
||||||
---@field private _chapterStarts table<number, boolean>?
|
---@field private _chapterStarts table<string, boolean>?
|
||||||
---@field private _stageLaneState StageLaneState
|
---@field private _stageLaneState StageLaneState
|
||||||
---@field private _maxStageIndex number
|
---@field private _maxStageIndex number
|
||||||
local StageLane = {}
|
local StageLane = {}
|
||||||
@@ -16,6 +16,7 @@ StageLane.__index = StageLane
|
|||||||
---| "BetweenChapters"
|
---| "BetweenChapters"
|
||||||
---| "Completed"
|
---| "Completed"
|
||||||
|
|
||||||
|
---@type string?
|
||||||
StageLane.DefaultLaneKey = nil
|
StageLane.DefaultLaneKey = nil
|
||||||
|
|
||||||
function StageLane.New(laneIdentifier)
|
function StageLane.New(laneIdentifier)
|
||||||
@@ -37,21 +38,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[stageIndex] then
|
if not self._stagesInLaneByIndex[tostring(stageIndex)] then
|
||||||
self._stagesInLaneByIndex[stageIndex] = {}
|
self._stagesInLaneByIndex[tostring(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[stageIndex], stage)
|
table.insert(self._stagesInLaneByIndex[tostring(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[stageNumber]
|
local stages = self._stagesInLaneByIndex[tostring(stageNumber)]
|
||||||
if not stages then
|
if not stages then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -88,7 +89,7 @@ end
|
|||||||
---@param stageNumber number
|
---@param stageNumber number
|
||||||
function StageLane:SetActiveStageIndex(stageNumber)
|
function StageLane:SetActiveStageIndex(stageNumber)
|
||||||
|
|
||||||
if self._stagesInLaneByIndex[stageNumber] == nil then
|
if self._stagesInLaneByIndex[tostring(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
|
||||||
@@ -108,6 +109,7 @@ 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
|
||||||
@@ -123,13 +125,14 @@ 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)
|
||||||
|
|
||||||
self._chapterStarts = self._chapterStarts or {}
|
if self._chapterStarts == nil then self._chapterStarts = {} end
|
||||||
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
|
||||||
@@ -158,7 +161,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[stageIndex]
|
return self._stagesInLaneByIndex[tostring(stageIndex)]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return number?
|
---@return number?
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ end
|
|||||||
function StageRepository:AddStage(stage)
|
function StageRepository:AddStage(stage)
|
||||||
|
|
||||||
local stageLaneIdentifier = stage:GetStageLaneIdentifier() or StageLane.DefaultLaneKey
|
local stageLaneIdentifier = stage:GetStageLaneIdentifier() or StageLane.DefaultLaneKey
|
||||||
|
|
||||||
if self.StageLanes[tostring(stageLaneIdentifier)] == nil then
|
if self.StageLanes[tostring(stageLaneIdentifier)] == nil then
|
||||||
self.StageLanes[tostring(stageLaneIdentifier)] = StageLane.New(stageLaneIdentifier)
|
self.StageLanes[tostring(stageLaneIdentifier)] = StageLane.New(stageLaneIdentifier)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -160,13 +160,14 @@ function Stage:superNew(database, stageConfig, logger, initData, stageType, miss
|
|||||||
self._logger:info("Initiating new Stage with name: " .. self.zoneName)
|
self._logger:info("Initiating new Stage with name: " .. self.zoneName)
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param self Stage
|
---@param selfA Stage
|
||||||
---@param time number?
|
---@param time number?
|
||||||
self.CheckContinuousAsync = function (self, time)
|
---@return number|nil
|
||||||
|
self.CheckContinuousAsync = function (selfA, time)
|
||||||
|
|
||||||
self:CheckAndUpdateSelf()
|
selfA:CheckAndUpdateSelf()
|
||||||
if self:IsComplete() == true then
|
if selfA:IsComplete() == true then
|
||||||
self:NotifyComplete()
|
selfA:NotifyComplete()
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -284,14 +285,14 @@ end
|
|||||||
function Stage:IsComplete()
|
function Stage:IsComplete()
|
||||||
if self._currentStageState >= StageState.Blue then return true end
|
if self._currentStageState >= StageState.Blue then return true end
|
||||||
|
|
||||||
for i, mission in pairs(self._db.sams) do
|
for _, mission in pairs(self._db.sams) do
|
||||||
local state = mission:getState()
|
local state = mission:getState()
|
||||||
if state == "ACTIVE" or state == "NEW" or state =="WAITING" then
|
if state == "ACTIVE" or state == "NEW" or state =="WAITING" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, mission in pairs(self._db.missions) do
|
for _, mission in pairs(self._db.missions) do
|
||||||
local state = mission:getState()
|
local state = mission:getState()
|
||||||
if state == "ACTIVE" or state == "NEW" then
|
if state == "ACTIVE" or state == "NEW" then
|
||||||
return false
|
return false
|
||||||
@@ -325,7 +326,9 @@ 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)
|
||||||
@@ -370,9 +373,9 @@ function Stage:CheckAndUpdateSelf()
|
|||||||
local availableMissionsCount = Util.tableLength(getAvailableMissions())
|
local availableMissionsCount = Util.tableLength(getAvailableMissions())
|
||||||
local activeCount = getActiveMissionsCount()
|
local activeCount = getActiveMissionsCount()
|
||||||
if activeCount < max and availableMissionsCount > 0 then
|
if activeCount < max and availableMissionsCount > 0 then
|
||||||
for i = activeCount+1, max do
|
for _ = activeCount+1, max do
|
||||||
if availableMissionsCount == 0 then
|
if availableMissionsCount == 0 then
|
||||||
i = max+1 --exits this loop
|
break
|
||||||
else
|
else
|
||||||
local mission = Util.randomFromList(getAvailableMissions()) --[[@as Mission]]
|
local mission = Util.randomFromList(getAvailableMissions()) --[[@as Mission]]
|
||||||
if mission then
|
if mission then
|
||||||
@@ -426,15 +429,15 @@ function Stage:PreActivate()
|
|||||||
end
|
end
|
||||||
|
|
||||||
self._currentStageState = StageState.PreActivated
|
self._currentStageState = StageState.PreActivated
|
||||||
for key, mission in pairs(self._db.sams) do
|
for _, mission in pairs(self._db.sams) do
|
||||||
if mission then
|
if mission then
|
||||||
mission:SpawnInactive()
|
mission:SpawnInactive()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for key, mission in pairs(self._db.missions) do
|
for _, mission in pairs(self._db.missions) do
|
||||||
if mission and mission.missionType == "DEEPSTRIKE" then
|
if mission and mission.missionType == "DEEPSTRIKE" then
|
||||||
mission:SpawnActive()
|
mission:SpawnInactive() --Not Really "inactive"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -595,8 +598,8 @@ function Stage:OnStageNumberChanged(number, stageLaneIdentifier)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param self Stage
|
---@param self Stage
|
||||||
---@param mission Mission
|
---@param _ Mission
|
||||||
Stage.OnMissionComplete = function(self, mission)
|
Stage.OnMissionComplete = function(self, _)
|
||||||
self:CheckAndUpdateSelf()
|
self:CheckAndUpdateSelf()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -651,7 +654,7 @@ function Stage:GetStageStats()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, mission in pairs(self._db.sams) do
|
for _, _ in pairs(self._db.sams) do
|
||||||
dead = dead + 1
|
dead = dead + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -679,13 +682,14 @@ function Stage:ActivateBlueStage()
|
|||||||
miscGroup:Spawn()
|
miscGroup:Spawn()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param self Stage
|
---@param selfA Stage
|
||||||
local ActivateBlueAsync = function(self)
|
---@return number|nil
|
||||||
|
local ActivateBlueAsync = function(selfA)
|
||||||
pcall(function()
|
pcall(function()
|
||||||
self:MarkStage()
|
selfA:MarkStage()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self:ActivateBlueGroups()
|
selfA:ActivateBlueGroups()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
local Stage = require("classes.stageClasses.Stages.BaseStage.Stage")
|
||||||
local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
|
local GlobalCapManager = require("classes.capClasses.GlobalCapManager")
|
||||||
local StageState = require("classes.stageClasses.Stages.StageState")
|
local StageState = require("classes.stageClasses.Stages.BaseStage.StageState")
|
||||||
|
|
||||||
---@class ExtraStage : Stage
|
---@class ExtraStage : Stage
|
||||||
local ExtraStage = {}
|
local ExtraStage = {}
|
||||||
@@ -23,7 +23,6 @@ function ExtraStage.New(database, stageConfig, logger, initData, spawnManager)
|
|||||||
self:superNew(database, stageConfig, logger, initData, "ExtraStage", "secondary", spawnManager)
|
self:superNew(database, stageConfig, logger, initData, "ExtraStage", "secondary", spawnManager)
|
||||||
|
|
||||||
self.OnPostBlueActivated = function (selfStage)
|
self.OnPostBlueActivated = function (selfStage)
|
||||||
|
|
||||||
selfStage:MarkStage()
|
selfStage:MarkStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -48,7 +47,6 @@ function ExtraStage:OnStageNumberChanged(number, stageLaneIdentifier)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local previousActive = self._activeStage
|
|
||||||
self._activeStage = number
|
self._activeStage = number
|
||||||
|
|
||||||
if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then
|
if self.stageNumber - self._activeStage == self._stageConfig.AmountPreactivateStage then
|
||||||
@@ -62,7 +60,7 @@ function ExtraStage:OnStageNumberChanged(number, stageLaneIdentifier)
|
|||||||
self:ActivateStage()
|
self:ActivateStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
if self._currentStageState == StageState.BLUE then
|
if self._currentStageState == StageState.Blue then
|
||||||
self:ActivateBlueStage()
|
self:ActivateBlueStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ function WaitingStage:OnStageNumberChanged()
|
|||||||
self._logger:debug("Waiting Stage OnStageNumberChanged override")
|
self._logger:debug("Waiting Stage OnStageNumberChanged override")
|
||||||
end
|
end
|
||||||
|
|
||||||
function WaitingStage:MarkStage(stageColor)
|
function WaitingStage:MarkStage(_)
|
||||||
self._logger:debug("Waiting Stage MarkStage override")
|
self._logger:debug("Waiting Stage MarkStage override")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
local DrawingHelper = require("classes.stageClasses.drawings.helper.DrawingHelper")
|
||||||
local Util = require("classes.util.Util")
|
|
||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local MissionEditorWarnings = require("classes.util.MissionEditorWarnings")
|
|
||||||
local drawingLogger = Logger.new("CustomDrawing")
|
local drawingLogger = Logger.new("CustomDrawing")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
local Util = require("classes.util.Util")
|
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
local DcsUtil = require("classes.util.DcsUtil")
|
||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
local GlobalConfig = require("classes.configuration.GlobalConfig")
|
||||||
@@ -55,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
|
||||||
@@ -126,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]
|
||||||
@@ -275,6 +274,7 @@ 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
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local Util = require("classes.util.Util")
|
local Util = require("classes.util.Util")
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
|
||||||
|
|
||||||
---@class BattleManager
|
---@class BattleManager
|
||||||
---@field private _name string
|
---@field private _name string
|
||||||
@@ -13,8 +12,6 @@ local DcsUtil = require("classes.util.DcsUtil")
|
|||||||
local BattleManager = {}
|
local BattleManager = {}
|
||||||
BattleManager.__index = BattleManager
|
BattleManager.__index = BattleManager
|
||||||
|
|
||||||
local debugDrawing = false
|
|
||||||
|
|
||||||
---@param redGroups Array<SpearheadGroup>
|
---@param redGroups Array<SpearheadGroup>
|
||||||
---@param blueGroups Array<SpearheadGroup>
|
---@param blueGroups Array<SpearheadGroup>
|
||||||
---@param name string
|
---@param name string
|
||||||
@@ -39,6 +36,7 @@ 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
|
||||||
@@ -90,8 +88,6 @@ function BattleManager:Update()
|
|||||||
|
|
||||||
self._logger:debug("BattleManager Update called for " .. self._name)
|
self._logger:debug("BattleManager Update called for " .. self._name)
|
||||||
|
|
||||||
local shootChance = 1 -- Adjust this value to control the shooting probability (0.0 to 1.0)
|
|
||||||
|
|
||||||
self:LetUnitsShoot(self._redGroups, self._blueGroups)
|
self:LetUnitsShoot(self._redGroups, self._blueGroups)
|
||||||
self:LetUnitsShoot(self._blueGroups, self._redGroups)
|
self:LetUnitsShoot(self._blueGroups, self._redGroups)
|
||||||
|
|
||||||
@@ -153,7 +149,7 @@ end
|
|||||||
---@return number
|
---@return number
|
||||||
function BattleManager:getBestAmmo(unit)
|
function BattleManager:getBestAmmo(unit)
|
||||||
|
|
||||||
local ammo = unit:getAmmo()
|
local ammo = unit:getAmmo() --[[@as table<number, table>]]
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -167,9 +163,9 @@ function BattleManager:getBestAmmo(unit)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local entry = Util.randomFromList(shells)
|
local entry = Util.randomFromList(shells) --[[@as table]]
|
||||||
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
|
local caliber = entry.desc.warhead.caliber --[[@as number]]
|
||||||
if caliber > 50 then
|
if caliber > 50 then
|
||||||
return 258503344128, 1
|
return 258503344128, 1
|
||||||
else
|
else
|
||||||
@@ -214,6 +210,7 @@ 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
|
---@class MissionCommandsHelper : OnPlayerEnterUnitListener
|
||||||
---@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
|
||||||
@@ -31,8 +31,6 @@ local function sortMissions(list, groupPos)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local id = 0
|
|
||||||
|
|
||||||
local instance = nil
|
local instance = nil
|
||||||
|
|
||||||
---@return MissionCommandsHelper
|
---@return MissionCommandsHelper
|
||||||
@@ -57,16 +55,16 @@ function MissionCommandsHelper.getOrCreate()
|
|||||||
|
|
||||||
instance._supplyUnitsTracker:AddOnSupplyUnitEventListener(
|
instance._supplyUnitsTracker:AddOnSupplyUnitEventListener(
|
||||||
{
|
{
|
||||||
enteredSupplyHub = function(self, unit)
|
enteredSupplyHub = function(_, unit)
|
||||||
if unit == nil then return end
|
if unit == nil then return end
|
||||||
instance.updateNeeded = true
|
instance.updateNeeded = true
|
||||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||||
end,
|
end,
|
||||||
exitedSupplyHub = function(self, unit)
|
exitedSupplyHub = function(_, unit)
|
||||||
instance.updateNeeded = true
|
instance.updateNeeded = true
|
||||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||||
end,
|
end,
|
||||||
supplyUnitSpawned = function(self, unit)
|
supplyUnitSpawned = function(_, unit)
|
||||||
instance.updateNeeded = true
|
instance.updateNeeded = true
|
||||||
instance:updateCommandsForGroup(unit:getGroup():getID())
|
instance:updateCommandsForGroup(unit:getGroup():getID())
|
||||||
end
|
end
|
||||||
@@ -371,7 +369,7 @@ 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
|
||||||
@@ -509,7 +507,6 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
|
|||||||
local unloadCargoCommand = function(params)
|
local unloadCargoCommand = function(params)
|
||||||
local unitID = params.unitID
|
local unitID = params.unitID
|
||||||
local crateType = params.crateType
|
local crateType = params.crateType
|
||||||
local supplyUnitsTracker = params.supplyUnitsTracker
|
|
||||||
params.supplyUnitsTracker:UnloadRequested(unitID, crateType, params.commandHelper)
|
params.supplyUnitsTracker:UnloadRequested(unitID, crateType, params.commandHelper)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -518,7 +515,7 @@ function MissionCommandsHelper:AddCargoCommands(groupID)
|
|||||||
for cargoType, amount in pairs(cargo) do
|
for cargoType, amount in pairs(cargo) do
|
||||||
local cargoConfig = SupplyConfigHelper.getSupplyConfig(cargoType)
|
local cargoConfig = SupplyConfigHelper.getSupplyConfig(cargoType)
|
||||||
if cargoConfig then
|
if cargoConfig then
|
||||||
for i = 1, amount do
|
for _ = 1, amount do
|
||||||
local path = { [1] = folderNames.cargo }
|
local path = { [1] = folderNames.cargo }
|
||||||
---@type UnloadCargoCommandParams
|
---@type UnloadCargoCommandParams
|
||||||
local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self
|
local params = { unitID = unit:getID(), crateType = cargoType, supplyUnitsTracker = self
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ 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
|
---@class SupplyUnitsTracker : OnPlayerEnterUnitListener
|
||||||
---@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,6 +43,8 @@ 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()
|
||||||
@@ -134,6 +136,7 @@ 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
|
||||||
|
|
||||||
@@ -158,15 +161,17 @@ 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
|
||||||
|
|
||||||
if self._cargoInUnits[unitID] == nil then
|
local unitIdStr = tostring(unitID)
|
||||||
self._cargoInUnits[unitID] = {}
|
|
||||||
|
if self._cargoInUnits[unitIdStr] == nil then
|
||||||
|
self._cargoInUnits[unitIdStr] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
if self._cargoInUnits[unitID][crateType] == nil then
|
if self._cargoInUnits[unitIdStr][crateType] == nil then
|
||||||
self._cargoInUnits[unitID][crateType] = 0
|
self._cargoInUnits[unitIdStr][crateType] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
self._cargoInUnits[unitID][crateType] = self._cargoInUnits[unitID][crateType] + 1
|
self._cargoInUnits[unitIdStr][crateType] = self._cargoInUnits[unitIdStr][crateType] + 1
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -185,7 +190,7 @@ function SupplyUnitsTracker:RemoveCargoFromUnit(unitID, crateType)
|
|||||||
self._cargoInUnits[unitIDStr][crateType] = self._cargoInUnits[unitIDStr][crateType] - 1
|
self._cargoInUnits[unitIDStr][crateType] = self._cargoInUnits[unitIDStr][crateType] - 1
|
||||||
|
|
||||||
local hasCargo = false
|
local hasCargo = false
|
||||||
for type, count in pairs(self._cargoInUnits[unitIDStr]) do
|
for _, count in pairs(self._cargoInUnits[unitIDStr]) do
|
||||||
if count > 0 then
|
if count > 0 then
|
||||||
hasCargo = true
|
hasCargo = true
|
||||||
break
|
break
|
||||||
@@ -216,13 +221,11 @@ end
|
|||||||
|
|
||||||
function SupplyUnitsTracker:CheckUnitsInZones()
|
function SupplyUnitsTracker:CheckUnitsInZones()
|
||||||
|
|
||||||
for name, unit in pairs(self._supplyUnitsByName) do
|
for _, unit in pairs(self._supplyUnitsByName) do
|
||||||
if unit ~= nil and unit:isExist() == true then
|
if unit ~= nil and unit:isExist() == true then
|
||||||
self._logger:debug("Checking unit: " .. unit:getName())
|
self._logger:debug("Checking unit: " .. unit:getName())
|
||||||
local pos = unit:getPoint()
|
local pos = unit:getPoint()
|
||||||
|
|
||||||
local group = unit:getGroup()
|
|
||||||
|
|
||||||
for hub, enabled in pairs(self._registeredHubs) do
|
for hub, enabled in pairs(self._registeredHubs) do
|
||||||
if enabled == true then
|
if enabled == true then
|
||||||
local zone = hub:GetZone()
|
local zone = hub:GetZone()
|
||||||
@@ -255,7 +258,7 @@ function SupplyUnitsTracker:CheckUnitsInZones()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self._unitPositions[unit:getID()] = pos
|
self._unitPositions[tostring(unit:getID())] = pos
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -325,6 +328,7 @@ 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,
|
||||||
@@ -486,7 +490,7 @@ function SupplyUnitsTracker:GetBoundingBoxes(foundObject)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local objPos = foundObject:getPoint()
|
local objPos = foundObject:getPoint()
|
||||||
local box = desc.box
|
local box = desc.box --[[@type table]]
|
||||||
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
|
||||||
@@ -499,10 +503,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
|
local minX = box.min.x --[[@as number]]
|
||||||
local maxX = box.max.x
|
local maxX = box.max.x --[[@as number]]
|
||||||
local minZ = box.min.z
|
local minZ = box.min.z --[[@as number]]
|
||||||
local maxZ = box.max.z
|
local maxZ = box.max.z --[[@as number]]
|
||||||
|
|
||||||
-- 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
|
||||||
@@ -519,8 +523,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)
|
local rotX = corner[1] * math.cos(heading) - corner[2] * math.sin(heading) --[[@as number]]
|
||||||
local rotZ = corner[1] * math.sin(heading) + corner[2] * math.cos(heading)
|
local rotZ = corner[1] * math.sin(heading) + corner[2] * math.cos(heading) --[[@as number]]
|
||||||
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)
|
||||||
@@ -589,7 +593,7 @@ function SupplyUnitsTracker:GetCargoPlacePosition(unit, crateTypeName)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local crateRelativeBBox = crateDesc.box
|
local crateRelativeBBox = crateDesc.box --[[@as table]]
|
||||||
|
|
||||||
-- Get drop zone config for this unit
|
-- Get drop zone config for this unit
|
||||||
local dropZones = {
|
local dropZones = {
|
||||||
@@ -612,9 +616,12 @@ 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 = {}
|
local occupiedObjects = {}
|
||||||
local found = function(foundItem, val)
|
|
||||||
|
---@param foundItem Object
|
||||||
|
---@param _ any
|
||||||
|
local found = function(foundItem, _)
|
||||||
local bbox = self:GetBoundingBoxes(foundItem)
|
local bbox = self:GetBoundingBoxes(foundItem)
|
||||||
if bbox then
|
if bbox then
|
||||||
self._logger:debug("Found object: " .. foundItem:getTypeName() .. " at (" .. foundItem:getPoint().x .. ", " .. foundItem:getPoint().z .. ")")
|
self._logger:debug("Found object: " .. foundItem:getTypeName() .. " at (" .. foundItem:getPoint().x .. ", " .. foundItem:getPoint().z .. ")")
|
||||||
@@ -662,6 +669,7 @@ 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,7 +25,9 @@ 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
|
||||||
local function getDefaultBriefing(siteType, coords)
|
local function getDefaultBriefing(siteType, coords)
|
||||||
return "We've dispatched forward units to find a proper spot for a new " .. siteType .. "." ..
|
return "We've dispatched forward units to find a proper spot for a new " .. siteType .. "." ..
|
||||||
"\nYou will need to drop off supplies so they can start building." ..
|
"\nYou will need to drop off supplies so they can start building." ..
|
||||||
@@ -43,6 +45,7 @@ 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)
|
||||||
@@ -83,13 +86,6 @@ function BuildableMission.new(database, logger, targetZone, noLandingZone, requi
|
|||||||
self.name = "Resupply"
|
self.name = "Resupply"
|
||||||
end
|
end
|
||||||
|
|
||||||
local type = "site"
|
|
||||||
if requiredCrateType == "SAM_CRATE" then
|
|
||||||
type = "SAM site"
|
|
||||||
elseif requiredCrateType == "FARP_CRATE" then
|
|
||||||
type = "FARP"
|
|
||||||
end
|
|
||||||
|
|
||||||
self.zoneName = targetZone.name .. "_supply"
|
self.zoneName = targetZone.name .. "_supply"
|
||||||
self._logger = logger
|
self._logger = logger
|
||||||
self._onCrateDroppedOfListeners = {}
|
self._onCrateDroppedOfListeners = {}
|
||||||
@@ -124,6 +120,7 @@ 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
|
||||||
@@ -150,17 +147,20 @@ 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)
|
||||||
|
|
||||||
if self._markIDsPerGroup[groupID] then
|
local groupIdStr = tostring(groupID)
|
||||||
DcsUtil.RemoveMark(self._markIDsPerGroup[groupID])
|
|
||||||
end
|
|
||||||
|
|
||||||
|
if self._markIDsPerGroup[groupIdStr] then
|
||||||
|
DcsUtil.RemoveMark(self._markIDsPerGroup[groupIdStr])
|
||||||
|
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[groupID] = markID
|
self._markIDsPerGroup[groupIdStr] = markID
|
||||||
end
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
@@ -204,6 +204,7 @@ 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()
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ 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)
|
||||||
@@ -84,7 +85,6 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
|
|||||||
|
|
||||||
self._logger:debug("Runway hit: " .. self._airportName .. ":" .. self._runway.Name)
|
self._logger:debug("Runway hit: " .. self._airportName .. ":" .. self._runway.Name)
|
||||||
for _, section in pairs(self._runwaySections) do
|
for _, section in pairs(self._runwaySections) do
|
||||||
|
|
||||||
local zone = self:SectionToSpearheadZone(section)
|
local zone = self:SectionToSpearheadZone(section)
|
||||||
if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
if Util.is3dPointInZone({ x = impactPoint.x, z = impactPoint.y, y = 0 }, zone) then
|
||||||
if section.kilosHit == nil then
|
if section.kilosHit == nil then
|
||||||
@@ -96,7 +96,7 @@ function RunwayStrikeMission:RunwayHit(impactPoint, explosiveMass)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param selfA RunwayStrikeMission
|
---@param selfA RunwayStrikeMission
|
||||||
local updateState = function(selfA, time)
|
local updateState = function(selfA, _)
|
||||||
selfA:UpdateState()
|
selfA:UpdateState()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -206,17 +206,18 @@ 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 any
|
---@param selfA RunwayStrikeMission
|
||||||
---@return unknown
|
---@param time number
|
||||||
|
---@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
|
||||||
return time + interval
|
return time + interval
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
||||||
@@ -249,12 +250,14 @@ function RunwayStrikeMission:DoRepairCycle()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class StaticSpawn
|
---@class StaticSpawn : table
|
||||||
---@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
|
||||||
@@ -443,6 +446,7 @@ 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)
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ end
|
|||||||
---@return boolean
|
---@return boolean
|
||||||
function ZoneMission:AllDependenciesMet()
|
function ZoneMission:AllDependenciesMet()
|
||||||
local allDependenciesMet = true
|
local allDependenciesMet = true
|
||||||
for missionName, value in pairs(self._dependencies) do
|
for missionName, _ in pairs(self._dependencies) do
|
||||||
if self._parentStage:IsMissionComplete(missionName) == false then
|
if self._parentStage:IsMissionComplete(missionName) == false then
|
||||||
allDependenciesMet = false
|
allDependenciesMet = false
|
||||||
self._dependencies[missionName] = false
|
self._dependencies[missionName] = false
|
||||||
@@ -227,10 +227,9 @@ end
|
|||||||
|
|
||||||
---@internal
|
---@internal
|
||||||
---@param checkHealth boolean
|
---@param checkHealth boolean
|
||||||
---@param messageIfDone boolean
|
---@param _ boolean
|
||||||
function ZoneMission:UpdateState(checkHealth, messageIfDone)
|
function ZoneMission:UpdateState(checkHealth, _)
|
||||||
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
|
||||||
@@ -238,7 +237,7 @@ function ZoneMission:UpdateState(checkHealth, messageIfDone)
|
|||||||
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
|
local life0 = staticObject:getDesc().life --[[@as number]]
|
||||||
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)
|
||||||
@@ -284,7 +283,9 @@ function ZoneMission:UpdateState(checkHealth, messageIfDone)
|
|||||||
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
|
||||||
@@ -297,13 +298,13 @@ function ZoneMission:UpdateState(checkHealth, messageIfDone)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, sceneryObject in pairs(self._missionGroups.sceneryTargets) do
|
for _, sceneryObject in pairs(self._missionGroups.sceneryTargets) do
|
||||||
total = total + 1
|
total = total + 1 --[[@as number]]
|
||||||
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
|
local deadRatio = (total - alive) / total --[[@as number]]
|
||||||
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"
|
||||||
@@ -499,6 +500,7 @@ 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)
|
||||||
|
|
||||||
@@ -509,6 +511,7 @@ function ZoneMission:OnUnitLost(object)
|
|||||||
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
|
||||||
|
|
||||||
|
|||||||
@@ -73,9 +73,10 @@ 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
|
||||||
function Mission:UpdateState(checkHealth, messageIfDone) end
|
---@diagnostic disable-next-line: unused-local
|
||||||
|
function Mission:UpdateState(_checkHealth, _messageIfDone) end
|
||||||
function Mission:StartCheckingContinuous() end
|
function Mission:StartCheckingContinuous() end
|
||||||
|
|
||||||
function Mission:PercentageComplete()
|
function Mission:PercentageComplete()
|
||||||
@@ -90,6 +91,7 @@ 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()
|
||||||
@@ -125,7 +127,7 @@ function Mission:NotifyMissionComplete()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local success, err = pcall(function()
|
local _, _ = pcall(function()
|
||||||
SpearheadAPI.Internal.notifyMissionComplete(self.zoneName)
|
SpearheadAPI.Internal.notifyMissionComplete(self.zoneName)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -136,7 +138,9 @@ function Mission:ForceMissionComplete()
|
|||||||
self:NotifyMissionComplete()
|
self:NotifyMissionComplete()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Mission:MarkMissionAreaToGroup(groupId) end
|
---@param _groupId number
|
||||||
|
---@diagnostic disable-next-line: unused-local
|
||||||
|
function Mission:MarkMissionAreaToGroup(_groupId) end
|
||||||
|
|
||||||
---endregion
|
---endregion
|
||||||
|
|
||||||
@@ -148,30 +152,27 @@ function Mission:ToStateString() return "status: in progress" end
|
|||||||
|
|
||||||
--endregion
|
--endregion
|
||||||
|
|
||||||
do --aliases
|
--- @alias MissionPriority
|
||||||
|
--- | "none"
|
||||||
|
--- | "primary"
|
||||||
|
--- | "secondary"
|
||||||
|
|
||||||
--- @alias MissionPriority
|
--- @alias MissionType
|
||||||
--- | "none"
|
--- | "nil"
|
||||||
--- | "primary"
|
--- | "STRIKE"
|
||||||
--- | "secondary"
|
--- | "DEEPSTRIKE"
|
||||||
|
--- | "CAS"
|
||||||
|
--- | "BAI"
|
||||||
|
--- | "DEAD"
|
||||||
|
--- | "SAM"
|
||||||
|
--- | "OCA"
|
||||||
|
--- | "LOGISTICS"
|
||||||
|
---
|
||||||
|
--- @alias MissionState
|
||||||
|
--- | "NEW"
|
||||||
|
--- | "WAITING"
|
||||||
|
--- | "ACTIVE"
|
||||||
|
--- | "COMPLETED"
|
||||||
|
|
||||||
--- @alias MissionType
|
|
||||||
--- | "nil"
|
|
||||||
--- | "STRIKE"
|
|
||||||
--- | "DEEPSTRIKE"
|
|
||||||
--- | "CAS"
|
|
||||||
--- | "BAI"
|
|
||||||
--- | "DEAD"
|
|
||||||
--- | "SAM"
|
|
||||||
--- | "OCA"
|
|
||||||
--- | "LOGISTICS"
|
|
||||||
|
|
||||||
--- @alias MissionState
|
|
||||||
--- | "NEW"
|
|
||||||
--- | "WAITING"
|
|
||||||
--- | "ACTIVE"
|
|
||||||
--- | "COMPLETED"
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return Mission
|
return Mission
|
||||||
@@ -32,6 +32,10 @@ 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
|
||||||
@@ -40,7 +44,7 @@ do -- INIT DCS_UTIL
|
|||||||
---@field zone_type SpearheadTriggerZoneType
|
---@field zone_type SpearheadTriggerZoneType
|
||||||
---@field properties Array<KeyValuePair>?
|
---@field properties Array<KeyValuePair>?
|
||||||
|
|
||||||
---@type Array<SpearheadTriggerZone>
|
---@type table<string, SpearheadTriggerZone>
|
||||||
DCS_UTIL.__trigger_zones = {}
|
DCS_UTIL.__trigger_zones = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -66,18 +70,21 @@ 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
|
||||||
|
|
||||||
do --init trigger zones
|
do --init trigger zones
|
||||||
for i, trigger_zone in pairs(env.mission.triggers.zones) do
|
for _, trigger_zone in pairs(env.mission.triggers.zones) do
|
||||||
-- reorder verts as they are not ordered correctly in the ME
|
-- reorder verts as they are not ordered correctly in the ME
|
||||||
local verts = {}
|
local verts = {}
|
||||||
if Util.tableLength(trigger_zone.verticies) >= 4 then
|
if Util.tableLength(trigger_zone.verticies) >= 4 then
|
||||||
@@ -104,8 +111,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
|
||||||
@@ -116,6 +123,7 @@ 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"
|
||||||
@@ -126,12 +134,12 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
if env.warehouses.warehouses then
|
if env.warehouses.warehouses then
|
||||||
DCS_UTIL.__warehouseStartingCoalition[-1] = "placeholder"
|
env.warehouses.warehouses = env.warehouses.warehouses --[[@as table<number, any>]]
|
||||||
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
|
||||||
warehouse_id = tostring(warehouse_id) or "nil"
|
local warehouse_id_str = tostring(warehouse_id) or "nil"
|
||||||
local coalitionNumber = DCS_UTIL.stringToCoalition(value.coalition)
|
local coalitionNumber = DCS_UTIL.stringToCoalition(value.coalition)
|
||||||
DCS_UTIL.__warehouseStartingCoalition[warehouse_id] = coalitionNumber
|
DCS_UTIL.__warehouseStartingCoalition[warehouse_id_str] = coalitionNumber
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -192,7 +200,7 @@ do -- INIT DCS_UTIL
|
|||||||
BLUE = 2
|
BLUE = 2
|
||||||
}
|
}
|
||||||
]] --
|
]] --
|
||||||
local input = string.lower(input)
|
input = string.lower(input)
|
||||||
if input == 'neutrals' or input == "neutral" or input == "0" then
|
if input == 'neutrals' or input == "neutral" or input == "0" then
|
||||||
return DCS_UTIL.Coalition.NEUTRAL
|
return DCS_UTIL.Coalition.NEUTRAL
|
||||||
end
|
end
|
||||||
@@ -218,11 +226,13 @@ 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 table unit names
|
---@param unit_names Array<string> unit names
|
||||||
---@param zone_names table zone names
|
---@param zone_names Array<string> zone names
|
||||||
---@return table unit list of objects { unit = UNIT, zone_name = zoneName}
|
---@return table<number, { unit : Unit|StaticObject, zone_name: string }>
|
||||||
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>
|
||||||
@@ -235,20 +245,25 @@ do -- INIT DCS_UTIL
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for index, zone_name in pairs(zone_names) do
|
for _, zone_name in pairs(zone_names) do
|
||||||
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
||||||
if zone then
|
if zone then
|
||||||
zones[#zones + 1] = zone
|
zones[#zones + 1] = zone
|
||||||
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 unit_pos = lUnit:getPosition().p
|
local isActive = true
|
||||||
local lCat = Object.getCategory(lUnit)
|
local lCat = Object.getCategory(lUnit)
|
||||||
for zone_name, zone in pairs(zones) do
|
if lCat == Object.Category.UNIT then
|
||||||
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 unit = lUnit --[[@as Unit]]
|
||||||
|
isActive = unit:isActive() == true
|
||||||
|
end
|
||||||
|
local unit_pos = lUnit:getPosition().p
|
||||||
|
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
|
||||||
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 }
|
||||||
@@ -262,9 +277,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 table groupnames list of group names
|
---@return Array<string> 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]
|
local zone = DCS_UTIL.__trigger_zones[zone_name] --[[@as SpearheadTriggerZone?]]
|
||||||
if zone == nil then
|
if zone == nil then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
@@ -277,11 +292,13 @@ 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
|
||||||
local entry = nil
|
---@type { unit : Unit|StaticObject|nil, groupname: string }|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] }
|
||||||
@@ -290,7 +307,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] = entry
|
units[#units + 1] = { groupname = entry.groupname, unit = entry.unit }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -308,20 +325,20 @@ 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 table zone names
|
---@param zone_names Array<string> zone names
|
||||||
---@return table zones list of objects { zone_name = zoneName}
|
---@return Array<string> 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 = {}
|
||||||
for index, zone_name in pairs(zone_names) do
|
for _, zone_name in pairs(zone_names) do
|
||||||
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
local zone = DCS_UTIL.__trigger_zones[zone_name]
|
||||||
if zone then
|
if zone then
|
||||||
zones[#zones + 1] = zone
|
zones[#zones + 1] = zone
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
---@type Array<string>
|
||||||
local result_zones = {}
|
local result_zones = {}
|
||||||
for zone_name, zone in pairs(zones) do
|
for _, zone in pairs(zones) do
|
||||||
if Util.is3dPointInZone({ x = x, z = z, y = 0 }, zone) == true then
|
if Util.is3dPointInZone({ x = x, z = z, y = 0 }, zone) == true then
|
||||||
result_zones[#result_zones + 1] = zone.name
|
result_zones[#result_zones + 1] = zone.name
|
||||||
end
|
end
|
||||||
@@ -396,6 +413,18 @@ 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 =
|
||||||
{
|
{
|
||||||
@@ -408,13 +437,14 @@ 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)
|
||||||
local vec3 = { x = location.x, y = height, z = location.y }
|
local vec3 = { x = location.x, y = height, z = location.y }
|
||||||
|
|
||||||
local unitType = string.lower(unitType or "")
|
unitType = string.lower(unitType or "")
|
||||||
local conversionType = config[unitType]
|
local conversionType = config[unitType]
|
||||||
|
|
||||||
if not conversionType then conversionType = "DDM" end
|
if not conversionType then conversionType = "DDM" end
|
||||||
@@ -429,6 +459,7 @@ 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)
|
||||||
|
|
||||||
@@ -440,7 +471,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
|
local minutes = (math.abs(dd) - degrees) * 60 --[[@as number]]
|
||||||
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
|
||||||
@@ -559,6 +590,7 @@ 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
|
||||||
@@ -571,10 +603,11 @@ 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)
|
||||||
for key, unit in pairs(players) do
|
for _, unit in pairs(players) do
|
||||||
units[#units + 1] = unit
|
units[#units + 1] = unit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -616,9 +649,9 @@ do -- INIT DCS_UTIL
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param unitName string
|
||||||
function DCS_UTIL.CleanCorpse(unitName)
|
function DCS_UTIL.CleanCorpse(unitName)
|
||||||
local unitName = "dead_" .. unitName
|
unitName = "dead_" .. unitName
|
||||||
|
|
||||||
local object = StaticObject.getByName(unitName)
|
local object = StaticObject.getByName(unitName)
|
||||||
|
|
||||||
if object then
|
if object then
|
||||||
@@ -632,11 +665,11 @@ do -- INIT DCS_UTIL
|
|||||||
---@field b number
|
---@field b number
|
||||||
---@field a number
|
---@field a number
|
||||||
|
|
||||||
local drawID = 4210
|
local __drawID = 4210
|
||||||
|
|
||||||
function DCS_UTIL.GetNextDrawID()
|
function DCS_UTIL.GetNextDrawID()
|
||||||
drawID = drawID + 1
|
__drawID = __drawID + 1
|
||||||
return drawID
|
return __drawID
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param groupID number
|
---@param groupID number
|
||||||
@@ -644,9 +677,9 @@ do -- INIT DCS_UTIL
|
|||||||
---@param location Vec3
|
---@param location Vec3
|
||||||
---@return number markID
|
---@return number markID
|
||||||
function DCS_UTIL.AddMarkToGroup(groupID, text, location)
|
function DCS_UTIL.AddMarkToGroup(groupID, text, location)
|
||||||
local drawID = DCS_UTIL.GetNextDrawID()
|
local nextId = DCS_UTIL.GetNextDrawID()
|
||||||
trigger.action.markToGroup(drawID, text, location, groupID, true, nil)
|
trigger.action.markToGroup(nextId, text, location, groupID, true, nil)
|
||||||
return drawID
|
return nextId
|
||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
@@ -654,9 +687,9 @@ do -- INIT DCS_UTIL
|
|||||||
---@param location Vec3
|
---@param location Vec3
|
||||||
---@return integer
|
---@return integer
|
||||||
function DCS_UTIL.AddMarkToAll(text, location)
|
function DCS_UTIL.AddMarkToAll(text, location)
|
||||||
local drawID = DCS_UTIL.GetNextDrawID()
|
local nextId = DCS_UTIL.GetNextDrawID()
|
||||||
trigger.action.markToAll(drawID, text, location, true, nil)
|
trigger.action.markToAll(nextId, text, location, true, nil)
|
||||||
return drawID
|
return nextId
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param markId number
|
---@param markId number
|
||||||
@@ -705,7 +738,7 @@ do -- INIT DCS_UTIL
|
|||||||
|
|
||||||
---@return number? id
|
---@return number? id
|
||||||
function DCS_UTIL.GetNeutralCountry()
|
function DCS_UTIL.GetNeutralCountry()
|
||||||
for name, id in pairs(country.id) do
|
for _, id in pairs(country.id) do
|
||||||
if coalition.getCountryCoalition(id) == DCS_UTIL.Coalition.NEUTRAL then
|
if coalition.getCountryCoalition(id) == DCS_UTIL.Coalition.NEUTRAL then
|
||||||
return id
|
return id
|
||||||
end
|
end
|
||||||
@@ -735,6 +768,8 @@ 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
|
||||||
@@ -759,7 +794,7 @@ do -- INIT DCS_UTIL
|
|||||||
function DCS_UTIL.GetPlayerGroupByGroupID(groupId)
|
function DCS_UTIL.GetPlayerGroupByGroupID(groupId)
|
||||||
for i = 0, 2 do
|
for i = 0, 2 do
|
||||||
local players = coalition.getPlayers(i)
|
local players = coalition.getPlayers(i)
|
||||||
for key, unit in pairs(players) do
|
for _, unit in pairs(players) do
|
||||||
if unit and unit:isExist() == true then
|
if unit and unit:isExist() == true then
|
||||||
local group = unit:getGroup()
|
local group = unit:getGroup()
|
||||||
if group and group:getID() == groupId then
|
if group and group:getID() == groupId then
|
||||||
@@ -775,7 +810,7 @@ do -- INIT DCS_UTIL
|
|||||||
function DCS_UTIL.GetPlayerUnitByID(unitID)
|
function DCS_UTIL.GetPlayerUnitByID(unitID)
|
||||||
for i = 0, 2 do
|
for i = 0, 2 do
|
||||||
local players = coalition.getPlayers(i)
|
local players = coalition.getPlayers(i)
|
||||||
for key, unit in pairs(players) do
|
for _, unit in pairs(players) do
|
||||||
if unit and unit:getID() == unitID then
|
if unit and unit:getID() == unitID then
|
||||||
return unit
|
return unit
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ 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,8 +1,12 @@
|
|||||||
|
|
||||||
---@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, warningMessage or "skip")
|
table.insert(MissionEditingWarnings.warnings, warningMessage or "skip")
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param logger Logger
|
---@param logger Logger
|
||||||
@@ -12,12 +16,12 @@ function MissionEditingWarnings.WriteAll(logger)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not MissionEditingWarnings or #MissionEditingWarnings == 0 then
|
if not MissionEditingWarnings.warnings or #MissionEditingWarnings.warnings == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
logger:warn("Mission Editor Warnings:")
|
logger:warn("Mission Editor Warnings:")
|
||||||
for _, warning in ipairs(MissionEditingWarnings) do
|
for _, warning in ipairs(MissionEditingWarnings.warnings) do
|
||||||
logger:warn("- " .. warning)
|
logger:warn("- " .. warning)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+45
-15
@@ -4,7 +4,7 @@ do -- INIT UTIL
|
|||||||
---splits a string in sub parts by separator
|
---splits a string in sub parts by separator
|
||||||
---@param input string
|
---@param input string
|
||||||
---@param separator string
|
---@param separator string
|
||||||
---@return table result list of strings
|
---@return Array<string> result list of strings
|
||||||
function UTIL.split_string(input, separator)
|
function UTIL.split_string(input, separator)
|
||||||
if separator == nil then
|
if separator == nil then
|
||||||
separator = " "
|
separator = " "
|
||||||
@@ -22,7 +22,7 @@ do -- INIT UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param table any
|
---@param table table<any, 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,23 +35,34 @@ 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
|
||||||
copy = {}
|
original = original --[[@as table<any, any>]]
|
||||||
for orig_key, orig_value in next, orig, nil do
|
copy = {} --[[@as table<any, any>]]
|
||||||
copy[UTIL.deepCopyTable(orig_key)] = UTIL.deepCopyTable(orig_value)
|
for orig_key, orig_value in pairs(original) do
|
||||||
|
local copiedKey = deepCopy(orig_key) --[[@as any]]
|
||||||
|
copy[copiedKey] = deepCopy(orig_value)
|
||||||
end
|
end
|
||||||
setmetatable(copy, UTIL.deepCopyTable(getmetatable(orig)))
|
setmetatable(copy, deepCopy(getmetatable(original)))
|
||||||
else -- number, string, boolean, etc
|
else -- number, string, boolean, etc
|
||||||
copy = orig
|
copy = original --[[@as any]]
|
||||||
end
|
end
|
||||||
return copy
|
return copy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return deepCopy(orig)
|
||||||
|
end
|
||||||
|
|
||||||
---Gets a random from the list
|
---Gets a random from the list
|
||||||
---@param list Array
|
---@generic T
|
||||||
---@return any @random element from the list
|
---@param list Array<T>
|
||||||
|
---@return T @random element from the list
|
||||||
function UTIL.randomFromList(list)
|
function UTIL.randomFromList(list)
|
||||||
local max = #list
|
local max = #list
|
||||||
|
|
||||||
@@ -65,11 +76,13 @@ do -- INIT UTIL
|
|||||||
return list[random]
|
return list[random]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param list Array
|
---@generic T
|
||||||
|
---@param list Array<T>
|
||||||
---@param start number start
|
---@param start number start
|
||||||
---@param n number length
|
---@param n number length
|
||||||
---@return Array
|
---@return Array<T>
|
||||||
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]
|
||||||
@@ -90,9 +103,10 @@ do -- INIT UTIL
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function table_print(tt, indent, done)
|
local function table_print(tt, indent, done)
|
||||||
done = done or {}
|
done = done or {} --[[@as table<any, boolean>]]
|
||||||
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
|
||||||
@@ -146,10 +160,10 @@ do -- INIT UTIL
|
|||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@param str string
|
---@param str string
|
||||||
---@param findableTable table
|
---@param findableTable table<any,any>
|
||||||
---@return boolean
|
---@return boolean
|
||||||
UTIL.startswithAny = function(str, findableTable)
|
UTIL.startswithAny = function(str, findableTable)
|
||||||
for key, value in pairs(findableTable) do
|
for _, value in pairs(findableTable) do
|
||||||
if type(value) == "string" and UTIL.startsWith(str, value) then return true end
|
if type(value) == "string" and UTIL.startsWith(str, value) then return true end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
@@ -238,7 +252,13 @@ do -- INIT UTIL
|
|||||||
return ((vec1Norm.x * vec2Norm.x) + (vec1Norm.y * vec2Norm.y) + (vec1Norm.z * vec2Norm.z))
|
return ((vec1Norm.x * vec2Norm.x) + (vec1Norm.y * vec2Norm.y) + (vec1Norm.z * vec2Norm.z))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param polygon Array<Vec2> of pairs { x, y }
|
||||||
|
---@param x number X location
|
||||||
|
---@param y number Y location
|
||||||
|
---@return boolean
|
||||||
local function isInComplexPolygon(polygon, x, y)
|
local function isInComplexPolygon(polygon, x, y)
|
||||||
|
---@param poly Array<Vec2> of pairs { x, y }
|
||||||
|
---@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
|
||||||
@@ -275,6 +295,7 @@ 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
|
||||||
@@ -291,6 +312,7 @@ 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
|
||||||
@@ -399,7 +421,9 @@ do -- INIT UTIL
|
|||||||
if #points == 0 then return {} end
|
if #points == 0 then return {} end
|
||||||
|
|
||||||
-- Simple clustering: group points that are within minSeparation of each other
|
-- Simple clustering: group points that are within minSeparation of each other
|
||||||
|
---@type Array<Array<Vec2>>
|
||||||
local clusters = {}
|
local clusters = {}
|
||||||
|
---@type table<integer, boolean>
|
||||||
local assigned = {}
|
local assigned = {}
|
||||||
|
|
||||||
for i, p in ipairs(points) do
|
for i, p in ipairs(points) do
|
||||||
@@ -440,6 +464,8 @@ 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 {}
|
||||||
@@ -517,6 +543,10 @@ 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)
|
||||||
|
|||||||
+1
-2
@@ -1,7 +1,6 @@
|
|||||||
--Single player purpose
|
--Single player purpose
|
||||||
|
|
||||||
local Logger = require("classes.util.Logger")
|
local Logger = require("classes.util.Logger")
|
||||||
local DcsUtil = require("classes.util.DcsUtil")
|
|
||||||
local Database = require("classes.spearhead_db")
|
local Database = require("classes.spearhead_db")
|
||||||
local SpearheadEvents = require("classes.spearhead_events")
|
local SpearheadEvents = require("classes.spearhead_events")
|
||||||
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
local MissionCommandsHelper = require("classes.stageClasses.helpers.MissionCommandsHelper")
|
||||||
@@ -47,7 +46,7 @@ local spawnManager = SpawnManager.new(spawnLogger)
|
|||||||
local detectionLogger = Logger.new("DetectionManager", defaultLogLevel)
|
local detectionLogger = Logger.new("DetectionManager", defaultLogLevel)
|
||||||
local detectionManager = DetectionManager.New(detectionLogger)
|
local detectionManager = DetectionManager.New(detectionLogger)
|
||||||
|
|
||||||
GlobalCapManager.start(databaseManager, capConfig, detectionManager, stageConfig, defaultLogLevel, spawnManager)
|
GlobalCapManager.start(databaseManager, capConfig, detectionManager, defaultLogLevel, spawnManager)
|
||||||
local globalStageManager = GlobalStageManager.new(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
local globalStageManager = GlobalStageManager.new(databaseManager, stageConfig, defaultLogLevel, spawnManager)
|
||||||
GlobalFleetManager.start(databaseManager)
|
GlobalFleetManager.start(databaseManager)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user