mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-07-16 22:22:25 +00:00
Compare commits
233 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf604da2ae | |||
| d8c2b8b719 | |||
| bca3abe2c2 | |||
| 3a06f6314e | |||
| 31075f7c04 | |||
| 6bf6b933cc | |||
| 5681244941 | |||
| e7f7199a39 | |||
| 788108c5b8 | |||
| 6e1dabfe9b | |||
| e48a823560 | |||
| 8f1e2a1d54 | |||
| 74d54637d5 | |||
| 1126b7753a | |||
| 3fbc76e37f | |||
| e24acb28f7 | |||
| 4e5b483cc0 | |||
| f28f807ee7 | |||
| 375a564446 | |||
| ab068670cc | |||
| c00da0f925 | |||
| 456c002c3c | |||
| 6161da3a22 | |||
| 038b89776d | |||
| 54e44299d8 | |||
| f71d6f3f30 | |||
| df6d968ebe | |||
| daae77def5 | |||
| 4d9197b3cc | |||
| b808f2f568 | |||
| 10dffb0689 | |||
| 91aa2eb9f2 | |||
| 722c33df62 | |||
| 3d697211bd | |||
| dc54cc82af | |||
| 4fced3416a | |||
| d4a46606fd | |||
| 015af9774c | |||
| f0a37172b9 | |||
| 2dd2e593e8 | |||
| 49fd78abe7 | |||
| 1b5067088f | |||
| 7c8cca7f56 | |||
| 2986a33a56 | |||
| 0658f6dc2b | |||
| ce6624fe0b | |||
| 75558078ee | |||
| 3ba868b3b9 | |||
| f6b5c69d4e | |||
| 85b10fb1c9 | |||
| a7f01eb04a | |||
| e578a673d9 | |||
| 65f9db8efa | |||
| 3f04249d07 | |||
| 2ebad9ce96 | |||
| b8a2b28462 | |||
| 9ccde838e7 | |||
| 6ba62e3e04 | |||
| b9cc66004d | |||
| fb1b5b209e | |||
| 17838e7fe7 | |||
| 9493570e6b | |||
| b0d0dbfe72 | |||
| 439c11c376 | |||
| 2d081dfc03 | |||
| a6c244f670 | |||
| 8c44cf8fca | |||
| 4a594f41b0 | |||
| ffea9708d1 | |||
| 04b4af58f7 | |||
| b108bd9ac6 | |||
| f44ba39ec5 | |||
| a54b785ca3 | |||
| 6c3f3cf0d2 | |||
| bd79750efa | |||
| 05df765c5c | |||
| 04a7c912ea | |||
| 39fc112e53 | |||
| 55fb8f2064 | |||
| 5dc5736976 | |||
| 1f23525799 | |||
| f390616e41 | |||
| 912c162eee | |||
| dfc7f17308 | |||
| c4e8ad50c8 | |||
| 652df5570a | |||
| bb8e6eb7a1 | |||
| 2efb6a624f | |||
| b7b369e78f | |||
| b1436b66d4 | |||
| d2107466cc | |||
| 3975e1961e | |||
| ca84fa11cd | |||
| 78ffaf6e0a | |||
| 7c3c39c1ba | |||
| ed614767e6 | |||
| 147f39981b | |||
| 6d94a0c776 | |||
| 80fdbc4960 | |||
| 81fd5cb605 | |||
| fc9ddae9b2 | |||
| b70bf3b9af | |||
| d0330cc696 | |||
| 250d640e76 | |||
| dca70eaa05 | |||
| 6a05789db5 | |||
| 5048201771 | |||
| 5e20874dca | |||
| 5e36425058 | |||
| bc16970d96 | |||
| 3f1ad24f6a | |||
| 674fef554d | |||
| f8f4bac77e | |||
| 3e2d312202 | |||
| 5aa8338c59 | |||
| 6ccfd499c8 | |||
| 468a8fed8b | |||
| 1362fe9019 | |||
| ef3127fdab | |||
| ba361e7eff | |||
| ab1e3e6c60 | |||
| 515764bb88 | |||
| 31fb9bc169 | |||
| 917f06fe04 | |||
| e5e81dbc35 | |||
| e95a9525c6 | |||
| c5f3bfe4a9 | |||
| 326d4b3135 | |||
| c4fad08d58 | |||
| 5a57d05fd6 | |||
| 5329745325 | |||
| 792222f567 | |||
| a8f14fca70 | |||
| 8a7fa326cd | |||
| 02105b1efc | |||
| 93fd9e5d42 | |||
| 65c384622c | |||
| 18afe9ad7a | |||
| d7b87b63d8 | |||
| 253cf0f5a5 | |||
| b5b079d75f | |||
| d0421f5226 | |||
| 79ddc01bf7 | |||
| c5a85456c0 | |||
| 9a383826e7 | |||
| 1e6731830e | |||
| c4b874e3f9 | |||
| d9aff32a36 | |||
| 8b04d32839 | |||
| 382605d4cf | |||
| 1337815f05 | |||
| 1cd3b6a26b | |||
| f34dcdb3db | |||
| e3b7a85956 | |||
| 655282a034 | |||
| 94dde73561 | |||
| 38cb8fb88e | |||
| ad5488784f | |||
| a4cdd62aff | |||
| 45008c9d57 | |||
| 92b0ab3c8d | |||
| 7074b70e86 | |||
| e15d335f3f | |||
| 840b14f4ce | |||
| 887f7aa3e9 | |||
| a8daf70dad | |||
| 9a9de9306e | |||
| 3e36e5f2b2 | |||
| cf824b912d | |||
| c3f5405288 | |||
| 084b47edb7 | |||
| 8d2e291deb | |||
| f84e2ede66 | |||
| 0a8782c890 | |||
| 3a432782b2 | |||
| 5dd32d92c0 | |||
| d96cc26cd8 | |||
| bda1fac923 | |||
| be5c1bed3b | |||
| ef40b1c524 | |||
| a4c81736aa | |||
| 2eafadcedf | |||
| 045c49679d | |||
| 6b4c08d53f | |||
| f40442d309 | |||
| 83bae9c2f7 | |||
| 944ef6332b | |||
| 1329cd23fd | |||
| fe7acecdd3 | |||
| 4471ec9b96 | |||
| 32e1d4f8fa | |||
| dbd78f35a4 | |||
| a2772c97d5 | |||
| 4f8e65b515 | |||
| 1d6437f9e2 | |||
| a733b17840 | |||
| 3adf6d635a | |||
| 2e9320df03 | |||
| d08219f9d9 | |||
| f929951dbe | |||
| 76a36cb9f9 | |||
| 56aebfbee8 | |||
| 747e5d801a | |||
| 29ed630536 | |||
| ffdcfa0129 | |||
| c5757ffd22 | |||
| 9cc08cb088 | |||
| 268b7ef80c | |||
| 172004b822 | |||
| 6aa4683080 | |||
| 2771e7f856 | |||
| 7c4dd8160d | |||
| 677a64c3dc | |||
| 1fdc50b0da | |||
| 56fcd8f37f | |||
| 09d4e155de | |||
| 65703d1092 | |||
| 2afd09b878 | |||
| f87a676e4b | |||
| 4ed2b0610d | |||
| cbd371b40f | |||
| 80e9cb692c | |||
| 3c74aef378 | |||
| 8bf56b8b1a | |||
| 7e2233d8c7 | |||
| 065717b2f5 | |||
| 63a524f25c | |||
| 838e11de05 | |||
| 2a56da4bb3 | |||
| f31741f934 | |||
| f84d02d8a1 | |||
| 7d3a08cde2 | |||
| 46258492bd |
@@ -0,0 +1,159 @@
|
||||
name: Moose-Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
|
||||
- name: Build informations
|
||||
run: |
|
||||
echo "Triggered by: ${{ github.event_name }}"
|
||||
echo "Running on: ${{ runner.os }}"
|
||||
echo "Ref: ${{ github.ref }}"
|
||||
echo "Branch name: ${{ steps.extract_branch.outputs.branch }}"
|
||||
echo "Repository: ${{ github.repository }}"
|
||||
echo "Commit-Id: ${{ github.sha }}"
|
||||
echo "Owner: ${{ github.repository_owner }}"
|
||||
echo "FORCE_PUSH: ${{ vars.FORCE_PUSH }}"
|
||||
|
||||
#########################################################################
|
||||
# Prepare build environment
|
||||
#########################################################################
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare build output folders
|
||||
run: |
|
||||
mkdir -p build/tools
|
||||
mkdir -p build/doc
|
||||
|
||||
- name: Checkout FlightControls modified luadocumentor
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: Applevangelist/luadocumentor
|
||||
path: './build/tools/luadocumentor'
|
||||
ref: 'patch-1'
|
||||
token: ${{ secrets.BOT_TOKEN }}
|
||||
|
||||
- name: Update apt-get (needed for act docker image)
|
||||
run: |
|
||||
sudo apt-get -qq update
|
||||
|
||||
- name: Install tree
|
||||
run: |
|
||||
sudo apt-get -qq install tree
|
||||
|
||||
#########################################################################
|
||||
# Install all prerequisites for LuaDocumentor
|
||||
#########################################################################
|
||||
- name: Install Lua
|
||||
run: |
|
||||
sudo apt-get -qq install lua5.1
|
||||
|
||||
- name: Install LuaRocks
|
||||
run: |
|
||||
sudo apt-get -qq install luarocks -y
|
||||
|
||||
- name: Install markdown (prereq for LuaDocumentor)
|
||||
run: |
|
||||
sudo luarocks install markdown 0.32-2
|
||||
|
||||
- name: Install penlight (prereq for LuaDocumentor)
|
||||
run: |
|
||||
sudo luarocks install penlight 1.11.0-1
|
||||
|
||||
- name: Install metalua-compiler (prereq for LuaDocumentor)
|
||||
run: |
|
||||
sudo luarocks install metalua-compiler 0.7.3-1
|
||||
|
||||
- name: Install metalua-parser (prereq for LuaDocumentor)
|
||||
run: |
|
||||
sudo luarocks install metalua-parser 0.7.3-2
|
||||
|
||||
- name: Install checks (prereq for LuaDocumentor)
|
||||
run: |
|
||||
sudo luarocks install checks
|
||||
|
||||
#########################################################################
|
||||
# Run LuaDocumentor
|
||||
#########################################################################
|
||||
- name: Run LuaDocumentor
|
||||
run: |
|
||||
lua luadocumentor.lua -d ${{ github.workspace }}/build/doc "${{ github.workspace }}/Moose Development/Moose"
|
||||
working-directory: ${{ github.workspace }}/build/tools/luadocumentor
|
||||
|
||||
#########################################################################
|
||||
# Replace <head> tag
|
||||
#########################################################################
|
||||
- name: Replace head tag
|
||||
run: |
|
||||
python3 "${{ github.workspace }}/Moose Development/docs-header.py"
|
||||
working-directory: ${{ github.workspace }}/build/doc
|
||||
|
||||
- name: Check replacement of head tag
|
||||
run: |
|
||||
head -10 ${{ github.workspace }}/build/doc/AI.AI_A2A_Cap.html
|
||||
|
||||
#########################################################################
|
||||
# Push to MOOSE_DOCS
|
||||
#########################################################################
|
||||
- name: Set docs repo for branch
|
||||
shell: bash
|
||||
id: set_doc_repo
|
||||
run: |
|
||||
if [[ $GITHUB_REF == 'refs/heads/master' ]]; then
|
||||
echo "docrepo=MOOSE_DOCS" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "docrepo=MOOSE_DOCS_DEVELOP" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Checkout ${{ steps.set_doc_repo.outputs.docrepo }} to folder MOOSE_DOCS
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/${{ steps.set_doc_repo.outputs.docrepo }}
|
||||
path: './build/MOOSE_DOCS'
|
||||
fetch-depth: 0
|
||||
ref: 'master'
|
||||
token: ${{ secrets.BOT_TOKEN }}
|
||||
|
||||
- name: Delete folder to remove deleted files
|
||||
run: |
|
||||
rm -rf ./build/MOOSE_DOCS/Documentation/
|
||||
|
||||
- name: Create target folder
|
||||
run: mkdir -p build/MOOSE_DOCS/Documentation
|
||||
|
||||
- name: Copy build result to MOOSE_DOCS
|
||||
run: |
|
||||
cp ./build/doc/*.* ./build/MOOSE_DOCS/Documentation/
|
||||
|
||||
- name: Push result to docs repository
|
||||
if: ${{ vars.FORCE_PUSH == 'true' }}
|
||||
run: |
|
||||
git config user.name "MooseBotter"
|
||||
git config user.email "MooseBotter@users.noreply.github.com"
|
||||
git add .
|
||||
git commit --allow-empty -m "Auto commit by GitHub Actions Workflow"
|
||||
git push --set-upstream origin master
|
||||
|
||||
working-directory: ${{ github.workspace }}/build/MOOSE_DOCS
|
||||
|
||||
#########################################################################
|
||||
# Show the results
|
||||
#########################################################################
|
||||
- name: List files in the repository
|
||||
run: |
|
||||
tree ${{ github.workspace }}/build
|
||||
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
@@ -0,0 +1,141 @@
|
||||
name: Moose-Includes
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
|
||||
- name: Build informations
|
||||
run: |
|
||||
echo "Triggered by: ${{ github.event_name }}"
|
||||
echo "Running on: ${{ runner.os }}"
|
||||
echo "Ref: ${{ github.ref }}"
|
||||
echo "Branch name: ${{ steps.extract_branch.outputs.branch }}"
|
||||
echo "Repository: ${{ github.repository }}"
|
||||
echo "Commit-Id: ${{ github.sha }}"
|
||||
echo "Owner: ${{ github.repository_owner }}"
|
||||
echo "FORCE_PUSH: ${{ vars.FORCE_PUSH }}"
|
||||
|
||||
#########################################################################
|
||||
# Prepare build environment
|
||||
#########################################################################
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare build output folders
|
||||
run: |
|
||||
mkdir -p build/result/Moose_Include_Dynamic
|
||||
mkdir -p build/result/Moose_Include_Static
|
||||
|
||||
- name: Update apt-get (needed for act docker image)
|
||||
run: |
|
||||
sudo apt-get -qq update
|
||||
|
||||
- name: Install tree
|
||||
run: |
|
||||
sudo apt-get -qq install tree
|
||||
|
||||
#########################################################################
|
||||
# Install all prerequisites
|
||||
#########################################################################
|
||||
- name: Install Lua 5.3
|
||||
run: |
|
||||
sudo apt-get -qq install lua5.3 -y
|
||||
- name: Check Lua version
|
||||
run: |
|
||||
lua -v
|
||||
|
||||
- name: Install LuaRocks
|
||||
run: |
|
||||
sudo apt-get -qq install luarocks -y
|
||||
- name: Check LuaRocks version
|
||||
run: |
|
||||
luarocks --version
|
||||
|
||||
- name: Install Lua 5.3 Dev for prerequisites for LuaSrcDiet
|
||||
run: |
|
||||
sudo apt-get -qq install liblua5.3-dev -y
|
||||
|
||||
- name: Install LuaSrcDiet
|
||||
run: |
|
||||
sudo luarocks install luasrcdiet
|
||||
|
||||
- name: Install LuaCheck
|
||||
run: |
|
||||
sudo luarocks install luacheck
|
||||
|
||||
#########################################################################
|
||||
# Build Include files
|
||||
#########################################################################
|
||||
- name: Build Include Static
|
||||
run: |
|
||||
export COMMIT_TIME=$(git show -s --format=%cd ${{ github.sha }} --date=iso-strict)
|
||||
lua5.3 "./Moose Setup/Moose_Create.lua" S "$COMMIT_TIME-${{ github.sha }}" "./Moose Development/Moose" "./Moose Setup" "./build/result/Moose_Include_Static"
|
||||
|
||||
- name: Build Includes Dynamic
|
||||
run: |
|
||||
export COMMIT_TIME=$(git show -s --format=%cd ${{ github.sha }} --date=iso-strict)
|
||||
lua5.3 "./Moose Setup/Moose_Create.lua" D "$COMMIT_TIME-${{ github.sha }}" "./Moose Development/Moose" "./Moose Setup" "./build/result/Moose_Include_Dynamic"
|
||||
|
||||
- name: Run LuaSrcDiet
|
||||
run: |
|
||||
luasrcdiet --basic --opt-emptylines ./build/result/Moose_Include_Static/Moose.lua -o ./build/result/Moose_Include_Static/Moose_.lua
|
||||
|
||||
#########################################################################
|
||||
# Run LuaCheck
|
||||
#########################################################################
|
||||
- name: Run LuaCheck
|
||||
if: ${{ vars.SKIP_LUACHECK != true }}
|
||||
continue-on-error: true
|
||||
run: |
|
||||
luacheck --std=lua51c --config=.luacheckrc -gurasqq "Moose Development/Moose"
|
||||
|
||||
#########################################################################
|
||||
# Push to MOOSE_INCLUDE
|
||||
#########################################################################
|
||||
- name: Checkout MOOSE_INCLUDE
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/MOOSE_INCLUDE
|
||||
path: './build/MOOSE_INCLUDE'
|
||||
fetch-depth: 0
|
||||
ref: ${{ steps.extract_branch.outputs.branch }}
|
||||
token: ${{ secrets.BOT_TOKEN }}
|
||||
|
||||
- name: Create target folder (needed if checkout is deactivated)
|
||||
run: mkdir -p build/MOOSE_INCLUDE
|
||||
|
||||
- name: Copy build reseult to MOOSE_INCLUDE
|
||||
run: |
|
||||
cp -r ./build/result/* ./build/MOOSE_INCLUDE/
|
||||
|
||||
- name: Push result to MOOSE_INCLUDE repository
|
||||
if: ${{ vars.FORCE_PUSH == 'true' }}
|
||||
run: |
|
||||
git config user.name "MooseBotter"
|
||||
git config user.email "MooseBotter@users.noreply.github.com"
|
||||
git add .
|
||||
git commit --allow-empty -m "Auto commit by GitHub Actions Workflow"
|
||||
git push --set-upstream origin ${{ steps.extract_branch.outputs.branch }}
|
||||
|
||||
working-directory: ${{ github.workspace }}/build/MOOSE_INCLUDE
|
||||
|
||||
#########################################################################
|
||||
# Show the results
|
||||
#########################################################################
|
||||
- name: List files in the repository
|
||||
run: |
|
||||
tree ${{ github.workspace }}/build
|
||||
|
||||
- run: echo "This job's status is ${{ job.status }}."
|
||||
@@ -0,0 +1,78 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
|
||||
name: Deploy Jekyll site to Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/workflows/pages.yml'
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
# Allow one concurrent deployment
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# Build job
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.1' # Not needed with a .ruby-version file
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
cache-version: 0 # Increment this number if you need to re-download cached gems
|
||||
working-directory: docs/
|
||||
- name: Setup Pages
|
||||
id: pages
|
||||
uses: actions/configure-pages@v3
|
||||
- name: Build with Jekyll
|
||||
# Outputs to the './_site' directory by default
|
||||
run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
|
||||
env:
|
||||
JEKYLL_ENV: production
|
||||
working-directory: docs/
|
||||
- name: Upload artifact
|
||||
# Automatically uploads an artifact from the './_site' directory by default
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
with:
|
||||
path: docs/_site/
|
||||
|
||||
# Deployment job
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
||||
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
needs: deploy
|
||||
steps:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
- run: npm install linkinator
|
||||
- run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --recurse
|
||||
+6
-5
@@ -227,11 +227,12 @@ pip-log.txt
|
||||
_gsdata_/
|
||||
|
||||
#GITHUB
|
||||
.gitattributes
|
||||
.gitignore
|
||||
Moose Test Missions/MOOSE_Test_Template.miz
|
||||
Moose Development/Moose/.vscode/launch.json
|
||||
MooseCodeWS.code-workspace
|
||||
.gitignore
|
||||
.gitignore
|
||||
/.gitignore
|
||||
|
||||
# Excludes for act (https://github.com/nektos/act)
|
||||
.secrets
|
||||
.env
|
||||
.actrc
|
||||
.vars
|
||||
|
||||
@@ -91,7 +91,12 @@
|
||||
-- An optional @{Core.Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{#AI_A2A_CAP.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_A2A_CAP
|
||||
|
||||
@@ -176,7 +176,12 @@
|
||||
-- Per one, two, three, four?
|
||||
--
|
||||
-- **The default grouping is 1. That means, that each spawned defender will act individually.**
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Authors: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons).
|
||||
|
||||
@@ -92,7 +92,12 @@
|
||||
-- An optional @{Core.Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_A2A_GCI
|
||||
|
||||
@@ -111,7 +111,12 @@
|
||||
-- When the AI is damaged, it is required that a new Patrol is started. However, damage cannon be foreseen early on.
|
||||
-- Therefore, when the damage threshold is reached, the AI will return immediately to the home base (RTB).
|
||||
-- Use the method @{#AI_A2A_PATROL.ManageDamage}() to have this proces in place.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_A2A_PATROL
|
||||
|
||||
@@ -15,7 +15,12 @@
|
||||
-- @extends AI.AI_A2A_Engage#AI_A2A_Engage -- TODO: Documentation. This class does not exist, unable to determine what it extends.
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_A2G_BAI
|
||||
|
||||
@@ -15,7 +15,12 @@
|
||||
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL TODO: Documentation. This class does not exist, unable to determine what it extends.
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_A2G_CAS
|
||||
|
||||
@@ -253,7 +253,12 @@
|
||||
--
|
||||
-- **The default grouping is 1. That means, that each spawned defender will act individually.**
|
||||
-- But you can specify a number between 1 and 4, so that the defenders will act as a group.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons).
|
||||
|
||||
@@ -68,7 +68,12 @@
|
||||
-- An optional @{Core.Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageZone}() to define that Zone. -- TODO: Documentation. Check that this is actually correct. The originally referenced class does not exist.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_A2G_SEAD
|
||||
|
||||
@@ -45,7 +45,12 @@
|
||||
-- * **Start**: Start the transport process.
|
||||
-- * **Stop**: Stop the transport process.
|
||||
-- * **Monitor**: Monitor and take action.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_AIR
|
||||
AI_AIR = {
|
||||
ClassName = "AI_AIR",
|
||||
|
||||
@@ -883,6 +883,11 @@ do -- AI_AIR_DISPATCHER
|
||||
-- However, the squadron will still stay alive. Any airplane that is airborne will continue its operations until all airborne airplanes
|
||||
-- of the squadron will be destroyed. This to keep consistency of air operations not to confuse the players.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_AIR_DISPATCHER
|
||||
AI_AIR_DISPATCHER = {
|
||||
ClassName = "AI_AIR_DISPATCHER",
|
||||
|
||||
@@ -68,7 +68,12 @@
|
||||
-- An optional @{Core.Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI.AI_CAP#AI_AIR_ENGAGE.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_AIR_ENGAGE
|
||||
|
||||
@@ -88,7 +88,12 @@
|
||||
-- An optional @{Core.Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI.AI_CAP#AI_AIR_PATROL.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_AIR_PATROL
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
|
||||
|
||||
--- Implements the core functions modeling squadrons for airplanes and helicopters.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_AIR_SQUADRON
|
||||
|
||||
@@ -130,7 +130,12 @@
|
||||
-- AIBAIZone:SearchOff()
|
||||
--
|
||||
-- Searching can be switched back on with the method @{#AI_BAI_ZONE.SearchOn}(). Use the method @{#AI_BAI_ZONE.SearchOnOff}() to flexibily switch searching on or off.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_BAI_ZONE
|
||||
|
||||
@@ -85,7 +85,12 @@
|
||||
--
|
||||
-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return,
|
||||
-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_BALANCER
|
||||
AI_BALANCER = {
|
||||
ClassName = "AI_BALANCER",
|
||||
|
||||
@@ -112,7 +112,12 @@
|
||||
-- An optional @{Core.Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{#AI_CAP_ZONE.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CAP_ZONE
|
||||
|
||||
@@ -118,7 +118,12 @@
|
||||
-- * **@{#AI_CAS_ZONE.Destroy}**: The AI has destroyed a target @{Wrapper.Unit}.
|
||||
-- * **@{#AI_CAS_ZONE.Destroyed}**: The AI has destroyed all target @{Wrapper.Unit}s assigned in the CAS task.
|
||||
-- * **Status**: The AI is checking status (fuel and damage). When the thresholds have been reached, the AI will RTB.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CAS_ZONE
|
||||
|
||||
@@ -25,7 +25,12 @@
|
||||
-- * @{AI.AI_Cargo_APC} - Cargo transportation using APCs and other vehicles between zones.
|
||||
-- * @{AI.AI_Cargo_Helicopter} - Cargo transportation using helicopters between zones.
|
||||
-- * @{AI.AI_Cargo_Airplane} - Cargo transportation using airplanes to and from airbases.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_CARGO
|
||||
AI_CARGO = {
|
||||
ClassName = "AI_CARGO",
|
||||
|
||||
@@ -75,7 +75,12 @@
|
||||
-- Using the @{#AI_CARGO_APC.Pickup}() method, you are able to direct the APCs towards a point on the battlefield to board/load the cargo at the specific coordinate.
|
||||
-- The APCs will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
--
|
||||
-- @field #AI_CARGO_APC
|
||||
AI_CARGO_APC = {
|
||||
|
||||
@@ -41,7 +41,12 @@
|
||||
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
|
||||
-- time is not so much of an issue ...
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_CARGO_AIRPLANE
|
||||
AI_CARGO_AIRPLANE = {
|
||||
ClassName = "AI_CARGO_AIRPLANE",
|
||||
|
||||
@@ -100,7 +100,12 @@
|
||||
--
|
||||
-- Yes, please ensure that the zones are declared using the @{Core.Zone} classes.
|
||||
-- Possible zones that function at the moment are ZONE, ZONE_GROUP, ZONE_UNIT, ZONE_POLYGON.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
|
||||
@@ -137,7 +137,12 @@
|
||||
-- Use @{#AI_CARGO_DISPATCHER_APC.SetHomeZone}() to specify the home zone.
|
||||
--
|
||||
-- If no home zone is specified, the APCs will wait near the deploy zone for a new pickup command.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CARGO_DISPATCHER_APC
|
||||
|
||||
@@ -108,7 +108,12 @@
|
||||
--
|
||||
-- **There are a lot of templates available that allows you to quickly setup an event handler for a specific event type!**
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
--
|
||||
-- @field #AI_CARGO_DISPATCHER_AIRPLANE
|
||||
AI_CARGO_DISPATCHER_AIRPLANE = {
|
||||
|
||||
@@ -140,7 +140,12 @@
|
||||
-- Use @{#AI_CARGO_DISPATCHER_HELICOPTER.SetHomeZone}() to specify the home zone.
|
||||
--
|
||||
-- If no home zone is specified, the helicopters will wait near the deploy zone for a new pickup command.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CARGO_DISPATCHER_HELICOPTER
|
||||
|
||||
@@ -130,7 +130,12 @@
|
||||
-- Use @{#AI_CARGO_DISPATCHER_SHIP.SetHomeZone}() to specify the home zone.
|
||||
--
|
||||
-- If no home zone is specified, the Ship will wait near the deploy zone for a new pickup command.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CARGO_DISPATCHER_SHIP
|
||||
|
||||
@@ -41,7 +41,12 @@
|
||||
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
|
||||
-- time is not so much of an issue ...
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CARGO_HELICOPTER
|
||||
|
||||
@@ -54,7 +54,12 @@
|
||||
-- Using the @{#AI_CARGO_SHIP.Pickup}() method, you are able to direct the Ship towards a Pickup zone to board/load the cargo at the specified
|
||||
-- coordinate. The Ship will follow the Shipping Lane to ensure consistent cargo transportation within the simulation environment.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_CARGO_SHIP
|
||||
AI_CARGO_SHIP = {
|
||||
ClassName = "AI_CARGO_SHIP",
|
||||
|
||||
@@ -147,8 +147,8 @@
|
||||
-- @image Escorting.JPG
|
||||
|
||||
|
||||
|
||||
--- @type AI_ESCORT
|
||||
---
|
||||
-- @type AI_ESCORT
|
||||
-- @extends AI.AI_Formation#AI_FORMATION
|
||||
|
||||
|
||||
@@ -168,11 +168,18 @@
|
||||
--
|
||||
-- -- First find the GROUP object and the CLIENT object.
|
||||
-- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor.
|
||||
-- local EscortGroup = GROUP:FindByName( "Group Name" ) -- The Group Name is the name of the group that will escort the Escort Client.
|
||||
-- local EscortGroup = SET_GROUP:New():FilterPrefixes("Escort"):FilterOnce() -- The the group name of the escorts contains "Escort".
|
||||
--
|
||||
-- -- Now use these 2 objects to construct the new EscortPlanes object.
|
||||
-- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
|
||||
--
|
||||
-- EscortPlanes:MenusAirplanes() -- create menus for airplanes
|
||||
-- EscortPlanes:__Start(2)
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_ESCORT
|
||||
AI_ESCORT = {
|
||||
ClassName = "AI_ESCORT",
|
||||
@@ -189,7 +196,7 @@ AI_ESCORT = {
|
||||
TaskPoints = {}
|
||||
}
|
||||
|
||||
--- @field Functional.Detection#DETECTION_AREAS
|
||||
-- @field Functional.Detection#DETECTION_AREAS
|
||||
AI_ESCORT.Detection = nil
|
||||
|
||||
--- MENUPARAM type
|
||||
@@ -211,10 +218,14 @@ AI_ESCORT.Detection = nil
|
||||
--
|
||||
-- -- First find the GROUP object and the CLIENT object.
|
||||
-- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor.
|
||||
-- local EscortGroup = GROUP:FindByName( "Group Name" ) -- The Group Name is the name of the group that will escort the Escort Client.
|
||||
-- local EscortGroup = SET_GROUP:New():FilterPrefixes("Escort"):FilterOnce() -- The the group name of the escorts contains "Escort".
|
||||
--
|
||||
-- -- Now use these 2 objects to construct the new EscortPlanes object.
|
||||
-- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
|
||||
-- EscortPlanes:MenusAirplanes() -- create menus for airplanes
|
||||
-- EscortPlanes:__Start(2)
|
||||
--
|
||||
--
|
||||
function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
|
||||
|
||||
local self = BASE:Inherit( self, AI_FORMATION:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) ) -- #AI_ESCORT
|
||||
@@ -227,10 +238,17 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
|
||||
self.EscortGroupSet = EscortGroupSet
|
||||
|
||||
self.EscortGroupSet:SetSomeIteratorLimit( 8 )
|
||||
|
||||
|
||||
self.EscortBriefing = EscortBriefing
|
||||
|
||||
self.Menu = {}
|
||||
self.Menu.HoldAtEscortPosition = self.Menu.HoldAtEscortPosition or {}
|
||||
self.Menu.HoldAtLeaderPosition = self.Menu.HoldAtLeaderPosition or {}
|
||||
self.Menu.Flare = self.Menu.Flare or {}
|
||||
self.Menu.Smoke = self.Menu.Smoke or {}
|
||||
self.Menu.Targets = self.Menu.Targets or {}
|
||||
self.Menu.ROE = self.Menu.ROE or {}
|
||||
self.Menu.ROT = self.Menu.ROT or {}
|
||||
|
||||
-- if not EscortBriefing then
|
||||
-- EscortGroup:MessageToClient( EscortGroup:GetCategoryName() .. " '" .. EscortName .. "' (" .. EscortGroup:GetCallsign() .. ") reporting! " ..
|
||||
@@ -250,7 +268,7 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
|
||||
|
||||
|
||||
EscortGroupSet:ForEachGroup(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
-- Set EscortGroup known at EscortUnit.
|
||||
if not self.PlayerUnit._EscortGroups then
|
||||
@@ -325,14 +343,14 @@ function AI_ESCORT:_InitEscortRoute( EscortGroup )
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||
function AI_ESCORT:onafterStart( EscortGroupSet )
|
||||
|
||||
self:F()
|
||||
|
||||
EscortGroupSet:ForEachGroup(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
EscortGroup:WayPointInitialize()
|
||||
|
||||
@@ -370,7 +388,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
|
||||
self:_InitFlightMenus()
|
||||
|
||||
self.EscortGroupSet:ForSomeGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
|
||||
self:_InitEscortMenus( EscortGroup )
|
||||
@@ -378,7 +396,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
|
||||
|
||||
self:SetFlightModeFormation( EscortGroup )
|
||||
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function EscortGroup:OnEventDeadOrCrash( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
@@ -394,14 +412,14 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||
function AI_ESCORT:onafterStop( EscortGroupSet )
|
||||
|
||||
self:F()
|
||||
|
||||
EscortGroupSet:ForEachGroup(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
EscortGroup:WayPointInitialize()
|
||||
|
||||
@@ -550,7 +568,7 @@ function AI_ESCORT:SetFlightMenuFormation( Formation )
|
||||
local MenuFlightFormationID = MENU_GROUP_COMMAND:New( self.PlayerGroup, Formation, FlightMenuFormation,
|
||||
function ( self, Formation, ... )
|
||||
self.EscortGroupSet:ForSomeGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup, self, Formation, Arguments )
|
||||
if EscortGroup:IsAir() then
|
||||
self:E({FormationID=FormationID})
|
||||
@@ -764,7 +782,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuHoldAtEscortPosition()
|
||||
|
||||
for _, MenuHoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition ) do
|
||||
for _, MenuHoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition or {} ) do
|
||||
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
|
||||
|
||||
local FlightMenuHoldPosition = MENU_GROUP_COMMAND
|
||||
@@ -785,7 +803,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuHoldAtEscortPosition( EscortGroup )
|
||||
|
||||
for _, HoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition ) do
|
||||
for _, HoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition or {}) do
|
||||
if EscortGroup:IsAir() then
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
local EscortMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", EscortGroup.EscortMenu )
|
||||
@@ -853,7 +871,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuHoldAtLeaderPosition()
|
||||
|
||||
for _, MenuHoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition ) do
|
||||
for _, MenuHoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition or {}) do
|
||||
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
|
||||
|
||||
local FlightMenuHoldAtLeaderPosition = MENU_GROUP_COMMAND
|
||||
@@ -874,7 +892,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuHoldAtLeaderPosition( EscortGroup )
|
||||
|
||||
for _, HoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition ) do
|
||||
for _, HoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition or {}) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -999,7 +1017,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuFlare()
|
||||
|
||||
for _, MenuFlare in pairs( self.Menu.Flare) do
|
||||
for _, MenuFlare in pairs( self.Menu.Flare or {}) do
|
||||
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
|
||||
local FlightMenuFlare = MENU_GROUP:New( self.PlayerGroup, MenuFlare.MenuText, FlightMenuReportNavigation )
|
||||
|
||||
@@ -1014,7 +1032,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuFlare( EscortGroup )
|
||||
|
||||
for _, MenuFlare in pairs( self.Menu.Flare) do
|
||||
for _, MenuFlare in pairs( self.Menu.Flare or {}) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1059,7 +1077,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuSmoke()
|
||||
|
||||
for _, MenuSmoke in pairs( self.Menu.Smoke) do
|
||||
for _, MenuSmoke in pairs( self.Menu.Smoke or {}) do
|
||||
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
|
||||
local FlightMenuSmoke = MENU_GROUP:New( self.PlayerGroup, MenuSmoke.MenuText, FlightMenuReportNavigation )
|
||||
|
||||
@@ -1076,7 +1094,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuSmoke( EscortGroup )
|
||||
|
||||
for _, MenuSmoke in pairs( self.Menu.Smoke) do
|
||||
for _, MenuSmoke in pairs( self.Menu.Smoke or {}) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1169,7 +1187,7 @@ function AI_ESCORT:SetFlightMenuTargets()
|
||||
local FlightMenuAttackNearbyAir = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest airborne targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Air ):SetTag( "Attack" )
|
||||
local FlightMenuAttackNearbyGround = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest ground targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Ground ):SetTag( "Attack" )
|
||||
|
||||
for _, MenuTargets in pairs( self.Menu.Targets) do
|
||||
for _, MenuTargets in pairs( self.Menu.Targets or {}) do
|
||||
MenuTargets.FlightReportTargetsScheduler = SCHEDULER:New( self, self._FlightReportTargetsScheduler, {}, MenuTargets.Interval, MenuTargets.Interval )
|
||||
end
|
||||
|
||||
@@ -1179,7 +1197,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuTargets( EscortGroup )
|
||||
|
||||
for _, MenuTargets in pairs( self.Menu.Targets) do
|
||||
for _, MenuTargets in pairs( self.Menu.Targets or {} or {}) do
|
||||
if EscortGroup:IsAir() then
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
--local EscortMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", EscortGroup.EscortMenu )
|
||||
@@ -1231,7 +1249,7 @@ function AI_ESCORT:MenuAssistedAttack()
|
||||
self:F()
|
||||
|
||||
self.EscortGroupSet:ForSomeGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if not EscortGroup:IsAir() then
|
||||
-- Request assistance from other escorts.
|
||||
@@ -1246,7 +1264,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuROE()
|
||||
|
||||
for _, MenuROE in pairs( self.Menu.ROE) do
|
||||
for _, MenuROE in pairs( self.Menu.ROE or {}) do
|
||||
local FlightMenuROE = MENU_GROUP:New( self.PlayerGroup, "Rule Of Engagement", self.FlightMenu )
|
||||
|
||||
local FlightMenuROEHoldFire = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Hold fire", FlightMenuROE, AI_ESCORT._FlightROEHoldFire, self, "Holding weapons!" )
|
||||
@@ -1261,7 +1279,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuROE( EscortGroup )
|
||||
|
||||
for _, MenuROE in pairs( self.Menu.ROE) do
|
||||
for _, MenuROE in pairs( self.Menu.ROE or {}) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1302,7 +1320,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuROT()
|
||||
|
||||
for _, MenuROT in pairs( self.Menu.ROT) do
|
||||
for _, MenuROT in pairs( self.Menu.ROT or {}) do
|
||||
local FlightMenuROT = MENU_GROUP:New( self.PlayerGroup, "Reaction On Threat", self.FlightMenu )
|
||||
|
||||
local FlightMenuROTNoReaction = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Fight until death", FlightMenuROT, AI_ESCORT._FlightROTNoReaction, self, "Fighting until death!" )
|
||||
@@ -1317,7 +1335,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuROT( EscortGroup )
|
||||
|
||||
for _, MenuROT in pairs( self.Menu.ROT) do
|
||||
for _, MenuROT in pairs( self.Menu.ROT or {}) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1375,7 +1393,7 @@ function AI_ESCORT:SetEscortMenuResumeMission( EscortGroup )
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP OrbitGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param #number OrbitHeight
|
||||
@@ -1419,7 +1437,7 @@ function AI_ESCORT:_HoldPosition( OrbitGroup, EscortGroup, OrbitHeight, OrbitSec
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP OrbitGroup
|
||||
-- @param #number OrbitHeight
|
||||
-- @param #number OrbitSeconds
|
||||
@@ -1428,7 +1446,7 @@ function AI_ESCORT:_FlightHoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds )
|
||||
local EscortUnit = self.PlayerUnit
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup, OrbitGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
if OrbitGroup == nil then
|
||||
@@ -1456,7 +1474,7 @@ end
|
||||
function AI_ESCORT:_FlightJoinUp()
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_JoinUp( EscortGroup )
|
||||
@@ -1483,7 +1501,7 @@ end
|
||||
function AI_ESCORT:_FlightFormationTrail( XStart, XSpace, YStart )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_EscortFormationTrail( EscortGroup, XStart, XSpace, YStart )
|
||||
@@ -1510,7 +1528,7 @@ end
|
||||
function AI_ESCORT:_FlightFormationStack( XStart, XSpace, YStart, YSpace )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_EscortFormationStack( EscortGroup, XStart, XSpace, YStart, YSpace )
|
||||
@@ -1533,7 +1551,7 @@ end
|
||||
function AI_ESCORT:_FlightFlare( Color, Message )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_Flare( EscortGroup, Color, Message )
|
||||
@@ -1556,7 +1574,7 @@ end
|
||||
function AI_ESCORT:_FlightSmoke( Color, Message )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_Smoke( EscortGroup, Color, Message )
|
||||
@@ -1587,7 +1605,7 @@ end
|
||||
function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets )
|
||||
@@ -1679,7 +1697,7 @@ function AI_ESCORT:_ScanTargets( ScanDuration )
|
||||
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param #AI_ESCORT self
|
||||
function AI_ESCORT.___Resume( EscortGroup, self )
|
||||
|
||||
@@ -1701,7 +1719,7 @@ function AI_ESCORT.___Resume( EscortGroup, self )
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param #number WayPoint
|
||||
function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint )
|
||||
@@ -1723,7 +1741,7 @@ function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint )
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item.
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
|
||||
@@ -1743,7 +1761,7 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = EscortGroup:TaskAttackUnit( DetectedUnit )
|
||||
@@ -1767,7 +1785,7 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
|
||||
local Tasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
|
||||
@@ -1795,7 +1813,7 @@ end
|
||||
function AI_ESCORT:_FlightAttackTarget( DetectedItem )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup, DetectedItem )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_AttackTarget( EscortGroup, DetectedItem )
|
||||
@@ -1842,7 +1860,7 @@ end
|
||||
|
||||
|
||||
---
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item.
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem )
|
||||
@@ -1854,7 +1872,7 @@ function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem )
|
||||
local Tasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
|
||||
@@ -1881,7 +1899,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROEHoldFire( EscortROEMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROE( EscortGroup, EscortGroup.OptionROEHoldFire, EscortROEMessage )
|
||||
end
|
||||
@@ -1890,7 +1908,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROEOpenFire( EscortROEMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROE( EscortGroup, EscortGroup.OptionROEOpenFire, EscortROEMessage )
|
||||
end
|
||||
@@ -1899,7 +1917,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROEReturnFire( EscortROEMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROE( EscortGroup, EscortGroup.OptionROEReturnFire, EscortROEMessage )
|
||||
end
|
||||
@@ -1908,7 +1926,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROEWeaponFree( EscortROEMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROE( EscortGroup, EscortGroup.OptionROEWeaponFree, EscortROEMessage )
|
||||
end
|
||||
@@ -1924,7 +1942,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROTNoReaction( EscortROTMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROT( EscortGroup, EscortGroup.OptionROTNoReaction, EscortROTMessage )
|
||||
end
|
||||
@@ -1933,7 +1951,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROTPassiveDefense( EscortROTMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROT( EscortGroup, EscortGroup.OptionROTPassiveDefense, EscortROTMessage )
|
||||
end
|
||||
@@ -1942,7 +1960,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROTEvadeFire( EscortROTMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROT( EscortGroup, EscortGroup.OptionROTEvadeFire, EscortROTMessage )
|
||||
end
|
||||
@@ -1951,7 +1969,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROTVertical( EscortROTMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROT( EscortGroup, EscortGroup.OptionROTVertical, EscortROTMessage )
|
||||
end
|
||||
@@ -2178,5 +2196,3 @@ function AI_ESCORT:_FlightReportTargetsScheduler()
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,12 @@
|
||||
|
||||
|
||||
--- Models the automatic assignment of AI escorts to player flights.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_ESCORT_DISPATCHER
|
||||
|
||||
@@ -20,7 +20,12 @@
|
||||
|
||||
|
||||
--- Models the assignment of AI escorts to player flights upon request using the radio menu.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_ESCORT_DISPATCHER_REQUEST
|
||||
|
||||
@@ -136,7 +136,12 @@
|
||||
--
|
||||
-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint.
|
||||
-- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Authors: **FlightControl**
|
||||
|
||||
@@ -92,7 +92,12 @@
|
||||
-- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" )
|
||||
-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 )
|
||||
-- LargeFormation:__Start( 1 )
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_FORMATION
|
||||
AI_FORMATION = {
|
||||
ClassName = "AI_FORMATION",
|
||||
|
||||
@@ -144,7 +144,12 @@
|
||||
-- When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on.
|
||||
-- Therefore, when the damage threshold is reached, the AI will return immediately to the home base (RTB).
|
||||
-- Use the method @{#AI_PATROL_ZONE.ManageDamage}() to have this process in place.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_PATROL_ZONE
|
||||
|
||||
@@ -54,6 +54,11 @@ do -- ACT_ACCOUNT
|
||||
-- The state transition method needs to start with the name **OnAfter + the name of the state**.
|
||||
-- These state transition methods need to provide a return value, which is specified at the function description.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @type ACT_ACCOUNT
|
||||
-- @field Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @extends Core.Fsm#FSM_PROCESS
|
||||
|
||||
@@ -51,7 +51,12 @@
|
||||
-- * **After** the state transition.
|
||||
-- The state transition method needs to start with the name **OnAfter + the name of the state**.
|
||||
-- These state transition methods need to provide a return value, which is specified at the function description.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 1) @{#ACT_ASSIGN_ACCEPT} class, extends @{Core.Fsm.Assign#ACT_ASSIGN}
|
||||
|
||||
@@ -57,7 +57,12 @@
|
||||
-- # 1.1) ACT_ASSIST_SMOKE_TARGETS_ZONE constructor:
|
||||
--
|
||||
-- * @{#ACT_ASSIST_SMOKE_TARGETS_ZONE.New}(): Creates a new ACT_ASSIST_SMOKE_TARGETS_ZONE object.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Actions.Act_Assist
|
||||
|
||||
@@ -69,7 +69,12 @@
|
||||
-- # 1.1) ACT_ROUTE_ZONE constructor:
|
||||
--
|
||||
-- * @{#ACT_ROUTE_ZONE.New}(): Creates a new ACT_ROUTE_ZONE object.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Actions.Act_Route
|
||||
|
||||
@@ -233,7 +233,12 @@
|
||||
-- Note that this option is optional, so can be omitted. The default value of the RR is 250 meters.
|
||||
-- * **NR=** Provide the maximum range in meters when the cargo units will be boarded within the carrier during boarding.
|
||||
-- Note that this option is optional, so can be omitted. The default value of the RR is 10 meters.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
|
||||
@@ -36,7 +36,12 @@ do -- CARGO_CRATE
|
||||
--
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players.
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #CARGO_CRATE
|
||||
|
||||
@@ -38,7 +38,12 @@ do -- CARGO_GROUP
|
||||
--
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players.
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #CARGO_GROUP CARGO_GROUP
|
||||
--
|
||||
CARGO_GROUP = {
|
||||
|
||||
@@ -29,7 +29,12 @@ do -- CARGO_SLINGLOAD
|
||||
--
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players.
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #CARGO_SLINGLOAD
|
||||
|
||||
@@ -27,7 +27,12 @@ do -- CARGO_UNIT
|
||||
-- Note that ground forces behave in a group, and thus, act in formation, regardless if one unit is commanded to move.
|
||||
--
|
||||
-- This class is used in CARGO_GROUP, and is not meant to be used by mission designers individually.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #CARGO_UNIT CARGO_UNIT
|
||||
|
||||
@@ -34,7 +34,8 @@ local _TraceClassMethod = {}
|
||||
|
||||
local _ClassID = 0
|
||||
|
||||
--- @type BASE
|
||||
---
|
||||
-- @type BASE
|
||||
-- @field ClassName The name of the class.
|
||||
-- @field ClassID The ID number of the class.
|
||||
-- @field ClassNameAndID The name of the class concatenated with the ID number of the class.
|
||||
@@ -201,10 +202,10 @@ BASE = {
|
||||
Scheduler = nil,
|
||||
}
|
||||
|
||||
--- @field #BASE.__
|
||||
-- @field #BASE.__
|
||||
BASE.__ = {}
|
||||
|
||||
--- @field #BASE._
|
||||
-- @field #BASE._
|
||||
BASE._ = {
|
||||
Schedules = {}, --- Contains the Schedulers Active
|
||||
}
|
||||
@@ -229,7 +230,7 @@ FORMATION = {
|
||||
-- @param #BASE self
|
||||
-- @return #BASE
|
||||
function BASE:New()
|
||||
--local self = routines.utils.deepCopy( self ) -- Create a new self instance
|
||||
--local self = UTILS.DeepCopy( self ) -- Create a new self instance
|
||||
local self = UTILS.DeepCopy(self)
|
||||
|
||||
_ClassID = _ClassID + 1
|
||||
@@ -252,7 +253,7 @@ end
|
||||
function BASE:Inherit( Child, Parent )
|
||||
|
||||
-- Create child.
|
||||
local Child = routines.utils.deepCopy( Child )
|
||||
local Child = UTILS.DeepCopy( Child )
|
||||
|
||||
if Child ~= nil then
|
||||
|
||||
@@ -1167,7 +1168,7 @@ function BASE:_F( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
|
||||
if DebugInfoFrom then
|
||||
LineFrom = DebugInfoFrom.currentline
|
||||
end
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "F", self.ClassName, self.ClassID, Function, routines.utils.oneLineSerialize( Arguments ) ) )
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "F", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1241,7 +1242,7 @@ function BASE:_T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
|
||||
if DebugInfoFrom then
|
||||
LineFrom = DebugInfoFrom.currentline
|
||||
end
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s", LineCurrent, LineFrom, "T", self.ClassName, self.ClassID, routines.utils.oneLineSerialize( Arguments ) ) )
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s", LineCurrent, LineFrom, "T", self.ClassName, self.ClassID, UTILS.BasicSerialize( Arguments ) ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1311,9 +1312,9 @@ function BASE:E( Arguments )
|
||||
LineFrom = DebugInfoFrom.currentline
|
||||
end
|
||||
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "E", self.ClassName, self.ClassID, Function, routines.utils.oneLineSerialize( Arguments ) ) )
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "E", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
||||
else
|
||||
env.info( string.format( "%1s:%30s%05d(%s)", "E", self.ClassName, self.ClassID, routines.utils.oneLineSerialize( Arguments ) ) )
|
||||
env.info( string.format( "%1s:%30s%05d(%s)", "E", self.ClassName, self.ClassID, UTILS.BasicSerialize( Arguments ) ) )
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1338,9 +1339,9 @@ function BASE:I( Arguments )
|
||||
LineFrom = DebugInfoFrom.currentline
|
||||
end
|
||||
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "I", self.ClassName, self.ClassID, Function, routines.utils.oneLineSerialize( Arguments ) ) )
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "I", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
||||
else
|
||||
env.info( string.format( "%1s:%30s%05d(%s)", "I", self.ClassName, self.ClassID, routines.utils.oneLineSerialize( Arguments ) ) )
|
||||
env.info( string.format( "%1s:%30s%05d(%s)", "I", self.ClassName, self.ClassID, UTILS.BasicSerialize( Arguments ) ) )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
--
|
||||
-- @module Core.ClientMenu
|
||||
-- @image Core_Menu.JPG
|
||||
-- last change: July 2023
|
||||
-- last change: Sept 2023
|
||||
|
||||
-- TODO
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
@@ -35,6 +35,7 @@
|
||||
-- @field #string lid Lid for log entries
|
||||
-- @field #string version Version string
|
||||
-- @field #string name Name
|
||||
-- @field #string groupname Group name
|
||||
-- @field #table path
|
||||
-- @field #table parentpath
|
||||
-- @field #CLIENTMENU Parent
|
||||
@@ -57,7 +58,7 @@
|
||||
CLIENTMENU = {
|
||||
ClassName = "CLIENTMENUE",
|
||||
lid = "",
|
||||
version = "0.1.0",
|
||||
version = "0.1.1",
|
||||
name = nil,
|
||||
path = nil,
|
||||
group = nil,
|
||||
@@ -68,6 +69,7 @@ CLIENTMENU = {
|
||||
Generic = false,
|
||||
debug = false,
|
||||
Controller = nil,
|
||||
groupname = nil,
|
||||
}
|
||||
|
||||
---
|
||||
@@ -91,6 +93,7 @@ function CLIENTMENU:NewEntry(Client,Text,Parent,Function,...)
|
||||
self.group = Client:GetGroup()
|
||||
self.client = Client
|
||||
self.GroupID = self.group:GetID()
|
||||
self.groupname = self.group:GetName() or "Unknown Groupname"
|
||||
else
|
||||
self.Generic = true
|
||||
end
|
||||
@@ -190,7 +193,13 @@ function CLIENTMENU:RemoveF10()
|
||||
self:T(self.lid.."RemoveF10")
|
||||
if self.GroupID then
|
||||
--self:I(self.lid.."Removing "..table.concat(self.path,";"))
|
||||
missionCommands.removeItemForGroup(self.GroupID , self.path )
|
||||
local function RemoveFunction()
|
||||
return missionCommands.removeItemForGroup(self.GroupID , self.path )
|
||||
end
|
||||
local status, err = pcall(RemoveFunction)
|
||||
if not status then
|
||||
self:I(string.format("**** Error Removing Menu Entry %s for %s!",tostring(self.name),self.groupname))
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
@@ -381,7 +390,7 @@ end
|
||||
CLIENTMENUMANAGER = {
|
||||
ClassName = "CLIENTMENUMANAGER",
|
||||
lid = "",
|
||||
version = "0.1.0",
|
||||
version = "0.1.1",
|
||||
name = nil,
|
||||
clientset = nil,
|
||||
menutree = {},
|
||||
@@ -471,13 +480,13 @@ function CLIENTMENUMANAGER:FindUUIDsByText(Text,Parent)
|
||||
for _uuid,_entry in pairs(self.flattree) do
|
||||
local Entry = _entry -- #CLIENTMENU
|
||||
if Parent then
|
||||
if Entry and string.find(Entry.name,Text) and string.find(Entry.UUID,Parent.UUID) then
|
||||
if Entry and string.find(Entry.name,Text,1,true) and string.find(Entry.UUID,Parent.UUID,1,true) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
end
|
||||
else
|
||||
if Entry and string.find(Entry.name,Text) then
|
||||
if Entry and string.find(Entry.name,Text,1,true) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
@@ -513,7 +522,7 @@ function CLIENTMENUMANAGER:FindUUIDsByParent(Parent)
|
||||
for _uuid,_entry in pairs(self.flattree) do
|
||||
local Entry = _entry -- #CLIENTMENU
|
||||
if Parent then
|
||||
if Entry and string.find(Entry.UUID,Parent.UUID) then
|
||||
if Entry and string.find(Entry.UUID,Parent.UUID,1,true) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
@@ -670,7 +679,7 @@ end
|
||||
--- Remove the entry and all entries below the given entry from the client's F10 menus.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry to remove
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client. In this case the generic structure will not be touched.
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:DeleteF10Entry(Entry,Client)
|
||||
self:T(self.lid.."DeleteF10Entry")
|
||||
@@ -714,7 +723,7 @@ function CLIENTMENUMANAGER:DeleteGenericEntry(Entry)
|
||||
--self:I("Level = "..i)
|
||||
for _id,_uuid in pairs(tbl[i]) do
|
||||
self:T(_uuid)
|
||||
if string.find(_uuid,uuid) or _uuid == uuid then
|
||||
if string.find(_uuid,uuid,1,true) or _uuid == uuid then
|
||||
--self:I("Match for ".._uuid)
|
||||
self.menutree[i][_id] = nil
|
||||
self.flattree[_uuid] = nil
|
||||
@@ -743,7 +752,7 @@ function CLIENTMENUMANAGER:RemoveGenericSubEntries(Entry)
|
||||
self:T("Level = "..i)
|
||||
for _id,_uuid in pairs(tbl[i]) do
|
||||
self:T(_uuid)
|
||||
if string.find(_uuid,uuid) then
|
||||
if string.find(_uuid,uuid,1,true) then
|
||||
self:T("Match for ".._uuid)
|
||||
self.menutree[i][_id] = nil
|
||||
self.flattree[_uuid] = nil
|
||||
@@ -783,3 +792,4 @@ end
|
||||
-- End ClientMenu
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -31,11 +31,12 @@
|
||||
-- @module Core.Database
|
||||
-- @image Core_Database.JPG
|
||||
|
||||
|
||||
--- @type DATABASE
|
||||
---
|
||||
-- @type DATABASE
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #table Templates Templates: Units, Groups, Statics, ClientsByName, ClientsByID.
|
||||
-- @field #table CLIENTS Clients.
|
||||
-- @field #table STORAGES DCS warehouse storages.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator.
|
||||
@@ -50,6 +51,7 @@
|
||||
-- * PLAYERSJOINED
|
||||
-- * PLAYERS
|
||||
-- * CARGOS
|
||||
-- * STORAGES (DCS warehouses)
|
||||
--
|
||||
-- On top, for internal MOOSE administration purposes, the DATABASE administers the Unit and Group TEMPLATES as defined within the Mission Editor.
|
||||
--
|
||||
@@ -90,6 +92,7 @@ DATABASE = {
|
||||
FLIGHTCONTROLS = {},
|
||||
OPSZONES = {},
|
||||
PATHLINES = {},
|
||||
STORAGES = {},
|
||||
}
|
||||
|
||||
local _DATABASECoalition =
|
||||
@@ -246,6 +249,38 @@ function DATABASE:FindAirbase( AirbaseName )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Adds a STORAGE (DCS warehouse wrapper) based on the Airbase Name to the DATABASE.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string AirbaseName The name of the airbase.
|
||||
-- @return Wrapper.Storage#STORAGE Storage object.
|
||||
function DATABASE:AddStorage( AirbaseName )
|
||||
|
||||
if not self.STORAGES[AirbaseName] then
|
||||
self.STORAGES[AirbaseName] = STORAGE:New( AirbaseName )
|
||||
end
|
||||
|
||||
return self.STORAGES[AirbaseName]
|
||||
end
|
||||
|
||||
|
||||
--- Deletes a STORAGE from the DATABASE based on the name of the associated airbase.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string AirbaseName The name of the airbase.
|
||||
function DATABASE:DeleteStorage( AirbaseName )
|
||||
self.STORAGES[AirbaseName] = nil
|
||||
end
|
||||
|
||||
|
||||
--- Finds an STORAGE based on the name of the associated airbase.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string AirbaseName Name of the airbase.
|
||||
-- @return Wrapper.Storage#STORAGE The found STORAGE.
|
||||
function DATABASE:FindStorage( AirbaseName )
|
||||
local storage = self.STORAGES[AirbaseName]
|
||||
return storage
|
||||
end
|
||||
|
||||
do -- Zones and Pathlines
|
||||
|
||||
--- Finds a @{Core.Zone} based on the zone name.
|
||||
@@ -1333,7 +1368,7 @@ function DATABASE:_EventOnBirth( Event )
|
||||
if PlayerName then
|
||||
|
||||
-- Debug info.
|
||||
self:I(string.format("Player '%s' joint unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
|
||||
self:I(string.format("Player '%s' joined unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
|
||||
|
||||
-- Add client in case it does not exist already.
|
||||
if not client then
|
||||
@@ -1813,13 +1848,13 @@ function DATABASE:GetFlightControl(airbasename)
|
||||
return self.FLIGHTCONTROLS[airbasename]
|
||||
end
|
||||
|
||||
--- @param #DATABASE self
|
||||
-- @param #DATABASE self
|
||||
function DATABASE:_RegisterTemplates()
|
||||
self:F2()
|
||||
|
||||
self.Navpoints = {}
|
||||
self.UNITS = {}
|
||||
--Build routines.db.units and self.Navpoints
|
||||
--Build self.Navpoints
|
||||
for CoalitionName, coa_data in pairs(env.mission.coalition) do
|
||||
self:T({CoalitionName=CoalitionName})
|
||||
|
||||
@@ -1841,7 +1876,7 @@ function DATABASE:_RegisterTemplates()
|
||||
for nav_ind, nav_data in pairs(coa_data.nav_points) do
|
||||
|
||||
if type(nav_data) == 'table' then
|
||||
self.Navpoints[CoalitionName][nav_ind] = routines.utils.deepCopy(nav_data)
|
||||
self.Navpoints[CoalitionName][nav_ind] = UTILS.DeepCopy(nav_data)
|
||||
|
||||
self.Navpoints[CoalitionName][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory.
|
||||
self.Navpoints[CoalitionName][nav_ind]['point'] = {} -- point is used by SSE, support it.
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
-- ### Contributions:
|
||||
-- ### Contributions: **Applevangelist**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -371,7 +371,9 @@ function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
||||
trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
self.CoalitionSide = CoalitionSide
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -454,3 +456,138 @@ function MESSAGE:ToLogIf( Condition )
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
_MESSAGESRS = {}
|
||||
|
||||
--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions.
|
||||
-- @param #string PathToSRS Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone".
|
||||
-- @param #number Port Port number of SRS, defaults to 5002.
|
||||
-- @param #string PathToCredentials (optional) Path to credentials file for e.g. Google.
|
||||
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
|
||||
-- @param #number Modulation Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations.
|
||||
-- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "male".
|
||||
-- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB"
|
||||
-- @param #string Voice (optional) Voice. Will override gender and culture settings, e.g. MSRS.Voices.Microsoft.Hazel or MSRS.Voices.Google.Standard.de_DE_Standard_D. Hint on Microsoft voices - working voices are limited to Hedda, Hazel, David, Zira and Hortense. **Must** be installed on your Desktop or Server!
|
||||
-- @param #number Coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Defaults to coalition.side.NEUTRAL.
|
||||
-- @param #number Volume (optional) Volume, can be between 0.0 and 1.0 (loudest).
|
||||
-- @param #string Label (optional) Label, defaults to "MESSAGE" or the Message Category set.
|
||||
-- @param Core.Point#COORDINATE Coordinate (optional) Coordinate this messages originates from.
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||
--
|
||||
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
|
||||
_MESSAGESRS.MSRS = MSRS:New(PathToSRS,Frequency,Modulation,Volume)
|
||||
_MESSAGESRS.MSRS:SetCoalition(Coalition)
|
||||
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
||||
_MESSAGESRS.MSRS:SetCulture(Culture)
|
||||
_MESSAGESRS.Culture = Culture
|
||||
--_MESSAGESRS.MSRS:SetFrequencies(Frequency)
|
||||
_MESSAGESRS.MSRS:SetGender(Gender)
|
||||
_MESSAGESRS.Gender = Gender
|
||||
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
|
||||
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
|
||||
--_MESSAGESRS.MSRS:SetModulations(Modulation)
|
||||
--_MESSAGESRS.MSRS:SetPath(PathToSRS)
|
||||
_MESSAGESRS.MSRS:SetPort(Port)
|
||||
-- _MESSAGESRS.MSRS:SetVolume(Volume)
|
||||
_MESSAGESRS.MSRS:SetVoice(Voice)
|
||||
_MESSAGESRS.Voice = Voice
|
||||
_MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE")
|
||||
env.info(_MESSAGESRS.MSRS.provider,false)
|
||||
end
|
||||
|
||||
--- Sends a message via SRS.
|
||||
-- @param #MESSAGE self
|
||||
-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||
-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||
-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #number coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param Core.Point#COORDINATE coordinate (optional) Coordinate this messages originates from. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @return #MESSAGE self
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||
--
|
||||
function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volume,coordinate)
|
||||
if _MESSAGESRS.SRSQ then
|
||||
_MESSAGESRS.MSRS:SetVoice(voice or _MESSAGESRS.Voice)
|
||||
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency,modulation,gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,voice or _MESSAGESRS.Voice,volume,self.MessageCategory)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sends a message via SRS on the blue coalition side.
|
||||
-- @param #MESSAGE self
|
||||
-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||
-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||
-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param Core.Point#COORDINATE coordinate (optional) Coordinate this messages originates from. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @return #MESSAGE self
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSBlue()
|
||||
--
|
||||
function MESSAGE:ToSRSBlue(frequency,modulation,gender,culture,voice,volume,coordinate)
|
||||
self:ToSRS(frequency,modulation,gender,culture,voice,coalition.side.BLUE,volume,coordinate)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sends a message via SRS on the red coalition side.
|
||||
-- @param #MESSAGE self
|
||||
-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||
-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||
-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param Core.Point#COORDINATE coordinate (optional) Coordinate this messages originates from. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @return #MESSAGE self
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.RED)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSRed()
|
||||
--
|
||||
function MESSAGE:ToSRSRed(frequency,modulation,gender,culture,voice,volume,coordinate)
|
||||
self:ToSRS(frequency,modulation,gender,culture,voice,coalition.side.RED,volume,coordinate)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sends a message via SRS to all - via the neutral coalition side.
|
||||
-- @param #MESSAGE self
|
||||
-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||
-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||
-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @param Core.Point#COORDINATE coordinate (optional) Coordinate this messages originates from. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
|
||||
-- @return #MESSAGE self
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.NEUTRAL)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSAll()
|
||||
--
|
||||
function MESSAGE:ToSRSAll(frequency,modulation,gender,culture,voice,volume,coordinate)
|
||||
self:ToSRS(frequency,modulation,gender,culture,voice,coalition.side.NEUTRAL,volume,coordinate)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -2389,7 +2389,6 @@ do -- COORDINATE
|
||||
end
|
||||
|
||||
--- Creates a free form shape on the F10 map. The first point is the current COORDINATE. The remaining points need to be specified.
|
||||
-- **NOTE**: A free form polygon must have **at least three points** in total and currently only **up to 15 points** in total are supported.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #table Coordinates Table of coordinates of the remaining points of the shape.
|
||||
-- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All.
|
||||
@@ -2463,9 +2462,30 @@ do -- COORDINATE
|
||||
vecs[11], vecs[12], vecs[13], vecs[14], vecs[15],
|
||||
Color, FillColor, LineType, ReadOnly, Text or "")
|
||||
else
|
||||
self:E("ERROR: Currently a free form polygon can only have 15 points in total!")
|
||||
|
||||
-- Unfortunately, unpack(vecs) does not work! So no idea how to generalize this :(
|
||||
trigger.action.markupToAll(7, Coalition, MarkID, unpack(vecs), Color, FillColor, LineType, ReadOnly, Text or "")
|
||||
--trigger.action.markupToAll(7, Coalition, MarkID, unpack(vecs), Color, FillColor, LineType, ReadOnly, Text or "")
|
||||
|
||||
-- Write command as string and execute that. Idea by Grimes https://forum.dcs.world/topic/324201-mark-to-all-function/#comment-5273793
|
||||
local s=string.format("trigger.action.markupToAll(7, %d, %d,", Coalition, MarkID)
|
||||
for _,vec in pairs(vecs) do
|
||||
s=s..string.format("%s,", UTILS._OneLineSerialize(vec))
|
||||
end
|
||||
s=s..string.format("%s, %s, %s, %s", UTILS._OneLineSerialize(Color), UTILS._OneLineSerialize(FillColor), tostring(LineType), tostring(ReadOnly))
|
||||
if Text and Text~="" then
|
||||
s=s..string.format(", \"%s\"", Text)
|
||||
end
|
||||
s=s..")"
|
||||
|
||||
|
||||
-- Execute string command
|
||||
local success=UTILS.DoString(s)
|
||||
|
||||
if not success then
|
||||
self:E("ERROR: Could not draw polygon")
|
||||
env.info(s)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return MarkID
|
||||
|
||||
@@ -208,7 +208,7 @@ SCHEDULER = {
|
||||
-- @param #number RandomizeFactor Specifies a randomization factor between 0 and 1 to randomize the Repeat.
|
||||
-- @param #number Stop Specifies the amount of seconds when the scheduler will be stopped.
|
||||
-- @return #SCHEDULER self.
|
||||
-- @return #table The ScheduleID of the planned schedule.
|
||||
-- @return #string The ScheduleID of the planned schedule.
|
||||
function SCHEDULER:New( MasterObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop )
|
||||
|
||||
local self = BASE:Inherit( self, BASE:New() ) -- #SCHEDULER
|
||||
|
||||
@@ -35,6 +35,13 @@
|
||||
-- * Validate the presence of objects in the SET.
|
||||
-- * Trigger events when objects in the SET change a zone presence.
|
||||
--
|
||||
-- ## Notes on `FilterPrefixes()`:
|
||||
--
|
||||
-- This filter always looks for a **partial match** somewhere in the given field. LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through the following to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching).
|
||||
-- For example, setting a filter like so `FilterPrefixes("Huey")` is perfectly all right, whilst `FilterPrefixes("UH-1H Al-Assad")` might not be due to the minus signs. A quick fix here is to use a dot (.)
|
||||
-- in place of the special character, or escape it with a percentage sign (%), i.e. either `FilterPrefixes("UH.1H Al.Assad")` or `FilterPrefixes("UH%-1H Al%-Assad")` will give you the expected results.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
@@ -46,8 +53,9 @@
|
||||
-- @image Core_Sets.JPG
|
||||
|
||||
do -- SET_BASE
|
||||
|
||||
--- @type SET_BASE
|
||||
|
||||
---
|
||||
-- @type SET_BASE
|
||||
-- @field #table Filter Table of filters.
|
||||
-- @field #table Set Table of objects.
|
||||
-- @field #table Index Table of indices.
|
||||
@@ -242,7 +250,7 @@ do -- SET_BASE
|
||||
function SET_BASE:Add( ObjectName, Object )
|
||||
|
||||
-- Debug info.
|
||||
self:T( { ObjectName = ObjectName, Object = Object } )
|
||||
self:T2( { ObjectName = ObjectName, Object = Object } )
|
||||
|
||||
-- Ensure that the existing element is removed from the Set before a new one is inserted to the Set
|
||||
if self.Set[ObjectName] then
|
||||
@@ -257,6 +265,8 @@ do -- SET_BASE
|
||||
|
||||
-- Trigger Added event.
|
||||
self:Added( ObjectName, Object )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using the Object Name as the index.
|
||||
@@ -429,7 +439,7 @@ do -- SET_BASE
|
||||
function SET_BASE:SetDatabase( BaseSet )
|
||||
|
||||
-- Copy the filter criteria of the BaseSet
|
||||
local OtherFilter = routines.utils.deepCopy( BaseSet.Filter )
|
||||
local OtherFilter = UTILS.DeepCopy( BaseSet.Filter )
|
||||
self.Filter = OtherFilter
|
||||
|
||||
-- Now base the new Set on the BaseSet
|
||||
@@ -578,8 +588,8 @@ do -- SET_BASE
|
||||
end
|
||||
|
||||
----- Private method that registers all alive players in the mission.
|
||||
---- @param #SET_BASE self
|
||||
---- @return #SET_BASE self
|
||||
-- @param #SET_BASE self
|
||||
-- @return #SET_BASE self
|
||||
-- function SET_BASE:_RegisterPlayers()
|
||||
--
|
||||
-- local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) }
|
||||
@@ -796,8 +806,8 @@ do -- SET_BASE
|
||||
|
||||
|
||||
----- Iterate the SET_BASE and call an iterator function for each **alive** unit, providing the Unit and optional parameters.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive unit in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
-- @param #SET_BASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive unit in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_BASE self
|
||||
-- function SET_BASE:ForEachDCSUnitAlive( IteratorFunction, ... )
|
||||
-- self:F3( arg )
|
||||
@@ -808,8 +818,8 @@ do -- SET_BASE
|
||||
-- end
|
||||
--
|
||||
----- Iterate the SET_BASE and call an iterator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
-- @param #SET_BASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_BASE self
|
||||
-- function SET_BASE:ForEachPlayer( IteratorFunction, ... )
|
||||
-- self:F3( arg )
|
||||
@@ -821,8 +831,8 @@ do -- SET_BASE
|
||||
--
|
||||
--
|
||||
----- Iterate the SET_BASE and call an iterator function for each client, providing the Client to the function and optional parameters.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a CLIENT parameter.
|
||||
-- @param #SET_BASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_BASE self
|
||||
-- function SET_BASE:ForEachClient( IteratorFunction, ... )
|
||||
-- self:F3( arg )
|
||||
@@ -850,8 +860,10 @@ do -- SET_BASE
|
||||
self:F3( Object )
|
||||
local outcome = false
|
||||
local name = Object:GetName()
|
||||
--self:I("SET_BASE: Objectname = "..name)
|
||||
self:ForEach(
|
||||
function(object)
|
||||
--self:I("SET_BASE: In set objectname = "..object:GetName())
|
||||
if object:GetName() == name then
|
||||
outcome = true
|
||||
end
|
||||
@@ -901,9 +913,12 @@ do -- SET_BASE
|
||||
|
||||
end
|
||||
|
||||
do -- SET_GROUP
|
||||
do
|
||||
|
||||
--- @type SET_GROUP #SET_GROUP
|
||||
-- SET_GROUP
|
||||
|
||||
---
|
||||
-- @type SET_GROUP #SET_GROUP
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
@@ -934,7 +949,8 @@ do -- SET_GROUP
|
||||
-- * @{#SET_GROUP.FilterCoalitions}: Builds the SET_GROUP with the groups belonging to the coalition(s).
|
||||
-- * @{#SET_GROUP.FilterCategories}: Builds the SET_GROUP with the groups belonging to the category(ies).
|
||||
-- * @{#SET_GROUP.FilterCountries}: Builds the SET_GROUP with the groups belonging to the country(ies).
|
||||
-- * @{#SET_GROUP.FilterPrefixes}: Builds the SET_GROUP with the groups *containing* the given string in the group name. **Attention!** Bad naming convention, as this not really filtering *prefixes*.
|
||||
-- * @{#SET_GROUP.FilterPrefixes}: Builds the SET_GROUP with the groups *containing* the given string in the group name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
-- * @{#SET_GROUP.FilterActive}: Builds the SET_GROUP with the groups that are only active. Groups that are inactive (late activation) won't be included in the set!
|
||||
--
|
||||
-- For the Category Filter, extra methods have been added:
|
||||
@@ -1568,7 +1584,7 @@ do -- SET_GROUP
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Group#GROUP GroupObject
|
||||
function( ZoneObject, GroupObject )
|
||||
if GroupObject:IsCompletelyInZone( ZoneObject ) then
|
||||
@@ -1590,7 +1606,7 @@ do -- SET_GROUP
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Group#GROUP GroupObject
|
||||
function( ZoneObject, GroupObject )
|
||||
if GroupObject:IsPartlyInZone( ZoneObject ) then
|
||||
@@ -1612,7 +1628,7 @@ do -- SET_GROUP
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Group#GROUP GroupObject
|
||||
function( ZoneObject, GroupObject )
|
||||
if GroupObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -1659,7 +1675,7 @@ do -- SET_GROUP
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Group#GROUP GroupObject
|
||||
function( ZoneObject, GroupObject )
|
||||
if GroupObject:IsAnyInZone( ZoneObject ) then
|
||||
@@ -1857,8 +1873,8 @@ do -- SET_GROUP
|
||||
end
|
||||
|
||||
----- Iterate the SET_GROUP and call an iterator function for each **alive** player, providing the Group of the player and optional parameters.
|
||||
---- @param #SET_GROUP self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a GROUP parameter.
|
||||
-- @param #SET_GROUP self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a GROUP parameter.
|
||||
---- @return #SET_GROUP self
|
||||
-- function SET_GROUP:ForEachPlayer( IteratorFunction, ... )
|
||||
-- self:F2( arg )
|
||||
@@ -1870,8 +1886,8 @@ do -- SET_GROUP
|
||||
--
|
||||
--
|
||||
----- Iterate the SET_GROUP and call an iterator function for each client, providing the Client to the function and optional parameters.
|
||||
---- @param #SET_GROUP self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a CLIENT parameter.
|
||||
-- @param #SET_GROUP self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_GROUP self
|
||||
-- function SET_GROUP:ForEachClient( IteratorFunction, ... )
|
||||
-- self:F2( arg )
|
||||
@@ -1945,7 +1961,7 @@ do -- SET_GROUP
|
||||
if self.Filter.Zones then
|
||||
local MGroupZone = false
|
||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||
--self:I( "Zone:", ZoneName )
|
||||
--self:T( "Zone:", ZoneName )
|
||||
if MGroup:IsInZone(Zone) then
|
||||
MGroupZone = true
|
||||
end
|
||||
@@ -2011,8 +2027,9 @@ do -- SET_GROUP
|
||||
end
|
||||
|
||||
do -- SET_UNIT
|
||||
|
||||
--- @type SET_UNIT
|
||||
|
||||
---
|
||||
-- @type SET_UNIT
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
@@ -2045,7 +2062,8 @@ do -- SET_UNIT
|
||||
-- * @{#SET_UNIT.FilterCategories}: Builds the SET_UNIT with the units belonging to the category(ies).
|
||||
-- * @{#SET_UNIT.FilterTypes}: Builds the SET_UNIT with the units belonging to the unit type(s).
|
||||
-- * @{#SET_UNIT.FilterCountries}: Builds the SET_UNIT with the units belonging to the country(ies).
|
||||
-- * @{#SET_UNIT.FilterPrefixes}: Builds the SET_UNIT with the units sharing the same string(s) in their name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*.
|
||||
-- * @{#SET_UNIT.FilterPrefixes}: Builds the SET_UNIT with the units sharing the same string(s) in their name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
-- * @{#SET_UNIT.FilterActive}: Builds the SET_UNIT with the units that are only active. Units that are inactive (late activation) won't be included in the set!
|
||||
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Core.Zone#ZONE}.
|
||||
--
|
||||
@@ -2672,7 +2690,7 @@ do -- SET_UNIT
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Unit#UNIT UnitObject
|
||||
function( ZoneObject, UnitObject )
|
||||
if UnitObject:IsInZone( ZoneObject ) then
|
||||
@@ -2694,7 +2712,7 @@ do -- SET_UNIT
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Unit#UNIT UnitObject
|
||||
function( ZoneObject, UnitObject )
|
||||
if UnitObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -3011,8 +3029,8 @@ do -- SET_UNIT
|
||||
|
||||
|
||||
----- Iterate the SET_UNIT and call an iterator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
---- @param #SET_UNIT self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a UNIT parameter.
|
||||
-- @param #SET_UNIT self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_UNIT self
|
||||
-- function SET_UNIT:ForEachPlayer( IteratorFunction, ... )
|
||||
-- self:F2( arg )
|
||||
@@ -3024,8 +3042,8 @@ do -- SET_UNIT
|
||||
--
|
||||
--
|
||||
----- Iterate the SET_UNIT and call an iterator function for each client, providing the Client to the function and optional parameters.
|
||||
---- @param #SET_UNIT self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a CLIENT parameter.
|
||||
-- @param #SET_UNIT self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_UNIT self
|
||||
-- function SET_UNIT:ForEachClient( IteratorFunction, ... )
|
||||
-- self:F2( arg )
|
||||
@@ -3040,7 +3058,7 @@ do -- SET_UNIT
|
||||
-- @param Wrapper.Unit#UNIT MUnit
|
||||
-- @return #SET_UNIT self
|
||||
function SET_UNIT:IsIncludeObject( MUnit )
|
||||
self:F2( MUnit )
|
||||
self:F2( {MUnit} )
|
||||
|
||||
local MUnitInclude = false
|
||||
|
||||
@@ -3191,8 +3209,9 @@ do -- SET_UNIT
|
||||
end
|
||||
|
||||
do -- SET_STATIC
|
||||
|
||||
--- @type SET_STATIC
|
||||
|
||||
---
|
||||
-- @type SET_STATIC
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the SET_STATIC class to build sets of Statics belonging to certain:
|
||||
@@ -3223,7 +3242,8 @@ do -- SET_STATIC
|
||||
-- * @{#SET_STATIC.FilterCategories}: Builds the SET_STATIC with the units belonging to the category(ies).
|
||||
-- * @{#SET_STATIC.FilterTypes}: Builds the SET_STATIC with the units belonging to the unit type(s).
|
||||
-- * @{#SET_STATIC.FilterCountries}: Builds the SET_STATIC with the units belonging to the country(ies).
|
||||
-- * @{#SET_STATIC.FilterPrefixes}: Builds the SET_STATIC with the units containing the same string(s) in their name. **ATTENTION** bad naming convention as this *does not** only filter *prefixes*.
|
||||
-- * @{#SET_STATIC.FilterPrefixes}: Builds the SET_STATIC with the units containing the same string(s) in their name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
-- * @{#SET_STATIC.FilterZones}: Builds the SET_STATIC with the units within a @{Core.Zone#ZONE}.
|
||||
--
|
||||
-- Once the filter criteria have been set for the SET_STATIC, you can start filtering using:
|
||||
@@ -3612,7 +3632,7 @@ do -- SET_STATIC
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Static#STATIC StaticObject
|
||||
function( ZoneObject, StaticObject )
|
||||
if StaticObject:IsInZone( ZoneObject ) then
|
||||
@@ -3634,7 +3654,7 @@ do -- SET_STATIC
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Static#STATIC StaticObject
|
||||
function( ZoneObject, StaticObject )
|
||||
if StaticObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -3945,8 +3965,9 @@ do -- SET_STATIC
|
||||
end
|
||||
|
||||
do -- SET_CLIENT
|
||||
|
||||
--- @type SET_CLIENT
|
||||
|
||||
---
|
||||
-- @type SET_CLIENT
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
@@ -3979,7 +4000,8 @@ do -- SET_CLIENT
|
||||
-- * @{#SET_CLIENT.FilterCategories}: Builds the SET_CLIENT with the clients belonging to the category(ies).
|
||||
-- * @{#SET_CLIENT.FilterTypes}: Builds the SET_CLIENT with the clients belonging to the client type(s).
|
||||
-- * @{#SET_CLIENT.FilterCountries}: Builds the SET_CLIENT with the clients belonging to the country(ies).
|
||||
-- * @{#SET_CLIENT.FilterPrefixes}: Builds the SET_CLIENT with the clients containing the same string(s) in their unit/pilot name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*.
|
||||
-- * @{#SET_CLIENT.FilterPrefixes}: Builds the SET_CLIENT with the clients containing the same string(s) in their unit/pilot name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
-- * @{#SET_CLIENT.FilterActive}: Builds the SET_CLIENT with the units that are only active. Units that are inactive (late activation) won't be included in the set!
|
||||
-- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Core.Zone#ZONE}.
|
||||
--
|
||||
@@ -4059,7 +4081,7 @@ do -- SET_CLIENT
|
||||
|
||||
--- Remove CLIENT(s) from SET_CLIENT.
|
||||
-- @param Core.Set#SET_CLIENT self
|
||||
-- @param Wrapper.Client#CLIENT RemoveClientNames A single name or an array of CLIENT names.
|
||||
-- @param Wrapper.Client#CLIENT RemoveClientNames A single object or an array of CLIENT objects.
|
||||
-- @return self
|
||||
function SET_CLIENT:RemoveClientsByName( RemoveClientNames )
|
||||
|
||||
@@ -4310,7 +4332,6 @@ do -- SET_CLIENT
|
||||
function SET_CLIENT:FilterStart()
|
||||
|
||||
if _DATABASE then
|
||||
self:_FilterStart()
|
||||
self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
|
||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
||||
@@ -4319,6 +4340,7 @@ do -- SET_CLIENT
|
||||
local timing = self.ZoneTimerInterval or 30
|
||||
self.ZoneTimer:Start(timing,timing)
|
||||
end
|
||||
self:_FilterStart()
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -4369,7 +4391,7 @@ do -- SET_CLIENT
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Client#CLIENT ClientObject
|
||||
function( ZoneObject, ClientObject )
|
||||
if ClientObject:IsInZone( ZoneObject ) then
|
||||
@@ -4391,7 +4413,7 @@ do -- SET_CLIENT
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Client#CLIENT ClientObject
|
||||
function( ZoneObject, ClientObject )
|
||||
if ClientObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -4459,7 +4481,7 @@ do -- SET_CLIENT
|
||||
if self.Filter.Active == false or (self.Filter.Active == true and MClient:IsActive() == true and MClient:IsAlive() == true) then
|
||||
MClientActive = true
|
||||
end
|
||||
--self:I( { "Evaluated Active", MClientActive } )
|
||||
--self:T( { "Evaluated Active", MClientActive } )
|
||||
MClientInclude = MClientInclude and MClientActive
|
||||
end
|
||||
|
||||
@@ -4541,7 +4563,7 @@ do -- SET_CLIENT
|
||||
if self.Filter.Playernames then
|
||||
local MClientPlayername = false
|
||||
local playername = MClient:GetPlayerName() or "Unknown"
|
||||
--self:I(playername)
|
||||
--self:T(playername)
|
||||
for _,_Playername in pairs(self.Filter.Playernames) do
|
||||
if playername and string.find(playername,_Playername) then
|
||||
MClientPlayername = true
|
||||
@@ -4556,7 +4578,7 @@ do -- SET_CLIENT
|
||||
local callsign = MClient:GetCallsign()
|
||||
--self:I(callsign)
|
||||
for _,_Callsign in pairs(self.Filter.Callsigns) do
|
||||
if callsign and string.find(callsign,_Callsign) then
|
||||
if callsign and string.find(callsign,_Callsign,1,true) then
|
||||
MClientCallsigns = true
|
||||
end
|
||||
end
|
||||
@@ -4573,7 +4595,8 @@ end
|
||||
|
||||
do -- SET_PLAYER
|
||||
|
||||
--- @type SET_PLAYER
|
||||
---
|
||||
-- @type SET_PLAYER
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_PLAYER} class to build sets of units belonging to alive players:
|
||||
@@ -4593,7 +4616,8 @@ do -- SET_PLAYER
|
||||
-- * @{#SET_PLAYER.FilterCategories}: Builds the SET_PLAYER with the clients belonging to the category(ies).
|
||||
-- * @{#SET_PLAYER.FilterTypes}: Builds the SET_PLAYER with the clients belonging to the client type(s).
|
||||
-- * @{#SET_PLAYER.FilterCountries}: Builds the SET_PLAYER with the clients belonging to the country(ies).
|
||||
-- * @{#SET_PLAYER.FilterPrefixes}: Builds the SET_PLAYER with the clients sharing the same string(s) in their unit/pilot name. **ATTENTION** Bad naming convention as this *does not* only filter prefixes.
|
||||
-- * @{#SET_PLAYER.FilterPrefixes}: Builds the SET_PLAYER with the clients sharing the same string(s) in their unit/pilot name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
--
|
||||
-- Once the filter criteria have been set for the SET_PLAYER, you can start filtering using:
|
||||
--
|
||||
@@ -4868,7 +4892,7 @@ do -- SET_PLAYER
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Client#CLIENT ClientObject
|
||||
function( ZoneObject, ClientObject )
|
||||
if ClientObject:IsInZone( ZoneObject ) then
|
||||
@@ -4890,7 +4914,7 @@ do -- SET_PLAYER
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Client#CLIENT ClientObject
|
||||
function( ZoneObject, ClientObject )
|
||||
if ClientObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -4998,8 +5022,9 @@ do -- SET_PLAYER
|
||||
end
|
||||
|
||||
do -- SET_AIRBASE
|
||||
|
||||
--- @type SET_AIRBASE
|
||||
|
||||
---
|
||||
-- @type SET_AIRBASE
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_AIRBASE} class to build sets of airbases optionally belonging to certain:
|
||||
@@ -5341,8 +5366,9 @@ do -- SET_AIRBASE
|
||||
end
|
||||
|
||||
do -- SET_CARGO
|
||||
|
||||
--- @type SET_CARGO
|
||||
|
||||
---
|
||||
-- @type SET_CARGO
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_CARGO} class to build sets of cargos optionally belonging to certain:
|
||||
@@ -5368,7 +5394,8 @@ do -- SET_CARGO
|
||||
-- Filter criteria are defined by:
|
||||
--
|
||||
-- * @{#SET_CARGO.FilterCoalitions}: Builds the SET_CARGO with the cargos belonging to the coalition(s).
|
||||
-- * @{#SET_CARGO.FilterPrefixes}: Builds the SET_CARGO with the cargos containing the same string(s). **ATTENTION** Bad naming convention as this *does not* only filter *prefixes*.
|
||||
-- * @{#SET_CARGO.FilterPrefixes}: Builds the SET_CARGO with the cargos containing the same string(s). **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
-- * @{#SET_CARGO.FilterTypes}: Builds the SET_CARGO with the cargos belonging to the cargo type(s).
|
||||
-- * @{#SET_CARGO.FilterCountries}: Builds the SET_CARGO with the cargos belonging to the country(ies).
|
||||
--
|
||||
@@ -5767,8 +5794,9 @@ do -- SET_CARGO
|
||||
end
|
||||
|
||||
do -- SET_ZONE
|
||||
|
||||
--- @type SET_ZONE
|
||||
|
||||
---
|
||||
-- @type SET_ZONE
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_ZONE} class to build sets of zones of various types.
|
||||
@@ -5789,7 +5817,8 @@ do -- SET_ZONE
|
||||
-- You can set filter criteria to build the collection of zones in SET_ZONE.
|
||||
-- Filter criteria are defined by:
|
||||
--
|
||||
-- * @{#SET_ZONE.FilterPrefixes}: Builds the SET_ZONE with the zones having a certain text pattern in their name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*.
|
||||
-- * @{#SET_ZONE.FilterPrefixes}: Builds the SET_ZONE with the zones having a certain text pattern in their name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
--
|
||||
-- Once the filter criteria have been set for the SET_ZONE, you can start filtering using:
|
||||
--
|
||||
@@ -5813,6 +5842,7 @@ do -- SET_ZONE
|
||||
},
|
||||
FilterMeta = {
|
||||
},
|
||||
Checktime = 5,
|
||||
}
|
||||
|
||||
--- Creates a new SET_ZONE object, building a set of zones.
|
||||
@@ -6023,7 +6053,29 @@ do -- SET_ZONE
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Get the average aggregated coordinate of this set of zones.
|
||||
-- @param #SET_ZONE self
|
||||
-- @return Core.Point#COORDINATE
|
||||
function SET_ZONE:GetAverageCoordinate()
|
||||
local x,y,z = 0,0,0
|
||||
local count = 0
|
||||
for _,_zone in pairs(self.Set) do
|
||||
local zone=_zone --Core.Zone#ZONE
|
||||
local vec3 = zone:GetVec3()
|
||||
x = x + vec3.x
|
||||
y = y + vec3.y
|
||||
z = z + vec3.z
|
||||
count = count + 1
|
||||
end
|
||||
if count > 1 then
|
||||
x = x/count
|
||||
y = y/count
|
||||
z = z/count
|
||||
end
|
||||
local coord = COORDINATE:New(x,y,z)
|
||||
return coord
|
||||
end
|
||||
|
||||
--- Private function.
|
||||
-- @param #SET_ZONE self
|
||||
@@ -6131,12 +6183,176 @@ do -- SET_ZONE
|
||||
|
||||
return zmin, dmin
|
||||
end
|
||||
|
||||
|
||||
--- Set the check time for SET_ZONE:Trigger()
|
||||
-- @param #SET_ZONE self
|
||||
-- @param #number seconds Check every seconds for objects entering or leaving the zone. Defaults to 5 secs.
|
||||
-- @return #SET_ZONE self
|
||||
function SET_ZONE:SetCheckTime(seconds)
|
||||
self.Checktime = seconds or 5
|
||||
return self
|
||||
end
|
||||
|
||||
--- Start watching if the Object or Objects move into or out of our set of zones.
|
||||
-- @param #SET_ZONE self
|
||||
-- @param Wrappe.Controllable#CONTROLLABLE Objects Object or Objects to watch, can be of type UNIT, GROUP, CLIENT, or SET\_UNIT, SET\_GROUP, SET\_CLIENT
|
||||
-- @return #SET_ZONE self
|
||||
-- @usage
|
||||
-- -- Create a SET_GROUP and a SET_ZONE for this:
|
||||
--
|
||||
-- local groupset = SET_GROUP:New():FilterPrefixes("Aerial"):FilterStart()
|
||||
--
|
||||
-- -- Trigger will check each zone of the SET_ZONE every 5 secs for objects entering or leaving from the groupset
|
||||
-- local zoneset = SET_ZONE:New():FilterPrefixes("Target Zone"):FilterOnce():Trigger(groupset)
|
||||
--
|
||||
-- -- Draw zones on map so we see what's going on
|
||||
-- zoneset:ForEachZone(
|
||||
-- function(zone)
|
||||
-- zone:DrawZone(-1, {0,1,0}, Alpha, FillColor, FillAlpha, 4, ReadOnly)
|
||||
-- end
|
||||
-- )
|
||||
--
|
||||
-- -- This FSM function will be called for entering objects
|
||||
-- function zoneset:OnAfterEnteredZone(From,Event,To,Controllable,Zone)
|
||||
-- MESSAGE:New("Group "..Controllable:GetName() .. " entered zone "..Zone:GetName(),10,"Set Trigger"):ToAll()
|
||||
-- end
|
||||
--
|
||||
-- -- This FSM function will be called for leaving objects
|
||||
-- function zoneset:OnAfterLeftZone(From,Event,To,Controllable,Zone)
|
||||
-- MESSAGE:New("Group "..Controllable:GetName() .. " left zone "..Zone:GetName(),10,"Set Trigger"):ToAll()
|
||||
-- end
|
||||
--
|
||||
-- -- Stop watching after 1 hour
|
||||
-- zoneset:__TriggerStop(3600)
|
||||
function SET_ZONE:Trigger(Objects)
|
||||
--self:I("Added Set_Zone Trigger")
|
||||
self:AddTransition("*","TriggerStart","TriggerRunning")
|
||||
self:AddTransition("*","EnteredZone","*")
|
||||
self:AddTransition("*","LeftZone","*")
|
||||
self:AddTransition("*","TriggerRunCheck","*")
|
||||
self:AddTransition("*","TriggerStop","TriggerStopped")
|
||||
self:TriggerStart()
|
||||
self.checkobjects = Objects
|
||||
if UTILS.IsInstanceOf(Objects,"SET_BASE") then
|
||||
self.objectset = Objects.Set
|
||||
else
|
||||
self.objectset = {Objects}
|
||||
end
|
||||
self:_TriggerCheck(true)
|
||||
self:__TriggerRunCheck(self.Checktime)
|
||||
return self
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "TriggerStop". Stops the SET_ZONE Trigger.
|
||||
-- @function [parent=#SET_ZONE] TriggerStop
|
||||
-- @param #SET_ZONE self
|
||||
|
||||
--- Triggers the FSM event "TriggerStop" after a delay.
|
||||
-- @function [parent=#SET_ZONE] __TriggerStop
|
||||
-- @param #SET_ZONE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- On After "EnteredZone" event. An observed object has entered the zone.
|
||||
-- @function [parent=#SET_ZONE] OnAfterEnteredZone
|
||||
-- @param #SET_ZONE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The controllable entering the zone.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The zone entered.
|
||||
|
||||
--- On After "LeftZone" event. An observed object has left the zone.
|
||||
-- @function [parent=#SET_ZONE] OnAfterLeftZone
|
||||
-- @param #SET_ZONE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The controllable leaving the zone.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The zone left.
|
||||
end
|
||||
|
||||
--- (Internal) Check the assigned objects for being in/out of the zone
|
||||
-- @param #SET_ZONE self
|
||||
-- @param #boolean fromstart If true, do the init of the objects
|
||||
-- @return #SET_ZONE self
|
||||
function SET_ZONE:_TriggerCheck(fromstart)
|
||||
--self:I("_TriggerCheck | FromStart = "..tostring(fromstart))
|
||||
if fromstart then
|
||||
for _,_object in pairs(self.objectset) do
|
||||
local obj = _object -- Wrapper.Controllable#CONTROLLABLE
|
||||
if obj and obj:IsAlive() then
|
||||
for _,_zone in pairs(self.Set) do
|
||||
if not obj.TriggerInZone then obj.TriggerInZone = {} end
|
||||
if _zone:IsCoordinateInZone(obj:GetCoordinate()) then
|
||||
obj.TriggerInZone[_zone.ZoneName] = true
|
||||
else
|
||||
obj.TriggerInZone[_zone.ZoneName] = false
|
||||
end
|
||||
--self:I("Object "..obj:GetName().." is in zone = "..tostring(obj.TriggerInZone[_zone.ZoneName]))
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for _,_object in pairs(self.objectset) do
|
||||
local obj = _object -- Wrapper.Controllable#CONTROLLABLE
|
||||
if obj and obj:IsAlive() then
|
||||
for _,_zone in pairs(self.Set) do
|
||||
-- Check for pop-up objects
|
||||
if not obj.TriggerInZone then
|
||||
-- has not been tagged previously - wasn't in set!
|
||||
obj.TriggerInZone = {}
|
||||
end
|
||||
if not obj.TriggerInZone[_zone.ZoneName] then
|
||||
-- has not been tagged previously - wasn't in set!
|
||||
obj.TriggerInZone[_zone.ZoneName] = false
|
||||
end
|
||||
-- is obj in zone?
|
||||
local inzone = _zone:IsCoordinateInZone(obj:GetCoordinate())
|
||||
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
|
||||
if inzone and not obj.TriggerInZone[_zone.ZoneName] then
|
||||
-- wasn't in zone before
|
||||
--self:I("Newly entered")
|
||||
self:__EnteredZone(0.5,obj,_zone)
|
||||
obj.TriggerInZone[_zone.ZoneName] = true
|
||||
elseif (not inzone) and obj.TriggerInZone[_zone.ZoneName] then
|
||||
-- has left the zone
|
||||
--self:I("Newly left")
|
||||
self:__LeftZone(0.5,obj,_zone)
|
||||
obj.TriggerInZone[_zone.ZoneName] = false
|
||||
else
|
||||
--self:I("Not left or not entered, or something went wrong!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- (Internal) Check the assigned objects for being in/out of the zone
|
||||
-- @param #SET_ZONE self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string to
|
||||
-- @return #SET_ZONE self
|
||||
function SET_ZONE:onafterTriggerRunCheck(From,Event,To)
|
||||
--self:I("onafterTriggerRunCheck")
|
||||
--self:I({From, Event, To})
|
||||
if self:GetState() ~= "TriggerStopped" then
|
||||
self:_TriggerCheck()
|
||||
self:__TriggerRunCheck(self.Checktime)
|
||||
end
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
do -- SET_ZONE_GOAL
|
||||
|
||||
--- @type SET_ZONE_GOAL
|
||||
|
||||
---
|
||||
-- @type SET_ZONE_GOAL
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_ZONE_GOAL} class to build sets of zones of various types.
|
||||
@@ -6157,7 +6373,8 @@ do -- SET_ZONE_GOAL
|
||||
-- You can set filter criteria to build the collection of zones in SET_ZONE_GOAL.
|
||||
-- Filter criteria are defined by:
|
||||
--
|
||||
-- * @{#SET_ZONE_GOAL.FilterPrefixes}: Builds the SET_ZONE_GOAL with the zones having a certain text pattern in their name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*.
|
||||
-- * @{#SET_ZONE_GOAL.FilterPrefixes}: Builds the SET_ZONE_GOAL with the zones having a certain text pattern in their name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
--
|
||||
-- Once the filter criteria have been set for the SET_ZONE_GOAL, you can start filtering using:
|
||||
--
|
||||
@@ -6446,8 +6663,9 @@ do -- SET_ZONE_GOAL
|
||||
end
|
||||
|
||||
do -- SET_OPSZONE
|
||||
|
||||
--- @type SET_OPSZONE
|
||||
|
||||
---
|
||||
-- @type SET_OPSZONE
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_OPSZONE} class to build sets of zones of various types.
|
||||
@@ -6468,7 +6686,8 @@ do -- SET_OPSZONE
|
||||
-- You can set filter criteria to build the collection of zones in SET_OPSZONE.
|
||||
-- Filter criteria are defined by:
|
||||
--
|
||||
-- * @{#SET_OPSZONE.FilterPrefixes}: Builds the SET_OPSZONE with the zones having a certain text pattern in their name. **ATTENTION!** Bad naming convention as this *does not* only filter *prefixes*.
|
||||
-- * @{#SET_OPSZONE.FilterPrefixes}: Builds the SET_OPSZONE with the zones having a certain text pattern in their name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
--
|
||||
-- Once the filter criteria have been set for the SET_OPSZONE, you can start filtering using:
|
||||
--
|
||||
@@ -6903,8 +7122,9 @@ end
|
||||
|
||||
|
||||
do -- SET_OPSGROUP
|
||||
|
||||
--- @type SET_OPSGROUP
|
||||
|
||||
---
|
||||
-- @type SET_OPSGROUP
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_OPSGROUP} class to build sets of OPS groups belonging to certain:
|
||||
@@ -6933,7 +7153,8 @@ do -- SET_OPSGROUP
|
||||
-- * @{#SET_OPSGROUP.FilterCoalitions}: Builds the SET_OPSGROUP with the groups belonging to the coalition(s).
|
||||
-- * @{#SET_OPSGROUP.FilterCategories}: Builds the SET_OPSGROUP with the groups belonging to the category(ies).
|
||||
-- * @{#SET_OPSGROUP.FilterCountries}: Builds the SET_OPSGROUP with the groups belonging to the country(ies).
|
||||
-- * @{#SET_OPSGROUP.FilterPrefixes}: Builds the SET_OPSGROUP with the groups *containing* the given string in the group name. **Attention!** Bad naming convention, as this not really filtering *prefixes*.
|
||||
-- * @{#SET_OPSGROUP.FilterPrefixes}: Builds the SET_OPSGROUP with the groups *containing* the given string in the group name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||
-- * @{#SET_OPSGROUP.FilterActive}: Builds the SET_OPSGROUP with the groups that are only active. Groups that are inactive (late activation) won't be included in the set!
|
||||
--
|
||||
-- For the Category Filter, extra methods have been added:
|
||||
@@ -7571,6 +7792,7 @@ do -- SET_SCENERY
|
||||
Scenerys = {},
|
||||
Filter = {
|
||||
SceneryPrefixes = nil,
|
||||
SceneryRoles = nil,
|
||||
Zones = nil,
|
||||
},
|
||||
}
|
||||
@@ -7593,7 +7815,7 @@ do -- SET_SCENERY
|
||||
|
||||
if ZoneSet then
|
||||
for _,_zone in pairs(ZoneSet.Set) do
|
||||
self:T("Zone type handed: "..tostring(_zone.ClassName))
|
||||
self:T("Zone type handed: "..tostring(_zone.ClassName))
|
||||
table.insert(zonenames,_zone:GetName())
|
||||
end
|
||||
self:AddSceneryByName(zonenames)
|
||||
@@ -7617,7 +7839,7 @@ do -- SET_SCENERY
|
||||
|
||||
--- Add SCENERY(s) to SET_SCENERY.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @param #string AddScenery A single SCENERY.
|
||||
-- @param Wrapper.Scenery#SCENERY AddScenery A single SCENERY object.
|
||||
-- @return #SET_SCENERY self
|
||||
function SET_SCENERY:AddScenery( AddScenery )
|
||||
self:F2( AddScenery:GetName() )
|
||||
@@ -7687,6 +7909,7 @@ do -- SET_SCENERY
|
||||
end
|
||||
for _,Zone in pairs( zones ) do
|
||||
local zonename = Zone:GetName()
|
||||
self:T(zonename)
|
||||
self.Filter.Zones[zonename] = Zone
|
||||
end
|
||||
return self
|
||||
@@ -7705,11 +7928,30 @@ do -- SET_SCENERY
|
||||
Prefixes = { Prefixes }
|
||||
end
|
||||
for PrefixID, Prefix in pairs( Prefixes ) do
|
||||
--self:T(Prefix)
|
||||
self.Filter.SceneryPrefixes[Prefix] = Prefix
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Builds a set of SCENERYs that **contain** an exact match of the "ROLE" property.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @param #string Role The string pattern(s) that needs to exactly match the scenery "ROLE" property from the ME quad-zone properties. Can also be passed as a `#table` of strings.
|
||||
-- @return #SET_SCENERY self
|
||||
function SET_SCENERY:FilterRoles( Role )
|
||||
if not self.Filter.SceneryRoles then
|
||||
self.Filter.SceneryRoles = {}
|
||||
end
|
||||
if type( Role ) ~= "table" then
|
||||
Role = { Role }
|
||||
end
|
||||
for PrefixID, Prefix in pairs( Role ) do
|
||||
--self:T(Prefix)
|
||||
self.Filter.SceneryRoles[Prefix] = Prefix
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Iterate the SET_SCENERY and count how many SCENERYSs are alive.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #number The number of SCENERYSs alive.
|
||||
@@ -7802,10 +8044,76 @@ do -- SET_SCENERY
|
||||
-- @param Wrapper.Scenery#SCENERY MScenery
|
||||
-- @return #SET_SCENERY self
|
||||
function SET_SCENERY:IsIncludeObject( MScenery )
|
||||
self:F2( MScenery )
|
||||
return true
|
||||
self:T( MScenery.SceneryName )
|
||||
|
||||
local MSceneryInclude = true
|
||||
|
||||
if MScenery then
|
||||
local MSceneryName = MScenery:GetName()
|
||||
|
||||
-- Filter Prefixes
|
||||
if self.Filter.Prefixes then
|
||||
local MSceneryPrefix = false
|
||||
for ZonePrefixId, ZonePrefix in pairs( self.Filter.Prefixes ) do
|
||||
self:T( { "Prefix:", string.find( MSceneryName, ZonePrefix, 1 ), ZonePrefix } )
|
||||
if string.find( MSceneryName, ZonePrefix, 1 ) then
|
||||
MSceneryPrefix = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Prefix", MSceneryPrefix } )
|
||||
MSceneryInclude = MSceneryInclude and MSceneryPrefix
|
||||
end
|
||||
|
||||
if self.Filter.Zones then
|
||||
local MSceneryZone = false
|
||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||
--self:T( "Zone:", ZoneName )
|
||||
local coord = MScenery:GetCoordinate()
|
||||
if coord and Zone:IsCoordinateInZone(coord) then
|
||||
MSceneryZone = true
|
||||
end
|
||||
self:T( { "Evaluated Zone", MSceneryZone } )
|
||||
end
|
||||
MSceneryInclude = MSceneryInclude and MSceneryZone
|
||||
end
|
||||
|
||||
-- Filter Roles
|
||||
if self.Filter.SceneryRoles then
|
||||
local MSceneryRole = false
|
||||
local Role = MScenery:GetProperty("ROLE") or "none"
|
||||
for ZoneRoleId, ZoneRole in pairs( self.Filter.SceneryRoles ) do
|
||||
self:T( { "Role:", ZoneRole, Role } )
|
||||
if ZoneRole == Role then
|
||||
MSceneryRole = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Role ", MSceneryRole } )
|
||||
MSceneryInclude = MSceneryInclude and MSceneryRole
|
||||
end
|
||||
end
|
||||
|
||||
self:T2( MSceneryInclude )
|
||||
return MSceneryInclude
|
||||
end
|
||||
|
||||
--- Filters for the defined collection.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #SET_SCENERY self
|
||||
function SET_SCENERY:FilterOnce()
|
||||
|
||||
for ObjectName, Object in pairs( self:GetSet() ) do
|
||||
self:T(ObjectName)
|
||||
if self:IsIncludeObject( Object ) then
|
||||
self:Add( ObjectName, Object )
|
||||
else
|
||||
self:Remove(ObjectName, true)
|
||||
end
|
||||
end
|
||||
|
||||
return self --FilteredSet
|
||||
end
|
||||
|
||||
|
||||
--- Count overall initial (Life0) lifepoints of the SET objects.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #number LIfe0Points
|
||||
@@ -7843,7 +8151,7 @@ do -- SET_SCENERY
|
||||
function SET_SCENERY:GetRelativeLife()
|
||||
local life = self:GetLife()
|
||||
local life0 = self:GetLife0()
|
||||
self:T3(string.format("Set Lifepoints: %d life0 | %d life",life0,life))
|
||||
self:T2(string.format("Set Lifepoints: %d life0 | %d life",life0,life))
|
||||
local rlife = math.floor((life / life0) * 100)
|
||||
return rlife
|
||||
end
|
||||
|
||||
@@ -744,7 +744,7 @@ do -- SETTINGS
|
||||
|
||||
self.PlayerMenu = PlayerMenu
|
||||
|
||||
self:I( string.format( "Setting menu for player %s", tostring( PlayerName ) ) )
|
||||
self:T( string.format( "Setting menu for player %s", tostring( PlayerName ) ) )
|
||||
|
||||
local submenu = MENU_GROUP:New( PlayerGroup, "LL Accuracy", PlayerMenu )
|
||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 0 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 0 )
|
||||
@@ -989,7 +989,7 @@ do -- SETTINGS
|
||||
do
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuGroupA2GSystem( PlayerUnit, PlayerGroup, PlayerName, A2GSystem )
|
||||
BASE:E( { self, PlayerUnit:GetName(), A2GSystem } )
|
||||
--BASE:E( {PlayerUnit:GetName(), A2GSystem } )
|
||||
self.A2GSystem = A2GSystem
|
||||
MESSAGE:New( string.format( "Settings: A2G format set to %s for player %s.", A2GSystem, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||
if _SETTINGS.MenuStatic == false then
|
||||
|
||||
@@ -286,6 +286,7 @@ SPAWN.Takeoff = {
|
||||
Cold = 4,
|
||||
}
|
||||
|
||||
---
|
||||
-- @type SPAWN.SpawnZoneTable
|
||||
-- @list <Core.Zone#ZONE_BASE> SpawnZone
|
||||
|
||||
@@ -327,6 +328,8 @@ function SPAWN:New( SpawnTemplatePrefix )
|
||||
self.SpawnInitModu = nil -- No special modulation.
|
||||
self.SpawnInitRadio = nil -- No radio comms setting.
|
||||
self.SpawnInitModex = nil
|
||||
self.SpawnInitModexPrefix = nil
|
||||
self.SpawnInitModexPostfix = nil
|
||||
self.SpawnInitAirbase = nil
|
||||
self.TweakedTemplate = false -- Check if the user is using self made template.
|
||||
|
||||
@@ -381,6 +384,8 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
|
||||
self.SpawnInitModu = nil -- No special modulation.
|
||||
self.SpawnInitRadio = nil -- No radio communication setting.
|
||||
self.SpawnInitModex = nil
|
||||
self.SpawnInitModexPrefix = nil
|
||||
self.SpawnInitModexPostfix = nil
|
||||
self.SpawnInitAirbase = nil
|
||||
self.TweakedTemplate = false -- Check if the user is using self made template.
|
||||
|
||||
@@ -540,6 +545,8 @@ function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPr
|
||||
self.SpawnInitModu = nil -- No special modulation.
|
||||
self.SpawnInitRadio = nil -- No radio communication setting.
|
||||
self.SpawnInitModex = nil
|
||||
self.SpawnInitModexPrefix = nil
|
||||
self.SpawnInitModexPostfix = nil
|
||||
self.SpawnInitAirbase = nil
|
||||
self.TweakedTemplate = true -- Check if the user is using self made template.
|
||||
self.MooseNameing = true
|
||||
@@ -811,12 +818,17 @@ end
|
||||
--- Sets the modex of the first unit of the group. If more units are in the group, the number is increased by one with every unit.
|
||||
-- @param #SPAWN self
|
||||
-- @param #number modex Modex of the first unit.
|
||||
-- @param #string prefix (optional) String to prefix to modex, e.g. for French AdA Modex, eg. -L-102 then "-L-" would be the prefix.
|
||||
-- @param #string postfix (optional) String to postfix to modex, example tbd.
|
||||
-- @return #SPAWN self
|
||||
function SPAWN:InitModex( modex )
|
||||
function SPAWN:InitModex( modex, prefix, postfix )
|
||||
|
||||
if modex then
|
||||
self.SpawnInitModex = tonumber( modex )
|
||||
end
|
||||
|
||||
self.SpawnInitModexPrefix = prefix
|
||||
self.SpawnInitModexPostfix = postfix
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -1202,7 +1214,6 @@ function SPAWN:InitCleanUp( SpawnCleanUpInterval )
|
||||
local SpawnGroup, SpawnCursor = self:GetFirstAliveGroup()
|
||||
self:T( { "CleanUp Scheduler:", SpawnGroup } )
|
||||
|
||||
-- self.CleanUpFunction = routines.scheduleFunction( self._SpawnCleanUpScheduler, { self }, timer.getTime() + 1, SpawnCleanUpInterval )
|
||||
self.CleanUpScheduler = SCHEDULER:New( self, self._SpawnCleanUpScheduler, {}, 1, SpawnCleanUpInterval, 0.2 )
|
||||
return self
|
||||
end
|
||||
@@ -1571,7 +1582,10 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
||||
-- Set tail number.
|
||||
if self.SpawnInitModex then
|
||||
for UnitID = 1, #SpawnTemplate.units do
|
||||
SpawnTemplate.units[UnitID].onboard_num = string.format( "%03d", self.SpawnInitModex + (UnitID - 1) )
|
||||
local modexnumber = string.format( "%03d", self.SpawnInitModex + (UnitID - 1) )
|
||||
if self.SpawnInitModexPrefix then modexnumber = self.SpawnInitModexPrefix..modexnumber end
|
||||
if self.SpawnInitModexPostfix then modexnumber = modexnumber..self.SpawnInitModexPostfix end
|
||||
SpawnTemplate.units[UnitID].onboard_num = modexnumber
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2178,14 +2192,18 @@ end
|
||||
-- @param #table Spots Table of parking spot IDs. Note that these in general are different from the numbering in the mission editor!
|
||||
-- @param #SPAWN.Takeoff Takeoff (Optional) Takeoff type, i.e. either SPAWN.Takeoff.Cold or SPAWN.Takeoff.Hot. Default is Hot.
|
||||
-- @return Wrapper.Group#GROUP The group that was spawned or nil when nothing was spawned.
|
||||
function SPAWN:SpawnAtParkingSpot( Airbase, Spots, Takeoff ) -- R2.5
|
||||
function SPAWN:SpawnAtParkingSpot( Airbase, Spots, Takeoff )
|
||||
self:F( { Airbase = Airbase, Spots = Spots, Takeoff = Takeoff } )
|
||||
|
||||
|
||||
-- Ensure that Spots parameter is a table.
|
||||
if type( Spots ) ~= "table" then
|
||||
Spots = { Spots }
|
||||
end
|
||||
|
||||
|
||||
if type(Airbase) == "string" then
|
||||
Airbase = AIRBASE:FindByName(Airbase)
|
||||
end
|
||||
|
||||
-- Get template group.
|
||||
local group = GROUP:FindByName( self.SpawnTemplatePrefix )
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
-- @module Core.Zone
|
||||
-- @image Core_Zones.JPG
|
||||
|
||||
--- @type ZONE_BASE
|
||||
---
|
||||
-- @type ZONE_BASE
|
||||
-- @field #string ZoneName Name of the zone.
|
||||
-- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
||||
-- @field #number DrawID Unique ID of the drawn zone on the F10 map.
|
||||
@@ -63,6 +64,7 @@
|
||||
-- @field #number ZoneID ID of zone. Only zones defined in the ME have an ID!
|
||||
-- @field #table Table of any trigger zone properties from the ME. The key is the Name of the property, and the value is the property's Value.
|
||||
-- @field #number Surface Type of surface. Only determined at the center of the zone!
|
||||
-- @field #number Checktime Check every Checktime seconds, used for ZONE:Trigger()
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
|
||||
@@ -121,6 +123,7 @@ ZONE_BASE = {
|
||||
ZoneID=nil,
|
||||
Properties={},
|
||||
Surface=nil,
|
||||
Checktime = 5,
|
||||
}
|
||||
|
||||
--- The ZONE_BASE.BoundingSquare
|
||||
@@ -189,13 +192,14 @@ end
|
||||
-- @param Core.Point#COORDINATE Coordinate The coordinate to test.
|
||||
-- @return #boolean true if the coordinate is within the zone.
|
||||
function ZONE_BASE:IsCoordinateInZone( Coordinate )
|
||||
if not Coordinate then return false end
|
||||
local InZone = self:IsVec2InZone( Coordinate:GetVec2() )
|
||||
return InZone
|
||||
end
|
||||
|
||||
--- Returns if a PointVec2 is within the zone. (Name is misleading, actually takes a #COORDINATE)
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param Core.Point#COORDINATE PointVec2 The coordinate to test.
|
||||
-- @param Core.Point#COORDINATE Coordinate The coordinate to test.
|
||||
-- @return #boolean true if the PointVec2 is within the zone.
|
||||
function ZONE_BASE:IsPointVec2InZone( Coordinate )
|
||||
local InZone = self:IsVec2InZone( Coordinate:GetVec2() )
|
||||
@@ -555,6 +559,154 @@ function ZONE_BASE:GetZoneMaybe()
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the check time for ZONE:Trigger()
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param #number seconds Check every seconds for objects entering or leaving the zone. Defaults to 5 secs.
|
||||
-- @return #ZONE_BASE self
|
||||
function ZONE_BASE:SetCheckTime(seconds)
|
||||
self.Checktime = seconds or 5
|
||||
return self
|
||||
end
|
||||
|
||||
--- Start watching if the Object or Objects move into or out of a zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param Wrappe.Controllable#CONTROLLABLE Objects Object or Objects to watch, can be of type UNIT, GROUP, CLIENT, or SET\_UNIT, SET\_GROUP, SET\_CLIENT
|
||||
-- @return #ZONE_BASE self
|
||||
-- @usage
|
||||
-- -- Create a new zone and start watching it every 5 secs for a defined GROUP entering or leaving
|
||||
-- local triggerzone = ZONE:New("ZonetoWatch"):Trigger(GROUP:FindByName("Aerial-1"))
|
||||
--
|
||||
-- -- This FSM function will be called when the group enters the zone
|
||||
-- function triggerzone:OnAfterEnteredZone(From,Event,To,Group)
|
||||
-- MESSAGE:New("Group has entered zone!",15):ToAll()
|
||||
-- end
|
||||
--
|
||||
-- -- This FSM function will be called when the group leaves the zone
|
||||
-- function triggerzone:OnAfterLeftZone(From,Event,To,Group)
|
||||
-- MESSAGE:New("Group has left zone!",15):ToAll()
|
||||
-- end
|
||||
--
|
||||
-- -- Stop watching the zone after 1 hour
|
||||
-- triggerzone:__TriggerStop(3600)
|
||||
function ZONE_BASE:Trigger(Objects)
|
||||
--self:I("Added Zone Trigger")
|
||||
self:SetStartState("TriggerStopped")
|
||||
self:AddTransition("TriggerStopped","TriggerStart","TriggerRunning")
|
||||
self:AddTransition("*","EnteredZone","*")
|
||||
self:AddTransition("*","LeftZone","*")
|
||||
self:AddTransition("*","TriggerRunCheck","*")
|
||||
self:AddTransition("*","TriggerStop","TriggerStopped")
|
||||
self:TriggerStart()
|
||||
self.checkobjects = Objects
|
||||
if UTILS.IsInstanceOf(Objects,"SET_BASE") then
|
||||
self.objectset = Objects.Set
|
||||
else
|
||||
self.objectset = {Objects}
|
||||
end
|
||||
self:_TriggerCheck(true)
|
||||
self:__TriggerRunCheck(self.Checktime)
|
||||
return self
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "TriggerStop". Stops the ZONE_BASE Trigger.
|
||||
-- @function [parent=#ZONE_BASE] TriggerStop
|
||||
-- @param #ZONE_BASE self
|
||||
|
||||
--- Triggers the FSM event "TriggerStop" after a delay.
|
||||
-- @function [parent=#ZONE_BASE] __TriggerStop
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- On After "EnteredZone" event. An observed object has entered the zone.
|
||||
-- @function [parent=#ZONE_BASE] OnAfterEnteredZone
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The controllable entering the zone.
|
||||
|
||||
--- On After "LeftZone" event. An observed object has left the zone.
|
||||
-- @function [parent=#ZONE_BASE] OnAfterLeftZone
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The controllable leaving the zone.
|
||||
end
|
||||
|
||||
--- (Internal) Check the assigned objects for being in/out of the zone
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param #boolean fromstart If true, do the init of the objects
|
||||
-- @return #ZONE_BASE self
|
||||
function ZONE_BASE:_TriggerCheck(fromstart)
|
||||
--self:I("_TriggerCheck | FromStart = "..tostring(fromstart))
|
||||
local objectset = self.objectset or {}
|
||||
if fromstart then
|
||||
-- just earmark everyone in/out
|
||||
for _,_object in pairs(objectset) do
|
||||
local obj = _object -- Wrapper.Controllable#CONTROLLABLE
|
||||
if not obj.TriggerInZone then obj.TriggerInZone = {} end
|
||||
if obj and obj:IsAlive() and self:IsCoordinateInZone(obj:GetCoordinate()) then
|
||||
obj.TriggerInZone[self.ZoneName] = true
|
||||
else
|
||||
obj.TriggerInZone[self.ZoneName] = false
|
||||
end
|
||||
--self:I("Object "..obj:GetName().." is in zone = "..tostring(obj.TriggerInZone[self.ZoneName]))
|
||||
end
|
||||
else
|
||||
-- Check for changes
|
||||
for _,_object in pairs(objectset) do
|
||||
local obj = _object -- Wrapper.Controllable#CONTROLLABLE
|
||||
if obj and obj:IsAlive() then
|
||||
if not obj.TriggerInZone then
|
||||
-- has not been tagged previously - wasn't in set!
|
||||
obj.TriggerInZone = {}
|
||||
end
|
||||
if not obj.TriggerInZone[self.ZoneName] then
|
||||
-- has not been tagged previously - wasn't in set!
|
||||
obj.TriggerInZone[self.ZoneName] = false
|
||||
end
|
||||
-- is obj in zone?
|
||||
local inzone = self:IsCoordinateInZone(obj:GetCoordinate())
|
||||
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
|
||||
if inzone and not obj.TriggerInZone[self.ZoneName] then
|
||||
-- wasn't in zone before
|
||||
--self:I("Newly entered")
|
||||
self:__EnteredZone(0.5,obj)
|
||||
obj.TriggerInZone[self.ZoneName] = true
|
||||
elseif (not inzone) and obj.TriggerInZone[self.ZoneName] then
|
||||
-- has left the zone
|
||||
--self:I("Newly left")
|
||||
self:__LeftZone(0.5,obj)
|
||||
obj.TriggerInZone[self.ZoneName] = false
|
||||
else
|
||||
--self:I("Not left or not entered, or something went wrong!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- (Internal) Check the assigned objects for being in/out of the zone
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string to
|
||||
-- @return #ZONE_BASE self
|
||||
function ZONE_BASE:onafterTriggerRunCheck(From,Event,To)
|
||||
if self:GetState() ~= "TriggerStopped" then
|
||||
self:_TriggerCheck()
|
||||
self:__TriggerRunCheck(self.Checktime)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Returns the Value of the zone with the given PropertyName, or nil if no matching property exists.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param #string PropertyName The name of a the TriggerZone Property to be retrieved.
|
||||
@@ -953,7 +1105,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
|
||||
|
||||
local Include = false
|
||||
if not UnitCategories then
|
||||
-- Anythink found is included.
|
||||
-- Anything found is included.
|
||||
Include = true
|
||||
else
|
||||
-- Check if found object is in specified categories.
|
||||
@@ -984,9 +1136,9 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
|
||||
if ObjectCategory == Object.Category.SCENERY then
|
||||
local SceneryType = ZoneObject:getTypeName()
|
||||
local SceneryName = ZoneObject:getName()
|
||||
--BASE:I("SceneryType "..SceneryType.."SceneryName"..SceneryName)
|
||||
--BASE:I("SceneryType "..SceneryType.." SceneryName "..tostring(SceneryName))
|
||||
self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {}
|
||||
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
|
||||
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( tostring(SceneryName), ZoneObject)
|
||||
table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName] )
|
||||
self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
|
||||
end
|
||||
@@ -1442,8 +1594,11 @@ function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,ma
|
||||
local T1 = timer.getTime()
|
||||
|
||||
local buildings = {}
|
||||
local buildingzones = {}
|
||||
|
||||
if self.ScanData and self.ScanData.BuildingCoordinates then
|
||||
buildings = self.ScanData.BuildingCoordinates
|
||||
buildingzones = self.ScanData.BuildingZones
|
||||
else
|
||||
-- build table of buildings coordinates
|
||||
for _,_object in pairs (objects) do
|
||||
@@ -1455,28 +1610,32 @@ function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,ma
|
||||
MARKER:New(scenery:GetCoordinate(),"Building"):ToAll()
|
||||
end
|
||||
buildings[#buildings+1] = scenery:GetCoordinate()
|
||||
local bradius = scenery:GetBoundingRadius() or dist
|
||||
local bzone = ZONE_RADIUS:New("Building-"..math.random(1,100000),scenery:GetVec2(),bradius,false)
|
||||
buildingzones[#buildingzones+1] = bzone
|
||||
--bzone:DrawZone(-1,{1,0,0},Alpha,FillColor,FillAlpha,1,ReadOnly)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.ScanData.BuildingCoordinates = buildings
|
||||
self.ScanData.BuildingZones = buildingzones
|
||||
end
|
||||
|
||||
-- max 1000 tries
|
||||
local rcoord = nil
|
||||
local found = false
|
||||
local found = true
|
||||
local iterations = 0
|
||||
|
||||
for i=1,1000 do
|
||||
iterations = iterations + 1
|
||||
rcoord = self:GetRandomCoordinate(inner,outer)
|
||||
found = false
|
||||
for _,_coord in pairs (buildings) do
|
||||
local coord = _coord -- Core.Point#COORDINATE
|
||||
found = true
|
||||
for _,_coord in pairs (buildingzones) do
|
||||
local zone = _coord -- Core.Zone#ZONE_RADIUS
|
||||
-- keep >50m dist from buildings
|
||||
if coord:Get3DDistance(rcoord) > dist then
|
||||
found = true
|
||||
else
|
||||
if zone:IsPointVec2InZone(rcoord) then
|
||||
found = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if found then
|
||||
@@ -1488,15 +1647,43 @@ function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,ma
|
||||
end
|
||||
end
|
||||
|
||||
if not found then
|
||||
-- max 1000 tries
|
||||
local rcoord = nil
|
||||
local found = true
|
||||
local iterations = 0
|
||||
|
||||
for i=1,1000 do
|
||||
iterations = iterations + 1
|
||||
rcoord = self:GetRandomCoordinate(inner,outer)
|
||||
found = true
|
||||
for _,_coord in pairs (buildings) do
|
||||
local coord = _coord -- Core.Point#COORDINATE
|
||||
-- keep >50m dist from buildings
|
||||
if coord:Get3DDistance(rcoord) < dist then
|
||||
found = false
|
||||
end
|
||||
end
|
||||
if found then
|
||||
-- we have a winner!
|
||||
if markfinal then
|
||||
MARKER:New(rcoord,"FREE"):ToAll()
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
T1=timer.getTime()
|
||||
|
||||
self:T(string.format("Found a coordinate: %s | Iterations: %d | Time: %d",tostring(found),iterations,T1-T0))
|
||||
self:T(string.format("Found a coordinate: %s | Iterations: %d | Time: %.3f",tostring(found),iterations,T1-T0))
|
||||
|
||||
if found then return rcoord else return nil end
|
||||
|
||||
end
|
||||
|
||||
--- @type ZONE
|
||||
---
|
||||
-- @type ZONE
|
||||
-- @extends #ZONE_RADIUS
|
||||
|
||||
|
||||
@@ -1580,8 +1767,8 @@ function ZONE:FindByName( ZoneName )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @type ZONE_UNIT
|
||||
---
|
||||
-- @type ZONE_UNIT
|
||||
-- @field Wrapper.Unit#UNIT ZoneUNIT
|
||||
-- @extends Core.Zone#ZONE_RADIUS
|
||||
|
||||
@@ -1723,7 +1910,8 @@ function ZONE_UNIT:GetVec3( Height )
|
||||
return Vec3
|
||||
end
|
||||
|
||||
--- @type ZONE_GROUP
|
||||
---
|
||||
-- @type ZONE_GROUP
|
||||
-- @extends #ZONE_RADIUS
|
||||
|
||||
|
||||
@@ -1809,7 +1997,8 @@ function ZONE_GROUP:GetRandomPointVec2( inner, outer )
|
||||
end
|
||||
|
||||
|
||||
--- @type ZONE_POLYGON_BASE
|
||||
---
|
||||
-- @type ZONE_POLYGON_BASE
|
||||
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}.
|
||||
-- @extends #ZONE_BASE
|
||||
|
||||
@@ -2458,7 +2647,8 @@ function ZONE_POLYGON_BASE:Boundary(Coalition, Color, Radius, Alpha, Segments, C
|
||||
return self
|
||||
end
|
||||
|
||||
--- @type ZONE_POLYGON
|
||||
---
|
||||
-- @type ZONE_POLYGON
|
||||
-- @extends #ZONE_POLYGON_BASE
|
||||
|
||||
|
||||
@@ -2586,7 +2776,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
|
||||
local minmarkcoord = COORDINATE:NewFromVec3(minVec3)
|
||||
local maxmarkcoord = COORDINATE:NewFromVec3(maxVec3)
|
||||
local ZoneRadius = minmarkcoord:Get2DDistance(maxmarkcoord)/2
|
||||
|
||||
-- self:I("Scan Radius:" ..ZoneRadius)
|
||||
local CenterVec3 = self:GetCoordinate():GetVec3()
|
||||
|
||||
--[[ this a bit shaky in functionality it seems
|
||||
@@ -2909,7 +3099,7 @@ end
|
||||
|
||||
do -- ZONE_ELASTIC
|
||||
|
||||
--- @type ZONE_ELASTIC
|
||||
-- @type ZONE_ELASTIC
|
||||
-- @field #table points Points in 2D.
|
||||
-- @field #table setGroups Set of GROUPs.
|
||||
-- @field #table setOpsGroups Set of OPSGROUPS.
|
||||
@@ -3109,7 +3299,7 @@ end
|
||||
|
||||
do -- ZONE_AIRBASE
|
||||
|
||||
--- @type ZONE_AIRBASE
|
||||
-- @type ZONE_AIRBASE
|
||||
-- @field #boolean isShip If `true`, airbase is a ship.
|
||||
-- @field #boolean isHelipad If `true`, airbase is a helipad.
|
||||
-- @field #boolean isAirdrome If `true`, airbase is an airdrome.
|
||||
|
||||
+194
-64
@@ -135,6 +135,22 @@ do -- env
|
||||
|
||||
end -- env
|
||||
|
||||
do -- radio
|
||||
|
||||
---@type radio
|
||||
-- @field #radio.modulation modulation
|
||||
|
||||
---
|
||||
-- @type radio.modulation
|
||||
-- @field AM
|
||||
-- @field FM
|
||||
|
||||
radio = {}
|
||||
radio.modulation = {}
|
||||
radio.modulation.AM = 0
|
||||
radio.modulation.FM = 1
|
||||
|
||||
end
|
||||
|
||||
do -- timer
|
||||
|
||||
@@ -329,11 +345,11 @@ end -- country
|
||||
|
||||
do -- Command
|
||||
|
||||
--- @type Command
|
||||
-- @type Command
|
||||
-- @field #string id
|
||||
-- @field #Command.params params
|
||||
|
||||
--- @type Command.params
|
||||
-- @type Command.params
|
||||
|
||||
end -- Command
|
||||
|
||||
@@ -374,7 +390,7 @@ end -- coalition
|
||||
|
||||
do -- Types
|
||||
|
||||
--- @type Desc
|
||||
-- @type Desc
|
||||
-- @field #number speedMax0 Max speed in meters/second at zero altitude.
|
||||
-- @field #number massEmpty Empty mass in kg.
|
||||
-- @field #number tankerType Type of refueling system: 0=boom, 1=probe.
|
||||
@@ -471,16 +487,16 @@ do -- Types
|
||||
-- @type AttributeNameArray
|
||||
-- @list <#AttributeName>
|
||||
|
||||
--- @type Zone
|
||||
-- @type Zone
|
||||
-- @field DCSVec3#Vec3 point
|
||||
-- @field #number radius
|
||||
|
||||
Zone = {}
|
||||
|
||||
--- @type ModelTime
|
||||
-- @type ModelTime
|
||||
-- @extends #number
|
||||
|
||||
--- @type Time
|
||||
-- @type Time
|
||||
-- @extends #number
|
||||
|
||||
--- A task descriptor (internal structure for DCS World). See [https://wiki.hoggitworld.com/view/Category:Tasks](https://wiki.hoggitworld.com/view/Category:Tasks).
|
||||
@@ -489,7 +505,7 @@ do -- Types
|
||||
-- @field #string id
|
||||
-- @field #Task.param param
|
||||
|
||||
--- @type Task.param
|
||||
-- @type Task.param
|
||||
|
||||
--- List of @{#Task}
|
||||
-- @type TaskArray
|
||||
@@ -536,7 +552,7 @@ do -- Object
|
||||
-- @field SCENERY
|
||||
-- @field CARGO
|
||||
|
||||
--- @type Object.Desc
|
||||
-- @type Object.Desc
|
||||
-- @extends #Desc
|
||||
-- @field #number life initial life level
|
||||
-- @field #Box3 box bounding box of collision geometry
|
||||
@@ -793,11 +809,118 @@ do -- Airbase
|
||||
-- @function [parent=#Airbase] getDesc
|
||||
-- @param self
|
||||
-- @return #Airbase.Desc
|
||||
|
||||
|
||||
--- Returns the warehouse object associated with the airbase object. Can then be used to call the warehouse class functions to modify the contents of the warehouse.
|
||||
-- @function [parent=#Airbase] getWarehouse
|
||||
-- @param self
|
||||
-- @return #Warehouse The DCS warehouse object of this airbase.
|
||||
|
||||
--- Enables or disables the airbase and FARP auto capture game mechanic where ownership of a base can change based on the presence of ground forces or the
|
||||
-- default setting assigned in the editor.
|
||||
-- @function [parent=#Airbase] autoCapture
|
||||
-- @param self
|
||||
-- @param #boolean setting `true` : enables autoCapture behavior, `false` : disables autoCapture behavior
|
||||
|
||||
--- Returns the current autoCapture setting for the passed base.
|
||||
-- @function [parent=#Airbase] autoCaptureIsOn
|
||||
-- @param self
|
||||
-- @return #boolean `true` if autoCapture behavior is enabled and `false` otherwise.
|
||||
|
||||
--- Changes the passed airbase object's coalition to the set value. Must be used with Airbase.autoCapture to disable auto capturing of the base,
|
||||
-- otherwise the base can revert back to a different coalition depending on the situation and built in game capture rules.
|
||||
-- @function [parent=#Airbase] setCoalition
|
||||
-- @param self
|
||||
-- @param #number coa The new owner coalition: 0=neutra, 1=red, 2=blue.
|
||||
|
||||
--- Returns the wsType of every object that exists in DCS. A wsType is a table consisting of 4 entries indexed numerically.
|
||||
-- It can be used to broadly categorize object types. The table can be broken down as: {mainCategory, subCat1, subCat2, index}
|
||||
-- @function [parent=#Airbase] getResourceMap
|
||||
-- @param self
|
||||
-- @return #table wsType of every object that exists in DCS.
|
||||
|
||||
Airbase = {} --#Airbase
|
||||
|
||||
end -- Airbase
|
||||
|
||||
|
||||
do -- Warehouse
|
||||
|
||||
--- [DCS Class Warehouse](https://wiki.hoggitworld.com/view/DCS_Class_Warehouse)
|
||||
-- The warehouse class gives control over warehouses that exist in airbase objects. These warehouses can limit the aircraft, munitions, and fuel available to coalition aircraft.
|
||||
-- @type Warehouse
|
||||
|
||||
|
||||
--- Get a warehouse by passing its name.
|
||||
-- @function [parent=#Warehouse] getByName
|
||||
-- @param #string Name Name of the warehouse.
|
||||
-- @return #Warehouse The warehouse object.
|
||||
|
||||
--- Adds the passed amount of a given item to the warehouse.
|
||||
-- itemName is the typeName associated with the item: "weapons.missiles.AIM_54C_Mk47"
|
||||
-- A wsType table can also be used, however the last digit with wsTypes has been known to change. {4, 4, 7, 322}
|
||||
-- @function [parent=#Warehouse] addItem
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
-- @param #number count Number of items to add.
|
||||
|
||||
--- Returns the number of the passed type of item currently in a warehouse object.
|
||||
-- @function [parent=#Warehouse] getItemCount
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
|
||||
--- Sets the passed amount of a given item to the warehouse.
|
||||
-- @function [parent=#Warehouse] setItem
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
-- @param #number count Number of items to add.
|
||||
|
||||
--- Removes the amount of the passed item from the warehouse.
|
||||
-- @function [parent=#Warehouse] removeItem
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
-- @param #number count Number of items to be removed.
|
||||
|
||||
--- Adds the passed amount of a liquid fuel into the warehouse inventory.
|
||||
-- @function [parent=#Warehouse] addLiquid
|
||||
-- @param self
|
||||
-- @param #number liquidType Type of liquid to add: 0=jetfuel, 1=aviation gasoline, 2=MW50, 3=Diesel.
|
||||
-- @param #number count Amount of liquid to add.
|
||||
|
||||
--- Returns the amount of the passed liquid type within a given warehouse.
|
||||
-- @function [parent=#Warehouse] getLiquidAmount
|
||||
-- @param self
|
||||
-- @param #number liquidType Type of liquid to add: 0=jetfuel, 1=aviation gasoline, 2=MW50, 3=Diesel.
|
||||
-- @return #number Amount of liquid.
|
||||
|
||||
--- Sets the passed amount of a liquid fuel into the warehouse inventory.
|
||||
-- @function [parent=#Warehouse] setLiquidAmount
|
||||
-- @param self
|
||||
-- @param #number liquidType Type of liquid to add: 0=jetfuel, 1=aviation gasoline, 2=MW50, 3=Diesel.
|
||||
-- @param #number count Amount of liquid.
|
||||
|
||||
--- Removes the set amount of liquid from the inventory in a warehouse.
|
||||
-- @function [parent=#Warehouse] setLiquidAmount
|
||||
-- @param self
|
||||
-- @param #number liquidType Type of liquid to add: 0=jetfuel, 1=aviation gasoline, 2=MW50, 3=Diesel.
|
||||
-- @param #number count Amount of liquid.
|
||||
|
||||
--- Returns the airbase object associated with the warehouse object.
|
||||
-- @function [parent=#Warehouse] getOwner
|
||||
-- @param self
|
||||
-- @return #Airbase The airbase object owning this warehouse.
|
||||
|
||||
--- Returns a full itemized list of everything currently in a warehouse. If a category is set to unlimited then the table will be returned empty.
|
||||
-- Aircraft and weapons are indexed by strings. Liquids are indexed by number.
|
||||
-- @function [parent=#Warehouse] getInventory
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
-- @return #table Itemized list of everything currently in a warehouse
|
||||
|
||||
|
||||
Warehouse = {} --#Warehouse
|
||||
|
||||
end
|
||||
|
||||
do -- Spot
|
||||
|
||||
--- [DCS Class Spot](https://wiki.hoggitworld.com/view/DCS_Class_Spot)
|
||||
@@ -860,7 +983,7 @@ do -- Spot
|
||||
end -- Spot
|
||||
|
||||
do -- Controller
|
||||
--- Controller is an object that performs A.I.-routines. Other words controller is an instance of A.I.. Controller stores current main task, active enroute tasks and behavior options. Controller performs commands. Please, read DCS A-10C GUI Manual EN.pdf chapter "Task Planning for Unit Groups", page 91 to understand A.I. system of DCS:A-10C.
|
||||
--- Controller is an object that performs A.I.-tasks. Other words controller is an instance of A.I.. Controller stores current main task, active enroute tasks and behavior options. Controller performs commands. Please, read DCS A-10C GUI Manual EN.pdf chapter "Task Planning for Unit Groups", page 91 to understand A.I. system of DCS:A-10C.
|
||||
--
|
||||
-- This class has 2 types of functions:
|
||||
--
|
||||
@@ -978,7 +1101,7 @@ end -- Controller
|
||||
|
||||
do -- Unit
|
||||
|
||||
--- @type Unit
|
||||
-- @type Unit
|
||||
-- @extends #CoalitionObject
|
||||
-- @field ID Identifier of an unit. It assigned to an unit by the Mission Editor automatically.
|
||||
-- @field #Unit.Category Category
|
||||
@@ -1093,15 +1216,18 @@ do -- Unit
|
||||
-- @field #Distance detectionDistanceHRM detection distance for RCS=1m^2 in high-resolution mapping mode, nil if radar has no HRM
|
||||
-- @field #Unit.Radar.detectionDistanceAir detectionDistanceAir detection distance for RCS=1m^2 airborne target, nil if radar doesn't support air search
|
||||
|
||||
--- @type Unit.Radar.detectionDistanceAir
|
||||
--- A radar.
|
||||
-- @type Unit.Radar.detectionDistanceAir
|
||||
-- @field #Unit.Radar.detectionDistanceAir.upperHemisphere upperHemisphere
|
||||
-- @field #Unit.Radar.detectionDistanceAir.lowerHemisphere lowerHemisphere
|
||||
|
||||
--- @type Unit.Radar.detectionDistanceAir.upperHemisphere
|
||||
--- A radar.
|
||||
-- @type Unit.Radar.detectionDistanceAir.upperHemisphere
|
||||
-- @field #Distance headOn
|
||||
-- @field #Distance tailOn
|
||||
|
||||
--- @type Unit.Radar.detectionDistanceAir.lowerHemisphere
|
||||
--- A radar.
|
||||
-- @type Unit.Radar.detectionDistanceAir.lowerHemisphere
|
||||
-- @field #Distance headOn
|
||||
-- @field #Distance tailOn
|
||||
|
||||
@@ -1403,22 +1529,26 @@ do -- AI
|
||||
-- @field IR_POINTER
|
||||
-- @field LASER
|
||||
|
||||
--- @type AI.Task.WaypointType
|
||||
---
|
||||
-- @type AI.Task.WaypointType
|
||||
-- @field TAKEOFF
|
||||
-- @field TAKEOFF_PARKING
|
||||
-- @field TURNING_POINT
|
||||
-- @field TAKEOFF_PARKING_HOT
|
||||
-- @field LAND
|
||||
|
||||
--- @type AI.Task.TurnMethod
|
||||
---
|
||||
-- @type AI.Task.TurnMethod
|
||||
-- @field FLY_OVER_POINT
|
||||
-- @field FIN_POINT
|
||||
|
||||
--- @type AI.Task.AltitudeType
|
||||
---
|
||||
-- @type AI.Task.AltitudeType
|
||||
-- @field BARO
|
||||
-- @field RADIO
|
||||
|
||||
--- @type AI.Task.VehicleFormation
|
||||
---
|
||||
-- @type AI.Task.VehicleFormation
|
||||
-- @field OFF_ROAD
|
||||
-- @field ON_ROAD
|
||||
-- @field RANK
|
||||
@@ -1428,27 +1558,30 @@ do -- AI
|
||||
-- @field ECHELON_LEFT
|
||||
-- @field ECHELON_RIGHT
|
||||
|
||||
--- @type AI.Option
|
||||
---
|
||||
-- @type AI.Option
|
||||
-- @field #AI.Option.Air Air
|
||||
-- @field #AI.Option.Ground Ground
|
||||
-- @field #AI.Option.Naval Naval
|
||||
|
||||
--- @type AI.Option.Air
|
||||
---
|
||||
-- @type AI.Option.Air
|
||||
-- @field #AI.Option.Air.id id
|
||||
-- @field #AI.Option.Air.val val
|
||||
|
||||
--- @type AI.Option.Ground
|
||||
---
|
||||
-- @type AI.Option.Ground
|
||||
-- @field #AI.Option.Ground.id id
|
||||
-- @field #AI.Option.Ground.val val
|
||||
-- @field #AI.Option.Ground.mid mid
|
||||
-- @field #AI.Option.Ground.mval mval
|
||||
--
|
||||
--- @type AI.Option.Naval
|
||||
-- @type AI.Option.Naval
|
||||
-- @field #AI.Option.Naval.id id
|
||||
-- @field #AI.Option.Naval.val val
|
||||
|
||||
|
||||
--- @type AI.Option.Air.id
|
||||
---
|
||||
-- @type AI.Option.Air.id
|
||||
-- @field NO_OPTION
|
||||
-- @field ROE
|
||||
-- @field REACTION_ON_THREAT
|
||||
@@ -1470,73 +1603,61 @@ do -- AI
|
||||
-- @field OPTION_RADIO_USAGE_KILL
|
||||
-- @field JETT_TANKS_IF_EMPTY
|
||||
-- @field FORCED_ATTACK
|
||||
|
||||
--- @type AI.Option.Air.id.FORMATION
|
||||
-- @field LINE_ABREAST
|
||||
-- @field TRAIL
|
||||
-- @field WEDGE
|
||||
-- @field ECHELON_RIGHT
|
||||
-- @field ECHELON_LEFT
|
||||
-- @field FINGER_FOUR
|
||||
-- @field SPREAD_FOUR
|
||||
-- @field WW2_BOMBER_ELEMENT
|
||||
-- @field WW2_BOMBER_ELEMENT_HEIGHT
|
||||
-- @field WW2_FIGHTER_VIC
|
||||
-- @field HEL_WEDGE
|
||||
-- @field HEL_ECHELON
|
||||
-- @field HEL_FRONT
|
||||
-- @field HEL_COLUMN
|
||||
-- @field COMBAT_BOX
|
||||
-- @field JAVELIN_DOWN
|
||||
|
||||
|
||||
--- @type AI.Option.Air.val
|
||||
---
|
||||
-- @type AI.Option.Air.val
|
||||
-- @field #AI.Option.Air.val.ROE ROE
|
||||
-- @field #AI.Option.Air.val.REACTION_ON_THREAT REACTION_ON_THREAT
|
||||
-- @field #AI.Option.Air.val.RADAR_USING RADAR_USING
|
||||
-- @field #AI.Option.Air.val.FLARE_USING FLARE_USING
|
||||
|
||||
--- @type AI.Option.Air.val.ROE
|
||||
---
|
||||
-- @type AI.Option.Air.val.ROE
|
||||
-- @field WEAPON_FREE
|
||||
-- @field OPEN_FIRE_WEAPON_FREE
|
||||
-- @field OPEN_FIRE
|
||||
-- @field RETURN_FIRE
|
||||
-- @field WEAPON_HOLD
|
||||
|
||||
--- @type AI.Option.Air.val.REACTION_ON_THREAT
|
||||
|
||||
---
|
||||
-- @type AI.Option.Air.val.REACTION_ON_THREAT
|
||||
-- @field NO_REACTION
|
||||
-- @field PASSIVE_DEFENCE
|
||||
-- @field EVADE_FIRE
|
||||
-- @field BYPASS_AND_ESCAPE
|
||||
-- @field ALLOW_ABORT_MISSION
|
||||
|
||||
--- @type AI.Option.Air.val.RADAR_USING
|
||||
---
|
||||
-- @type AI.Option.Air.val.RADAR_USING
|
||||
-- @field NEVER
|
||||
-- @field FOR_ATTACK_ONLY
|
||||
-- @field FOR_SEARCH_IF_REQUIRED
|
||||
-- @field FOR_CONTINUOUS_SEARCH
|
||||
|
||||
--- @type AI.Option.Air.val.FLARE_USING
|
||||
---
|
||||
-- @type AI.Option.Air.val.FLARE_USING
|
||||
-- @field NEVER
|
||||
-- @field AGAINST_FIRED_MISSILE
|
||||
-- @field WHEN_FLYING_IN_SAM_WEZ
|
||||
-- @field WHEN_FLYING_NEAR_ENEMIES
|
||||
|
||||
--- @type AI.Option.Air.val.ECM_USING
|
||||
|
||||
---
|
||||
-- @type AI.Option.Air.val.ECM_USING
|
||||
-- @field NEVER_USE
|
||||
-- @field USE_IF_ONLY_LOCK_BY_RADAR
|
||||
-- @field USE_IF_DETECTED_LOCK_BY_RADAR
|
||||
-- @field ALWAYS_USE
|
||||
|
||||
--- @type AI.Option.Air.val.MISSILE_ATTACK
|
||||
|
||||
---
|
||||
-- @type AI.Option.Air.val.MISSILE_ATTACK
|
||||
-- @field MAX_RANGE
|
||||
-- @field NEZ_RANGE
|
||||
-- @field HALF_WAY_RMAX_NEZ
|
||||
-- @field TARGET_THREAT_EST
|
||||
-- @field RANDOM_RANGE
|
||||
|
||||
|
||||
--- @type AI.Option.Ground.id
|
||||
---
|
||||
-- @type AI.Option.Ground.id
|
||||
-- @field NO_OPTION
|
||||
-- @field ROE @{#AI.Option.Ground.val.ROE}
|
||||
-- @field FORMATION
|
||||
@@ -1545,42 +1666,51 @@ do -- AI
|
||||
-- @field ENGAGE_AIR_WEAPONS
|
||||
-- @field AC_ENGAGEMENT_RANGE_RESTRICTION
|
||||
|
||||
--- @type AI.Option.Ground.mid -- Moose added
|
||||
---
|
||||
-- @type AI.Option.Ground.mid -- Moose added
|
||||
-- @field RESTRICT_AAA_MIN 27
|
||||
-- @field RESTRICT_AAA_MAX 29
|
||||
-- @field RESTRICT_TARGETS @{#AI.Option.Ground.mval.ENGAGE_TARGETS} 28
|
||||
|
||||
--- @type AI.Option.Ground.val
|
||||
---
|
||||
-- @type AI.Option.Ground.val
|
||||
-- @field #AI.Option.Ground.val.ROE ROE
|
||||
-- @field #AI.Option.Ground.val.ALARM_STATE ALARM_STATE
|
||||
-- @field #AI.Option.Ground.val.ENGAGE_TARGETS RESTRICT_TARGETS
|
||||
|
||||
--- @type AI.Option.Ground.val.ROE
|
||||
---
|
||||
-- @type AI.Option.Ground.val.ROE
|
||||
-- @field OPEN_FIRE
|
||||
-- @field RETURN_FIRE
|
||||
-- @field WEAPON_HOLD
|
||||
|
||||
--- @type AI.Option.Ground.mval -- Moose added
|
||||
---
|
||||
-- @type AI.Option.Ground.mval -- Moose added
|
||||
-- @field #AI.Option.Ground.mval.ENGAGE_TARGETS ENGAGE_TARGETS
|
||||
|
||||
--- @type AI.Option.Ground.mval.ENGAGE_TARGETS -- Moose added
|
||||
---
|
||||
-- @type AI.Option.Ground.mval.ENGAGE_TARGETS -- Moose added
|
||||
-- @field ANY_TARGET -- 0
|
||||
-- @field AIR_UNITS_ONLY -- 1
|
||||
-- @field GROUND_UNITS_ONLY -- 2
|
||||
|
||||
--- @type AI.Option.Ground.val.ALARM_STATE
|
||||
---
|
||||
-- @type AI.Option.Ground.val.ALARM_STATE
|
||||
-- @field AUTO
|
||||
-- @field GREEN
|
||||
-- @field RED
|
||||
|
||||
--- @type AI.Option.Naval.id
|
||||
---
|
||||
-- @type AI.Option.Naval.id
|
||||
-- @field NO_OPTION
|
||||
-- @field ROE
|
||||
|
||||
--- @type AI.Option.Naval.val
|
||||
---
|
||||
-- @type AI.Option.Naval.val
|
||||
-- @field #AI.Option.Naval.val.ROE ROE
|
||||
|
||||
--- @type AI.Option.Naval.val.ROE
|
||||
---
|
||||
-- @type AI.Option.Naval.val.ROE
|
||||
-- @field OPEN_FIRE
|
||||
-- @field RETURN_FIRE
|
||||
-- @field WEAPON_HOLD
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **Applevangelist**
|
||||
-- Last Update July 2023
|
||||
-- Last Update Sept 2023
|
||||
--
|
||||
-- ===
|
||||
-- @module Functional.AICSAR
|
||||
@@ -191,7 +191,7 @@
|
||||
-- @field #AICSAR
|
||||
AICSAR = {
|
||||
ClassName = "AICSAR",
|
||||
version = "0.1.15",
|
||||
version = "0.1.16",
|
||||
lid = "",
|
||||
coalition = coalition.side.BLUE,
|
||||
template = "",
|
||||
@@ -889,7 +889,7 @@ function AICSAR:_InitMission(Pilot,Index)
|
||||
|
||||
-- Cargo transport assignment.
|
||||
local opstransport=OPSTRANSPORT:New(Pilot, pickupzone, self.farpzone)
|
||||
|
||||
--opstransport:SetVerbosity(3)
|
||||
|
||||
local helo = self:_GetFlight()
|
||||
-- inject reservation
|
||||
@@ -915,8 +915,9 @@ function AICSAR:_InitMission(Pilot,Index)
|
||||
self:__PilotUnloaded(2,Helo,OpsGroup)
|
||||
end
|
||||
|
||||
function helo:OnAfterLoadingDone(From,Event,To)
|
||||
AICPickedUp(helo,helo:GetCargoGroups(),Index)
|
||||
function helo:OnAfterLoading(From,Event,To)
|
||||
AICPickedUp(helo,helo:GetCargoGroups(),Index)
|
||||
helo:__LoadingDone(5)
|
||||
end
|
||||
|
||||
function helo:OnAfterDead(From,Event,To)
|
||||
@@ -925,6 +926,7 @@ function AICSAR:_InitMission(Pilot,Index)
|
||||
|
||||
function helo:OnAfterUnloaded(From,Event,To,OpsGroupCargo)
|
||||
AICHeloUnloaded(helo,OpsGroupCargo)
|
||||
helo:__UnloadingDone(5)
|
||||
end
|
||||
|
||||
self.helos[Index] = helo
|
||||
|
||||
@@ -108,8 +108,8 @@
|
||||
-- @image Escorting.JPG
|
||||
|
||||
|
||||
|
||||
--- @type ESCORT
|
||||
---
|
||||
-- @type ESCORT
|
||||
-- @extends Core.Base#BASE
|
||||
-- @field Wrapper.Client#CLIENT EscortClient
|
||||
-- @field Wrapper.Group#GROUP EscortGroup
|
||||
@@ -600,7 +600,7 @@ function ESCORT:MenuReportTargets( Seconds )
|
||||
self.EscortMenuAttackNearbyTargets = MENU_GROUP:New( self.EscortClient:GetGroup(), "Attack targets", self.EscortMenu )
|
||||
|
||||
|
||||
self.ReportTargetsScheduler = SCHEDULER:New( self, self._ReportTargetsScheduler, {}, 1, Seconds )
|
||||
self.ReportTargetsScheduler, self.ReportTargetsSchedulerID = SCHEDULER:New( self, self._ReportTargetsScheduler, {}, 1, Seconds )
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -693,7 +693,7 @@ function ESCORT:MenuResumeMission()
|
||||
end
|
||||
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_HoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds )
|
||||
|
||||
local EscortGroup = self.EscortGroup
|
||||
@@ -733,7 +733,7 @@ function ESCORT:_HoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds )
|
||||
|
||||
end
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_JoinUpAndFollow( Distance )
|
||||
|
||||
local EscortGroup = self.EscortGroup
|
||||
@@ -766,7 +766,7 @@ function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
|
||||
EscortGroup:MessageToClient( "Rejoining and Following at " .. Distance .. "!", 30, EscortClient )
|
||||
end
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_Flare( Color, Message )
|
||||
|
||||
local EscortGroup = self.EscortGroup
|
||||
@@ -776,7 +776,7 @@ function ESCORT:_Flare( Color, Message )
|
||||
EscortGroup:MessageToClient( Message, 10, EscortClient )
|
||||
end
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_Smoke( Color, Message )
|
||||
|
||||
local EscortGroup = self.EscortGroup
|
||||
@@ -787,7 +787,7 @@ function ESCORT:_Smoke( Color, Message )
|
||||
end
|
||||
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_ReportNearbyTargetsNow()
|
||||
|
||||
local EscortGroup = self.EscortGroup
|
||||
@@ -809,12 +809,12 @@ function ESCORT:_SwitchReportNearbyTargets( ReportTargets )
|
||||
self.ReportTargetsScheduler:Schedule( self, self._ReportTargetsScheduler, {}, 1, 30 )
|
||||
end
|
||||
else
|
||||
routines.removeFunction( self.ReportTargetsScheduler )
|
||||
self.ReportTargetsScheduler:Remove(self.ReportTargetsSchedulerID)
|
||||
self.ReportTargetsScheduler = nil
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_ScanTargets( ScanDuration )
|
||||
|
||||
local EscortGroup = self.EscortGroup -- Wrapper.Group#GROUP
|
||||
@@ -844,7 +844,7 @@ function ESCORT:_ScanTargets( ScanDuration )
|
||||
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
function _Resume( EscortGroup )
|
||||
env.info( '_Resume' )
|
||||
|
||||
@@ -856,7 +856,7 @@ function _Resume( EscortGroup )
|
||||
|
||||
end
|
||||
|
||||
--- @param #ESCORT self
|
||||
-- @param #ESCORT self
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
function ESCORT:_AttackTarget( DetectedItem )
|
||||
|
||||
@@ -877,7 +877,7 @@ function ESCORT:_AttackTarget( DetectedItem )
|
||||
local Tasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
Tasks[#Tasks+1] = EscortGroup:TaskAttackUnit( DetectedUnit )
|
||||
@@ -900,7 +900,7 @@ function ESCORT:_AttackTarget( DetectedItem )
|
||||
local Tasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
|
||||
@@ -921,7 +921,7 @@ function ESCORT:_AttackTarget( DetectedItem )
|
||||
end
|
||||
|
||||
---
|
||||
--- @param #ESCORT self
|
||||
-- @param #ESCORT self
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
function ESCORT:_AssistTarget( EscortGroupAttack, DetectedItem )
|
||||
|
||||
@@ -939,7 +939,7 @@ function ESCORT:_AssistTarget( EscortGroupAttack, DetectedItem )
|
||||
local Tasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
Tasks[#Tasks+1] = EscortGroupAttack:TaskAttackUnit( DetectedUnit )
|
||||
@@ -961,7 +961,7 @@ function ESCORT:_AssistTarget( EscortGroupAttack, DetectedItem )
|
||||
local Tasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
Tasks[#Tasks+1] = EscortGroupAttack:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
|
||||
@@ -981,7 +981,7 @@ function ESCORT:_AssistTarget( EscortGroupAttack, DetectedItem )
|
||||
|
||||
end
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_ROE( EscortROEFunction, EscortROEMessage )
|
||||
|
||||
local EscortGroup = self.EscortGroup
|
||||
@@ -991,7 +991,7 @@ function ESCORT:_ROE( EscortROEFunction, EscortROEMessage )
|
||||
EscortGroup:MessageToClient( EscortROEMessage, 10, EscortClient )
|
||||
end
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_ROT( EscortROTFunction, EscortROTMessage )
|
||||
|
||||
local EscortGroup = self.EscortGroup
|
||||
@@ -1001,7 +1001,7 @@ function ESCORT:_ROT( EscortROTFunction, EscortROTMessage )
|
||||
EscortGroup:MessageToClient( EscortROTMessage, 10, EscortClient )
|
||||
end
|
||||
|
||||
--- @param #MENUPARAM MenuParam
|
||||
-- @param #MENUPARAM MenuParam
|
||||
function ESCORT:_ResumeMission( WayPoint )
|
||||
|
||||
local EscortGroup = self.EscortGroup
|
||||
@@ -1036,7 +1036,7 @@ function ESCORT:RegisterRoute()
|
||||
return TaskPoints
|
||||
end
|
||||
|
||||
--- @param Functional.Escort#ESCORT self
|
||||
-- @param Functional.Escort#ESCORT self
|
||||
function ESCORT:_FollowScheduler()
|
||||
self:F( { self.FollowDistance } )
|
||||
|
||||
|
||||
@@ -113,14 +113,9 @@
|
||||
-- -- Start missile trainer.
|
||||
-- fox:Start()
|
||||
--
|
||||
-- # Fine Tuning
|
||||
--
|
||||
-- Todo!
|
||||
--
|
||||
-- # Special Events
|
||||
--
|
||||
-- Todo!
|
||||
-- # Notes
|
||||
--
|
||||
-- The script needs to be running before you enter an airplane slot. If FOX is not available to you, go back to observers and then join a slot again.
|
||||
--
|
||||
-- @field #FOX
|
||||
FOX = {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
-- @module Functional.Mantis
|
||||
-- @image Functional.Mantis.jpg
|
||||
--
|
||||
-- Last Update: July 2023
|
||||
-- Last Update: Sept 2023
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **MANTIS** class, extends Core.Base#BASE
|
||||
@@ -431,22 +431,24 @@ MANTIS.SamDataCH = {
|
||||
-- units from CH (Military Assets by Currenthill)
|
||||
-- https://www.currenthill.com/
|
||||
-- group name MUST contain CHM to ID launcher type correctly!
|
||||
["2S38 CH"] = { Range=8, Blindspot=0.5, Height=6, Type="Short", Radar="2S38" },
|
||||
["PantsirS1 CH"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" },
|
||||
["PantsirS2 CH"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
|
||||
["PGL-625 CH"] = { Range=10, Blindspot=0.5, Height=5, Type="Short", Radar="PGL_625" },
|
||||
["HQ-17A CH"] = { Range=20, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
|
||||
["M903PAC2 CH"] = { Range=160, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
|
||||
["M903PAC3 CH"] = { Range=120, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
|
||||
["TorM2 CH"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" },
|
||||
["TorM2K CH"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" },
|
||||
["TorM2M CH"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" },
|
||||
["NASAMS3-AMRAAMER CH"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
|
||||
["NASAMS3-AIM9X2 CH"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
|
||||
["C-RAM CH"] = { Range=2, Blindspot=0, Height=2, Type="Short", Radar="CH_Centurion_C_RAM" },
|
||||
["PGZ-09 CH"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="CH_PGZ09" },
|
||||
["S350-9M100 CH"] = { Range=15, Blindspot=1.5, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
|
||||
["S350-9M96D CH"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" },
|
||||
["2S38 CH"] = { Range=8, Blindspot=0.5, Height=6, Type="Short", Radar="2S38" },
|
||||
["PantsirS1 CH"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" },
|
||||
["PantsirS2 CH"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
|
||||
["PGL-625 CH"] = { Range=10, Blindspot=0.5, Height=5, Type="Short", Radar="PGL_625" },
|
||||
["HQ-17A CH"] = { Range=20, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
|
||||
["M903PAC2 CH"] = { Range=160, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
|
||||
["M903PAC3 CH"] = { Range=120, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
|
||||
["TorM2 CH"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" },
|
||||
["TorM2K CH"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" },
|
||||
["TorM2M CH"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" },
|
||||
["NASAMS3-AMRAAMER CH"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
|
||||
["NASAMS3-AIM9X2 CH"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
|
||||
["C-RAM CH"] = { Range=2, Blindspot=0, Height=2, Type="Short", Radar="CH_Centurion_C_RAM" },
|
||||
["PGZ-09 CH"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="CH_PGZ09" },
|
||||
["S350-9M100 CH"] = { Range=15, Blindspot=1.5, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
|
||||
["S350-9M96D CH"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" },
|
||||
["LAV-AD CH"] = { Range=8, Blindspot=0.2, Height=4.8, Type="Short", Radar="CH_LAVAD" },
|
||||
["HQ-22 CH"] = { Range=170, Blindspot=5, Height=27, Type="Long", Radar="CH_HQ22_LN" },
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
@@ -465,6 +467,7 @@ do
|
||||
--@param #string awacs Group name of your Awacs (optional)
|
||||
--@param #boolean EmOnOff Make MANTIS switch Emissions on and off instead of changing the alarm state between RED and GREEN (optional)
|
||||
--@param #number Padding For #SEAD - Extra number of seconds to add to radar switch-back-on time (optional)
|
||||
--@param #table Zones Table of Core.Zone#ZONE Zones Consider SAM groups in this zone(s) only for this MANTIS instance, must be handed as #table of Zone objects
|
||||
--@return #MANTIS self
|
||||
--@usage Start up your MANTIS with a basic setting
|
||||
--
|
||||
@@ -483,7 +486,7 @@ do
|
||||
-- mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
|
||||
-- mybluemantis:Start()
|
||||
--
|
||||
function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs, EmOnOff, Padding)
|
||||
function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs, EmOnOff, Padding, Zones)
|
||||
|
||||
-- DONE: Create some user functions for these
|
||||
-- DONE: Make HQ useful
|
||||
@@ -544,6 +547,7 @@ do
|
||||
self.maxclassic = 6
|
||||
self.autoshorad = true
|
||||
self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP
|
||||
self.FilterZones = Zones
|
||||
|
||||
self.UseEmOnOff = true
|
||||
if EmOnOff == false then
|
||||
@@ -593,16 +597,23 @@ do
|
||||
|
||||
self:T({self.ewr_templates})
|
||||
|
||||
self.SAM_Group = SET_GROUP:New():FilterPrefixes(self.SAM_Templates_Prefix):FilterCoalitions(self.Coalition)
|
||||
self.EWR_Group = SET_GROUP:New():FilterPrefixes(self.ewr_templates):FilterCoalitions(self.Coalition)
|
||||
|
||||
if self.FilterZones then
|
||||
self.SAM_Group:FilterZones(self.FilterZones)
|
||||
end
|
||||
|
||||
if self.dynamic then
|
||||
-- Set SAM SET_GROUP
|
||||
self.SAM_Group = SET_GROUP:New():FilterPrefixes(self.SAM_Templates_Prefix):FilterCoalitions(self.Coalition):FilterStart()
|
||||
self.SAM_Group:FilterStart()
|
||||
-- Set EWR SET_GROUP
|
||||
self.EWR_Group = SET_GROUP:New():FilterPrefixes(self.ewr_templates):FilterCoalitions(self.Coalition):FilterStart()
|
||||
self.EWR_Group:FilterStart()
|
||||
else
|
||||
-- Set SAM SET_GROUP
|
||||
self.SAM_Group = SET_GROUP:New():FilterPrefixes(self.SAM_Templates_Prefix):FilterCoalitions(self.Coalition):FilterOnce()
|
||||
self.SAM_Group:FilterOnce()
|
||||
-- Set EWR SET_GROUP
|
||||
self.EWR_Group = SET_GROUP:New():FilterPrefixes(self.ewr_templates):FilterCoalitions(self.Coalition):FilterOnce()
|
||||
self.EWR_Group:FilterOnce()
|
||||
end
|
||||
|
||||
-- set up CC
|
||||
@@ -612,7 +623,7 @@ do
|
||||
|
||||
-- TODO Version
|
||||
-- @field #string version
|
||||
self.version="0.8.11"
|
||||
self.version="0.8.14"
|
||||
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
||||
|
||||
--- FSM Functions ---
|
||||
|
||||
@@ -50,6 +50,11 @@
|
||||
-- * **100 meter**: Destroys the missile when the distance to the aircraft is below or equal to 100 meter.
|
||||
-- * **150 meter**: Destroys the missile when the distance to the aircraft is below or equal to 150 meter.
|
||||
-- * **200 meter**: Destroys the missile when the distance to the aircraft is below or equal to 200 meter.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE.
|
||||
-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -67,8 +72,8 @@
|
||||
-- @module Functional.MissileTrainer
|
||||
-- @image Missile_Trainer.JPG
|
||||
|
||||
|
||||
--- @type MISSILETRAINER
|
||||
---
|
||||
-- @type MISSILETRAINER
|
||||
-- @field Core.Set#SET_CLIENT DBClients
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
@@ -97,6 +102,11 @@
|
||||
-- * @{#MISSILETRAINER.InitRangeOnOff}: Sets by default the display of range information of missiles ON of OFF.
|
||||
-- * @{#MISSILETRAINER.InitBearingOnOff}: Sets by default the display of bearing information of missiles ON of OFF.
|
||||
-- * @{#MISSILETRAINER.InitMenusOnOff}: Allows to configure the options through the radio menu.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE.
|
||||
-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality.
|
||||
--
|
||||
-- @field #MISSILETRAINER
|
||||
MISSILETRAINER = {
|
||||
@@ -205,7 +215,7 @@ function MISSILETRAINER:New( Distance, Briefing )
|
||||
|
||||
|
||||
-- self.DB:ForEachClient(
|
||||
-- --- @param Wrapper.Client#CLIENT Client
|
||||
-- -- @param Wrapper.Client#CLIENT Client
|
||||
-- function( Client )
|
||||
--
|
||||
-- ... actions ...
|
||||
@@ -555,7 +565,7 @@ function MISSILETRAINER:_AddBearing( Client, TrainerWeapon )
|
||||
|
||||
local DirectionVector = { x = PositionMissile.x - TargetVec3.x, y = PositionMissile.y - TargetVec3.y, z = PositionMissile.z - TargetVec3.z }
|
||||
local DirectionRadians = math.atan2( DirectionVector.z, DirectionVector.x )
|
||||
--DirectionRadians = DirectionRadians + routines.getNorthCorrection( PositionTarget )
|
||||
|
||||
if DirectionRadians < 0 then
|
||||
DirectionRadians = DirectionRadians + 2 * math.pi
|
||||
end
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
-- @module Functional.Movement
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
--- @type MOVEMENT
|
||||
---
|
||||
-- @type MOVEMENT
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
@@ -55,7 +56,6 @@ end
|
||||
--- Call this function to start the MOVEMENT scheduling.
|
||||
function MOVEMENT:ScheduleStart()
|
||||
self:F()
|
||||
--self.MoveFunction = routines.scheduleFunction( self._Scheduler, { self }, timer.getTime() + 1, 120 )
|
||||
self.MoveFunction = SCHEDULER:New( self, self._Scheduler, {}, 1, 120 )
|
||||
end
|
||||
|
||||
|
||||
@@ -3483,7 +3483,7 @@ function RAT:Status(message, forID)
|
||||
-- Get group.
|
||||
local group=ratcraft.group --Wrapper.Group#GROUP
|
||||
|
||||
if group and group:IsAlive() then
|
||||
if group and group:IsAlive() and (group:GetCoordinate() or group:GetVec3()) then
|
||||
nalive=nalive+1
|
||||
|
||||
-- Gather some information.
|
||||
@@ -3491,8 +3491,11 @@ function RAT:Status(message, forID)
|
||||
local life=self:_GetLife(group)
|
||||
local fuel=group:GetFuel()*100.0
|
||||
local airborne=group:InAir()
|
||||
local coords=group:GetCoordinate()
|
||||
local alt=coords.y or 1000
|
||||
local coords=group:GetCoordinate() or group:GetVec3()
|
||||
local alt=1000
|
||||
if coords then
|
||||
alt=coords.y or 1000
|
||||
end
|
||||
--local vel=group:GetVelocityKMH()
|
||||
local departure=ratcraft.departure:GetName()
|
||||
local destination=ratcraft.destination:GetName()
|
||||
|
||||
@@ -591,7 +591,7 @@ RANGE.MenuF10Root = nil
|
||||
|
||||
--- Range script version.
|
||||
-- @field #string version
|
||||
RANGE.version = "2.7.0"
|
||||
RANGE.version = "2.7.1"
|
||||
|
||||
-- TODO list:
|
||||
-- TODO: Verbosity level for messages.
|
||||
@@ -2044,6 +2044,7 @@ function RANGE:OnEventShot( EventData )
|
||||
-- Attack parameters.
|
||||
local attackHdg=_unit:GetHeading()
|
||||
local attackAlt=_unit:GetHeight()
|
||||
attackAlt = UTILS.MetersToFeet(attackAlt)
|
||||
local attackVel=_unit:GetVelocityKNOTS()
|
||||
|
||||
-- Tracking info and init of last bomb position.
|
||||
|
||||
@@ -226,6 +226,7 @@ SCORING = {
|
||||
ClassID = 0,
|
||||
Players = {},
|
||||
AutoSave = true,
|
||||
version = "1.17.1"
|
||||
}
|
||||
|
||||
local _SCORINGCoalition = {
|
||||
@@ -659,7 +660,7 @@ function SCORING:_AddPlayerFromUnit( UnitData )
|
||||
self.Players[PlayerName].Penalty = self.Players[PlayerName].Penalty + self.CoalitionChangePenalty or 50
|
||||
self.Players[PlayerName].PenaltyCoalition = self.Players[PlayerName].PenaltyCoalition + 1
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' changed coalition from " .. _SCORINGCoalition[self.Players[PlayerName].UnitCoalition] .. " to " .. _SCORINGCoalition[UnitCoalition] ..
|
||||
"(changed " .. self.Players[PlayerName].PenaltyCoalition .. " times the coalition). ".. self.CoalitionChangePenalty .."Penalty points added.",
|
||||
"(changed " .. self.Players[PlayerName].PenaltyCoalition .. " times the coalition). ".. self.CoalitionChangePenalty .." penalty points added.",
|
||||
MESSAGE.Type.Information
|
||||
):ToAll()
|
||||
self:ScoreCSV( PlayerName, "", "COALITION_PENALTY", 1, -1*self.CoalitionChangePenalty, self.Players[PlayerName].UnitName, _SCORINGCoalition[self.Players[PlayerName].UnitCoalition], _SCORINGCategory[self.Players[PlayerName].UnitCategory], self.Players[PlayerName].UnitType,
|
||||
@@ -1420,7 +1421,7 @@ function SCORING:ReportDetailedPlayerHits( PlayerName )
|
||||
Penalty = Penalty + UnitData.Penalty
|
||||
PenaltyHit = UnitData.PenaltyHit
|
||||
end
|
||||
local ScoreMessageHit = string.format( "%s:%d ", CategoryName, Score - Penalty )
|
||||
local ScoreMessageHit = string.format( "%s: %d ", CategoryName, Score - Penalty )
|
||||
self:T( ScoreMessageHit )
|
||||
ScoreMessageHits = ScoreMessageHits .. ScoreMessageHit
|
||||
PlayerScore = PlayerScore + Score
|
||||
@@ -1476,7 +1477,7 @@ function SCORING:ReportDetailedPlayerDestroys( PlayerName )
|
||||
end
|
||||
end
|
||||
|
||||
local ScoreMessageDestroy = string.format( " %s:%d ", CategoryName, Score - Penalty )
|
||||
local ScoreMessageDestroy = string.format( " %s: %d ", CategoryName, Score - Penalty )
|
||||
self:T( ScoreMessageDestroy )
|
||||
ScoreMessageDestroys = ScoreMessageDestroys .. ScoreMessageDestroy
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--- **Functional** - Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||
--- **Functional** - Make SAM sites evasive and execute defensive behaviour when being fired upon.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -19,7 +19,7 @@
|
||||
--
|
||||
-- ### Authors: **FlightControl**, **applevangelist**
|
||||
--
|
||||
-- Last Update: Feb 2022
|
||||
-- Last Update: September 2023
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -66,7 +66,7 @@ SEAD = {
|
||||
-- @field Harms
|
||||
SEAD.Harms = {
|
||||
["AGM_88"] = "AGM_88",
|
||||
["AGM_45"] = "AGM_45",
|
||||
--["AGM_45"] = "AGM_45",
|
||||
["AGM_122"] = "AGM_122",
|
||||
["AGM_84"] = "AGM_84",
|
||||
["AGM_45"] = "AGM_45",
|
||||
@@ -143,7 +143,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
|
||||
self:AddTransition("*", "ManageEvasion", "*")
|
||||
self:AddTransition("*", "CalculateHitZone", "*")
|
||||
|
||||
self:I("*** SEAD - Started Version 0.4.3")
|
||||
self:I("*** SEAD - Started Version 0.4.4")
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -203,7 +203,7 @@ function SEAD:SwitchEmissions(Switch)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add an object to call back when going evasive.
|
||||
--- Set an object to call back when going evasive.
|
||||
-- @param #SEAD self
|
||||
-- @param #table Object The object to call. Needs to have object functions as follows:
|
||||
-- `:SeadSuppressionPlanned(Group, Name, SuppressionStartTime, SuppressionEndTime)`
|
||||
@@ -369,7 +369,7 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
|
||||
local reach = 10
|
||||
if hit then
|
||||
local wpndata = SEAD.HarmData[data]
|
||||
reach = wpndata[1] * 1,1
|
||||
reach = wpndata[1] * 1.1
|
||||
local mach = wpndata[2]
|
||||
wpnspeed = math.floor(mach * 340.29)
|
||||
end
|
||||
@@ -405,7 +405,7 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
|
||||
local function SuppressionStop(args)
|
||||
self:T(string.format("*** SEAD - %s Radar On",args[2]))
|
||||
local grp = args[1] -- Wrapper.Group#GROUP
|
||||
local name = args[2] -- #string Group Nam
|
||||
local name = args[2] -- #string Group Name
|
||||
if self.UseEmissionsOnOff then
|
||||
grp:EnableEmission(true)
|
||||
end
|
||||
@@ -424,7 +424,7 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
|
||||
if _tti > 600 then delay = _tti - 90 end -- shot from afar, 600 is default shorad ontime
|
||||
|
||||
local SuppressionStartTime = timer.getTime() + delay
|
||||
local SuppressionEndTime = timer.getTime() + _tti + self.Padding
|
||||
local SuppressionEndTime = timer.getTime() + delay + _tti + self.Padding + delay
|
||||
local _targetgroupname = _targetgroup:GetName()
|
||||
if not self.SuppressedGroups[_targetgroupname] then
|
||||
self:T(string.format("*** SEAD - %s | Parameters TTI %ds | Switch-Off in %ds",_targetgroupname,_tti,delay))
|
||||
|
||||
@@ -3616,9 +3616,10 @@ function WAREHOUSE:onafterStatus(From, Event, To)
|
||||
end
|
||||
|
||||
-- Print queue after processing requests.
|
||||
self:_PrintQueue(self.queue, "Queue waiting")
|
||||
self:_PrintQueue(self.pending, "Queue pending")
|
||||
|
||||
if self.verbosity > 2 then
|
||||
self:_PrintQueue(self.queue, "Queue waiting")
|
||||
self:_PrintQueue(self.pending, "Queue pending")
|
||||
end
|
||||
-- Check fuel for all assets.
|
||||
--self:_CheckFuel()
|
||||
|
||||
@@ -4101,9 +4102,9 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay,
|
||||
-- Get the size of an object.
|
||||
local function _GetObjectSize(DCSdesc)
|
||||
if DCSdesc.box then
|
||||
local x=DCSdesc.box.max.x+math.abs(DCSdesc.box.min.x) --length
|
||||
local y=DCSdesc.box.max.y+math.abs(DCSdesc.box.min.y) --height
|
||||
local z=DCSdesc.box.max.z+math.abs(DCSdesc.box.min.z) --width
|
||||
local x=DCSdesc.box.max.x-DCSdesc.box.min.x --length
|
||||
local y=DCSdesc.box.max.y-DCSdesc.box.min.y --height
|
||||
local z=DCSdesc.box.max.z-DCSdesc.box.min.z --width
|
||||
return math.max(x,z), x , y, z
|
||||
end
|
||||
return 0,0,0,0
|
||||
@@ -5498,8 +5499,13 @@ function WAREHOUSE:onafterAssetDead(From, Event, To, asset, request)
|
||||
---
|
||||
|
||||
-- Remove dead group from cargo group set.
|
||||
request.cargogroupset:Remove(groupname, NoTriggerEvent)
|
||||
self:T(self.lid..string.format("Removed selfpropelled cargo %s: ncargo=%d.", groupname, request.cargogroupset:Count()))
|
||||
if request.cargogroupset then
|
||||
-- cargogroupset was nil for user case. Difficult to reproduce so we add a nil check.
|
||||
request.cargogroupset:Remove(groupname, NoTriggerEvent)
|
||||
self:T(self.lid..string.format("Removed selfpropelled cargo %s: ncargo=%d.", groupname, request.cargogroupset:Count()))
|
||||
else
|
||||
self:E(self.lid..string.format("ERROR: cargogroupset is nil for request ID=%s!", tostring(request.uid)))
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
@@ -6767,7 +6773,7 @@ function WAREHOUSE:_UnitDead(deadunit, deadgroup, request)
|
||||
-- Dont trigger a Remove event for the group sets.
|
||||
local NoTriggerEvent=true
|
||||
|
||||
if not request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
|
||||
if request.transporttype~=WAREHOUSE.TransportType.SELFPROPELLED then
|
||||
|
||||
---
|
||||
-- Complicated case: Dead unit could be:
|
||||
@@ -8229,7 +8235,7 @@ end
|
||||
-- @return #number Request ID.
|
||||
function WAREHOUSE:_GetIDsFromGroupName(groupname)
|
||||
|
||||
---@param #string text The text to analyse.
|
||||
-- @param #string text The text to analyse.
|
||||
local function analyse(text)
|
||||
|
||||
-- Get rid of #0001 tail from spawn.
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
--
|
||||
-- ZONE_GOAL_CARGO models processes that have a Goal with a defined achievement involving a Zone and Cargo.
|
||||
-- Derived classes implement the ways how the achievements can be realized.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Enums.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/FiFo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Profiler.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Routines.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Socket.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/STTS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Templates.lua' )
|
||||
@@ -50,6 +49,7 @@ __Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Unit.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Weapon.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Net.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Storage.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Cargo/Cargo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' )
|
||||
@@ -114,6 +114,7 @@ __Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/RescueHelo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Squadron.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Target.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/EasyGCICAP.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' )
|
||||
@@ -128,9 +129,9 @@ __Moose.Include( 'Scripts/Moose/AI/AI_A2G_CAS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_SEAD.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_Dispatcher.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Patrol.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cap.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cas.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Bai.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_CAP.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_CAS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_BAI.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Formation.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Escort.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Escort_Request.lua' )
|
||||
@@ -169,7 +170,7 @@ __Moose.Include( 'Scripts/Moose/Tasking/Task_A2G_Dispatcher.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_A2G.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_A2A_Dispatcher.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_A2A.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_CARGO.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo_Transport.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo_CSAR.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo_Dispatcher.lua' )
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
__Moose.Include( 'Utilities\\Enums.lua' )
|
||||
__Moose.Include( 'Utilities\\Routines.lua' )
|
||||
__Moose.Include( 'Utilities\\Utils.lua' )
|
||||
__Moose.Include( 'Utilities\\Profiler.lua' )
|
||||
__Moose.Include( 'Utilities\\Templates.lua' )
|
||||
__Moose.Include( 'Utilities\\STTS.lua' )
|
||||
__Moose.Include( 'Utilities\\FiFo.lua' )
|
||||
__Moose.Include( 'Utilities\\Socket.lua' )
|
||||
|
||||
__Moose.Include( 'Core\\Base.lua' )
|
||||
__Moose.Include( 'Core\\Beacon.lua' )
|
||||
__Moose.Include( 'Core\\UserFlag.lua' )
|
||||
__Moose.Include( 'Core\\Report.lua' )
|
||||
__Moose.Include( 'Core\\Scheduler.lua' )
|
||||
__Moose.Include( 'Core\\ScheduleDispatcher.lua' )
|
||||
__Moose.Include( 'Core\\Event.lua' )
|
||||
__Moose.Include( 'Core\\Settings.lua' )
|
||||
__Moose.Include( 'Core\\Menu.lua' )
|
||||
__Moose.Include( 'Core\\Zone.lua' )
|
||||
__Moose.Include( 'Core\\Zone_Detection.lua' )
|
||||
__Moose.Include( 'Core\\Database.lua' )
|
||||
__Moose.Include( 'Core\\Set.lua' )
|
||||
__Moose.Include( 'Core\\Point.lua' )
|
||||
__Moose.Include( 'Core\\Velocity.lua' )
|
||||
__Moose.Include( 'Core\\Message.lua' )
|
||||
__Moose.Include( 'Core\\Fsm.lua' )
|
||||
__Moose.Include( 'Core\\Spawn.lua' )
|
||||
__Moose.Include( 'Core\\SpawnStatic.lua' )
|
||||
__Moose.Include( 'Core\\Timer.lua' )
|
||||
__Moose.Include( 'Core\\Goal.lua' )
|
||||
__Moose.Include( 'Core\\Spot.lua' )
|
||||
__Moose.Include( 'Core\\Astar.lua' )
|
||||
__Moose.Include( 'Core\\MarkerOps_Base.lua' )
|
||||
__Moose.Include( 'Core\\TextAndSound.lua' )
|
||||
__Moose.Include( 'Core\\Condition.lua' )
|
||||
__Moose.Include( 'Core\\ClientMenu.lua' )
|
||||
|
||||
__Moose.Include( 'Wrapper\\Object.lua' )
|
||||
__Moose.Include( 'Wrapper\\Identifiable.lua' )
|
||||
__Moose.Include( 'Wrapper\\Positionable.lua' )
|
||||
__Moose.Include( 'Wrapper\\Controllable.lua' )
|
||||
__Moose.Include( 'Wrapper\\Group.lua' )
|
||||
__Moose.Include( 'Wrapper\\Unit.lua' )
|
||||
__Moose.Include( 'Wrapper\\Client.lua' )
|
||||
__Moose.Include( 'Wrapper\\Static.lua' )
|
||||
__Moose.Include( 'Wrapper\\Airbase.lua' )
|
||||
__Moose.Include( 'Wrapper\\Scenery.lua' )
|
||||
__Moose.Include( 'Wrapper\\Marker.lua' )
|
||||
|
||||
__Moose.Include( 'Cargo\\Cargo.lua' )
|
||||
__Moose.Include( 'Cargo\\CargoUnit.lua' )
|
||||
__Moose.Include( 'Cargo\\CargoSlingload.lua' )
|
||||
__Moose.Include( 'Cargo\\CargoCrate.lua' )
|
||||
__Moose.Include( 'Cargo\\CargoGroup.lua' )
|
||||
|
||||
__Moose.Include( 'Functional\\Scoring.lua' )
|
||||
__Moose.Include( 'Functional\\CleanUp.lua' )
|
||||
__Moose.Include( 'Functional\\Movement.lua' )
|
||||
__Moose.Include( 'Functional\\Sead.lua' )
|
||||
__Moose.Include( 'Functional\\Escort.lua' )
|
||||
__Moose.Include( 'Functional\\MissileTrainer.lua' )
|
||||
__Moose.Include( 'Functional\\ATC_Ground.lua' )
|
||||
__Moose.Include( 'Functional\\Detection.lua' )
|
||||
__Moose.Include( 'Functional\\DetectionZones.lua' )
|
||||
__Moose.Include( 'Functional\\Designate.lua' )
|
||||
__Moose.Include( 'Functional\\RAT.lua' )
|
||||
__Moose.Include( 'Functional\\Range.lua' )
|
||||
__Moose.Include( 'Functional\\ZoneGoal.lua' )
|
||||
__Moose.Include( 'Functional\\ZoneGoalCoalition.lua' )
|
||||
__Moose.Include( 'Functional\\ZoneCaptureCoalition.lua' )
|
||||
__Moose.Include( 'Functional\\Artillery.lua' )
|
||||
__Moose.Include( 'Functional\\Suppression.lua' )
|
||||
__Moose.Include( 'Functional\\PseudoATC.lua' )
|
||||
__Moose.Include( 'Functional\\Warehouse.lua' )
|
||||
__Moose.Include( 'Functional\\Fox.lua' )
|
||||
__Moose.Include( 'Functional\\Mantis.lua' )
|
||||
__Moose.Include( 'Functional\\Shorad.lua' )
|
||||
__Moose.Include( 'Functional\\Autolase.lua' )
|
||||
__Moose.Include( 'Functional\\AICSAR.lua' )
|
||||
|
||||
__Moose.Include( 'Ops\\Airboss.lua' )
|
||||
__Moose.Include( 'Ops\\RecoveryTanker.lua' )
|
||||
__Moose.Include( 'Ops\\RescueHelo.lua' )
|
||||
__Moose.Include( 'Ops\\ATIS.lua' )
|
||||
__Moose.Include( 'Ops\\Auftrag.lua' )
|
||||
__Moose.Include( 'Ops\\Target.lua' )
|
||||
__Moose.Include( 'Ops\\OpsGroup.lua' )
|
||||
__Moose.Include( 'Ops\\FlightGroup.lua' )
|
||||
__Moose.Include( 'Ops\\NavyGroup.lua' )
|
||||
__Moose.Include( 'Ops\\ArmyGroup.lua' )
|
||||
__Moose.Include( 'Ops\\Cohort.lua' )
|
||||
__Moose.Include( 'Ops\\Squadron.lua' )
|
||||
__Moose.Include( 'Ops\\Platoon.lua' )
|
||||
__Moose.Include( 'Ops\\Legion.lua' )
|
||||
__Moose.Include( 'Ops\\AirWing.lua' )
|
||||
__Moose.Include( 'Ops\\Brigade.lua' )
|
||||
__Moose.Include( 'Ops\\Intelligence.lua' )
|
||||
__Moose.Include( 'Ops\\Commander.lua' )
|
||||
__Moose.Include( 'Ops\\OpsTransport.lua' )
|
||||
__Moose.Include( 'Ops\\CSAR.lua' )
|
||||
__Moose.Include( 'Ops\\CTLD.lua' )
|
||||
__Moose.Include( 'Ops\\OpsZone.lua' )
|
||||
__Moose.Include( 'Ops\\Chief.lua' )
|
||||
__Moose.Include( 'Ops\\Flotilla.lua' )
|
||||
__Moose.Include( 'Ops\\Fleet.lua' )
|
||||
__Moose.Include( 'Ops\\Awacs.lua' )
|
||||
__Moose.Include( 'Ops\\PlayerTask.lua' )
|
||||
__Moose.Include( 'Ops\\Operation.lua' )
|
||||
__Moose.Include( 'Ops\\FlightControl.lua' )
|
||||
|
||||
__Moose.Include( 'AI\\AI_Balancer.lua' )
|
||||
__Moose.Include( 'AI\\AI_Air.lua' )
|
||||
__Moose.Include( 'AI\\AI_Air_Patrol.lua' )
|
||||
__Moose.Include( 'AI\\AI_Air_Engage.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2A_Patrol.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2A_Cap.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2A_Gci.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2A_Dispatcher.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2G_BAI.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2G_CAS.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2G_SEAD.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2G_Dispatcher.lua' )
|
||||
__Moose.Include( 'AI\\AI_Patrol.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cap.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cas.lua' )
|
||||
__Moose.Include( 'AI\\AI_Bai.lua' )
|
||||
__Moose.Include( 'AI\\AI_Formation.lua' )
|
||||
__Moose.Include( 'AI\\AI_Escort.lua' )
|
||||
__Moose.Include( 'AI\\AI_Escort_Request.lua' )
|
||||
__Moose.Include( 'AI\\AI_Escort_Dispatcher.lua' )
|
||||
__Moose.Include( 'AI\\AI_Escort_Dispatcher_Request.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_APC.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Helicopter.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Airplane.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Ship.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_APC.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Helicopter.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Airplane.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Ship.lua' )
|
||||
|
||||
__Moose.Include( 'Actions\\Act_Assign.lua' )
|
||||
__Moose.Include( 'Actions\\Act_Route.lua' )
|
||||
__Moose.Include( 'Actions\\Act_Account.lua' )
|
||||
__Moose.Include( 'Actions\\Act_Assist.lua' )
|
||||
|
||||
__Moose.Include( 'Sound\\UserSound.lua' )
|
||||
__Moose.Include( 'Sound\\SoundOutput.lua' )
|
||||
__Moose.Include( 'Sound\\Radio.lua' )
|
||||
__Moose.Include( 'Sound\\RadioQueue.lua' )
|
||||
__Moose.Include( 'Sound\\RadioSpeech.lua' )
|
||||
__Moose.Include( 'Sound\\SRS.lua' )
|
||||
|
||||
__Moose.Include( 'Tasking\\CommandCenter.lua' )
|
||||
__Moose.Include( 'Tasking\\Mission.lua' )
|
||||
__Moose.Include( 'Tasking\\Task.lua' )
|
||||
__Moose.Include( 'Tasking\\TaskInfo.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Manager.lua' )
|
||||
__Moose.Include( 'Tasking\\DetectionManager.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_A2G_Dispatcher.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_A2G.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_A2A_Dispatcher.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_A2A.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Cargo.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Cargo_Transport.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Cargo_CSAR.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Cargo_Dispatcher.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Capture_Zone.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Capture_Dispatcher.lua' )
|
||||
|
||||
__Moose.Include( 'Globals.lua' )
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,14 +34,17 @@
|
||||
-- @field Core.Set#SET_ZONE zonesetCAP Set of CAP zones.
|
||||
-- @field Core.Set#SET_ZONE zonesetTANKER Set of TANKER zones.
|
||||
-- @field Core.Set#SET_ZONE zonesetAWACS Set of AWACS zones.
|
||||
-- @field Core.Set#SET_ZONE zonesetRECON Set of RECON zones.
|
||||
-- @field #number nflightsCAP Number of CAP flights constantly in the air.
|
||||
-- @field #number nflightsAWACS Number of AWACS flights constantly in the air.
|
||||
-- @field #number nflightsTANKERboom Number of TANKER flights with BOOM constantly in the air.
|
||||
-- @field #number nflightsTANKERprobe Number of TANKER flights with PROBE constantly in the air.
|
||||
-- @field #number nflightsRescueHelo Number of Rescue helo flights constantly in the air.
|
||||
-- @field #number nflightsRecon Number of Recon flights constantly in the air.
|
||||
-- @field #table pointsCAP Table of CAP points.
|
||||
-- @field #table pointsTANKER Table of Tanker points.
|
||||
-- @field #table pointsAWACS Table of AWACS points.
|
||||
-- @field #table pointsRecon Table of RECON points.
|
||||
-- @field #boolean markpoints Display markers on the F10 map.
|
||||
-- @field Ops.Airboss#AIRBOSS airboss Airboss attached to this wing.
|
||||
--
|
||||
@@ -51,7 +54,9 @@
|
||||
-- @field #string takeoffType Take of type.
|
||||
-- @field #boolean despawnAfterLanding Aircraft are despawned after landing.
|
||||
-- @field #boolean despawnAfterHolding Aircraft are despawned after holding.
|
||||
--
|
||||
-- @field #boolean capOptionPatrolRaceTrack Use closer patrol race track or standard orbit auftrag.
|
||||
-- @field #number capFormation If capOptionPatrolRaceTrack is true, set the formation, also.
|
||||
--
|
||||
-- @extends Ops.Legion#LEGION
|
||||
|
||||
--- *I fly because it releases my mind from the tyranny of petty things.* -- Antoine de Saint-Exupery
|
||||
@@ -123,7 +128,10 @@ AIRWING = {
|
||||
pointsCAP = {},
|
||||
pointsTANKER = {},
|
||||
pointsAWACS = {},
|
||||
pointsRecon = {},
|
||||
markpoints = false,
|
||||
capOptionPatrolRaceTrack = false,
|
||||
capFormation = nil,
|
||||
}
|
||||
|
||||
--- Payload data.
|
||||
@@ -175,7 +183,7 @@ AIRWING = {
|
||||
|
||||
--- AIRWING class version.
|
||||
-- @field #string version
|
||||
AIRWING.version="0.9.2"
|
||||
AIRWING.version="0.9.4"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
@@ -219,6 +227,7 @@ function AIRWING:New(warehousename, airwingname)
|
||||
-- Defaults:
|
||||
self.nflightsCAP=0
|
||||
self.nflightsAWACS=0
|
||||
self.nflightsRecon=0
|
||||
self.nflightsTANKERboom=0
|
||||
self.nflightsTANKERprobe=0
|
||||
self.nflightsRecoveryTanker=0
|
||||
@@ -694,6 +703,24 @@ function AIRWING:SetNumberCAP(n)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set CAP flight formation.
|
||||
-- @param #AIRWING self
|
||||
-- @param #number Formation Formation to take, e.g. ENUMS.Formation.FixedWing.Trail.Close, also see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_option_formation).
|
||||
-- @return #AIRWING self
|
||||
function AIRWING:SetCAPFormation(Formation)
|
||||
self.capFormation = Formation
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set CAP close race track.We'll utilize the AUFTRAG PatrolRaceTrack instead of a standard race track orbit task.
|
||||
-- @param #AIRWING self
|
||||
-- @param #boolean OnOff If true, switch this on, else switch off. Off by default.
|
||||
-- @return #AIRWING self
|
||||
function AIRWING:SetCapCloseRaceTrack(OnOff)
|
||||
self.capOptionPatrolRaceTrack = OnOff
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set number of TANKER flights with Boom constantly in the air.
|
||||
-- @param #AIRWING self
|
||||
-- @param #number Nboom Number of flights. Default 1.
|
||||
@@ -734,6 +761,15 @@ function AIRWING:SetNumberAWACS(n)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set number of RECON flights constantly in the air.
|
||||
-- @param #AIRWING self
|
||||
-- @param #number n Number of flights. Default 1.
|
||||
-- @return #AIRWING self
|
||||
function AIRWING:SetNumberRecon(n)
|
||||
self.nflightsRecon=n or 1
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set number of Rescue helo flights constantly in the air.
|
||||
-- @param #AIRWING self
|
||||
-- @param #number n Number of flights. Default 1.
|
||||
@@ -819,6 +855,23 @@ function AIRWING:AddPatrolPointCAP(Coordinate, Altitude, Speed, Heading, LegLeng
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a patrol Point for RECON missions.
|
||||
-- @param #AIRWING self
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point.
|
||||
-- @param #number Altitude Orbit altitude in feet.
|
||||
-- @param #number Speed Orbit speed in knots.
|
||||
-- @param #number Heading Heading in degrees.
|
||||
-- @param #number LegLength Length of race-track orbit in NM.
|
||||
-- @return #AIRWING self
|
||||
function AIRWING:AddPatrolPointRecon(Coordinate, Altitude, Speed, Heading, LegLength)
|
||||
|
||||
local patrolpoint=self:NewPatrolPoint("RECON", Coordinate, Altitude, Speed, Heading, LegLength)
|
||||
|
||||
table.insert(self.pointsRecon, patrolpoint)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a patrol Point for TANKER missions.
|
||||
-- @param #AIRWING self
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point.
|
||||
@@ -971,6 +1024,9 @@ function AIRWING:onafterStatus(From, Event, To)
|
||||
-- Check Rescue Helo missions.
|
||||
self:CheckRescuhelo()
|
||||
|
||||
-- Check Recon missions.
|
||||
self:CheckRECON()
|
||||
|
||||
----------------
|
||||
-- Transport ---
|
||||
----------------
|
||||
@@ -1078,13 +1134,14 @@ end
|
||||
-- @return #AIRWING self
|
||||
function AIRWING:CheckCAP()
|
||||
|
||||
local Ncap=0 --self:CountMissionsInQueue({AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT})
|
||||
local Ncap=0
|
||||
|
||||
|
||||
-- Count CAP missions.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
if mission:IsNotOver() and mission.type==AUFTRAG.Type.GCICAP and mission.patroldata then
|
||||
if mission:IsNotOver() and (mission.type==AUFTRAG.Type.GCICAP or mission.type == AUFTRAG.Type.PATROLRACETRACK) and mission.patroldata then
|
||||
Ncap=Ncap+1
|
||||
end
|
||||
|
||||
@@ -1096,8 +1153,18 @@ function AIRWING:CheckCAP()
|
||||
|
||||
local altitude=patrol.altitude+1000*patrol.noccupied
|
||||
|
||||
local missionCAP=AUFTRAG:NewGCICAP(patrol.coord, altitude, patrol.speed, patrol.heading, patrol.leg)
|
||||
|
||||
local missionCAP = nil -- Ops.Auftrag#AUFTRAG
|
||||
|
||||
if self.capOptionPatrolRaceTrack then
|
||||
|
||||
missionCAP=AUFTRAG:NewPATROL_RACETRACK(patrol.coord,altitude,patrol.speed,patrol.heading,patrol.leg, self.capFormation)
|
||||
|
||||
else
|
||||
|
||||
missionCAP=AUFTRAG:NewGCICAP(patrol.coord, altitude, patrol.speed, patrol.heading, patrol.leg)
|
||||
|
||||
end
|
||||
|
||||
missionCAP.patroldata=patrol
|
||||
|
||||
patrol.noccupied=patrol.noccupied+1
|
||||
@@ -1111,6 +1178,58 @@ function AIRWING:CheckCAP()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Check how many RECON missions are assigned and add number of missing missions.
|
||||
-- @param #AIRWING self
|
||||
-- @return #AIRWING self
|
||||
function AIRWING:CheckRECON()
|
||||
|
||||
local Ncap=0
|
||||
|
||||
-- Count CAP missions.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
if mission:IsNotOver() and mission.type==AUFTRAG.Type.RECON and mission.patroldata then
|
||||
Ncap=Ncap+1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--self:I(self.lid.."Number of active RECON Missions: "..Ncap)
|
||||
|
||||
for i=1,self.nflightsRecon-Ncap do
|
||||
|
||||
--self:I(self.lid.."Creating RECON Missions: "..i)
|
||||
|
||||
local patrol=self:_GetPatrolData(self.pointsRecon)
|
||||
|
||||
local altitude=patrol.altitude --+1000*patrol.noccupied
|
||||
|
||||
local ZoneSet = SET_ZONE:New()
|
||||
local Zone = ZONE_RADIUS:New(self.alias.." Recon "..math.random(1,10000),patrol.coord:GetVec2(),UTILS.NMToMeters(patrol.leg/2))
|
||||
|
||||
ZoneSet:AddZone(Zone)
|
||||
|
||||
if self.Debug then
|
||||
Zone:DrawZone(self.coalition,{0,0,1},Alpha,FillColor,FillAlpha,2,true)
|
||||
end
|
||||
|
||||
local missionRECON=AUFTRAG:NewRECON(ZoneSet,patrol.speed,patrol.altitude,true)
|
||||
|
||||
missionRECON.patroldata=patrol
|
||||
missionRECON.categories={AUFTRAG.Category.AIRCRAFT}
|
||||
|
||||
patrol.noccupied=patrol.noccupied+1
|
||||
|
||||
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end
|
||||
|
||||
self:AddMission(missionRECON)
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Check how many TANKER missions are assigned and add number of missing missions.
|
||||
-- @param #AIRWING self
|
||||
-- @return #AIRWING self
|
||||
@@ -1192,7 +1311,6 @@ function AIRWING:CheckAWACS()
|
||||
|
||||
end
|
||||
|
||||
|
||||
for i=1,self.nflightsAWACS-N do
|
||||
|
||||
local patrol=self:_GetPatrolData(self.pointsAWACS)
|
||||
|
||||
@@ -1735,10 +1735,10 @@ AIRBOSS.Difficulty = {
|
||||
-- @field #table trapsheet Groove data table recorded every 0.5 seconds.
|
||||
-- @field #boolean trapon If true, save trap sheets.
|
||||
-- @field #string debriefschedulerID Debrief scheduler ID.
|
||||
--
|
||||
--
|
||||
-- @field Sound.SRS#MSRS SRS
|
||||
-- @field Sound.SRS#MSRSQUEUE SRSQ
|
||||
--
|
||||
--
|
||||
-- @extends #AIRBOSS.FlightGroup
|
||||
|
||||
--- Main group level radio menu: F10 Other/Airboss.
|
||||
@@ -2543,7 +2543,7 @@ function AIRBOSS:AddRecoveryWindow( starttime, stoptime, case, holdingoffset, tu
|
||||
return self
|
||||
end
|
||||
if Tstop <= Tnow then
|
||||
self:I( string.format( "WARNING: Recovery stop time %s already over. Tnow=%s! Recovery window rejected.", UTILS.SecondsToClock( Tstop ), UTILS.SecondsToClock( Tnow ) ) )
|
||||
string.format( "WARNING: Recovery stop time %s already over. Tnow=%s! Recovery window rejected.", UTILS.SecondsToClock( Tstop ), UTILS.SecondsToClock( Tnow ) )
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -3058,7 +3058,7 @@ end
|
||||
-- @param #number Port Port of the SRS server, defaults to 5002.
|
||||
-- @param #string Culture (Optional, Airboss Culture) Culture, defaults to "en-US".
|
||||
-- @param #string Gender (Optional, Airboss Gender) Gender, e.g. "male" or "female". Defaults to "male".
|
||||
-- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings.
|
||||
-- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings.
|
||||
-- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json".
|
||||
-- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest).
|
||||
-- @param #table AltBackend (Optional) See MSRS for details.
|
||||
@@ -3087,10 +3087,10 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
|
||||
-- SRSQUEUE
|
||||
self.SRSQ = MSRSQUEUE:New("AIRBOSS")
|
||||
self.SRSQ:SetTransmitOnlyWithPlayers(true)
|
||||
if not self.PilotRadio then
|
||||
if not self.PilotRadio then
|
||||
self:SetSRSPilotVoice()
|
||||
end
|
||||
return self
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM.
|
||||
@@ -3258,7 +3258,7 @@ function AIRBOSS:SoundCheckLSO( delay )
|
||||
end
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
end
|
||||
end
|
||||
@@ -3293,7 +3293,7 @@ function AIRBOSS:SoundCheckMarshal( delay )
|
||||
end
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
end
|
||||
end
|
||||
@@ -3684,7 +3684,7 @@ function AIRBOSS:onafterStatus( From, Event, To )
|
||||
if i == 0 then
|
||||
text = text .. " none"
|
||||
end
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Check for collision.
|
||||
if collision then
|
||||
@@ -4075,7 +4075,7 @@ function AIRBOSS:_CheckRecoveryTimes()
|
||||
|
||||
-- Check that wind is blowing from a direction > 5° different from the current heading.
|
||||
local hdg = self:GetHeading()
|
||||
local wind = self:GetHeadingIntoWind()
|
||||
local wind = self:GetHeadingIntoWind(nextwindow.SPEED)
|
||||
local delta = self:_GetDeltaHeading( hdg, wind )
|
||||
local uturn = delta > 5
|
||||
|
||||
@@ -5459,6 +5459,7 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
||||
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||
|
||||
-- Return values.
|
||||
local alt
|
||||
@@ -5927,6 +5928,9 @@ function AIRBOSS:_ScanCarrierZone()
|
||||
-- Create a new flight group
|
||||
if knownflight then
|
||||
|
||||
-- Debug output.
|
||||
self:T2(self.lid..string.format("Known flight group %s of type %s in CCA.", groupname, actype))
|
||||
|
||||
-- Check if flight is AI and if we want to handle it at all.
|
||||
if knownflight.ai and knownflight.flag == -100 and self.handleai then
|
||||
|
||||
@@ -5943,9 +5947,10 @@ function AIRBOSS:_ScanCarrierZone()
|
||||
flight.airboss = self
|
||||
end
|
||||
|
||||
-- Send AI flight to marshal stack.
|
||||
-- Send AI flight to marshal stack if group closes in more than 5 and has initial flag value.
|
||||
if putintomarshal then
|
||||
|
||||
|
||||
-- Get the next free stack for current recovery case.
|
||||
local stack = self:_GetFreeStack( knownflight.ai )
|
||||
|
||||
@@ -6723,7 +6728,7 @@ function AIRBOSS:_AddMarshalGroup( flight, stack )
|
||||
|
||||
-- If the carrier is supposed to turn into the wind, we take the wind coordinate.
|
||||
if self.recoverywindow and self.recoverywindow.WIND then
|
||||
brc = self:GetBRCintoWind()
|
||||
brc = self:GetBRCintoWind(self.recoverywindow.SPEED)
|
||||
end
|
||||
|
||||
-- Get charlie time estimate.
|
||||
@@ -6955,7 +6960,7 @@ function AIRBOSS:_GetFreeStack( ai, case, empty )
|
||||
|
||||
end
|
||||
|
||||
self:I( self.lid .. string.format( "Returning free stack %s", tostring( nfree ) ) )
|
||||
self:T( self.lid .. string.format( "Returning free stack %s", tostring( nfree ) ) )
|
||||
return nfree
|
||||
end
|
||||
|
||||
@@ -7889,7 +7894,7 @@ function AIRBOSS:_RemoveFlight( flight, completely )
|
||||
-- Remove player from players table.
|
||||
local playerdata = self.players[flight.name]
|
||||
if playerdata then
|
||||
self:I( self.lid .. string.format( "Removing player %s completely.", flight.name ) )
|
||||
self:T( self.lid .. string.format( "Removing player %s completely.", flight.name ) )
|
||||
self.players[flight.name] = nil
|
||||
end
|
||||
|
||||
@@ -11548,12 +11553,12 @@ end
|
||||
-- @param #boolean magnetic If true, calculate magnetic heading. By default true heading is returned.
|
||||
-- @param Core.Point#COORDINATE coord (Optional) Coordinate from which heading is calculated. Default is current carrier position.
|
||||
-- @return #number Carrier heading in degrees.
|
||||
function AIRBOSS:GetHeadingIntoWind( magnetic, coord )
|
||||
function AIRBOSS:GetHeadingIntoWind_old( magnetic, coord )
|
||||
|
||||
local function adjustDegreesForWindSpeed(windSpeed)
|
||||
local degreesAdjustment = 0
|
||||
-- the windspeeds are in m/s
|
||||
|
||||
|
||||
-- +0 degrees at 15m/s = 37kts
|
||||
-- +0 degrees at 14m/s = 35kts
|
||||
-- +0 degrees at 13m/s = 33kts
|
||||
@@ -11568,7 +11573,7 @@ function AIRBOSS:GetHeadingIntoWind( magnetic, coord )
|
||||
-- +20 degrees at 4m/s = 26kts
|
||||
-- +20 degrees at 3m/s = 26kts
|
||||
-- +30 degrees at 2m/s = 26kts 1s
|
||||
|
||||
|
||||
if windSpeed > 0 and windSpeed < 3 then
|
||||
degreesAdjustment = 30
|
||||
elseif windSpeed >= 3 and windSpeed < 5 then
|
||||
@@ -11580,21 +11585,15 @@ function AIRBOSS:GetHeadingIntoWind( magnetic, coord )
|
||||
elseif windSpeed >= 13 then
|
||||
degreesAdjustment = 0
|
||||
end
|
||||
|
||||
|
||||
return degreesAdjustment
|
||||
end
|
||||
|
||||
-- Get direction the wind is blowing from. This is where we want to go.
|
||||
local windfrom, vwind = self:GetWind( nil, nil, coord )
|
||||
|
||||
--self:I("windfrom="..windfrom.." vwind="..vwind)
|
||||
|
||||
vwind = vwind + adjustDegreesForWindSpeed(vwind)
|
||||
|
||||
--self:I("windfrom="..windfrom.." (c)vwind="..vwind)
|
||||
|
||||
-- Actually, we want the runway in the wind.
|
||||
local intowind = windfrom - self.carrierparam.rwyangle
|
||||
local intowind = windfrom - self.carrierparam.rwyangle + adjustDegreesForWindSpeed(vwind)
|
||||
|
||||
-- If no wind, take current heading.
|
||||
if vwind < 0.1 then
|
||||
@@ -11614,13 +11613,108 @@ function AIRBOSS:GetHeadingIntoWind( magnetic, coord )
|
||||
return intowind
|
||||
end
|
||||
|
||||
--- Get true (or magnetic) heading of carrier into the wind. This accounts for the angled runway.
|
||||
-- Implementation based on [Mags & Bambi](https://magwo.github.io/carrier-cruise/).
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number vdeck Desired wind velocity over deck in knots.
|
||||
-- @param #boolean magnetic If true, calculate magnetic heading. By default true heading is returned.
|
||||
-- @param Core.Point#COORDINATE coord (Optional) Coordinate from which heading is calculated. Default is current carrier position.
|
||||
-- @return #number Carrier heading in degrees.
|
||||
-- @return #number Carrier speed in knots to reach desired wind speed on deck.
|
||||
function AIRBOSS:GetHeadingIntoWind( vdeck, magnetic, coord )
|
||||
|
||||
-- Default offset angle.
|
||||
local Offset=self.carrierparam.rwyangle or 0
|
||||
|
||||
-- Get direction the wind is blowing from.
|
||||
local windfrom, vwind=self:GetWind(18, nil ,coord)
|
||||
|
||||
-- Ships min/max speed.
|
||||
local Vmin=4
|
||||
local Vmax=UTILS.KmphToKnots(self.carrier:GetSpeedMax())
|
||||
|
||||
-- No wind. will stay on current heading.
|
||||
if vwind<0.1 then
|
||||
local h=self:GetHeading(magnetic)
|
||||
return h, math.min(vdeck, Vmax)
|
||||
end
|
||||
|
||||
-- Convert wind speed to knots.
|
||||
vwind=UTILS.MpsToKnots(vwind)
|
||||
|
||||
-- Wind to in knots.
|
||||
local windto=(windfrom+180)%360
|
||||
|
||||
-- Offset angle in rad. We also define the rotation to be clock-wise, which requires a minus sign.
|
||||
local alpha=math.rad(-Offset)
|
||||
|
||||
-- Constant.
|
||||
local C = math.sqrt(math.cos(alpha)^2 / math.sin(alpha)^2 + 1)
|
||||
|
||||
|
||||
-- Upper limit of desired speed due to max boat speed.
|
||||
local vdeckMax=vwind + math.cos(alpha) * Vmax
|
||||
|
||||
-- Lower limit of desired speed due to min boat speed.
|
||||
local vdeckMin=vwind + math.cos(alpha) * Vmin
|
||||
|
||||
|
||||
-- Speed of ship so it matches the desired speed.
|
||||
local v=0
|
||||
|
||||
-- Angle wrt. to wind TO-direction
|
||||
local theta=0
|
||||
|
||||
if vdeck>vdeckMax then
|
||||
-- Boat cannot go fast enough
|
||||
|
||||
-- Set max speed.
|
||||
v=Vmax
|
||||
|
||||
-- Calculate theta.
|
||||
theta = math.asin(v/(vwind*C)) - math.asin(-1/C)
|
||||
|
||||
elseif vdeck<vdeckMin then
|
||||
-- Boat cannot go slow enought
|
||||
|
||||
-- Set min speed.
|
||||
v=Vmin
|
||||
|
||||
-- Calculatge theta.
|
||||
theta = math.asin(v/(vwind*C)) - math.asin(-1/C)
|
||||
|
||||
elseif vdeck*math.sin(alpha)>vwind then
|
||||
-- Too little wind
|
||||
|
||||
-- Set theta to 90°
|
||||
theta=math.pi/2
|
||||
|
||||
-- Set speed.
|
||||
v = math.sqrt(vdeck^2 - vwind^2)
|
||||
|
||||
else
|
||||
-- Normal case
|
||||
theta = math.asin(vdeck * math.sin(alpha) / vwind)
|
||||
v = vdeck * math.cos(alpha) - vwind * math.cos(theta)
|
||||
end
|
||||
|
||||
-- Magnetic heading.
|
||||
local magvar= magnetic and self.magvar or 0
|
||||
|
||||
-- Ship heading so cross wind is min for the given wind.
|
||||
local intowind = (540 + (windto - magvar + math.deg(theta) )) % 360
|
||||
|
||||
return intowind, v
|
||||
end
|
||||
|
||||
--- Get base recovery course (BRC) when the carrier would head into the wind.
|
||||
-- This includes the current wind direction and accounts for the angled runway.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number vdeck Desired wind velocity over deck in knots.
|
||||
-- @return #number BRC into the wind in degrees.
|
||||
function AIRBOSS:GetBRCintoWind()
|
||||
function AIRBOSS:GetBRCintoWind(vdeck)
|
||||
-- BRC is the magnetic heading.
|
||||
return self:GetHeadingIntoWind( true )
|
||||
return self:GetHeadingIntoWind(vdeck, true )
|
||||
end
|
||||
|
||||
--- Get final bearing (FB) of carrier.
|
||||
@@ -13526,28 +13620,32 @@ function AIRBOSS:CarrierTurnIntoWind( time, vdeck, uturn )
|
||||
-- Wind speed.
|
||||
local _, vwind = self:GetWind()
|
||||
|
||||
-- Desired wind on deck in knots.
|
||||
local vdeck=UTILS.MpsToKnots(vdeck)
|
||||
|
||||
-- Get heading into the wind accounting for angled runway.
|
||||
local hiw, speedknots = self:GetHeadingIntoWind(vdeck)
|
||||
|
||||
-- Speed of carrier in m/s but at least 4 knots.
|
||||
local vtot = math.max( vdeck - vwind, UTILS.KnotsToMps( 4 ) )
|
||||
local vtot = UTILS.KnotsToMps(speedknots)
|
||||
|
||||
-- Distance to travel
|
||||
local dist = vtot * time
|
||||
|
||||
-- Speed in knots
|
||||
local speedknots = UTILS.MpsToKnots( vtot )
|
||||
-- Distance in NM.
|
||||
local distNM = UTILS.MetersToNM( dist )
|
||||
|
||||
-- Debug output
|
||||
self:I( self.lid .. string.format( "Carrier steaming into the wind (%.1f kts). Distance=%.1f NM, Speed=%.1f knots, Time=%d sec.", UTILS.MpsToKnots( vwind ), distNM, speedknots, time ) )
|
||||
|
||||
-- Get heading into the wind accounting for angled runway.
|
||||
local hiw = self:GetHeadingIntoWind()
|
||||
|
||||
-- Current heading.
|
||||
local hdg = self:GetHeading()
|
||||
|
||||
-- Heading difference.
|
||||
local deltaH = self:_GetDeltaHeading( hdg, hiw )
|
||||
|
||||
-- Debug output
|
||||
self:I( self.lid .. string.format( "Carrier steaming into the wind (%.1f kts). Heading=%03d-->%03d (Delta=%.1f), Speed=%.1f knots, Distance=%.1f NM, Time=%d sec",
|
||||
UTILS.MpsToKnots( vwind ), hdg, hiw, deltaH, speedknots, distNM, speedknots, time ) )
|
||||
|
||||
-- Current coordinate.
|
||||
local Cv = self:GetCoordinate()
|
||||
|
||||
local Ctiw = nil -- Core.Point#COORDINATE
|
||||
@@ -13561,7 +13659,7 @@ function AIRBOSS:CarrierTurnIntoWind( time, vdeck, uturn )
|
||||
Csoo = Cv:Translate( 750, hdg ):Translate( 750, hiw )
|
||||
|
||||
-- Heading into wind from Csoo.
|
||||
local hsw = self:GetHeadingIntoWind( false, Csoo )
|
||||
local hsw = self:GetHeadingIntoWind(vdeck, false, Csoo )
|
||||
|
||||
-- Into the wind coord.
|
||||
Ctiw = Csoo:Translate( dist, hsw )
|
||||
@@ -13573,7 +13671,7 @@ function AIRBOSS:CarrierTurnIntoWind( time, vdeck, uturn )
|
||||
Csoo = Cv:Translate( 900, hdg ):Translate( 900, hiw )
|
||||
|
||||
-- Heading into wind from Csoo.
|
||||
local hsw = self:GetHeadingIntoWind( false, Csoo )
|
||||
local hsw = self:GetHeadingIntoWind(vdeck, false, Csoo )
|
||||
|
||||
-- Into the wind coord.
|
||||
Ctiw = Csoo:Translate( dist, hsw )
|
||||
@@ -13585,7 +13683,7 @@ function AIRBOSS:CarrierTurnIntoWind( time, vdeck, uturn )
|
||||
Csoo = Cv:Translate( 1100, hdg - 90 ):Translate( 1000, hiw )
|
||||
|
||||
-- Heading into wind from Csoo.
|
||||
local hsw = self:GetHeadingIntoWind( false, Csoo )
|
||||
local hsw = self:GetHeadingIntoWind(vdeck, false, Csoo )
|
||||
|
||||
-- Into the wind coord.
|
||||
Ctiw = Csoo:Translate( dist, hsw )
|
||||
@@ -13597,7 +13695,7 @@ function AIRBOSS:CarrierTurnIntoWind( time, vdeck, uturn )
|
||||
Csoo = Cv:Translate( 1200, hdg - 90 ):Translate( 1000, hiw )
|
||||
|
||||
-- Heading into wind from Csoo.
|
||||
local hsw = self:GetHeadingIntoWind( false, Csoo )
|
||||
local hsw = self:GetHeadingIntoWind(vdeck, false, Csoo )
|
||||
|
||||
-- Into the wind coord.
|
||||
Ctiw = Csoo:Translate( dist, hsw )
|
||||
@@ -13810,7 +13908,8 @@ function AIRBOSS:_CheckCarrierTurning()
|
||||
local hdg
|
||||
if self.turnintowind then
|
||||
-- We are now steaming into the wind.
|
||||
hdg = self:GetHeadingIntoWind( false )
|
||||
local vdeck=self.recoverywindow and self.recoverywindow.SPEED or 20
|
||||
hdg = self:GetHeadingIntoWind(vdeck, false)
|
||||
else
|
||||
-- We turn towards the next waypoint.
|
||||
hdg = self:GetCoordinate():HeadingTo( self:_GetNextWaypoint() )
|
||||
@@ -14730,12 +14829,12 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
if radio == nil or call == nil then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if not self.SRS then
|
||||
|
||||
|
||||
-- Create a new radio transmission item.
|
||||
local transmission = {} -- #AIRBOSS.Radioitem
|
||||
|
||||
|
||||
transmission.radio = radio
|
||||
transmission.call = call
|
||||
transmission.Tplay = timer.getAbsTime() + (delay or 0)
|
||||
@@ -14743,12 +14842,12 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
transmission.isplaying = false
|
||||
transmission.Tstarted = nil
|
||||
transmission.loud = loud and call.loud
|
||||
|
||||
|
||||
-- Player onboard number if sender has one.
|
||||
if self:_IsOnboard( call.modexsender ) then
|
||||
self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall )
|
||||
end
|
||||
|
||||
|
||||
-- Play onboard number if receiver has one.
|
||||
if self:_IsOnboard( call.modexreceiver ) then
|
||||
self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall )
|
||||
@@ -14787,61 +14886,68 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
end
|
||||
|
||||
else
|
||||
-- SRS transmission
|
||||
|
||||
local frequency = self.MarshalRadio.frequency
|
||||
local modulation = self.MarshalRadio.modulation
|
||||
local voice = nil
|
||||
local gender = nil
|
||||
local culture = nil
|
||||
|
||||
if radio.alias == "AIRBOSS" then
|
||||
frequency = self.AirbossRadio.frequency
|
||||
modulation = self.AirbossRadio.modulation
|
||||
voice = self.AirbossRadio.voice
|
||||
gender = self.AirbossRadio.gender
|
||||
culture = self.AirbossRadio.culture
|
||||
end
|
||||
|
||||
if radio.alias == "MARSHAL" then
|
||||
voice = self.MarshalRadio.voice
|
||||
gender = self.MarshalRadio.gender
|
||||
culture = self.MarshalRadio.culture
|
||||
end
|
||||
|
||||
if radio.alias == "LSO" then
|
||||
frequency = self.LSORadio.frequency
|
||||
modulation = self.LSORadio.modulation
|
||||
voice = self.LSORadio.voice
|
||||
gender = self.LSORadio.gender
|
||||
culture = self.LSORadio.culture
|
||||
end
|
||||
|
||||
if pilotcall then
|
||||
voice = self.PilotRadio.voice
|
||||
gender = self.PilotRadio.gender
|
||||
culture = self.PilotRadio.culture
|
||||
radio.alias = "PILOT"
|
||||
end
|
||||
|
||||
if not radio.alias then
|
||||
-- TODO - what freq to use here?
|
||||
frequency = self.AirbossRadio.frequency
|
||||
modulation = self.AirbossRadio.modulation
|
||||
radio.alias = "AIRBOSS"
|
||||
-- SRS transmission
|
||||
if call.subtitle ~= nil and string.len(call.subtitle) > 1 then
|
||||
|
||||
|
||||
else
|
||||
-- SRS transmission
|
||||
|
||||
local frequency = self.MarshalRadio.frequency
|
||||
local modulation = self.MarshalRadio.modulation
|
||||
local voice = nil
|
||||
local gender = nil
|
||||
local culture = nil
|
||||
|
||||
if radio.alias == "AIRBOSS" then
|
||||
frequency = self.AirbossRadio.frequency
|
||||
modulation = self.AirbossRadio.modulation
|
||||
voice = self.AirbossRadio.voice
|
||||
gender = self.AirbossRadio.gender
|
||||
culture = self.AirbossRadio.culture
|
||||
end
|
||||
|
||||
if radio.alias == "MARSHAL" then
|
||||
voice = self.MarshalRadio.voice
|
||||
gender = self.MarshalRadio.gender
|
||||
culture = self.MarshalRadio.culture
|
||||
end
|
||||
|
||||
if radio.alias == "LSO" then
|
||||
frequency = self.LSORadio.frequency
|
||||
modulation = self.LSORadio.modulation
|
||||
voice = self.LSORadio.voice
|
||||
gender = self.LSORadio.gender
|
||||
culture = self.LSORadio.culture
|
||||
end
|
||||
|
||||
if pilotcall then
|
||||
voice = self.PilotRadio.voice
|
||||
gender = self.PilotRadio.gender
|
||||
culture = self.PilotRadio.culture
|
||||
radio.alias = "PILOT"
|
||||
end
|
||||
|
||||
if not radio.alias then
|
||||
-- TODO - what freq to use here?
|
||||
frequency = self.AirbossRadio.frequency
|
||||
modulation = self.AirbossRadio.modulation
|
||||
radio.alias = "AIRBOSS"
|
||||
end
|
||||
|
||||
local volume = nil
|
||||
|
||||
if loud then
|
||||
volume = 1.0
|
||||
end
|
||||
|
||||
--local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle
|
||||
local text = call.subtitle
|
||||
self:I(self.lid..text)
|
||||
local srstext = self:_GetNiceSRSText(text)
|
||||
self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, tstart, 0.1, subgroups, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias)
|
||||
end
|
||||
|
||||
local volume = nil
|
||||
|
||||
if loud then
|
||||
volume = 1.0
|
||||
end
|
||||
|
||||
--local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle
|
||||
local text = call.subtitle
|
||||
self:I(self.lid..text)
|
||||
local srstext = self:_GetNiceSRSText(text)
|
||||
self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, tstart, 0.1, subgroups, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15176,44 +15282,44 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
|
||||
-- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay)
|
||||
self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear )
|
||||
else
|
||||
|
||||
|
||||
if not self.SRS then
|
||||
-- Wait until previous sound finished.
|
||||
local wait = 0
|
||||
|
||||
|
||||
-- Onboard number to get the attention.
|
||||
if receiver == playerData.onboard then
|
||||
|
||||
|
||||
-- Which voice over number to use.
|
||||
if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then
|
||||
|
||||
|
||||
-- User sound of board number.
|
||||
wait = wait + self:_Number2Sound( playerData, sender, receiver )
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Negative.
|
||||
if string.find( text:lower(), "negative" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.NEGATIVE.duration
|
||||
end
|
||||
|
||||
|
||||
-- Affirm.
|
||||
if string.find( text:lower(), "affirm" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.AFFIRMATIVE.duration
|
||||
end
|
||||
|
||||
|
||||
-- Roger.
|
||||
if string.find( text:lower(), "roger" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.ROGER.duration
|
||||
end
|
||||
|
||||
|
||||
-- Play click sound to end message.
|
||||
if wait > 0 then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.CLICK )
|
||||
@@ -15226,7 +15332,7 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
|
||||
local voice = self.MarshalRadio.voice
|
||||
local gender = self.MarshalRadio.gender
|
||||
local culture = self.MarshalRadio.culture
|
||||
|
||||
|
||||
if not sender then sender = "AIRBOSS" end
|
||||
|
||||
if string.find(sender,"AIRBOSS" ) then
|
||||
@@ -15629,7 +15735,7 @@ function AIRBOSS:_LSOCallAircraftBall( modex, nickname, fuelstate )
|
||||
local text = string.format( "%s Ball, %.1f.", nickname, fuelstate )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Nickname UPPERCASE.
|
||||
local NICKNAME = nickname:upper()
|
||||
@@ -15665,7 +15771,7 @@ function AIRBOSS:_MarshalCallGasAtTanker( modex )
|
||||
local text = string.format( "Bingo fuel! Going for gas at the recovery tanker." )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
|
||||
-- Create new call to display complete subtitle.
|
||||
@@ -15689,7 +15795,7 @@ function AIRBOSS:_MarshalCallGasAtDivert( modex, divertname )
|
||||
local text = string.format( "Bingo fuel! Going for gas at divert field %s.", divertname )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Create new call to display complete subtitle.
|
||||
local call = self:_NewRadioCall( self.PilotCall.BINGOFUEL, modex, text, self.Tmessage, nil, modex )
|
||||
@@ -15711,7 +15817,7 @@ function AIRBOSS:_MarshalCallRecoveryStopped( case )
|
||||
local text = string.format( "Case %d recovery ops are stopped. Deck is closed.", case )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Create new call to display complete subtitle.
|
||||
local call = self:_NewRadioCall( self.MarshalCall.CASE, "AIRBOSS", text, self.Tmessage, "99" )
|
||||
@@ -15752,7 +15858,7 @@ function AIRBOSS:_MarshalCallRecoveryPausedResumedAt( clock )
|
||||
local text = string.format( "aircraft recovery is paused and will be resumed at %s.", clock )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Create new call with full subtitle.
|
||||
local call = self:_NewRadioCall( self.MarshalCall.RECOVERYPAUSEDRESUMED, "AIRBOSS", text, self.Tmessage, "99" )
|
||||
@@ -15779,7 +15885,7 @@ function AIRBOSS:_MarshalCallClearedForRecovery( modex, case )
|
||||
local text = string.format( "you're cleared for Case %d recovery.", case )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Create new call with full subtitle.
|
||||
local call = self:_NewRadioCall( self.MarshalCall.CLEAREDFORRECOVERY, "MARSHAL", text, self.Tmessage, modex )
|
||||
@@ -15817,7 +15923,7 @@ function AIRBOSS:_MarshalCallNewFinalBearing( FB )
|
||||
local text = string.format( "new final bearing %03d°.", FB )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Create new call with full subtitle.
|
||||
local call = self:_NewRadioCall( self.MarshalCall.NEWFB, "AIRBOSS", text, self.Tmessage, "99" )
|
||||
@@ -15840,7 +15946,7 @@ function AIRBOSS:_MarshalCallCarrierTurnTo( hdg )
|
||||
local text = string.format( "carrier is now starting turn to heading %03d°.", hdg )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Create new call with full subtitle.
|
||||
local call = self:_NewRadioCall( self.MarshalCall.CARRIERTURNTOHEADING, "AIRBOSS", text, self.Tmessage, "99" )
|
||||
@@ -15871,7 +15977,7 @@ function AIRBOSS:_MarshalCallStackFull( modex, nwaiting )
|
||||
end
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Create new call with full subtitle.
|
||||
local call = self:_NewRadioCall( self.MarshalCall.STACKFULL, "AIRBOSS", text, self.Tmessage, modex )
|
||||
@@ -15942,7 +16048,7 @@ function AIRBOSS:_MarshalCallArrived( modex, case, brc, altitude, charlie, qfe )
|
||||
local text = string.format( "Case %d, expected BRC %03d°, hold at angels %d. Expected Charlie Time %s. Altimeter %.2f. Report see me.", case, brc, angels, charlie, qfe )
|
||||
|
||||
-- Debug message.
|
||||
self:I( self.lid .. text )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
-- Create new call to display complete subtitle.
|
||||
local casecall = self:_NewRadioCall( self.MarshalCall.CASE, "MARSHAL", text, self.Tmessage, modex )
|
||||
|
||||
@@ -443,6 +443,7 @@ _AUFTRAGSNR=0
|
||||
-- @field #string REARMING Rearming mission.
|
||||
-- @field #string CAPTUREZONE Capture zone mission.
|
||||
-- @field #string NOTHING Nothing.
|
||||
-- @field #string PATROLRACETRACK Patrol Racetrack.
|
||||
AUFTRAG.Type={
|
||||
ANTISHIP="Anti Ship",
|
||||
AWACS="AWACS",
|
||||
@@ -484,10 +485,10 @@ AUFTRAG.Type={
|
||||
RELOCATECOHORT="Relocate Cohort",
|
||||
AIRDEFENSE="Air Defence",
|
||||
EWR="Early Warning Radar",
|
||||
--RECOVERYTANKER="Recovery Tanker",
|
||||
REARMING="Rearming",
|
||||
CAPTUREZONE="Capture Zone",
|
||||
NOTHING="Nothing",
|
||||
PATROLRACETRACK="Patrol Racetrack",
|
||||
}
|
||||
|
||||
--- Special task description.
|
||||
@@ -511,6 +512,7 @@ AUFTRAG.Type={
|
||||
-- @field #string REARMING Rearming.
|
||||
-- @field #string CAPTUREZONE Capture OPS zone.
|
||||
-- @field #string NOTHING Nothing.
|
||||
-- @field #string PATROLRACETRACK Patrol Racetrack.
|
||||
AUFTRAG.SpecialTask={
|
||||
FORMATION="Formation",
|
||||
PATROLZONE="PatrolZone",
|
||||
@@ -532,6 +534,7 @@ AUFTRAG.SpecialTask={
|
||||
REARMING="Rearming",
|
||||
CAPTUREZONE="Capture Zone",
|
||||
NOTHING="Nothing",
|
||||
PATROLRACETRACK="Patrol Racetrack",
|
||||
}
|
||||
|
||||
--- Mission status.
|
||||
@@ -652,7 +655,7 @@ AUFTRAG.Category={
|
||||
|
||||
--- AUFTRAG class version.
|
||||
-- @field #string version
|
||||
AUFTRAG.version="1.2.0"
|
||||
AUFTRAG.version="1.2.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -1017,7 +1020,7 @@ end
|
||||
-- @param #number Altitude Hover altitude in feet AGL. Default is 50 feet above ground.
|
||||
-- @param #number Time Time in seconds to hold the hover. Default 300 seconds.
|
||||
-- @param #number Speed Speed in knots to fly to the target coordinate. Default 150kn.
|
||||
-- @param #number MissionAlt Altitide to fly towards the mission in feet AGL. Default 1000ft.
|
||||
-- @param #number MissionAlt Altitude to fly towards the mission in feet AGL. Default 1000ft.
|
||||
-- @return #AUFTRAG self
|
||||
function AUFTRAG:NewHOVER(Coordinate, Altitude, Time, Speed, MissionAlt)
|
||||
|
||||
@@ -1049,6 +1052,58 @@ function AUFTRAG:NewHOVER(Coordinate, Altitude, Time, Speed, MissionAlt)
|
||||
return mission
|
||||
end
|
||||
|
||||
--- **[AIR]** Create an enhanced orbit race track mission. Planes will keep closer to the track.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Core.Point#COORDINATE Coordinate Where to start the race track.
|
||||
-- @param #number Altitude (Optional) Altitude in feet. Defaults to 20,000ft ASL.
|
||||
-- @param #number Speed (Optional) Speed in knots. Defaults to 300kn TAS.
|
||||
-- @param #number Heading (Optional) Heading in degrees, 0 to 360. Defaults to 90 degree (East).
|
||||
-- @param #number Leg (Optional) Leg of the race track in NM. Defaults to 10nm.
|
||||
-- @param #number Formation (Optional) Formation to take, e.g. ENUMS.Formation.FixedWing.Trail.Close, also see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_option_formation).
|
||||
-- @return #AUFTRAG self
|
||||
function AUFTRAG:NewPATROL_RACETRACK(Coordinate,Altitude,Speed,Heading,Leg,Formation)
|
||||
|
||||
local mission = AUFTRAG:New(AUFTRAG.Type.PATROLRACETRACK)
|
||||
|
||||
-- Target.
|
||||
mission:_TargetFromObject(Coordinate)
|
||||
|
||||
-- Set Altitude.
|
||||
if Altitude then
|
||||
mission.TrackAltitude=UTILS.FeetToMeters(Altitude)
|
||||
else
|
||||
mission.TrackAltitude=UTILS.FeetToMeters(20000)
|
||||
end
|
||||
|
||||
-- Points
|
||||
mission.TrackPoint1 = Coordinate
|
||||
|
||||
local leg = UTILS.NMToMeters(Leg) or UTILS.NMToMeters(10)
|
||||
|
||||
local heading = Heading or 90
|
||||
|
||||
if heading < 0 or heading > 360 then heading = 90 end
|
||||
|
||||
mission.TrackPoint2 = Coordinate:Translate(leg,heading,true)
|
||||
|
||||
-- Orbit speed in m/s TAS.
|
||||
mission.TrackSpeed = UTILS.IasToTas(UTILS.KnotsToKmph(Speed or 300), mission.TrackAltitude)
|
||||
|
||||
-- Mission speed in km/h and altitude
|
||||
mission.missionSpeed = UTILS.KnotsToKmph(Speed or 300)
|
||||
mission.missionAltitude = mission.TrackAltitude * 0.9
|
||||
mission.missionTask=ENUMS.MissionTask.CAP
|
||||
mission.optionROE=ENUMS.ROE.ReturnFire
|
||||
mission.optionROT=ENUMS.ROT.PassiveDefense
|
||||
|
||||
mission.categories={AUFTRAG.Category.AIRCRAFT}
|
||||
|
||||
mission.DCStask=mission:GetDCSMissionTask()
|
||||
|
||||
return mission
|
||||
end
|
||||
|
||||
|
||||
--- **[AIR]** Create an ORBIT mission, which can be either a circular orbit or a race-track pattern.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Core.Point#COORDINATE Coordinate Where to orbit.
|
||||
@@ -1181,7 +1236,7 @@ function AUFTRAG:NewORBIT_GROUP(Group, Altitude, Speed, Leg, Heading, OffsetVec2
|
||||
end
|
||||
|
||||
|
||||
--- **[AIR]** Create a Ground Controlled CAP (GCICAP) mission. Flights with this task are considered for A2A INTERCEPT missions by the CHIEF class. They will perform a compat air patrol but not engage by
|
||||
--- **[AIR]** Create a Ground Controlled CAP (GCICAP) mission. Flights with this task are considered for A2A INTERCEPT missions by the CHIEF class. They will perform a combat air patrol but not engage by
|
||||
-- themselfs. They wait for the CHIEF to tell them whom to engage.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Core.Point#COORDINATE Coordinate Where to orbit.
|
||||
@@ -1312,8 +1367,11 @@ function AUFTRAG:NewCAP(ZoneCAP, Altitude, Speed, Coordinate, Heading, Leg, Targ
|
||||
-- Ensure given TargetTypes parameter is a table.
|
||||
TargetTypes=UTILS.EnsureTable(TargetTypes, true)
|
||||
|
||||
-- Set default altitude if not specified.
|
||||
Altitude = Altitude or 10000
|
||||
|
||||
-- Create ORBIT first.
|
||||
local mission=AUFTRAG:NewORBIT(Coordinate or ZoneCAP:GetCoordinate(), Altitude or 10000, Speed or 350, Heading, Leg)
|
||||
local mission=AUFTRAG:NewORBIT(Coordinate or ZoneCAP:GetCoordinate(), Altitude, Speed or 350, Heading, Leg)
|
||||
|
||||
-- Mission type CAP.
|
||||
mission.type=AUFTRAG.Type.CAP
|
||||
@@ -1336,9 +1394,9 @@ function AUFTRAG:NewCAP(ZoneCAP, Altitude, Speed, Coordinate, Heading, Leg, Targ
|
||||
return mission
|
||||
end
|
||||
|
||||
--- **[AIR]** Create a CAP mission on a group.
|
||||
--- **[AIR]** Create a CAP mission over a (moving) group.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Wrapper.Group#GROUP Grp.
|
||||
-- @param Wrapper.Group#GROUP Grp The grp to perform the CAP over.
|
||||
-- @param #number Altitude Orbit altitude in feet. Default is 6,000 ft.
|
||||
-- @param #number Speed Orbit speed in knots. Default 250 KIAS.
|
||||
-- @param #number RelHeading Relative heading [0, 360) of race-track pattern in degrees wrt heading of the carrier. Default is heading of the carrier.
|
||||
@@ -2226,7 +2284,15 @@ function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude, Adinfinitum, Randomly, Forma
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.RECON)
|
||||
|
||||
mission:_TargetFromObject(ZoneSet)
|
||||
|
||||
|
||||
if ZoneSet:IsInstanceOf("SET_ZONE") then
|
||||
mission.missionZoneSet = ZoneSet
|
||||
elseif ZoneSet:IsInstanceOf("ZONE_BASE") then
|
||||
mission.missionZoneSet = SET_ZONE:New()
|
||||
mission.missionZoneSet:AddZone(ZoneSet)
|
||||
end
|
||||
|
||||
|
||||
mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.RECON)
|
||||
|
||||
mission.optionROE=ENUMS.ROE.WeaponHold
|
||||
@@ -2666,7 +2732,7 @@ function AUFTRAG:NewAUTO(EngageGroup)
|
||||
elseif auftrag==AUFTRAG.Type.ORBIT then
|
||||
mission=AUFTRAG:NewORBIT(Coordinate,Altitude,Speed,Heading,Leg)
|
||||
elseif auftrag==AUFTRAG.Type.RECON then
|
||||
-- Not implemented yet.
|
||||
mission=AUFTRAG:NewRECON(ZoneSet,Speed,Altitude,Adinfinitum,Randomly,Formation)
|
||||
elseif auftrag==AUFTRAG.Type.RESCUEHELO then
|
||||
mission=AUFTRAG:NewRESCUEHELO(Carrier)
|
||||
elseif auftrag==AUFTRAG.Type.SEAD then
|
||||
@@ -2677,6 +2743,8 @@ function AUFTRAG:NewAUTO(EngageGroup)
|
||||
mission=AUFTRAG:NewTANKER(Coordinate,Altitude,Speed,Heading,Leg,RefuelSystem)
|
||||
elseif auftrag==AUFTRAG.Type.TROOPTRANSPORT then
|
||||
mission=AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet,DropoffCoordinate,PickupCoordinate)
|
||||
elseif auftrag==AUFTRAG.Type.PATROLRACETRACK then
|
||||
mission=AUFTRAG:NewPATROL_RACETRACK(Coordinate,Altitude,Speed,Heading,Leg,Formation)
|
||||
else
|
||||
|
||||
end
|
||||
@@ -5359,6 +5427,10 @@ function AUFTRAG:GetTargetCoordinate()
|
||||
|
||||
-- Special case where we defined a
|
||||
return self.transportPickup
|
||||
|
||||
elseif self.missionZoneSet and self.type == AUFTRAG.Type.RECON then
|
||||
|
||||
return self.missionZoneSet:GetAverageCoordinate()
|
||||
|
||||
elseif self.engageTarget then
|
||||
|
||||
@@ -5776,10 +5848,12 @@ function AUFTRAG:UpdateMarker()
|
||||
-- Get target coordinates. Can be nil!
|
||||
local targetcoord=self:GetTargetCoordinate()
|
||||
|
||||
if self.markerCoaliton and self.markerCoaliton>=0 then
|
||||
self.marker=MARKER:New(targetcoord, text):ReadOnly():ToCoalition(self.markerCoaliton)
|
||||
else
|
||||
self.marker=MARKER:New(targetcoord, text):ReadOnly():ToAll()
|
||||
if targetcoord then
|
||||
if self.markerCoaliton and self.markerCoaliton>=0 then
|
||||
self.marker=MARKER:New(targetcoord, text):ReadOnly():ToCoalition(self.markerCoaliton)
|
||||
else
|
||||
self.marker=MARKER:New(targetcoord, text):ReadOnly():ToAll()
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
@@ -6326,8 +6400,32 @@ function AUFTRAG:GetDCSMissionTask()
|
||||
|
||||
DCStask.params=param
|
||||
|
||||
table.insert(DCStasks, DCStask)
|
||||
table.insert(DCStasks, DCStask)
|
||||
|
||||
elseif self.type==AUFTRAG.Type.PATROLRACETRACK then
|
||||
|
||||
---------------------
|
||||
-- Enhanced Orbit Racetrack --
|
||||
---------------------
|
||||
|
||||
local DCStask={}
|
||||
DCStask.id=AUFTRAG.SpecialTask.PATROLRACETRACK
|
||||
|
||||
local param={}
|
||||
-- ONTROLLABLE:PatrolRaceTrack(Point1, Point2, Altitude, Speed, Formation, Delay)
|
||||
|
||||
param.TrackAltitude = self.TrackAltitude
|
||||
param.TrackSpeed = self.TrackSpeed
|
||||
param.TrackPoint1 = self.TrackPoint1
|
||||
param.TrackPoint2 = self.TrackPoint2
|
||||
param.missionSpeed = self.missionSpeed
|
||||
param.missionAltitude = self.missionAltitude
|
||||
param.TrackFormation = self.TrackFormation
|
||||
|
||||
DCStask.params=param
|
||||
|
||||
table.insert(DCStasks, DCStask)
|
||||
|
||||
elseif self.type==AUFTRAG.Type.HOVER then
|
||||
|
||||
---------------------
|
||||
@@ -6602,6 +6700,8 @@ function AUFTRAG:GetMissionTaskforMissionType(MissionType)
|
||||
mtask=ENUMS.MissionTask.NOTHING
|
||||
elseif MissionType==AUFTRAG.Type.HOVER then
|
||||
mtask=ENUMS.MissionTask.NOTHING
|
||||
elseif MissionType==AUFTRAG.Type.PATROLRACETRACK then
|
||||
mtask=ENUMS.MissionTask.CAP
|
||||
end
|
||||
|
||||
return mtask
|
||||
@@ -6688,8 +6788,6 @@ function AUFTRAG.CheckMissionCapabilityAll(MissionTypes, Capabilities)
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **applevangelist**
|
||||
-- @date Last Update December 2022
|
||||
-- @date Last Update July 2023
|
||||
-- @module Ops.AWACS
|
||||
-- @image OPS_AWACS.jpg
|
||||
|
||||
@@ -63,6 +63,7 @@ do
|
||||
-- @field Utilities.FiFo#FIFO RadioQueue
|
||||
-- @field Utilities.FiFo#FIFO PrioRadioQueue
|
||||
-- @field Utilities.FiFo#FIFO CAPAirwings
|
||||
-- @field Utilities.FiFo#FIFO TacticalQueue
|
||||
-- @field #number AwacsTimeOnStation
|
||||
-- @field #number AwacsTimeStamp
|
||||
-- @field #number EscortsTimeOnStation
|
||||
@@ -113,6 +114,13 @@ do
|
||||
-- @field Wrapper.Group#GROUP GCIGroup EWR group object for GCI ops
|
||||
-- @field #string locale Localization
|
||||
-- @field #boolean IncludeHelicopters
|
||||
-- @field #boolean TacticalMenu
|
||||
-- @field #table TacticalFrequencies
|
||||
-- @field #table TacticalSubscribers
|
||||
-- @field #number TacticalBaseFreq
|
||||
-- @field #number TacticalIncrFreq
|
||||
-- @field #number TacticalModulation
|
||||
-- @field #number TacticalInterval
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
|
||||
@@ -499,7 +507,7 @@ do
|
||||
-- @field #AWACS
|
||||
AWACS = {
|
||||
ClassName = "AWACS", -- #string
|
||||
version = "0.2.55", -- #string
|
||||
version = "0.2.57", -- #string
|
||||
lid = "", -- #string
|
||||
coalition = coalition.side.BLUE, -- #number
|
||||
coalitiontxt = "blue", -- #string
|
||||
@@ -532,6 +540,7 @@ AWACS = {
|
||||
ContactsAO = {}, -- Utilities.FiFo#FIFO
|
||||
RadioQueue = {}, -- Utilities.FiFo#FIFO
|
||||
PrioRadioQueue = {}, -- Utilities.FiFo#FIFO
|
||||
TacticalQueue = {}, -- Utilities.FiFo#FIFO
|
||||
AwacsTimeOnStation = 4,
|
||||
AwacsTimeStamp = 0,
|
||||
EscortsTimeOnStation = 4,
|
||||
@@ -587,6 +596,13 @@ AWACS = {
|
||||
GCIGroup = nil,
|
||||
locale = "en",
|
||||
IncludeHelicopters = false,
|
||||
TacticalMenu = false,
|
||||
TacticalFrequencies = {},
|
||||
TacticalSubscribers = {},
|
||||
TacticalBaseFreq = 130,
|
||||
TacticalIncrFreq = 0.5,
|
||||
TacticalModulation = radio.modulation.AM,
|
||||
TacticalInterval = 120,
|
||||
}
|
||||
|
||||
---
|
||||
@@ -917,7 +933,7 @@ AWACS.TaskStatus = {
|
||||
--@field #boolean FromAI
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO-List 0.2.52
|
||||
-- TODO-List 0.2.53
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- DONE - WIP - Player tasking, VID
|
||||
@@ -1110,6 +1126,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
|
||||
self.Volume = 1.0
|
||||
self.RadioQueue = FIFO:New() -- Utilities.FiFo#FIFO
|
||||
self.PrioRadioQueue = FIFO:New() -- Utilities.FiFo#FIFO
|
||||
self.TacticalQueue = FIFO:New() -- Utilities.FiFo#FIFO
|
||||
self.maxspeakentries = 3
|
||||
self.GoogleTTSPadding = 1
|
||||
self.WindowsTTSPadding = 2.5
|
||||
@@ -1180,6 +1197,15 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
|
||||
|
||||
self.clientmenus = FIFO:New() -- Utilities.FiFo#FIFO
|
||||
|
||||
-- Tactical Menu
|
||||
self.TacticalMenu = false
|
||||
self.TacticalBaseFreq = 130
|
||||
self.TacticalIncrFreq = 0.5
|
||||
self.TacticalModulation = radio.modulation.AM
|
||||
self.acticalFrequencies = {}
|
||||
self.TacticalSubscribers = {}
|
||||
self.TacticalInterval = 120
|
||||
|
||||
-- SET for Intel Detection
|
||||
self.DetectionSet=SET_GROUP:New()
|
||||
|
||||
@@ -1204,6 +1230,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
|
||||
self:AddTransition("*", "LostCluster", "*")
|
||||
self:AddTransition("*", "LostContact", "*")
|
||||
self:AddTransition("*", "CheckRadioQueue", "*")
|
||||
self:AddTransition("*", "CheckTacticalQueue", "*")
|
||||
self:AddTransition("*", "EscortShiftChange", "*")
|
||||
self:AddTransition("*", "AwacsShiftChange", "*")
|
||||
self:AddTransition("*", "FlightOnMission", "*")
|
||||
@@ -1354,6 +1381,159 @@ end
|
||||
-- Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- [User] Set the tactical information option, create 10 radio channels groups can subscribe and get Bogey Dope on a specific frequency automatically.
|
||||
-- @param #AWACS self
|
||||
-- @param #number BaseFreq Base Frequency to use, defaults to 130.
|
||||
-- @param #number Increase Increase to use, defaults to 0.5, thus channels created are 130, 130.5, 131 .. etc.
|
||||
-- @param #number Modulation Modulation to use, defaults to radio.modulation.AM.
|
||||
-- @param #number Interval Seconds between each update call.
|
||||
-- @param #number Number Number of Frequencies to create, can be 1..10.
|
||||
-- @return #AWACS self
|
||||
function AWACS:SetTacticalRadios(BaseFreq,Increase,Modulation,Interval,Number)
|
||||
self:T(self.lid.."SetTacticalRadios")
|
||||
self.TacticalMenu = true
|
||||
self.TacticalBaseFreq = BaseFreq or 130
|
||||
self.TacticalIncrFreq = Increase or 0.5
|
||||
self.TacticalModulation = Modulation or radio.modulation.AM
|
||||
self.TacticalInterval = Interval or 120
|
||||
local number = Number or 10
|
||||
if number < 1 then number = 1 end
|
||||
if number > 10 then number = 10 end
|
||||
for i=1,number do
|
||||
local freq = self.TacticalBaseFreq + ((i-1)*self.TacticalIncrFreq)
|
||||
self.TacticalFrequencies[freq] = freq
|
||||
end
|
||||
if self.AwacsSRS then
|
||||
self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation,self.Volume)
|
||||
self.TacticalSRS:SetCoalition(self.coalition)
|
||||
self.TacticalSRS:SetGender(self.Gender)
|
||||
self.TacticalSRS:SetCulture(self.Culture)
|
||||
self.TacticalSRS:SetVoice(self.Voice)
|
||||
self.TacticalSRS:SetPort(self.Port)
|
||||
self.TacticalSRS:SetLabel("AWACS")
|
||||
if self.PathToGoogleKey then
|
||||
self.TacticalSRS:SetGoogle(self.PathToGoogleKey)
|
||||
end
|
||||
self.TacticalSRSQ = MSRSQUEUE:New("Tactical AWACS")
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- TODO
|
||||
-- [Internal] _RefreshMenuNonSubscribed
|
||||
-- @param #AWACS self
|
||||
-- @return #AWACS self
|
||||
function AWACS:_RefreshMenuNonSubscribed()
|
||||
self:T(self.lid.."_RefreshMenuNonSubscribed")
|
||||
local aliveset = self.clientset:GetAliveSet()
|
||||
|
||||
for _,_group in pairs(aliveset) do
|
||||
-- go through set and re-build the sub-menu
|
||||
local grp = _group -- Wrapper.Client#CLIENT
|
||||
local Group = grp:GetGroup()
|
||||
local gname = nil
|
||||
if Group and Group:IsAlive() then
|
||||
gname = Group:GetName()
|
||||
self:T(gname)
|
||||
end
|
||||
local menustr = self.clientmenus:ReadByID(gname)
|
||||
local menu = menustr.tactical -- Core.Menu#MENU_GROUP
|
||||
if not self.TacticalSubscribers[gname] and menu then
|
||||
menu:RemoveSubMenus()
|
||||
for _,_freq in UTILS.spairs(self.TacticalFrequencies) do
|
||||
local modu = UTILS.GetModulationName(self.TacticalModulation)
|
||||
local text = string.format("Subscribe to %.3f %s",_freq,modu)
|
||||
local entry = MENU_GROUP_COMMAND:New(Group,text,menu,self._SubScribeTactRadio,self,Group,_freq)
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal] _UnsubScribeTactRadio
|
||||
-- @param #AWACS self
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @return #AWACS self
|
||||
function AWACS:_UnsubScribeTactRadio(Group)
|
||||
self:T(self.lid.."_UnsubScribeTactRadio")
|
||||
local text = ""
|
||||
local textScreen = ""
|
||||
local GID, Outcome = self:_GetManagedGrpID(Group)
|
||||
local gcallsign = self:_GetCallSign(Group,GID) or "Ghost 1"
|
||||
local gname = Group:GetName() or "unknown"
|
||||
|
||||
if Outcome and self.TacticalSubscribers[gname] then
|
||||
-- Pilot is checked in
|
||||
local Freq = self.TacticalSubscribers[gname]
|
||||
self.TacticalFrequencies[Freq] = Freq
|
||||
self.TacticalSubscribers[gname] = nil
|
||||
local modu = self.TacticalModulation == 0 and "AM" or "FM"
|
||||
text = string.format("%s, %s, switch back to AWACS main frequency!",gcallsign,self.callsigntxt)
|
||||
self:_NewRadioEntry(text,text,GID,true,true,true,false,true)
|
||||
self:_RefreshMenuNonSubscribed()
|
||||
elseif self.AwacsFG then
|
||||
-- no, unknown
|
||||
local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
|
||||
text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
|
||||
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal] _SubScribeTactRadio
|
||||
-- @param #AWACS self
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @param #number Frequency
|
||||
-- @return #AWACS self
|
||||
function AWACS:_SubScribeTactRadio(Group,Frequency)
|
||||
self:T(self.lid.."_SubScribeTactRadio")
|
||||
local text = ""
|
||||
local textScreen = ""
|
||||
local GID, Outcome = self:_GetManagedGrpID(Group)
|
||||
local gcallsign = self:_GetCallSign(Group,GID) or "Ghost 1"
|
||||
local gname = Group:GetName() or "unknown"
|
||||
|
||||
if Outcome then
|
||||
-- Pilot is checked in
|
||||
self.TacticalSubscribers[gname] = Frequency
|
||||
self.TacticalFrequencies[Frequency] = nil
|
||||
local modu = self.TacticalModulation == 0 and "AM" or "FM"
|
||||
text = string.format("%s, %s, switch to %.3f %s for tactical information!",gcallsign,self.callsigntxt,Frequency,modu)
|
||||
self:_NewRadioEntry(text,text,GID,true,true,true,false,true)
|
||||
local menustr = self.clientmenus:ReadByID(gname)
|
||||
local menu = menustr.tactical -- Core.Menu#MENU_GROUP
|
||||
if menu then
|
||||
menu:RemoveSubMenus()
|
||||
local text = string.format("Unsubscribe %.3f %s",Frequency,modu)
|
||||
local entry = MENU_GROUP_COMMAND:New(Group,text,menu,self._UnsubScribeTactRadio,self,Group)
|
||||
end
|
||||
elseif self.AwacsFG then
|
||||
-- no, unknown
|
||||
local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
|
||||
text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
|
||||
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal] _CheckSubscribers
|
||||
-- @param #AWACS self
|
||||
-- @return #AWACS self
|
||||
function AWACS:_CheckSubscribers()
|
||||
self:T(self.lid.."_InitLocalization")
|
||||
|
||||
for _name,_freq in pairs(self.TacticalSubscribers or {}) do
|
||||
local grp = GROUP:FindByName(_name)
|
||||
if (not grp) or (not grp:IsAlive()) then
|
||||
self.TacticalFrequencies[_freq] = _freq
|
||||
self.TacticalSubscribers[_name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal] Init localization
|
||||
-- @param #AWACS self
|
||||
-- @return #AWACS self
|
||||
@@ -1426,19 +1606,22 @@ end
|
||||
-- @param #boolean IsNew New
|
||||
-- @param #boolean FromAI From AI
|
||||
-- @param #boolean IsPrio Priority entry
|
||||
-- @param #boolean Tactical Is for tactical info
|
||||
-- @return #AWACS self
|
||||
function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,FromAI,IsPrio)
|
||||
function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,FromAI,IsPrio,Tactical)
|
||||
self:T(self.lid.."_NewRadioEntry")
|
||||
local RadioEntry = {} -- #AWACS.RadioEntry
|
||||
RadioEntry.IsNew = IsNew
|
||||
RadioEntry.TextTTS = TextTTS
|
||||
RadioEntry.TextScreen = TextScreen
|
||||
RadioEntry.TextScreen = TextScreen or TextTTS
|
||||
RadioEntry.GroupID = GID
|
||||
RadioEntry.ToScreen = ToScreen
|
||||
RadioEntry.Duration = STTS.getSpeechTime(TextTTS,0.95,false) or 8
|
||||
RadioEntry.FromAI = FromAI
|
||||
RadioEntry.IsGroup = IsGroup
|
||||
if IsPrio then
|
||||
if Tactical then
|
||||
self.TacticalQueue:Push(RadioEntry)
|
||||
elseif IsPrio then
|
||||
self.PrioRadioQueue:Push(RadioEntry)
|
||||
else
|
||||
self.RadioQueue:Push(RadioEntry)
|
||||
@@ -1618,7 +1801,7 @@ function AWACS:_EventHandler(EventData)
|
||||
if WeaponDesc.category == 1 then
|
||||
Type = "Missile"
|
||||
-- AAM
|
||||
local guidance = WeaponDesc.guidance -- IR=2, Radar Active=3, Radar Semi Active=4, Radar Passive = 5
|
||||
local guidance = WeaponDesc.guidance or 4 -- IR=2, Radar Active=3, Radar Semi Active=4, Radar Passive = 5
|
||||
if guidance == 2 then
|
||||
warndist = 10
|
||||
elseif guidance == 3 then
|
||||
@@ -2689,8 +2872,9 @@ end
|
||||
-- @param #AWACS self
|
||||
-- @param #string Callsign Callsign to address
|
||||
-- @param #number GID GroupID for comms
|
||||
-- @param #boolean Tactical Is for tactical info
|
||||
-- @return #AWACS self
|
||||
function AWACS:_CreateBogeyDope(Callsign,GID)
|
||||
function AWACS:_CreateBogeyDope(Callsign,GID,Tactical)
|
||||
self:T(self.lid.."_CreateBogeyDope for "..Callsign.." GID "..GID)
|
||||
|
||||
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
|
||||
@@ -2716,7 +2900,7 @@ function AWACS:_CreateBogeyDope(Callsign,GID)
|
||||
local tag = contact.TargetGroupNaming
|
||||
local reportingname = contact.ReportingName
|
||||
-- DONE - add tag
|
||||
self:_AnnounceContact(contact,false,group,true,tag,false,reportingname)
|
||||
self:_AnnounceContact(contact,false,group,true,tag,false,reportingname,Tactical)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2841,8 +3025,9 @@ end
|
||||
--- [Internal] AWACS Menu for Bogey Dope
|
||||
-- @param #AWACS self
|
||||
-- @param Wrapper.Group#GROUP Group Group to use
|
||||
-- @param #boolean Tactical Check for tactical info
|
||||
-- @return #AWACS self
|
||||
function AWACS:_BogeyDope(Group)
|
||||
function AWACS:_BogeyDope(Group,Tactical)
|
||||
self:T(self.lid.."_BogeyDope")
|
||||
local text = ""
|
||||
local textScreen = ""
|
||||
@@ -2853,8 +3038,7 @@ function AWACS:_BogeyDope(Group)
|
||||
-- no intel yet!
|
||||
local clean = self.gettext:GetEntry("CLEAN",self.locale)
|
||||
text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
|
||||
self:_NewRadioEntry(text,text,0,false,true,true,false,true)
|
||||
|
||||
self:_NewRadioEntry(text,text,0,false,true,true,false,true,Tactical)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -2896,7 +3080,7 @@ function AWACS:_BogeyDope(Group)
|
||||
local clean = self.gettext:GetEntry("CLEAN",self.locale)
|
||||
text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
|
||||
|
||||
self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true)
|
||||
self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true,Tactical)
|
||||
|
||||
else
|
||||
|
||||
@@ -2915,9 +3099,9 @@ function AWACS:_BogeyDope(Group)
|
||||
textScreen = string.format("%s%d %s.\n",textScreen,contactsAO,groupstxt)
|
||||
end
|
||||
|
||||
self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false,true)
|
||||
self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false,true,Tactical)
|
||||
|
||||
self:_CreateBogeyDope(self:_GetCallSign(Group,GID) or "Ghost 1",GID)
|
||||
self:_CreateBogeyDope(self:_GetCallSign(Group,GID) or "Ghost 1",GID,Tactical)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2925,7 +3109,7 @@ function AWACS:_BogeyDope(Group)
|
||||
-- no, unknown
|
||||
local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
|
||||
text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
|
||||
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
|
||||
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,Tactical)
|
||||
|
||||
end
|
||||
return self
|
||||
@@ -3528,11 +3712,17 @@ function AWACS:_CheckOut(Group,GID,dead)
|
||||
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
|
||||
local Stack = managedgroup.AnchorStackNo
|
||||
local Angels = managedgroup.AnchorStackAngels
|
||||
local GroupName = managedgroup.GroupName
|
||||
-- remove menus
|
||||
if managedgroup.IsPlayer then
|
||||
if self.clientmenus:HasUniqueID(managedgroup.GroupName) then
|
||||
local menus = self.clientmenus:PullByID(managedgroup.GroupName) --#AWACS.MenuStructure
|
||||
if self.clientmenus:HasUniqueID(GroupName) then
|
||||
local menus = self.clientmenus:PullByID(GroupName) --#AWACS.MenuStructure
|
||||
menus.basemenu:Remove()
|
||||
if self.TacticalSubscribers[GroupName] then
|
||||
local Freq = self.TacticalSubscribers[GroupName]
|
||||
self.TacticalFrequencies[Freq] = Freq
|
||||
self.TacticalSubscribers[GroupName] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
-- delete open tasks
|
||||
@@ -3614,6 +3804,22 @@ function AWACS:_SetClientMenus()
|
||||
local friendly = MENU_GROUP_COMMAND:New(cgrp,"Friendly",vid,self._VID,self,cgrp,AWACS.IFF.FRIENDLY)
|
||||
end
|
||||
|
||||
local tactical
|
||||
if self.TacticalMenu then
|
||||
tactical = MENU_GROUP:New(cgrp,"Tactical Radio",basemenu)
|
||||
if self.TacticalSubscribers[cgrpname] then
|
||||
-- unsubscribe
|
||||
local entry = MENU_GROUP_COMMAND:New(cgrp,"Unsubscribe",tactical,self._UnsubScribeTactRadio,self,cgrp)
|
||||
else
|
||||
-- subscribe
|
||||
for _,_freq in UTILS.spairs(self.TacticalFrequencies) do
|
||||
local modu = UTILS.GetModulationName(self.TacticalModulation)
|
||||
local text = string.format("Subscribe to %.3f %s",_freq,modu)
|
||||
local entry = MENU_GROUP_COMMAND:New(cgrp,text,tactical,self._SubScribeTactRadio,self,cgrp,_freq)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local ainfo = MENU_GROUP_COMMAND:New(cgrp,"Awacs Info",basemenu,self._ShowAwacsInfo,self,cgrp)
|
||||
local checkout = MENU_GROUP_COMMAND:New(cgrp,"Check Out",basemenu,self._CheckOut,self,cgrp)
|
||||
|
||||
@@ -3631,6 +3837,7 @@ function AWACS:_SetClientMenus()
|
||||
unable = unable,
|
||||
abort = abort,
|
||||
commit=commit,
|
||||
tactical=tactical,
|
||||
}
|
||||
self.clientmenus:PullByID(cgrpname)
|
||||
self.clientmenus:Push(menus,cgrpname)
|
||||
@@ -4812,8 +5019,9 @@ end
|
||||
-- @param #string Tag Tag name for this contact. Alpha, Brave, Charlie ...
|
||||
-- @param #boolean IsPopup This is a pop-up group
|
||||
-- @param #string ReportingName The NATO code reporting name for the contact, e.g. "Foxbat". "Bogey" if unknown.
|
||||
-- @param #boolean Tactical
|
||||
-- @return #AWACS self
|
||||
function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,ReportingName)
|
||||
function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,ReportingName,Tactical)
|
||||
self:T(self.lid.."_AnnounceContact")
|
||||
-- do we have a group to talk to?
|
||||
local tag = ""
|
||||
@@ -4940,7 +5148,7 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
|
||||
BRAText = string.gsub(BRAText,"BRA","brah")
|
||||
|
||||
local prio = IsNew or IsBogeyDope
|
||||
self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false,prio)
|
||||
self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false,prio,Tactical)
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -5328,6 +5536,15 @@ function AWACS:_MergedCall(GID)
|
||||
local merge = self.gettext:GetEntry("MERGED",self.locale)
|
||||
local text = string.format("%s. %s. %s.",self.callsigntxt,pilotcallsign,merge)
|
||||
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
|
||||
if GID and GID ~= 0 then
|
||||
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
|
||||
if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then
|
||||
local name = managedgroup.GroupName
|
||||
if self.TacticalSubscribers[name] then
|
||||
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true)
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -5703,6 +5920,10 @@ function AWACS:onafterStart(From, Event, To)
|
||||
self:__Started(-5)
|
||||
end
|
||||
|
||||
if self.TacticalMenu then
|
||||
self:__CheckTacticalQueue(55)
|
||||
end
|
||||
|
||||
self:__Status(-30)
|
||||
return self
|
||||
end
|
||||
@@ -5976,6 +6197,8 @@ function AWACS:onafterStatus(From, Event, To)
|
||||
|
||||
self:_CheckMerges()
|
||||
|
||||
self:_CheckSubscribers()
|
||||
|
||||
local outcome, targets = self:_TargetSelectionProcess(true)
|
||||
|
||||
self:_CheckTaskQueue()
|
||||
@@ -6316,6 +6539,77 @@ function AWACS:onafterLostCluster(From,Event,To,Cluster,Mission)
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal] onafterCheckTacticalQueue
|
||||
-- @param #AWACS self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #AWACS self
|
||||
function AWACS:onafterCheckTacticalQueue(From,Event,To)
|
||||
self:T({From, Event, To})
|
||||
-- do we have messages queued?
|
||||
|
||||
if self.clientset:CountAlive() == 0 then
|
||||
self:T(self.lid.."No player connected.")
|
||||
self:__CheckTacticalQueue(-5)
|
||||
return self
|
||||
end
|
||||
|
||||
for _name,_freq in pairs(self.TacticalSubscribers) do
|
||||
local Group = nil
|
||||
if _name then
|
||||
Group = GROUP:FindByName(_name)
|
||||
end
|
||||
if Group and Group:IsAlive() then
|
||||
self:_BogeyDope(Group,true)
|
||||
end
|
||||
end
|
||||
|
||||
if (self.TacticalQueue:IsNotEmpty()) then
|
||||
|
||||
while self.TacticalQueue:Count() > 0 do
|
||||
|
||||
local RadioEntry = self.TacticalQueue:Pull() -- #AWACS.RadioEntry
|
||||
self:T({RadioEntry})
|
||||
local frequency = self.TacticalBaseFreq
|
||||
if RadioEntry.GroupID and RadioEntry.GroupID ~= 0 then
|
||||
local managedgroup = self.ManagedGrps[RadioEntry.GroupID] -- #AWACS.ManagedGroup
|
||||
if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then
|
||||
local name = managedgroup.GroupName
|
||||
frequency = self.TacticalSubscribers[name]
|
||||
end
|
||||
end
|
||||
-- AI AWACS Speaking
|
||||
local gtext = RadioEntry.TextTTS
|
||||
if self.PathToGoogleKey then
|
||||
gtext = string.format("<speak><prosody rate='medium'>%s</prosody></speak>",gtext)
|
||||
end
|
||||
self.TacticalSRSQ:NewTransmission(gtext,nil,self.TacticalSRS,nil,0.5,nil,nil,nil,frequency,self.TacticalModulation,nil,nil,nil,nil,nil)
|
||||
|
||||
self:T(RadioEntry.TextTTS)
|
||||
|
||||
if RadioEntry.ToScreen and RadioEntry.TextScreen and (not self.SuppressScreenOutput) then
|
||||
if RadioEntry.GroupID and RadioEntry.GroupID ~= 0 then
|
||||
local managedgroup = self.ManagedGrps[RadioEntry.GroupID] -- #AWACS.ManagedGroup
|
||||
if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then
|
||||
MESSAGE:New(RadioEntry.TextScreen,20,"AWACS"):ToGroup(managedgroup.Group)
|
||||
self:T(RadioEntry.TextScreen)
|
||||
end
|
||||
else
|
||||
MESSAGE:New(RadioEntry.TextScreen,20,"AWACS"):ToCoalition(self.coalition)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end -- end while
|
||||
|
||||
if self:Is("Running") then
|
||||
self:__CheckTacticalQueue(-self.TacticalInterval)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- [Internal] onafterCheckRadioQueue
|
||||
-- @param #AWACS self
|
||||
-- @param #string From
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
-- You need to load an .ogg soundfile for the pilot\'s beacons into the mission, e.g. "beacon.ogg", use a once trigger, "sound to country" for that.
|
||||
-- Create a late-activated single infantry unit as template in the mission editor and name it e.g. "Downed Pilot".
|
||||
--
|
||||
-- Example sound files are here: [Moose Sound](https://github.com/FlightControl-Master/MOOSE_SOUND/tree/master/CTLD%20CSAR)
|
||||
--
|
||||
-- ## 1. Basic Setup
|
||||
--
|
||||
-- A basic setup example is the following:
|
||||
|
||||
@@ -616,6 +616,8 @@ do
|
||||
-- You need to load an .ogg soundfile for the pilot\'s beacons into the mission, e.g. "beacon.ogg", use a once trigger, "sound to country" for that.
|
||||
-- Create the late-activated troops, vehicles, that will make up your deployable forces.
|
||||
--
|
||||
-- Example sound files are here: [Moose Sound](https://github.com/FlightControl-Master/MOOSE_SOUND/tree/master/CTLD%20CSAR)
|
||||
--
|
||||
-- ## 1. Basic Setup
|
||||
--
|
||||
-- ## 1.1 Create and start a CTLD instance
|
||||
|
||||
@@ -1485,6 +1485,17 @@ function CHIEF:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
|
||||
return zone
|
||||
end
|
||||
|
||||
--- Remove a GCI CAP
|
||||
-- @param #CHIEF self
|
||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||
function CHIEF:RemoveGciCapZone(Zone)
|
||||
|
||||
-- Hand over to commander.
|
||||
local zone=self.commander:RemoveGciCapZone(Zone)
|
||||
|
||||
return zone
|
||||
end
|
||||
|
||||
--- Add an AWACS zone.
|
||||
-- @param #CHIEF self
|
||||
-- @param Core.Zone#ZONE Zone Zone.
|
||||
@@ -1501,6 +1512,17 @@ function CHIEF:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
|
||||
return zone
|
||||
end
|
||||
|
||||
--- Remove a AWACS zone.
|
||||
-- @param #CHIEF self
|
||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||
function CHIEF:RemoveAwacsZone(Zone)
|
||||
|
||||
-- Hand over to commander.
|
||||
local zone=self.commander:RemoveAwacsZone(Zone)
|
||||
|
||||
return zone
|
||||
end
|
||||
|
||||
--- Add a refuelling tanker zone.
|
||||
-- @param #CHIEF self
|
||||
-- @param Core.Zone#ZONE Zone Zone.
|
||||
@@ -1518,6 +1540,16 @@ function CHIEF:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSystem)
|
||||
return zone
|
||||
end
|
||||
|
||||
--- Remove a refuelling tanker zone.
|
||||
-- @param #CHIEF self
|
||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||
function CHIEF:RemoveTankerZone(Zone)
|
||||
|
||||
-- Hand over to commander.
|
||||
local zone=self.commander:RemoveTankerZone(Zone)
|
||||
|
||||
return zone
|
||||
end
|
||||
|
||||
--- Set border zone set, defining your territory.
|
||||
--
|
||||
|
||||
@@ -75,7 +75,7 @@ COHORT = {
|
||||
livery = nil,
|
||||
skill = nil,
|
||||
legion = nil,
|
||||
Ngroups = nil,
|
||||
--Ngroups = nil,
|
||||
Ngroups = 0,
|
||||
engageRange = nil,
|
||||
tacanChannel = {},
|
||||
@@ -1098,7 +1098,7 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
|
||||
-- Assets on mission NOTHING are considered.
|
||||
table.insert(assets, asset)
|
||||
|
||||
elseif self.legion:IsAssetOnMission(asset, AUFTRAG.Type.GCICAP) and MissionType==AUFTRAG.Type.INTERCEPT then
|
||||
elseif self.legion:IsAssetOnMission(asset, {AUFTRAG.Type.GCICAP, AUFTRAG.Type.PATROLRACETRACK}) and MissionType==AUFTRAG.Type.INTERCEPT then
|
||||
|
||||
-- Check if the payload of this asset is compatible with the mission.
|
||||
-- Note: we do not check the payload as an asset that is on a GCICAP mission should be able to do an INTERCEPT as well!
|
||||
@@ -1595,4 +1595,3 @@ end
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -710,6 +710,26 @@ function COMMANDER:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
|
||||
return patrolzone
|
||||
end
|
||||
|
||||
--- Remove a GCI CAP.
|
||||
-- @param #COMMANDER self
|
||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||
function COMMANDER:RemoveGciCapZone(Zone)
|
||||
|
||||
local patrolzone={} --Ops.AirWing#AIRWING.PatrolZone
|
||||
|
||||
patrolzone.zone=Zone
|
||||
for i,_patrolzone in pairs(self.gcicapZones) do
|
||||
if _patrolzone.zone == patrolzone.zone then
|
||||
if _patrolzone.mission and _patrolzone.mission:IsNotOver() then
|
||||
_patrolzone.mission:Cancel()
|
||||
end
|
||||
table.remove(self.gcicapZones, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
return patrolzone
|
||||
end
|
||||
|
||||
--- Add an AWACS zone.
|
||||
-- @param #COMMANDER self
|
||||
-- @param Core.Zone#ZONE Zone Zone.
|
||||
@@ -735,6 +755,26 @@ function COMMANDER:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
|
||||
return awacszone
|
||||
end
|
||||
|
||||
--- Remove a AWACS zone.
|
||||
-- @param #COMMANDER self
|
||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||
function COMMANDER:RemoveAwacsZone(Zone)
|
||||
|
||||
local awacszone={} --Ops.AirWing#AIRWING.PatrolZone
|
||||
|
||||
awacszone.zone=Zone
|
||||
for i,_awacszone in pairs(self.awacsZones) do
|
||||
if _awacszone.zone == awacszone.zone then
|
||||
if _awacszone.mission and _awacszone.mission:IsNotOver() then
|
||||
_awacszone.mission:Cancel()
|
||||
end
|
||||
table.remove(self.awacsZones, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
return awacszone
|
||||
end
|
||||
|
||||
--- Add a refuelling tanker zone.
|
||||
-- @param #COMMANDER self
|
||||
-- @param Core.Zone#ZONE Zone Zone.
|
||||
@@ -762,6 +802,26 @@ function COMMANDER:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSyst
|
||||
return tankerzone
|
||||
end
|
||||
|
||||
--- Remove a refuelling tanker zone.
|
||||
-- @param #COMMANDER self
|
||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||
function COMMANDER:RemoveTankerZone(Zone)
|
||||
|
||||
local tankerzone={} --Ops.AirWing#AIRWING.PatrolZone
|
||||
|
||||
tankerzone.zone=Zone
|
||||
for i,_tankerzone in pairs(self.tankerZones) do
|
||||
if _tankerzone.zone == tankerzone.zone then
|
||||
if _tankerzone.mission and _tankerzone.mission:IsNotOver() then
|
||||
_tankerzone.mission:Cancel()
|
||||
end
|
||||
table.remove(self.tankerZones, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
return tankerzone
|
||||
end
|
||||
|
||||
--- Check if this mission is already in the queue.
|
||||
-- @param #COMMANDER self
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
@@ -1747,7 +1807,7 @@ function COMMANDER:RecruitAssetsForEscort(Mission, Assets)
|
||||
local Cohorts=self:_GetCohorts(Mission.escortLegions, Mission.escortCohorts, Mission.operation)
|
||||
|
||||
-- Call LEGION function but provide COMMANDER as self.
|
||||
local assigned=LEGION.AssignAssetsForEscort(self, Cohorts, Assets, Mission.NescortMin, Mission.NescortMax, Mission.escortTargetTypes, Mission.escortEngageRange)
|
||||
local assigned=LEGION.AssignAssetsForEscort(self, Cohorts, Assets, Mission.NescortMin, Mission.NescortMax, Mission.escortMissionType, Mission.escortTargetTypes, Mission.escortEngageRange)
|
||||
|
||||
return assigned
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
--
|
||||
-- * Manage aircraft departure and arrival
|
||||
-- * Handles AI and human players
|
||||
-- * Limit number of AI groups taxiing, taking off and landing simultaniously
|
||||
-- * Limit number of AI groups taxiing, taking off and landing simultaneously
|
||||
-- * Immersive voice overs via SRS text-to-speech
|
||||
-- * Define holding patterns for airdromes
|
||||
--
|
||||
@@ -61,6 +61,7 @@
|
||||
-- @field #number runwaydestroyed Time stamp (abs), when runway was destroyed. If `nil`, runway is operational.
|
||||
-- @field #number runwayrepairtime Time in seconds until runway will be repaired after it was destroyed. Default is 3600 sec (one hour).
|
||||
-- @field #boolean markerParking If `true`, occupied parking spots are marked.
|
||||
-- @field #boolean nosubs If `true`, SRS TTS is without subtitles.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- **Ground Control**: Airliner X, Good news, you are clear to taxi to the active.
|
||||
@@ -122,7 +123,7 @@
|
||||
-- * `Length` is the length of the pattern.
|
||||
-- * `FlightLevelMin` is the lowest altitude at which aircraft can hold.
|
||||
-- * `FlightLevelMax` is the highest altitude at which aircraft can hold.
|
||||
-- * `Prio` is the priority of this holdig stacks. If multiple patterns are defined, patterns with higher prio will be filled first.
|
||||
-- * `Prio` is the priority of this holding stacks. If multiple patterns are defined, patterns with higher prio will be filled first.
|
||||
--
|
||||
-- # Parking Guard
|
||||
--
|
||||
@@ -137,13 +138,13 @@
|
||||
--
|
||||
-- # Limits for Inbound and Outbound Flights
|
||||
--
|
||||
-- You can define limits on how many aircraft are simultaniously landing and taking off. This avoids (DCS) problems where taxiing aircraft cause a "traffic jam" on the taxi way(s)
|
||||
-- You can define limits on how many aircraft are simultaneously landing and taking off. This avoids (DCS) problems where taxiing aircraft cause a "traffic jam" on the taxi way(s)
|
||||
-- and bring the whole airbase effectively to a stand still.
|
||||
--
|
||||
-- ## Landing Limits
|
||||
--
|
||||
-- The number of groups getting landing clearance can be set with the @{#FLIGHTCONTROL.SetLimitLanding}(*Nlanding, Ntakeoff*) function.
|
||||
-- The first parameter, `Nlanding`, defines how many groups get clearance simultaniously.
|
||||
-- The first parameter, `Nlanding`, defines how many groups get clearance simultaneously.
|
||||
--
|
||||
-- The second parameter, `Ntakeoff`, sets a limit on how many flights can take off whilst inbound flights still get clearance. By default, this is set to zero because the runway can only be used for takeoff *or*
|
||||
-- landing. So if you have a flight taking off, inbound fights will have to wait until the runway is clear.
|
||||
@@ -155,7 +156,7 @@
|
||||
-- ## Taxiing/Takeoff Limits
|
||||
--
|
||||
-- The number of AI flight groups getting clearance to taxi to the runway can be set with the @{#FLIGHTCONTROL.SetLimitTaxi}(*Nlanding, Ntakeoff*) function.
|
||||
-- The first parameter, `Ntaxi`, defines how many groups are allowed to taxi to the runway simultaniously. Note that once the AI starts to taxi, we loose complete control over it.
|
||||
-- The first parameter, `Ntaxi`, defines how many groups are allowed to taxi to the runway simultaneously. Note that once the AI starts to taxi, we loose complete control over it.
|
||||
-- They will follow their internal logic to get the the runway and take off. Therefore, giving clearance to taxi is equivalent to giving them clearance for takeoff.
|
||||
--
|
||||
-- By default, the parameter only counts the number of flights taxiing *to* the runway. If you set the second parameter, `IncludeInbound`, to `true`, this will also count the flights
|
||||
@@ -237,9 +238,9 @@
|
||||
-- atcNellis:SetParkingGuardStatic("Static Generator F Template")
|
||||
-- -- Set taxi speed limit to 25 knots.
|
||||
-- atcNellis:SetSpeedLimitTaxi(25)
|
||||
-- -- Set that max 3 groups are allowed to taxi simultaniously.
|
||||
-- -- Set that max 3 groups are allowed to taxi simultaneously.
|
||||
-- atcNellis:SetLimitTaxi(3, false, 1)
|
||||
-- -- Set that max 2 groups are allowd to land simultaniously and unlimited number (99) groups can land, while other groups are taking off.
|
||||
-- -- Set that max 2 groups are allowd to land simultaneously and unlimited number (99) groups can land, while other groups are taking off.
|
||||
-- atcNellis:SetLimitLanding(2, 99)
|
||||
-- -- Use Google for text-to-speech.
|
||||
-- atcNellis:SetSRSTower(nil, nil, "en-AU-Standard-A", nil, nil, "D:\\Path To Google\\GoogleCredentials.json")
|
||||
@@ -270,6 +271,7 @@ FLIGHTCONTROL = {
|
||||
Nparkingspots = nil,
|
||||
holdingpatterns = {},
|
||||
hpcounter = 0,
|
||||
nosubs = false,
|
||||
}
|
||||
|
||||
--- Holding point. Contains holding stacks.
|
||||
@@ -327,7 +329,7 @@ FLIGHTCONTROL.FlightStatus={
|
||||
|
||||
--- FlightControl class version.
|
||||
-- @field #string version
|
||||
FLIGHTCONTROL.version="0.7.3"
|
||||
FLIGHTCONTROL.version="0.7.4"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -407,6 +409,7 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS, Port,
|
||||
self:SetFrequency(Frequency, Modulation)
|
||||
self:SetMarkHoldingPattern(true)
|
||||
self:SetRunwayRepairtime()
|
||||
self.nosubs = false
|
||||
|
||||
-- Set SRS Port
|
||||
self:SetSRSPort(Port or 5002)
|
||||
@@ -556,6 +559,22 @@ function FLIGHTCONTROL:SetVerbosity(VerbosityLevel)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set subtitles to appear on SRS TTS messages.
|
||||
-- @param #FLIGHTCONTROL self
|
||||
-- @return #FLIGHTCONTROL self
|
||||
function FLIGHTCONTROL:SwitchSubtitlesOn()
|
||||
self.nosubs = false
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set subtitles to appear on SRS TTS messages.
|
||||
-- @param #FLIGHTCONTROL self
|
||||
-- @return #FLIGHTCONTROL self
|
||||
function FLIGHTCONTROL:SwitchSubtitlesOff()
|
||||
self.nosubs = true
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the tower frequency.
|
||||
-- @param #FLIGHTCONTROL self
|
||||
-- @param #number Frequency Frequency in MHz. Default 305 MHz.
|
||||
@@ -595,7 +614,7 @@ end
|
||||
-- @param #string Culture Culture, e.g. "en-GB" (default).
|
||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
||||
-- @param #number Volume Volume. Default 1.0.
|
||||
-- @param #string Label Name under which SRS transmitts.
|
||||
-- @param #string Label Name under which SRS transmits.
|
||||
-- @param #string PathToGoogleCredentials Path to google credentials json file.
|
||||
-- @param #number Port Server port for SRS
|
||||
-- @return #FLIGHTCONTROL self
|
||||
@@ -626,7 +645,7 @@ end
|
||||
-- @param #string Culture Culture, e.g. "en-GB" (default).
|
||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`. See [Google Voices](https://cloud.google.com/text-to-speech/docs/voices).
|
||||
-- @param #number Volume Volume. Default 1.0.
|
||||
-- @param #string Label Name under which SRS transmitts. Default `self.alias`.
|
||||
-- @param #string Label Name under which SRS transmits. Default `self.alias`.
|
||||
-- @param #string PathToGoogleCredentials Path to google credentials json file.
|
||||
-- @return #FLIGHTCONTROL self
|
||||
function FLIGHTCONTROL:SetSRSTower(Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials)
|
||||
@@ -644,7 +663,7 @@ end
|
||||
-- @param #string Culture Culture, e.g. "en-US" (default).
|
||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
||||
-- @param #number Volume Volume. Default 1.0.
|
||||
-- @param #string Label Name under which SRS transmitts. Default "Pilot".
|
||||
-- @param #string Label Name under which SRS transmits. Default "Pilot".
|
||||
-- @param #string PathToGoogleCredentials Path to google credentials json file.
|
||||
-- @return #FLIGHTCONTROL self
|
||||
function FLIGHTCONTROL:SetSRSPilot(Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials)
|
||||
@@ -657,17 +676,17 @@ function FLIGHTCONTROL:SetSRSPilot(Gender, Culture, Voice, Volume, Label, PathTo
|
||||
end
|
||||
|
||||
|
||||
--- Set the number of aircraft groups, that are allowed to land simultaniously.
|
||||
--- Set the number of aircraft groups, that are allowed to land simultaneously.
|
||||
-- Note that this restricts AI and human players.
|
||||
--
|
||||
-- By default, up to two groups get landing clearance. They are spaced out in time, i.e. after the first one got cleared, the second has to wait a bit.
|
||||
-- This
|
||||
--
|
||||
-- By default, landing clearance is only given when **no** other flight is taking off. You can adjust this for airports with more than one runway or
|
||||
-- in cases where simulatious takeoffs and landings are unproblematic. Note that only because there are multiple runways, it does not mean the AI uses them.
|
||||
-- in cases where simultaneous takeoffs and landings are unproblematic. Note that only because there are multiple runways, it does not mean the AI uses them.
|
||||
--
|
||||
-- @param #FLIGHTCONTROL self
|
||||
-- @param #number Nlanding Max number of aircraft landing simultaniously. Default 2.
|
||||
-- @param #number Nlanding Max number of aircraft landing simultaneously. Default 2.
|
||||
-- @param #number Ntakeoff Allowed number of aircraft taking off for groups to get landing clearance. Default 0.
|
||||
-- @return #FLIGHTCONTROL self
|
||||
function FLIGHTCONTROL:SetLimitLanding(Nlanding, Ntakeoff)
|
||||
@@ -691,7 +710,7 @@ function FLIGHTCONTROL:SetLandingInterval(dt)
|
||||
end
|
||||
|
||||
|
||||
--- Set the number of **AI** aircraft groups, that are allowed to taxi simultaniously.
|
||||
--- Set the number of **AI** aircraft groups, that are allowed to taxi simultaneously.
|
||||
-- If the limit is reached, other AI groups not get taxi clearance to taxi to the runway.
|
||||
--
|
||||
-- By default, this only counts the number of AI that taxi from their parking position to the runway.
|
||||
@@ -887,7 +906,7 @@ end
|
||||
-- Note that this is the time, the DCS engine uses not something we can control on a user level or we could get via scripting.
|
||||
-- You need to input the value. On the DCS forum it was stated that this is currently one hour. Hence this is the default value.
|
||||
-- @param #FLIGHTCONTROL self
|
||||
-- @param #number RepairTime Time in seconds until the runway is repaired. Default 3600 sec (one hour).
|
||||
-- @param #number RepairTime Time in seconds until the runway is repaired. Default 3600sec (one hour).
|
||||
-- @return #FLIGHTCONTROL self
|
||||
function FLIGHTCONTROL:SetRunwayRepairtime(RepairTime)
|
||||
self.runwayrepairtime=RepairTime or 3600
|
||||
@@ -1010,7 +1029,7 @@ function FLIGHTCONTROL:onbeforeStatusUpdate()
|
||||
if Tqueue>0 then
|
||||
-- Debug info.
|
||||
local text=string.format("Still got %d messages in the radio queue. Will call status again in %.1f sec", #self.msrsqueue, Tqueue)
|
||||
self:I(self.lid..text)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Call status again in dt seconds.
|
||||
self:__StatusUpdate(-Tqueue)
|
||||
@@ -2753,9 +2772,10 @@ function FLIGHTCONTROL:_PlayerInfoATIS(groupname)
|
||||
if flight then
|
||||
|
||||
local text=string.format("Airbase %s ATIS:", self.airbasename)
|
||||
|
||||
local srstxt = string.format("Airbase %s ", self.airbasename)
|
||||
if self.atis then
|
||||
text=text..string.format("\nATIS %.3f MHz %s", self.atis.frequency, UTILS.GetModulationName(self.atis.modulation))
|
||||
srstxt=srstxt..string.format("ATIS %.3f Megahertz %s", self.atis.frequency, UTILS.GetModulationName(self.atis.modulation))
|
||||
if self.atis.towerfrequency then
|
||||
local tower=""
|
||||
for _,freq in pairs(self.atis.towerfrequency) do
|
||||
@@ -2779,7 +2799,17 @@ function FLIGHTCONTROL:_PlayerInfoATIS(groupname)
|
||||
end
|
||||
|
||||
-- Message to flight
|
||||
self:TextMessageToFlight(text, flight, 10, true)
|
||||
|
||||
--self:TextMessageToFlight(text, flight, 10, true)
|
||||
-- Call sign.
|
||||
local callsign=self:_GetCallsignName(flight)
|
||||
|
||||
-- Pilot calls inbound for landing.
|
||||
local rtext=string.format("%s, %s, request ATIS frequency.", self.alias, callsign)
|
||||
|
||||
-- Radio message.
|
||||
self:TransmissionPilot(rtext, flight)
|
||||
self:TransmissionTower(srstxt,flight,10)
|
||||
|
||||
else
|
||||
self:E(self.lid..string.format("Cannot find flight group %s.", tostring(groupname)))
|
||||
@@ -3390,7 +3420,7 @@ function FLIGHTCONTROL:_PlayerRequestDirectLanding(groupname)
|
||||
if nTakeoff>self.NlandingTakeoff then
|
||||
|
||||
-- Message text.
|
||||
local text=string.format("%s, negative! We have currently traffic taking off", callsign)
|
||||
local text=string.format("%s, negative! We have currently traffic taking off!", callsign)
|
||||
|
||||
-- Send message.
|
||||
self:TransmissionTower(text, flight, 10)
|
||||
@@ -3854,7 +3884,7 @@ function FLIGHTCONTROL:_PlayerArrived(groupname)
|
||||
else
|
||||
|
||||
-- Message text.
|
||||
local text=string.format("%s, %s, arrived at parking position", self.alias, callsign)
|
||||
local text=string.format("%s, %s, arrived at parking position.", self.alias, callsign)
|
||||
|
||||
-- Transmit message.
|
||||
self:TransmissionPilot(text, flight)
|
||||
@@ -4277,7 +4307,7 @@ function FLIGHTCONTROL:TransmissionTower(Text, Flight, Delay)
|
||||
local subgroups=nil
|
||||
if Flight and not Flight.isAI then
|
||||
local playerData=Flight:_GetPlayerData()
|
||||
if playerData.subtitles then
|
||||
if playerData.subtitles and (not self.nosubs) then
|
||||
subgroups=subgroups or {}
|
||||
table.insert(subgroups, Flight.group)
|
||||
end
|
||||
@@ -4324,7 +4354,7 @@ function FLIGHTCONTROL:TransmissionPilot(Text, Flight, Delay)
|
||||
local subgroups=nil
|
||||
if Flight and not Flight.isAI then
|
||||
local playerData=Flight:_GetPlayerData()
|
||||
if playerData.subtitles then
|
||||
if playerData.subtitles and (not self.nosubs) then
|
||||
subgroups=subgroups or {}
|
||||
table.insert(subgroups, Flight.group)
|
||||
end
|
||||
|
||||
@@ -325,7 +325,322 @@ function FLIGHTGROUP:New(group)
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
-- TODO: Add pseudo functions.
|
||||
--- FSM Function OnAfterElementSpawned.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementSpawned
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
|
||||
--- FSM Function OnAfterElementParking.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementParking
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
-- @param Wrapper.Airbase#AIRBASE.ParkingSpot Spot Parking Spot.
|
||||
|
||||
--- FSM Function OnAfterElementEngineOn.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementEngineOn
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
|
||||
--- FSM Function OnAfterElementTaxiing.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementTaxiing
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
|
||||
--- FSM Function OnAfterElementTakeoff.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementTakeoff
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil.
|
||||
|
||||
--- FSM Function OnAfterElementAirborne.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementAirborne
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
|
||||
--- FSM Function OnAfterElementLanded.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementLanded
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil.
|
||||
|
||||
--- FSM Function OnAfterElementArrived.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementArrived
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase, where the element arrived.
|
||||
-- @param Wrapper.Airbase#AIRBASE.ParkingSpot Parking The Parking spot the element has.
|
||||
|
||||
--- FSM Function OnAfterElementDestroyed.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementDestroyed
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
|
||||
--- FSM Function OnAfterElementDead.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterElementDead
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element.
|
||||
|
||||
--- FSM Function OnAfterSpawned.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterSpawned
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterParking.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterParking
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterTaxiing.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterTaxiing
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterTakeoff.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterTakeoff
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterAirborne.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterAirborne
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterCruise.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterCruise
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterLanding.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterLanding
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterLanded.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterLanded
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase the flight landed.
|
||||
|
||||
--- FSM Function OnAfterLandedAt.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterLandedAt
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterArrived.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterArrived
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterDead.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterDead
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterUpdateRoute.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterUpdateRoute
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number n Next waypoint index. Default is the one coming after that one that has been passed last.
|
||||
-- @param #number N Waypoint Max waypoint index to be included in the route. Default is the final waypoint.
|
||||
|
||||
--- FSM Function OnAfterOutOfMissilesAA.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterOutOfMissilesAA
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterOutOfMissilesAG.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterOutOfMissilesAG
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterRTB.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterRTB
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to hold at.
|
||||
-- @param #number SpeedTo Speed used for traveling from current position to holding point in knots. Default 75% of max speed.
|
||||
-- @param #number SpeedHold Holding speed in knots. Default 250 kts.
|
||||
-- @param #number SpeedLand Landing speed in knots. Default 170 kts.
|
||||
|
||||
--- FSM Function OnAfterLandAtAirbase.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterLandAtAirbase
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to hold at.
|
||||
|
||||
--- FSM Function OnAfterWait.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterWait
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number Duration Duration how long the group will be waiting in seconds. Default `nil` (=forever).
|
||||
-- @param #number Altitude Altitude in feet. Default 10,000 ft for airplanes and 1,000 feet for helos.
|
||||
-- @param #number Speed Speed in knots. Default 250 kts for airplanes and 20 kts for helos.
|
||||
|
||||
--- FSM Function OnAfterRefuel.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterRefuel
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Point#COORDINATE Coordinate The coordinate.
|
||||
|
||||
--- FSM Function OnAfterRefueled.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterRefueled
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterDisengage.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterDisengage
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Set#SET_UNIT TargetUnitSet
|
||||
|
||||
--- FSM Function OnAfterEngageTarget.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterEngageTarget
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #table Target Target object. Can be a UNIT, STATIC, GROUP, SET_UNIT or SET_GROUP object.
|
||||
|
||||
--- FSM Function OnAfterLandAt.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterLandAt
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Set#SET_UNIT TargetUnitSet
|
||||
|
||||
--- FSM Function OnAfterFuelLow.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterFuelLow
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnAfterFuelCritical.
|
||||
-- @function [parent=#FLIGHTGROUP] OnAfterFuelCritical
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
|
||||
--- FSM Function OnBeforeUpdateRoute.
|
||||
-- @function [parent=#FLIGHTGROUP] OnBeforeUpdateRoute
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number n Next waypoint index. Default is the one coming after that one that has been passed last.
|
||||
-- @param #number N Waypoint Max waypoint index to be included in the route. Default is the final waypoint.
|
||||
-- @return #boolean Transision allowed?
|
||||
|
||||
--- FSM Function OnBeforeRTB.
|
||||
-- @function [parent=#FLIGHTGROUP] OnBeforeRTB
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to hold at.
|
||||
-- @param #number SpeedTo Speed used for travelling from current position to holding point in knots.
|
||||
-- @param #number SpeedHold Holding speed in knots.
|
||||
|
||||
--- FSM Function OnBeforeLandAtAirbase.
|
||||
-- @function [parent=#FLIGHTGROUP] OnBeforeLandAtAirbase
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to hold at.
|
||||
|
||||
--- FSM Function OnBeforeWait.
|
||||
-- @function [parent=#FLIGHTGROUP] OnBeforeWait
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number Duration Duration how long the group will be waiting in seconds. Default `nil` (=forever).
|
||||
-- @param #number Altitude Altitude in feet. Default 10,000 ft for airplanes and 1,000 feet for helos.
|
||||
-- @param #number Speed Speed in knots. Default 250 kts for airplanes and 20 kts for helos.
|
||||
|
||||
--- FSM Function OnBeforeLandAt.
|
||||
-- @function [parent=#FLIGHTGROUP] OnBeforeLandAt
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Point#COORDINATE Coordinate The coordinate where to land. Default is current position.
|
||||
-- @param #number Duration The duration in seconds to remain on ground. Default 600 sec (10 min).
|
||||
|
||||
-- TODO: Add pseudo functions ? Normally done, but should be double check
|
||||
|
||||
-- Handle events:
|
||||
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
||||
@@ -2290,6 +2605,9 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n, N)
|
||||
elseif task.dcstask.id==AUFTRAG.SpecialTask.RECON then
|
||||
-- For recon missions, we need to allow the update as we insert new waypoints.
|
||||
self:T2(self.lid.."Allowing update route for Task: ReconMission")
|
||||
elseif task.dcstask.id==AUFTRAG.SpecialTask.PATROLRACETRACK then
|
||||
-- For recon missions, we need to allow the update as we insert new waypoints.
|
||||
self:T2(self.lid.."Allowing update route for Task: Patrol Race Track")
|
||||
elseif task.dcstask.id==AUFTRAG.SpecialTask.HOVER then
|
||||
-- For recon missions, we need to allow the update as we insert new waypoints.
|
||||
self:T2(self.lid.."Allowing update route for Task: Hover")
|
||||
@@ -4206,11 +4524,13 @@ function FLIGHTGROUP:GetClosestAirbase()
|
||||
|
||||
local coord=group:GetCoordinate()
|
||||
local coalition=self:GetCoalition()
|
||||
|
||||
local airbase=coord:GetClosestAirbase() --(nil, coalition)
|
||||
|
||||
return airbase
|
||||
|
||||
|
||||
if coord then
|
||||
local airbase=coord:GetClosestAirbase() --(nil, coalition)
|
||||
return airbase
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
|
||||
return nil
|
||||
|
||||
@@ -45,9 +45,14 @@ LEGION = {
|
||||
cohorts = {},
|
||||
}
|
||||
|
||||
--- Random score that is added to the asset score in the selection process.
|
||||
-- @field #number RandomAssetScore
|
||||
LEGION.RandomAssetScore=1
|
||||
|
||||
|
||||
--- LEGION class version.
|
||||
-- @field #string version
|
||||
LEGION.version="0.4.0"
|
||||
LEGION.version="0.5.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
@@ -960,7 +965,7 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission, Assets)
|
||||
local pause=false
|
||||
|
||||
-- Check if mission is INTERCEPT and asset is currently on GCI mission. If so, GCI is paused.
|
||||
if currM.type==AUFTRAG.Type.GCICAP and Mission.type==AUFTRAG.Type.INTERCEPT then
|
||||
if (currM.type==AUFTRAG.Type.GCICAP or currM.type==AUFTRAG.Type.PATROLRACETRACK) and Mission.type==AUFTRAG.Type.INTERCEPT then
|
||||
pause=true
|
||||
elseif (currM.type==AUFTRAG.Type.ONGUARD or currM.type==AUFTRAG.Type.PATROLZONE) and (Mission.type==AUFTRAG.Type.ARTY or Mission.type==AUFTRAG.Type.GROUNDATTACK) then
|
||||
pause=true
|
||||
@@ -1440,7 +1445,7 @@ end
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
|
||||
function LEGION:onafterLegionAssetReturned(From, Event, To, Cohort, Asset)
|
||||
-- Debug message.
|
||||
self:I(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
|
||||
self:T(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
|
||||
|
||||
-- Stop flightgroup.
|
||||
if Asset.flightgroup and not Asset.flightgroup:IsStopped() then
|
||||
@@ -2552,9 +2557,10 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
|
||||
|
||||
-- Distance to target.
|
||||
local TargetDistance=TargetVec2 and UTILS.VecDist2D(TargetVec2, cohort.legion:GetVec2()) or 0
|
||||
|
||||
|
||||
-- Is in range?
|
||||
local Rmax=cohort:GetMissionRange(WeaponTypes)
|
||||
local RangeMax = RangeMax or 0
|
||||
local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance
|
||||
|
||||
return InRange
|
||||
@@ -2605,6 +2611,7 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
|
||||
-- Is capable of the mission type?
|
||||
local can=AUFTRAG.CheckMissionCapability(MissionType, Cohort.missiontypes)
|
||||
|
||||
|
||||
if can then
|
||||
can=CheckCategory(Cohort)
|
||||
else
|
||||
@@ -2682,7 +2689,7 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Recruit assets from Cohorts for the given parameters. **NOTE** that we set the `asset.isReserved=true` flag so it cant be recruited by anyone else.
|
||||
--- Recruit assets from Cohorts for the given parameters. **NOTE** that we set the `asset.isReserved=true` flag so it cannot be recruited by anyone else.
|
||||
-- @param #table Cohorts Cohorts included.
|
||||
-- @param #string MissionTypeRecruit Mission type for recruiting the cohort assets.
|
||||
-- @param #string MissionTypeOpt Mission type for which the assets are optimized. Default is the same as `MissionTypeRecruit`.
|
||||
@@ -3176,7 +3183,7 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu
|
||||
if currmission.type==AUFTRAG.Type.ALERT5 and currmission.alert5MissionType==MissionType then
|
||||
-- Prefer assets that are on ALERT5 for this mission type.
|
||||
score=score+25
|
||||
elseif currmission.type==AUFTRAG.Type.GCICAP and MissionType==AUFTRAG.Type.INTERCEPT then
|
||||
elseif (currmission.type==AUFTRAG.Type.GCICAP or currmission.type==AUFTRAG.Type.PATROLRACETRACK) and MissionType==AUFTRAG.Type.INTERCEPT then
|
||||
-- Prefer assets that are on GCICAP to perform INTERCEPTS. We set this even higher than alert5 because they are already in the air.
|
||||
score=score+35
|
||||
elseif (currmission.type==AUFTRAG.Type.ONGUARD or currmission.type==AUFTRAG.Type.PATROLZONE) and (MissionType==AUFTRAG.Type.ARTY or MissionType==AUFTRAG.Type.GROUNDATTACK) then
|
||||
@@ -3229,7 +3236,25 @@ function LEGION._OptimizeAssetSelection(assets, MissionType, TargetVec2, Include
|
||||
-- Calculate the mission score of all assets.
|
||||
for _,_asset in pairs(assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
-- Calculate the asset score.
|
||||
asset.score=LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload)
|
||||
|
||||
if IncludePayload then
|
||||
|
||||
-- Max random asset score.
|
||||
local RandomScoreMax=asset.legion and asset.legion.RandomAssetScore or LEGION.RandomAssetScore
|
||||
|
||||
-- Random score.
|
||||
local RandomScore=math.random(0, RandomScoreMax)
|
||||
|
||||
-- Debug info.
|
||||
--env.info(string.format("Asset %s: randomscore=%d, max=%d", asset.spawngroupname, RandomScore, RandomScoreMax))
|
||||
|
||||
-- Add a bit of randomness.
|
||||
asset.score=asset.score+RandomScore
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--- Sort assets wrt to their mission score. Higher is better.
|
||||
@@ -3246,7 +3271,7 @@ function LEGION._OptimizeAssetSelection(assets, MissionType, TargetVec2, Include
|
||||
local text=string.format("Optimized %d assets for %s mission/transport (payload=%s):", #assets, MissionType, tostring(IncludePayload))
|
||||
for i,Asset in pairs(assets) do
|
||||
local asset=Asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
text=text..string.format("\n%s %s: score=%d", asset.squadname, asset.spawngroupname, asset.score or -1)
|
||||
text=text..string.format("\n%d. %s [%s]: score=%d", i, asset.spawngroupname, asset.squadname, asset.score or -1)
|
||||
asset.score=nil
|
||||
end
|
||||
env.info(text)
|
||||
|
||||
@@ -90,7 +90,7 @@ NAVYGROUP = {
|
||||
|
||||
--- NavyGroup version.
|
||||
-- @field #string version
|
||||
NAVYGROUP.version="1.0.1"
|
||||
NAVYGROUP.version="1.0.2"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -586,7 +586,7 @@ end
|
||||
-- @param #string stoptime Stop time, e.g. "9:00" for nine o'clock. Default 90 minutes after start time.
|
||||
-- @param #number speed Wind speed on deck in knots during turn into wind leg. Default 20 knots.
|
||||
-- @param #boolean uturn If `true` (or `nil`), carrier wil perform a U-turn and go back to where it came from before resuming its route to the next waypoint. If false, it will go directly to the next waypoint.
|
||||
-- @param #number offset Offset angle in degrees, e.g. to account for an angled runway. Default 0 deg.
|
||||
-- @param #number offset Offset angle clock-wise in degrees, *e.g.* to account for an angled runway. Default 0 deg. Use around -9.1° for US carriers.
|
||||
-- @return #NAVYGROUP.IntoWind Turn into window data table.
|
||||
function NAVYGROUP:AddTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
||||
|
||||
@@ -1277,25 +1277,20 @@ end
|
||||
-- @param #NAVYGROUP.IntoWind Into wind parameters.
|
||||
function NAVYGROUP:onafterTurnIntoWind(From, Event, To, IntoWind)
|
||||
|
||||
IntoWind.Heading=self:GetHeadingIntoWind(IntoWind.Offset)
|
||||
-- Calculate heading and speed of ship.
|
||||
local heading, speed=self:GetHeadingIntoWind(IntoWind.Offset, IntoWind.Speed)
|
||||
|
||||
IntoWind.Heading=heading
|
||||
IntoWind.Open=true
|
||||
|
||||
-- Get coordinate.
|
||||
IntoWind.Coordinate=self:GetCoordinate(true)
|
||||
|
||||
-- Set current into wind parameters.
|
||||
self.intowind=IntoWind
|
||||
|
||||
-- Wind speed in m/s.
|
||||
local _,vwind=self:GetWind()
|
||||
|
||||
-- Convert to knots.
|
||||
vwind=UTILS.MpsToKnots(vwind)
|
||||
|
||||
-- Speed of carrier relative to wind but at least 4 knots.
|
||||
local speed=math.max(IntoWind.Speed-vwind, 4)
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Steaming into wind: Heading=%03d Speed=%.1f Vwind=%.1f Vtot=%.1f knots, Tstart=%d Tstop=%d", IntoWind.Heading, speed, vwind, speed+vwind, IntoWind.Tstart, IntoWind.Tstop))
|
||||
self:T(self.lid..string.format("Steaming into wind: Heading=%03d Speed=%.1f, Tstart=%d Tstop=%d", IntoWind.Heading, speed, IntoWind.Tstart, IntoWind.Tstop))
|
||||
|
||||
local distance=UTILS.NMToMeters(1000)
|
||||
|
||||
@@ -2055,15 +2050,16 @@ end
|
||||
|
||||
--- Get wind direction and speed at current position.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #number Altitude Altitude in meters above main sea level at which the wind is calculated. Default 18 meters.
|
||||
-- @return #number Direction the wind is blowing **from** in degrees.
|
||||
-- @return #number Wind speed in m/s.
|
||||
function NAVYGROUP:GetWind()
|
||||
function NAVYGROUP:GetWind(Altitude)
|
||||
|
||||
-- Current position of the carrier or input.
|
||||
local coord=self:GetCoordinate()
|
||||
|
||||
-- Wind direction and speed. By default at 50 meters ASL.
|
||||
local Wdir, Wspeed=coord:GetWind(50)
|
||||
-- Wind direction and speed. By default at 18 meters ASL.
|
||||
local Wdir, Wspeed=coord:GetWind(Altitude or 18)
|
||||
|
||||
return Wdir, Wspeed
|
||||
end
|
||||
@@ -2072,7 +2068,7 @@ end
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #number Offset Offset angle in degrees, e.g. to account for an angled runway.
|
||||
-- @return #number Carrier heading in degrees.
|
||||
function NAVYGROUP:GetHeadingIntoWind(Offset)
|
||||
function NAVYGROUP:GetHeadingIntoWind_old(Offset)
|
||||
|
||||
Offset=Offset or 0
|
||||
|
||||
@@ -2086,15 +2082,104 @@ function NAVYGROUP:GetHeadingIntoWind(Offset)
|
||||
if vwind<0.1 then
|
||||
intowind=self:GetHeading()
|
||||
end
|
||||
|
||||
|
||||
-- Adjust negative values.
|
||||
if intowind<0 then
|
||||
intowind=intowind+360
|
||||
end
|
||||
|
||||
|
||||
return intowind
|
||||
end
|
||||
|
||||
|
||||
--- Get heading of group into the wind. This minimizes the cross wind for an angled runway.
|
||||
-- Implementation based on [Mags & Bami](https://magwo.github.io/carrier-cruise/) work.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #number Offset Offset angle in degrees, e.g. to account for an angled runway.
|
||||
-- @param #number vdeck Desired wind speed on deck in Knots.
|
||||
-- @return #number Carrier heading in degrees.
|
||||
function NAVYGROUP:GetHeadingIntoWind(Offset, vdeck)
|
||||
|
||||
-- Default offset angle.
|
||||
Offset=Offset or 0
|
||||
|
||||
-- Get direction the wind is blowing from.
|
||||
local windfrom, vwind=self:GetWind(18)
|
||||
|
||||
-- Convert wind speed to knots.
|
||||
vwind=UTILS.MpsToKnots(vwind)
|
||||
|
||||
-- Wind to in knots.
|
||||
local windto=(windfrom+180)%360
|
||||
|
||||
-- Offset angle in rad. We also define the rotation to be clock-wise, which requires a minus sign.
|
||||
local alpha=math.rad(-Offset)
|
||||
|
||||
-- Ships min/max speed.
|
||||
local Vmin=4
|
||||
local Vmax=UTILS.KmphToKnots(self.speedMax)
|
||||
|
||||
-- Constant.
|
||||
local C = math.sqrt(math.cos(alpha)^2 / math.sin(alpha)^2 + 1)
|
||||
|
||||
|
||||
-- Upper limit of desired speed due to max boat speed.
|
||||
local vdeckMax=vwind + math.cos(alpha) * Vmax
|
||||
|
||||
-- Lower limit of desired speed due to min boat speed.
|
||||
local vdeckMin=vwind + math.cos(alpha) * Vmin
|
||||
|
||||
|
||||
-- Speed of ship so it matches the desired speed.
|
||||
local v=0
|
||||
|
||||
-- Angle wrt. to wind TO-direction
|
||||
local theta=0
|
||||
|
||||
if vdeck>vdeckMax then
|
||||
-- Boat cannot go fast enough
|
||||
|
||||
-- Set max speed.
|
||||
v=Vmax
|
||||
|
||||
-- Calculate theta.
|
||||
theta = math.asin(v/(vwind*C)) - math.asin(-1/C)
|
||||
|
||||
elseif vdeck<vdeckMin then
|
||||
-- Boat cannot go slow enought
|
||||
|
||||
-- Set min speed.
|
||||
v=Vmin
|
||||
|
||||
-- Calculatge theta.
|
||||
theta = math.asin(v/(vwind*C)) - math.asin(-1/C)
|
||||
|
||||
elseif vdeck*math.sin(alpha)>vwind then
|
||||
-- Too little wind
|
||||
|
||||
-- Set theta to 90°
|
||||
theta=math.pi/2
|
||||
|
||||
-- Set speed.
|
||||
v = math.sqrt(vdeck^2 - vwind^2)
|
||||
|
||||
else
|
||||
-- Normal case
|
||||
theta = math.asin(vdeck * math.sin(alpha) / vwind)
|
||||
v = vdeck * math.cos(alpha) - vwind * math.cos(theta)
|
||||
end
|
||||
|
||||
|
||||
-- Ship heading so cross wind is min for the given wind.
|
||||
local intowind = (540 + (windto + math.deg(theta) )) % 360
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Heading into Wind: vship=%.1f, vwind=%.1f, WindTo=%03d°, Theta=%03d°, Heading=%03d", v, vwind, windto, theta, intowind))
|
||||
|
||||
return intowind, v
|
||||
end
|
||||
|
||||
|
||||
--- Find free path to next waypoint.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @return #boolean If true, a path was found.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
||||
--- **Ops** - Troop transport assignment for OPS groups.
|
||||
--- **Ops** - Transport assignment for OPS groups and storage.
|
||||
--
|
||||
-- ## Main Features:
|
||||
--
|
||||
-- * Transport troops from A to B
|
||||
-- * Transport of warehouse storage (fuel, weapons and equipment)
|
||||
-- * Supports ground, naval and airborne (airplanes and helicopters) units as carriers
|
||||
-- * Use combined forces (ground, naval, air) to transport the troops
|
||||
-- * Additional FSM events to hook into and customize your mission design
|
||||
@@ -63,6 +64,7 @@
|
||||
-- @field Ops.Chief#CHIEF chief Chief of the transport.
|
||||
-- @field Ops.OpsZone#OPSZONE opszone OPS zone.
|
||||
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed.
|
||||
-- @field #number cargocounter Running number to generate cargo UIDs.
|
||||
--
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
@@ -79,7 +81,7 @@
|
||||
-- * Cargo groups are **not** split and distributed into different carrier *units*. That means that the whole cargo group **must fit** into one of the carrier units.
|
||||
-- * Cargo groups must be inside the pickup zones to be considered for loading. Groups not inside the pickup zone will not get the command to board.
|
||||
--
|
||||
-- # Constructor
|
||||
-- # Troop Transport
|
||||
--
|
||||
-- A new cargo transport assignment is created with the @{#OPSTRANSPORT.New}() function
|
||||
--
|
||||
@@ -101,6 +103,30 @@
|
||||
--
|
||||
-- You can also mix carrier types. For instance, you can assign the same transport to APCs and helicopters. Or to helicopters and airplanes.
|
||||
--
|
||||
-- # Storage Transport
|
||||
--
|
||||
-- An instance of the OPSTRANSPORT class is created similarly to the troop transport case. However, the first parameter is `nil` as not troops
|
||||
-- are transported.
|
||||
--
|
||||
-- local storagetransport=OPSTRANSPORT:New(nil, PickupZone, DeployZone)
|
||||
--
|
||||
-- ## Defining Storage
|
||||
--
|
||||
-- The storage warehouses from which the cargo is taken and to which the cargo is delivered have to be specified
|
||||
--
|
||||
-- storagetransport:AddCargoStorage(berlinStorage, batumiStorage, STORAGE.Liquid.JETFUEL, 1000)
|
||||
--
|
||||
-- Here `berlinStorage` and `batumiStorage` are @{Wrapper.Storage#STORAGE} objects of DCS warehouses.
|
||||
--
|
||||
-- Furthermore, that type of cargo (liquids or weapons/equipment) and the amount has to be specified. If weapons/equipment is the cargo,
|
||||
-- we also need to specify the weight per storage item as this cannot be retrieved from the DCS API and is not stored in any MOOSE database.
|
||||
--
|
||||
-- storagetransport:AddCargoStorage(berlinStorage, batumiStorage, ENUMS.Storage.weapons.bombs.Mk_82, 9, 230)
|
||||
--
|
||||
-- Finally, the transport is assigned to one or multiple groups, which carry out the transport
|
||||
--
|
||||
-- myopsgroup:AddOpsTransport(storagetransport)
|
||||
--
|
||||
-- # Examples
|
||||
--
|
||||
-- A carrier group is assigned to transport infantry troops from zone "Zone Kobuleti X" to zone "Zone Alpha".
|
||||
@@ -131,6 +157,7 @@ OPSTRANSPORT = {
|
||||
legions = {},
|
||||
statusLegion = {},
|
||||
requestID = {},
|
||||
cargocounter = 0,
|
||||
}
|
||||
|
||||
--- Cargo transport status.
|
||||
@@ -186,6 +213,27 @@ OPSTRANSPORT.Status={
|
||||
-- @field #number radius Radomization radius for waypoints in meters. Default 0 m.
|
||||
-- @field #boolean reverse If `true`, path is used in reversed order.
|
||||
|
||||
--- Storage data.
|
||||
-- @type OPSTRANSPORT.Storage
|
||||
-- @field Wrapper.Storage#STORAGE storageFrom Storage from.
|
||||
-- @field Wrapper.Storage#STORAGE storageTo Storage To.
|
||||
-- @field #string cargoType Type of cargo.
|
||||
-- @field #number cargoAmount Amount of cargo that should be transported.
|
||||
-- @field #number cargoReserved Amount of cargo that is reserved for a carrier group.
|
||||
-- @field #number cargoDelivered Amount of cargo that has been delivered.
|
||||
-- @field #number cargoLost Amount of cargo that was lost.
|
||||
-- @field #number cargoLoaded Amount of cargo that is loading.
|
||||
-- @field #number cargoWeight Weight of one single cargo item in kg. Default 1 kg.
|
||||
|
||||
--- Storage data.
|
||||
-- @type OPSTRANSPORT.CargoType
|
||||
-- @field #string OPSGROUP Cargo is an OPSGROUP.
|
||||
-- @field #string STORAGE Cargo is storage of DCS warehouse.
|
||||
OPSTRANSPORT.CargoType={
|
||||
OPSGROUP="OPSGROUP",
|
||||
STORAGE="STORAGE",
|
||||
}
|
||||
|
||||
--- Generic transport condition.
|
||||
-- @type OPSTRANSPORT.Condition
|
||||
-- @field #function func Callback function to check for a condition. Should return a #boolean.
|
||||
@@ -196,7 +244,7 @@ _OPSTRANSPORTID=0
|
||||
|
||||
--- Army Group version.
|
||||
-- @field #string version
|
||||
OPSTRANSPORT.version="0.7.0"
|
||||
OPSTRANSPORT.version="0.8.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -205,6 +253,7 @@ OPSTRANSPORT.version="0.7.0"
|
||||
-- TODO: Trains.
|
||||
-- TODO: Stop transport.
|
||||
-- TODO: Improve pickup and transport paths.
|
||||
-- DONE: Storage.
|
||||
-- DONE: Disembark parameters per cargo group.
|
||||
-- DONE: Special transport cohorts/legions. Similar to mission.
|
||||
-- DONE: Cancel transport.
|
||||
@@ -576,6 +625,38 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo, DisembarkActi
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add cargo warehouse storage to be transported. This adds items such as fuel, weapons and other equipment, which is to be transported
|
||||
-- from one DCS warehouse to another.
|
||||
-- For weapons and equipment, the weight per item has to be specified explicitly as these cannot be retrieved by the DCS API. For liquids the
|
||||
-- default value of 1 kg per item should be used as the amount of liquid is already given in kg.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param Wrapper.Storage#STORAGE StorageFrom Storage warehouse from which the cargo is taken.
|
||||
-- @param Wrapper.Storage#STORAGE StorageTo Storage warehouse to which the cargo is delivered.
|
||||
-- @param #string CargoType Type of cargo, *e.g.* `"weapons.bombs.Mk_84"` or liquid type as #number.
|
||||
-- @param #number CargoAmount Amount of cargo. Liquids in kg.
|
||||
-- @param #number CargoWeight Weight of a single cargo item in kg. Default 1 kg.
|
||||
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo if other than default.
|
||||
-- @return #OPSTRANSPORT self
|
||||
function OPSTRANSPORT:AddCargoStorage(StorageFrom, StorageTo, CargoType, CargoAmount, CargoWeight, TransportZoneCombo)
|
||||
|
||||
-- Use default TZC if no transport zone combo is provided.
|
||||
TransportZoneCombo=TransportZoneCombo or self.tzcDefault
|
||||
|
||||
-- Cargo data.
|
||||
local cargo=self:_CreateCargoStorage(StorageFrom,StorageTo, CargoType, CargoAmount, CargoWeight, TransportZoneCombo)
|
||||
|
||||
if cargo then
|
||||
|
||||
-- Add total amount of ever assigned cargos.
|
||||
self.Ncargo=self.Ncargo+1
|
||||
|
||||
-- Add to TZC table.
|
||||
table.insert(TransportZoneCombo.Cargos, cargo)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Set pickup zone.
|
||||
-- @param #OPSTRANSPORT self
|
||||
@@ -1063,16 +1144,14 @@ end
|
||||
-- @return #table Cargo Ops groups. Can be and empty table `{}`.
|
||||
function OPSTRANSPORT:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
|
||||
|
||||
local cargos=self:GetCargos(TransportZoneCombo)
|
||||
local cargos=self:GetCargos(TransportZoneCombo, Carrier, Delivered)
|
||||
|
||||
local opsgroups={}
|
||||
for _,_cargo in pairs(cargos) do
|
||||
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
|
||||
if Delivered==nil or cargo.delivered==Delivered then
|
||||
if cargo.type=="OPSGROUP" then
|
||||
if cargo.opsgroup and not (cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped()) then
|
||||
if Carrier==nil or Carrier:CanCargo(cargo.opsgroup) then
|
||||
table.insert(opsgroups, cargo.opsgroup)
|
||||
end
|
||||
table.insert(opsgroups, cargo.opsgroup)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1080,6 +1159,27 @@ function OPSTRANSPORT:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
|
||||
return opsgroups
|
||||
end
|
||||
|
||||
--- Get (all) cargo @{Ops.OpsGroup#OPSGROUP}s. Optionally, only delivered or undelivered groups can be returned.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param #boolean Delivered If `true`, only delivered groups are returned. If `false` only undelivered groups are returned. If `nil`, all groups are returned.
|
||||
-- @param Ops.OpsGroup#OPSGROUP Carrier (Optional) Only count cargo groups that fit into the given carrier group. Current cargo is not a factor.
|
||||
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
|
||||
-- @return #table Cargo Ops groups. Can be and empty table `{}`.
|
||||
function OPSTRANSPORT:GetCargoStorages(Delivered, Carrier, TransportZoneCombo)
|
||||
|
||||
local cargos=self:GetCargos(TransportZoneCombo, Carrier, Delivered)
|
||||
|
||||
local opsgroups={}
|
||||
for _,_cargo in pairs(cargos) do
|
||||
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
|
||||
if cargo.type=="STORAGE" then
|
||||
table.insert(opsgroups, cargo.storage)
|
||||
end
|
||||
end
|
||||
|
||||
return opsgroups
|
||||
end
|
||||
|
||||
--- Get carriers.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @return #table Carrier Ops groups.
|
||||
@@ -1090,22 +1190,60 @@ end
|
||||
--- Get cargos.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
|
||||
-- @param Ops.OpsGroup#OPSGROUP Carrier Specific carrier.
|
||||
-- @param #boolean Delivered Delivered status.
|
||||
-- @return #table Cargos.
|
||||
function OPSTRANSPORT:GetCargos(TransportZoneCombo)
|
||||
|
||||
function OPSTRANSPORT:GetCargos(TransportZoneCombo, Carrier, Delivered)
|
||||
|
||||
local tczs=self.tzCombos
|
||||
if TransportZoneCombo then
|
||||
return TransportZoneCombo.Cargos
|
||||
else
|
||||
local cargos={}
|
||||
for _,_tzc in pairs(self.tzCombos) do
|
||||
local tzc=_tzc --#OPSTRANSPORT.TransportZoneCombo
|
||||
for _,cargo in pairs(tzc.Cargos) do
|
||||
table.insert(cargos, cargo)
|
||||
end
|
||||
end
|
||||
return cargos
|
||||
tczs={TransportZoneCombo}
|
||||
end
|
||||
|
||||
local cargos={}
|
||||
for _,_tcz in pairs(tczs) do
|
||||
local tcz=_tcz --#OPSTRANSPORT.TransportZoneCombo
|
||||
for _,_cargo in pairs(tcz.Cargos) do
|
||||
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
|
||||
if Delivered==nil or cargo.delivered==Delivered then
|
||||
if Carrier==nil or Carrier:CanCargo(cargo) then
|
||||
table.insert(cargos, cargo)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return cargos
|
||||
end
|
||||
|
||||
--- Get total weight.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param Ops.OpsGroup#OPSGROUP.CargoGroup Cargo Cargo data.
|
||||
-- @param #boolean IncludeReserved Include reserved cargo.
|
||||
-- @return #number Weight in kg.
|
||||
function OPSTRANSPORT:GetCargoTotalWeight(Cargo, IncludeReserved)
|
||||
|
||||
local weight=0
|
||||
|
||||
if Cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
|
||||
weight=Cargo.opsgroup:GetWeightTotal(nil, IncludeReserved)
|
||||
else
|
||||
if type(Cargo.storage.cargoType)=="number" then
|
||||
if IncludeReserved then
|
||||
return Cargo.storage.cargoAmount+Cargo.storage.cargoReserved
|
||||
else
|
||||
return Cargo.storage.cargoAmount
|
||||
end
|
||||
else
|
||||
if IncludeReserved then
|
||||
return Cargo.storage.cargoAmount*100 -- Assume 100 kg per item
|
||||
else
|
||||
return (Cargo.storage.cargoAmount+Cargo.storage.cargoReserved)*100 -- Assume 100 kg per item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return weight
|
||||
end
|
||||
|
||||
--- Set transport start and stop time.
|
||||
@@ -1642,11 +1780,18 @@ function OPSTRANSPORT:onafterStatusUpdate(From, Event, To)
|
||||
text=text..string.format("\nCargos:")
|
||||
for _,_cargo in pairs(self:GetCargos()) do
|
||||
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
|
||||
local carrier=cargo.opsgroup:_GetMyCarrierElement()
|
||||
local name=carrier and carrier.name or "none"
|
||||
local cstate=carrier and carrier.status or "N/A"
|
||||
text=text..string.format("\n- %s: %s [%s], weight=%d kg, carrier=%s [%s], delivered=%s [UID=%s]",
|
||||
cargo.opsgroup:GetName(), cargo.opsgroup.cargoStatus:upper(), cargo.opsgroup:GetState(), cargo.opsgroup:GetWeightTotal(), name, cstate, tostring(cargo.delivered), tostring(cargo.opsgroup.cargoTransportUID))
|
||||
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
|
||||
local carrier=cargo.opsgroup:_GetMyCarrierElement()
|
||||
local name=carrier and carrier.name or "none"
|
||||
local cstate=carrier and carrier.status or "N/A"
|
||||
text=text..string.format("\n- %s: %s [%s], weight=%d kg, carrier=%s [%s], delivered=%s [UID=%s]",
|
||||
cargo.opsgroup:GetName(), cargo.opsgroup.cargoStatus:upper(), cargo.opsgroup:GetState(), cargo.opsgroup:GetWeightTotal(), name, cstate, tostring(cargo.delivered), tostring(cargo.opsgroup.cargoTransportUID))
|
||||
else
|
||||
--TODO: Storage
|
||||
local storage=cargo.storage
|
||||
text=text..string.format("\n- storage type=%s: amount: total=%d loaded=%d, lost=%d, delivered=%d, delivered=%s [UID=%s]",
|
||||
storage.cargoType, storage.cargoAmount, storage.cargoLoaded, storage.cargoLost, storage.cargoDelivered, tostring(cargo.delivered), tostring(cargo.uid))
|
||||
end
|
||||
end
|
||||
|
||||
text=text..string.format("\nCarriers:")
|
||||
@@ -1923,14 +2068,14 @@ function OPSTRANSPORT:_CheckDelivered()
|
||||
if cargo.delivered then
|
||||
-- This one is delivered.
|
||||
dead=false
|
||||
elseif cargo.opsgroup==nil then
|
||||
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup==nil then
|
||||
-- This one is nil?!
|
||||
dead=false
|
||||
elseif cargo.opsgroup:IsDestroyed() then
|
||||
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsDestroyed() then
|
||||
-- This one was destroyed.
|
||||
elseif cargo.opsgroup:IsDead() then
|
||||
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsDead() then
|
||||
-- This one is dead.
|
||||
elseif cargo.opsgroup:IsStopped() then
|
||||
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsStopped() then
|
||||
-- This one is stopped.
|
||||
dead=false
|
||||
else
|
||||
@@ -2116,10 +2261,12 @@ function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo, Disembark
|
||||
end
|
||||
end
|
||||
|
||||
self.cargocounter=self.cargocounter+1
|
||||
|
||||
-- Create a new data item.
|
||||
local cargo={} --Ops.OpsGroup#OPSGROUP.CargoGroup
|
||||
|
||||
cargo.uid=self.cargocounter
|
||||
cargo.type="OPSGROUP"
|
||||
cargo.opsgroup=opsgroup
|
||||
cargo.delivered=false
|
||||
cargo.status="Unknown"
|
||||
@@ -2133,6 +2280,45 @@ function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo, Disembark
|
||||
return cargo
|
||||
end
|
||||
|
||||
--- Create a cargo group data structure.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param Wrapper.Storage#STORAGE StorageFrom Storage from.
|
||||
-- @param Wrapper.Storage#STORAGE StorageTo Storage to.
|
||||
-- @param #string CargoType Type of cargo.
|
||||
-- @param #number CargoAmount Total amount of cargo that should be transported. Liquids in kg.
|
||||
-- @param #number CargoWeight Weight of a single cargo item in kg. Default 1 kg.
|
||||
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
|
||||
-- @return Ops.OpsGroup#OPSGROUP.CargoGroup Cargo group data.
|
||||
function OPSTRANSPORT:_CreateCargoStorage(StorageFrom, StorageTo, CargoType, CargoAmount, CargoWeight, TransportZoneCombo)
|
||||
|
||||
local storage={} --#OPSTRANSPORT.Storage
|
||||
storage.storageFrom=StorageFrom
|
||||
storage.storageTo=StorageTo
|
||||
storage.cargoType=CargoType
|
||||
storage.cargoAmount=CargoAmount
|
||||
storage.cargoDelivered=0
|
||||
storage.cargoLost=0
|
||||
storage.cargoReserved=0
|
||||
storage.cargoLoaded=0
|
||||
storage.cargoWeight=CargoWeight or 1
|
||||
|
||||
self.cargocounter=self.cargocounter+1
|
||||
|
||||
-- Create a new data item.
|
||||
local cargo={} --Ops.OpsGroup#OPSGROUP.CargoGroup
|
||||
cargo.uid=self.cargocounter
|
||||
cargo.type="STORAGE"
|
||||
cargo.opsgroup=nil
|
||||
cargo.storage=storage
|
||||
cargo.delivered=false
|
||||
cargo.status="Unknown"
|
||||
cargo.tzcUID=TransportZoneCombo
|
||||
cargo.disembarkZone=nil
|
||||
cargo.disembarkCarriers=nil
|
||||
|
||||
return cargo
|
||||
end
|
||||
|
||||
--- Count how many cargo groups are inside a zone.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param Core.Zone#ZONE Zone The zone object.
|
||||
@@ -2143,7 +2329,9 @@ end
|
||||
function OPSTRANSPORT:_CountCargosInZone(Zone, Delivered, Carrier, TransportZoneCombo)
|
||||
|
||||
-- Get cargo ops groups.
|
||||
local cargos=self:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
|
||||
--local cargos=self:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
|
||||
|
||||
local cargos=self:GetCargos(TransportZoneCombo, Carrier, Delivered)
|
||||
|
||||
--- Function to check if carrier is supposed to be disembarked to.
|
||||
local function iscarrier(_cargo)
|
||||
@@ -2185,22 +2373,33 @@ function OPSTRANSPORT:_CountCargosInZone(Zone, Delivered, Carrier, TransportZone
|
||||
|
||||
local N=0
|
||||
for _,_cargo in pairs(cargos) do
|
||||
local cargo=_cargo --Ops.OpsGroup#OPSGROUP
|
||||
|
||||
-- Is not cargo?
|
||||
local isNotCargo=cargo:IsNotCargo(true)
|
||||
if not isNotCargo then
|
||||
isNotCargo=iscarrier(cargo)
|
||||
end
|
||||
|
||||
-- Is in zone?
|
||||
local isInZone=cargo:IsInZone(Zone)
|
||||
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
|
||||
|
||||
-- Is in utero?
|
||||
local isInUtero=cargo:IsInUtero()
|
||||
local isNotCargo=true
|
||||
local isInZone=true
|
||||
local isInUtero=true
|
||||
|
||||
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
|
||||
local opsgroup=cargo.opsgroup
|
||||
|
||||
-- Is not cargo?
|
||||
isNotCargo=opsgroup:IsNotCargo(true)
|
||||
if not isNotCargo then
|
||||
isNotCargo=iscarrier(opsgroup)
|
||||
end
|
||||
|
||||
-- Is in zone?
|
||||
isInZone=opsgroup:IsInZone(Zone)
|
||||
|
||||
-- Is in utero?
|
||||
isInUtero=opsgroup:IsInUtero()
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Cargo=%s: notcargo=%s, iscarrier=%s inzone=%s, inutero=%s", opsgroup:GetName(), tostring(opsgroup:IsNotCargo(true)), tostring(iscarrier(opsgroup)), tostring(isInZone), tostring(isInUtero)))
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Cargo=%s: notcargo=%s, iscarrier=%s inzone=%s, inutero=%s", cargo:GetName(), tostring(cargo:IsNotCargo(true)), tostring(iscarrier(cargo)), tostring(isInZone), tostring(isInUtero)))
|
||||
|
||||
-- We look for groups that are not cargo, in the zone or in utero.
|
||||
if isNotCargo and (isInZone or isInUtero) then
|
||||
|
||||
@@ -104,7 +104,7 @@ PLAYERRECCE = {
|
||||
ClassName = "PLAYERRECCE",
|
||||
verbose = true,
|
||||
lid = nil,
|
||||
version = "0.0.17",
|
||||
version = "0.0.18",
|
||||
ViewZone = {},
|
||||
ViewZoneVisual = {},
|
||||
ViewZoneLaser = {},
|
||||
@@ -807,6 +807,7 @@ function PLAYERRECCE:_SetClientLaserCode(client,group,playername,code)
|
||||
self.ClientMenus[playername]:Remove()
|
||||
self.ClientMenus[playername]=nil
|
||||
end
|
||||
self:_BuildMenus()
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -829,6 +830,7 @@ function PLAYERRECCE:_SwitchOnStation(client,group,playername)
|
||||
self.ClientMenus[playername]:Remove()
|
||||
self.ClientMenus[playername]=nil
|
||||
end
|
||||
self:_BuildMenus(client)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -851,6 +853,7 @@ function PLAYERRECCE:_SwitchSmoke(client,group,playername)
|
||||
self.ClientMenus[playername]:Remove()
|
||||
self.ClientMenus[playername]=nil
|
||||
end
|
||||
self:_BuildMenus(client)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -873,6 +876,7 @@ function PLAYERRECCE:_SwitchLasing(client,group,playername)
|
||||
self.ClientMenus[playername]:Remove()
|
||||
self.ClientMenus[playername]=nil
|
||||
end
|
||||
self:_BuildMenus(client)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -902,6 +906,7 @@ function PLAYERRECCE:_SwitchLasingDist(client,group,playername,mindist,maxdist)
|
||||
self.ClientMenus[playername]:Remove()
|
||||
self.ClientMenus[playername]=nil
|
||||
end
|
||||
self:_BuildMenus(client)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -930,6 +935,8 @@ function PLAYERRECCE:_SmokeTargets(client,group,playername)
|
||||
|
||||
if cameraset:CountAlive() > 0 then
|
||||
self:__TargetsSmoked(-1,client,playername,cameraset)
|
||||
else
|
||||
return self
|
||||
end
|
||||
|
||||
local highsmoke = self.SmokeColor.highsmoke
|
||||
@@ -1068,7 +1075,7 @@ self:T(self.lid.."_ReportLaserTargets")
|
||||
if number > 0 and self.AutoLase[playername] then
|
||||
local Settings = ( client and _DATABASE:GetPlayerSettings( playername ) ) or _SETTINGS
|
||||
local target = self:_GetHVTTarget(targetset) -- the one we're lasing
|
||||
local ThreatLevel = target:GetThreatLevel()
|
||||
local ThreatLevel = target:GetThreatLevel() or 1
|
||||
local ThreatLevelText = "high"
|
||||
if ThreatLevel > 3 and ThreatLevel < 8 then
|
||||
ThreatLevelText = "medium"
|
||||
@@ -1078,7 +1085,7 @@ self:T(self.lid.."_ReportLaserTargets")
|
||||
local ThreatGraph = "[" .. string.rep( "■", ThreatLevel ) .. string.rep( "□", 10 - ThreatLevel ) .. "]: "..ThreatLevel
|
||||
local report = REPORT:New("Lasing Report")
|
||||
report:Add(string.rep("-",15))
|
||||
report:Add("Target type: "..target:GetTypeName())
|
||||
report:Add("Target type: "..target:GetTypeName() or "unknown")
|
||||
report:Add("Threat Level: "..ThreatGraph.." ("..ThreatLevelText..")")
|
||||
if not self.ReferencePoint then
|
||||
report:Add("Location: "..client:GetCoordinate():ToStringBULLS(self.Coalition,Settings))
|
||||
@@ -1088,14 +1095,14 @@ self:T(self.lid.."_ReportLaserTargets")
|
||||
report:Add("Laser Code: "..self.UnitLaserCodes[playername] or 1688)
|
||||
report:Add(string.rep("-",15))
|
||||
local text = report:Text()
|
||||
self:__TargetReport(-1,client,targetset,target,text)
|
||||
self:__TargetReport(1,client,targetset,target,text)
|
||||
else
|
||||
local report = REPORT:New("Lasing Report")
|
||||
report:Add(string.rep("-",15))
|
||||
report:Add("N O T A R G E T S")
|
||||
report:Add(string.rep("-",15))
|
||||
local text = report:Text()
|
||||
self:__TargetReport(-1,client,nil,nil,text)
|
||||
self:__TargetReport(1,client,nil,nil,text)
|
||||
end
|
||||
return self
|
||||
end
|
||||
@@ -1130,25 +1137,27 @@ function PLAYERRECCE:_ReportVisualTargets(client,group,playername)
|
||||
end
|
||||
report:Add(string.rep("-",15))
|
||||
local text = report:Text()
|
||||
self:__TargetReport(-1,client,targetset,nil,text)
|
||||
self:__TargetReport(1,client,targetset,nil,text)
|
||||
else
|
||||
local report = REPORT:New("Target Report")
|
||||
report:Add(string.rep("-",15))
|
||||
report:Add("N O T A R G E T S")
|
||||
report:Add(string.rep("-",15))
|
||||
local text = report:Text()
|
||||
self:__TargetReport(-1,client,nil,nil,text)
|
||||
self:__TargetReport(1,client,nil,nil,text)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal]
|
||||
--- [Internal] Build Menus
|
||||
-- @param #PLAYERRECCE self
|
||||
-- @param #PLAYERRECCE self
|
||||
function PLAYERRECCE:_BuildMenus()
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) Client object
|
||||
-- @return #PLAYERRECCE self
|
||||
function PLAYERRECCE:_BuildMenus(Client)
|
||||
self:T(self.lid.."_BuildMenus")
|
||||
local clients = self.PlayerSet -- Core.Set#SET_CLIENT
|
||||
local clientset = clients:GetSetObjects()
|
||||
if Client then clientset = {Client} end
|
||||
for _,_client in pairs(clientset) do
|
||||
local client = _client -- Wrapper.Client#CLIENT
|
||||
if client and client:IsAlive() then
|
||||
@@ -1156,7 +1165,7 @@ function PLAYERRECCE:_BuildMenus()
|
||||
if not self.UnitLaserCodes[playername] then
|
||||
self:_SetClientLaserCode(nil,nil,playername,1688)
|
||||
end
|
||||
if not self.SmokeOwn[playername] then
|
||||
if self.SmokeOwn[playername] == nil then
|
||||
self.SmokeOwn[playername] = self.smokeownposition
|
||||
end
|
||||
local group = client:GetGroup()
|
||||
@@ -1919,7 +1928,7 @@ function PLAYERRECCE:onafterTargetReport(From, Event, To, Client, TargetSet, Tar
|
||||
-- send message to AttackSet
|
||||
for _,_client in pairs(self.AttackSet.Set) do
|
||||
local client = _client -- Wrapper.Client#CLIENT
|
||||
if client and client:IsAlive() then
|
||||
if client and client:IsAlive() and client ~= Client then
|
||||
MESSAGE:New(Text,45,self.Name or "FACA"):ToClient(client)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-- ===
|
||||
-- @module Ops.PlayerTask
|
||||
-- @image OPS_PlayerTask.jpg
|
||||
-- @date Last Update June 2023
|
||||
-- @date Last Update Oct 2023
|
||||
|
||||
|
||||
do
|
||||
@@ -98,7 +98,7 @@ PLAYERTASK = {
|
||||
|
||||
--- PLAYERTASK class version.
|
||||
-- @field #string version
|
||||
PLAYERTASK.version="0.1.17"
|
||||
PLAYERTASK.version="0.1.21"
|
||||
|
||||
--- Generic task condition.
|
||||
-- @type PLAYERTASK.Condition
|
||||
@@ -470,10 +470,11 @@ end
|
||||
--- [User] Remove a client from this task
|
||||
-- @param #PLAYERTASK self
|
||||
-- @param Wrapper.Client#CLIENT Client
|
||||
-- @param #string Name Name of the client
|
||||
-- @return #PLAYERTASK self
|
||||
function PLAYERTASK:RemoveClient(Client)
|
||||
function PLAYERTASK:RemoveClient(Client,Name)
|
||||
self:T(self.lid.."RemoveClient")
|
||||
local name = Client:GetPlayerName()
|
||||
local name = Name or Client:GetPlayerName()
|
||||
if self.Clients:HasUniqueID(name) then
|
||||
self.Clients:PullByID(name)
|
||||
if self.verbose then
|
||||
@@ -1008,6 +1009,7 @@ do
|
||||
-- @field Core.ClientMenu#CLIENTMENUMANAGER ActiveTaskMenuTemplate
|
||||
-- @field Core.ClientMenu#CLIENTMENU ActiveTopMenu
|
||||
-- @field Core.ClientMenu#CLIENTMENU ActiveInfoMenu
|
||||
-- @field Core.ClientMenu#CLIENTMENU MenuNoTask
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
---
|
||||
@@ -1336,6 +1338,7 @@ PLAYERTASKCONTROLLER = {
|
||||
InfoHasCoordinate = false,
|
||||
UseTypeNames = false,
|
||||
Scoring = nil,
|
||||
MenuNoTask = nil,
|
||||
}
|
||||
|
||||
---
|
||||
@@ -1549,7 +1552,7 @@ PLAYERTASKCONTROLLER.Messages = {
|
||||
|
||||
--- PLAYERTASK class version.
|
||||
-- @field #string version
|
||||
PLAYERTASKCONTROLLER.version="0.1.60a"
|
||||
PLAYERTASKCONTROLLER.version="0.1.62"
|
||||
|
||||
--- Create and run a new TASKCONTROLLER instance.
|
||||
-- @param #PLAYERTASKCONTROLLER self
|
||||
@@ -1654,13 +1657,6 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
|
||||
local starttime = math.random(5,10)
|
||||
self:__Status(starttime)
|
||||
|
||||
-- Player leaves
|
||||
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.Crash, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
|
||||
|
||||
self:I(self.lid..self.version.." Started.")
|
||||
|
||||
return self
|
||||
@@ -2175,7 +2171,7 @@ end
|
||||
-- @return #PLAYERTASKCONTROLLER self
|
||||
function PLAYERTASKCONTROLLER:_EventHandler(EventData)
|
||||
self:T(self.lid.."_EventHandler: "..EventData.id)
|
||||
self:T(self.lid.."_EventHandler: "..EventData.IniPlayerName)
|
||||
--self:T(self.lid.."_EventHandler: "..EventData.IniPlayerName)
|
||||
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
|
||||
if EventData.IniPlayerName then
|
||||
self:T(self.lid.."Event for player: "..EventData.IniPlayerName)
|
||||
@@ -2191,6 +2187,10 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
|
||||
task:RemoveClient(Client)
|
||||
--text = "Task aborted!"
|
||||
text = self.gettext:GetEntry("TASKABORT",self.locale)
|
||||
else
|
||||
task:RemoveClient(nil,EventData.IniPlayerName)
|
||||
--text = "Task aborted!"
|
||||
text = self.gettext:GetEntry("TASKABORT",self.locale)
|
||||
end
|
||||
else
|
||||
--text = "No active task!"
|
||||
@@ -2200,7 +2200,8 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
|
||||
end
|
||||
elseif EventData.id == EVENTS.PlayerEnterAircraft and EventData.IniCoalition == self.Coalition then
|
||||
if EventData.IniPlayerName and EventData.IniGroup then
|
||||
if self.IsClientSet and self.ClientSet:IsNotInSet(CLIENT:FindByName(EventData.IniUnitName)) then
|
||||
--if self.IsClientSet and self.ClientSet:IsNotInSet(CLIENT:FindByName(EventData.IniUnitName)) then
|
||||
if self.IsClientSet and (not self.ClientSet:IsIncludeObject(CLIENT:FindByName(EventData.IniUnitName))) then
|
||||
self:T(self.lid.."Client not in SET: "..EventData.IniPlayerName)
|
||||
return self
|
||||
end
|
||||
@@ -2481,6 +2482,15 @@ function PLAYERTASKCONTROLLER:_CheckTaskQueue()
|
||||
self:T("*****Removing player " .. _id)
|
||||
self.TasksPerPlayer:PullByID(_id)
|
||||
end
|
||||
local clients=task:GetClientObjects()
|
||||
for _,client in pairs(clients) do
|
||||
self:_RemoveMenuEntriesForTask(task,client)
|
||||
--self:_SwitchMenuForClient(client,"Info")
|
||||
end
|
||||
for _,client in pairs(clients) do
|
||||
-- self:_RemoveMenuEntriesForTask(Task,client)
|
||||
self:_SwitchMenuForClient(client,"Info",5)
|
||||
end
|
||||
-- Follow-up tasks?
|
||||
local nexttasks = {}
|
||||
if task.FinalState == "Success" then
|
||||
@@ -2499,7 +2509,8 @@ function PLAYERTASKCONTROLLER:_CheckTaskQueue()
|
||||
end
|
||||
end
|
||||
local TNow = timer.getAbsTime()
|
||||
if TNow - task.timestamp > 10 then
|
||||
if TNow - task.timestamp > 5 then
|
||||
self:_RemoveMenuEntriesForTask(task)
|
||||
local task = self.TaskQueue:PullByID(_id) -- Ops.PlayerTask#PLAYERTASK
|
||||
task = nil
|
||||
end
|
||||
@@ -3469,6 +3480,19 @@ function PLAYERTASKCONTROLLER:_UpdateJoinMenuTemplate()
|
||||
local actinfomenu = self.ActiveInfoMenu
|
||||
--local entrynumbers = {}
|
||||
--local existingentries = {}
|
||||
|
||||
if self.TaskQueue:Count() == 0 and self.MenuNoTask == nil then
|
||||
local menunotasks = self.gettext:GetEntry("MENUNOTASKS",self.locale)
|
||||
self.MenuNoTask = controller:NewEntry(menunotasks,self.JoinMenu)
|
||||
controller:AddEntry(self.MenuNoTask)
|
||||
end
|
||||
|
||||
if self.TaskQueue:Count() > 0 and self.MenuNoTask ~= nil then
|
||||
controller:DeleteGenericEntry(self.MenuNoTask)
|
||||
controller:DeleteF10Entry(self.MenuNoTask)
|
||||
self.MenuNoTask = nil
|
||||
end
|
||||
|
||||
local maxn = self.menuitemlimit
|
||||
-- Generate task type menu items
|
||||
for _type,_ in pairs(taskpertype) do
|
||||
@@ -3499,13 +3523,6 @@ function PLAYERTASKCONTROLLER:_UpdateJoinMenuTemplate()
|
||||
if _task.InMenu then
|
||||
self:T("**** Task already in Menu ".._task.Target:GetName())
|
||||
else
|
||||
--local pilotcount = _task:CountClients()
|
||||
--local newtext = "]"
|
||||
--local tnow = timer.getTime()
|
||||
-- marker for new tasks
|
||||
--if tnow - _task.timestamp < 60 then
|
||||
--newtext = "*]"
|
||||
--end
|
||||
local menutaskno = self.gettext:GetEntry("MENUTASKNO",self.locale)
|
||||
--local text = string.format("%s %03d [%d%s",menutaskno,_task.PlayerTaskNr,pilotcount,newtext)
|
||||
local text = string.format("%s %03d",menutaskno,_task.PlayerTaskNr)
|
||||
@@ -3516,7 +3533,6 @@ function PLAYERTASKCONTROLLER:_UpdateJoinMenuTemplate()
|
||||
text = string.format("%s (%03d)",name,_task.PlayerTaskNr)
|
||||
end
|
||||
end
|
||||
--local taskentry = MENU_GROUP_COMMAND:New(group,text,ttypes[_tasktype],self._JoinTask,self,group,client,_task):SetTag(newtag)
|
||||
local parenttable, number = controller:FindEntriesByText(_tasktype,JoinMenu)
|
||||
if number > 0 then
|
||||
local Parent = parenttable[1]
|
||||
@@ -3579,28 +3595,28 @@ function PLAYERTASKCONTROLLER:_RemoveMenuEntriesForTask(Task,Client)
|
||||
if Task then
|
||||
if Task.UUIDS and self.JoinTaskMenuTemplate then
|
||||
--self:I("***** JoinTaskMenuTemplate")
|
||||
UTILS.PrintTableToLog(Task.UUIDS)
|
||||
--UTILS.PrintTableToLog(Task.UUIDS)
|
||||
local controller = self.JoinTaskMenuTemplate
|
||||
for _,_uuid in pairs(Task.UUIDS) do
|
||||
local Entry = controller:FindEntryByUUID(_uuid)
|
||||
if Entry then
|
||||
controller:DeleteF10Entry(Entry,Client)
|
||||
controller:DeleteGenericEntry(Entry)
|
||||
UTILS.PrintTableToLog(controller.menutree)
|
||||
--UTILS.PrintTableToLog(controller.menutree)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if Task.AUUIDS and self.ActiveTaskMenuTemplate then
|
||||
--self:I("***** ActiveTaskMenuTemplate")
|
||||
UTILS.PrintTableToLog(Task.AUUIDS)
|
||||
--UTILS.PrintTableToLog(Task.AUUIDS)
|
||||
for _,_uuid in pairs(Task.AUUIDS) do
|
||||
local controller = self.ActiveTaskMenuTemplate
|
||||
local Entry = controller:FindEntryByUUID(_uuid)
|
||||
if Entry then
|
||||
controller:DeleteF10Entry(Entry,Client)
|
||||
controller:DeleteGenericEntry(Entry)
|
||||
UTILS.PrintTableToLog(controller.menutree)
|
||||
--UTILS.PrintTableToLog(controller.menutree)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3641,8 +3657,13 @@ function PLAYERTASKCONTROLLER:_CreateJoinMenuTemplate()
|
||||
self.JoinInfoMenu = JoinTaskMenuTemplate:NewEntry(menutaskinfo,self.JoinTopMenu)
|
||||
end
|
||||
|
||||
if self.TaskQueue:Count() == 0 then
|
||||
JoinTaskMenuTemplate:NewEntry(menunotasks,self.JoinMenu)
|
||||
if self.TaskQueue:Count() == 0 and self.MenuNoTask == nil then
|
||||
self.MenuNoTask = JoinTaskMenuTemplate:NewEntry(menunotasks,self.JoinMenu)
|
||||
end
|
||||
|
||||
if self.TaskQueue:Count() > 0 and self.MenuNoTask ~= nil then
|
||||
JoinTaskMenuTemplate:DeleteGenericEntry(self.MenuNoTask)
|
||||
self.MenuNoTask = nil
|
||||
end
|
||||
|
||||
self.JoinTaskMenuTemplate = JoinTaskMenuTemplate
|
||||
@@ -4043,6 +4064,13 @@ function PLAYERTASKCONTROLLER:onafterStart(From, Event, To)
|
||||
self:T(self.lid.."onafterStart")
|
||||
self:_CreateJoinMenuTemplate()
|
||||
self:_CreateActiveTaskMenuTemplate()
|
||||
-- Player Events
|
||||
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.Crash, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
|
||||
self:SetEventPriority(5)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -4190,6 +4218,15 @@ function PLAYERTASKCONTROLLER:onafterTaskFailed(From, Event, To, Task)
|
||||
taskname = string.format(failtxttts, self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType))
|
||||
self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2)
|
||||
end
|
||||
local clients=Task:GetClientObjects()
|
||||
for _,client in pairs(clients) do
|
||||
self:_RemoveMenuEntriesForTask(Task,client)
|
||||
--self:_SwitchMenuForClient(client,"Info")
|
||||
end
|
||||
for _,client in pairs(clients) do
|
||||
-- self:_RemoveMenuEntriesForTask(Task,client)
|
||||
self:_SwitchMenuForClient(client,"Info",5)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
-- @field #boolean eplrs If true, enable data link, e.g. if used as AWACS.
|
||||
-- @field #boolean recovery If true, tanker will recover using the AIRBOSS marshal pattern.
|
||||
-- @field #number terminaltype Terminal type of used parking spots on airbases.
|
||||
-- @field #boolean unlimitedfuel If true, the tanker will have unlimited fuel.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Recovery Tanker.
|
||||
@@ -300,6 +301,7 @@ RECOVERYTANKER = {
|
||||
eplrs = nil,
|
||||
recovery = nil,
|
||||
terminaltype = nil,
|
||||
unlimitedfuel = false,
|
||||
}
|
||||
|
||||
--- Unique ID (global).
|
||||
@@ -308,7 +310,7 @@ _RECOVERYTANKERID=0
|
||||
|
||||
--- Class version.
|
||||
-- @field #string version
|
||||
RECOVERYTANKER.version="1.0.9"
|
||||
RECOVERYTANKER.version="1.0.10"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -326,6 +328,7 @@ RECOVERYTANKER.version="1.0.9"
|
||||
-- DONE: Set AA TACAN.
|
||||
-- DONE: Add refueling event/state.
|
||||
-- DONE: Possibility to add already present/spawned aircraft, e.g. for warehouse.
|
||||
-- DONE: Add unlimited fuel
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@@ -550,6 +553,15 @@ end
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set the tanker to have unlimited fuel.
|
||||
-- @param #RECOVERYTANKER self
|
||||
-- @param #boolean OnOff If true, the tanker will have unlimited fuel.
|
||||
-- @return #RECOVERYTANKER self
|
||||
function RECOVERYTANKER:SetUnlimitedFuel(OnOff)
|
||||
self.unlimitedfuel = OnOff
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the speed the tanker flys in its orbit pattern.
|
||||
-- @param #RECOVERYTANKER self
|
||||
-- @param #number speed True air speed (TAS) in knots. Default 274 knots, which results in ~250 KIAS.
|
||||
@@ -899,6 +911,14 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
||||
-- Spawn tanker. We need to introduce an alias in case this class is used twice. This would confuse the spawn routine.
|
||||
local Spawn=SPAWN:NewWithAlias(self.tankergroupname, self.alias)
|
||||
|
||||
if self.unlimitedfuel then
|
||||
Spawn:OnSpawnGroup(
|
||||
function (grp)
|
||||
grp:CommandSetUnlimitedFuel(self.unlimitedfuel)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
-- Set radio frequency and modulation.
|
||||
Spawn:InitRadioCommsOnOff(true)
|
||||
Spawn:InitRadioFrequency(self.RadioFreq)
|
||||
|
||||
@@ -17,7 +17,12 @@
|
||||
--- Makes the radio speak.
|
||||
--
|
||||
-- # RADIOSPEECH usage
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
--
|
||||
-- @type RADIOSPEECH
|
||||
-- @extends Core.RadioQueue#RADIOQUEUE
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
-- @field #string google Full path google credentials JSON file, e.g. "C:\Users\username\Downloads\service-account-file.json".
|
||||
-- @field #string Label Label showing up on the SRS radio overlay. Default is "ROBOT". No spaces allowed.
|
||||
-- @field #table AltBackend Table containing functions and variables to enable an alternate backend to transmit to SRS.
|
||||
-- @field #string ConfigFileName Name of the standard config file
|
||||
-- @field #string ConfigFilePath Path to the standard config file
|
||||
-- @field #boolean ConfigLoaded
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *It is a very sad thing that nowadays there is so little useless information.* - Oscar Wilde
|
||||
@@ -91,7 +94,7 @@
|
||||
-- ## Set Google
|
||||
--
|
||||
-- Use Google's text-to-speech engine with the @{#MSRS.SetGoogle} function, e.g. ':SetGoogle()'.
|
||||
-- By enabling this it also allows you to utilize SSML in your text for added flexibilty.
|
||||
-- By enabling this it also allows you to utilize SSML in your text for added flexibility.
|
||||
-- For more information on setting up a cloud account, visit: https://cloud.google.com/text-to-speech
|
||||
-- Google's supported SSML reference: https://cloud.google.com/text-to-speech/docs/ssml
|
||||
--
|
||||
@@ -185,6 +188,9 @@ MSRS = {
|
||||
coordinate = nil,
|
||||
Label = "ROBOT",
|
||||
AltBackend = nil,
|
||||
ConfigFileName = "Moose_MSRS.lua",
|
||||
ConfigFilePath = "Config\\",
|
||||
ConfigLoaded = false,
|
||||
}
|
||||
|
||||
--- MSRS class version.
|
||||
@@ -192,7 +198,7 @@ MSRS = {
|
||||
MSRS.version="0.1.2"
|
||||
|
||||
--- Voices
|
||||
-- @type Voices
|
||||
-- @type MSRS.Voices
|
||||
MSRS.Voices = {
|
||||
Microsoft = {
|
||||
["Hedda"] = "Microsoft Hedda Desktop", -- de-DE
|
||||
@@ -292,6 +298,37 @@ MSRS.Voices = {
|
||||
},
|
||||
}
|
||||
|
||||
---
|
||||
-- @type MSRS.ProviderOptions
|
||||
-- @field #string key
|
||||
-- @field #string secret
|
||||
-- @field #string region
|
||||
-- @field #string defaultVoice
|
||||
-- @field #string voice
|
||||
|
||||
--- GRPC options
|
||||
-- @type MSRS.GRPCOptions
|
||||
-- @field #string plaintext
|
||||
-- @field #string srsClientName
|
||||
-- @field #table position
|
||||
-- @field #string coalition
|
||||
-- @field #MSRS.ProviderOptions gcloud
|
||||
-- @field #MSRS.ProviderOptions win
|
||||
-- @field #MSRS.ProviderOptions azure
|
||||
-- @field #MSRS.ProviderOptions aws
|
||||
-- @field #string DefaultProvider
|
||||
|
||||
MSRS.GRPCOptions = {} -- #MSRS.GRPCOptions
|
||||
MSRS.GRPCOptions.gcloud = {} -- #MSRS.ProviderOptions
|
||||
MSRS.GRPCOptions.win = {} -- #MSRS.ProviderOptions
|
||||
MSRS.GRPCOptions.azure = {} -- #MSRS.ProviderOptions
|
||||
MSRS.GRPCOptions.aws = {} -- #MSRS.ProviderOptions
|
||||
|
||||
MSRS.GRPCOptions.win.defaultVoice = "Hedda"
|
||||
MSRS.GRPCOptions.win.voice = "Hedda"
|
||||
|
||||
MSRS.GRPCOptions.DefaultProvider = "win"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -299,6 +336,8 @@ MSRS.Voices = {
|
||||
-- TODO: Add functions to remove freqs and modulations.
|
||||
-- DONE: Add coordinate.
|
||||
-- DONE: Add google.
|
||||
-- DONE: Add gRPC google options
|
||||
-- DONE: Add loading default config file
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@@ -328,25 +367,49 @@ function MSRS:New(PathToSRS, Frequency, Modulation, Volume, AltBackend)
|
||||
|
||||
-- Add parameters to vars so alternate backends can use them if applicable
|
||||
Backend.Vars = Backend.Vars or {}
|
||||
Backend.Vars.PathToSRS = UTILS.DeepCopy(PathToSRS) -- DeepCopy probably unecessary
|
||||
Backend.Vars.PathToSRS = PathToSRS
|
||||
Backend.Vars.Frequency = UTILS.DeepCopy(Frequency)
|
||||
Backend.Vars.Modulation = UTILS.DeepCopy(Modulation)
|
||||
Backend.Vars.Volume = UTILS.DeepCopy(Volume) -- DeepCopy probably unecessary
|
||||
Backend.Vars.Volume = Volume
|
||||
|
||||
Backend.Functions = Backend.Functions or {}
|
||||
|
||||
return self:_NewAltBackend(Backend)
|
||||
end
|
||||
|
||||
-- If no AltBackend table, the proceed with default initialization
|
||||
self:SetPath(PathToSRS)
|
||||
self:SetPort()
|
||||
self:SetFrequencies(Frequency)
|
||||
self:SetModulations(Modulation)
|
||||
self:SetGender()
|
||||
self:SetCoalition()
|
||||
self:SetLabel()
|
||||
self:SetVolume()
|
||||
local success = self:LoadConfigFile(nil,nil,self.ConfigLoaded)
|
||||
|
||||
if (not success) and (not self.ConfigLoaded) then
|
||||
|
||||
-- If no AltBackend table, the proceed with default initialisation
|
||||
self:SetPath(PathToSRS)
|
||||
self:SetPort()
|
||||
self:SetFrequencies(Frequency)
|
||||
self:SetModulations(Modulation)
|
||||
self:SetGender()
|
||||
self:SetCoalition()
|
||||
self:SetLabel()
|
||||
self:SetVolume(Volume)
|
||||
|
||||
else
|
||||
|
||||
-- there might be some overwrites from :New()
|
||||
|
||||
if PathToSRS then
|
||||
self:SetPath(PathToSRS)
|
||||
end
|
||||
|
||||
if Frequency then
|
||||
self:SetFrequencies(Frequency)
|
||||
self:SetModulations(Modulation)
|
||||
end
|
||||
|
||||
if Volume then
|
||||
self:SetVolume(Volume)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self.lid = string.format("%s-%s | ", self.name, self.version)
|
||||
|
||||
if not io or not os then
|
||||
@@ -366,24 +429,25 @@ end
|
||||
-- @return #MSRS self
|
||||
function MSRS:SetPath(Path)
|
||||
|
||||
if Path==nil then
|
||||
if Path==nil and not self.path then
|
||||
self:E("ERROR: No path to SRS directory specified!")
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Set path.
|
||||
self.path=Path
|
||||
|
||||
-- Remove (back)slashes.
|
||||
local n=1 ; local nmax=1000
|
||||
while (self.path:sub(-1)=="/" or self.path:sub(-1)==[[\]]) and n<=nmax do
|
||||
self.path=self.path:sub(1,#self.path-1)
|
||||
n=n+1
|
||||
if Path then
|
||||
-- Set path.
|
||||
self.path=Path
|
||||
|
||||
-- Remove (back)slashes.
|
||||
local n=1 ; local nmax=1000
|
||||
while (self.path:sub(-1)=="/" or self.path:sub(-1)==[[\]]) and n<=nmax do
|
||||
self.path=self.path:sub(1,#self.path-1)
|
||||
n=n+1
|
||||
end
|
||||
|
||||
-- Debug output.
|
||||
self:I(string.format("SRS path=%s", self:GetPath()))
|
||||
end
|
||||
|
||||
-- Debug output.
|
||||
self:T(string.format("SRS path=%s", self:GetPath()))
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -579,6 +643,23 @@ function MSRS:SetVoice(Voice)
|
||||
|
||||
self.voice=Voice
|
||||
|
||||
--local defaultprovider = self.provider or self.GRPCOptions.DefaultProvider or MSRS.GRPCOptions.DefaultProvider or "win"
|
||||
|
||||
--self.GRPCOptions[defaultprovider].voice = Voice
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set to use a specific voice. Will override gender and culture settings.
|
||||
-- @param #MSRS self
|
||||
-- @param #string Voice Voice.
|
||||
-- @return #MSRS self
|
||||
function MSRS:SetDefaultVoice(Voice)
|
||||
|
||||
self.defaultVoice=Voice
|
||||
local provider = self.provider or self.GRPCOptions.DefaultProvider or MSRS.GRPCOptions.DefaultProvider or "win"
|
||||
self.GRPCOptions[provider].defaultVoice = Voice
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -595,12 +676,35 @@ end
|
||||
|
||||
--- Use google text-to-speech.
|
||||
-- @param #MSRS self
|
||||
-- @param PathToCredentials Full path to the google credentials JSON file, e.g. "C:\Users\username\Downloads\service-account-file.json".
|
||||
-- @param #string PathToCredentials Full path to the google credentials JSON file, e.g. "C:\Users\username\Downloads\service-account-file.json". Can also be the Google API key.
|
||||
-- @return #MSRS self
|
||||
function MSRS:SetGoogle(PathToCredentials)
|
||||
|
||||
self.google=PathToCredentials
|
||||
|
||||
if PathToCredentials then
|
||||
|
||||
self.google=PathToCredentials
|
||||
self.APIKey=PathToCredentials
|
||||
self.provider = "gcloud"
|
||||
|
||||
self.GRPCOptions.DefaultProvider = "gcloud"
|
||||
self.GRPCOptions.gcloud.key = PathToCredentials
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Use google text-to-speech.
|
||||
-- @param #MSRS self
|
||||
-- @param #string APIKey API Key, usually a string of length 40 with characters and numbers.
|
||||
-- @return #MSRS self
|
||||
function MSRS:SetGoogleAPIKey(APIKey)
|
||||
if APIKey then
|
||||
self.APIKey=APIKey
|
||||
self.provider = "gcloud"
|
||||
self.GRPCOptions.DefaultProvider = "gcloud"
|
||||
self.GRPCOptions.gcloud.key = APIKey
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -634,7 +738,7 @@ function MSRS:Help()
|
||||
end
|
||||
|
||||
--- Sets an alternate SRS backend to be used by MSRS to transmit over SRS for all new MSRS class instances.
|
||||
-- @param #table A table containing a table `Functions` with new/replacement class functions and `Vars` with new/replacement variables.
|
||||
-- @param #table Backend A table containing a table `Functions` with new/replacement class functions and `Vars` with new/replacement variables.
|
||||
-- @return #boolean Returns 'true' on success.
|
||||
function MSRS.SetDefaultBackend(Backend)
|
||||
if type(Backend) == "table" then
|
||||
@@ -1016,6 +1120,171 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
|
||||
return command
|
||||
end
|
||||
|
||||
--- Get central SRS configuration to be able to play tts over SRS radio using the `DCS-SR-ExternalAudio.exe`.
|
||||
-- @param #MSRS self
|
||||
-- @param #string Path Path to config file, defaults to "C:\Users\<yourname>\Saved Games\DCS\Config"
|
||||
-- @param #string Filename File to load, defaults to "Moose_MSRS.lua"
|
||||
-- @param #boolean ConfigLoaded - if true, skip the loading
|
||||
-- @return #boolean success
|
||||
-- @usage
|
||||
-- 0) Benefits: Centralize configuration of SRS, keep paths and keys out of the mission source code, making it safer and easier to move missions to/between servers,
|
||||
-- and also make config easier to use in the code.
|
||||
-- 1) Create a config file named "Moose_MSRS.lua" at this location "C:\Users\<yourname>\Saved Games\DCS\Config" (or wherever your Saved Games folder resides).
|
||||
-- 2) The file needs the following structure:
|
||||
--
|
||||
-- -- Moose MSRS default Config
|
||||
-- MSRS_Config = {
|
||||
-- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- adjust as needed
|
||||
-- Port = 5002, -- adjust as needed
|
||||
-- Frequency = {127,243}, -- must be a table, 1..n entries!
|
||||
-- Modulation = {0,0}, -- must be a table, 1..n entries, one for each frequency!
|
||||
-- Volume = 1.0,
|
||||
-- Coalition = 0, -- 0 = Neutral, 1 = Red, 2 = Blue
|
||||
-- Coordinate = {0,0,0}, -- x,y,alt - optional
|
||||
-- Culture = "en-GB",
|
||||
-- Gender = "male",
|
||||
-- Google = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourfilename.json", -- path to google json key file - optional
|
||||
-- Label = "MSRS",
|
||||
-- Voice = "Microsoft Hazel Desktop",
|
||||
-- -- gRPC (optional)
|
||||
-- GRPC = { -- see https://github.com/DCS-gRPC/rust-server
|
||||
-- coalition = "blue", -- blue, red, neutral
|
||||
-- DefaultProvider = "gcloud", -- win, gcloud, aws, or azure, some of the values below depend on your cloud provider
|
||||
-- gcloud = {
|
||||
-- key = "<API Google Key>", -- for gRPC Google API key
|
||||
-- --secret = "", -- needed for aws
|
||||
-- --region = "",-- needed for aws
|
||||
-- defaultVoice = MSRS.Voices.Google.Standard.en_GB_Standard_F,
|
||||
-- },
|
||||
-- win = {
|
||||
-- defaultVoice = "Hazel",
|
||||
-- },
|
||||
-- }
|
||||
-- }
|
||||
--
|
||||
-- 3) Load the config into the MSRS raw class before you do anything else:
|
||||
--
|
||||
-- MSRS.LoadConfigFile() -- Note the "." here
|
||||
--
|
||||
-- This will populate variables for the MSRS raw class and all instances you create with e.g. `mysrs = MSRS:New()`
|
||||
-- Optionally you can also load this per **single instance** if so needed, i.e.
|
||||
--
|
||||
-- mysrs:LoadConfig(Path,Filename)
|
||||
--
|
||||
-- 4) Use the config in your code like so, variable names are basically the same as in the config file, but all lower case, examples:
|
||||
--
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS(MSRS.path,nil,MSRS.google,243,radio.modulation.AM,nil,nil,
|
||||
-- MSRS.Voices.Google.Standard.de_DE_Standard_B,coalition.side.BLUE)
|
||||
--
|
||||
-- -- later on in your code
|
||||
--
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS(243,radio.modulation.AM,nil,nil,MSRS.Voices.Google.Standard.fr_FR_Standard_C)
|
||||
--
|
||||
-- -- Create new ATIS as usual
|
||||
-- atis=ATIS:New(AIRBASE.Caucasus.Batumi, 123, radio.modulation.AM)
|
||||
-- atis:SetSRS(nil,nil,nil,MSRS.Voices.Google.Standard.en_US_Standard_H)
|
||||
-- --Start ATIS
|
||||
-- atis:Start()
|
||||
function MSRS:LoadConfigFile(Path,Filename,ConfigLoaded)
|
||||
|
||||
local path = Path or lfs.writedir()..MSRS.ConfigFilePath
|
||||
local file = Filename or MSRS.ConfigFileName or "Moose_MSRS.lua"
|
||||
|
||||
if UTILS.CheckFileExists(path,file) and not ConfigLoaded then
|
||||
assert(loadfile(path..file))()
|
||||
-- now we should have a global var MSRS_Config
|
||||
if MSRS_Config then
|
||||
--[[
|
||||
-- Moose MSRS default Config
|
||||
MSRS_Config = {
|
||||
Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- adjust as needed
|
||||
Port = 5002, -- adjust as needed
|
||||
Frequency = {127,243}, -- must be a table, 1..n entries!
|
||||
Modulation = {0,0}, -- must be a table, 1..n entries, one for each frequency!
|
||||
Volume = 1.0,
|
||||
Coalition = 0, -- 0 = Neutral, 1 = Red, 2 = Blue
|
||||
Coordinate = {0,0,0}, -- x,y,alt - optional
|
||||
Culture = "en-GB",
|
||||
Gender = "male",
|
||||
Google = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourfilename.json", -- path to google json key file - optional
|
||||
Label = "MSRS",
|
||||
Voice = "Microsoft Hazel Desktop",
|
||||
-- gRPC (optional)
|
||||
GRPC = { -- see https://github.com/DCS-gRPC/rust-server
|
||||
coalition = "blue", -- blue, red, neutral
|
||||
DefaultProvider = "gcloud", -- win, gcloud, aws, or azure, some of the values below depend on your cloud provider
|
||||
gcloud = {
|
||||
key = "<API Google Key>", -- for gRPC Google API key
|
||||
--secret = "", -- needed for aws
|
||||
--region = "",-- needed for aws
|
||||
defaultVoice = MSRS.Voices.Google.Standard.en_GB_Standard_F,
|
||||
},
|
||||
win = {
|
||||
defaultVoice = "Hazel",
|
||||
},
|
||||
}
|
||||
}
|
||||
--]]
|
||||
if self then
|
||||
self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||
self.port = MSRS_Config.Port or 5002
|
||||
self.frequencies = MSRS_Config.Frequency or {127,243}
|
||||
self.modulations = MSRS_Config.Modulation or {0,0}
|
||||
self.coalition = MSRS_Config.Coalition or 0
|
||||
if MSRS_Config.Coordinate then
|
||||
self.coordinate = COORDINATE:New( MSRS_Config.Coordinate[1],MSRS_Config.Coordinate[2],MSRS_Config.Coordinate[3])
|
||||
end
|
||||
self.culture = MSRS_Config.Culture or "en-GB"
|
||||
self.gender = MSRS_Config.Gender or "male"
|
||||
self.google = MSRS_Config.Google
|
||||
self.Label = MSRS_Config.Label or "MSRS"
|
||||
self.voice = MSRS_Config.Voice or MSRS.Voices.Microsoft.Hazel
|
||||
if MSRS_Config.GRPC then
|
||||
self.provider = MSRS_Config.GRPC.DefaultProvider
|
||||
if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then
|
||||
self.APIKey = MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider].key
|
||||
self.defaultVoice = MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider].defaultVoice
|
||||
self.region = MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider].secret
|
||||
self.secret = MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider].region
|
||||
end
|
||||
end
|
||||
self.ConfigLoaded = true
|
||||
else
|
||||
MSRS.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||
MSRS.port = MSRS_Config.Port or 5002
|
||||
MSRS.frequencies = MSRS_Config.Frequency or {127,243}
|
||||
MSRS.modulations = MSRS_Config.Modulation or {0,0}
|
||||
MSRS.coalition = MSRS_Config.Coalition or 0
|
||||
if MSRS_Config.Coordinate then
|
||||
MSRS.coordinate = COORDINATE:New( MSRS_Config.Coordinate[1],MSRS_Config.Coordinate[2],MSRS_Config.Coordinate[3])
|
||||
end
|
||||
MSRS.culture = MSRS_Config.Culture or "en-GB"
|
||||
MSRS.gender = MSRS_Config.Gender or "male"
|
||||
MSRS.google = MSRS_Config.Google
|
||||
MSRS.Label = MSRS_Config.Label or "MSRS"
|
||||
MSRS.voice = MSRS_Config.Voice or MSRS.Voices.Microsoft.Hazel
|
||||
if MSRS_Config.GRPC then
|
||||
MSRS.provider = MSRS_Config.GRPC.DefaultProvider
|
||||
if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then
|
||||
MSRS.APIKey = MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider].key
|
||||
MSRS.defaultVoice = MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider].defaultVoice
|
||||
MSRS.region = MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider].secret
|
||||
MSRS.secret = MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider].region
|
||||
end
|
||||
end
|
||||
MSRS.ConfigLoaded = true
|
||||
end
|
||||
end
|
||||
env.info("MSRS - Sucessfully loaded default configuration from disk!",false)
|
||||
else
|
||||
env.info("MSRS - Cannot load default configuration from disk!",false)
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- MSRS DCS-gRPC alternate backend
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1194,7 +1463,7 @@ MSRS_BACKEND_DCSGRPC.Functions.PlayTextExt = function (self, Text, Delay, Freque
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, self.PlayTextExt, self, Text, 0, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label)
|
||||
else
|
||||
self:_DCSgRPCtts(tostring(Text, nil, Frequencies, Voice, Label))
|
||||
self:_DCSgRPCtts(tostring(Text), nil, Frequencies, Voice, Label)
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -1260,7 +1529,7 @@ MSRS_BACKEND_DCSGRPC.Functions._DCSgRPCtts = function (self, Text, Plaintext, Fr
|
||||
BASE:T("MSRS_BACKEND_DCSGRPC:_DCSgRPCtts()")
|
||||
BASE:T({Text, Plaintext, Frequencies, Voice, Label})
|
||||
|
||||
local options = {}
|
||||
local options = self.ProviderOptions or MSRS.ProviderOptions or {} -- #MSRS.GRPCOptions
|
||||
local ssml = Text or ''
|
||||
|
||||
local XmitFrequencies = Frequencies or self.Frequency
|
||||
@@ -1272,7 +1541,7 @@ MSRS_BACKEND_DCSGRPC.Functions._DCSgRPCtts = function (self, Text, Plaintext, Fr
|
||||
options.srsClientName = Label or self.Label
|
||||
options.position = {}
|
||||
if self.coordinate then
|
||||
options.position.lat, options.position.lat, options.position.alt = self:_GetLatLongAlt(self.coordinate)
|
||||
options.position.lat, options.position.lon, options.position.alt = self:_GetLatLongAlt(self.coordinate)
|
||||
end
|
||||
|
||||
options.position.lat = options.position.lat or 0.0
|
||||
@@ -1284,12 +1553,23 @@ MSRS_BACKEND_DCSGRPC.Functions._DCSgRPCtts = function (self, Text, Plaintext, Fr
|
||||
elseif UTILS.GetCoalitionName(self.coalition) == 'Red' then
|
||||
options.coalition = 'red'
|
||||
end
|
||||
|
||||
|
||||
local provider = self.provider or self.GRPCOptions.DefaultProvider or MSRS.GRPCOptions.DefaultProvider
|
||||
|
||||
options.provider = {}
|
||||
options.provider[self.provider] = {}
|
||||
|
||||
|
||||
options.provider[provider] = {}
|
||||
|
||||
if self.APIKey then
|
||||
options.provider[provider].key = self.APIKey
|
||||
end
|
||||
|
||||
if self.defaultVoice then
|
||||
options.provider[provider].defaultVoice = self.defaultVoice
|
||||
end
|
||||
|
||||
if self.voice then
|
||||
options.provider[self.provider].voice = Voice or self.voice
|
||||
options.provider[provider].voice = Voice or self.voice or self.defaultVoice
|
||||
elseif ssml then
|
||||
-- DCS-gRPC doesn't directly support language/gender, but can use SSML
|
||||
-- Only use if a voice isn't explicitly set
|
||||
@@ -1315,7 +1595,7 @@ MSRS_BACKEND_DCSGRPC.Functions._DCSgRPCtts = function (self, Text, Plaintext, Fr
|
||||
BASE:T("GRPC.tts")
|
||||
BASE:T(ssml)
|
||||
BASE:T(freq)
|
||||
BASE:T(options)
|
||||
BASE:T({options})
|
||||
GRPC.tts(ssml, freq, options)
|
||||
end
|
||||
|
||||
|
||||
@@ -162,7 +162,12 @@
|
||||
-- choose from 2 added menu options either to accept or reject the assigned task within 30 seconds.
|
||||
-- If the task is not accepted within 30 seconds; the task will be cancelled and a new task will be assigned.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #COMMANDCENTER
|
||||
COMMANDCENTER = {
|
||||
ClassName = "COMMANDCENTER",
|
||||
|
||||
@@ -32,7 +32,12 @@
|
||||
-- -------------------------------
|
||||
-- The @{#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Contributions: Mechanist, Prof_Hilactic, FlightControl - Concept & Testing
|
||||
|
||||
@@ -117,7 +117,12 @@
|
||||
-- - @{#MISSION.ReportPlayersPerTask}(): Generates a report showing the active players per task.
|
||||
-- - @{#MISSION.ReportPlayersProgress}(): Generates a report showing the task progress per player.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #MISSION
|
||||
MISSION = {
|
||||
ClassName = "MISSION",
|
||||
|
||||
@@ -203,7 +203,12 @@
|
||||
--
|
||||
-- These different completion states are important for the mission designer to reflect scoring to a player.
|
||||
-- A success could mean a positive score to be given, while a failure could mean a negative score or penalties to be awarded.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author(s): **FlightControl**
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
-- # TASKINFO class, extends @{Core.Base#BASE}
|
||||
--
|
||||
-- ## The TASKINFO class implements the methods to contain information and display information of a task.
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #TASKINFO
|
||||
TASKINFO = {
|
||||
ClassName = "TASKINFO",
|
||||
|
||||
@@ -35,6 +35,11 @@ do -- TASK_A2A
|
||||
-- * @{#TASK_A2A.SetScoreOnDestroy}(): Set a score when a target in scope of the A2A attack, has been destroyed.
|
||||
-- * @{#TASK_A2A.SetScoreOnSuccess}(): Set a score when all the targets in scope of the A2A attack, have been destroyed.
|
||||
-- * @{#TASK_A2A.SetPenaltyOnFailed}(): Set a penalty when the A2A attack has failed.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #TASK_A2A
|
||||
TASK_A2A = {
|
||||
|
||||
@@ -176,6 +176,11 @@ do -- TASK_A2A_DISPATCHER
|
||||
-- * @{Tasking.Task#TASK.SetScoreOnSuccess}() will add additional (negative) scores when the task goes into **Failed** state.
|
||||
-- This means the **task has not been successfully completed**, and the scores must be given with a negative value!
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #TASK_A2A_DISPATCHER
|
||||
TASK_A2A_DISPATCHER = {
|
||||
ClassName = "TASK_A2A_DISPATCHER",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user