mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Compare commits
376 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd155f8277 | ||
|
|
531132e8a7 | ||
|
|
7464406a17 | ||
|
|
bd5c1af335 | ||
|
|
53f556a4e6 | ||
|
|
0ddf8762c2 | ||
|
|
2893bfb290 | ||
|
|
d984a1b142 | ||
|
|
f02b774242 | ||
|
|
5ede860361 | ||
|
|
d0d52246f4 | ||
|
|
748aa131e4 | ||
|
|
1b4e170271 | ||
|
|
a3d56b6d1b | ||
|
|
33bd928076 | ||
|
|
23df6bbc2a | ||
|
|
f2fc321ded | ||
|
|
0b3fc515e0 | ||
|
|
e50d54f6bc | ||
|
|
6e60a66d0c | ||
|
|
11f0b2899d | ||
|
|
581138b5bc | ||
|
|
0ce3a189c3 | ||
|
|
08f2c29014 | ||
|
|
9208d7a70d | ||
|
|
4076ff5bb5 | ||
|
|
dcd4d0ab62 | ||
|
|
056b761ebc | ||
|
|
298c569f93 | ||
|
|
32dbb520d6 | ||
|
|
6af66db4c3 | ||
|
|
ff84d682bd | ||
|
|
d2b7d46227 | ||
|
|
58f4eead1c | ||
|
|
f3bafd5803 | ||
|
|
bb07e1935e | ||
|
|
2946c2e225 | ||
|
|
088436c5ce | ||
|
|
2e386be2f6 | ||
|
|
797bf0047b | ||
|
|
9c0c93507a | ||
|
|
f29d055ca3 | ||
|
|
baf7123364 | ||
|
|
1468641563 | ||
|
|
f6b6a6a577 | ||
|
|
4d7d34b71f | ||
|
|
82bea9d5ff | ||
|
|
35d91c9c94 | ||
|
|
8b08942c4d | ||
|
|
a44ad5c755 | ||
|
|
b7236eeb58 | ||
|
|
eb84ad3cee | ||
|
|
09933b307b | ||
|
|
91a34ac4d8 | ||
|
|
21babb548c | ||
|
|
11967bd608 | ||
|
|
ea6e63dc9b | ||
|
|
28c8d99878 | ||
|
|
547579ffb0 | ||
|
|
4fda8cc5fb | ||
|
|
697042eac6 | ||
|
|
30d6936f1d | ||
|
|
4ac583e434 | ||
|
|
b315375ade | ||
|
|
e26647c2ca | ||
|
|
4ddd278471 | ||
|
|
72e31b90a9 | ||
|
|
fa762fe0fc | ||
|
|
aca5846209 | ||
|
|
4fd7d7cba9 | ||
|
|
677d888d96 | ||
|
|
06c3ca0079 | ||
|
|
9280a1224d | ||
|
|
406dbb707a | ||
|
|
4758af61c2 | ||
|
|
729c1f5e33 | ||
|
|
fce7b07014 | ||
|
|
8386fe5f67 | ||
|
|
4696569f83 | ||
|
|
2c695e187f | ||
|
|
048ab6acfe | ||
|
|
84230e2360 | ||
|
|
f2783c46c2 | ||
|
|
ca9913e38b | ||
|
|
df1bc5c55d | ||
|
|
ff951c69d9 | ||
|
|
e53a80783e | ||
|
|
a1fb09285b | ||
|
|
f2f7c88299 | ||
|
|
e2bf1f727d | ||
|
|
65315251b5 | ||
|
|
2a9e98c21e | ||
|
|
b40c1e4575 | ||
|
|
a9befc4d96 | ||
|
|
f5d6d31b10 | ||
|
|
65fb22b6cc | ||
|
|
d0346c4aa3 | ||
|
|
96da09b9e0 | ||
|
|
c1d468b35f | ||
|
|
109270d717 | ||
|
|
f80e7a2166 | ||
|
|
9b95e71d75 | ||
|
|
de6c7d636b | ||
|
|
f57beab6d2 | ||
|
|
29414bfd21 | ||
|
|
60b8a5f5af | ||
|
|
db6dc7b77e | ||
|
|
aaf3553597 | ||
|
|
4e50bd213c | ||
|
|
c813e2dbc4 | ||
|
|
4c81333a0a | ||
|
|
761d83a68f | ||
|
|
3d93c268b3 | ||
|
|
79b1f1615f | ||
|
|
d6a0fff993 | ||
|
|
8d45ea00e8 | ||
|
|
47f010cb28 | ||
|
|
2d17c4d21a | ||
|
|
d14b7e8f4c | ||
|
|
d8b046491b | ||
|
|
d9748ef147 | ||
|
|
b20eb84d19 | ||
|
|
64d7946c06 | ||
|
|
c2be4fbcf1 | ||
|
|
b052fc6243 | ||
|
|
8385b1d21a | ||
|
|
58d9637c5d | ||
|
|
d4f4465b0a | ||
|
|
5fe77956cb | ||
|
|
e0a108e00d | ||
|
|
d640acc7cc | ||
|
|
acf37f6133 | ||
|
|
8dcd22f18c | ||
|
|
2d086a62f0 | ||
|
|
47ad2499d4 | ||
|
|
5d510807c9 | ||
|
|
dd771a089c | ||
|
|
3f927b16e5 | ||
|
|
5ba8f9e0e8 | ||
|
|
833a0561c3 | ||
|
|
0338fd5d33 | ||
|
|
ea2175bba8 | ||
|
|
cf48b21073 | ||
|
|
0835022c5c | ||
|
|
a70ad71689 | ||
|
|
f306361317 | ||
|
|
0347e42fc7 | ||
|
|
7557e79c0c | ||
|
|
9cc32ff8dc | ||
|
|
1b7eef5419 | ||
|
|
029bdc3bd1 | ||
|
|
b052d99349 | ||
|
|
93acd870ea | ||
|
|
4fe1318e7c | ||
|
|
93cdb92e76 | ||
|
|
6ffe69484c | ||
|
|
39b89d937e | ||
|
|
501ab70992 | ||
|
|
b488d43d78 | ||
|
|
6ac46addf0 | ||
|
|
33259be4d9 | ||
|
|
e4cea7b3c4 | ||
|
|
3bdf4b4c76 | ||
|
|
6f5f89a0ee | ||
|
|
46f70dd8a6 | ||
|
|
e2e9bd7de0 | ||
|
|
1b01b89343 | ||
|
|
4e36ed170b | ||
|
|
bf0ad93bf7 | ||
|
|
a51afeda14 | ||
|
|
e46b148721 | ||
|
|
8765ebe2c6 | ||
|
|
b55b11be09 | ||
|
|
2a7dbad02a | ||
|
|
aeac2eb3d7 | ||
|
|
e83c8c3ee0 | ||
|
|
d65042c640 | ||
|
|
c72cdd8f0b | ||
|
|
7e2f8771b5 | ||
|
|
3ccfcdbd0f | ||
|
|
44b3f41ae4 | ||
|
|
c5dec374c8 | ||
|
|
3f384d72ab | ||
|
|
1d5952b4a5 | ||
|
|
8eec7fcc9e | ||
|
|
db7e94d879 | ||
|
|
16f3dcbbb4 | ||
|
|
f482dac491 | ||
|
|
f6f3189504 | ||
|
|
73fa021476 | ||
|
|
071554bfc5 | ||
|
|
cd8abd97c5 | ||
|
|
1527b53c76 | ||
|
|
e25eeee0cc | ||
|
|
bbc7f7e14c | ||
|
|
0261020796 | ||
|
|
b9830a8437 | ||
|
|
257530d421 | ||
|
|
caaee4f551 | ||
|
|
5f7115f4fe | ||
|
|
9ec92a8fca | ||
|
|
a14435ce54 | ||
|
|
e82e4f7dd7 | ||
|
|
c7ef270d4d | ||
|
|
7cc040c234 | ||
|
|
9227ba9ecd | ||
|
|
a9a56b3738 | ||
|
|
e7fb073bab | ||
|
|
0d1fc2fbf2 | ||
|
|
f86b3505b2 | ||
|
|
e89b921f3e | ||
|
|
0d18ce086c | ||
|
|
8fb126682f | ||
|
|
63a0224ea4 | ||
|
|
ebe486c69a | ||
|
|
69fa6f4ee6 | ||
|
|
702ec75935 | ||
|
|
1c4e3cb801 | ||
|
|
465ec216ea | ||
|
|
ab516e0cd8 | ||
|
|
d803b51e84 | ||
|
|
53f89fd42c | ||
|
|
c72f109553 | ||
|
|
f2ba2022c2 | ||
|
|
92e03522db | ||
|
|
9716162739 | ||
|
|
4eea8fcadd | ||
|
|
5b7e0ce375 | ||
|
|
0ae9be49da | ||
|
|
c250712e53 | ||
|
|
bda4efc634 | ||
|
|
566ebb67e3 | ||
|
|
e84e16f58b | ||
|
|
55ffe37a79 | ||
|
|
6c21dfa48c | ||
|
|
b31fc3ed44 | ||
|
|
68548f4581 | ||
|
|
42fd2322d2 | ||
|
|
8382eb9cd8 | ||
|
|
585901dc7d | ||
|
|
2a7213c1b7 | ||
|
|
f837e9dec7 | ||
|
|
cd4fb0c6c5 | ||
|
|
b8d44643c1 | ||
|
|
230d9d82bf | ||
|
|
47d01f18c1 | ||
|
|
c089e56060 | ||
|
|
8a1c9c0e54 | ||
|
|
87f1a5ed0d | ||
|
|
a4fd55e87d | ||
|
|
d2d6fac7df | ||
|
|
5243a408cc | ||
|
|
bc3f9ed7c0 | ||
|
|
b224739df3 | ||
|
|
0f4162a9a9 | ||
|
|
ff26e4d1dc | ||
|
|
6b270916c4 | ||
|
|
1f17fd89a4 | ||
|
|
b3a006096c | ||
|
|
a8e35a552d | ||
|
|
6903e252d2 | ||
|
|
6ee1afc670 | ||
|
|
ff6704f123 | ||
|
|
3b8bbdd4c1 | ||
|
|
c770f4cb68 | ||
|
|
7e5a97e7c7 | ||
|
|
9ce1d360d6 | ||
|
|
f342ba758e | ||
|
|
6f473faa92 | ||
|
|
dd37a42470 | ||
|
|
018d8eecf6 | ||
|
|
fe9d841af5 | ||
|
|
88e1bbd60d | ||
|
|
d0491b3b5a | ||
|
|
e078e48853 | ||
|
|
f789fbac70 | ||
|
|
bc3a5271dc | ||
|
|
4d4b8862c2 | ||
|
|
31b75b7d17 | ||
|
|
fac7a5fdc6 | ||
|
|
cca5a5d55d | ||
|
|
3243c92331 | ||
|
|
49191fb144 | ||
|
|
eab37d5e48 | ||
|
|
f739062463 | ||
|
|
e838431b28 | ||
|
|
c22304f2b0 | ||
|
|
1c10bfea92 | ||
|
|
c97d2ecaba | ||
|
|
2dc9f19d78 | ||
|
|
89a9d1d0a4 | ||
|
|
cf7d41cd7f | ||
|
|
fd191be274 | ||
|
|
31bdde130a | ||
|
|
afe542cc63 | ||
|
|
494550fe91 | ||
|
|
29c0d81c27 | ||
|
|
e79c2481da | ||
|
|
89a902fd57 | ||
|
|
460ad9db39 | ||
|
|
ae604fd847 | ||
|
|
099f059eec | ||
|
|
c3bba7d1fc | ||
|
|
db71610d72 | ||
|
|
4b8d120f20 | ||
|
|
1dc31cc852 | ||
|
|
68b97773fe | ||
|
|
3c0e977584 | ||
|
|
f03a48b118 | ||
|
|
c489a88106 | ||
|
|
4747dae51a | ||
|
|
b1e8ba74a8 | ||
|
|
641707f37b | ||
|
|
67924c894d | ||
|
|
52ed645f6c | ||
|
|
7c8f212b03 | ||
|
|
9f41cc51be | ||
|
|
85c73cb0a5 | ||
|
|
1b1f8e0d2c | ||
|
|
f87126f22c | ||
|
|
6390b223b0 | ||
|
|
b635490e47 | ||
|
|
62e8302753 | ||
|
|
cac7b39823 | ||
|
|
cc79dc74d4 | ||
|
|
af3c579a03 | ||
|
|
a508c63279 | ||
|
|
427a11bd0f | ||
|
|
6f3133d48c | ||
|
|
4f4e8b17c1 | ||
|
|
aa7f26ac79 | ||
|
|
084caad5d7 | ||
|
|
0850796368 | ||
|
|
343bf05c2c | ||
|
|
ff58649954 | ||
|
|
bbf793febe | ||
|
|
3e40d72e25 | ||
|
|
1c1daa4ebe | ||
|
|
fdcda6e5f3 | ||
|
|
a50dde7f2b | ||
|
|
1fb4cb1c4f | ||
|
|
cd0f854f41 | ||
|
|
52c2401d93 | ||
|
|
f071c674d0 | ||
|
|
02a87d9fe0 | ||
|
|
3c53f627c2 | ||
|
|
12d68a41ca | ||
|
|
2dfde7d1fd | ||
|
|
c011d38313 | ||
|
|
6c4a64601f | ||
|
|
68350d6824 | ||
|
|
434f985e77 | ||
|
|
2e6cac7bee | ||
|
|
ba1dcfcdba | ||
|
|
b346dabdf8 | ||
|
|
a0429458d0 | ||
|
|
1376a16812 | ||
|
|
847dc1839f | ||
|
|
4267314260 | ||
|
|
b5110c8554 | ||
|
|
0dd4da1db4 | ||
|
|
1f1d1e4f2f | ||
|
|
4d4f8e9d61 | ||
|
|
522eb8b256 | ||
|
|
6fe883a17a | ||
|
|
b662ecc76b | ||
|
|
fbbdac9b7e | ||
|
|
6dd69eb6db | ||
|
|
1b6aeff005 | ||
|
|
de380614fb | ||
|
|
4287774d9f | ||
|
|
f6fdff927b | ||
|
|
58ce4b001e | ||
|
|
6bba2fec0b | ||
|
|
5d2656d679 | ||
|
|
9a360a3bd5 |
8
.github/workflows/build-includes.yml
vendored
8
.github/workflows/build-includes.yml
vendored
@@ -95,10 +95,6 @@ jobs:
|
|||||||
export COMMIT_TIME=$(git show -s --format=%cd ${{ github.sha }} --date=iso-strict)
|
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"
|
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
|
# Run LuaCheck
|
||||||
#########################################################################
|
#########################################################################
|
||||||
@@ -108,6 +104,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
luacheck --std=lua51c --config=.luacheckrc -gurasqq "Moose Development/Moose"
|
luacheck --std=lua51c --config=.luacheckrc -gurasqq "Moose Development/Moose"
|
||||||
|
|
||||||
|
- name: Run LuaSrcDiet
|
||||||
|
run: |
|
||||||
|
luasrcdiet --basic --opt-emptylines ./build/result/Moose_Include_Static/Moose.lua -o ./build/result/Moose_Include_Static/Moose_.lua
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# Push to MOOSE_INCLUDE
|
# Push to MOOSE_INCLUDE
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|||||||
2
.github/workflows/gh-pages.yml
vendored
2
.github/workflows/gh-pages.yml
vendored
@@ -75,4 +75,4 @@ jobs:
|
|||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
- run: npm install linkinator
|
- run: npm install linkinator
|
||||||
- run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --verbosity error --timeout 5000 --recurse --skip "(java.com)"
|
- run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --verbosity error --timeout 5000 --recurse --skip "(java.com)" --retry-errors --retry-errors-count 3 --retry-errors-jitter
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -228,6 +228,9 @@ pip-log.txt
|
|||||||
#Goodsync
|
#Goodsync
|
||||||
_gsdata_/
|
_gsdata_/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
.idea
|
||||||
|
|
||||||
#GITHUB
|
#GITHUB
|
||||||
Moose Test Missions/MOOSE_Test_Template.miz
|
Moose Test Missions/MOOSE_Test_Template.miz
|
||||||
Moose Development/Moose/.vscode/launch.json
|
Moose Development/Moose/.vscode/launch.json
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [AID-A2A - AI A2A Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching)
|
-- [AID-A2A - AI A2A Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -310,7 +310,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to set a specific Engage Radius.
|
-- Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to set a specific Engage Radius.
|
||||||
-- **The Engage Radius is defined for ALL squadrons which are operational.**
|
-- **The Engage Radius is defined for ALL squadrons which are operational.**
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-019%20-%20Engage%20Range%20Test)
|
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-019%20-%20Engage%20Range%20Test)
|
||||||
--
|
--
|
||||||
-- In this example an Engage Radius is set to various values.
|
-- In this example an Engage Radius is set to various values.
|
||||||
--
|
--
|
||||||
@@ -333,7 +333,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
|
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
|
||||||
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
|
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-013%20-%20Intercept%20Test)
|
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-013%20-%20Intercept%20Test)
|
||||||
--
|
--
|
||||||
-- In these examples, the Gci Radius is set to various values:
|
-- In these examples, the Gci Radius is set to various values:
|
||||||
--
|
--
|
||||||
@@ -366,7 +366,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are.
|
-- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are.
|
||||||
-- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition.
|
-- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition.
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-009 - AI_A2A - Border Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-009%20-%20Border%20Test)
|
-- Demonstration Mission: [AID-009 - AI_A2A - Border Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-009%20-%20Border%20Test)
|
||||||
--
|
--
|
||||||
-- In this example a border is set for the CCCP A2A dispatcher:
|
-- In this example a border is set for the CCCP A2A dispatcher:
|
||||||
--
|
--
|
||||||
@@ -1233,7 +1233,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
--
|
--
|
||||||
-- **Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to modify the default Engage Radius for ALL squadrons.**
|
-- **Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to modify the default Engage Radius for ALL squadrons.**
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-019%20-%20Engage%20Range%20Test)
|
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-019%20-%20Engage%20Range%20Test)
|
||||||
--
|
--
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
-- @param #number EngageRadius (Optional, Default = 100000) The radius to report friendlies near the target.
|
-- @param #number EngageRadius (Optional, Default = 100000) The radius to report friendlies near the target.
|
||||||
@@ -1283,7 +1283,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
|
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
|
||||||
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
|
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-013%20-%20Intercept%20Test)
|
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-013%20-%20Intercept%20Test)
|
||||||
--
|
--
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
-- @param #number GciRadius (Optional, Default = 200000) The radius to ground control intercept detected targets from the nearest airbase.
|
-- @param #number GciRadius (Optional, Default = 200000) The radius to ground control intercept detected targets from the nearest airbase.
|
||||||
@@ -3257,7 +3257,8 @@ do -- AI_A2A_DISPATCHER
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
--- AI_A2A_Fsm:onafterHome
|
||||||
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action )
|
function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action )
|
||||||
if Defender and Defender:IsAlive() then
|
if Defender and Defender:IsAlive() then
|
||||||
self:F( { "CAP Home", Defender:GetName() } )
|
self:F( { "CAP Home", Defender:GetName() } )
|
||||||
@@ -3505,7 +3506,8 @@ do -- AI_A2A_DISPATCHER
|
|||||||
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
--- function Fsm:onafterLostControl
|
||||||
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function Fsm:onafterLostControl( Defender, From, Event, To )
|
function Fsm:onafterLostControl( Defender, From, Event, To )
|
||||||
self:F( { "GCI LostControl", Defender:GetName() } )
|
self:F( { "GCI LostControl", Defender:GetName() } )
|
||||||
self:GetParent( self ).onafterHome( self, Defender, From, Event, To )
|
self:GetParent( self ).onafterHome( self, Defender, From, Event, To )
|
||||||
@@ -3518,7 +3520,8 @@ do -- AI_A2A_DISPATCHER
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
--- function Fsm:onafterHome
|
||||||
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function Fsm:onafterHome( DefenderGroup, From, Event, To, Action )
|
function Fsm:onafterHome( DefenderGroup, From, Event, To, Action )
|
||||||
self:F( { "GCI Home", DefenderGroup:GetName() } )
|
self:F( { "GCI Home", DefenderGroup:GetName() } )
|
||||||
self:GetParent( self ).onafterHome( self, DefenderGroup, From, Event, To )
|
self:GetParent( self ).onafterHome( self, DefenderGroup, From, Event, To )
|
||||||
@@ -3959,7 +3962,7 @@ do
|
|||||||
--
|
--
|
||||||
-- # Demo Missions
|
-- # Demo Missions
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [AID-A2G - AI A2G Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2G%20-%20AI%20A2G%20Dispatching)
|
-- [AID-A2G - AI A2G Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2G_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [AID-AIR - AI AIR Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching)
|
-- [AI_A2A_Dispatcher](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/BAI%20-%20Battlefield%20Air%20Interdiction)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_BAI)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AIB%20-%20AI%20Balancing)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_Balancer)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -168,7 +168,8 @@ function AI_BALANCER:ReturnToHomeAirbase( ReturnThresholdRange )
|
|||||||
self.ReturnThresholdRange = ReturnThresholdRange
|
self.ReturnThresholdRange = ReturnThresholdRange
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_BALANCER self
|
--- AI_BALANCER:onenterSpawning
|
||||||
|
-- @param #AI_BALANCER self
|
||||||
-- @param Core.Set#SET_GROUP SetGroup
|
-- @param Core.Set#SET_GROUP SetGroup
|
||||||
-- @param #string ClientName
|
-- @param #string ClientName
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param Wrapper.Group#GROUP AIGroup
|
||||||
@@ -190,7 +191,8 @@ function AI_BALANCER:onenterSpawning( SetGroup, From, Event, To, ClientName )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_BALANCER self
|
--- AI_BALANCER:onenterDestroying
|
||||||
|
-- @param #AI_BALANCER self
|
||||||
-- @param Core.Set#SET_GROUP SetGroup
|
-- @param Core.Set#SET_GROUP SetGroup
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param Wrapper.Group#GROUP AIGroup
|
||||||
function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, ClientName, AIGroup )
|
function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, ClientName, AIGroup )
|
||||||
@@ -233,15 +235,16 @@ function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- AI_BALANCER:onenterMonitoring
|
||||||
--- @param #AI_BALANCER self
|
-- @param #AI_BALANCER self
|
||||||
function AI_BALANCER:onenterMonitoring( SetGroup )
|
function AI_BALANCER:onenterMonitoring( SetGroup )
|
||||||
|
|
||||||
self:T2( { self.SetClient:Count() } )
|
self:T2( { self.SetClient:Count() } )
|
||||||
--self.SetClient:Flush()
|
--self.SetClient:Flush()
|
||||||
|
|
||||||
self.SetClient:ForEachClient(
|
self.SetClient:ForEachClient(
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
--- SetClient:ForEachClient
|
||||||
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
function( Client )
|
function( Client )
|
||||||
self:T3(Client.ClientName)
|
self:T3(Client.ClientName)
|
||||||
|
|
||||||
@@ -264,7 +267,8 @@ function AI_BALANCER:onenterMonitoring( SetGroup )
|
|||||||
self:T2( RangeZone )
|
self:T2( RangeZone )
|
||||||
|
|
||||||
_DATABASE:ForEachPlayerUnit(
|
_DATABASE:ForEachPlayerUnit(
|
||||||
--- @param Wrapper.Unit#UNIT RangeTestUnit
|
--- Nameless function
|
||||||
|
-- @param Wrapper.Unit#UNIT RangeTestUnit
|
||||||
function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange )
|
function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange )
|
||||||
self:T2( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } )
|
self:T2( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } )
|
||||||
if RangeTestUnit:IsInZone( RangeZone ) == true then
|
if RangeTestUnit:IsInZone( RangeZone ) == true then
|
||||||
@@ -276,7 +280,8 @@ function AI_BALANCER:onenterMonitoring( SetGroup )
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- @param Core.Zone#ZONE_RADIUS RangeZone
|
--- Nameless function
|
||||||
|
-- @param Core.Zone#ZONE_RADIUS RangeZone
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param Wrapper.Group#GROUP AIGroup
|
||||||
function( RangeZone, AIGroup, PlayerInRange )
|
function( RangeZone, AIGroup, PlayerInRange )
|
||||||
if PlayerInRange.Value == false then
|
if PlayerInRange.Value == false then
|
||||||
@@ -307,6 +312,3 @@ function AI_BALANCER:onenterMonitoring( SetGroup )
|
|||||||
|
|
||||||
self:__Monitor( 10 )
|
self:__Monitor( 10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAP%20-%20Combat%20Air%20Patrol)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_CAP)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAS%20-%20Close%20Air%20Support)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_CAS)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
--
|
--
|
||||||
-- Test missions can be located on the main GITHUB site.
|
-- Test missions can be located on the main GITHUB site.
|
||||||
--
|
--
|
||||||
-- [FlightControl-Master/MOOSE_MISSIONS/AID - AI Dispatching/AID-CGO - AI Cargo Dispatching/](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/AID%20-%20AI%20Dispatching/AID-CGO%20-%20AI%20Cargo%20Dispatching)
|
-- [FlightControl-Master/MOOSE_MISSIONS/AID - AI Dispatching/AID-CGO - AI Cargo Dispatching/](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_Cargo_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -572,7 +572,7 @@
|
|||||||
-- A home zone can be specified to where the Carriers will move when there isn't any cargo left for pickup.
|
-- A home zone can be specified to where the Carriers will move when there isn't any cargo left for pickup.
|
||||||
-- Use @{#AI_CARGO_DISPATCHER.SetHomeZone}() to specify the home zone.
|
-- Use @{#AI_CARGO_DISPATCHER.SetHomeZone}() to specify the home zone.
|
||||||
--
|
--
|
||||||
-- If no home zone is specified, the carriers will wait near the deploy zone for a new pickup command.
|
-- If no home zone is specified, the carriers will wait near the deploy zone for a new pickup command.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -583,10 +583,12 @@ AI_CARGO_DISPATCHER = {
|
|||||||
PickupCargo = {}
|
PickupCargo = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #list
|
--- List of AI_Cargo
|
||||||
|
-- @field #list
|
||||||
AI_CARGO_DISPATCHER.AI_Cargo = {}
|
AI_CARGO_DISPATCHER.AI_Cargo = {}
|
||||||
|
|
||||||
--- @field #list
|
--- List of PickupCargo
|
||||||
|
-- @field #list
|
||||||
AI_CARGO_DISPATCHER.PickupCargo = {}
|
AI_CARGO_DISPATCHER.PickupCargo = {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [ESC - Escorting](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/ESC%20-%20Escorting)
|
-- [ESC - Escorting](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_Escort)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [ESC - Escorting](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/ESC%20-%20Escorting)
|
-- [ESC - Escorting](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_Escort)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
-- * Assign a group leader that will guide the large formation path.
|
-- * Assign a group leader that will guide the large formation path.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/FOR%20-%20AI%20Group%20Formation)
|
-- ## Additional Material:
|
||||||
--
|
--
|
||||||
-- ===
|
-- * **Demo Missions:** [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_Formation)
|
||||||
--
|
-- * **YouTube videos:** [Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0bFIJ9jIdYM22uaWmIN4oz)
|
||||||
-- ### [YouTube Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0bFIJ9jIdYM22uaWmIN4oz)
|
-- * **Guides:** None
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/PAT%20-%20Patrolling)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_Patrol)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ CARGOS = {}
|
|||||||
|
|
||||||
do -- CARGO
|
do -- CARGO
|
||||||
|
|
||||||
--- @type CARGO
|
-- @type CARGO
|
||||||
-- @extends Core.Fsm#FSM_PROCESS
|
-- @extends Core.Fsm#FSM_PROCESS
|
||||||
-- @field #string Type A string defining the type of the cargo. eg. Engineers, Equipment, Screwdrivers.
|
-- @field #string Type A string defining the type of the cargo. eg. Engineers, Equipment, Screwdrivers.
|
||||||
-- @field #string Name A string defining the name of the cargo. The name is the unique identifier of the cargo.
|
-- @field #string Name A string defining the name of the cargo. The name is the unique identifier of the cargo.
|
||||||
@@ -433,7 +433,7 @@ do -- CARGO
|
|||||||
Reported = {},
|
Reported = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @type CARGO.CargoObjects
|
-- @type CARGO.CargoObjects
|
||||||
-- @map < #string, Wrapper.Positionable#POSITIONABLE > The alive POSITIONABLE objects representing the the cargo.
|
-- @map < #string, Wrapper.Positionable#POSITIONABLE > The alive POSITIONABLE objects representing the the cargo.
|
||||||
|
|
||||||
--- CARGO Constructor. This class is an abstract class and should not be instantiated.
|
--- CARGO Constructor. This class is an abstract class and should not be instantiated.
|
||||||
@@ -447,7 +447,7 @@ do -- CARGO
|
|||||||
function CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) --R2.1
|
function CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) --R2.1
|
||||||
|
|
||||||
local self = BASE:Inherit( self, FSM:New() ) -- #CARGO
|
local self = BASE:Inherit( self, FSM:New() ) -- #CARGO
|
||||||
self:F( { Type, Name, Weight, LoadRadius, NearRadius } )
|
self:T( { Type, Name, Weight, LoadRadius, NearRadius } )
|
||||||
|
|
||||||
self:SetStartState( "UnLoaded" )
|
self:SetStartState( "UnLoaded" )
|
||||||
self:AddTransition( { "UnLoaded", "Boarding" }, "Board", "Boarding" )
|
self:AddTransition( { "UnLoaded", "Boarding" }, "Board", "Boarding" )
|
||||||
@@ -711,7 +711,7 @@ do -- CARGO
|
|||||||
-- @param #CARGO self
|
-- @param #CARGO self
|
||||||
-- @return #CARGO
|
-- @return #CARGO
|
||||||
function CARGO:Spawn( PointVec2 )
|
function CARGO:Spawn( PointVec2 )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -812,7 +812,7 @@ do -- CARGO
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the CargoGroup is within the loading radius.
|
-- @return #boolean true if the CargoGroup is within the loading radius.
|
||||||
function CARGO:IsInLoadRadius( Coordinate )
|
function CARGO:IsInLoadRadius( Coordinate )
|
||||||
self:F( { Coordinate, LoadRadius = self.LoadRadius } )
|
self:T( { Coordinate, LoadRadius = self.LoadRadius } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -832,7 +832,7 @@ do -- CARGO
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo can report itself.
|
-- @return #boolean true if the Cargo can report itself.
|
||||||
function CARGO:IsInReportRadius( Coordinate )
|
function CARGO:IsInReportRadius( Coordinate )
|
||||||
self:F( { Coordinate } )
|
self:T( { Coordinate } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -853,23 +853,23 @@ do -- CARGO
|
|||||||
-- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision).
|
-- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision).
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
function CARGO:IsNear( Coordinate, NearRadius )
|
function CARGO:IsNear( Coordinate, NearRadius )
|
||||||
--self:F( { PointVec2 = PointVec2, NearRadius = NearRadius } )
|
--self:T( { PointVec2 = PointVec2, NearRadius = NearRadius } )
|
||||||
|
|
||||||
if self.CargoObject:IsAlive() then
|
if self.CargoObject:IsAlive() then
|
||||||
--local Distance = PointVec2:Get2DDistance( self.CargoObject:GetPointVec2() )
|
--local Distance = PointVec2:Get2DDistance( self.CargoObject:GetPointVec2() )
|
||||||
--self:F( { CargoObjectName = self.CargoObject:GetName() } )
|
--self:T( { CargoObjectName = self.CargoObject:GetName() } )
|
||||||
--self:F( { CargoObjectVec2 = self.CargoObject:GetVec2() } )
|
--self:T( { CargoObjectVec2 = self.CargoObject:GetVec2() } )
|
||||||
--self:F( { PointVec2 = PointVec2:GetVec2() } )
|
--self:T( { PointVec2 = PointVec2:GetVec2() } )
|
||||||
local Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
|
local Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
|
||||||
--self:F( { Distance = Distance, NearRadius = NearRadius or "nil" } )
|
--self:T( { Distance = Distance, NearRadius = NearRadius or "nil" } )
|
||||||
|
|
||||||
if Distance <= NearRadius then
|
if Distance <= NearRadius then
|
||||||
--self:F( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = true } )
|
--self:T( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = true } )
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--self:F( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = false } )
|
--self:T( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = false } )
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -878,12 +878,12 @@ do -- CARGO
|
|||||||
-- @param Core.Zone#ZONE_BASE Zone
|
-- @param Core.Zone#ZONE_BASE Zone
|
||||||
-- @return #boolean **true** if cargo is in the Zone, **false** if cargo is not in the Zone.
|
-- @return #boolean **true** if cargo is in the Zone, **false** if cargo is not in the Zone.
|
||||||
function CARGO:IsInZone( Zone )
|
function CARGO:IsInZone( Zone )
|
||||||
--self:F( { Zone } )
|
--self:T( { Zone } )
|
||||||
|
|
||||||
if self:IsLoaded() then
|
if self:IsLoaded() then
|
||||||
return Zone:IsPointVec2InZone( self.CargoCarrier:GetPointVec2() )
|
return Zone:IsPointVec2InZone( self.CargoCarrier:GetPointVec2() )
|
||||||
else
|
else
|
||||||
--self:F( { Size = self.CargoObject:GetSize(), Units = self.CargoObject:GetUnits() } )
|
--self:T( { Size = self.CargoObject:GetSize(), Units = self.CargoObject:GetUnits() } )
|
||||||
if self.CargoObject:GetSize() ~= 0 then
|
if self.CargoObject:GetSize() ~= 0 then
|
||||||
return Zone:IsPointVec2InZone( self.CargoObject:GetPointVec2() )
|
return Zone:IsPointVec2InZone( self.CargoObject:GetPointVec2() )
|
||||||
else
|
else
|
||||||
@@ -1034,7 +1034,7 @@ end -- CARGO
|
|||||||
|
|
||||||
do -- CARGO_REPRESENTABLE
|
do -- CARGO_REPRESENTABLE
|
||||||
|
|
||||||
--- @type CARGO_REPRESENTABLE
|
-- @type CARGO_REPRESENTABLE
|
||||||
-- @extends #CARGO
|
-- @extends #CARGO
|
||||||
-- @field test
|
-- @field test
|
||||||
|
|
||||||
@@ -1056,7 +1056,7 @@ do -- CARGO_REPRESENTABLE
|
|||||||
|
|
||||||
-- Inherit CARGO.
|
-- Inherit CARGO.
|
||||||
local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE
|
local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE
|
||||||
self:F( { Type, Name, LoadRadius, NearRadius } )
|
self:T( { Type, Name, LoadRadius, NearRadius } )
|
||||||
|
|
||||||
-- Descriptors.
|
-- Descriptors.
|
||||||
local Desc=CargoObject:GetDesc()
|
local Desc=CargoObject:GetDesc()
|
||||||
@@ -1086,7 +1086,7 @@ do -- CARGO_REPRESENTABLE
|
|||||||
function CARGO_REPRESENTABLE:Destroy()
|
function CARGO_REPRESENTABLE:Destroy()
|
||||||
|
|
||||||
-- Cargo objects are deleted from the _DATABASE and SET_CARGO objects.
|
-- Cargo objects are deleted from the _DATABASE and SET_CARGO objects.
|
||||||
self:F( { CargoName = self:GetName() } )
|
self:T( { CargoName = self:GetName() } )
|
||||||
--_EVENTDISPATCHER:CreateEventDeleteCargo( self )
|
--_EVENTDISPATCHER:CreateEventDeleteCargo( self )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -1123,12 +1123,12 @@ do -- CARGO_REPRESENTABLE
|
|||||||
CoordinateZone:Scan( { Object.Category.UNIT } )
|
CoordinateZone:Scan( { Object.Category.UNIT } )
|
||||||
for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do
|
for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do
|
||||||
local NearUnit = UNIT:Find( DCSUnit )
|
local NearUnit = UNIT:Find( DCSUnit )
|
||||||
self:F({NearUnit=NearUnit})
|
self:T({NearUnit=NearUnit})
|
||||||
local NearUnitCoalition = NearUnit:GetCoalition()
|
local NearUnitCoalition = NearUnit:GetCoalition()
|
||||||
local CargoCoalition = self:GetCoalition()
|
local CargoCoalition = self:GetCoalition()
|
||||||
if NearUnitCoalition == CargoCoalition then
|
if NearUnitCoalition == CargoCoalition then
|
||||||
local Attributes = NearUnit:GetDesc()
|
local Attributes = NearUnit:GetDesc()
|
||||||
self:F({Desc=Attributes})
|
self:T({Desc=Attributes})
|
||||||
if NearUnit:HasAttribute( "Trucks" ) then
|
if NearUnit:HasAttribute( "Trucks" ) then
|
||||||
MESSAGE:New( Message, 20, NearUnit:GetCallsign() .. " reporting - Cargo " .. self:GetName() ):ToGroup( TaskGroup )
|
MESSAGE:New( Message, 20, NearUnit:GetCallsign() .. " reporting - Cargo " .. self:GetName() ):ToGroup( TaskGroup )
|
||||||
break
|
break
|
||||||
@@ -1142,7 +1142,7 @@ end -- CARGO_REPRESENTABLE
|
|||||||
|
|
||||||
do -- CARGO_REPORTABLE
|
do -- CARGO_REPORTABLE
|
||||||
|
|
||||||
--- @type CARGO_REPORTABLE
|
-- @type CARGO_REPORTABLE
|
||||||
-- @extends #CARGO
|
-- @extends #CARGO
|
||||||
CARGO_REPORTABLE = {
|
CARGO_REPORTABLE = {
|
||||||
ClassName = "CARGO_REPORTABLE"
|
ClassName = "CARGO_REPORTABLE"
|
||||||
@@ -1158,7 +1158,7 @@ do -- CARGO_REPORTABLE
|
|||||||
-- @return #CARGO_REPORTABLE
|
-- @return #CARGO_REPORTABLE
|
||||||
function CARGO_REPORTABLE:New( Type, Name, Weight, LoadRadius, NearRadius )
|
function CARGO_REPORTABLE:New( Type, Name, Weight, LoadRadius, NearRadius )
|
||||||
local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_REPORTABLE
|
local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_REPORTABLE
|
||||||
self:F( { Type, Name, Weight, LoadRadius, NearRadius } )
|
self:T( { Type, Name, Weight, LoadRadius, NearRadius } )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1178,7 +1178,7 @@ end
|
|||||||
|
|
||||||
do -- CARGO_PACKAGE
|
do -- CARGO_PACKAGE
|
||||||
|
|
||||||
--- @type CARGO_PACKAGE
|
-- @type CARGO_PACKAGE
|
||||||
-- @extends #CARGO_REPRESENTABLE
|
-- @extends #CARGO_REPRESENTABLE
|
||||||
CARGO_PACKAGE = {
|
CARGO_PACKAGE = {
|
||||||
ClassName = "CARGO_PACKAGE"
|
ClassName = "CARGO_PACKAGE"
|
||||||
@@ -1195,7 +1195,7 @@ do -- CARGO_PACKAGE
|
|||||||
-- @return #CARGO_PACKAGE
|
-- @return #CARGO_PACKAGE
|
||||||
function CARGO_PACKAGE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius )
|
function CARGO_PACKAGE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius )
|
||||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_PACKAGE
|
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_PACKAGE
|
||||||
self:F( { Type, Name, Weight, LoadRadius, NearRadius } )
|
self:T( { Type, Name, Weight, LoadRadius, NearRadius } )
|
||||||
|
|
||||||
self:T( CargoCarrier )
|
self:T( CargoCarrier )
|
||||||
self.CargoCarrier = CargoCarrier
|
self.CargoCarrier = CargoCarrier
|
||||||
@@ -1213,7 +1213,7 @@ end
|
|||||||
-- @param #number BoardDistance
|
-- @param #number BoardDistance
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterOnBoard( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
function CARGO_PACKAGE:onafterOnBoard( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
self.CargoInAir = self.CargoCarrier:InAir()
|
self.CargoInAir = self.CargoCarrier:InAir()
|
||||||
|
|
||||||
@@ -1246,7 +1246,7 @@ end
|
|||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
function CARGO_PACKAGE:IsNear( CargoCarrier )
|
function CARGO_PACKAGE:IsNear( CargoCarrier )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
local CargoCarrierPoint = CargoCarrier:GetCoordinate()
|
local CargoCarrierPoint = CargoCarrier:GetCoordinate()
|
||||||
|
|
||||||
@@ -1271,7 +1271,7 @@ end
|
|||||||
-- @param #number LoadDistance
|
-- @param #number LoadDistance
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterOnBoarded( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
function CARGO_PACKAGE:onafterOnBoarded( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
if self:IsNear( CargoCarrier ) then
|
if self:IsNear( CargoCarrier ) then
|
||||||
self:__Load( 1, CargoCarrier, Speed, LoadDistance, Angle )
|
self:__Load( 1, CargoCarrier, Speed, LoadDistance, Angle )
|
||||||
@@ -1292,7 +1292,7 @@ end
|
|||||||
-- @param #number Radius
|
-- @param #number Radius
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterUnBoard( From, Event, To, CargoCarrier, Speed, UnLoadDistance, UnBoardDistance, Radius, Angle )
|
function CARGO_PACKAGE:onafterUnBoard( From, Event, To, CargoCarrier, Speed, UnLoadDistance, UnBoardDistance, Radius, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
self.CargoInAir = self.CargoCarrier:InAir()
|
self.CargoInAir = self.CargoCarrier:InAir()
|
||||||
|
|
||||||
@@ -1331,7 +1331,7 @@ end
|
|||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
-- @param #number Speed
|
-- @param #number Speed
|
||||||
function CARGO_PACKAGE:onafterUnBoarded( From, Event, To, CargoCarrier, Speed )
|
function CARGO_PACKAGE:onafterUnBoarded( From, Event, To, CargoCarrier, Speed )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
if self:IsNear( CargoCarrier ) then
|
if self:IsNear( CargoCarrier ) then
|
||||||
self:__UnLoad( 1, CargoCarrier, Speed )
|
self:__UnLoad( 1, CargoCarrier, Speed )
|
||||||
@@ -1350,7 +1350,7 @@ end
|
|||||||
-- @param #number LoadDistance
|
-- @param #number LoadDistance
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterLoad( From, Event, To, CargoCarrier, Speed, LoadDistance, Angle )
|
function CARGO_PACKAGE:onafterLoad( From, Event, To, CargoCarrier, Speed, LoadDistance, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
self.CargoCarrier = CargoCarrier
|
self.CargoCarrier = CargoCarrier
|
||||||
|
|
||||||
@@ -1378,7 +1378,7 @@ end
|
|||||||
-- @param #number Distance
|
-- @param #number Distance
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Distance, Angle )
|
function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Distance, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
local StartPointVec2 = self.CargoCarrier:GetPointVec2()
|
local StartPointVec2 = self.CargoCarrier:GetPointVec2()
|
||||||
local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ do -- CARGO_CRATE
|
|||||||
-- @return #CARGO_CRATE
|
-- @return #CARGO_CRATE
|
||||||
function CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
function CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
||||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_CRATE
|
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_CRATE
|
||||||
self:F( { Type, Name, NearRadius } )
|
self:T( { Type, Name, NearRadius } )
|
||||||
|
|
||||||
self.CargoObject = CargoStatic -- Wrapper.Static#STATIC
|
self.CargoObject = CargoStatic -- Wrapper.Static#STATIC
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2
|
-- @param Core.Point#POINT_VEC2
|
||||||
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
||||||
--self:F( { ToPointVec2, From, Event, To } )
|
--self:T( { ToPointVec2, From, Event, To } )
|
||||||
|
|
||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Speed = 10
|
local Speed = 10
|
||||||
@@ -153,7 +153,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
function CARGO_CRATE:onenterLoaded( From, Event, To, CargoCarrier )
|
function CARGO_CRATE:onenterLoaded( From, Event, To, CargoCarrier )
|
||||||
--self:F( { From, Event, To, CargoCarrier } )
|
--self:T( { From, Event, To, CargoCarrier } )
|
||||||
|
|
||||||
self.CargoCarrier = CargoCarrier
|
self.CargoCarrier = CargoCarrier
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo Crate is within the report radius.
|
-- @return #boolean true if the Cargo Crate is within the report radius.
|
||||||
function CARGO_CRATE:IsInReportRadius( Coordinate )
|
function CARGO_CRATE:IsInReportRadius( Coordinate )
|
||||||
--self:F( { Coordinate, LoadRadius = self.LoadRadius } )
|
--self:T( { Coordinate, LoadRadius = self.LoadRadius } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -210,7 +210,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param Core.Point#Coordinate Coordinate
|
-- @param Core.Point#Coordinate Coordinate
|
||||||
-- @return #boolean true if the Cargo Crate is within the loading radius.
|
-- @return #boolean true if the Cargo Crate is within the loading radius.
|
||||||
function CARGO_CRATE:IsInLoadRadius( Coordinate )
|
function CARGO_CRATE:IsInLoadRadius( Coordinate )
|
||||||
--self:F( { Coordinate, LoadRadius = self.NearRadius } )
|
--self:T( { Coordinate, LoadRadius = self.NearRadius } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -231,7 +231,7 @@ do -- CARGO_CRATE
|
|||||||
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
||||||
-- @return #nil There is no valid Cargo in the CargoGroup.
|
-- @return #nil There is no valid Cargo in the CargoGroup.
|
||||||
function CARGO_CRATE:GetCoordinate()
|
function CARGO_CRATE:GetCoordinate()
|
||||||
--self:F()
|
--self:T()
|
||||||
|
|
||||||
return self.CargoObject:GetCoordinate()
|
return self.CargoObject:GetCoordinate()
|
||||||
end
|
end
|
||||||
@@ -261,7 +261,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #CARGO_CRATE self
|
-- @param #CARGO_CRATE self
|
||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
function CARGO_CRATE:RouteTo( Coordinate )
|
function CARGO_CRATE:RouteTo( Coordinate )
|
||||||
self:F( {Coordinate = Coordinate } )
|
self:T( {Coordinate = Coordinate } )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ do -- CARGO_CRATE
|
|||||||
-- @return #boolean The Cargo is near to the Carrier.
|
-- @return #boolean The Cargo is near to the Carrier.
|
||||||
-- @return #nil The Cargo is not near to the Carrier.
|
-- @return #nil The Cargo is not near to the Carrier.
|
||||||
function CARGO_CRATE:IsNear( CargoCarrier, NearRadius )
|
function CARGO_CRATE:IsNear( CargoCarrier, NearRadius )
|
||||||
self:F( {NearRadius = NearRadius } )
|
self:T( {NearRadius = NearRadius } )
|
||||||
|
|
||||||
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
|
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
|
||||||
end
|
end
|
||||||
@@ -283,7 +283,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #CARGO_CRATE self
|
-- @param #CARGO_CRATE self
|
||||||
function CARGO_CRATE:Respawn()
|
function CARGO_CRATE:Respawn()
|
||||||
|
|
||||||
self:F( { "Respawning crate " .. self:GetName() } )
|
self:T( { "Respawning crate " .. self:GetName() } )
|
||||||
|
|
||||||
|
|
||||||
-- Respawn the group...
|
-- Respawn the group...
|
||||||
@@ -300,7 +300,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #CARGO_CRATE self
|
-- @param #CARGO_CRATE self
|
||||||
function CARGO_CRATE:onafterReset()
|
function CARGO_CRATE:onafterReset()
|
||||||
|
|
||||||
self:F( { "Reset crate " .. self:GetName() } )
|
self:T( { "Reset crate " .. self:GetName() } )
|
||||||
|
|
||||||
|
|
||||||
-- Respawn the group...
|
-- Respawn the group...
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ do -- CARGO_GROUP
|
|||||||
|
|
||||||
-- Inherit CAROG_REPORTABLE
|
-- Inherit CAROG_REPORTABLE
|
||||||
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_GROUP
|
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_GROUP
|
||||||
self:F( { Type, Name, LoadRadius } )
|
self:T( { Type, Name, LoadRadius } )
|
||||||
|
|
||||||
self.CargoSet = SET_CARGO:New()
|
self.CargoSet = SET_CARGO:New()
|
||||||
self.CargoGroup = CargoGroup
|
self.CargoGroup = CargoGroup
|
||||||
@@ -146,7 +146,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #CARGO_GROUP self
|
-- @param #CARGO_GROUP self
|
||||||
function CARGO_GROUP:Respawn()
|
function CARGO_GROUP:Respawn()
|
||||||
|
|
||||||
self:F( { "Respawning" } )
|
self:T( { "Respawning" } )
|
||||||
|
|
||||||
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
||||||
local Cargo = CargoData -- Cargo.Cargo#CARGO
|
local Cargo = CargoData -- Cargo.Cargo#CARGO
|
||||||
@@ -227,7 +227,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #CARGO_GROUP self
|
-- @param #CARGO_GROUP self
|
||||||
function CARGO_GROUP:Regroup()
|
function CARGO_GROUP:Regroup()
|
||||||
|
|
||||||
self:F("Regroup")
|
self:T("Regroup")
|
||||||
|
|
||||||
if self.Grouped == false then
|
if self.Grouped == false then
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ do -- CARGO_GROUP
|
|||||||
for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do
|
for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do
|
||||||
local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT
|
local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT
|
||||||
|
|
||||||
self:F( { CargoUnit:GetName(), UnLoaded = CargoUnit:IsUnLoaded() } )
|
self:T( { CargoUnit:GetName(), UnLoaded = CargoUnit:IsUnLoaded() } )
|
||||||
|
|
||||||
if CargoUnit:IsUnLoaded() then
|
if CargoUnit:IsUnLoaded() then
|
||||||
|
|
||||||
@@ -258,7 +258,7 @@ do -- CARGO_GROUP
|
|||||||
-- Then we register the new group in the database
|
-- Then we register the new group in the database
|
||||||
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID )
|
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID )
|
||||||
|
|
||||||
self:F( { "Regroup", GroupTemplate } )
|
self:T( { "Regroup", GroupTemplate } )
|
||||||
|
|
||||||
-- Now we spawn the new group based on the template created.
|
-- Now we spawn the new group based on the template created.
|
||||||
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
|
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
|
||||||
@@ -271,7 +271,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function CARGO_GROUP:OnEventCargoDead( EventData )
|
function CARGO_GROUP:OnEventCargoDead( EventData )
|
||||||
|
|
||||||
self:E(EventData)
|
self:T(EventData)
|
||||||
|
|
||||||
local Destroyed = false
|
local Destroyed = false
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ do -- CARGO_GROUP
|
|||||||
|
|
||||||
if Destroyed then
|
if Destroyed then
|
||||||
self:Destroyed()
|
self:Destroyed()
|
||||||
self:E( { "Cargo group destroyed" } )
|
self:T( { "Cargo group destroyed" } )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -309,14 +309,14 @@ do -- CARGO_GROUP
|
|||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||||
function CARGO_GROUP:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
function CARGO_GROUP:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||||
self:F( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } )
|
self:T( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } )
|
||||||
|
|
||||||
NearRadius = NearRadius or self.NearRadius
|
NearRadius = NearRadius or self.NearRadius
|
||||||
|
|
||||||
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
|
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
|
||||||
self.CargoSet:ForEach(
|
self.CargoSet:ForEach(
|
||||||
function( Cargo, ... )
|
function( Cargo, ... )
|
||||||
self:F( { "Board Unit", Cargo:GetName( ), Cargo:IsDestroyed(), Cargo.CargoObject:IsAlive() } )
|
self:T( { "Board Unit", Cargo:GetName( ), Cargo:IsDestroyed(), Cargo.CargoObject:IsAlive() } )
|
||||||
local CargoGroup = Cargo.CargoObject --Wrapper.Group#GROUP
|
local CargoGroup = Cargo.CargoObject --Wrapper.Group#GROUP
|
||||||
CargoGroup:OptionAlarmStateGreen()
|
CargoGroup:OptionAlarmStateGreen()
|
||||||
Cargo:__Board( 1, CargoCarrier, NearRadius, ... )
|
Cargo:__Board( 1, CargoCarrier, NearRadius, ... )
|
||||||
@@ -334,7 +334,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
function CARGO_GROUP:onafterLoad( From, Event, To, CargoCarrier, ... )
|
function CARGO_GROUP:onafterLoad( From, Event, To, CargoCarrier, ... )
|
||||||
--self:F( { From, Event, To, CargoCarrier, ...} )
|
--self:T( { From, Event, To, CargoCarrier, ...} )
|
||||||
|
|
||||||
if From == "UnLoaded" then
|
if From == "UnLoaded" then
|
||||||
-- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier.
|
-- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier.
|
||||||
@@ -359,7 +359,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||||
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||||
--self:F( { CargoCarrier.UnitName, From, Event, To } )
|
--self:T( { CargoCarrier.UnitName, From, Event, To } )
|
||||||
|
|
||||||
local Boarded = true
|
local Boarded = true
|
||||||
local Cancelled = false
|
local Cancelled = false
|
||||||
@@ -393,7 +393,7 @@ do -- CARGO_GROUP
|
|||||||
if not Boarded then
|
if not Boarded then
|
||||||
self:__Boarding( -5, CargoCarrier, NearRadius, ... )
|
self:__Boarding( -5, CargoCarrier, NearRadius, ... )
|
||||||
else
|
else
|
||||||
self:F("Group Cargo is loaded")
|
self:T("Group Cargo is loaded")
|
||||||
self:__Load( 1, CargoCarrier, ... )
|
self:__Load( 1, CargoCarrier, ... )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -413,7 +413,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||||
function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
|
function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||||
self:F( {From, Event, To, ToPointVec2, NearRadius } )
|
self:T( {From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
NearRadius = NearRadius or 25
|
NearRadius = NearRadius or 25
|
||||||
|
|
||||||
@@ -456,7 +456,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||||
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||||
--self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
--self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
--local NearRadius = NearRadius or 25
|
--local NearRadius = NearRadius or 25
|
||||||
|
|
||||||
@@ -493,7 +493,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
|
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
|
||||||
--self:F( { From, Event, To, ToPointVec2 } )
|
--self:T( { From, Event, To, ToPointVec2 } )
|
||||||
|
|
||||||
if From == "Loaded" then
|
if From == "Loaded" then
|
||||||
|
|
||||||
@@ -611,7 +611,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #CARGO_GROUP self
|
-- @param #CARGO_GROUP self
|
||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
function CARGO_GROUP:RouteTo( Coordinate )
|
function CARGO_GROUP:RouteTo( Coordinate )
|
||||||
--self:F( {Coordinate = Coordinate } )
|
--self:T( {Coordinate = Coordinate } )
|
||||||
|
|
||||||
-- For each Cargo within the CargoSet, route each object to the Coordinate
|
-- For each Cargo within the CargoSet, route each object to the Coordinate
|
||||||
self.CargoSet:ForEach(
|
self.CargoSet:ForEach(
|
||||||
@@ -629,13 +629,13 @@ do -- CARGO_GROUP
|
|||||||
-- @param #number NearRadius
|
-- @param #number NearRadius
|
||||||
-- @return #boolean The Cargo is near to the Carrier or #nil if the Cargo is not near to the Carrier.
|
-- @return #boolean The Cargo is near to the Carrier or #nil if the Cargo is not near to the Carrier.
|
||||||
function CARGO_GROUP:IsNear( CargoCarrier, NearRadius )
|
function CARGO_GROUP:IsNear( CargoCarrier, NearRadius )
|
||||||
self:F( {NearRadius = NearRadius } )
|
self:T( {NearRadius = NearRadius } )
|
||||||
|
|
||||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||||
if Cargo:IsAlive() then
|
if Cargo:IsAlive() then
|
||||||
if Cargo:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) then
|
if Cargo:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) then
|
||||||
self:F( "Near" )
|
self:T( "Near" )
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -649,7 +649,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo Group is within the load radius.
|
-- @return #boolean true if the Cargo Group is within the load radius.
|
||||||
function CARGO_GROUP:IsInLoadRadius( Coordinate )
|
function CARGO_GROUP:IsInLoadRadius( Coordinate )
|
||||||
--self:F( { Coordinate } )
|
--self:T( { Coordinate } )
|
||||||
|
|
||||||
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
||||||
|
|
||||||
@@ -669,7 +669,7 @@ do -- CARGO_GROUP
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
self:F( { Distance = Distance, LoadRadius = self.LoadRadius } )
|
self:T( { Distance = Distance, LoadRadius = self.LoadRadius } )
|
||||||
if Distance <= self.LoadRadius then
|
if Distance <= self.LoadRadius then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
@@ -687,12 +687,12 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Point#Coordinate Coordinate
|
-- @param Core.Point#Coordinate Coordinate
|
||||||
-- @return #boolean true if the Cargo Group is within the report radius.
|
-- @return #boolean true if the Cargo Group is within the report radius.
|
||||||
function CARGO_GROUP:IsInReportRadius( Coordinate )
|
function CARGO_GROUP:IsInReportRadius( Coordinate )
|
||||||
--self:F( { Coordinate } )
|
--self:T( { Coordinate } )
|
||||||
|
|
||||||
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
||||||
|
|
||||||
if Cargo then
|
if Cargo then
|
||||||
self:F( { Cargo } )
|
self:T( { Cargo } )
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if Cargo:IsUnLoaded() then
|
if Cargo:IsUnLoaded() then
|
||||||
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
|
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
|
||||||
@@ -738,7 +738,7 @@ do -- CARGO_GROUP
|
|||||||
-- @return #boolean **true** if the first element of the CargoGroup is in the Zone
|
-- @return #boolean **true** if the first element of the CargoGroup is in the Zone
|
||||||
-- @return #boolean **false** if there is no element of the CargoGroup in the Zone.
|
-- @return #boolean **false** if there is no element of the CargoGroup in the Zone.
|
||||||
function CARGO_GROUP:IsInZone( Zone )
|
function CARGO_GROUP:IsInZone( Zone )
|
||||||
--self:F( { Zone } )
|
--self:T( { Zone } )
|
||||||
|
|
||||||
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @return #CARGO_SLINGLOAD
|
-- @return #CARGO_SLINGLOAD
|
||||||
function CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
function CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
||||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_SLINGLOAD
|
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_SLINGLOAD
|
||||||
self:F( { Type, Name, NearRadius } )
|
self:T( { Type, Name, NearRadius } )
|
||||||
|
|
||||||
self.CargoObject = CargoStatic
|
self.CargoObject = CargoStatic
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo Crate is within the report radius.
|
-- @return #boolean true if the Cargo Crate is within the report radius.
|
||||||
function CARGO_SLINGLOAD:IsInReportRadius( Coordinate )
|
function CARGO_SLINGLOAD:IsInReportRadius( Coordinate )
|
||||||
--self:F( { Coordinate, LoadRadius = self.LoadRadius } )
|
--self:T( { Coordinate, LoadRadius = self.LoadRadius } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -149,7 +149,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo Slingload is within the loading radius.
|
-- @return #boolean true if the Cargo Slingload is within the loading radius.
|
||||||
function CARGO_SLINGLOAD:IsInLoadRadius( Coordinate )
|
function CARGO_SLINGLOAD:IsInLoadRadius( Coordinate )
|
||||||
--self:F( { Coordinate } )
|
--self:T( { Coordinate } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -169,7 +169,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
||||||
-- @return #nil There is no valid Cargo in the CargoGroup.
|
-- @return #nil There is no valid Cargo in the CargoGroup.
|
||||||
function CARGO_SLINGLOAD:GetCoordinate()
|
function CARGO_SLINGLOAD:GetCoordinate()
|
||||||
--self:F()
|
--self:T()
|
||||||
|
|
||||||
return self.CargoObject:GetCoordinate()
|
return self.CargoObject:GetCoordinate()
|
||||||
end
|
end
|
||||||
@@ -199,7 +199,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param #CARGO_SLINGLOAD self
|
-- @param #CARGO_SLINGLOAD self
|
||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
function CARGO_SLINGLOAD:RouteTo( Coordinate )
|
function CARGO_SLINGLOAD:RouteTo( Coordinate )
|
||||||
--self:F( {Coordinate = Coordinate } )
|
--self:T( {Coordinate = Coordinate } )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @return #boolean The Cargo is near to the Carrier.
|
-- @return #boolean The Cargo is near to the Carrier.
|
||||||
-- @return #nil The Cargo is not near to the Carrier.
|
-- @return #nil The Cargo is not near to the Carrier.
|
||||||
function CARGO_SLINGLOAD:IsNear( CargoCarrier, NearRadius )
|
function CARGO_SLINGLOAD:IsNear( CargoCarrier, NearRadius )
|
||||||
--self:F( {NearRadius = NearRadius } )
|
--self:T( {NearRadius = NearRadius } )
|
||||||
|
|
||||||
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
|
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
|
||||||
end
|
end
|
||||||
@@ -222,7 +222,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param #CARGO_SLINGLOAD self
|
-- @param #CARGO_SLINGLOAD self
|
||||||
function CARGO_SLINGLOAD:Respawn()
|
function CARGO_SLINGLOAD:Respawn()
|
||||||
|
|
||||||
--self:F( { "Respawning slingload " .. self:GetName() } )
|
--self:T( { "Respawning slingload " .. self:GetName() } )
|
||||||
|
|
||||||
|
|
||||||
-- Respawn the group...
|
-- Respawn the group...
|
||||||
@@ -239,7 +239,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param #CARGO_SLINGLOAD self
|
-- @param #CARGO_SLINGLOAD self
|
||||||
function CARGO_SLINGLOAD:onafterReset()
|
function CARGO_SLINGLOAD:onafterReset()
|
||||||
|
|
||||||
--self:F( { "Reset slingload " .. self:GetName() } )
|
--self:T( { "Reset slingload " .. self:GetName() } )
|
||||||
|
|
||||||
|
|
||||||
-- Respawn the group...
|
-- Respawn the group...
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 25 m.
|
-- @param #number NearRadius (optional) Defaut 25 m.
|
||||||
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Speed = 60
|
local Speed = 60
|
||||||
@@ -114,7 +114,7 @@ do -- CARGO_UNIT
|
|||||||
else
|
else
|
||||||
self.CargoObject:ReSpawnAt( FromPointVec2, CargoDeployHeading )
|
self.CargoObject:ReSpawnAt( FromPointVec2, CargoDeployHeading )
|
||||||
end
|
end
|
||||||
self:F( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } )
|
self:T( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } )
|
||||||
self.CargoCarrier = nil
|
self.CargoCarrier = nil
|
||||||
|
|
||||||
local Points = {}
|
local Points = {}
|
||||||
@@ -148,7 +148,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||||
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Speed = 10
|
local Speed = 10
|
||||||
@@ -174,7 +174,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||||
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
self.CargoInAir = self.CargoObject:InAir()
|
self.CargoInAir = self.CargoObject:InAir()
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2
|
-- @param Core.Point#POINT_VEC2
|
||||||
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
||||||
self:F( { ToPointVec2, From, Event, To } )
|
self:T( { ToPointVec2, From, Event, To } )
|
||||||
|
|
||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Speed = 10
|
local Speed = 10
|
||||||
@@ -236,7 +236,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param Wrapper.Group#GROUP CargoCarrier
|
-- @param Wrapper.Group#GROUP CargoCarrier
|
||||||
-- @param #number NearRadius
|
-- @param #number NearRadius
|
||||||
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||||
self:F( { From, Event, To, CargoCarrier, NearRadius = NearRadius } )
|
self:T( { From, Event, To, CargoCarrier, NearRadius = NearRadius } )
|
||||||
|
|
||||||
self.CargoInAir = self.CargoObject:InAir()
|
self.CargoInAir = self.CargoObject:InAir()
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ do -- CARGO_UNIT
|
|||||||
local MaxSpeed = Desc.speedMaxOffRoad
|
local MaxSpeed = Desc.speedMaxOffRoad
|
||||||
local TypeName = Desc.typeName
|
local TypeName = Desc.typeName
|
||||||
|
|
||||||
--self:F({Unit=self.CargoObject:GetName()})
|
--self:T({Unit=self.CargoObject:GetName()})
|
||||||
|
|
||||||
-- A cargo unit can only be boarded if it is not dead
|
-- A cargo unit can only be boarded if it is not dead
|
||||||
|
|
||||||
@@ -298,9 +298,9 @@ do -- CARGO_UNIT
|
|||||||
-- @param Wrapper.Client#CLIENT CargoCarrier
|
-- @param Wrapper.Client#CLIENT CargoCarrier
|
||||||
-- @param #number NearRadius Default 25 m.
|
-- @param #number NearRadius Default 25 m.
|
||||||
function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||||
self:F( { From, Event, To, CargoCarrier:GetName(), NearRadius = NearRadius } )
|
self:T( { From, Event, To, CargoCarrier:GetName(), NearRadius = NearRadius } )
|
||||||
|
|
||||||
self:F( { IsAlive=self.CargoObject:IsAlive() } )
|
self:T( { IsAlive=self.CargoObject:IsAlive() } )
|
||||||
|
|
||||||
if CargoCarrier and CargoCarrier:IsAlive() then -- and self.CargoObject and self.CargoObject:IsAlive() then
|
if CargoCarrier and CargoCarrier:IsAlive() then -- and self.CargoObject and self.CargoObject:IsAlive() then
|
||||||
if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then
|
if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then
|
||||||
@@ -321,7 +321,7 @@ do -- CARGO_UNIT
|
|||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
|
|
||||||
--self:F({Unit=self.CargoObject:GetName()})
|
--self:T({Unit=self.CargoObject:GetName()})
|
||||||
|
|
||||||
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
|
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
|
||||||
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
||||||
@@ -348,7 +348,7 @@ do -- CARGO_UNIT
|
|||||||
self.CargoObject:SetCommand( self.CargoObject:CommandStopRoute( true ) )
|
self.CargoObject:SetCommand( self.CargoObject:CommandStopRoute( true ) )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:E("Something is wrong")
|
self:T("Something is wrong")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -361,11 +361,11 @@ do -- CARGO_UNIT
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
function CARGO_UNIT:onenterLoaded( From, Event, To, CargoCarrier )
|
function CARGO_UNIT:onenterLoaded( From, Event, To, CargoCarrier )
|
||||||
self:F( { From, Event, To, CargoCarrier } )
|
self:T( { From, Event, To, CargoCarrier } )
|
||||||
|
|
||||||
self.CargoCarrier = CargoCarrier
|
self.CargoCarrier = CargoCarrier
|
||||||
|
|
||||||
--self:F({Unit=self.CargoObject:GetName()})
|
--self:T({Unit=self.CargoObject:GetName()})
|
||||||
|
|
||||||
-- Only destroy the CargoObject if there is a CargoObject (packages don't have CargoObjects).
|
-- Only destroy the CargoObject if there is a CargoObject (packages don't have CargoObjects).
|
||||||
if self.CargoObject then
|
if self.CargoObject then
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ end
|
|||||||
CLIENTMENUMANAGER = {
|
CLIENTMENUMANAGER = {
|
||||||
ClassName = "CLIENTMENUMANAGER",
|
ClassName = "CLIENTMENUMANAGER",
|
||||||
lid = "",
|
lid = "",
|
||||||
version = "0.1.3",
|
version = "0.1.4",
|
||||||
name = nil,
|
name = nil,
|
||||||
clientset = nil,
|
clientset = nil,
|
||||||
menutree = {},
|
menutree = {},
|
||||||
@@ -439,18 +439,18 @@ function CLIENTMENUMANAGER:_EventHandler(EventData)
|
|||||||
--self:I(self.lid.."_EventHandler: "..tostring(EventData.IniPlayerName))
|
--self:I(self.lid.."_EventHandler: "..tostring(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.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
|
||||||
self:T(self.lid.."Leave event for player: "..tostring(EventData.IniPlayerName))
|
self:T(self.lid.."Leave event for player: "..tostring(EventData.IniPlayerName))
|
||||||
local Client = _DATABASE:FindClient( EventData.IniPlayerName )
|
local Client = _DATABASE:FindClient( EventData.IniUnitName )
|
||||||
if Client then
|
if Client then
|
||||||
self:ResetMenu(Client)
|
self:ResetMenu(Client)
|
||||||
end
|
end
|
||||||
elseif (EventData.id == EVENTS.PlayerEnterAircraft) and EventData.IniCoalition == self.Coalition then
|
elseif (EventData.id == EVENTS.PlayerEnterAircraft) and EventData.IniCoalition == self.Coalition then
|
||||||
if EventData.IniPlayerName and EventData.IniGroup then
|
if EventData.IniPlayerName and EventData.IniGroup then
|
||||||
if (not self.clientset:IsIncludeObject(_DATABASE:FindClient( EventData.IniPlayerName ))) then
|
if (not self.clientset:IsIncludeObject(_DATABASE:FindClient( EventData.IniUnitName ))) then
|
||||||
self:T(self.lid.."Client not in SET: "..EventData.IniPlayerName)
|
self:T(self.lid.."Client not in SET: "..EventData.IniPlayerName)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
--self:I(self.lid.."Join event for player: "..EventData.IniPlayerName)
|
--self:I(self.lid.."Join event for player: "..EventData.IniPlayerName)
|
||||||
local player = _DATABASE:FindClient( EventData.IniPlayerName )
|
local player = _DATABASE:FindClient( EventData.IniUnitName )
|
||||||
self:Propagate(player)
|
self:Propagate(player)
|
||||||
end
|
end
|
||||||
elseif EventData.id == EVENTS.PlayerEnterUnit then
|
elseif EventData.id == EVENTS.PlayerEnterUnit then
|
||||||
@@ -668,7 +668,7 @@ function CLIENTMENUMANAGER:Propagate(Client)
|
|||||||
for _,_client in pairs(Set) do
|
for _,_client in pairs(Set) do
|
||||||
local client = _client -- Wrapper.Client#CLIENT
|
local client = _client -- Wrapper.Client#CLIENT
|
||||||
if client and client:IsAlive() then
|
if client and client:IsAlive() then
|
||||||
local playername = client:GetPlayerName()
|
local playername = client:GetPlayerName() or "none"
|
||||||
if not self.playertree[playername] then
|
if not self.playertree[playername] then
|
||||||
self.playertree[playername] = {}
|
self.playertree[playername] = {}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -449,10 +449,10 @@ do -- Zones and Pathlines
|
|||||||
|
|
||||||
-- Loop over layers.
|
-- Loop over layers.
|
||||||
for layerID, layerData in pairs(env.mission.drawings.layers or {}) do
|
for layerID, layerData in pairs(env.mission.drawings.layers or {}) do
|
||||||
|
|
||||||
-- Loop over objects in layers.
|
-- Loop over objects in layers.
|
||||||
for objectID, objectData in pairs(layerData.objects or {}) do
|
for objectID, objectData in pairs(layerData.objects or {}) do
|
||||||
|
|
||||||
-- Check for polygon which has at least 4 points (we would need 3 but the origin seems to be there twice)
|
-- Check for polygon which has at least 4 points (we would need 3 but the origin seems to be there twice)
|
||||||
if objectData.polygonMode and (objectData.polygonMode=="free") and objectData.points and #objectData.points>=4 then
|
if objectData.polygonMode and (objectData.polygonMode=="free") and objectData.points and #objectData.points>=4 then
|
||||||
|
|
||||||
@@ -488,10 +488,32 @@ do -- Zones and Pathlines
|
|||||||
|
|
||||||
-- Create new polygon zone.
|
-- Create new polygon zone.
|
||||||
local Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, points)
|
local Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, points)
|
||||||
|
|
||||||
|
--Zone.DrawID = objectID
|
||||||
|
|
||||||
-- Set color.
|
-- Set color.
|
||||||
Zone:SetColor({1, 0, 0}, 0.15)
|
Zone:SetColor({1, 0, 0}, 0.15)
|
||||||
|
Zone:SetFillColor({1, 0, 0}, 0.15)
|
||||||
|
|
||||||
|
if objectData.colorString then
|
||||||
|
-- eg colorString = 0xff0000ff
|
||||||
|
local color = string.gsub(objectData.colorString,"^0x","")
|
||||||
|
local r = tonumber(string.sub(color,1,2),16)/255
|
||||||
|
local g = tonumber(string.sub(color,3,4),16)/255
|
||||||
|
local b = tonumber(string.sub(color,5,6),16)/255
|
||||||
|
local a = tonumber(string.sub(color,7,8),16)/255
|
||||||
|
Zone:SetColor({r, g, b}, a)
|
||||||
|
end
|
||||||
|
if objectData.fillColorString then
|
||||||
|
-- eg fillColorString = 0xff00004b
|
||||||
|
local color = string.gsub(objectData.colorString,"^0x","")
|
||||||
|
local r = tonumber(string.sub(color,1,2),16)/255
|
||||||
|
local g = tonumber(string.sub(color,3,4),16)/255
|
||||||
|
local b = tonumber(string.sub(color,5,6),16)/255
|
||||||
|
local a = tonumber(string.sub(color,7,8),16)/255
|
||||||
|
Zone:SetFillColor({r, g, b}, a)
|
||||||
|
end
|
||||||
|
|
||||||
-- Store in DB.
|
-- Store in DB.
|
||||||
self.ZONENAMES[ZoneName] = ZoneName
|
self.ZONENAMES[ZoneName] = ZoneName
|
||||||
|
|
||||||
@@ -532,7 +554,26 @@ do -- Zones and Pathlines
|
|||||||
|
|
||||||
-- Set color.
|
-- Set color.
|
||||||
Zone:SetColor({1, 0, 0}, 0.15)
|
Zone:SetColor({1, 0, 0}, 0.15)
|
||||||
|
|
||||||
|
if objectData.colorString then
|
||||||
|
-- eg colorString = 0xff0000ff
|
||||||
|
local color = string.gsub(objectData.colorString,"^0x","")
|
||||||
|
local r = tonumber(string.sub(color,1,2),16)/255
|
||||||
|
local g = tonumber(string.sub(color,3,4),16)/255
|
||||||
|
local b = tonumber(string.sub(color,5,6),16)/255
|
||||||
|
local a = tonumber(string.sub(color,7,8),16)/255
|
||||||
|
Zone:SetColor({r, g, b}, a)
|
||||||
|
end
|
||||||
|
if objectData.fillColorString then
|
||||||
|
-- eg fillColorString = 0xff00004b
|
||||||
|
local color = string.gsub(objectData.colorString,"^0x","")
|
||||||
|
local r = tonumber(string.sub(color,1,2),16)/255
|
||||||
|
local g = tonumber(string.sub(color,3,4),16)/255
|
||||||
|
local b = tonumber(string.sub(color,5,6),16)/255
|
||||||
|
local a = tonumber(string.sub(color,7,8),16)/255
|
||||||
|
Zone:SetFillColor({r, g, b}, a)
|
||||||
|
end
|
||||||
|
|
||||||
-- Store in DB.
|
-- Store in DB.
|
||||||
self.ZONENAMES[ZoneName] = ZoneName
|
self.ZONENAMES[ZoneName] = ZoneName
|
||||||
|
|
||||||
@@ -756,7 +797,7 @@ end -- cargo
|
|||||||
|
|
||||||
--- Finds a CLIENT based on the ClientName.
|
--- Finds a CLIENT based on the ClientName.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string ClientName
|
-- @param #string ClientName - Note this is the UNIT name of the client!
|
||||||
-- @return Wrapper.Client#CLIENT The found CLIENT.
|
-- @return Wrapper.Client#CLIENT The found CLIENT.
|
||||||
function DATABASE:FindClient( ClientName )
|
function DATABASE:FindClient( ClientName )
|
||||||
|
|
||||||
@@ -1302,9 +1343,17 @@ function DATABASE:_RegisterAirbase(airbase)
|
|||||||
|
|
||||||
-- Unique ID.
|
-- Unique ID.
|
||||||
local airbaseUID=airbase:GetID(true)
|
local airbaseUID=airbase:GetID(true)
|
||||||
|
|
||||||
|
local typename = airbase:GetTypeName()
|
||||||
|
|
||||||
|
local category = airbase.category
|
||||||
|
|
||||||
|
if category == Airbase.Category.SHIP and typename == "FARP_SINGLE_01" then
|
||||||
|
category = Airbase.Category.HELIPAD
|
||||||
|
end
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
local text=string.format("Register %s: %s (UID=%d), Runways=%d, Parking=%d [", AIRBASE.CategoryName[airbase.category], tostring(DCSAirbaseName), airbaseUID, #airbase.runways, airbase.NparkingTotal)
|
local text=string.format("Register %s: %s (UID=%d), Runways=%d, Parking=%d [", AIRBASE.CategoryName[category], tostring(DCSAirbaseName), airbaseUID, #airbase.runways, airbase.NparkingTotal)
|
||||||
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
||||||
if airbase.NparkingTerminal and airbase.NparkingTerminal[terminalType] then
|
if airbase.NparkingTerminal and airbase.NparkingTerminal[terminalType] then
|
||||||
text=text..string.format("%d=%d ", terminalType, airbase.NparkingTerminal[terminalType])
|
text=text..string.format("%d=%d ", terminalType, airbase.NparkingTerminal[terminalType])
|
||||||
@@ -1852,7 +1901,7 @@ end
|
|||||||
|
|
||||||
--- Add a flight control to the data base.
|
--- Add a flight control to the data base.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol
|
-- @param OPS.FlightControl#FLIGHTCONTROL flightcontrol
|
||||||
function DATABASE:AddFlightControl(flightcontrol)
|
function DATABASE:AddFlightControl(flightcontrol)
|
||||||
self:F2( { flightcontrol } )
|
self:F2( { flightcontrol } )
|
||||||
self.FLIGHTCONTROLS[flightcontrol.airbasename]=flightcontrol
|
self.FLIGHTCONTROLS[flightcontrol.airbasename]=flightcontrol
|
||||||
@@ -1861,7 +1910,7 @@ end
|
|||||||
--- Get a flight control object from the data base.
|
--- Get a flight control object from the data base.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string airbasename Name of the associated airbase.
|
-- @param #string airbasename Name of the associated airbase.
|
||||||
-- @return Ops.FlightControl#FLIGHTCONTROL The FLIGHTCONTROL object.s
|
-- @return OPS.FlightControl#FLIGHTCONTROL The FLIGHTCONTROL object.s
|
||||||
function DATABASE:GetFlightControl(airbasename)
|
function DATABASE:GetFlightControl(airbasename)
|
||||||
return self.FLIGHTCONTROLS[airbasename]
|
return self.FLIGHTCONTROLS[airbasename]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -261,6 +261,15 @@ EVENTS = {
|
|||||||
SimulationStart = world.event.S_EVENT_SIMULATION_START or -1,
|
SimulationStart = world.event.S_EVENT_SIMULATION_START or -1,
|
||||||
WeaponRearm = world.event.S_EVENT_WEAPON_REARM or -1,
|
WeaponRearm = world.event.S_EVENT_WEAPON_REARM or -1,
|
||||||
WeaponDrop = world.event.S_EVENT_WEAPON_DROP or -1,
|
WeaponDrop = world.event.S_EVENT_WEAPON_DROP or -1,
|
||||||
|
-- Added with DCS 2.9.0
|
||||||
|
UnitTaskTimeout = world.event.S_EVENT_UNIT_TASK_TIMEOUT or -1,
|
||||||
|
UnitTaskStage = world.event.S_EVENT_UNIT_TASK_STAGE or -1,
|
||||||
|
MacSubtaskScore = world.event.S_EVENT_MAC_SUBTASK_SCORE or -1,
|
||||||
|
MacExtraScore = world.event.S_EVENT_MAC_EXTRA_SCORE or -1,
|
||||||
|
MissionRestart = world.event.S_EVENT_MISSION_RESTART or -1,
|
||||||
|
MissionWinner = world.event.S_EVENT_MISSION_WINNER or -1,
|
||||||
|
PostponedTakeoff = world.event.S_EVENT_POSTPONED_TAKEOFF or -1,
|
||||||
|
PostponedLand = world.event.S_EVENT_POSTPONED_LAND or -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- The Event structure
|
--- The Event structure
|
||||||
@@ -636,6 +645,55 @@ local _EVENTMETA = {
|
|||||||
Event = "OnEventWeaponDrop",
|
Event = "OnEventWeaponDrop",
|
||||||
Text = "S_EVENT_WEAPON_DROP"
|
Text = "S_EVENT_WEAPON_DROP"
|
||||||
},
|
},
|
||||||
|
-- DCS 2.9
|
||||||
|
[EVENTS.UnitTaskTimeout] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventUnitTaskTimeout",
|
||||||
|
Text = "S_EVENT_UNIT_TASK_TIMEOUT "
|
||||||
|
},
|
||||||
|
[EVENTS.UnitTaskStage] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventUnitTaskStage",
|
||||||
|
Text = "S_EVENT_UNIT_TASK_STAGE "
|
||||||
|
},
|
||||||
|
[EVENTS.MacSubtaskScore] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventMacSubtaskScore",
|
||||||
|
Text = "S_EVENT_MAC_SUBTASK_SCORE"
|
||||||
|
},
|
||||||
|
[EVENTS.MacExtraScore] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventMacExtraScore",
|
||||||
|
Text = "S_EVENT_MAC_EXTRA_SCOREP"
|
||||||
|
},
|
||||||
|
[EVENTS.MissionRestart] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventMissionRestart",
|
||||||
|
Text = "S_EVENT_MISSION_RESTART"
|
||||||
|
},
|
||||||
|
[EVENTS.MissionWinner] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventMissionWinner",
|
||||||
|
Text = "S_EVENT_MISSION_WINNER"
|
||||||
|
},
|
||||||
|
[EVENTS.PostponedTakeoff] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventPostponedTakeoff",
|
||||||
|
Text = "S_EVENT_POSTPONED_TAKEOFF"
|
||||||
|
},
|
||||||
|
[EVENTS.PostponedLand] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventPostponedLand",
|
||||||
|
Text = "S_EVENT_POSTPONED_LAND"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- The Events structure
|
--- The Events structure
|
||||||
@@ -1245,11 +1303,14 @@ function EVENT:onEvent( Event )
|
|||||||
Event.TgtDCSUnit = Event.target
|
Event.TgtDCSUnit = Event.target
|
||||||
if Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object
|
if Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object
|
||||||
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
-- Workaround for borked target info on cruise missiles
|
||||||
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
|
if Event.TgtDCSUnitName and Event.TgtDCSUnitName ~= "" then
|
||||||
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
|
||||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
||||||
|
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||||
|
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||||
|
end
|
||||||
else
|
else
|
||||||
Event.TgtDCSUnitName = string.format("No target object for Event ID %s", tostring(Event.id))
|
Event.TgtDCSUnitName = string.format("No target object for Event ID %s", tostring(Event.id))
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
@@ -1287,7 +1348,8 @@ function EVENT:onEvent( Event )
|
|||||||
Event.Weapon = Event.weapon
|
Event.Weapon = Event.weapon
|
||||||
Event.WeaponName = Event.Weapon:getTypeName()
|
Event.WeaponName = Event.Weapon:getTypeName()
|
||||||
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
|
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
|
||||||
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName()
|
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon.getPlayerName and Event.Weapon:getPlayerName()
|
||||||
|
--Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName()
|
||||||
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
|
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
|
||||||
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
|
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
|
||||||
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ do -- FSM
|
|||||||
--
|
--
|
||||||
-- ### Linear Transition Example
|
-- ### Linear Transition Example
|
||||||
--
|
--
|
||||||
-- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE_MISSIONS/blob/master/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua)
|
-- This example is fully implemented in the MOOSE test mission on GitHub: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Core/FSM/FSM-100%20-%20Transition%20Explanation)
|
||||||
--
|
--
|
||||||
-- It models a unit standing still near Batumi, and flaring every 5 seconds while switching between a Green flare and a Red flare.
|
-- It models a unit standing still near Batumi, and flaring every 5 seconds while switching between a Green flare and a Red flare.
|
||||||
-- The purpose of this example is not to show how exciting flaring is, but it demonstrates how a Linear Transition FSM can be build.
|
-- The purpose of this example is not to show how exciting flaring is, but it demonstrates how a Linear Transition FSM can be build.
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
|||||||
if CoalitionSide then
|
if CoalitionSide then
|
||||||
if self.MessageDuration ~= 0 then
|
if self.MessageDuration ~= 0 then
|
||||||
self:T( self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ) .. " / " .. self.MessageDuration )
|
self:T( self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ) .. " / " .. self.MessageDuration )
|
||||||
trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
trigger.action.outTextForCoalition( CoalitionSide, self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -459,14 +459,14 @@ end
|
|||||||
|
|
||||||
_MESSAGESRS = {}
|
_MESSAGESRS = {}
|
||||||
|
|
||||||
--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions.
|
--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions. `SetMSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #string PathToSRS Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone".
|
-- @param #string PathToSRS (optional) Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone" or your configuration file setting.
|
||||||
-- @param #number Port Port number of SRS, defaults to 5002.
|
-- @param #number Port Port (optional) number of SRS, defaults to 5002 or your configuration file setting.
|
||||||
-- @param #string PathToCredentials (optional) Path to credentials file for e.g. Google.
|
-- @param #string PathToCredentials (optional) Path to credentials file for Google.
|
||||||
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
|
-- @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 #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 "female".
|
-- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "female" or your configuration file setting.
|
||||||
-- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB"
|
-- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB" or your configuration file setting.
|
||||||
-- @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 #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 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 #number Volume (optional) Volume, can be between 0.0 and 1.0 (loudest).
|
||||||
@@ -480,45 +480,51 @@ _MESSAGESRS = {}
|
|||||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||||
--
|
--
|
||||||
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
|
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
|
||||||
_MESSAGESRS.MSRS = MSRS:New(PathToSRS,Frequency or 243,Modulation or radio.modulation.AM,Volume)
|
|
||||||
|
|
||||||
_MESSAGESRS.frequency = Frequency
|
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
_MESSAGESRS.modulation = Modulation or radio.modulation.AM
|
|
||||||
|
|
||||||
_MESSAGESRS.MSRS:SetCoalition(Coalition or coalition.side.NEUTRAL)
|
_MESSAGESRS.frequency = Frequency or MSRS.frequencies or 243
|
||||||
_MESSAGESRS.coalition = Coalition or coalition.side.NEUTRAL
|
_MESSAGESRS.modulation = Modulation or MSRS.modulations or radio.modulation.AM
|
||||||
|
|
||||||
|
_MESSAGESRS.MSRS = MSRS:New(_MESSAGESRS.PathToSRS,_MESSAGESRS.frequency, _MESSAGESRS.modulation)
|
||||||
|
|
||||||
|
_MESSAGESRS.coalition = Coalition or MSRS.coalition or coalition.side.NEUTRAL
|
||||||
|
_MESSAGESRS.MSRS:SetCoalition(_MESSAGESRS.coalition)
|
||||||
|
|
||||||
_MESSAGESRS.coordinate = Coordinate
|
_MESSAGESRS.coordinate = Coordinate
|
||||||
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
|
||||||
|
|
||||||
|
if Coordinate then
|
||||||
|
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
||||||
|
end
|
||||||
|
|
||||||
|
_MESSAGESRS.Culture = Culture or MSRS.culture or "en-GB"
|
||||||
_MESSAGESRS.MSRS:SetCulture(Culture)
|
_MESSAGESRS.MSRS:SetCulture(Culture)
|
||||||
_MESSAGESRS.Culture = Culture or "en-GB"
|
|
||||||
|
|
||||||
|
_MESSAGESRS.Gender = Gender or MSRS.gender or "female"
|
||||||
_MESSAGESRS.MSRS:SetGender(Gender)
|
_MESSAGESRS.MSRS:SetGender(Gender)
|
||||||
_MESSAGESRS.Gender = Gender or "female"
|
|
||||||
|
|
||||||
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
|
if PathToCredentials then
|
||||||
_MESSAGESRS.google = PathToCredentials
|
_MESSAGESRS.MSRS:SetProviderOptionsGoogle(PathToCredentials)
|
||||||
|
_MESSAGESRS.MSRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
|
end
|
||||||
_MESSAGESRS.label = Label or "MESSAGE"
|
|
||||||
|
|
||||||
_MESSAGESRS.MSRS:SetPort(Port or 5002)
|
|
||||||
_MESSAGESRS.port = Port or 5002
|
|
||||||
|
|
||||||
_MESSAGESRS.volume = Volume or 1
|
_MESSAGESRS.label = Label or MSRS.Label or "MESSAGE"
|
||||||
|
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
|
||||||
|
|
||||||
|
_MESSAGESRS.port = Port or MSRS.port or 5002
|
||||||
|
_MESSAGESRS.MSRS:SetPort(Port or 5002)
|
||||||
|
|
||||||
|
_MESSAGESRS.volume = Volume or MSRS.volume or 1
|
||||||
_MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)
|
_MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)
|
||||||
|
|
||||||
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
|
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
|
||||||
|
|
||||||
_MESSAGESRS.voice = Voice --or MSRS.Voices.Microsoft.Hedda
|
_MESSAGESRS.voice = Voice or MSRS.voice --or MSRS.Voices.Microsoft.Hedda
|
||||||
--if _MESSAGESRS.google and not Voice then _MESSAGESRS.Voice = MSRS.Voices.Google.Standard.en_GB_Standard_A end
|
|
||||||
--_MESSAGESRS.MSRS:SetVoice(Voice or _MESSAGESRS.voice)
|
|
||||||
|
|
||||||
_MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE")
|
_MESSAGESRS.SRSQ = MSRSQUEUE:New(_MESSAGESRS.label)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sends a message via SRS.
|
--- Sends a message via SRS. `ToSRS()` will try to use as many attributes configured with @{Core.Message#MESSAGE.SetMSRS}() and @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #MESSAGE self
|
-- @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 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 #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.
|
||||||
@@ -546,7 +552,7 @@ function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volum
|
|||||||
_MESSAGESRS.MSRS:SetCoordinate(coordinate)
|
_MESSAGESRS.MSRS:SetCoordinate(coordinate)
|
||||||
end
|
end
|
||||||
local category = string.gsub(self.MessageCategory,":","")
|
local category = string.gsub(self.MessageCategory,":","")
|
||||||
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency or _MESSAGESRS.frequency,modulation or _MESSAGESRS.modulation, gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,nil,volume or _MESSAGESRS.volume,category,coordinate or _MESSAGESRS.coordinate)
|
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,0.5,1,nil,nil,nil,frequency or _MESSAGESRS.frequency,modulation or _MESSAGESRS.modulation, gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,nil,volume or _MESSAGESRS.volume,category,coordinate or _MESSAGESRS.coordinate)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ PATHLINE = {
|
|||||||
|
|
||||||
--- PATHLINE class version.
|
--- PATHLINE class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
PATHLINE.version="0.1.0"
|
PATHLINE.version="0.1.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -237,13 +237,14 @@ end
|
|||||||
--- Get COORDINATES of pathline. Note that COORDINATE objects are created when calling this function. That does involve deep copy calls and can have an impact on performance if done too often.
|
--- Get COORDINATES of pathline. Note that COORDINATE objects are created when calling this function. That does involve deep copy calls and can have an impact on performance if done too often.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @return <Core.Point#COORDINATE> List of COORDINATES points.
|
-- @return <Core.Point#COORDINATE> List of COORDINATES points.
|
||||||
function PATHLINE:GetCoordinats()
|
function PATHLINE:GetCoordinates()
|
||||||
|
|
||||||
local vecs={}
|
local vecs={}
|
||||||
|
|
||||||
for _,_point in pairs(self.points) do
|
for _,_point in pairs(self.points) do
|
||||||
local point=_point --#PATHLINE.Point
|
local point=_point --#PATHLINE.Point
|
||||||
local coord=COORDINATE:NewFromVec3(point.vec3)
|
local coord=COORDINATE:NewFromVec3(point.vec3)
|
||||||
|
table.insert(vecs,coord)
|
||||||
end
|
end
|
||||||
|
|
||||||
return vecs
|
return vecs
|
||||||
@@ -262,7 +263,7 @@ function PATHLINE:GetPointFromIndex(n)
|
|||||||
local point=nil --#PATHLINE.Point
|
local point=nil --#PATHLINE.Point
|
||||||
|
|
||||||
if n>=1 and n<=N then
|
if n>=1 and n<=N then
|
||||||
point=self.point[n]
|
point=self.points[n]
|
||||||
else
|
else
|
||||||
self:E(self.lid..string.format("ERROR: No point in pathline for N=%s", tostring(n)))
|
self:E(self.lid..string.format("ERROR: No point in pathline for N=%s", tostring(n)))
|
||||||
end
|
end
|
||||||
@@ -367,4 +368,4 @@ end
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -8,22 +8,6 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- # Demo Missions
|
|
||||||
--
|
|
||||||
-- ### [POINT_VEC Demo Missions source code]()
|
|
||||||
--
|
|
||||||
-- ### [POINT_VEC Demo Missions, only for beta testers]()
|
|
||||||
--
|
|
||||||
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # YouTube Channel
|
|
||||||
--
|
|
||||||
-- ### [POINT_VEC YouTube Channel]()
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Authors:
|
-- ### Authors:
|
||||||
--
|
--
|
||||||
-- * FlightControl (Design & Programming)
|
-- * FlightControl (Design & Programming)
|
||||||
@@ -40,8 +24,9 @@
|
|||||||
|
|
||||||
|
|
||||||
do -- COORDINATE
|
do -- COORDINATE
|
||||||
|
|
||||||
--- @type COORDINATE
|
---
|
||||||
|
-- @type COORDINATE
|
||||||
-- @field #string ClassName Name of the class
|
-- @field #string ClassName Name of the class
|
||||||
-- @field #number x Component of the 3D vector.
|
-- @field #number x Component of the 3D vector.
|
||||||
-- @field #number y Component of the 3D vector.
|
-- @field #number y Component of the 3D vector.
|
||||||
@@ -196,7 +181,7 @@ do -- COORDINATE
|
|||||||
-- * @{#COORDINATE.ToStringBR}(): Generates a Bearing & Range text in the format of DDD for DI where DDD is degrees and DI is distance.
|
-- * @{#COORDINATE.ToStringBR}(): Generates a Bearing & Range text in the format of DDD for DI where DDD is degrees and DI is distance.
|
||||||
-- * @{#COORDINATE.ToStringBRA}(): Generates a Bearing, Range & Altitude text.
|
-- * @{#COORDINATE.ToStringBRA}(): Generates a Bearing, Range & Altitude text.
|
||||||
-- * @{#COORDINATE.ToStringBRAANATO}(): Generates a Generates a Bearing, Range, Aspect & Altitude text in NATOPS.
|
-- * @{#COORDINATE.ToStringBRAANATO}(): Generates a Generates a Bearing, Range, Aspect & Altitude text in NATOPS.
|
||||||
-- * @{#COORDINATE.ToStringLL}(): Generates a Latutide & Longitude text.
|
-- * @{#COORDINATE.ToStringLL}(): Generates a Latitude & Longitude text.
|
||||||
-- * @{#COORDINATE.ToStringLLDMS}(): Generates a Lat, Lon, Degree, Minute, Second text.
|
-- * @{#COORDINATE.ToStringLLDMS}(): Generates a Lat, Lon, Degree, Minute, Second text.
|
||||||
-- * @{#COORDINATE.ToStringLLDDM}(): Generates a Lat, Lon, Degree, decimal Minute text.
|
-- * @{#COORDINATE.ToStringLLDDM}(): Generates a Lat, Lon, Degree, decimal Minute text.
|
||||||
-- * @{#COORDINATE.ToStringMGRS}(): Generates a MGRS grid coordinate text.
|
-- * @{#COORDINATE.ToStringMGRS}(): Generates a MGRS grid coordinate text.
|
||||||
@@ -920,7 +905,7 @@ do -- COORDINATE
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Return an angle in radians from the COORDINATE using a direction vector in Vec3 format.
|
--- Return an angle in radians from the COORDINATE using a **direction vector in Vec3 format**.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
|
-- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
|
||||||
-- @return #number DirectionRadians The angle in radians.
|
-- @return #number DirectionRadians The angle in radians.
|
||||||
@@ -933,10 +918,12 @@ do -- COORDINATE
|
|||||||
return DirectionRadians
|
return DirectionRadians
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return an angle in degrees from the COORDINATE using a direction vector in Vec3 format.
|
--- Return an angle in degrees from the COORDINATE using a **direction vector in Vec3 format**.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
|
-- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
|
||||||
-- @return #number DirectionRadians The angle in degrees.
|
-- @return #number DirectionRadians The angle in degrees.
|
||||||
|
-- @usage
|
||||||
|
-- local directionAngle = currentCoordinate:GetAngleDegrees(currentCoordinate:GetDirectionVec3(sourceCoordinate:GetVec3()))
|
||||||
function COORDINATE:GetAngleDegrees( DirectionVec3 )
|
function COORDINATE:GetAngleDegrees( DirectionVec3 )
|
||||||
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
|
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
|
||||||
local Angle = UTILS.ToDegree( AngleRadians )
|
local Angle = UTILS.ToDegree( AngleRadians )
|
||||||
@@ -2469,15 +2456,18 @@ do -- COORDINATE
|
|||||||
-- Write command as string and execute that. Idea by Grimes https://forum.dcs.world/topic/324201-mark-to-all-function/#comment-5273793
|
-- 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)
|
local s=string.format("trigger.action.markupToAll(7, %d, %d,", Coalition, MarkID)
|
||||||
for _,vec in pairs(vecs) do
|
for _,vec in pairs(vecs) do
|
||||||
s=s..string.format("%s,", UTILS._OneLineSerialize(vec))
|
--s=s..string.format("%s,", UTILS._OneLineSerialize(vec))
|
||||||
|
s=s..string.format("{x=%.1f, y=%.1f, z=%.1f},", vec.x, vec.y, vec.z)
|
||||||
end
|
end
|
||||||
s=s..string.format("%s, %s, %s, %s", UTILS._OneLineSerialize(Color), UTILS._OneLineSerialize(FillColor), tostring(LineType), tostring(ReadOnly))
|
s=s..string.format("{%.3f, %.3f, %.3f, %.3f},", Color[1], Color[2], Color[3], Color[4])
|
||||||
if Text and Text~="" then
|
s=s..string.format("{%.3f, %.3f, %.3f, %.3f},", FillColor[1], FillColor[2], FillColor[3], FillColor[4])
|
||||||
s=s..string.format(", \"%s\"", Text)
|
s=s..string.format("%d,", LineType or 1)
|
||||||
|
s=s..string.format("%s", tostring(ReadOnly))
|
||||||
|
if Text and type(Text)=="string" and string.len(Text)>0 then
|
||||||
|
s=s..string.format(", \"%s\"", tostring(Text))
|
||||||
end
|
end
|
||||||
s=s..")"
|
s=s..")"
|
||||||
|
|
||||||
|
|
||||||
-- Execute string command
|
-- Execute string command
|
||||||
local success=UTILS.DoString(s)
|
local success=UTILS.DoString(s)
|
||||||
|
|
||||||
@@ -2565,7 +2555,7 @@ do -- COORDINATE
|
|||||||
|
|
||||||
Offset=Offset or 2
|
Offset=Offset or 2
|
||||||
|
|
||||||
-- Measurement of visibility should not be from the ground, so Adding a hypotethical 2 meters to each Coordinate.
|
-- Measurement of visibility should not be from the ground, so Adding a hypothetical 2 meters to each Coordinate.
|
||||||
local FromVec3 = self:GetVec3()
|
local FromVec3 = self:GetVec3()
|
||||||
FromVec3.y = FromVec3.y + Offset
|
FromVec3.y = FromVec3.y + Offset
|
||||||
|
|
||||||
@@ -2966,10 +2956,10 @@ do -- COORDINATE
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- corrected Track to be direction of travel of bogey (self in this case)
|
-- corrected Track to be direction of travel of bogey (self in this case)
|
||||||
local track = "Maneuver"
|
local track = "Maneuver"
|
||||||
|
|
||||||
if self.Heading then
|
if self.Heading then
|
||||||
track = UTILS.BearingToCardinal(self.Heading) or "North"
|
track = UTILS.BearingToCardinal(self.Heading) or "North"
|
||||||
end
|
end
|
||||||
|
|
||||||
if rangeNM > 3 then
|
if rangeNM > 3 then
|
||||||
@@ -3021,6 +3011,16 @@ do -- COORDINATE
|
|||||||
return BRAANATO
|
return BRAANATO
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Return the BULLSEYE as COORDINATE Object
|
||||||
|
-- @param #number Coalition Coalition of the bulls eye to return, e.g. coalition.side.BLUE
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
-- @usage
|
||||||
|
-- -- note the dot (.) here,not using the colon (:)
|
||||||
|
-- local redbulls = COORDINATE.GetBullseyeCoordinate(coalition.side.RED)
|
||||||
|
function COORDINATE.GetBullseyeCoordinate(Coalition)
|
||||||
|
return COORDINATE:NewFromVec3( coalition.getMainRefPoint( Coalition ) )
|
||||||
|
end
|
||||||
|
|
||||||
--- Return a BULLS string out of the BULLS of the coalition to the COORDINATE.
|
--- Return a BULLS string out of the BULLS of the coalition to the COORDINATE.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param DCS#coalition.side Coalition The coalition.
|
-- @param DCS#coalition.side Coalition The coalition.
|
||||||
@@ -3071,6 +3071,18 @@ do -- COORDINATE
|
|||||||
return coord.LOtoLL( self:GetVec3() )
|
return coord.LOtoLL( self:GetVec3() )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get Latitude & Longitude text.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
||||||
|
-- @return #string LLText
|
||||||
|
function COORDINATE:ToStringLL( Settings )
|
||||||
|
|
||||||
|
local LL_Accuracy = Settings and Settings.LL_Accuracy or _SETTINGS.LL_Accuracy
|
||||||
|
local lat, lon = coord.LOtoLL( self:GetVec3() )
|
||||||
|
return string.format('%f', lat) .. ' ' .. string.format('%f', lon)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Provides a Lat Lon string in Degree Minute Second format.
|
--- Provides a Lat Lon string in Degree Minute Second format.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
||||||
@@ -3104,6 +3116,49 @@ do -- COORDINATE
|
|||||||
local MGRS = coord.LLtoMGRS( lat, lon )
|
local MGRS = coord.LLtoMGRS( lat, lon )
|
||||||
return "MGRS " .. UTILS.tostringMGRS( MGRS, MGRS_Accuracy )
|
return "MGRS " .. UTILS.tostringMGRS( MGRS, MGRS_Accuracy )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Provides a COORDINATE from an MGRS String
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #string MGRSString MGRS String, e.g. "MGRS 37T DK 12345 12345"
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:NewFromMGRSString( MGRSString )
|
||||||
|
local myparts = UTILS.Split(MGRSString," ")
|
||||||
|
local northing = tostring(myparts[5]) or ""
|
||||||
|
local easting = tostring(myparts[4]) or ""
|
||||||
|
if string.len(easting) < 5 then easting = easting..string.rep("0",5-string.len(easting)) end
|
||||||
|
if string.len(northing) < 5 then northing = northing..string.rep("0",5-string.len(northing)) end
|
||||||
|
local MGRS = {
|
||||||
|
UTMZone = myparts[2],
|
||||||
|
MGRSDigraph = myparts[3],
|
||||||
|
Easting = easting,
|
||||||
|
Northing = northing,
|
||||||
|
}
|
||||||
|
local lat, lon = coord.MGRStoLL(MGRS)
|
||||||
|
local point = coord.LLtoLO(lat, lon, 0)
|
||||||
|
local coord = COORDINATE:NewFromVec2({x=point.x,y=point.z})
|
||||||
|
return coord
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Provides a COORDINATE from an MGRS Coordinate
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #string UTMZone UTM Zone, e.g. "37T"
|
||||||
|
-- @param #string MGRSDigraph Digraph, e.g. "DK"
|
||||||
|
-- @param #string Easting Meters easting - string in order to allow for leading zeros, e.g. "01234". Should be 5 digits.
|
||||||
|
-- @param #string Northing Meters northing - string in order to allow for leading zeros, e.g. "12340". Should be 5 digits.
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:NewFromMGRS( UTMZone, MGRSDigraph, Easting, Northing )
|
||||||
|
if string.len(Easting) < 5 then Easting = Easting..string.rep("0",5-string.len(Easting) )end
|
||||||
|
if string.len(Northing) < 5 then Northing = Northing..string.rep("0",5-string.len(Northing) )end
|
||||||
|
local MGRS = {
|
||||||
|
UTMZone = UTMZone,
|
||||||
|
MGRSDigraph = MGRSDigraph,
|
||||||
|
Easting = Easting,
|
||||||
|
Northing = Northing,
|
||||||
|
}
|
||||||
|
local lat, lon = coord.MGRStoLL(MGRS)
|
||||||
|
local point = coord.LLtoLO(lat, lon, 0)
|
||||||
|
local coord = COORDINATE:NewFromVec2({x=point.x,y=point.z})
|
||||||
|
end
|
||||||
|
|
||||||
--- Provides a coordinate string of the point, based on a coordinate format system:
|
--- Provides a coordinate string of the point, based on a coordinate format system:
|
||||||
-- * Uses default settings in COORDINATE.
|
-- * Uses default settings in COORDINATE.
|
||||||
@@ -3617,7 +3672,7 @@ end
|
|||||||
|
|
||||||
do -- POINT_VEC2
|
do -- POINT_VEC2
|
||||||
|
|
||||||
--- @type POINT_VEC2
|
-- @type POINT_VEC2
|
||||||
-- @field DCS#Distance x The x coordinate in meters.
|
-- @field DCS#Distance x The x coordinate in meters.
|
||||||
-- @field DCS#Distance y the y coordinate in meters.
|
-- @field DCS#Distance y the y coordinate in meters.
|
||||||
-- @extends Core.Point#COORDINATE
|
-- @extends Core.Point#COORDINATE
|
||||||
|
|||||||
@@ -14,17 +14,13 @@
|
|||||||
--
|
--
|
||||||
-- # Demo Missions
|
-- # Demo Missions
|
||||||
--
|
--
|
||||||
-- ### [SCHEDULER Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SCH%20-%20Scheduler)
|
-- ### [SCHEDULER Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Core/Scheduler)
|
||||||
--
|
|
||||||
-- ### [SCHEDULER Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SCH%20-%20Scheduler)
|
|
||||||
--
|
|
||||||
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- # YouTube Channel
|
-- # YouTube Channel
|
||||||
--
|
--
|
||||||
-- ### [SCHEDULER YouTube Channel (none)]()
|
-- ### None
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -146,7 +146,45 @@ do -- SET_BASE
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [Internal] Add a functional filter
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a CONTROLLABLE object as first argument.
|
||||||
|
-- @param ... Condition function arguments, if any.
|
||||||
|
-- @return #boolean If true, at least one condition is true
|
||||||
|
function SET_BASE:FilterFunction(ConditionFunction, ...)
|
||||||
|
|
||||||
|
local condition={}
|
||||||
|
condition.func=ConditionFunction
|
||||||
|
condition.arg={}
|
||||||
|
|
||||||
|
if arg then
|
||||||
|
condition.arg=arg
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self.Filter.Functions then self.Filter.Functions = {} end
|
||||||
|
table.insert(self.Filter.Functions, condition)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] Check if the condition functions returns true.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE Object The object to filter for
|
||||||
|
-- @return #boolean If true, if **all** conditions are true
|
||||||
|
function SET_BASE:_EvalFilterFunctions(Object)
|
||||||
|
-- All conditions must be true.
|
||||||
|
for _,_condition in pairs(self.Filter.Functions or {}) do
|
||||||
|
local condition=_condition
|
||||||
|
-- Call function.
|
||||||
|
if condition.func(Object,unpack(condition.arg)) == false then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- No condition was true.
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
--- Clear the Objects in the Set.
|
--- Clear the Objects in the Set.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @param #boolean TriggerEvent If `true`, an event remove is triggered for each group that is removed from the set.
|
-- @param #boolean TriggerEvent If `true`, an event remove is triggered for each group that is removed from the set.
|
||||||
@@ -417,13 +455,34 @@ do -- SET_BASE
|
|||||||
|
|
||||||
--- Gets a random object from the @{Core.Set#SET_BASE} and derived classes.
|
--- Gets a random object from the @{Core.Set#SET_BASE} and derived classes.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @return Core.Base#BASE
|
-- @return Core.Base#BASE or nil if none found or the SET is empty!
|
||||||
function SET_BASE:GetRandom()
|
function SET_BASE:GetRandom()
|
||||||
local tablemax = table.maxn(self.Index)
|
local tablemax = 0
|
||||||
|
for _,_ind in pairs(self.Index) do
|
||||||
|
tablemax = tablemax + 1
|
||||||
|
end
|
||||||
|
--local tablemax = table.maxn(self.Index)
|
||||||
local RandomItem = self.Set[self.Index[math.random(1,tablemax)]]
|
local RandomItem = self.Set[self.Index[math.random(1,tablemax)]]
|
||||||
self:T3( { RandomItem } )
|
self:T3( { RandomItem } )
|
||||||
return RandomItem
|
return RandomItem
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets a random object from the @{Core.Set#SET_BASE} and derived classes. A bit slower than @{#SET_BASE.GetRandom}() but tries to ensure you get an object back if the SET is not empty.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @return Core.Base#BASE or nil if the SET is empty!
|
||||||
|
function SET_BASE:GetRandomSurely()
|
||||||
|
local tablemax = 0
|
||||||
|
local sorted = {}
|
||||||
|
for _,_obj in pairs(self.Set) do
|
||||||
|
tablemax = tablemax + 1
|
||||||
|
sorted[tablemax] = _obj
|
||||||
|
end
|
||||||
|
--local tablemax = table.maxn(self.Index)
|
||||||
|
--local RandomItem = self.Set[self.Index[math.random(1,tablemax)]]
|
||||||
|
local RandomItem = sorted[math.random(1,tablemax)]
|
||||||
|
self:T3( { RandomItem } )
|
||||||
|
return RandomItem
|
||||||
|
end
|
||||||
|
|
||||||
--- Retrieves the amount of objects in the @{Core.Set#SET_BASE} and derived classes.
|
--- Retrieves the amount of objects in the @{Core.Set#SET_BASE} and derived classes.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
@@ -561,10 +620,12 @@ do -- SET_BASE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Iterate the SET_BASE while identifying the nearest object from a @{Core.Point#POINT_VEC2}.
|
--- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#POINT_VEC2}.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest object in the set.
|
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#COORDINATE} or @{Core.Point#POINT_VEC2} object (but **not** a simple DCS#Vec2!) from where to evaluate the closest object in the set.
|
||||||
-- @return Core.Base#BASE The closest object.
|
-- @return Core.Base#BASE The closest object.
|
||||||
|
-- @usage
|
||||||
|
-- myset:FindNearestObjectFromPointVec2( ZONE:New("Test Zone"):GetCoordinate() )
|
||||||
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
|
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
|
||||||
self:F2( PointVec2 )
|
self:F2( PointVec2 )
|
||||||
|
|
||||||
@@ -961,6 +1022,7 @@ do
|
|||||||
-- * @{#SET_GROUP.FilterCategoryShip}: Builds the SET_GROUP from ships.
|
-- * @{#SET_GROUP.FilterCategoryShip}: Builds the SET_GROUP from ships.
|
||||||
-- * @{#SET_GROUP.FilterCategoryStructure}: Builds the SET_GROUP from structures.
|
-- * @{#SET_GROUP.FilterCategoryStructure}: Builds the SET_GROUP from structures.
|
||||||
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Core.Zone#ZONE}.
|
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Core.Zone#ZONE}.
|
||||||
|
-- * @{#SET_GROUP.FilterFunction}: Builds the SET_GROUP with a custom condition.
|
||||||
--
|
--
|
||||||
-- Once the filter criteria have been set for the SET_GROUP, you can start filtering using:
|
-- Once the filter criteria have been set for the SET_GROUP, you can start filtering using:
|
||||||
--
|
--
|
||||||
@@ -1034,6 +1096,7 @@ do
|
|||||||
Countries = nil,
|
Countries = nil,
|
||||||
GroupPrefixes = nil,
|
GroupPrefixes = nil,
|
||||||
Zones = nil,
|
Zones = nil,
|
||||||
|
Functions = nil,
|
||||||
},
|
},
|
||||||
FilterMeta = {
|
FilterMeta = {
|
||||||
Coalitions = {
|
Coalitions = {
|
||||||
@@ -1065,8 +1128,15 @@ do
|
|||||||
self:FilterActive( false )
|
self:FilterActive( false )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
--- Filter the set once
|
||||||
|
-- @function [parent=#SET_GROUP] FilterOnce
|
||||||
|
-- @param #SET_GROUP self
|
||||||
|
-- @return #SET_GROUP self
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get a *new* set that only contains alive groups.
|
--- Get a *new* set that only contains alive groups.
|
||||||
-- @param #SET_GROUP self
|
-- @param #SET_GROUP self
|
||||||
-- @return #SET_GROUP Set of alive groups.
|
-- @return #SET_GROUP Set of alive groups.
|
||||||
@@ -1134,7 +1204,7 @@ do
|
|||||||
if not DontSetCargoBayLimit then
|
if not DontSetCargoBayLimit then
|
||||||
-- I set the default cargo bay weight limit each time a new group is added to the set.
|
-- I set the default cargo bay weight limit each time a new group is added to the set.
|
||||||
-- TODO Why is this here in the first place?
|
-- TODO Why is this here in the first place?
|
||||||
for UnitID, UnitData in pairs( group:GetUnits() ) do
|
for UnitID, UnitData in pairs( group:GetUnits() or {} ) do
|
||||||
if UnitData and UnitData:IsAlive() then
|
if UnitData and UnitData:IsAlive() then
|
||||||
UnitData:SetCargoBayWeightLimit()
|
UnitData:SetCargoBayWeightLimit()
|
||||||
end
|
end
|
||||||
@@ -1240,7 +1310,26 @@ do
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Add a custom condition function.
|
||||||
|
-- @function [parent=#SET_GROUP] FilterFunction
|
||||||
|
-- @param #SET_GROUP self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a GROUP object as first argument.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #SET_GROUP self
|
||||||
|
-- @usage
|
||||||
|
-- -- Image you want to exclude a specific GROUP from a SET:
|
||||||
|
-- local groundset = SET_GROUP:New():FilterCoalitions("blue"):FilterCategoryGround():FilterFunction(
|
||||||
|
-- -- The function needs to take a GROUP object as first - and in this case, only - argument.
|
||||||
|
-- function(grp)
|
||||||
|
-- local isinclude = true
|
||||||
|
-- if grp:GetName() == "Exclude Me" then isinclude = false end
|
||||||
|
-- return isinclude
|
||||||
|
-- end
|
||||||
|
-- ):FilterOnce()
|
||||||
|
-- BASE:I(groundset:Flush())
|
||||||
|
|
||||||
|
|
||||||
--- Builds a set of groups of coalitions.
|
--- Builds a set of groups of coalitions.
|
||||||
-- Possible current coalitions are red, blue and neutral.
|
-- Possible current coalitions are red, blue and neutral.
|
||||||
-- @param #SET_GROUP self
|
-- @param #SET_GROUP self
|
||||||
@@ -1489,7 +1578,7 @@ do
|
|||||||
function SET_GROUP:AddInDatabase( Event )
|
function SET_GROUP:AddInDatabase( Event )
|
||||||
self:F3( { Event } )
|
self:F3( { Event } )
|
||||||
|
|
||||||
if Event.IniObjectCategory == 1 then
|
if Event.IniObjectCategory == Object.Category.UNIT then
|
||||||
if not self.Database[Event.IniDCSGroupName] then
|
if not self.Database[Event.IniDCSGroupName] then
|
||||||
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
||||||
self:T3( self.Database[Event.IniDCSGroupName] )
|
self:T3( self.Database[Event.IniDCSGroupName] )
|
||||||
@@ -1914,7 +2003,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupActive
|
MGroupInclude = MGroupInclude and MGroupActive
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Coalitions then
|
if self.Filter.Coalitions and MGroupInclude then
|
||||||
local MGroupCoalition = false
|
local MGroupCoalition = false
|
||||||
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
||||||
self:T3( { "Coalition:", MGroup:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
self:T3( { "Coalition:", MGroup:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
||||||
@@ -1925,7 +2014,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupCoalition
|
MGroupInclude = MGroupInclude and MGroupCoalition
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MGroupInclude then
|
||||||
local MGroupCategory = false
|
local MGroupCategory = false
|
||||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||||
self:T3( { "Category:", MGroup:GetCategory(), self.FilterMeta.Categories[CategoryName], CategoryName } )
|
self:T3( { "Category:", MGroup:GetCategory(), self.FilterMeta.Categories[CategoryName], CategoryName } )
|
||||||
@@ -1936,7 +2025,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupCategory
|
MGroupInclude = MGroupInclude and MGroupCategory
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Countries then
|
if self.Filter.Countries and MGroupInclude then
|
||||||
local MGroupCountry = false
|
local MGroupCountry = false
|
||||||
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
||||||
self:T3( { "Country:", MGroup:GetCountry(), CountryName } )
|
self:T3( { "Country:", MGroup:GetCountry(), CountryName } )
|
||||||
@@ -1947,7 +2036,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupCountry
|
MGroupInclude = MGroupInclude and MGroupCountry
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.GroupPrefixes then
|
if self.Filter.GroupPrefixes and MGroupInclude then
|
||||||
local MGroupPrefix = false
|
local MGroupPrefix = false
|
||||||
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
||||||
self:T3( { "Prefix:", string.find( MGroup:GetName(), GroupPrefix, 1 ), GroupPrefix } )
|
self:T3( { "Prefix:", string.find( MGroup:GetName(), GroupPrefix, 1 ), GroupPrefix } )
|
||||||
@@ -1958,7 +2047,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupPrefix
|
MGroupInclude = MGroupInclude and MGroupPrefix
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Zones then
|
if self.Filter.Zones and MGroupInclude then
|
||||||
local MGroupZone = false
|
local MGroupZone = false
|
||||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||||
--self:T( "Zone:", ZoneName )
|
--self:T( "Zone:", ZoneName )
|
||||||
@@ -1968,6 +2057,12 @@ do
|
|||||||
end
|
end
|
||||||
MGroupInclude = MGroupInclude and MGroupZone
|
MGroupInclude = MGroupInclude and MGroupZone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.Filter.Functions and MGroupInclude then
|
||||||
|
local MGroupFunc = false
|
||||||
|
MGroupFunc = self:_EvalFilterFunctions(MGroup)
|
||||||
|
MGroupInclude = MGroupInclude and MGroupFunc
|
||||||
|
end
|
||||||
|
|
||||||
self:T2( MGroupInclude )
|
self:T2( MGroupInclude )
|
||||||
return MGroupInclude
|
return MGroupInclude
|
||||||
@@ -1976,6 +2071,7 @@ do
|
|||||||
--- Get the closest group of the set with respect to a given reference coordinate. Optionally, only groups of given coalitions are considered in the search.
|
--- Get the closest group of the set with respect to a given reference coordinate. Optionally, only groups of given coalitions are considered in the search.
|
||||||
-- @param #SET_GROUP self
|
-- @param #SET_GROUP self
|
||||||
-- @param Core.Point#COORDINATE Coordinate Reference Coordinate from which the closest group is determined.
|
-- @param Core.Point#COORDINATE Coordinate Reference Coordinate from which the closest group is determined.
|
||||||
|
-- @param #table Coalitions (Optional) Table of coalition #number entries to filter for.
|
||||||
-- @return Wrapper.Group#GROUP The closest group (if any).
|
-- @return Wrapper.Group#GROUP The closest group (if any).
|
||||||
-- @return #number Distance in meters to the closest group.
|
-- @return #number Distance in meters to the closest group.
|
||||||
function SET_GROUP:GetClosestGroup(Coordinate, Coalitions)
|
function SET_GROUP:GetClosestGroup(Coordinate, Coalitions)
|
||||||
@@ -2066,6 +2162,7 @@ do -- SET_UNIT
|
|||||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
-- 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.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}.
|
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Core.Zone#ZONE}.
|
||||||
|
-- * @{#SET_UNIT.FilterFunction}: Builds the SET_UNIT with a custom condition.
|
||||||
--
|
--
|
||||||
-- Once the filter criteria have been set for the SET_UNIT, you can start filtering using:
|
-- Once the filter criteria have been set for the SET_UNIT, you can start filtering using:
|
||||||
--
|
--
|
||||||
@@ -2144,6 +2241,7 @@ do -- SET_UNIT
|
|||||||
Countries = nil,
|
Countries = nil,
|
||||||
UnitPrefixes = nil,
|
UnitPrefixes = nil,
|
||||||
Zones = nil,
|
Zones = nil,
|
||||||
|
Functions = nil,
|
||||||
},
|
},
|
||||||
FilterMeta = {
|
FilterMeta = {
|
||||||
Coalitions = {
|
Coalitions = {
|
||||||
@@ -2425,6 +2523,26 @@ do -- SET_UNIT
|
|||||||
return CountU
|
return CountU
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the alive set.
|
||||||
|
-- @param #SET_UNIT self
|
||||||
|
-- @return #table Table of SET objects
|
||||||
|
-- @return #SET_UNIT AliveSet
|
||||||
|
function SET_UNIT:GetAliveSet()
|
||||||
|
|
||||||
|
local AliveSet = SET_UNIT:New()
|
||||||
|
|
||||||
|
-- Clean the Set before returning with only the alive Groups.
|
||||||
|
for GroupName, GroupObject in pairs(self.Set) do
|
||||||
|
local GroupObject=GroupObject --Wrapper.Client#CLIENT
|
||||||
|
|
||||||
|
if GroupObject and GroupObject:IsAlive() then
|
||||||
|
AliveSet:Add(GroupName, GroupObject)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return AliveSet.Set or {}, AliveSet
|
||||||
|
end
|
||||||
|
|
||||||
--- [Internal] Private function for use of continous zone filter
|
--- [Internal] Private function for use of continous zone filter
|
||||||
-- @param #SET_UNIT self
|
-- @param #SET_UNIT self
|
||||||
-- @return #SET_UNIT self
|
-- @return #SET_UNIT self
|
||||||
@@ -2495,6 +2613,25 @@ do -- SET_UNIT
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Add a custom condition function.
|
||||||
|
-- @function [parent=#SET_UNIT] FilterFunction
|
||||||
|
-- @param #SET_UNIT self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a UNIT object as first argument.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #SET_UNIT self
|
||||||
|
-- @usage
|
||||||
|
-- -- Image you want to exclude a specific UNIT from a SET:
|
||||||
|
-- local groundset = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterFunction(
|
||||||
|
-- -- The function needs to take a UNIT object as first - and in this case, only - argument.
|
||||||
|
-- function(unit)
|
||||||
|
-- local isinclude = true
|
||||||
|
-- if unit:GetName() == "Exclude Me" then isinclude = false end
|
||||||
|
-- return isinclude
|
||||||
|
-- end
|
||||||
|
-- ):FilterOnce()
|
||||||
|
-- BASE:I(groundset:Flush())
|
||||||
|
|
||||||
|
|
||||||
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
||||||
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
||||||
-- @param #SET_UNIT self
|
-- @param #SET_UNIT self
|
||||||
@@ -2504,7 +2641,7 @@ do -- SET_UNIT
|
|||||||
function SET_UNIT:AddInDatabase( Event )
|
function SET_UNIT:AddInDatabase( Event )
|
||||||
self:F3( { Event } )
|
self:F3( { Event } )
|
||||||
|
|
||||||
if Event.IniObjectCategory == 1 then
|
if Event.IniObjectCategory == Object.Category.UNIT then
|
||||||
if not self.Database[Event.IniDCSUnitName] then
|
if not self.Database[Event.IniDCSUnitName] then
|
||||||
self.Database[Event.IniDCSUnitName] = UNIT:Register( Event.IniDCSUnitName )
|
self.Database[Event.IniDCSUnitName] = UNIT:Register( Event.IniDCSUnitName )
|
||||||
self:T3( self.Database[Event.IniDCSUnitName] )
|
self:T3( self.Database[Event.IniDCSUnitName] )
|
||||||
@@ -2819,53 +2956,51 @@ do -- SET_UNIT
|
|||||||
-- @param #SET_UNIT self
|
-- @param #SET_UNIT self
|
||||||
-- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units.
|
-- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units.
|
||||||
function SET_UNIT:GetCoordinate()
|
function SET_UNIT:GetCoordinate()
|
||||||
|
|
||||||
local Coordinate = self:GetRandom():GetCoordinate()
|
|
||||||
--self:F({Coordinate:GetVec3()})
|
|
||||||
|
|
||||||
|
local function GetSetVec3(units)
|
||||||
local x1 = Coordinate.x
|
-- Init.
|
||||||
local x2 = Coordinate.x
|
local x=0
|
||||||
local y1 = Coordinate.y
|
local y=0
|
||||||
local y2 = Coordinate.y
|
local z=0
|
||||||
local z1 = Coordinate.z
|
local n=0
|
||||||
local z2 = Coordinate.z
|
-- Loop over all units.
|
||||||
local MaxVelocity = 0
|
for _,unit in pairs(units) do
|
||||||
local AvgHeading = nil
|
local vec3=nil --DCS#Vec3
|
||||||
local MovingCount = 0
|
if unit and unit:IsAlive() then
|
||||||
|
vec3 = unit:GetVec3()
|
||||||
for UnitName, UnitData in pairs( self:GetSet() ) do
|
end
|
||||||
|
if vec3 then
|
||||||
local Unit = UnitData -- Wrapper.Unit#UNIT
|
-- Sum up posits.
|
||||||
local Coordinate = Unit:GetCoordinate()
|
x=x+vec3.x
|
||||||
|
y=y+vec3.y
|
||||||
x1 = (Coordinate.x < x1) and Coordinate.x or x1
|
z=z+vec3.z
|
||||||
x2 = (Coordinate.x > x2) and Coordinate.x or x2
|
-- Increase counter.
|
||||||
y1 = (Coordinate.y < y1) and Coordinate.y or y1
|
n=n+1
|
||||||
y2 = (Coordinate.y > y2) and Coordinate.y or y2
|
end
|
||||||
z1 = (Coordinate.y < z1) and Coordinate.z or z1
|
|
||||||
z2 = (Coordinate.y > z2) and Coordinate.z or z2
|
|
||||||
|
|
||||||
local Velocity = Coordinate:GetVelocity()
|
|
||||||
if Velocity ~= 0 then
|
|
||||||
MaxVelocity = (MaxVelocity < Velocity) and Velocity or MaxVelocity
|
|
||||||
local Heading = Coordinate:GetHeading()
|
|
||||||
AvgHeading = AvgHeading and (AvgHeading + Heading) or Heading
|
|
||||||
MovingCount = MovingCount + 1
|
|
||||||
end
|
end
|
||||||
|
if n>0 then
|
||||||
|
-- Average.
|
||||||
|
local Vec3={x=x/n, y=y/n, z=z/n} --DCS#Vec3
|
||||||
|
return Vec3
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local Coordinate = nil
|
||||||
|
local Vec3 = GetSetVec3(self.Set)
|
||||||
|
if Vec3 then
|
||||||
|
Coordinate = COORDINATE:NewFromVec3(Vec3)
|
||||||
end
|
end
|
||||||
|
|
||||||
AvgHeading = AvgHeading and (AvgHeading / MovingCount)
|
if Coordinate then
|
||||||
|
local heading = self:GetHeading() or 0
|
||||||
|
local velocity = self:GetVelocity() or 0
|
||||||
|
Coordinate:SetHeading( heading )
|
||||||
|
Coordinate:SetVelocity( velocity )
|
||||||
|
self:I(UTILS.PrintTableToLog(Coordinate))
|
||||||
|
end
|
||||||
|
|
||||||
Coordinate.x = (x2 - x1) / 2 + x1
|
|
||||||
Coordinate.y = (y2 - y1) / 2 + y1
|
|
||||||
Coordinate.z = (z2 - z1) / 2 + z1
|
|
||||||
Coordinate:SetHeading( AvgHeading )
|
|
||||||
Coordinate:SetVelocity( MaxVelocity )
|
|
||||||
|
|
||||||
self:F( { Coordinate = Coordinate } )
|
|
||||||
return Coordinate
|
return Coordinate
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the maximum velocity of the SET_UNIT.
|
--- Get the maximum velocity of the SET_UNIT.
|
||||||
@@ -3074,7 +3209,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitActive
|
MUnitInclude = MUnitInclude and MUnitActive
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Coalitions then
|
if self.Filter.Coalitions and MUnitInclude then
|
||||||
local MUnitCoalition = false
|
local MUnitCoalition = false
|
||||||
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
||||||
self:F( { "Coalition:", MUnit:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
self:F( { "Coalition:", MUnit:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
||||||
@@ -3085,7 +3220,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitCoalition
|
MUnitInclude = MUnitInclude and MUnitCoalition
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MUnitInclude then
|
||||||
local MUnitCategory = false
|
local MUnitCategory = false
|
||||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||||
self:T3( { "Category:", MUnit:GetDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } )
|
self:T3( { "Category:", MUnit:GetDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } )
|
||||||
@@ -3096,7 +3231,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitCategory
|
MUnitInclude = MUnitInclude and MUnitCategory
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Types then
|
if self.Filter.Types and MUnitInclude then
|
||||||
local MUnitType = false
|
local MUnitType = false
|
||||||
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
||||||
self:T3( { "Type:", MUnit:GetTypeName(), TypeName } )
|
self:T3( { "Type:", MUnit:GetTypeName(), TypeName } )
|
||||||
@@ -3107,7 +3242,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitType
|
MUnitInclude = MUnitInclude and MUnitType
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Countries then
|
if self.Filter.Countries and MUnitInclude then
|
||||||
local MUnitCountry = false
|
local MUnitCountry = false
|
||||||
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
||||||
self:T3( { "Country:", MUnit:GetCountry(), CountryName } )
|
self:T3( { "Country:", MUnit:GetCountry(), CountryName } )
|
||||||
@@ -3118,7 +3253,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitCountry
|
MUnitInclude = MUnitInclude and MUnitCountry
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.UnitPrefixes then
|
if self.Filter.UnitPrefixes and MUnitInclude then
|
||||||
local MUnitPrefix = false
|
local MUnitPrefix = false
|
||||||
for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do
|
for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do
|
||||||
self:T3( { "Prefix:", string.find( MUnit:GetName(), UnitPrefix, 1 ), UnitPrefix } )
|
self:T3( { "Prefix:", string.find( MUnit:GetName(), UnitPrefix, 1 ), UnitPrefix } )
|
||||||
@@ -3129,7 +3264,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitPrefix
|
MUnitInclude = MUnitInclude and MUnitPrefix
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.RadarTypes then
|
if self.Filter.RadarTypes and MUnitInclude then
|
||||||
local MUnitRadar = false
|
local MUnitRadar = false
|
||||||
for RadarTypeID, RadarType in pairs( self.Filter.RadarTypes ) do
|
for RadarTypeID, RadarType in pairs( self.Filter.RadarTypes ) do
|
||||||
self:T3( { "Radar:", RadarType } )
|
self:T3( { "Radar:", RadarType } )
|
||||||
@@ -3143,7 +3278,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitRadar
|
MUnitInclude = MUnitInclude and MUnitRadar
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.SEAD then
|
if self.Filter.SEAD and MUnitInclude then
|
||||||
local MUnitSEAD = false
|
local MUnitSEAD = false
|
||||||
if MUnit:HasSEAD() == true then
|
if MUnit:HasSEAD() == true then
|
||||||
self:T3( "SEAD Found" )
|
self:T3( "SEAD Found" )
|
||||||
@@ -3153,7 +3288,7 @@ do -- SET_UNIT
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Zones then
|
if self.Filter.Zones and MUnitInclude then
|
||||||
local MGroupZone = false
|
local MGroupZone = false
|
||||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||||
self:T3( "Zone:", ZoneName )
|
self:T3( "Zone:", ZoneName )
|
||||||
@@ -3164,6 +3299,11 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MGroupZone
|
MUnitInclude = MUnitInclude and MGroupZone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.Filter.Functions and MUnitInclude then
|
||||||
|
local MUnitFunc = self:_EvalFilterFunctions(MUnit)
|
||||||
|
MUnitInclude = MUnitInclude and MUnitFunc
|
||||||
|
end
|
||||||
|
|
||||||
self:T2( MUnitInclude )
|
self:T2( MUnitInclude )
|
||||||
return MUnitInclude
|
return MUnitInclude
|
||||||
end
|
end
|
||||||
@@ -3245,6 +3385,7 @@ do -- SET_STATIC
|
|||||||
-- * @{#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.
|
-- * @{#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)
|
-- 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}.
|
-- * @{#SET_STATIC.FilterZones}: Builds the SET_STATIC with the units within a @{Core.Zone#ZONE}.
|
||||||
|
-- * @{#SET_STATIC.FilterFunction}: Builds the SET_STATIC with a custom condition.
|
||||||
--
|
--
|
||||||
-- Once the filter criteria have been set for the SET_STATIC, you can start filtering using:
|
-- Once the filter criteria have been set for the SET_STATIC, you can start filtering using:
|
||||||
--
|
--
|
||||||
@@ -3447,7 +3588,25 @@ do -- SET_STATIC
|
|||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Add a custom condition function.
|
||||||
|
-- @function [parent=#SET_STATIC] FilterFunction
|
||||||
|
-- @param #SET_STATIC self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a STATIC object as first argument.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #SET_STATIC self
|
||||||
|
-- @usage
|
||||||
|
-- -- Image you want to exclude a specific CLIENT from a SET:
|
||||||
|
-- local groundset = SET_STATIC:New():FilterCoalitions("blue"):FilterActive(true):FilterFunction(
|
||||||
|
-- -- The function needs to take a STATIC object as first - and in this case, only - argument.
|
||||||
|
-- function(static)
|
||||||
|
-- local isinclude = true
|
||||||
|
-- if static:GetName() == "Exclude Me" then isinclude = false end
|
||||||
|
-- return isinclude
|
||||||
|
-- end
|
||||||
|
-- ):FilterOnce()
|
||||||
|
-- BASE:I(groundset:Flush())
|
||||||
|
|
||||||
--- Builds a set of units of defined countries.
|
--- Builds a set of units of defined countries.
|
||||||
-- Possible current countries are those known within DCS world.
|
-- Possible current countries are those known within DCS world.
|
||||||
-- @param #SET_STATIC self
|
-- @param #SET_STATIC self
|
||||||
@@ -4004,6 +4163,7 @@ do -- SET_CLIENT
|
|||||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
-- 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.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}.
|
-- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Core.Zone#ZONE}.
|
||||||
|
-- * @{#SET_CLIENT.FilterFunction}: Builds the SET_CLIENT with a custom condition.
|
||||||
--
|
--
|
||||||
-- Once the filter criteria have been set for the SET_CLIENT, you can start filtering using:
|
-- Once the filter criteria have been set for the SET_CLIENT, you can start filtering using:
|
||||||
--
|
--
|
||||||
@@ -4317,6 +4477,8 @@ do -- SET_CLIENT
|
|||||||
self:UnHandleEvent(EVENTS.Birth)
|
self:UnHandleEvent(EVENTS.Birth)
|
||||||
self:UnHandleEvent(EVENTS.Dead)
|
self:UnHandleEvent(EVENTS.Dead)
|
||||||
self:UnHandleEvent(EVENTS.Crash)
|
self:UnHandleEvent(EVENTS.Crash)
|
||||||
|
--self:UnHandleEvent(EVENTS.PlayerEnterUnit)
|
||||||
|
--self:UnHandleEvent(EVENTS.PlayerLeaveUnit)
|
||||||
|
|
||||||
if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then
|
if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then
|
||||||
self.ZoneTimer:Stop()
|
self.ZoneTimer:Stop()
|
||||||
@@ -4335,6 +4497,9 @@ do -- SET_CLIENT
|
|||||||
self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
|
self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
|
||||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||||
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
||||||
|
--self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventPlayerEnterUnit)
|
||||||
|
--self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventPlayerLeaveUnit)
|
||||||
|
--self:SetEventPriority(1)
|
||||||
if self.Filter.Zones then
|
if self.Filter.Zones then
|
||||||
self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self)
|
self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self)
|
||||||
local timing = self.ZoneTimerInterval or 30
|
local timing = self.ZoneTimerInterval or 30
|
||||||
@@ -4345,6 +4510,43 @@ do -- SET_CLIENT
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handle CA slots addition
|
||||||
|
-- @param #SET_CLIENT self
|
||||||
|
-- @param Core.Event#EVENTDATA Event
|
||||||
|
-- @return #SET_CLIENT self
|
||||||
|
function SET_CLIENT:_EventPlayerEnterUnit(Event)
|
||||||
|
self:I( "_EventPlayerEnterUnit" )
|
||||||
|
if Event.IniDCSUnit then
|
||||||
|
if Event.IniObjectCategory == Object.Category.UNIT and Event.IniGroup and Event.IniGroup:IsGround() then
|
||||||
|
-- CA Slot entered
|
||||||
|
local ObjectName, Object = self:AddInDatabase( Event )
|
||||||
|
self:I( ObjectName, UTILS.PrintTableToLog(Object) )
|
||||||
|
if Object and self:IsIncludeObject( Object ) then
|
||||||
|
self:Add( ObjectName, Object )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Handle CA slots removal
|
||||||
|
-- @param #SET_CLIENT self
|
||||||
|
-- @param Core.Event#EVENTDATA Event
|
||||||
|
-- @return #SET_CLIENT self
|
||||||
|
function SET_CLIENT:_EventPlayerLeaveUnit(Event)
|
||||||
|
self:I( "_EventPlayerLeaveUnit" )
|
||||||
|
if Event.IniDCSUnit then
|
||||||
|
if Event.IniObjectCategory == Object.Category.UNIT and Event.IniGroup and Event.IniGroup:IsGround() then
|
||||||
|
-- CA Slot left
|
||||||
|
local ObjectName, Object = self:FindInDatabase( Event )
|
||||||
|
if ObjectName then
|
||||||
|
self:Remove( ObjectName )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
||||||
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
||||||
@@ -4464,6 +4666,25 @@ do -- SET_CLIENT
|
|||||||
return AliveSet.Set or {}
|
return AliveSet.Set or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Add a custom condition function.
|
||||||
|
-- @function [parent=#SET_CLIENT] FilterFunction
|
||||||
|
-- @param #SET_CLIENT self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a CLIENT object as first argument.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #SET_CLIENT self
|
||||||
|
-- @usage
|
||||||
|
-- -- Image you want to exclude a specific CLIENT from a SET:
|
||||||
|
-- local groundset = SET_CLIENT:New():FilterCoalitions("blue"):FilterActive(true):FilterFunction(
|
||||||
|
-- -- The function needs to take a UNIT object as first - and in this case, only - argument.
|
||||||
|
-- function(client)
|
||||||
|
-- local isinclude = true
|
||||||
|
-- if client:GetPlayerName() == "Exclude Me" then isinclude = false end
|
||||||
|
-- return isinclude
|
||||||
|
-- end
|
||||||
|
-- ):FilterOnce()
|
||||||
|
-- BASE:I(groundset:Flush())
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @param #SET_CLIENT self
|
-- @param #SET_CLIENT self
|
||||||
-- @param Wrapper.Client#CLIENT MClient
|
-- @param Wrapper.Client#CLIENT MClient
|
||||||
@@ -4485,7 +4706,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientActive
|
MClientInclude = MClientInclude and MClientActive
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Coalitions then
|
if self.Filter.Coalitions and MClientInclude then
|
||||||
local MClientCoalition = false
|
local MClientCoalition = false
|
||||||
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
||||||
local ClientCoalitionID = _DATABASE:GetCoalitionFromClientTemplate( MClientName )
|
local ClientCoalitionID = _DATABASE:GetCoalitionFromClientTemplate( MClientName )
|
||||||
@@ -4498,7 +4719,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientCoalition
|
MClientInclude = MClientInclude and MClientCoalition
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MClientInclude then
|
||||||
local MClientCategory = false
|
local MClientCategory = false
|
||||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||||
local ClientCategoryID = _DATABASE:GetCategoryFromClientTemplate( MClientName )
|
local ClientCategoryID = _DATABASE:GetCategoryFromClientTemplate( MClientName )
|
||||||
@@ -4511,7 +4732,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientCategory
|
MClientInclude = MClientInclude and MClientCategory
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Types then
|
if self.Filter.Types and MClientInclude then
|
||||||
local MClientType = false
|
local MClientType = false
|
||||||
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
||||||
self:T3( { "Type:", MClient:GetTypeName(), TypeName } )
|
self:T3( { "Type:", MClient:GetTypeName(), TypeName } )
|
||||||
@@ -4523,7 +4744,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientType
|
MClientInclude = MClientInclude and MClientType
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Countries then
|
if self.Filter.Countries and MClientInclude then
|
||||||
local MClientCountry = false
|
local MClientCountry = false
|
||||||
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
||||||
local ClientCountryID = _DATABASE:GetCountryFromClientTemplate( MClientName )
|
local ClientCountryID = _DATABASE:GetCountryFromClientTemplate( MClientName )
|
||||||
@@ -4536,7 +4757,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientCountry
|
MClientInclude = MClientInclude and MClientCountry
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.ClientPrefixes then
|
if self.Filter.ClientPrefixes and MClientInclude then
|
||||||
local MClientPrefix = false
|
local MClientPrefix = false
|
||||||
for ClientPrefixId, ClientPrefix in pairs( self.Filter.ClientPrefixes ) do
|
for ClientPrefixId, ClientPrefix in pairs( self.Filter.ClientPrefixes ) do
|
||||||
self:T3( { "Prefix:", string.find( MClient.UnitName, ClientPrefix, 1 ), ClientPrefix } )
|
self:T3( { "Prefix:", string.find( MClient.UnitName, ClientPrefix, 1 ), ClientPrefix } )
|
||||||
@@ -4548,7 +4769,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientPrefix
|
MClientInclude = MClientInclude and MClientPrefix
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Zones then
|
if self.Filter.Zones and MClientInclude then
|
||||||
local MClientZone = false
|
local MClientZone = false
|
||||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||||
self:T3( "Zone:", ZoneName )
|
self:T3( "Zone:", ZoneName )
|
||||||
@@ -4560,7 +4781,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientZone
|
MClientInclude = MClientInclude and MClientZone
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Playernames then
|
if self.Filter.Playernames and MClientInclude then
|
||||||
local MClientPlayername = false
|
local MClientPlayername = false
|
||||||
local playername = MClient:GetPlayerName() or "Unknown"
|
local playername = MClient:GetPlayerName() or "Unknown"
|
||||||
--self:T(playername)
|
--self:T(playername)
|
||||||
@@ -4573,7 +4794,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientPlayername
|
MClientInclude = MClientInclude and MClientPlayername
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Callsigns then
|
if self.Filter.Callsigns and MClientInclude then
|
||||||
local MClientCallsigns = false
|
local MClientCallsigns = false
|
||||||
local callsign = MClient:GetCallsign()
|
local callsign = MClient:GetCallsign()
|
||||||
--self:I(callsign)
|
--self:I(callsign)
|
||||||
@@ -4586,6 +4807,11 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientCallsigns
|
MClientInclude = MClientInclude and MClientCallsigns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.Filter.Functions and MClientInclude then
|
||||||
|
local MClientFunc = self:_EvalFilterFunctions(MClient)
|
||||||
|
MClientInclude = MClientInclude and MClientFunc
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
self:T2( MClientInclude )
|
self:T2( MClientInclude )
|
||||||
return MClientInclude
|
return MClientInclude
|
||||||
@@ -5179,7 +5405,7 @@ do -- SET_AIRBASE
|
|||||||
function SET_AIRBASE:GetRandomAirbase()
|
function SET_AIRBASE:GetRandomAirbase()
|
||||||
|
|
||||||
local RandomAirbase = self:GetRandom()
|
local RandomAirbase = self:GetRandom()
|
||||||
self:F( { RandomAirbase = RandomAirbase:GetName() } )
|
--self:F( { RandomAirbase = RandomAirbase:GetName() } )
|
||||||
|
|
||||||
return RandomAirbase
|
return RandomAirbase
|
||||||
end
|
end
|
||||||
@@ -5345,7 +5571,7 @@ do -- SET_AIRBASE
|
|||||||
MAirbaseInclude = MAirbaseInclude and MAirbaseCoalition
|
MAirbaseInclude = MAirbaseInclude and MAirbaseCoalition
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MAirbaseInclude then
|
||||||
local MAirbaseCategory = false
|
local MAirbaseCategory = false
|
||||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||||
local AirbaseCategoryID = _DATABASE:GetCategoryFromAirbase( MAirbaseName )
|
local AirbaseCategoryID = _DATABASE:GetCategoryFromAirbase( MAirbaseName )
|
||||||
@@ -7611,6 +7837,28 @@ do -- SET_OPSGROUP
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles the OnBirth event for the Set.
|
||||||
|
-- @param #SET_OPSGROUP self
|
||||||
|
-- @param Core.Event#EVENTDATA Event Event data.
|
||||||
|
function SET_OPSGROUP:_EventOnBirth( Event )
|
||||||
|
self:F3( { Event } )
|
||||||
|
|
||||||
|
if Event.IniDCSUnit and Event.IniDCSGroup then
|
||||||
|
local DCSgroup=Event.IniDCSGroup --DCS#Group
|
||||||
|
|
||||||
|
if DCSgroup:getInitialSize() == DCSgroup:getSize() then -- This seems to be not a good check as even for the first birth event, getSize returns the total number of units in the group.
|
||||||
|
|
||||||
|
local groupname, group = self:AddInDatabase( Event )
|
||||||
|
|
||||||
|
if group and group:CountAliveUnits()==DCSgroup:getInitialSize() then
|
||||||
|
if group and self:IsIncludeObject( group ) then
|
||||||
|
self:Add( groupname, group )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Handles the OnDead or OnCrash event for alive groups set.
|
--- Handles the OnDead or OnCrash event for alive groups set.
|
||||||
-- Note: The GROUP object in the SET_OPSGROUP collection will only be removed if the last unit is destroyed of the GROUP.
|
-- Note: The GROUP object in the SET_OPSGROUP collection will only be removed if the last unit is destroyed of the GROUP.
|
||||||
-- @param #SET_OPSGROUP self
|
-- @param #SET_OPSGROUP self
|
||||||
@@ -7631,12 +7879,12 @@ do -- SET_OPSGROUP
|
|||||||
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
||||||
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
||||||
-- @param #SET_OPSGROUP self
|
-- @param #SET_OPSGROUP self
|
||||||
-- @param Core.Event#EVENTDATA Event
|
-- @param Core.Event#EVENTDATA Event Event data.
|
||||||
-- @return #string The name of the GROUP
|
-- @return #string The name of the GROUP.
|
||||||
-- @return #table The GROUP
|
-- @return Wrapper.Group#GROUP The GROUP object.
|
||||||
function SET_OPSGROUP:AddInDatabase( Event )
|
function SET_OPSGROUP:AddInDatabase( Event )
|
||||||
|
|
||||||
if Event.IniObjectCategory==1 then
|
if Event.IniObjectCategory==Object.Category.UNIT then
|
||||||
|
|
||||||
if not self.Database[Event.IniDCSGroupName] then
|
if not self.Database[Event.IniDCSGroupName] then
|
||||||
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
||||||
@@ -7651,8 +7899,8 @@ do -- SET_OPSGROUP
|
|||||||
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
||||||
-- @param #SET_OPSGROUP self
|
-- @param #SET_OPSGROUP self
|
||||||
-- @param Core.Event#EVENTDATA Event Event data table.
|
-- @param Core.Event#EVENTDATA Event Event data table.
|
||||||
-- @return #string The name of the GROUP
|
-- @return #string The name of the GROUP.
|
||||||
-- @return #table The GROUP
|
-- @return Wrapper.Group#GROUP The GROUP object.
|
||||||
function SET_OPSGROUP:FindInDatabase(Event)
|
function SET_OPSGROUP:FindInDatabase(Event)
|
||||||
return Event.IniDCSGroupName, self.Database[Event.IniDCSGroupName]
|
return Event.IniDCSGroupName, self.Database[Event.IniDCSGroupName]
|
||||||
end
|
end
|
||||||
@@ -7691,7 +7939,7 @@ do -- SET_OPSGROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Filter coalitions.
|
-- Filter coalitions.
|
||||||
if self.Filter.Coalitions then
|
if self.Filter.Coalitions and MGroupInclude then
|
||||||
|
|
||||||
local MGroupCoalition = false
|
local MGroupCoalition = false
|
||||||
|
|
||||||
@@ -7705,7 +7953,7 @@ do -- SET_OPSGROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Filter categories.
|
-- Filter categories.
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MGroupInclude then
|
||||||
|
|
||||||
local MGroupCategory = false
|
local MGroupCategory = false
|
||||||
|
|
||||||
@@ -7719,7 +7967,7 @@ do -- SET_OPSGROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Filter countries.
|
-- Filter countries.
|
||||||
if self.Filter.Countries then
|
if self.Filter.Countries and MGroupInclude then
|
||||||
local MGroupCountry = false
|
local MGroupCountry = false
|
||||||
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
||||||
if country.id[CountryName] == MGroup:GetCountry() then
|
if country.id[CountryName] == MGroup:GetCountry() then
|
||||||
@@ -7730,12 +7978,12 @@ do -- SET_OPSGROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Filter "prefixes".
|
-- Filter "prefixes".
|
||||||
if self.Filter.GroupPrefixes then
|
if self.Filter.GroupPrefixes and MGroupInclude then
|
||||||
|
|
||||||
local MGroupPrefix = false
|
local MGroupPrefix = false
|
||||||
|
|
||||||
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
||||||
if string.find( MGroup:GetName(), GroupPrefix:gsub ("-", "%%-"), 1 ) then --Not sure why "-" is replaced by "%-" ?!
|
if string.find( MGroup:GetName(), GroupPrefix:gsub ("-", "%%-"), 1 ) then --Not sure why "-" is replaced by "%-" ?! - So we can still match group names with a dash in them
|
||||||
MGroupPrefix = true
|
MGroupPrefix = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -7971,7 +8219,7 @@ do -- SET_SCENERY
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Get a table of alive objects.
|
--- Get a table of alive objects.
|
||||||
-- @param #SET_GROUP self
|
-- @param #SET_SCENERY self
|
||||||
-- @return #table Table of alive objects
|
-- @return #table Table of alive objects
|
||||||
-- @return Core.Set#SET_SCENERY SET of alive objects
|
-- @return Core.Set#SET_SCENERY SET of alive objects
|
||||||
function SET_SCENERY:GetAliveSet()
|
function SET_SCENERY:GetAliveSet()
|
||||||
@@ -8006,9 +8254,15 @@ do -- SET_SCENERY
|
|||||||
-- @param #SET_SCENERY self
|
-- @param #SET_SCENERY self
|
||||||
-- @return Core.Point#COORDINATE The center coordinate of all the objects in the set.
|
-- @return Core.Point#COORDINATE The center coordinate of all the objects in the set.
|
||||||
function SET_SCENERY:GetCoordinate()
|
function SET_SCENERY:GetCoordinate()
|
||||||
|
|
||||||
local Coordinate = self:GetRandom():GetCoordinate()
|
local Coordinate = COORDINATE:New({0,0,0})
|
||||||
|
|
||||||
|
local Item = self:GetRandomSurely()
|
||||||
|
|
||||||
|
if Item then
|
||||||
|
Coordinate:GetCoordinate()
|
||||||
|
end
|
||||||
|
|
||||||
local x1 = Coordinate.x
|
local x1 = Coordinate.x
|
||||||
local x2 = Coordinate.x
|
local x2 = Coordinate.x
|
||||||
local y1 = Coordinate.y
|
local y1 = Coordinate.y
|
||||||
@@ -8145,7 +8399,7 @@ do -- SET_SCENERY
|
|||||||
--- Calculate current relative lifepoints of the SET objects, i.e. Life divided by Life0 as percentage value, eg 75 meaning 75% alive.
|
--- Calculate current relative lifepoints of the SET objects, i.e. Life divided by Life0 as percentage value, eg 75 meaning 75% alive.
|
||||||
-- **CAVEAT**: Some objects change their life value or "hitpoints" **after** the first hit. Hence we will adjust the Life0 value to 120%
|
-- **CAVEAT**: Some objects change their life value or "hitpoints" **after** the first hit. Hence we will adjust the Life0 value to 120%
|
||||||
-- of the last life value if life exceeds life0 ata any point.
|
-- of the last life value if life exceeds life0 ata any point.
|
||||||
-- Thus will will get a smooth percentage decrease, if you use this e.g. as success criteria for a bombing task.
|
-- Thus we will get a smooth percentage decrease, if you use this e.g. as success criteria for a bombing task.
|
||||||
-- @param #SET_SCENERY self
|
-- @param #SET_SCENERY self
|
||||||
-- @return #number LifePoints
|
-- @return #number LifePoints
|
||||||
function SET_SCENERY:GetRelativeLife()
|
function SET_SCENERY:GetRelativeLife()
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPA%20-%20Spawning)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Core/Spawn)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -320,7 +320,7 @@ function SPAWN:New( SpawnTemplatePrefix )
|
|||||||
self.AIOnOff = true -- The AI is on by default when spawning a group.
|
self.AIOnOff = true -- The AI is on by default when spawning a group.
|
||||||
self.SpawnUnControlled = false
|
self.SpawnUnControlled = false
|
||||||
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
|
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
|
||||||
self.DelayOnOff = false -- No intial delay when spawning the first group.
|
self.DelayOnOff = false -- No initial delay when spawning the first group.
|
||||||
self.SpawnGrouping = nil -- No grouping.
|
self.SpawnGrouping = nil -- No grouping.
|
||||||
self.SpawnInitLivery = nil -- No special livery.
|
self.SpawnInitLivery = nil -- No special livery.
|
||||||
self.SpawnInitSkill = nil -- No special skill.
|
self.SpawnInitSkill = nil -- No special skill.
|
||||||
@@ -332,6 +332,7 @@ function SPAWN:New( SpawnTemplatePrefix )
|
|||||||
self.SpawnInitModexPostfix = nil
|
self.SpawnInitModexPostfix = nil
|
||||||
self.SpawnInitAirbase = nil
|
self.SpawnInitAirbase = nil
|
||||||
self.TweakedTemplate = false -- Check if the user is using self made template.
|
self.TweakedTemplate = false -- Check if the user is using self made template.
|
||||||
|
self.SpawnRandomCallsign = false
|
||||||
|
|
||||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||||
else
|
else
|
||||||
@@ -1099,6 +1100,30 @@ function SPAWN:InitRandomizeZones( SpawnZoneTable )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [AIR/Fighter only!] This method randomizes the callsign for a new group.
|
||||||
|
-- @param #SPAWN self
|
||||||
|
-- @return #SPAWN self
|
||||||
|
function SPAWN:InitRandomizeCallsign()
|
||||||
|
self.SpawnRandomCallsign = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [BLUE AIR only!] This method sets a specific callsign for a spawned group. Use for a group with one unit only!
|
||||||
|
-- @param #SPAWN self
|
||||||
|
-- @param #number ID ID of the callsign enumerator, e.g. CALLSIGN.Tanker.Texaco - - resulting in e.g. Texaco-2-1
|
||||||
|
-- @param #string Name Name of this callsign as it cannot be determined from the ID because of the dependency on the task type of the plane, and the plane type. E.g. "Texaco"
|
||||||
|
-- @param #number Minor Minor number, i.e. the unit number within the group, e.g 2 - resulting in e.g. Texaco-2-1
|
||||||
|
-- @param #number Major Major number, i.e. the group number of this name, e.g. 1 - resulting in e.g. Texaco-2-1
|
||||||
|
-- @return #SPAWN self
|
||||||
|
function SPAWN:InitCallSign(ID,Name,Minor,Major)
|
||||||
|
self.SpawnInitCallSign = true
|
||||||
|
self.SpawnInitCallSignID = ID or 1
|
||||||
|
self.SpawnInitCallSignMinor = Minor or 1
|
||||||
|
self.SpawnInitCallSignMajor = Major or 1
|
||||||
|
self.SpawnInitCallSignName = string.lower(Name) or "enfield"
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- This method sets a spawn position for the group that is different from the location of the template.
|
--- This method sets a spawn position for the group that is different from the location of the template.
|
||||||
-- @param #SPAWN self
|
-- @param #SPAWN self
|
||||||
-- @param Core.Point#COORDINATE Coordinate The position to spawn from
|
-- @param Core.Point#COORDINATE Coordinate The position to spawn from
|
||||||
@@ -1433,6 +1458,7 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
else
|
else
|
||||||
|
|
||||||
local SpawnTemplate = self.SpawnGroups[self.SpawnIndex].SpawnTemplate
|
local SpawnTemplate = self.SpawnGroups[self.SpawnIndex].SpawnTemplate
|
||||||
|
local SpawnZone = self.SpawnGroups[self.SpawnIndex].SpawnZone
|
||||||
self:T( SpawnTemplate.name )
|
self:T( SpawnTemplate.name )
|
||||||
|
|
||||||
if SpawnTemplate then
|
if SpawnTemplate then
|
||||||
@@ -1458,6 +1484,23 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
if self.SpawnRandomizeUnits then
|
if self.SpawnRandomizeUnits then
|
||||||
for UnitID = 1, #SpawnTemplate.units do
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
local RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnOuterRadius, self.SpawnInnerRadius )
|
local RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnOuterRadius, self.SpawnInnerRadius )
|
||||||
|
if (SpawnZone) then
|
||||||
|
local inZone = SpawnZone:IsVec2InZone(RandomVec2)
|
||||||
|
local numTries = 1
|
||||||
|
while (not inZone) and (numTries < 20) do
|
||||||
|
if not inZone then
|
||||||
|
RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnOuterRadius, self.SpawnInnerRadius )
|
||||||
|
numTries = numTries + 1
|
||||||
|
inZone = SpawnZone:IsVec2InZone(RandomVec2)
|
||||||
|
self:I("Retrying " .. numTries .. "spawn " .. SpawnTemplate.name .. " in Zone " .. SpawnZone:GetName() .. "!")
|
||||||
|
self:I(SpawnZone)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (not inZone) then
|
||||||
|
self:I("Could not place unit within zone and within radius!")
|
||||||
|
RandomVec2 = SpawnZone:GetRandomVec2()
|
||||||
|
end
|
||||||
|
end
|
||||||
SpawnTemplate.units[UnitID].x = RandomVec2.x
|
SpawnTemplate.units[UnitID].x = RandomVec2.x
|
||||||
SpawnTemplate.units[UnitID].y = RandomVec2.y
|
SpawnTemplate.units[UnitID].y = RandomVec2.y
|
||||||
self:T( 'SpawnTemplate.units[' .. UnitID .. '].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units[' .. UnitID .. '].y = ' .. SpawnTemplate.units[UnitID].y )
|
self:T( 'SpawnTemplate.units[' .. UnitID .. '].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units[' .. UnitID .. '].y = ' .. SpawnTemplate.units[UnitID].y )
|
||||||
@@ -1509,12 +1552,14 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
|
|
||||||
for UnitID = 1, #SpawnTemplate.units do
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
|
|
||||||
if UnitID > 1 then -- don't rotate position of unit #1
|
if not self.SpawnRandomizeUnits then
|
||||||
local unitXOff = SpawnTemplate.units[UnitID].x - pivotX -- rotate position offset around unit #1
|
if UnitID > 1 then -- don't rotate position of unit #1
|
||||||
local unitYOff = SpawnTemplate.units[UnitID].y - pivotY
|
local unitXOff = SpawnTemplate.units[UnitID].x - pivotX -- rotate position offset around unit #1
|
||||||
|
local unitYOff = SpawnTemplate.units[UnitID].y - pivotY
|
||||||
|
|
||||||
SpawnTemplate.units[UnitID].x = pivotX + (unitXOff * cosHeading) - (unitYOff * sinHeading)
|
SpawnTemplate.units[UnitID].x = pivotX + (unitXOff * cosHeading) - (unitYOff * sinHeading)
|
||||||
SpawnTemplate.units[UnitID].y = pivotY + (unitYOff * cosHeading) + (unitXOff * sinHeading)
|
SpawnTemplate.units[UnitID].y = pivotY + (unitYOff * cosHeading) + (unitXOff * sinHeading)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- adjust heading of all units, including unit #1
|
-- adjust heading of all units, including unit #1
|
||||||
@@ -1644,8 +1689,8 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
|
|
||||||
-- If there is a SpawnFunction hook defined, call it.
|
-- If there is a SpawnFunction hook defined, call it.
|
||||||
if self.SpawnFunctionHook then
|
if self.SpawnFunctionHook then
|
||||||
-- delay calling this for .1 seconds so that it hopefully comes after the BIRTH event of the group.
|
-- delay calling this for .3 seconds so that it hopefully comes after the BIRTH event of the group.
|
||||||
self.SpawnHookScheduler:Schedule( nil, self.SpawnFunctionHook, { self.SpawnGroups[self.SpawnIndex].Group, unpack( self.SpawnFunctionArguments ) }, 0.1 )
|
self.SpawnHookScheduler:Schedule( nil, self.SpawnFunctionHook, { self.SpawnGroups[self.SpawnIndex].Group, unpack( self.SpawnFunctionArguments ) }, 0.3 )
|
||||||
end
|
end
|
||||||
-- TODO: Need to fix this by putting an "R" in the name of the group when the group repeats.
|
-- TODO: Need to fix this by putting an "R" in the name of the group when the group repeats.
|
||||||
-- if self.Repeat then
|
-- if self.Repeat then
|
||||||
@@ -2783,7 +2828,7 @@ end
|
|||||||
-- @return Wrapper.Group#GROUP that was spawned or #nil if nothing was spawned.
|
-- @return Wrapper.Group#GROUP that was spawned or #nil if nothing was spawned.
|
||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- local SpawnPointVec2 = ZONE:New( ZoneName ):GetPointVec2()
|
-- local SpawnPointVec2 = ZONE:New( ZoneName ):GetPointVec2()
|
||||||
--
|
--
|
||||||
-- -- Spawn at the zone center position at the height specified in the ME of the group template!
|
-- -- Spawn at the zone center position at the height specified in the ME of the group template!
|
||||||
-- SpawnAirplanes:SpawnFromPointVec2( SpawnPointVec2 )
|
-- SpawnAirplanes:SpawnFromPointVec2( SpawnPointVec2 )
|
||||||
@@ -3275,22 +3320,156 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Callsign
|
-- Callsign
|
||||||
|
|
||||||
|
if self.SpawnRandomCallsign and SpawnTemplate.units[1].callsign then
|
||||||
|
if type( SpawnTemplate.units[1].callsign ) ~= "number" then
|
||||||
|
-- change callsign
|
||||||
|
local min = 1
|
||||||
|
local max = 8
|
||||||
|
local ctable = CALLSIGN.Aircraft
|
||||||
|
if string.find(SpawnTemplate.units[1].type, "A-10",1,true) then
|
||||||
|
max = 12
|
||||||
|
end
|
||||||
|
if string.find(SpawnTemplate.units[1].type, "18",1,true) then
|
||||||
|
min = 9
|
||||||
|
max = 20
|
||||||
|
ctable = CALLSIGN.F18
|
||||||
|
end
|
||||||
|
if string.find(SpawnTemplate.units[1].type, "16",1,true) then
|
||||||
|
min = 9
|
||||||
|
max = 20
|
||||||
|
ctable = CALLSIGN.F16
|
||||||
|
end
|
||||||
|
if SpawnTemplate.units[1].type == "F-15E" then
|
||||||
|
min = 9
|
||||||
|
max = 18
|
||||||
|
ctable = CALLSIGN.F15E
|
||||||
|
end
|
||||||
|
local callsignnr = math.random(min,max)
|
||||||
|
local callsignname = "Enfield"
|
||||||
|
for name, value in pairs(ctable) do
|
||||||
|
if value==callsignnr then
|
||||||
|
callsignname = name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
|
SpawnTemplate.units[UnitID].callsign[1] = callsignnr
|
||||||
|
SpawnTemplate.units[UnitID].callsign[2] = UnitID
|
||||||
|
SpawnTemplate.units[UnitID].callsign[3] = "1"
|
||||||
|
SpawnTemplate.units[UnitID].callsign["name"] = tostring(callsignname)..tostring(UnitID).."1"
|
||||||
|
-- UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].callsign,1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Russkis
|
||||||
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
|
SpawnTemplate.units[UnitID].callsign = math.random(1,999)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.SpawnInitCallSign then
|
||||||
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
|
local Callsign = SpawnTemplate.units[UnitID].callsign
|
||||||
|
if Callsign and type( Callsign ) ~= "number" then
|
||||||
|
SpawnTemplate.units[UnitID].callsign[1] = self.SpawnInitCallSignID
|
||||||
|
SpawnTemplate.units[UnitID].callsign[2] = self.SpawnInitCallSignMinor
|
||||||
|
SpawnTemplate.units[UnitID].callsign[3] = self.SpawnInitCallSignMajor
|
||||||
|
SpawnTemplate.units[UnitID].callsign["name"] = string.format("%s%d%d",self.SpawnInitCallSignName,self.SpawnInitCallSignMinor,self.SpawnInitCallSignMajor)
|
||||||
|
--UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].callsign,1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for UnitID = 1, #SpawnTemplate.units do
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
local Callsign = SpawnTemplate.units[UnitID].callsign
|
local Callsign = SpawnTemplate.units[UnitID].callsign
|
||||||
if Callsign then
|
if Callsign then
|
||||||
if type( Callsign ) ~= "number" then -- blue callsign
|
if type( Callsign ) ~= "number" and not self.SpawnInitCallSign then -- blue callsign
|
||||||
|
-- UTILS.PrintTableToLog(Callsign,1)
|
||||||
Callsign[2] = ((SpawnIndex - 1) % 10) + 1
|
Callsign[2] = ((SpawnIndex - 1) % 10) + 1
|
||||||
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
|
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
|
||||||
CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers
|
CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers
|
||||||
local CallsignLen = CallsignName:len()
|
local CallsignLen = CallsignName:len()
|
||||||
|
SpawnTemplate.units[UnitID].callsign[2] = UnitID
|
||||||
SpawnTemplate.units[UnitID].callsign["name"] = CallsignName:sub( 1, CallsignLen ) .. SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
|
SpawnTemplate.units[UnitID].callsign["name"] = CallsignName:sub( 1, CallsignLen ) .. SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
|
||||||
else
|
elseif type( Callsign ) == "number" then
|
||||||
SpawnTemplate.units[UnitID].callsign = Callsign + SpawnIndex
|
SpawnTemplate.units[UnitID].callsign = Callsign + SpawnIndex
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- Link16
|
||||||
|
local AddProps = SpawnTemplate.units[UnitID].AddPropAircraft
|
||||||
|
if AddProps then
|
||||||
|
if SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 then
|
||||||
|
-- 4 digit octal with leading 0
|
||||||
|
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16) ~= nil then
|
||||||
|
local octal = SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16
|
||||||
|
local decimal = UTILS.OctalToDecimal(octal)+UnitID-1
|
||||||
|
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",UTILS.DecimalToOctal(decimal))
|
||||||
|
else -- ED bug - chars in here
|
||||||
|
local STN = math.floor(UTILS.RandomGaussian(4088/2,nil,1000,4088))
|
||||||
|
STN = STN+UnitID-1
|
||||||
|
local OSTN = UTILS.DecimalToOctal(STN)
|
||||||
|
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",OSTN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- A10CII
|
||||||
|
if SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN then
|
||||||
|
-- 3 digit octal with leading 0
|
||||||
|
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN) ~= nil then
|
||||||
|
local octal = SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN
|
||||||
|
local decimal = UTILS.OctalToDecimal(octal)+UnitID-1
|
||||||
|
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",UTILS.DecimalToOctal(decimal))
|
||||||
|
else -- ED bug - chars in here
|
||||||
|
local STN = math.floor(UTILS.RandomGaussian(504/2,nil,100,504))
|
||||||
|
STN = STN+UnitID-1
|
||||||
|
local OSTN = UTILS.DecimalToOctal(STN)
|
||||||
|
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",OSTN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- VoiceCallsignNumber
|
||||||
|
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber and type( Callsign ) ~= "number" then
|
||||||
|
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber = SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
|
||||||
|
end
|
||||||
|
-- VoiceCallsignLabel
|
||||||
|
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel and type( Callsign ) ~= "number" then
|
||||||
|
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
|
||||||
|
CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers
|
||||||
|
local label = "NY" -- Navy One exception
|
||||||
|
if not string.find(CallsignName," ") then
|
||||||
|
label = string.upper(string.match(CallsignName,"^%a")..string.match(CallsignName,"%a$"))
|
||||||
|
end
|
||||||
|
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel = label
|
||||||
|
end
|
||||||
|
-- UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].AddPropAircraft,1)
|
||||||
|
-- FlightLead
|
||||||
|
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.Link16 and SpawnTemplate.units[UnitID].datalinks.Link16.settings then
|
||||||
|
SpawnTemplate.units[UnitID].datalinks.Link16.settings.flightLead = UnitID == 1 and true or false
|
||||||
|
end
|
||||||
|
-- A10CII
|
||||||
|
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.SADL and SpawnTemplate.units[UnitID].datalinks.SADL.settings then
|
||||||
|
SpawnTemplate.units[UnitID].datalinks.SADL.settings.flightLead = UnitID == 1 and true or false
|
||||||
|
end
|
||||||
|
-- UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].datalinks,1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Link16 team members
|
||||||
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
|
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.Link16 and SpawnTemplate.units[UnitID].datalinks.Link16.network then
|
||||||
|
local team = {}
|
||||||
|
local isF16 = string.find(SpawnTemplate.units[UnitID].type,"F-16",1,true) and true or false
|
||||||
|
for ID = 1, #SpawnTemplate.units do
|
||||||
|
local member = {}
|
||||||
|
member.missionUnitId = ID
|
||||||
|
if isF16 then
|
||||||
|
member.TDOA = true
|
||||||
|
end
|
||||||
|
table.insert(team,member)
|
||||||
|
end
|
||||||
|
SpawnTemplate.units[UnitID].datalinks.Link16.network.teamMembers = team
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T3( { "Template:", SpawnTemplate } )
|
self:T3( { "Template:", SpawnTemplate } )
|
||||||
|
--UTILS.PrintTableToLog(SpawnTemplate,1)
|
||||||
return SpawnTemplate
|
return SpawnTemplate
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -3432,6 +3611,7 @@ function SPAWN:_RandomizeZones( SpawnIndex )
|
|||||||
self:T( { SpawnVec2 = SpawnVec2 } )
|
self:T( { SpawnVec2 = SpawnVec2 } )
|
||||||
|
|
||||||
local SpawnTemplate = self.SpawnGroups[SpawnIndex].SpawnTemplate
|
local SpawnTemplate = self.SpawnGroups[SpawnIndex].SpawnTemplate
|
||||||
|
self.SpawnGroups[SpawnIndex].SpawnZone = SpawnZone
|
||||||
|
|
||||||
self:T( { Route = SpawnTemplate.route } )
|
self:T( { Route = SpawnTemplate.route } )
|
||||||
|
|
||||||
|
|||||||
@@ -15,14 +15,14 @@
|
|||||||
--
|
--
|
||||||
-- # Demo Missions
|
-- # Demo Missions
|
||||||
--
|
--
|
||||||
-- ## [SPAWNSTATIC Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPS%20-%20Spawning%20Statics)
|
-- ## [SPAWNSTATIC Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Core/SpawnStatic)
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- # YouTube Channel
|
-- # YouTube Channel
|
||||||
--
|
--
|
||||||
-- ## [SPAWNSTATIC YouTube Channel]() [No videos yet!]
|
-- ## No videos yet!
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -329,14 +329,14 @@ do
|
|||||||
if self.Lasing then
|
if self.Lasing then
|
||||||
if self.Target and self.Target:IsAlive() then
|
if self.Target and self.Target:IsAlive() then
|
||||||
|
|
||||||
self.SpotIR:setPoint( self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/100):AddX(math.random(-100,100)/100):GetVec3() )
|
self.SpotIR:setPoint( self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/200):AddX(math.random(-100,100)/200):GetVec3() )
|
||||||
self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() )
|
self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() )
|
||||||
|
|
||||||
self:__Lasing(0.2)
|
self:__Lasing(0.2)
|
||||||
elseif self.TargetCoord then
|
elseif self.TargetCoord then
|
||||||
|
|
||||||
-- Wiggle the IR spot a bit.
|
-- Wiggle the IR spot a bit.
|
||||||
local irvec3={x=self.TargetCoord.x+math.random(-100,100)/100, y=self.TargetCoord.y+math.random(-100,100)/100, z=self.TargetCoord.z} --#DCS.Vec3
|
local irvec3={x=self.TargetCoord.x+math.random(-100,100)/200, y=self.TargetCoord.y+math.random(-100,100)/200, z=self.TargetCoord.z} --#DCS.Vec3
|
||||||
local lsvec3={x=self.TargetCoord.x, y=self.TargetCoord.y, z=self.TargetCoord.z} --#DCS.Vec3
|
local lsvec3={x=self.TargetCoord.x, y=self.TargetCoord.y, z=self.TargetCoord.z} --#DCS.Vec3
|
||||||
|
|
||||||
self.SpotIR:setPoint(irvec3)
|
self.SpotIR:setPoint(irvec3)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -16,9 +16,9 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/CSR-001%20-%20Basics).
|
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Functional/AICSAR).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **Applevangelist**
|
-- ### Author: **Applevangelist**
|
||||||
@@ -527,7 +527,7 @@ end
|
|||||||
--- [User] Switch sound output on and use SRS output for sound files.
|
--- [User] Switch sound output on and use SRS output for sound files.
|
||||||
-- @param #AICSAR self
|
-- @param #AICSAR self
|
||||||
-- @param #boolean OnOff Switch on (true) or off (false).
|
-- @param #boolean OnOff Switch on (true) or off (false).
|
||||||
-- @param #string Path Path to your SRS Server Component, e.g. "E:\\\\Program Files\\\\DCS-SimpleRadio-Standalone"
|
-- @param #string Path Path to your SRS Server Component, e.g. "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone"
|
||||||
-- @param #number Frequency Defaults to 243 (guard)
|
-- @param #number Frequency Defaults to 243 (guard)
|
||||||
-- @param #number Modulation Radio modulation. Defaults to radio.modulation.AM
|
-- @param #number Modulation Radio modulation. Defaults to radio.modulation.AM
|
||||||
-- @param #string SoundPath Where to find the audio files. Defaults to nil, i.e. add messages via "Sound to..." in the Mission Editor.
|
-- @param #string SoundPath Where to find the audio files. Defaults to nil, i.e. add messages via "Sound to..." in the Mission Editor.
|
||||||
@@ -538,13 +538,13 @@ function AICSAR:SetSRSRadio(OnOff,Path,Frequency,Modulation,SoundPath,Port)
|
|||||||
self.SRSRadio = OnOff and true
|
self.SRSRadio = OnOff and true
|
||||||
self.SRSTTSRadio = false
|
self.SRSTTSRadio = false
|
||||||
self.SRSFrequency = Frequency or 243
|
self.SRSFrequency = Frequency or 243
|
||||||
self.SRSPath = Path or "c:\\"
|
self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
self.SRS:SetLabel("ACSR")
|
self.SRS:SetLabel("ACSR")
|
||||||
self.SRS:SetCoalition(self.coalition)
|
self.SRS:SetCoalition(self.coalition)
|
||||||
self.SRSModulation = Modulation or radio.modulation.AM
|
self.SRSModulation = Modulation or radio.modulation.AM
|
||||||
local soundpath = os.getenv('TMP') .. "\\DCS\\Mission\\l10n\\DEFAULT" -- defaults to "l10n/DEFAULT/", i.e. add messages by "Sound to..." in the ME
|
local soundpath = os.getenv('TMP') .. "\\DCS\\Mission\\l10n\\DEFAULT" -- defaults to "l10n/DEFAULT/", i.e. add messages by "Sound to..." in the ME
|
||||||
self.SRSSoundPath = SoundPath or soundpath
|
self.SRSSoundPath = SoundPath or soundpath
|
||||||
self.SRSPort = Port or 5002
|
self.SRSPort = Port or MSRS.port or 5002
|
||||||
if OnOff then
|
if OnOff then
|
||||||
self.SRS = MSRS:New(Path,Frequency,Modulation)
|
self.SRS = MSRS:New(Path,Frequency,Modulation)
|
||||||
self.SRS:SetPort(self.SRSPort)
|
self.SRS:SetPort(self.SRSPort)
|
||||||
@@ -570,11 +570,11 @@ function AICSAR:SetSRSTTSRadio(OnOff,Path,Frequency,Modulation,Port,Voice,Cultur
|
|||||||
self.SRSTTSRadio = OnOff and true
|
self.SRSTTSRadio = OnOff and true
|
||||||
self.SRSRadio = false
|
self.SRSRadio = false
|
||||||
self.SRSFrequency = Frequency or 243
|
self.SRSFrequency = Frequency or 243
|
||||||
self.SRSPath = Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
self.SRSModulation = Modulation or radio.modulation.AM
|
self.SRSModulation = Modulation or radio.modulation.AM
|
||||||
self.SRSPort = Port or 5002
|
self.SRSPort = Port or MSRS.port or 5002
|
||||||
if OnOff then
|
if OnOff then
|
||||||
self.SRS = MSRS:New(Path,Frequency,Modulation,1)
|
self.SRS = MSRS:New(self.SRSPath,Frequency,Modulation)
|
||||||
self.SRS:SetPort(self.SRSPort)
|
self.SRS:SetPort(self.SRSPort)
|
||||||
self.SRS:SetCoalition(self.coalition)
|
self.SRS:SetCoalition(self.coalition)
|
||||||
self.SRS:SetLabel("ACSR")
|
self.SRS:SetLabel("ACSR")
|
||||||
@@ -582,7 +582,8 @@ function AICSAR:SetSRSTTSRadio(OnOff,Path,Frequency,Modulation,Port,Voice,Cultur
|
|||||||
self.SRS:SetCulture(Culture)
|
self.SRS:SetCulture(Culture)
|
||||||
self.SRS:SetGender(Gender)
|
self.SRS:SetGender(Gender)
|
||||||
if GoogleCredentials then
|
if GoogleCredentials then
|
||||||
self.SRS:SetGoogle(GoogleCredentials)
|
self.SRS:SetProviderOptionsGoogle(GoogleCredentials,GoogleCredentials)
|
||||||
|
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
self.SRSGoogle = true
|
self.SRSGoogle = true
|
||||||
end
|
end
|
||||||
self.SRSQ = MSRSQUEUE:New(self.alias)
|
self.SRSQ = MSRSQUEUE:New(self.alias)
|
||||||
@@ -600,14 +601,16 @@ end
|
|||||||
function AICSAR:SetPilotTTSVoice(Voice,Culture,Gender)
|
function AICSAR:SetPilotTTSVoice(Voice,Culture,Gender)
|
||||||
self:T(self.lid .. "SetPilotTTSVoice")
|
self:T(self.lid .. "SetPilotTTSVoice")
|
||||||
self.SRSPilotVoice = true
|
self.SRSPilotVoice = true
|
||||||
self.SRSPilot = MSRS:New(self.SRSPath,self.SRSFrequency,self.SRSModulation,1)
|
self.SRSPilot = MSRS:New(self.SRSPath,self.SRSFrequency,self.SRSModulation)
|
||||||
self.SRSPilot:SetCoalition(self.coalition)
|
self.SRSPilot:SetCoalition(self.coalition)
|
||||||
self.SRSPilot:SetVoice(Voice)
|
self.SRSPilot:SetVoice(Voice)
|
||||||
self.SRSPilot:SetCulture(Culture or "en-US")
|
self.SRSPilot:SetCulture(Culture or "en-US")
|
||||||
self.SRSPilot:SetGender(Gender or "male")
|
self.SRSPilot:SetGender(Gender or "male")
|
||||||
self.SRSPilot:SetLabel("PILOT")
|
self.SRSPilot:SetLabel("PILOT")
|
||||||
if self.SRS.google then
|
if self.SRSGoogle then
|
||||||
self.SRSPilot:SetGoogle(self.SRS.google)
|
local poptions = self.SRS:GetProviderOptions(MSRS.Provider.GOOGLE) -- Sound.SRS#MSRS.ProviderOptions
|
||||||
|
self.SRSPilot:SetProviderOptionsGoogle(poptions.credentials,poptions.key)
|
||||||
|
self.SRSPilot:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -622,14 +625,16 @@ end
|
|||||||
function AICSAR:SetOperatorTTSVoice(Voice,Culture,Gender)
|
function AICSAR:SetOperatorTTSVoice(Voice,Culture,Gender)
|
||||||
self:T(self.lid .. "SetOperatorTTSVoice")
|
self:T(self.lid .. "SetOperatorTTSVoice")
|
||||||
self.SRSOperatorVoice = true
|
self.SRSOperatorVoice = true
|
||||||
self.SRSOperator = MSRS:New(self.SRSPath,self.SRSFrequency,self.SRSModulation,1)
|
self.SRSOperator = MSRS:New(self.SRSPath,self.SRSFrequency,self.SRSModulation)
|
||||||
self.SRSOperator:SetCoalition(self.coalition)
|
self.SRSOperator:SetCoalition(self.coalition)
|
||||||
self.SRSOperator:SetVoice(Voice)
|
self.SRSOperator:SetVoice(Voice)
|
||||||
self.SRSOperator:SetCulture(Culture or "en-GB")
|
self.SRSOperator:SetCulture(Culture or "en-GB")
|
||||||
self.SRSOperator:SetGender(Gender or "female")
|
self.SRSOperator:SetGender(Gender or "female")
|
||||||
self.SRSPilot:SetLabel("RESCUE")
|
self.SRSOperator:SetLabel("RESCUE")
|
||||||
if self.SRS.google then
|
if self.SRSGoogle then
|
||||||
self.SRSOperator:SetGoogle(self.SRS.google)
|
local poptions = self.SRS:GetProviderOptions(MSRS.Provider.GOOGLE) -- Sound.SRS#MSRS.ProviderOptions
|
||||||
|
self.SRSOperator:SetProviderOptionsGoogle(poptions.credentials,poptions.key)
|
||||||
|
self.SRSOperator:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,9 +10,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions: None
|
||||||
--
|
|
||||||
-- [ABP - Airbase Police](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/ABP%20-%20Airbase%20Police)
|
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -20,13 +18,15 @@
|
|||||||
-- ### Author: FlightControl - Framework Design & Programming
|
-- ### Author: FlightControl - Framework Design & Programming
|
||||||
-- ### Refactoring to use the Runway auto-detection: Applevangelist
|
-- ### Refactoring to use the Runway auto-detection: Applevangelist
|
||||||
-- @date August 2022
|
-- @date August 2022
|
||||||
|
-- Last Update Nov 2023
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Functional.ATC_Ground
|
-- @module Functional.ATC_Ground
|
||||||
-- @image Air_Traffic_Control_Ground_Operations.JPG
|
-- @image Air_Traffic_Control_Ground_Operations.JPG
|
||||||
|
|
||||||
--- @type ATC_GROUND
|
---
|
||||||
|
-- @type ATC_GROUND
|
||||||
-- @field Core.Set#SET_CLIENT SetClient
|
-- @field Core.Set#SET_CLIENT SetClient
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
@@ -39,7 +39,8 @@ ATC_GROUND = {
|
|||||||
AirbaseNames = nil,
|
AirbaseNames = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @type ATC_GROUND.AirbaseNames
|
---
|
||||||
|
-- @type ATC_GROUND.AirbaseNames
|
||||||
-- @list <#string>
|
-- @list <#string>
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ function ATC_GROUND:New( Airbases, AirbaseList )
|
|||||||
|
|
||||||
-- Inherits from BASE
|
-- Inherits from BASE
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND
|
local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND
|
||||||
self:E( { self.ClassName, Airbases } )
|
self:T( { self.ClassName, Airbases } )
|
||||||
|
|
||||||
self.Airbases = Airbases
|
self.Airbases = Airbases
|
||||||
self.AirbaseList = AirbaseList
|
self.AirbaseList = AirbaseList
|
||||||
@@ -82,7 +83,7 @@ function ATC_GROUND:New( Airbases, AirbaseList )
|
|||||||
end
|
end
|
||||||
|
|
||||||
self.SetClient:ForEachClient(
|
self.SetClient:ForEachClient(
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
function( Client )
|
function( Client )
|
||||||
Client:SetState( self, "Speeding", false )
|
Client:SetState( self, "Speeding", false )
|
||||||
Client:SetState( self, "Warnings", 0)
|
Client:SetState( self, "Warnings", 0)
|
||||||
@@ -246,11 +247,11 @@ function ATC_GROUND:SetMaximumKickSpeedMiph( MaximumKickSpeedMiph, Airbase )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #ATC_GROUND self
|
-- @param #ATC_GROUND self
|
||||||
function ATC_GROUND:_AirbaseMonitor()
|
function ATC_GROUND:_AirbaseMonitor()
|
||||||
|
|
||||||
self.SetClient:ForEachClient(
|
self.SetClient:ForEachClient(
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
function( Client )
|
function( Client )
|
||||||
|
|
||||||
if Client:IsAlive() then
|
if Client:IsAlive() then
|
||||||
@@ -258,7 +259,7 @@ function ATC_GROUND:_AirbaseMonitor()
|
|||||||
local IsOnGround = Client:InAir() == false
|
local IsOnGround = Client:InAir() == false
|
||||||
|
|
||||||
for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do
|
for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do
|
||||||
self:E( AirbaseID, AirbaseMeta.KickSpeed )
|
self:T( AirbaseID, AirbaseMeta.KickSpeed )
|
||||||
|
|
||||||
if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then
|
if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then
|
||||||
|
|
||||||
@@ -271,7 +272,7 @@ function ATC_GROUND:_AirbaseMonitor()
|
|||||||
|
|
||||||
if IsOnGround then
|
if IsOnGround then
|
||||||
local Taxi = Client:GetState( self, "Taxi" )
|
local Taxi = Client:GetState( self, "Taxi" )
|
||||||
self:E( Taxi )
|
self:T( Taxi )
|
||||||
if Taxi == false then
|
if Taxi == false then
|
||||||
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
|
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
|
||||||
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
|
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
|
||||||
@@ -331,7 +332,7 @@ function ATC_GROUND:_AirbaseMonitor()
|
|||||||
Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
|
Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
|
||||||
else
|
else
|
||||||
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
Client:Destroy()
|
Client:Destroy()
|
||||||
Client:SetState( self, "Speeding", false )
|
Client:SetState( self, "Speeding", false )
|
||||||
Client:SetState( self, "Warnings", 0 )
|
Client:SetState( self, "Warnings", 0 )
|
||||||
@@ -363,7 +364,7 @@ function ATC_GROUND:_AirbaseMonitor()
|
|||||||
Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 )
|
Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 )
|
||||||
else
|
else
|
||||||
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
Client:Destroy()
|
Client:Destroy()
|
||||||
Client:SetState( self, "IsOffRunway", false )
|
Client:SetState( self, "IsOffRunway", false )
|
||||||
Client:SetState( self, "OffRunwayWarnings", 0 )
|
Client:SetState( self, "OffRunwayWarnings", 0 )
|
||||||
@@ -424,13 +425,20 @@ ATC_GROUND_UNIVERSAL = {
|
|||||||
|
|
||||||
--- Creates a new ATC\_GROUND\_UNIVERSAL object. This works on any map.
|
--- Creates a new ATC\_GROUND\_UNIVERSAL object. This works on any map.
|
||||||
-- @param #ATC_GROUND_UNIVERSAL self
|
-- @param #ATC_GROUND_UNIVERSAL self
|
||||||
-- @param AirbaseList (Optional) A table of Airbase Names.
|
-- @param AirbaseList A table of Airbase Names. Leave empty to cover **all** airbases of the map.
|
||||||
-- @return #ATC_GROUND_UNIVERSAL self
|
-- @return #ATC_GROUND_UNIVERSAL self
|
||||||
|
-- @usage
|
||||||
|
-- -- define monitoring for one airbase
|
||||||
|
-- local atc=ATC_GROUND_UNIVERSAL:New({AIRBASE.Syria.Gecitkale})
|
||||||
|
-- -- set kick speed
|
||||||
|
-- atc:SetKickSpeed(UTILS.KnotsToMps(20))
|
||||||
|
-- -- start monitoring evey 10 secs
|
||||||
|
-- atc:Start(10)
|
||||||
function ATC_GROUND_UNIVERSAL:New(AirbaseList)
|
function ATC_GROUND_UNIVERSAL:New(AirbaseList)
|
||||||
|
|
||||||
-- Inherits from BASE
|
-- Inherits from BASE
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND
|
local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND
|
||||||
self:E( { self.ClassName } )
|
self:T( { self.ClassName } )
|
||||||
|
|
||||||
self.Airbases = {}
|
self.Airbases = {}
|
||||||
|
|
||||||
@@ -440,6 +448,13 @@ function ATC_GROUND_UNIVERSAL:New(AirbaseList)
|
|||||||
|
|
||||||
self.AirbaseList = AirbaseList
|
self.AirbaseList = AirbaseList
|
||||||
|
|
||||||
|
if not self.AirbaseList then
|
||||||
|
self.AirbaseList = {}
|
||||||
|
for _name,_ in pairs(_DATABASE.AIRBASES) do
|
||||||
|
self.AirbaseList[_name]=_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
self.SetClient = SET_CLIENT:New():FilterCategories( "plane" ):FilterStart()
|
self.SetClient = SET_CLIENT:New():FilterCategories( "plane" ):FilterStart()
|
||||||
|
|
||||||
|
|
||||||
@@ -460,8 +475,9 @@ function ATC_GROUND_UNIVERSAL:New(AirbaseList)
|
|||||||
self.Airbases[AirbaseName].Monitor = true
|
self.Airbases[AirbaseName].Monitor = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
self.SetClient:ForEachClient(
|
self.SetClient:ForEachClient(
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
function( Client )
|
function( Client )
|
||||||
Client:SetState( self, "Speeding", false )
|
Client:SetState( self, "Speeding", false )
|
||||||
Client:SetState( self, "Warnings", 0)
|
Client:SetState( self, "Warnings", 0)
|
||||||
@@ -679,9 +695,10 @@ end
|
|||||||
-- @param #ATC_GROUND_UNIVERSAL self
|
-- @param #ATC_GROUND_UNIVERSAL self
|
||||||
-- @return #ATC_GROUND_UNIVERSAL self
|
-- @return #ATC_GROUND_UNIVERSAL self
|
||||||
function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
||||||
|
self:I("_AirbaseMonitor")
|
||||||
self.SetClient:ForEachClient(
|
self.SetClient:ForEachClient(
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
--- Nameless function
|
||||||
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
function( Client )
|
function( Client )
|
||||||
|
|
||||||
if Client:IsAlive() then
|
if Client:IsAlive() then
|
||||||
@@ -689,7 +706,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
|||||||
local IsOnGround = Client:InAir() == false
|
local IsOnGround = Client:InAir() == false
|
||||||
|
|
||||||
for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do
|
for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do
|
||||||
self:E( AirbaseID, AirbaseMeta.KickSpeed )
|
self:T( AirbaseID, AirbaseMeta.KickSpeed )
|
||||||
|
|
||||||
if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then
|
if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then
|
||||||
|
|
||||||
@@ -706,7 +723,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
|||||||
|
|
||||||
if IsOnGround then
|
if IsOnGround then
|
||||||
local Taxi = Client:GetState( self, "Taxi" )
|
local Taxi = Client:GetState( self, "Taxi" )
|
||||||
self:E( Taxi )
|
self:T( Taxi )
|
||||||
if Taxi == false then
|
if Taxi == false then
|
||||||
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
|
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
|
||||||
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
|
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
|
||||||
@@ -766,7 +783,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
|||||||
Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
|
Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
|
||||||
else
|
else
|
||||||
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
Client:Destroy()
|
Client:Destroy()
|
||||||
Client:SetState( self, "Speeding", false )
|
Client:SetState( self, "Speeding", false )
|
||||||
Client:SetState( self, "Warnings", 0 )
|
Client:SetState( self, "Warnings", 0 )
|
||||||
@@ -798,7 +815,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
|||||||
Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 )
|
Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 )
|
||||||
else
|
else
|
||||||
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
Client:Destroy()
|
Client:Destroy()
|
||||||
Client:SetState( self, "IsOffRunway", false )
|
Client:SetState( self, "IsOffRunway", false )
|
||||||
Client:SetState( self, "OffRunwayWarnings", 0 )
|
Client:SetState( self, "OffRunwayWarnings", 0 )
|
||||||
@@ -838,15 +855,16 @@ end
|
|||||||
|
|
||||||
--- Start SCHEDULER for ATC_GROUND_UNIVERSAL object.
|
--- Start SCHEDULER for ATC_GROUND_UNIVERSAL object.
|
||||||
-- @param #ATC_GROUND_UNIVERSAL self
|
-- @param #ATC_GROUND_UNIVERSAL self
|
||||||
-- @param RepeatScanSeconds Time in second for defining occurency of alerts.
|
-- @param RepeatScanSeconds Time in second for defining schedule of alerts.
|
||||||
-- @return #ATC_GROUND_UNIVERSAL self
|
-- @return #ATC_GROUND_UNIVERSAL self
|
||||||
function ATC_GROUND_UNIVERSAL:Start( RepeatScanSeconds )
|
function ATC_GROUND_UNIVERSAL:Start( RepeatScanSeconds )
|
||||||
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
||||||
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds )
|
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @type ATC_GROUND_CAUCASUS
|
---
|
||||||
|
-- @type ATC_GROUND_CAUCASUS
|
||||||
-- @extends #ATC_GROUND
|
-- @extends #ATC_GROUND
|
||||||
|
|
||||||
--- # ATC\_GROUND\_CAUCASUS, extends @{#ATC_GROUND_UNIVERSAL}
|
--- # ATC\_GROUND\_CAUCASUS, extends @{#ATC_GROUND_UNIVERSAL}
|
||||||
@@ -981,12 +999,12 @@ end
|
|||||||
-- @return nothing
|
-- @return nothing
|
||||||
function ATC_GROUND_CAUCASUS:Start( RepeatScanSeconds )
|
function ATC_GROUND_CAUCASUS:Start( RepeatScanSeconds )
|
||||||
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
||||||
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds )
|
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
--- @type ATC_GROUND_NEVADA
|
-- @type ATC_GROUND_NEVADA
|
||||||
-- @extends #ATC_GROUND
|
-- @extends #ATC_GROUND
|
||||||
|
|
||||||
|
|
||||||
@@ -1120,11 +1138,11 @@ end
|
|||||||
-- @return nothing
|
-- @return nothing
|
||||||
function ATC_GROUND_NEVADA:Start( RepeatScanSeconds )
|
function ATC_GROUND_NEVADA:Start( RepeatScanSeconds )
|
||||||
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
||||||
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds )
|
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
--- @type ATC_GROUND_NORMANDY
|
-- @type ATC_GROUND_NORMANDY
|
||||||
-- @extends #ATC_GROUND
|
-- @extends #ATC_GROUND
|
||||||
|
|
||||||
|
|
||||||
@@ -1277,10 +1295,11 @@ end
|
|||||||
-- @return nothing
|
-- @return nothing
|
||||||
function ATC_GROUND_NORMANDY:Start( RepeatScanSeconds )
|
function ATC_GROUND_NORMANDY:Start( RepeatScanSeconds )
|
||||||
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
||||||
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds )
|
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @type ATC_GROUND_PERSIANGULF
|
---
|
||||||
|
-- @type ATC_GROUND_PERSIANGULF
|
||||||
-- @extends #ATC_GROUND
|
-- @extends #ATC_GROUND
|
||||||
|
|
||||||
|
|
||||||
@@ -1419,11 +1438,11 @@ end
|
|||||||
-- @return nothing
|
-- @return nothing
|
||||||
function ATC_GROUND_PERSIANGULF:Start( RepeatScanSeconds )
|
function ATC_GROUND_PERSIANGULF:Start( RepeatScanSeconds )
|
||||||
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
||||||
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds )
|
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @type ATC_GROUND_MARIANAISLANDS
|
-- @type ATC_GROUND_MARIANAISLANDS
|
||||||
-- @extends #ATC_GROUND
|
-- @extends #ATC_GROUND
|
||||||
|
|
||||||
|
|
||||||
@@ -1517,7 +1536,7 @@ end
|
|||||||
-- * @{#ATC_GROUND.SetMaximumKickSpeedKmph}(): Set the maximum speed allowed at an airbase in kilometers per hour.
|
-- * @{#ATC_GROUND.SetMaximumKickSpeedKmph}(): Set the maximum speed allowed at an airbase in kilometers per hour.
|
||||||
-- * @{#ATC_GROUND.SetMaximumKickSpeedMiph}(): Set the maximum speed allowed at an airbase in miles per hour.
|
-- * @{#ATC_GROUND.SetMaximumKickSpeedMiph}(): Set the maximum speed allowed at an airbase in miles per hour.
|
||||||
--
|
--
|
||||||
---- @field #ATC_GROUND_MARIANAISLANDS
|
-- @field #ATC_GROUND_MARIANAISLANDS
|
||||||
ATC_GROUND_MARIANAISLANDS = {
|
ATC_GROUND_MARIANAISLANDS = {
|
||||||
ClassName = "ATC_GROUND_MARIANAISLANDS",
|
ClassName = "ATC_GROUND_MARIANAISLANDS",
|
||||||
}
|
}
|
||||||
@@ -1529,7 +1548,7 @@ ATC_GROUND_MARIANAISLANDS = {
|
|||||||
function ATC_GROUND_MARIANAISLANDS:New( AirbaseNames )
|
function ATC_GROUND_MARIANAISLANDS:New( AirbaseNames )
|
||||||
|
|
||||||
-- Inherits from BASE
|
-- Inherits from BASE
|
||||||
local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New( self.Airbases, AirbaseNames ) )
|
local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New( AirbaseNames ) )
|
||||||
|
|
||||||
self:SetKickSpeedKmph( 50 )
|
self:SetKickSpeedKmph( 50 )
|
||||||
self:SetMaximumKickSpeedKmph( 150 )
|
self:SetMaximumKickSpeedKmph( 150 )
|
||||||
@@ -1543,5 +1562,5 @@ end
|
|||||||
-- @return nothing
|
-- @return nothing
|
||||||
function ATC_GROUND_MARIANAISLANDS:Start( RepeatScanSeconds )
|
function ATC_GROUND_MARIANAISLANDS:Start( RepeatScanSeconds )
|
||||||
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
RepeatScanSeconds = RepeatScanSeconds or 0.05
|
||||||
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds )
|
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- ### [AmmoTruck](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/AMT%20-%20AmmoTruck/AmmoTruck%20100%20-%20NTTR%20-%20Basic)
|
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Functional/AmmoTruck)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
-- Last update: July 2023
|
-- Last update: July 2023
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **AMMOTRUCK** class, extends Core.FSM#FSM
|
--- **AMMOTRUCK** class, extends Core.Fsm#FSM
|
||||||
-- @type AMMOTRUCK
|
-- @type AMMOTRUCK
|
||||||
-- @field #string ClassName Class Name
|
-- @field #string ClassName Class Name
|
||||||
-- @field #string lid Lid for log entries
|
-- @field #string lid Lid for log entries
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
-- @field #number waitingtime Max waiting time in seconds
|
-- @field #number waitingtime Max waiting time in seconds
|
||||||
-- @field #boolean routeonroad Route truck on road if true (default)
|
-- @field #boolean routeonroad Route truck on road if true (default)
|
||||||
-- @field #number reloads Number of reloads a single truck can do before he must return home
|
-- @field #number reloads Number of reloads a single truck can do before he must return home
|
||||||
-- @extends Core.FSM#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- *Amateurs talk about tactics, but professionals study logistics.* - General Robert H Barrow, USMC
|
--- *Amateurs talk about tactics, but professionals study logistics.* - General Robert H Barrow, USMC
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -3546,7 +3546,7 @@ end
|
|||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
function ARTY:onafterRespawn(Controllable, From, Event, To)
|
function ARTY:onafterRespawn(Controllable, From, Event, To)
|
||||||
self:_EventFromTo("onafterRespawn", Event, From, To)
|
self:_EventFromTo("onafterRespawn", Event, From, To)
|
||||||
|
self:I("Respawning arty group")
|
||||||
local group=self.Controllable --Wrapper.Group#GROUP
|
local group=self.Controllable --Wrapper.Group#GROUP
|
||||||
|
|
||||||
-- Respawn group.
|
-- Respawn group.
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
-- **AUOTLASE** - Autolase targets in the field.
|
-- **AUOTLASE** - Autolase targets in the field.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- ### [Autolase](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/)
|
-- None yet.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- **Main Features:**
|
-- **Main Features:**
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
-- @image Designation.JPG
|
-- @image Designation.JPG
|
||||||
--
|
--
|
||||||
-- Date: 24 Oct 2021
|
-- Date: 24 Oct 2021
|
||||||
-- Last Update: Oct 2023
|
-- Last Update: Jan 2024
|
||||||
--
|
--
|
||||||
--- Class AUTOLASE
|
--- Class AUTOLASE
|
||||||
-- @type AUTOLASE
|
-- @type AUTOLASE
|
||||||
@@ -87,6 +87,7 @@
|
|||||||
-- @field Core.Set#SET_GROUP RecceSet
|
-- @field Core.Set#SET_GROUP RecceSet
|
||||||
-- @field #table LaserCodes
|
-- @field #table LaserCodes
|
||||||
-- @field #table playermenus
|
-- @field #table playermenus
|
||||||
|
-- @field #boolean smokemenu
|
||||||
-- @extends Ops.Intel#INTEL
|
-- @extends Ops.Intel#INTEL
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -97,6 +98,7 @@ AUTOLASE = {
|
|||||||
verbose = 0,
|
verbose = 0,
|
||||||
alias = "",
|
alias = "",
|
||||||
debug = false,
|
debug = false,
|
||||||
|
smokemenu = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Laser spot info
|
--- Laser spot info
|
||||||
@@ -115,7 +117,7 @@ AUTOLASE = {
|
|||||||
|
|
||||||
--- AUTOLASE class version.
|
--- AUTOLASE class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AUTOLASE.version = "0.1.22"
|
AUTOLASE.version = "0.1.23"
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
-- Begin Functional.Autolase.lua
|
-- Begin Functional.Autolase.lua
|
||||||
@@ -202,6 +204,7 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
|
|||||||
self.blacklistattributes = {}
|
self.blacklistattributes = {}
|
||||||
self:SetLaserCodes( { 1688, 1130, 4785, 6547, 1465, 4578 } ) -- set self.LaserCodes
|
self:SetLaserCodes( { 1688, 1130, 4785, 6547, 1465, 4578 } ) -- set self.LaserCodes
|
||||||
self.playermenus = {}
|
self.playermenus = {}
|
||||||
|
self.smokemenu = true
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
-- Set some string id for output to DCS.log file.
|
||||||
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
|
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
|
||||||
@@ -329,9 +332,11 @@ function AUTOLASE:SetPilotMenu()
|
|||||||
local lasetopm = MENU_GROUP:New(Group,"Autolase",nil)
|
local lasetopm = MENU_GROUP:New(Group,"Autolase",nil)
|
||||||
self.playermenus[unitname] = lasetopm
|
self.playermenus[unitname] = lasetopm
|
||||||
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Status",lasetopm,self.ShowStatus,self,Group,Unit)
|
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Status",lasetopm,self.ShowStatus,self,Group,Unit)
|
||||||
local smoke = (self.smoketargets == true) and "off" or "on"
|
if self.smokemenu then
|
||||||
local smoketext = string.format("Switch smoke targets to %s",smoke)
|
local smoke = (self.smoketargets == true) and "off" or "on"
|
||||||
local smokemenu = MENU_GROUP_COMMAND:New(Group,smoketext,lasetopm,self.SetSmokeTargets,self,(not self.smoketargets))
|
local smoketext = string.format("Switch smoke targets to %s",smoke)
|
||||||
|
local smokemenu = MENU_GROUP_COMMAND:New(Group,smoketext,lasetopm,self.SetSmokeTargets,self,(not self.smoketargets))
|
||||||
|
end
|
||||||
for _,_grp in pairs(self.RecceSet.Set) do
|
for _,_grp in pairs(self.RecceSet.Set) do
|
||||||
local grp = _grp -- Wrapper.Group#GROUP
|
local grp = _grp -- Wrapper.Group#GROUP
|
||||||
local unit = grp:GetUnit(1)
|
local unit = grp:GetUnit(1)
|
||||||
@@ -443,7 +448,7 @@ end
|
|||||||
-- @param #string Gender (Optional) Defaults to "male"
|
-- @param #string Gender (Optional) Defaults to "male"
|
||||||
-- @param #string Culture (Optional) Defaults to "en-US"
|
-- @param #string Culture (Optional) Defaults to "en-US"
|
||||||
-- @param #number Port (Optional) Defaults to 5002
|
-- @param #number Port (Optional) Defaults to 5002
|
||||||
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS#SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
||||||
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
||||||
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
||||||
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
|
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
|
||||||
@@ -451,18 +456,18 @@ end
|
|||||||
function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation,Label,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
|
function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation,Label,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
|
||||||
if OnOff then
|
if OnOff then
|
||||||
self.useSRS = true
|
self.useSRS = true
|
||||||
self.SRSPath = Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
self.SRSFreq = Frequency or 271
|
self.SRSFreq = Frequency or 271
|
||||||
self.SRSMod = Modulation or radio.modulation.AM
|
self.SRSMod = Modulation or radio.modulation.AM
|
||||||
self.Gender = Gender or "male"
|
self.Gender = Gender or MSRS.gender or "male"
|
||||||
self.Culture = Culture or "en-US"
|
self.Culture = Culture or MSRS.culture or "en-US"
|
||||||
self.Port = Port or 5002
|
self.Port = Port or MSRS.port or 5002
|
||||||
self.Voice = Voice
|
self.Voice = Voice
|
||||||
self.PathToGoogleKey = PathToGoogleKey
|
self.PathToGoogleKey = PathToGoogleKey
|
||||||
self.Volume = Volume or 1.0
|
self.Volume = Volume or 1.0
|
||||||
self.Label = Label
|
self.Label = Label
|
||||||
-- set up SRS
|
-- set up SRS
|
||||||
self.SRS = MSRS:New(self.SRSPath,self.SRSFreq,self.SRSMod,self.Volume)
|
self.SRS = MSRS:New(self.SRSPath,self.SRSFreq,self.SRSMod)
|
||||||
self.SRS:SetCoalition(self.coalition)
|
self.SRS:SetCoalition(self.coalition)
|
||||||
self.SRS:SetLabel(self.MenuName or self.Name)
|
self.SRS:SetLabel(self.MenuName or self.Name)
|
||||||
self.SRS:SetGender(self.Gender)
|
self.SRS:SetGender(self.Gender)
|
||||||
@@ -470,8 +475,10 @@ function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation,Label,Gender,Cultu
|
|||||||
self.SRS:SetPort(self.Port)
|
self.SRS:SetPort(self.Port)
|
||||||
self.SRS:SetVoice(self.Voice)
|
self.SRS:SetVoice(self.Voice)
|
||||||
self.SRS:SetCoalition(self.coalition)
|
self.SRS:SetCoalition(self.coalition)
|
||||||
|
self.SRS:SetVolume(self.Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.SRS:SetGoogle(self.PathToGoogleKey)
|
self.SRS:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
|
||||||
|
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
self.SRSQueue = MSRSQUEUE:New(self.alias)
|
self.SRSQueue = MSRSQUEUE:New(self.alias)
|
||||||
else
|
else
|
||||||
@@ -579,6 +586,23 @@ function AUTOLASE:SetSmokeTargets(OnOff,Color)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (User) Show the "Switch smoke target..." menu entry for pilots. On by default.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:EnableSmokeMenu()
|
||||||
|
self.smokemenu = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Do not show the "Switch smoke target..." menu entry for pilots.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:DisableSmokeMenu()
|
||||||
|
self.smokemenu = false
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- (Internal) Function to calculate line of sight.
|
--- (Internal) Function to calculate line of sight.
|
||||||
-- @param #AUTOLASE self
|
-- @param #AUTOLASE self
|
||||||
-- @param Wrapper.Unit#UNIT Unit
|
-- @param Wrapper.Unit#UNIT Unit
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [CLA - CleanUp Airbase](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CLA%20-%20CleanUp%20Airbase)
|
-- [CLA - CleanUp Airbase](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/CleanUp)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -15,10 +15,12 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Additional Material:
|
||||||
--
|
--
|
||||||
-- [DES - Designation](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/DES%20-%20Designation)
|
-- * **Demo Missions:** [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/Designate)
|
||||||
--
|
-- * **YouTube videos:** None
|
||||||
|
-- * **Guides:** None
|
||||||
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- Targets detected by recce will be communicated to a group of attacking players.
|
-- Targets detected by recce will be communicated to a group of attacking players.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [DET - Detection](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/DET%20-%20Detection)
|
-- [DET - Detection](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Functional/Detection)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -38,8 +38,9 @@
|
|||||||
-- @image Detection.JPG
|
-- @image Detection.JPG
|
||||||
|
|
||||||
do -- DETECTION_BASE
|
do -- DETECTION_BASE
|
||||||
|
|
||||||
--- @type DETECTION_BASE
|
---
|
||||||
|
-- @type DETECTION_BASE
|
||||||
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Core.Set} of GROUPs in the Forward Air Controller role.
|
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Core.Set} of GROUPs in the Forward Air Controller role.
|
||||||
-- @field DCS#Distance DetectionRange The range till which targets are accepted to be detected.
|
-- @field DCS#Distance DetectionRange The range till which targets are accepted to be detected.
|
||||||
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
|
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
|
||||||
@@ -91,6 +92,11 @@ do -- DETECTION_BASE
|
|||||||
--
|
--
|
||||||
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||||
--
|
--
|
||||||
|
--
|
||||||
|
-- ## Radar Blur - use to make the radar less exact, e.g. for WWII scenarios
|
||||||
|
--
|
||||||
|
-- * @{#DETECTION_BASE.SetRadarBlur}(): Set the radar blur to be used.
|
||||||
|
--
|
||||||
-- ## **DETECTION_ derived classes** group the detected units into a **DetectedItems[]** list
|
-- ## **DETECTION_ derived classes** group the detected units into a **DetectedItems[]** list
|
||||||
--
|
--
|
||||||
-- DETECTION_BASE derived classes build a list called DetectedItems[], which is essentially a first later
|
-- DETECTION_BASE derived classes build a list called DetectedItems[], which is essentially a first later
|
||||||
@@ -268,11 +274,13 @@ do -- DETECTION_BASE
|
|||||||
DetectedItems = {},
|
DetectedItems = {},
|
||||||
DetectedItemsByIndex = {},
|
DetectedItemsByIndex = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @type DETECTION_BASE.DetectedObjects
|
---
|
||||||
|
-- @type DETECTION_BASE.DetectedObjects
|
||||||
-- @list <#DETECTION_BASE.DetectedObject>
|
-- @list <#DETECTION_BASE.DetectedObject>
|
||||||
|
|
||||||
--- @type DETECTION_BASE.DetectedObject
|
---
|
||||||
|
-- @type DETECTION_BASE.DetectedObject
|
||||||
-- @field #string Name
|
-- @field #string Name
|
||||||
-- @field #boolean IsVisible
|
-- @field #boolean IsVisible
|
||||||
-- @field #boolean KnowType
|
-- @field #boolean KnowType
|
||||||
@@ -283,8 +291,9 @@ do -- DETECTION_BASE
|
|||||||
-- @field #number LastTime
|
-- @field #number LastTime
|
||||||
-- @field #boolean LastPos
|
-- @field #boolean LastPos
|
||||||
-- @field #number LastVelocity
|
-- @field #number LastVelocity
|
||||||
|
|
||||||
--- @type DETECTION_BASE.DetectedItems
|
---
|
||||||
|
-- @type DETECTION_BASE.DetectedItems
|
||||||
-- @list <#DETECTION_BASE.DetectedItem>
|
-- @list <#DETECTION_BASE.DetectedItem>
|
||||||
|
|
||||||
--- Detected item data structure.
|
--- Detected item data structure.
|
||||||
@@ -522,7 +531,7 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
do -- State Transition Handling
|
do -- State Transition Handling
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
@@ -530,7 +539,7 @@ do -- DETECTION_BASE
|
|||||||
self:__Detect( 1 )
|
self:__Detect( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
@@ -570,7 +579,7 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #number The amount of alive recce.
|
-- @param #number The amount of alive recce.
|
||||||
function DETECTION_BASE:CountAliveRecce()
|
function DETECTION_BASE:CountAliveRecce()
|
||||||
|
|
||||||
@@ -578,7 +587,7 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
function DETECTION_BASE:ForEachAliveRecce( IteratorFunction, ... )
|
function DETECTION_BASE:ForEachAliveRecce( IteratorFunction, ... )
|
||||||
self:F2( arg )
|
self:F2( arg )
|
||||||
|
|
||||||
@@ -587,7 +596,7 @@ do -- DETECTION_BASE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
@@ -712,6 +721,31 @@ do -- DETECTION_BASE
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Calculate radar blur probability
|
||||||
|
|
||||||
|
if self.RadarBlur then
|
||||||
|
MESSAGE:New("Radar Blur",10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
||||||
|
local minheight = self.RadarBlurMinHeight or 250 -- meters
|
||||||
|
local thresheight = self.RadarBlurThresHeight or 90 -- 10% chance to find a low flying group
|
||||||
|
local thresblur = self.RadarBlurThresBlur or 85 -- 25% chance to escape the radar overall
|
||||||
|
local dist = math.floor(Distance)
|
||||||
|
if dist <= self.RadarBlurClosing then
|
||||||
|
thresheight = (((dist*dist)/self.RadarBlurClosingSquare)*thresheight)
|
||||||
|
thresblur = (((dist*dist)/self.RadarBlurClosingSquare)*thresblur)
|
||||||
|
end
|
||||||
|
local fheight = math.floor(math.random(1,10000)/100)
|
||||||
|
local fblur = math.floor(math.random(1,10000)/100)
|
||||||
|
local unit = UNIT:FindByName(DetectedObjectName)
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
local AGL = unit:GetAltitude(true)
|
||||||
|
MESSAGE:New("Unit "..DetectedObjectName.." is at "..math.floor(AGL).."m. Distance "..math.floor(Distance).."km.",10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
||||||
|
MESSAGE:New(string.format("fheight = %d/%d | fblur = %d/%d",fheight,thresheight,fblur,thresblur),10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
||||||
|
if fblur > thresblur then DetectionAccepted = false end
|
||||||
|
if AGL <= minheight and fheight < thresheight then DetectionAccepted = false end
|
||||||
|
MESSAGE:New("Detection Accepted = "..tostring(DetectionAccepted),10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Calculate additional probabilities
|
-- Calculate additional probabilities
|
||||||
|
|
||||||
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.DistanceProbability then
|
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.DistanceProbability then
|
||||||
@@ -1011,7 +1045,24 @@ do -- DETECTION_BASE
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Method to make the radar detection less accurate, e.g. for WWII scenarios.
|
||||||
|
-- @param #DETECTION_BASE self
|
||||||
|
-- @param #number minheight Minimum flight height to be detected, in meters AGL (above ground)
|
||||||
|
-- @param #number thresheight Threshold to escape the radar if flying below minheight, defaults to 90 (90% escape chance)
|
||||||
|
-- @param #number thresblur Threshold to be detected by the radar overall, defaults to 85 (85% chance to be found)
|
||||||
|
-- @param #number closing Closing-in in km - the limit of km from which on it becomes increasingly difficult to escape radar detection if flying towards the radar position. Should be about 1/3 of the radar detection radius in kilometers, defaults to 20.
|
||||||
|
-- @return #DETECTION_BASE self
|
||||||
|
function DETECTION_BASE:SetRadarBlur(minheight,thresheight,thresblur,closing)
|
||||||
|
self.RadarBlur = true
|
||||||
|
self.RadarBlurMinHeight = minheight or 250 -- meters
|
||||||
|
self.RadarBlurThresHeight = thresheight or 90 -- 10% chance to find a low flying group
|
||||||
|
self.RadarBlurThresBlur = thresblur or 85 -- 25% chance to escape the radar overall
|
||||||
|
self.RadarBlurClosing = closing or 20 -- 20km
|
||||||
|
self.RadarBlurClosingSquare = self.RadarBlurClosing * self.RadarBlurClosing
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -1354,7 +1405,7 @@ do -- DETECTION_BASE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @param DCS#Unit FoundDCSUnit
|
-- @param DCS#Unit FoundDCSUnit
|
||||||
-- @param Wrapper.Group#GROUP ReportGroup
|
-- @param Wrapper.Group#GROUP ReportGroup
|
||||||
-- @param Core.Set#SET_GROUP ReportSetGroup
|
-- @param Core.Set#SET_GROUP ReportSetGroup
|
||||||
local FindNearByFriendlies = function( FoundDCSUnit, ReportGroupData )
|
local FindNearByFriendlies = function( FoundDCSUnit, ReportGroupData )
|
||||||
@@ -1419,7 +1470,7 @@ do -- DETECTION_BASE
|
|||||||
DetectedItem.PlayersNearBy = nil
|
DetectedItem.PlayersNearBy = nil
|
||||||
|
|
||||||
_DATABASE:ForEachPlayer(
|
_DATABASE:ForEachPlayer(
|
||||||
--- @param Wrapper.Unit#UNIT PlayerUnit
|
-- @param Wrapper.Unit#UNIT PlayerUnit
|
||||||
function( PlayerUnitName )
|
function( PlayerUnitName )
|
||||||
local PlayerUnit = UNIT:FindByName( PlayerUnitName )
|
local PlayerUnit = UNIT:FindByName( PlayerUnitName )
|
||||||
|
|
||||||
@@ -1975,8 +2026,9 @@ do -- DETECTION_BASE
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- DETECTION_UNITS
|
do -- DETECTION_UNITS
|
||||||
|
|
||||||
--- @type DETECTION_UNITS
|
---
|
||||||
|
-- @type DETECTION_UNITS
|
||||||
-- @field DCS#Distance DetectionRange The range till which targets are detected.
|
-- @field DCS#Distance DetectionRange The range till which targets are detected.
|
||||||
-- @extends Functional.Detection#DETECTION_BASE
|
-- @extends Functional.Detection#DETECTION_BASE
|
||||||
|
|
||||||
@@ -2231,8 +2283,9 @@ do -- DETECTION_UNITS
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- DETECTION_TYPES
|
do -- DETECTION_TYPES
|
||||||
|
|
||||||
--- @type DETECTION_TYPES
|
---
|
||||||
|
-- @type DETECTION_TYPES
|
||||||
-- @extends Functional.Detection#DETECTION_BASE
|
-- @extends Functional.Detection#DETECTION_BASE
|
||||||
|
|
||||||
--- Will detect units within the battle zone.
|
--- Will detect units within the battle zone.
|
||||||
@@ -2434,8 +2487,9 @@ do -- DETECTION_TYPES
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- DETECTION_AREAS
|
do -- DETECTION_AREAS
|
||||||
|
|
||||||
--- @type DETECTION_AREAS
|
---
|
||||||
|
-- @type DETECTION_AREAS
|
||||||
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||||
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
||||||
-- @extends Functional.Detection#DETECTION_BASE
|
-- @extends Functional.Detection#DETECTION_BASE
|
||||||
@@ -2961,7 +3015,7 @@ do -- DETECTION_AREAS
|
|||||||
|
|
||||||
-- DetectedSet:Flush( self )
|
-- DetectedSet:Flush( self )
|
||||||
|
|
||||||
DetectedSet:ForEachUnit( --- @param Wrapper.Unit#UNIT DetectedUnit
|
DetectedSet:ForEachUnit( -- @param Wrapper.Unit#UNIT DetectedUnit
|
||||||
function( DetectedUnit )
|
function( DetectedUnit )
|
||||||
if DetectedUnit:IsAlive() then
|
if DetectedUnit:IsAlive() then
|
||||||
-- self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
-- self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
||||||
|
|||||||
@@ -16,11 +16,13 @@
|
|||||||
-- * Escort tactical situation reporting.
|
-- * Escort tactical situation reporting.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Additional Material:
|
||||||
--
|
--
|
||||||
-- [ESC - Escorting](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/ESC%20-%20Escorting)
|
-- * **Demo Missions:** [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/Escort)
|
||||||
--
|
-- * **YouTube videos:** None
|
||||||
|
-- * **Guides:** None
|
||||||
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- Allows you to interact with escorting AI on your flight and take the lead.
|
-- Allows you to interact with escorting AI on your flight and take the lead.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- ### [MANTIS - Modular, Automatic and Network capable Targeting and Interception System](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/MTS%20-%20Mantis/MTS-010%20-%20Basic%20Mantis%20Demo)
|
-- ### [MANTIS - Modular, Automatic and Network capable Targeting and Interception System](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/Mantis)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
-- @module Functional.Mantis
|
-- @module Functional.Mantis
|
||||||
-- @image Functional.Mantis.jpg
|
-- @image Functional.Mantis.jpg
|
||||||
--
|
--
|
||||||
-- Last Update: Oct 2023
|
-- Last Update: Dec 2023
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **MANTIS** class, extends Core.Base#BASE
|
--- **MANTIS** class, extends Core.Base#BASE
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
-- Known SAM types at the time of writing are:
|
-- Known SAM types at the time of writing are:
|
||||||
--
|
--
|
||||||
-- * Avenger
|
-- * Avenger
|
||||||
-- * Chaparrel
|
-- * Chaparral
|
||||||
-- * Hawk
|
-- * Hawk
|
||||||
-- * Linebacker
|
-- * Linebacker
|
||||||
-- * NASAMS
|
-- * NASAMS
|
||||||
@@ -365,7 +365,7 @@ MANTIS.SamData = {
|
|||||||
["SA-15"] = { Range=11, Blindspot=0, Height=6, Type="Short", Radar="Tor 9A331" },
|
["SA-15"] = { Range=11, Blindspot=0, Height=6, Type="Short", Radar="Tor 9A331" },
|
||||||
["SA-13"] = { Range=5, Blindspot=0, Height=3, Type="Short", Radar="Strela" },
|
["SA-13"] = { Range=5, Blindspot=0, Height=3, Type="Short", Radar="Strela" },
|
||||||
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
|
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
|
||||||
["Chaparrel"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
||||||
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Linebacker" },
|
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Linebacker" },
|
||||||
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
||||||
-- units from HDS Mod, multi launcher options is tricky
|
-- units from HDS Mod, multi launcher options is tricky
|
||||||
@@ -631,7 +631,7 @@ do
|
|||||||
|
|
||||||
-- TODO Version
|
-- TODO Version
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
self.version="0.8.15"
|
self.version="0.8.16"
|
||||||
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
||||||
|
|
||||||
--- FSM Functions ---
|
--- FSM Functions ---
|
||||||
@@ -799,12 +799,16 @@ do
|
|||||||
-- @param #MANTIS self
|
-- @param #MANTIS self
|
||||||
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
|
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
|
||||||
-- @param #number Number Number of closest zones to be considered, defaults to 3.
|
-- @param #number Number Number of closest zones to be considered, defaults to 3.
|
||||||
|
-- @param #boolean Random If true, use a random coordinate inside the next zone to scoot to.
|
||||||
|
-- @param #string Formation Formation to use, defaults to "Cone". See mission editor dropdown for options.
|
||||||
-- @return #MANTIS self
|
-- @return #MANTIS self
|
||||||
function MANTIS:AddScootZones(ZoneSet, Number)
|
function MANTIS:AddScootZones(ZoneSet, Number, Random, Formation)
|
||||||
self:T(self.lid .. " AddScootZones")
|
self:T(self.lid .. " AddScootZones")
|
||||||
self.SkateZones = ZoneSet
|
self.SkateZones = ZoneSet
|
||||||
self.SkateNumber = Number or 3
|
self.SkateNumber = Number or 3
|
||||||
self.shootandscoot = true
|
self.shootandscoot = true
|
||||||
|
self.ScootRandom = Random
|
||||||
|
self.ScootFormation = Formation or "Cone"
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1145,7 +1149,7 @@ do
|
|||||||
--self:T(self.lid.." Relocating HQ")
|
--self:T(self.lid.." Relocating HQ")
|
||||||
local text = self.lid.." Relocating HQ"
|
local text = self.lid.." Relocating HQ"
|
||||||
--local m= MESSAGE:New(text,10,"MANTIS"):ToAll()
|
--local m= MESSAGE:New(text,10,"MANTIS"):ToAll()
|
||||||
_hqgrp:RelocateGroundRandomInRadius(20,500,true,true)
|
_hqgrp:RelocateGroundRandomInRadius(20,500,true,true,nil,true)
|
||||||
end
|
end
|
||||||
--relocate EWR
|
--relocate EWR
|
||||||
-- TODO: maybe dependent on AlarmState? Observed: SA11 SR only relocates if no objects in reach
|
-- TODO: maybe dependent on AlarmState? Observed: SA11 SR only relocates if no objects in reach
|
||||||
@@ -1159,7 +1163,7 @@ do
|
|||||||
local text = self.lid.." Relocating EWR ".._grp:GetName()
|
local text = self.lid.." Relocating EWR ".._grp:GetName()
|
||||||
local m= MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
local m= MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
||||||
if self.verbose then self:I(text) end
|
if self.verbose then self:I(text) end
|
||||||
_grp:RelocateGroundRandomInRadius(20,500,true,true)
|
_grp:RelocateGroundRandomInRadius(20,500,true,true,nil,true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1809,8 +1813,8 @@ do
|
|||||||
self.Shorad.Groupset=self.ShoradGroupSet
|
self.Shorad.Groupset=self.ShoradGroupSet
|
||||||
self.Shorad.debug = self.debug
|
self.Shorad.debug = self.debug
|
||||||
end
|
end
|
||||||
if self.shootandscoot and self.SkateZones then
|
if self.shootandscoot and self.SkateZones and self.Shorad then
|
||||||
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3)
|
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3,self.ScootRandom,self.ScootFormation)
|
||||||
end
|
end
|
||||||
self:__Status(-math.random(1,10))
|
self:__Status(-math.random(1,10))
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [MIT - Missile Trainer](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/MIT%20-%20Missile%20Trainer)
|
-- [MIT - Missile Trainer](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/MissileTrainer)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -33,16 +33,11 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Additional Material:
|
||||||
--
|
--
|
||||||
-- ### [RAT - Random Air Traffic](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/RAT%20-%20Random%20Air%20Traffic)
|
-- * **Demo Missions:** [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/RAT)
|
||||||
--
|
-- * **YouTube videos:** [Random Air Traffic](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0u4Zxywtg-mx_ov4vi68CO)
|
||||||
-- ===
|
-- * **Guides:** None
|
||||||
--
|
|
||||||
-- # YouTube Channel
|
|
||||||
--
|
|
||||||
-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg)
|
|
||||||
-- ### [MOOSE - RAT - Random Air Traffic](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0u4Zxywtg-mx_ov4vi68CO)
|
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -170,7 +165,7 @@
|
|||||||
--
|
--
|
||||||
-- * A specific departure and/or destination airport can be chosen.
|
-- * A specific departure and/or destination airport can be chosen.
|
||||||
-- * Valid coalitions can be set, e.g. only red, blue or neutral, all three "colours".
|
-- * Valid coalitions can be set, e.g. only red, blue or neutral, all three "colours".
|
||||||
-- * It is possible to start in air within a zone defined in the mission editor or within a zone above an airport of the map.
|
-- * It is possible to start in air within a zone or within a zone above an airport of the map.
|
||||||
--
|
--
|
||||||
-- ## Flight Plan
|
-- ## Flight Plan
|
||||||
--
|
--
|
||||||
@@ -1179,13 +1174,13 @@ function RAT:SetTakeoffAir()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set possible departure ports. This can be an airport or a zone defined in the mission editor.
|
--- Set possible departure ports. This can be an airport or a zone.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @param #string departurenames Name or table of names of departure airports or zones.
|
-- @param #string departurenames Name or table of names of departure airports or zones.
|
||||||
-- @return #RAT RAT self object.
|
-- @return #RAT RAT self object.
|
||||||
-- @usage RAT:SetDeparture("Sochi-Adler") will spawn RAT objects at Sochi-Adler airport.
|
-- @usage RAT:SetDeparture("Sochi-Adler") will spawn RAT objects at Sochi-Adler airport.
|
||||||
-- @usage RAT:SetDeparture({"Sochi-Adler", "Gudauta"}) will spawn RAT aircraft radomly at Sochi-Adler or Gudauta airport.
|
-- @usage RAT:SetDeparture({"Sochi-Adler", "Gudauta"}) will spawn RAT aircraft radomly at Sochi-Adler or Gudauta airport.
|
||||||
-- @usage RAT:SetDeparture({"Zone A", "Gudauta"}) will spawn RAT aircraft in air randomly within Zone A, which has to be defined in the mission editor, or within a zone around Gudauta airport. Note that this also requires RAT:takeoff("air") to be set.
|
-- @usage RAT:SetDeparture({"Zone A", "Gudauta"}) will spawn RAT aircraft in air randomly within Zone A, or within a zone around Gudauta airport. Note that this also requires RAT:takeoff("air") to be set.
|
||||||
function RAT:SetDeparture(departurenames)
|
function RAT:SetDeparture(departurenames)
|
||||||
self:F2(departurenames)
|
self:F2(departurenames)
|
||||||
|
|
||||||
@@ -2537,7 +2532,7 @@ function RAT:_SetRoute(takeoff, landing, _departure, _destination, _waypoint)
|
|||||||
end
|
end
|
||||||
elseif self:_ZoneExists(_departure) then
|
elseif self:_ZoneExists(_departure) then
|
||||||
-- If it's not an airport, check whether it's a zone.
|
-- If it's not an airport, check whether it's a zone.
|
||||||
departure=ZONE:New(_departure)
|
departure=ZONE:FindByName(_departure)
|
||||||
else
|
else
|
||||||
local text=string.format("ERROR! Specified departure airport %s does not exist for %s.", _departure, self.alias)
|
local text=string.format("ERROR! Specified departure airport %s does not exist for %s.", _departure, self.alias)
|
||||||
self:E(RAT.id..text)
|
self:E(RAT.id..text)
|
||||||
@@ -2635,7 +2630,7 @@ function RAT:_SetRoute(takeoff, landing, _departure, _destination, _waypoint)
|
|||||||
end
|
end
|
||||||
|
|
||||||
elseif self:_ZoneExists(_destination) then
|
elseif self:_ZoneExists(_destination) then
|
||||||
destination=ZONE:New(_destination)
|
destination=ZONE:FindByName(_destination)
|
||||||
else
|
else
|
||||||
local text=string.format("ERROR: Specified destination airport/zone %s does not exist for %s!", _destination, self.alias)
|
local text=string.format("ERROR: Specified destination airport/zone %s does not exist for %s!", _destination, self.alias)
|
||||||
self:E(RAT.id.."ERROR: "..text)
|
self:E(RAT.id.."ERROR: "..text)
|
||||||
@@ -3142,7 +3137,7 @@ function RAT:_PickDeparture(takeoff)
|
|||||||
end
|
end
|
||||||
elseif self:_ZoneExists(name) then
|
elseif self:_ZoneExists(name) then
|
||||||
if takeoff==RAT.wp.air then
|
if takeoff==RAT.wp.air then
|
||||||
dep=ZONE:New(name)
|
dep=ZONE:FindByName(name)
|
||||||
else
|
else
|
||||||
self:E(RAT.id..string.format("ERROR! Takeoff is not in air. Cannot use %s as departure.", name))
|
self:E(RAT.id..string.format("ERROR! Takeoff is not in air. Cannot use %s as departure.", name))
|
||||||
end
|
end
|
||||||
@@ -3254,7 +3249,7 @@ function RAT:_PickDestination(departure, q, minrange, maxrange, random, landing)
|
|||||||
end
|
end
|
||||||
elseif self:_ZoneExists(name) then
|
elseif self:_ZoneExists(name) then
|
||||||
if landing==RAT.wp.air then
|
if landing==RAT.wp.air then
|
||||||
dest=ZONE:New(name)
|
dest=ZONE:FindByName(name)
|
||||||
else
|
else
|
||||||
self:E(RAT.id..string.format("ERROR! Landing is not in air. Cannot use zone %s as destination!", name))
|
self:E(RAT.id..string.format("ERROR! Landing is not in air. Cannot use zone %s as destination!", name))
|
||||||
end
|
end
|
||||||
@@ -4930,12 +4925,12 @@ function RAT:_AirportExists(name)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test if a trigger zone defined in the mission editor exists.
|
--- Test if a zone exists.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @param #string name
|
-- @param #string name
|
||||||
-- @return #boolean True if zone exsits, false otherwise.
|
-- @return #boolean True if zone exsits, false otherwise.
|
||||||
function RAT:_ZoneExists(name)
|
function RAT:_ZoneExists(name)
|
||||||
local z=trigger.misc.getZone(name)
|
local z=ZONE:FindByName(name) --trigger.misc.getZone(name) as suggested by @Viking on MOOSE discord #rat
|
||||||
if z then
|
if z then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1207,25 +1207,29 @@ end
|
|||||||
-- @return #RANGE self
|
-- @return #RANGE self
|
||||||
function RANGE:SetSRS(PathToSRS, Port, Coalition, Frequency, Modulation, Volume, PathToGoogleKey)
|
function RANGE:SetSRS(PathToSRS, Port, Coalition, Frequency, Modulation, Volume, PathToGoogleKey)
|
||||||
|
|
||||||
if PathToSRS then
|
if PathToSRS or MSRS.path then
|
||||||
|
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
|
|
||||||
self.controlmsrs=MSRS:New(PathToSRS, Frequency or 256, Modulation or radio.modulation.AM, Volume or 1.0)
|
self.controlmsrs=MSRS:New(PathToSRS or MSRS.path, Frequency or 256, Modulation or radio.modulation.AM)
|
||||||
self.controlmsrs:SetPort(Port)
|
self.controlmsrs:SetPort(Port or MSRS.port)
|
||||||
self.controlmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
self.controlmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
||||||
self.controlmsrs:SetLabel("RANGEC")
|
self.controlmsrs:SetLabel("RANGEC")
|
||||||
|
self.controlmsrs:SetVolume(Volume or 1.0)
|
||||||
self.controlsrsQ = MSRSQUEUE:New("CONTROL")
|
self.controlsrsQ = MSRSQUEUE:New("CONTROL")
|
||||||
|
|
||||||
self.instructmsrs=MSRS:New(PathToSRS, Frequency or 305, Modulation or radio.modulation.AM, Volume or 1.0)
|
self.instructmsrs=MSRS:New(PathToSRS or MSRS.path, Frequency or 305, Modulation or radio.modulation.AM)
|
||||||
self.instructmsrs:SetPort(Port)
|
self.instructmsrs:SetPort(Port or MSRS.port)
|
||||||
self.instructmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
self.instructmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
||||||
self.instructmsrs:SetLabel("RANGEI")
|
self.instructmsrs:SetLabel("RANGEI")
|
||||||
|
self.instructmsrs:SetVolume(Volume or 1.0)
|
||||||
self.instructsrsQ = MSRSQUEUE:New("INSTRUCT")
|
self.instructsrsQ = MSRSQUEUE:New("INSTRUCT")
|
||||||
|
|
||||||
if PathToGoogleKey then
|
if PathToGoogleKey then
|
||||||
self.controlmsrs:SetGoogle(PathToGoogleKey)
|
self.controlmsrs:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
|
||||||
self.instructmsrs:SetGoogle(PathToGoogleKey)
|
self.controlmsrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
self.instructmsrs:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
|
||||||
|
self.instructmsrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -1234,7 +1238,7 @@ function RANGE:SetSRS(PathToSRS, Port, Coalition, Frequency, Modulation, Volume,
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (SRS) Set range control frequency and voice.
|
--- (SRS) Set range control frequency and voice. Use `RANGE:SetSRS()` once first before using this function.
|
||||||
-- @param #RANGE self
|
-- @param #RANGE self
|
||||||
-- @param #number frequency Frequency in MHz. Default 256 MHz.
|
-- @param #number frequency Frequency in MHz. Default 256 MHz.
|
||||||
-- @param #number modulation Modulation, defaults to radio.modulation.AM.
|
-- @param #number modulation Modulation, defaults to radio.modulation.AM.
|
||||||
@@ -1244,6 +1248,10 @@ end
|
|||||||
-- @param #string relayunitname Name of the unit used for transmission location.
|
-- @param #string relayunitname Name of the unit used for transmission location.
|
||||||
-- @return #RANGE self
|
-- @return #RANGE self
|
||||||
function RANGE:SetSRSRangeControl( frequency, modulation, voice, culture, gender, relayunitname )
|
function RANGE:SetSRSRangeControl( frequency, modulation, voice, culture, gender, relayunitname )
|
||||||
|
if not self.instructmsrs then
|
||||||
|
self:E(self.lid.."Use myrange:SetSRS() once first before using myrange:SetSRSRangeControl!")
|
||||||
|
return self
|
||||||
|
end
|
||||||
self.rangecontrolfreq = frequency or 256
|
self.rangecontrolfreq = frequency or 256
|
||||||
self.controlmsrs:SetFrequencies(self.rangecontrolfreq)
|
self.controlmsrs:SetFrequencies(self.rangecontrolfreq)
|
||||||
self.controlmsrs:SetModulations(modulation or radio.modulation.AM)
|
self.controlmsrs:SetModulations(modulation or radio.modulation.AM)
|
||||||
@@ -1259,7 +1267,7 @@ function RANGE:SetSRSRangeControl( frequency, modulation, voice, culture, gender
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (SRS) Set range instructor frequency and voice.
|
--- (SRS) Set range instructor frequency and voice. Use `RANGE:SetSRS()` once first before using this function.
|
||||||
-- @param #RANGE self
|
-- @param #RANGE self
|
||||||
-- @param #number frequency Frequency in MHz. Default 305 MHz.
|
-- @param #number frequency Frequency in MHz. Default 305 MHz.
|
||||||
-- @param #number modulation Modulation, defaults to radio.modulation.AM.
|
-- @param #number modulation Modulation, defaults to radio.modulation.AM.
|
||||||
@@ -1269,6 +1277,10 @@ end
|
|||||||
-- @param #string relayunitname Name of the unit used for transmission location.
|
-- @param #string relayunitname Name of the unit used for transmission location.
|
||||||
-- @return #RANGE self
|
-- @return #RANGE self
|
||||||
function RANGE:SetSRSRangeInstructor( frequency, modulation, voice, culture, gender, relayunitname )
|
function RANGE:SetSRSRangeInstructor( frequency, modulation, voice, culture, gender, relayunitname )
|
||||||
|
if not self.instructmsrs then
|
||||||
|
self:E(self.lid.."Use myrange:SetSRS() once first before using myrange:SetSRSRangeInstructor!")
|
||||||
|
return self
|
||||||
|
end
|
||||||
self.instructorfreq = frequency or 305
|
self.instructorfreq = frequency or 305
|
||||||
self.instructmsrs:SetFrequencies(self.instructorfreq)
|
self.instructmsrs:SetFrequencies(self.instructorfreq)
|
||||||
self.instructmsrs:SetModulations(modulation or radio.modulation.AM)
|
self.instructmsrs:SetModulations(modulation or radio.modulation.AM)
|
||||||
@@ -1729,7 +1741,9 @@ end
|
|||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function RANGE:OnEventBirth( EventData )
|
function RANGE:OnEventBirth( EventData )
|
||||||
self:F( { eventbirth = EventData } )
|
self:F( { eventbirth = EventData } )
|
||||||
|
|
||||||
|
if not EventData.IniPlayerName then return end
|
||||||
|
|
||||||
local _unitName = EventData.IniUnitName
|
local _unitName = EventData.IniUnitName
|
||||||
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
||||||
|
|
||||||
@@ -2179,7 +2193,7 @@ function RANGE:onafterExitRange( From, Event, To, player )
|
|||||||
|
|
||||||
local text = "You left the bombing range zone. "
|
local text = "You left the bombing range zone. "
|
||||||
|
|
||||||
local r=math.random(2)
|
local r=math.random(5)
|
||||||
|
|
||||||
if r==1 then
|
if r==1 then
|
||||||
text=text.."Have a nice day!"
|
text=text.."Have a nice day!"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [SCO - Scoring](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SCO%20-%20Scoring)
|
-- [SCO - Scoring](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/Scoring)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -276,9 +276,15 @@ function SCORING:New( GameName )
|
|||||||
self:SetMessagesZone( true )
|
self:SetMessagesZone( true )
|
||||||
|
|
||||||
-- Scales
|
-- Scales
|
||||||
|
|
||||||
self:SetScaleDestroyScore( 10 )
|
self:SetScaleDestroyScore( 10 )
|
||||||
self:SetScaleDestroyPenalty( 30 )
|
self:SetScaleDestroyPenalty( 30 )
|
||||||
|
|
||||||
|
-- Hitting a target multiple times before destoying it should not result in a higger score
|
||||||
|
-- Multiple hits is typically a results of bombs/missles missing their target but still inflict some spash damage
|
||||||
|
-- Making this configurable to anyone can enable this anyway if they want
|
||||||
|
self:SetScoreIncrementOnHit(0)
|
||||||
|
|
||||||
-- Default fratricide penalty level (maximum penalty that can be assigned to a player before he gets kicked).
|
-- Default fratricide penalty level (maximum penalty that can be assigned to a player before he gets kicked).
|
||||||
self:SetFratricide( self.ScaleDestroyPenalty * 3 )
|
self:SetFratricide( self.ScaleDestroyPenalty * 3 )
|
||||||
self.penaltyonfratricide = true
|
self.penaltyonfratricide = true
|
||||||
@@ -467,6 +473,16 @@ function SCORING:SetMessagesHit( OnOff )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Configure to increment score after a target has been hit.
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @param #number score amount of point to inclement score on each hit
|
||||||
|
-- @return #SCORING
|
||||||
|
function SCORING:SetScoreIncrementOnHit( score )
|
||||||
|
|
||||||
|
self.ScoreIncrementOnHit = score
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- If to send messages after a target has been hit.
|
--- If to send messages after a target has been hit.
|
||||||
-- @param #SCORING self
|
-- @param #SCORING self
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
@@ -885,6 +901,7 @@ function SCORING:OnEventBirth( Event )
|
|||||||
Event.IniUnit.BirthTime = timer.getTime()
|
Event.IniUnit.BirthTime = timer.getTime()
|
||||||
if PlayerName then
|
if PlayerName then
|
||||||
self:_AddPlayerFromUnit( Event.IniUnit )
|
self:_AddPlayerFromUnit( Event.IniUnit )
|
||||||
|
self.Players[PlayerName].PlayerKills = 0
|
||||||
self:SetScoringMenu( Event.IniGroup )
|
self:SetScoringMenu( Event.IniGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1015,7 +1032,7 @@ function SCORING:_EventOnHit( Event )
|
|||||||
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
||||||
-- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth
|
-- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth
|
||||||
if PlayerHit.UNIT.ThreatType == nil then
|
if PlayerHit.UNIT.ThreatType == nil then
|
||||||
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
||||||
-- if this fails for some reason, set a good default value
|
-- if this fails for some reason, set a good default value
|
||||||
if PlayerHit.ThreatType == nil then
|
if PlayerHit.ThreatType == nil then
|
||||||
PlayerHit.ThreatLevel = 1
|
PlayerHit.ThreatLevel = 1
|
||||||
@@ -1025,7 +1042,7 @@ function SCORING:_EventOnHit( Event )
|
|||||||
PlayerHit.ThreatLevel = PlayerHit.UNIT.ThreatLevel
|
PlayerHit.ThreatLevel = PlayerHit.UNIT.ThreatLevel
|
||||||
PlayerHit.ThreatType = PlayerHit.UNIT.ThreatType
|
PlayerHit.ThreatType = PlayerHit.UNIT.ThreatType
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Only grant hit scores if there was more than one second between the last hit.
|
-- Only grant hit scores if there was more than one second between the last hit.
|
||||||
if timer.getTime() - PlayerHit.TimeStamp > 1 then
|
if timer.getTime() - PlayerHit.TimeStamp > 1 then
|
||||||
PlayerHit.TimeStamp = timer.getTime()
|
PlayerHit.TimeStamp = timer.getTime()
|
||||||
@@ -1060,10 +1077,8 @@ function SCORING:_EventOnHit( Event )
|
|||||||
end
|
end
|
||||||
self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||||
else
|
else
|
||||||
-- Hitting a target multiple times before destoying it should not result in a higger score
|
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||||
-- Multiple hits is typically a results of bombs/missles missing their target but still inflict some spash damage
|
PlayerHit.Score = PlayerHit.Score + self.ScoreIncrementOnHit
|
||||||
-- Player.Score = Player.Score + 1
|
|
||||||
-- PlayerHit.Score = PlayerHit.Score + 1
|
|
||||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
||||||
if TargetPlayerName ~= nil then -- It is a player hitting another player ...
|
if TargetPlayerName ~= nil then -- It is a player hitting another player ...
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " ..
|
||||||
@@ -1128,7 +1143,7 @@ function SCORING:_EventOnHit( Event )
|
|||||||
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
||||||
-- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth
|
-- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth
|
||||||
if PlayerHit.UNIT.ThreatType == nil then
|
if PlayerHit.UNIT.ThreatType == nil then
|
||||||
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
||||||
-- if this fails for some reason, set a good default value
|
-- if this fails for some reason, set a good default value
|
||||||
if PlayerHit.ThreatType == nil then
|
if PlayerHit.ThreatType == nil then
|
||||||
PlayerHit.ThreatLevel = 1
|
PlayerHit.ThreatLevel = 1
|
||||||
@@ -1163,10 +1178,8 @@ function SCORING:_EventOnHit( Event )
|
|||||||
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||||
self:ScoreCSV( Event.WeaponPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
self:ScoreCSV( Event.WeaponPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||||
else
|
else
|
||||||
-- Hitting a target multiple times before destoying it should not result in a higger score
|
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||||
-- Multiple hits is typically a results of bombs/missles missing their target but still inflict some spash damage
|
PlayerHit.Score = PlayerHit.Score + self.ScoreIncrementOnHit
|
||||||
-- Player.Score = Player.Score + 1
|
|
||||||
-- PlayerHit.Score = PlayerHit.Score + 1
|
|
||||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||||
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||||
@@ -1274,13 +1287,18 @@ function SCORING:_EventOnDeadOrCrash( Event )
|
|||||||
TargetDestroy.Penalty = TargetDestroy.Penalty + ThreatPenalty
|
TargetDestroy.Penalty = TargetDestroy.Penalty + ThreatPenalty
|
||||||
TargetDestroy.PenaltyDestroy = TargetDestroy.PenaltyDestroy + 1
|
TargetDestroy.PenaltyDestroy = TargetDestroy.PenaltyDestroy + 1
|
||||||
|
|
||||||
|
|
||||||
|
self:OnKillPvP(Player, TargetPlayerName, true, TargetThreatLevel, Player.ThreatLevel, ThreatPenalty)
|
||||||
|
|
||||||
if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player
|
if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player
|
||||||
|
self:OnKillPvP(Player, TargetPlayerName, true)
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
||||||
"Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty,
|
"Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Information )
|
MESSAGE.Type.Information )
|
||||||
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
||||||
else
|
else
|
||||||
|
self:OnKillPvE(Player, TargetUnitName, true, TargetThreatLevel, Player.ThreatLevel, ThreatPenalty)
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly target " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly target " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
||||||
"Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty,
|
"Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Information )
|
MESSAGE.Type.Information )
|
||||||
@@ -1303,12 +1321,19 @@ function SCORING:_EventOnDeadOrCrash( Event )
|
|||||||
TargetDestroy.Score = TargetDestroy.Score + ThreatScore
|
TargetDestroy.Score = TargetDestroy.Score + ThreatScore
|
||||||
TargetDestroy.ScoreDestroy = TargetDestroy.ScoreDestroy + 1
|
TargetDestroy.ScoreDestroy = TargetDestroy.ScoreDestroy + 1
|
||||||
if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player
|
if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player
|
||||||
|
if Player.PlayerKills ~= nil then
|
||||||
|
Player.PlayerKills = Player.PlayerKills + 1
|
||||||
|
else
|
||||||
|
Player.PlayerKills = 1
|
||||||
|
end
|
||||||
|
self:OnKillPvP(Player, TargetPlayerName, false, TargetThreatLevel, Player.ThreatLevel, ThreatScore)
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
||||||
"Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty,
|
"Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Information )
|
MESSAGE.Type.Information )
|
||||||
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
||||||
else
|
else
|
||||||
|
self:OnKillPvE(Player, TargetUnitName, false, TargetThreatLevel, Player.ThreatLevel, ThreatScore)
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
||||||
"Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty,
|
"Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Information )
|
MESSAGE.Type.Information )
|
||||||
@@ -1907,3 +1932,26 @@ function SCORING:SwitchAutoSave(OnOff)
|
|||||||
self.AutoSave = OnOff
|
self.AutoSave = OnOff
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles the event when one player kill another player
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @param #PLAYER Player the ataching player
|
||||||
|
-- @param #string TargetPlayerName the name of the killed player
|
||||||
|
-- @param #bool IsTeamKill true if this kill was a team kill
|
||||||
|
-- @param #number TargetThreatLevel Thread level of the target
|
||||||
|
-- @param #number PlayerThreatLevelThread level of the player
|
||||||
|
-- @param #number Score The score based on both threat levels
|
||||||
|
function SCORING:OnKillPvP(Player, TargetPlayerName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score)
|
||||||
|
|
||||||
|
end
|
||||||
|
--- Handles the event when one player kill another player
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @param #PLAYER Player the ataching player
|
||||||
|
-- @param #string TargetUnitName the name of the killed unit
|
||||||
|
-- @param #bool IsTeamKill true if this kill was a team kill
|
||||||
|
-- @param #number TargetThreatLevel Thread level of the target
|
||||||
|
-- @param #number PlayerThreatLevelThread level of the player
|
||||||
|
-- @param #number Score The score based on both threat levels
|
||||||
|
function SCORING:OnKillPvE(Player, TargetUnitName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score)
|
||||||
|
|
||||||
|
end
|
||||||
@@ -13,13 +13,13 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [SEV - SEAD Evasion](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SEV%20-%20SEAD%20Evasion)
|
-- [SEV - SEAD Evasion](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/Sead)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: **FlightControl**, **applevangelist**
|
-- ### Authors: **applevangelist**, **FlightControl**
|
||||||
--
|
--
|
||||||
-- Last Update: Oct 2023
|
-- Last Update: Dec 2023
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -144,7 +144,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
|
|||||||
self:AddTransition("*", "ManageEvasion", "*")
|
self:AddTransition("*", "ManageEvasion", "*")
|
||||||
self:AddTransition("*", "CalculateHitZone", "*")
|
self:AddTransition("*", "CalculateHitZone", "*")
|
||||||
|
|
||||||
self:I("*** SEAD - Started Version 0.4.5")
|
self:I("*** SEAD - Started Version 0.4.6")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -401,7 +401,7 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
|
|||||||
grp:EnableEmission(false)
|
grp:EnableEmission(false)
|
||||||
end
|
end
|
||||||
grp:OptionAlarmStateGreen() -- needed else we cannot move around
|
grp:OptionAlarmStateGreen() -- needed else we cannot move around
|
||||||
grp:RelocateGroundRandomInRadius(20,300,false,false,"Diamond")
|
grp:RelocateGroundRandomInRadius(20,300,false,false,"Diamond",true)
|
||||||
if self.UseCallBack then
|
if self.UseCallBack then
|
||||||
local object = self.CallBack
|
local object = self.CallBack
|
||||||
object:SeadSuppressionStart(grp,name,attacker)
|
object:SeadSuppressionStart(grp,name,attacker)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- ### [SHORAD - Short Range Air Defense](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SRD%20-%20SHORAD%20Defense)
|
-- ### [SHORAD - Short Range Air Defense](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/Shorad)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -41,10 +41,14 @@
|
|||||||
-- @field #boolean DefendMavs Default true, intercept incoming AG-Missiles
|
-- @field #boolean DefendMavs Default true, intercept incoming AG-Missiles
|
||||||
-- @field #number DefenseLowProb Default 70, minimum detection limit
|
-- @field #number DefenseLowProb Default 70, minimum detection limit
|
||||||
-- @field #number DefenseHighProb Default 90, maximum detection limit
|
-- @field #number DefenseHighProb Default 90, maximum detection limit
|
||||||
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green.
|
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green
|
||||||
-- @field #boolean shootandscoot
|
-- @field #boolean shootandscoot If true, shoot and scoot between zones
|
||||||
-- @field #number SkateNumber
|
-- @field #number SkateNumber Number of zones to consider
|
||||||
-- @field Core.Set#SET_ZONE SkateZones
|
-- @field Core.Set#SET_ZONE SkateZones Zones in this set are considered
|
||||||
|
-- @field #number minscootdist Min distance of the next zone
|
||||||
|
-- @field #number maxscootdist Max distance of the next zone
|
||||||
|
-- @field #boolean scootrandomcoord If true, use a random coordinate in the zone and not the center
|
||||||
|
-- @field #string scootformation Formation to take for scooting, e.g. "Vee" or "Cone"
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -77,14 +81,15 @@
|
|||||||
--
|
--
|
||||||
-- `myshorad = SHORAD:New("RedShorad", "Red SHORAD", SamSet, 25000, 600, "red")`
|
-- `myshorad = SHORAD:New("RedShorad", "Red SHORAD", SamSet, 25000, 600, "red")`
|
||||||
--
|
--
|
||||||
-- ## Customize options
|
-- ## Customization options
|
||||||
--
|
--
|
||||||
-- * SHORAD:SwitchDebug(debug)
|
-- * myshorad:SwitchDebug(debug)
|
||||||
-- * SHORAD:SwitchHARMDefense(onoff)
|
-- * myshorad:SwitchHARMDefense(onoff)
|
||||||
-- * SHORAD:SwitchAGMDefense(onoff)
|
-- * myshorad:SwitchAGMDefense(onoff)
|
||||||
-- * SHORAD:SetDefenseLimits(low,high)
|
-- * myshorad:SetDefenseLimits(low,high)
|
||||||
-- * SHORAD:SetActiveTimer(seconds)
|
-- * myshorad:SetActiveTimer(seconds)
|
||||||
-- * SHORAD:SetDefenseRadius(meters)
|
-- * myshorad:SetDefenseRadius(meters)
|
||||||
|
-- * myshorad:AddScootZones(ZoneSet,Number,Random,Formation)
|
||||||
--
|
--
|
||||||
-- @field #SHORAD
|
-- @field #SHORAD
|
||||||
SHORAD = {
|
SHORAD = {
|
||||||
@@ -107,6 +112,9 @@ SHORAD = {
|
|||||||
shootandscoot = false,
|
shootandscoot = false,
|
||||||
SkateNumber = 3,
|
SkateNumber = 3,
|
||||||
SkateZones = nil,
|
SkateZones = nil,
|
||||||
|
minscootdist = 100,
|
||||||
|
minscootdist = 3000,
|
||||||
|
scootrandomcoord = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
@@ -174,7 +182,7 @@ do
|
|||||||
self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin
|
self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin
|
||||||
self.UseEmOnOff = true -- Decide if we are using Emission on/off (default) or AlarmState red/green
|
self.UseEmOnOff = true -- Decide if we are using Emission on/off (default) or AlarmState red/green
|
||||||
if UseEmOnOff == false then self.UseEmOnOff = UseEmOnOff end
|
if UseEmOnOff == false then self.UseEmOnOff = UseEmOnOff end
|
||||||
self:I("*** SHORAD - Started Version 0.3.2")
|
self:I("*** SHORAD - Started Version 0.3.4")
|
||||||
-- Set the string id for output to DCS.log file.
|
-- Set the string id for output to DCS.log file.
|
||||||
self.lid=string.format("SHORAD %s | ", self.name)
|
self.lid=string.format("SHORAD %s | ", self.name)
|
||||||
self:_InitState()
|
self:_InitState()
|
||||||
@@ -219,12 +227,16 @@ do
|
|||||||
-- @param #SHORAD self
|
-- @param #SHORAD self
|
||||||
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
|
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
|
||||||
-- @param #number Number Number of closest zones to be considered, defaults to 3.
|
-- @param #number Number Number of closest zones to be considered, defaults to 3.
|
||||||
|
-- @param #boolean Random If true, use a random coordinate inside the next zone to scoot to.
|
||||||
|
-- @param #string Formation Formation to use, defaults to "Cone". See mission editor dropdown for options.
|
||||||
-- @return #SHORAD self
|
-- @return #SHORAD self
|
||||||
function SHORAD:AddScootZones(ZoneSet, Number)
|
function SHORAD:AddScootZones(ZoneSet, Number, Random, Formation)
|
||||||
self:T(self.lid .. " AddScootZones")
|
self:T(self.lid .. " AddScootZones")
|
||||||
self.SkateZones = ZoneSet
|
self.SkateZones = ZoneSet
|
||||||
self.SkateNumber = Number or 3
|
self.SkateNumber = Number or 3
|
||||||
self.shootandscoot = true
|
self.shootandscoot = true
|
||||||
|
self.scootrandomcoord = Random
|
||||||
|
self.scootformation = Formation or "Cone"
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -613,8 +625,8 @@ do
|
|||||||
function SHORAD:onafterShootAndScoot(From,Event,To,Shorad)
|
function SHORAD:onafterShootAndScoot(From,Event,To,Shorad)
|
||||||
self:T( { From,Event,To } )
|
self:T( { From,Event,To } )
|
||||||
local possibleZones = {}
|
local possibleZones = {}
|
||||||
local mindist = 100
|
local mindist = self.minscootdist or 100
|
||||||
local maxdist = 3000
|
local maxdist = self.maxscootdist or 3000
|
||||||
if Shorad and Shorad:IsAlive() then
|
if Shorad and Shorad:IsAlive() then
|
||||||
local NowCoord = Shorad:GetCoordinate()
|
local NowCoord = Shorad:GetCoordinate()
|
||||||
for _,_zone in pairs(self.SkateZones.Set) do
|
for _,_zone in pairs(self.SkateZones.Set) do
|
||||||
@@ -630,7 +642,11 @@ do
|
|||||||
if rand == 0 then rand = 1 end
|
if rand == 0 then rand = 1 end
|
||||||
self:T(self.lid .. " ShootAndScoot to zone "..rand)
|
self:T(self.lid .. " ShootAndScoot to zone "..rand)
|
||||||
local ToCoordinate = possibleZones[rand]:GetCoordinate()
|
local ToCoordinate = possibleZones[rand]:GetCoordinate()
|
||||||
Shorad:RouteGroundTo(ToCoordinate,20,"Cone",1)
|
if self.scootrandomcoord then
|
||||||
|
ToCoordinate = possibleZones[rand]:GetRandomCoordinate(nil,nil,{land.SurfaceType.LAND,land.SurfaceType.ROAD})
|
||||||
|
end
|
||||||
|
local formation = self.scootformation or "Cone"
|
||||||
|
Shorad:RouteGroundTo(ToCoordinate,20,formation,1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
@@ -731,4 +747,4 @@ do
|
|||||||
end
|
end
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
-- SHORAD end
|
-- SHORAD end
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|||||||
1311
Moose Development/Moose/Functional/Stratego.lua
Normal file
1311
Moose Development/Moose/Functional/Stratego.lua
Normal file
File diff suppressed because it is too large
Load Diff
590
Moose Development/Moose/Functional/Tiresias.lua
Normal file
590
Moose Development/Moose/Functional/Tiresias.lua
Normal file
@@ -0,0 +1,590 @@
|
|||||||
|
--- **Functional** - TIRESIAS - manages AI behaviour.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- The @{#TIRESIAS} class is working in the back to keep your large-scale ground units in check.
|
||||||
|
--
|
||||||
|
-- ## Features:
|
||||||
|
--
|
||||||
|
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
|
||||||
|
-- * Does not affect ships to keep the Navy guys happy.
|
||||||
|
-- * Does not affect OpsGroup type groups.
|
||||||
|
-- * Distinguishes between SAM groups, AAA groups and other ground groups.
|
||||||
|
-- * Exceptions can be defined to keep certain actions going.
|
||||||
|
-- * Works coalition-independent in the back
|
||||||
|
-- * Easy setup.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Missions:
|
||||||
|
--
|
||||||
|
-- ### [TIRESIAS](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master)
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author : **applevangelist **
|
||||||
|
--
|
||||||
|
-- @module Functional.Tiresias
|
||||||
|
-- @image Functional.Tiresias.jpg
|
||||||
|
--
|
||||||
|
-- Last Update: Dec 2023
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
--- **TIRESIAS** class, extends Core.Base#BASE
|
||||||
|
-- @type TIRESIAS
|
||||||
|
-- @field #string ClassName
|
||||||
|
-- @field #booelan debug
|
||||||
|
-- @field #string version
|
||||||
|
-- @field #number Interval
|
||||||
|
-- @field Core.Set#SET_GROUP GroundSet
|
||||||
|
-- @field #number Coalition
|
||||||
|
-- @field Core.Set#SET_GROUP VehicleSet
|
||||||
|
-- @field Core.Set#SET_GROUP AAASet
|
||||||
|
-- @field Core.Set#SET_GROUP SAMSet
|
||||||
|
-- @field Core.Set#SET_GROUP ExceptionSet
|
||||||
|
-- @field Core.Set#SET_OPSGROUP OpsGroupSet
|
||||||
|
-- @field #number AAARange
|
||||||
|
-- @field #number HeloSwitchRange
|
||||||
|
-- @field #number PlaneSwitchRange
|
||||||
|
-- @field Core.Set#SET_GROUP FlightSet
|
||||||
|
-- @field #boolean SwitchAAA
|
||||||
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @type TIRESIAS.Data
|
||||||
|
-- @field #string type
|
||||||
|
-- @field #number range
|
||||||
|
-- @field #boolean invisible
|
||||||
|
-- @field #boolean AIOff
|
||||||
|
-- @field #boolean exception
|
||||||
|
|
||||||
|
|
||||||
|
--- *Tiresias, Greek demi-god and shapeshifter, blinded by the Gods, works as oracle for you.* (Wiki)
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## TIRESIAS Concept
|
||||||
|
--
|
||||||
|
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
|
||||||
|
-- * Does not affect ships to keep the Navy guys happy.
|
||||||
|
-- * Does not affect OpsGroup type groups.
|
||||||
|
-- * Distinguishes between SAM groups, AAA groups and other ground groups.
|
||||||
|
-- * Exceptions can be defined in SET_GROUP objects to keep certain actions going.
|
||||||
|
-- * Works coalition-independent in the back
|
||||||
|
-- * Easy setup.
|
||||||
|
--
|
||||||
|
-- ## Setup
|
||||||
|
--
|
||||||
|
-- Setup is a one-liner:
|
||||||
|
--
|
||||||
|
-- local blinder = TIRESIAS:New()
|
||||||
|
--
|
||||||
|
-- Optionally you can set up exceptions, e.g. for convoys driving around
|
||||||
|
--
|
||||||
|
-- local exceptionset = SET_GROUP:New():FilterCoalitions("red"):FilterPrefixes("Convoy"):FilterStart()
|
||||||
|
-- local blinder = TIRESIAS:New()
|
||||||
|
-- blinder:AddExceptionSet(exceptionset)
|
||||||
|
--
|
||||||
|
-- Options
|
||||||
|
--
|
||||||
|
-- -- Setup different radius for activation around helo and airplane groups (applies to AI and humans)
|
||||||
|
-- blinder:SetActivationRanges(10,25) -- defaults are 10, and 25
|
||||||
|
--
|
||||||
|
-- -- Setup engagement ranges for AAA (non-advanced SAM units like Flaks etc) and if you want them to be AIOff
|
||||||
|
-- blinder:SetAAARanges(60,true) -- defaults are 60, and true
|
||||||
|
--
|
||||||
|
-- @field #TIRESIAS
|
||||||
|
TIRESIAS = {
|
||||||
|
ClassName = "TIRESIAS",
|
||||||
|
debug = false,
|
||||||
|
version = "0.0.4",
|
||||||
|
Interval = 20,
|
||||||
|
GroundSet = nil,
|
||||||
|
VehicleSet = nil,
|
||||||
|
AAASet = nil,
|
||||||
|
SAMSet = nil,
|
||||||
|
ExceptionSet = nil,
|
||||||
|
AAARange = 60, -- 60%
|
||||||
|
HeloSwitchRange = 10, -- NM
|
||||||
|
PlaneSwitchRange = 25, -- NM
|
||||||
|
SwitchAAA = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- [USER] Create a new Tiresias object and start it up.
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:New()
|
||||||
|
|
||||||
|
-- Inherit everything from FSM class.
|
||||||
|
local self = BASE:Inherit(self, FSM:New()) -- #TIRESIAS
|
||||||
|
|
||||||
|
--- FSM Functions ---
|
||||||
|
|
||||||
|
-- Start State.
|
||||||
|
self:SetStartState("Stopped")
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||||
|
self:AddTransition("*", "Status", "*") -- TIRESIAS status update.
|
||||||
|
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||||
|
|
||||||
|
self.ExceptionSet = SET_GROUP:New():Clear(false)
|
||||||
|
|
||||||
|
self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
|
||||||
|
|
||||||
|
self.lid = string.format("TIRESIAS %s | ",self.version)
|
||||||
|
|
||||||
|
self:I(self.lid.."Managing ground groups!")
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop". Stops TIRESIAS and all its event handlers.
|
||||||
|
-- @function [parent=#TIRESIAS] Stop
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop" after a delay. Stops TIRESIAS and all its event handlers.
|
||||||
|
-- @function [parent=#TIRESIAS] __Stop
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Start". Starts TIRESIAS and all its event handlers. Note - `:New()` already starts the instance.
|
||||||
|
-- @function [parent=#TIRESIAS] Start
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Start" after a delay. Starts TIRESIAS and all its event handlers. Note - `:New()` already starts the instance.
|
||||||
|
-- @function [parent=#TIRESIAS] __Start
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
self:__Start(1)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Helper Functions
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---[USER] Set activation radius for Helos and Planes in Nautical Miles.
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #number HeloMiles Radius around a Helicopter in which AI ground units will be activated. Defaults to 10NM.
|
||||||
|
-- @param #number PlaneMiles Radius around an Airplane in which AI ground units will be activated. Defaults to 25NM.
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:SetActivationRanges(HeloMiles,PlaneMiles)
|
||||||
|
self.HeloSwitchRange = HeloMiles or 10
|
||||||
|
self.PlaneSwitchRange = PlaneMiles or 25
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---[USER] Set AAA Ranges - AAA equals non-SAM systems which qualify as AAA in DCS world.
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #number FiringRange The engagement range that AAA units will be set to. Can be 0 to 100 (percent). Defaults to 60.
|
||||||
|
-- @param #boolean SwitchAAA Decide if these system will have their AI switched off, too. Defaults to true.
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:SetAAARanges(FiringRange,SwitchAAA)
|
||||||
|
self.AAARange = FiringRange or 60
|
||||||
|
self.SwitchAAA = (SwitchAAA == false) and false or true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [USER] Add a SET_GROUP of GROUP objects as exceptions. Can be done multiple times.
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param Core.Set#SET_GROUP Set to add to the exception list.
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:AddExceptionSet(Set)
|
||||||
|
self:T(self.lid.."AddExceptionSet")
|
||||||
|
local exceptions = self.ExceptionSet
|
||||||
|
Set:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if not grp.Tiresias then
|
||||||
|
grp.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "Exception",
|
||||||
|
exception = true,
|
||||||
|
}
|
||||||
|
exceptions:AddGroup(grp,true)
|
||||||
|
end
|
||||||
|
BASE:I("TIRESIAS: Added exception group: "..grp:GetName())
|
||||||
|
end
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Filter Function
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @return #boolean isin
|
||||||
|
function TIRESIAS._FilterNotAAA(Group)
|
||||||
|
local grp = Group -- Wrapper.Group#GROUP
|
||||||
|
local isaaa = grp:IsAAA()
|
||||||
|
if isaaa == true and grp:IsGround() and not grp:IsShip() then
|
||||||
|
return false -- remove from SET
|
||||||
|
else
|
||||||
|
return true -- keep in SET
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Filter Function
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @return #boolean isin
|
||||||
|
function TIRESIAS._FilterNotSAM(Group)
|
||||||
|
local grp = Group -- Wrapper.Group#GROUP
|
||||||
|
local issam = grp:IsSAM()
|
||||||
|
if issam == true and grp:IsGround() and not grp:IsShip() then
|
||||||
|
return false -- remove from SET
|
||||||
|
else
|
||||||
|
return true -- keep in SET
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Filter Function
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @return #boolean isin
|
||||||
|
function TIRESIAS._FilterAAA(Group)
|
||||||
|
local grp = Group -- Wrapper.Group#GROUP
|
||||||
|
local isaaa = grp:IsAAA()
|
||||||
|
if isaaa == true and grp:IsGround() and not grp:IsShip() then
|
||||||
|
return true -- remove from SET
|
||||||
|
else
|
||||||
|
return false -- keep in SET
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Filter Function
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @return #boolean isin
|
||||||
|
function TIRESIAS._FilterSAM(Group)
|
||||||
|
local grp = Group -- Wrapper.Group#GROUP
|
||||||
|
local issam = grp:IsSAM()
|
||||||
|
if issam == true and grp:IsGround() and not grp:IsShip() then
|
||||||
|
return true -- remove from SET
|
||||||
|
else
|
||||||
|
return false -- keep in SET
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Init Groups
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:_InitGroups()
|
||||||
|
self:T(self.lid.."_InitGroups")
|
||||||
|
-- Set all groups invisible/motionless
|
||||||
|
local EngageRange = self.AAARange
|
||||||
|
local SwitchAAA = self.SwitchAAA
|
||||||
|
--- AAA
|
||||||
|
self.AAASet:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if not grp.Tiresias then
|
||||||
|
grp:OptionEngageRange(EngageRange)
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
if SwitchAAA then
|
||||||
|
grp:SetAIOff()
|
||||||
|
grp:EnableEmission(false)
|
||||||
|
end
|
||||||
|
grp.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "AAA",
|
||||||
|
invisible = true,
|
||||||
|
range = EngageRange,
|
||||||
|
exception = false,
|
||||||
|
AIOff = SwitchAAA,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
|
if grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp.Tiresias.invisible = true
|
||||||
|
if SwitchAAA then
|
||||||
|
grp:SetAIOff()
|
||||||
|
grp:EnableEmission(false)
|
||||||
|
grp.Tiresias.AIOff = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--BASE:I(string.format("Init/Switch off AAA %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
|
end
|
||||||
|
)
|
||||||
|
--- Vehicles
|
||||||
|
self.VehicleSet:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if not grp.Tiresias then
|
||||||
|
grp:SetAIOff()
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "Vehicle",
|
||||||
|
invisible = true,
|
||||||
|
AIOff = true,
|
||||||
|
exception = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
|
if grp.Tiresias and grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp:SetAIOff()
|
||||||
|
grp.Tiresias.invisible = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--BASE:I(string.format("Init/Switch off Vehicle %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
|
end
|
||||||
|
)
|
||||||
|
--- SAM
|
||||||
|
self.SAMSet:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if not grp.Tiresias then
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "SAM",
|
||||||
|
invisible = true,
|
||||||
|
exception = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
|
if grp.Tiresias and grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp.Tiresias.invisible = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--BASE:I(string.format("Init/Switch off SAM %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
|
end
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Event handler function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:_EventHandler(EventData)
|
||||||
|
self:T(string.format("%s Event = %d",self.lid, EventData.id))
|
||||||
|
local event = EventData -- Core.Event#EVENTDATA
|
||||||
|
if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then
|
||||||
|
--local _coalition = event.IniCoalition
|
||||||
|
--if _coalition ~= self.Coalition then
|
||||||
|
-- return --ignore!
|
||||||
|
--end
|
||||||
|
local unitname = event.IniUnitName or "none"
|
||||||
|
local _unit = event.IniUnit
|
||||||
|
local _group = event.IniGroup
|
||||||
|
if _group and _group:IsAlive() then
|
||||||
|
local radius = self.PlaneSwitchRange
|
||||||
|
if _group:IsHelicopter() then
|
||||||
|
radius = self.HeloSwitchRange
|
||||||
|
end
|
||||||
|
self:_SwitchOnGroups(_group,radius)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Switch Groups Behaviour
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param Wrapper.Group#GROUP group
|
||||||
|
-- @param #number radius Radius in NM
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:_SwitchOnGroups(group,radius)
|
||||||
|
self:T(self.lid.."_SwitchOnGroups "..group:GetName().." Radius "..radius.." NM")
|
||||||
|
local zone = ZONE_GROUP:New("Zone-"..group:GetName(),group,UTILS.NMToMeters(radius))
|
||||||
|
local ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
|
||||||
|
local count = ground:CountAlive()
|
||||||
|
if self.debug then
|
||||||
|
local text = string.format("There are %d groups around this plane or helo!",count)
|
||||||
|
self:I(text)
|
||||||
|
end
|
||||||
|
local SwitchAAA = self.SwitchAAA
|
||||||
|
if ground:CountAlive() > 0 then
|
||||||
|
ground:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if grp.Tiresias and grp.Tiresias.type and (not grp.Tiresias.exception == true ) then
|
||||||
|
if grp.Tiresias.invisible == true then
|
||||||
|
grp:SetCommandInvisible(false)
|
||||||
|
grp.Tiresias.invisible = false
|
||||||
|
end
|
||||||
|
if grp.Tiresias.type == "Vehicle" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
|
||||||
|
grp:SetAIOn()
|
||||||
|
grp.Tiresias.AIOff = false
|
||||||
|
end
|
||||||
|
if SwitchAAA and grp.Tiresias.type == "AAA" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
|
||||||
|
grp:SetAIOn()
|
||||||
|
grp:EnableEmission(true)
|
||||||
|
grp.Tiresias.AIOff = false
|
||||||
|
end
|
||||||
|
--BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
|
else
|
||||||
|
BASE:E("TIRESIAS - This group has not been initialized or is an exception!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- FSM Functions
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- [INTERNAL] FSM Function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:onafterStart(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
|
||||||
|
local VehicleSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterNotAAA):FilterFunction(TIRESIAS._FilterNotSAM):FilterStart()
|
||||||
|
local AAASet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterAAA):FilterStart()
|
||||||
|
local SAMSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterSAM):FilterStart()
|
||||||
|
local OpsGroupSet = SET_OPSGROUP:New():FilterActive(true):FilterStart()
|
||||||
|
self.FlightSet = SET_GROUP:New():FilterCategories({"plane","helicopter"}):FilterStart()
|
||||||
|
|
||||||
|
local EngageRange = self.AAARange
|
||||||
|
|
||||||
|
local ExceptionSet = self.ExceptionSet
|
||||||
|
if self.ExceptionSet then
|
||||||
|
function ExceptionSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
BASE:I("TIRESIAS: EXCEPTION Object Added: "..Object:GetName())
|
||||||
|
if Object and Object:IsAlive() then
|
||||||
|
Object.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "Exception",
|
||||||
|
exception = true,
|
||||||
|
}
|
||||||
|
Object:SetAIOn()
|
||||||
|
Object:SetCommandInvisible(false)
|
||||||
|
Object:EnableEmission(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local OGS = OpsGroupSet:GetAliveSet()
|
||||||
|
for _,_OG in pairs(OGS or {}) do
|
||||||
|
local OG = _OG -- Ops.OpsGroup#OPSGROUP
|
||||||
|
local grp = OG:GetGroup()
|
||||||
|
ExceptionSet:AddGroup(grp,true)
|
||||||
|
end
|
||||||
|
|
||||||
|
function OpsGroupSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
local grp = Object:GetGroup()
|
||||||
|
ExceptionSet:AddGroup(grp,true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function VehicleSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
BASE:I("TIRESIAS: VEHCILE Object Added: "..Object:GetName())
|
||||||
|
if Object and Object:IsAlive() then
|
||||||
|
Object:SetAIOff()
|
||||||
|
Object:SetCommandInvisible(true)
|
||||||
|
Object.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "Vehicle",
|
||||||
|
invisible = true,
|
||||||
|
AIOff = true,
|
||||||
|
exception = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local SwitchAAA = self.SwitchAAA
|
||||||
|
|
||||||
|
function AAASet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
if Object and Object:IsAlive() then
|
||||||
|
BASE:I("TIRESIAS: AAA Object Added: "..Object:GetName())
|
||||||
|
Object:OptionEngageRange(EngageRange)
|
||||||
|
Object:SetCommandInvisible(true)
|
||||||
|
if SwitchAAA then
|
||||||
|
Object:SetAIOff()
|
||||||
|
Object:EnableEmission(false)
|
||||||
|
end
|
||||||
|
Object.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "AAA",
|
||||||
|
invisible = true,
|
||||||
|
range = EngageRange,
|
||||||
|
exception = false,
|
||||||
|
AIOff = SwitchAAA,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function SAMSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
if Object and Object:IsAlive() then
|
||||||
|
BASE:I("TIRESIAS: SAM Object Added: "..Object:GetName())
|
||||||
|
Object:SetCommandInvisible(true)
|
||||||
|
Object.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "SAM",
|
||||||
|
invisible = true,
|
||||||
|
exception = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.VehicleSet = VehicleSet
|
||||||
|
self.AAASet = AAASet
|
||||||
|
self.SAMSet = SAMSet
|
||||||
|
self.OpsGroupSet = OpsGroupSet
|
||||||
|
|
||||||
|
self:_InitGroups()
|
||||||
|
|
||||||
|
self:__Status(1)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] FSM Function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:onbeforeStatus(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
if self:GetState() == "Stopped" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] FSM Function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:onafterStatus(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
if self.debug then
|
||||||
|
local count = self.VehicleSet:CountAlive()
|
||||||
|
local AAAcount = self.AAASet:CountAlive()
|
||||||
|
local SAMcount = self.SAMSet:CountAlive()
|
||||||
|
local text = string.format("Overall: %d | Vehicles: %d | AAA: %d | SAM: %d",count+AAAcount+SAMcount,count,AAAcount,SAMcount)
|
||||||
|
self:I(text)
|
||||||
|
end
|
||||||
|
self:_InitGroups()
|
||||||
|
if self.FlightSet:CountAlive() > 0 then
|
||||||
|
local Set = self.FlightSet:GetAliveSet()
|
||||||
|
for _,_plane in pairs(Set) do
|
||||||
|
local plane = _plane -- Wrapper.Group#GROUP
|
||||||
|
local radius = self.PlaneSwitchRange
|
||||||
|
if plane:IsHelicopter() then
|
||||||
|
radius = self.HeloSwitchRange
|
||||||
|
end
|
||||||
|
self:_SwitchOnGroups(_plane,radius)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self:GetState() ~= "Stopped" then
|
||||||
|
self:__Status(self.Interval)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] FSM Function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:onafterStop(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- End
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
-- @field #number respawndelay Delay before respawn in seconds.
|
-- @field #number respawndelay Delay before respawn in seconds.
|
||||||
-- @field #number runwaydestroyed Time stamp timer.getAbsTime() when the runway was destroyed.
|
-- @field #number runwaydestroyed Time stamp timer.getAbsTime() when the runway was destroyed.
|
||||||
-- @field #number runwayrepairtime Time in seconds until runway will be repaired after it was destroyed. Default is 3600 sec (one hour).
|
-- @field #number runwayrepairtime Time in seconds until runway will be repaired after it was destroyed. Default is 3600 sec (one hour).
|
||||||
-- @field Ops.FlightControl#FLIGHTCONTROL flightcontrol Flight control of this warehouse.
|
-- @field OPS.FlightControl#FLIGHTCONTROL flightcontrol Flight control of this warehouse.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Have your assets at the right place at the right time - or not!
|
--- Have your assets at the right place at the right time - or not!
|
||||||
@@ -3414,7 +3414,7 @@ end
|
|||||||
-- FSM states
|
-- FSM states
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- On after Start event. Starts the warehouse. Addes event handlers and schedules status updates of reqests and queue.
|
--- On after Start event. Starts the warehouse. Adds event handlers and schedules status updates of reqests and queue.
|
||||||
-- @param #WAREHOUSE self
|
-- @param #WAREHOUSE self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
@@ -3595,6 +3595,7 @@ function WAREHOUSE:onafterStatus(From, Event, To)
|
|||||||
local Trepair=self:GetRunwayRepairtime()
|
local Trepair=self:GetRunwayRepairtime()
|
||||||
self:I(self.lid..string.format("Runway destroyed! Will be repaired in %d sec", Trepair))
|
self:I(self.lid..string.format("Runway destroyed! Will be repaired in %d sec", Trepair))
|
||||||
if Trepair==0 then
|
if Trepair==0 then
|
||||||
|
self.runwaydestroyed = nil
|
||||||
self:RunwayRepaired()
|
self:RunwayRepaired()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -5392,7 +5393,8 @@ function WAREHOUSE:onafterRunwayDestroyed(From, Event, To)
|
|||||||
self:_InfoMessage(text)
|
self:_InfoMessage(text)
|
||||||
|
|
||||||
self.runwaydestroyed=timer.getAbsTime()
|
self.runwaydestroyed=timer.getAbsTime()
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "RunwayRepaired" event.
|
--- On after "RunwayRepaired" event.
|
||||||
@@ -5407,7 +5409,8 @@ function WAREHOUSE:onafterRunwayRepaired(From, Event, To)
|
|||||||
self:_InfoMessage(text)
|
self:_InfoMessage(text)
|
||||||
|
|
||||||
self.runwaydestroyed=nil
|
self.runwaydestroyed=nil
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -7404,6 +7407,8 @@ function WAREHOUSE:_CheckRequestNow(request)
|
|||||||
|
|
||||||
-- Check if at least one (cargo) asset is available.
|
-- Check if at least one (cargo) asset is available.
|
||||||
if _nassets>0 then
|
if _nassets>0 then
|
||||||
|
|
||||||
|
local asset=_assets[1] --#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
-- Get the attibute of the requested asset.
|
-- Get the attibute of the requested asset.
|
||||||
_assetattribute=_assets[1].attribute
|
_assetattribute=_assets[1].attribute
|
||||||
@@ -7414,11 +7419,24 @@ function WAREHOUSE:_CheckRequestNow(request)
|
|||||||
if _assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER then
|
if _assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER then
|
||||||
|
|
||||||
if self.airbase and self.airbase:GetCoalition()==self:GetCoalition() then
|
if self.airbase and self.airbase:GetCoalition()==self:GetCoalition() then
|
||||||
|
|
||||||
|
-- Check if DCS warehouse of airbase has enough assets
|
||||||
|
if self.airbase.storage then
|
||||||
|
local nS=self.airbase.storage:GetAmount(asset.unittype)
|
||||||
|
local nA=asset.nunits*request.nasset -- Number of units requested
|
||||||
|
if nS<nA then
|
||||||
|
local text=string.format("Warehouse %s: Request denied! DCS Warehouse has only %d assets of type %s ==> NOT enough to spawn the requested %d asset units (%d groups)",
|
||||||
|
self.alias, nS, asset.unittype, nA, request.nasset)
|
||||||
|
self:_InfoMessage(text, 5)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
if self:IsRunwayOperational() or _assetairstart then
|
if self:IsRunwayOperational() or _assetairstart then
|
||||||
|
|
||||||
if _assetairstart then
|
if _assetairstart then
|
||||||
-- Airstart no need to check parking
|
-- Airstart no need to check parking
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Check parking.
|
-- Check parking.
|
||||||
@@ -7530,6 +7548,9 @@ function WAREHOUSE:_CheckRequestNow(request)
|
|||||||
self:_InfoMessage(text, 5)
|
self:_InfoMessage(text, 5)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
elseif _assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER then
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [CAZ - Capture Zones](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAZ%20-%20Capture%20Zones)
|
-- [CAZ - Capture Zones](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Functional/ZoneCaptureCoalition)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,180 +1,181 @@
|
|||||||
__Moose.Include( 'Scripts/Moose/Utilities/Enums.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Enums.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Utilities/FiFo.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Utils.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Utilities/Profiler.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Profiler.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Utilities/Socket.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Templates.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Utilities/STTS.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/STTS.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Utilities/Templates.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/FiFo.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Utilities/Utils.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Socket.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Base.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Base.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Astar.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Beacon.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Condition.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/UserFlag.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Report.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Scheduler.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/ScheduleDispatcher.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Event.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Settings.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Menu.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Zone.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Zone_Detection.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Database.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Set.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Point.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Velocity.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Message.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Fsm.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Spawn.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/SpawnStatic.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Timer.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Goal.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Spot.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/MarkerOps_Base.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/TextAndSound.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Pathline.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/ClientMenu.lua')
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Astar.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Object.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Beacon.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Identifiable.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Condition.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Positionable.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/ClientMenu.lua')
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Controllable.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Database.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Group.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Event.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Unit.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Fsm.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Client.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Goal.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Static.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/MarkerOps_Base.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Airbase.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Menu.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Scenery.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Message.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Marker.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Point.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Weapon.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Report.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Net.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/ScheduleDispatcher.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Storage.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Scheduler.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Set.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Settings.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Spawn.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Spot.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/TextAndSound.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Timer.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/UserFlag.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Velocity.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Zone_Detection.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Zone.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Pathline.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/Cargo.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Client.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoUnit.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Controllable.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoSlingload.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Group.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoCrate.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Identifiable.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoGroup.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Marker.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Object.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Positionable.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' )
|
|
||||||
__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( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Scoring.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/CleanUp.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoSlingload.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Movement.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoCrate.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Sead.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoGroup.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Escort.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/MissileTrainer.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ATC_Ground.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Detection.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/DetectionZones.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Designate.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/RAT.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Range.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ZoneGoal.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ZoneGoalCoalition.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ZoneCaptureCoalition.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Artillery.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Suppression.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/PseudoATC.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Warehouse.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Fox.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Mantis.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Shorad.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/AICSAR.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/AmmoTruck.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Autolase.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ZoneGoalCargo.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Tiresias.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Stratego.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/AICSAR.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/AmmoTruck.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Artillery.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RescueHelo.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/ATC_Ground.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/ATIS.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Autolase.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/CTLD.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/CleanUp.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/CSAR.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Designate.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/AirWing.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Detection.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/ArmyGroup.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/DetectionZones.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Auftrag.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Escort.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Awacs.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Fox.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Brigade.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Mantis.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Chief.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/MissileTrainer.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Cohort.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Movement.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Commander.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/PseudoATC.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Fleet.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Range.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/FlightControl.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/RAT.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/FlightGroup.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Scoring.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Flotilla.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Sead.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Intelligence.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Shorad.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Legion.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Suppression.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/NavyGroup.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Warehouse.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Operation.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneCaptureCoalition.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsGroup.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoal.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsTransport.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCargo.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsZone.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCoalition.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Platoon.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/PlayerTask.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/PlayerRecce.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Squadron.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Target.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/EasyGCICAP.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Balancer.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/AirWing.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Air.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/ArmyGroup.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Air_Patrol.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/ATIS.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Air_Engage.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Auftrag.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_A2A_Patrol.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Awacs.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_A2A_Cap.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Brigade.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_A2A_Gci.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Chief.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_A2A_Dispatcher.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Cohort.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_A2G_BAI.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Commander.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_A2G_CAS.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/CSAR.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_A2G_SEAD.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/CTLD.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_A2G_Dispatcher.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Fleet.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Patrol.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/FlightControl.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_CAP.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/FlightGroup.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_CAS.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Flotilla.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_BAI.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Intelligence.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Formation.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Legion.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Escort.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/NavyGroup.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Escort_Request.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Operation.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Escort_Dispatcher.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/OpsGroup.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Escort_Dispatcher_Request.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/OpsTransport.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/OpsZone.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_APC.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Platoon.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_Helicopter.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/PlayerTask.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_Airplane.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/PlayerRecce.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_Ship.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_Dispatcher.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/RescueHelo.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_Dispatcher_APC.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Squadron.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Target.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/EasyGCICAP.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Cargo_Dispatcher_Ship.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Actions/Act_Assign.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Actions/Act_Route.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air_Patrol.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Actions/Act_Account.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air_Engage.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Actions/Act_Assist.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Patrol.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Cap.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Gci.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_BAI.lua' )
|
|
||||||
__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_Formation.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Escort.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Escort_Request.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Escort_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Escort_Dispatcher_Request.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_APC.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Helicopter.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Airplane.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Ship.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher_APC.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher_Ship.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Actions/Act_Assign.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Sound/UserSound.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Actions/Act_Route.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Sound/SoundOutput.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Actions/Act_Account.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Sound/Radio.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Actions/Act_Assist.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Sound/RadioQueue.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Sound/RadioSpeech.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Sound/SRS.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Sound/Radio.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/CommandCenter.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Sound/RadioQueue.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Mission.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Sound/RadioSpeech.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Sound/SoundOutput.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/TaskInfo.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Sound/SRS.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Manager.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Sound/UserSound.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/DetectionManager.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_A2G_Dispatcher.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_A2G.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_A2A_Dispatcher.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_A2A.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_CARGO.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Cargo_Transport.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Cargo_CSAR.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Cargo_Dispatcher.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Capture_Zone.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Capture_Dispatcher.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/CommandCenter.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Globals.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/Mission.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/Task.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/TaskInfo.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Manager.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/DetectionManager.lua' )
|
|
||||||
__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_Transport.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo_CSAR.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Capture_Zone.lua' )
|
|
||||||
__Moose.Include( 'Scripts/Moose/Tasking/Task_Capture_Dispatcher.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Globals.lua' )
|
|
||||||
|
|||||||
@@ -312,10 +312,16 @@
|
|||||||
--
|
--
|
||||||
-- atis=ATIS:New("Batumi", 305, radio.modulation.AM)
|
-- atis=ATIS:New("Batumi", 305, radio.modulation.AM)
|
||||||
-- atis:SetSRS("D:\\DCS\\_SRS\\", "male", "en-US")
|
-- atis:SetSRS("D:\\DCS\\_SRS\\", "male", "en-US")
|
||||||
-- atis:Start()
|
-- atis:Start()
|
||||||
--
|
--
|
||||||
-- This uses a male voice with US accent. It requires SRS to be installed in the `D:\DCS\_SRS\` directory. Note that backslashes need to be escaped or simply use slashes (as in linux).
|
-- This uses a male voice with US accent. It requires SRS to be installed in the `D:\DCS\_SRS\` directory. Note that backslashes need to be escaped or simply use slashes (as in linux).
|
||||||
--
|
--
|
||||||
|
-- ### SRS can use multiple frequencies:
|
||||||
|
--
|
||||||
|
-- atis=ATIS:New("Batumi", {305,103.85}, {radio.modulation.AM,radio.modulation.FM})
|
||||||
|
-- atis:SetSRS("D:\\DCS\\_SRS\\", "male", "en-US")
|
||||||
|
-- atis:Start()
|
||||||
|
--
|
||||||
-- ### SRS Localization
|
-- ### SRS Localization
|
||||||
--
|
--
|
||||||
-- You can localize the SRS output, all you need is to provide a table of translations and set the `locale` of your instance. You need to provide the translations in your script **before you instantiate your ATIS**.
|
-- You can localize the SRS output, all you need is to provide a table of translations and set the `locale` of your instance. You need to provide the translations in your script **before you instantiate your ATIS**.
|
||||||
@@ -694,7 +700,7 @@ ATIS.Messages = {
|
|||||||
EN =
|
EN =
|
||||||
{
|
{
|
||||||
HOURS = "hours",
|
HOURS = "hours",
|
||||||
TIME = "hours",
|
TIME = "Hours",
|
||||||
NOCLOUDINFO = "Cloud coverage information not available",
|
NOCLOUDINFO = "Cloud coverage information not available",
|
||||||
OVERCAST = "Overcast",
|
OVERCAST = "Overcast",
|
||||||
BROKEN = "Broken clouds",
|
BROKEN = "Broken clouds",
|
||||||
@@ -884,13 +890,14 @@ _ATIS = {}
|
|||||||
|
|
||||||
--- ATIS class version.
|
--- ATIS class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
ATIS.version = "0.10.3"
|
ATIS.version = "1.0.0"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: Correct fog for elevation.
|
-- TODO: Correct fog for elevation.
|
||||||
|
-- DONE: Option to add multiple frequencies for SRS
|
||||||
-- DONE: Zulu time --> Zulu in output.
|
-- DONE: Zulu time --> Zulu in output.
|
||||||
-- DONE: Fix for AB not having a runway - Helopost like Naqoura
|
-- DONE: Fix for AB not having a runway - Helopost like Naqoura
|
||||||
-- DONE: Add new Normandy airfields.
|
-- DONE: Add new Normandy airfields.
|
||||||
@@ -899,7 +906,7 @@ ATIS.version = "0.10.3"
|
|||||||
-- DONE: Visibility reported twice over SRS
|
-- DONE: Visibility reported twice over SRS
|
||||||
-- DONE: Add text report for output.
|
-- DONE: Add text report for output.
|
||||||
-- DONE: Add stop FMS functions.
|
-- DONE: Add stop FMS functions.
|
||||||
-- NOGO: Use local time. Not realisitc!
|
-- NOGO: Use local time. Not realistic!
|
||||||
-- DONE: Dew point. Approx. done.
|
-- DONE: Dew point. Approx. done.
|
||||||
-- DONE: Metric units.
|
-- DONE: Metric units.
|
||||||
-- DONE: Set UTC correction.
|
-- DONE: Set UTC correction.
|
||||||
@@ -915,8 +922,8 @@ ATIS.version = "0.10.3"
|
|||||||
--- Create a new ATIS class object for a specific airbase.
|
--- Create a new ATIS class object for a specific airbase.
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @param #string AirbaseName Name of the airbase.
|
-- @param #string AirbaseName Name of the airbase.
|
||||||
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz.
|
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. When using **SRS** this can be passed as a table of multiple frequencies.
|
||||||
-- @param #number Modulation Radio modulation: 0=AM, 1=FM. Default 0=AM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators.
|
-- @param #number Modulation Radio modulation: 0=AM, 1=FM. Default 0=AM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. When using **SRS** this can be passed as a table of multiple modulations.
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
function ATIS:New(AirbaseName, Frequency, Modulation)
|
function ATIS:New(AirbaseName, Frequency, Modulation)
|
||||||
|
|
||||||
@@ -1519,34 +1526,62 @@ function ATIS:MarkRunways( markall )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Use SRS Simple-Text-To-Speech for transmissions. No sound files necessary.
|
--- Use SRS Simple-Text-To-Speech for transmissions. No sound files necessary.`SetSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @param #string PathToSRS Path to SRS directory.
|
-- @param #string PathToSRS Path to SRS directory (only necessary if SRS exe backend is used).
|
||||||
-- @param #string Gender Gender: "male" or "female" (default).
|
-- @param #string Gender Gender: "male" or "female" (default).
|
||||||
-- @param #string Culture Culture, e.g. "en-GB" (default).
|
-- @param #string Culture Culture, e.g. "en-GB" (default).
|
||||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
||||||
-- @param #number Port SRS port. Default 5002.
|
-- @param #number Port SRS port. Default 5002.
|
||||||
-- @param #string GoogleKey Path to Google JSON-Key.
|
-- @param #string GoogleKey Path to Google JSON-Key (SRS exe backend) or Google API key (DCS-gRPC backend).
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey)
|
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey)
|
||||||
if PathToSRS or MSRS.path then
|
--if PathToSRS or MSRS.path then
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
self.msrs=MSRS:New(PathToSRS, self.frequency, self.modulation)
|
|
||||||
self.msrs:SetGender(Gender)
|
local path = PathToSRS or MSRS.path
|
||||||
self.msrs:SetCulture(Culture)
|
local gender = Gender or MSRS.gender
|
||||||
self.msrs:SetVoice(Voice)
|
local culture = Culture or MSRS.culture
|
||||||
self.msrs:SetPort(Port)
|
local voice = Voice or MSRS.voice
|
||||||
|
local port = Port or MSRS.port or 5002
|
||||||
|
|
||||||
|
self.msrs=MSRS:New(path, self.frequency, self.modulation)
|
||||||
|
self.msrs:SetGender(gender)
|
||||||
|
self.msrs:SetCulture(culture)
|
||||||
|
self.msrs:SetPort(port)
|
||||||
self.msrs:SetCoalition(self:GetCoalition())
|
self.msrs:SetCoalition(self:GetCoalition())
|
||||||
self.msrs:SetLabel("ATIS")
|
self.msrs:SetLabel("ATIS")
|
||||||
self.msrs:SetGoogle(GoogleKey)
|
if GoogleKey then
|
||||||
|
self.msrs:SetProviderOptionsGoogle(GoogleKey,GoogleKey)
|
||||||
|
self.msrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
|
-- Pre-configured Google?
|
||||||
|
if (not GoogleKey) and self.msrs:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
|
voice = Voice or MSRS.poptions.gcloud.voice
|
||||||
|
end
|
||||||
|
self.msrs:SetVoice(voice)
|
||||||
self.msrs:SetCoordinate(self.airbase:GetCoordinate())
|
self.msrs:SetCoordinate(self.airbase:GetCoordinate())
|
||||||
self.msrsQ = MSRSQUEUE:New("ATIS")
|
self.msrsQ = MSRSQUEUE:New("ATIS")
|
||||||
self.msrsQ:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
self.msrsQ:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
||||||
if self.dTQueueCheck<=10 then
|
if self.dTQueueCheck<=10 then
|
||||||
self:SetQueueUpdateTime(90)
|
self:SetQueueUpdateTime(90)
|
||||||
end
|
end
|
||||||
|
--else
|
||||||
|
--self:E(self.lid..string.format("ERROR: No SRS path specified!"))
|
||||||
|
--end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set an alternative provider to the one set in your MSRS configuration file.
|
||||||
|
-- @param #ATIS self
|
||||||
|
-- @param #string Provider The provider to use. Known providers are: `MSRS.Provider.WINDOWS` and `MSRS.Provider.GOOGLE`
|
||||||
|
-- @return #ATIS self
|
||||||
|
function ATIS:SetSRSProvider(Provider)
|
||||||
|
self:T(self.lid.."SetSRSProvider")
|
||||||
|
if self.msrs then
|
||||||
|
self.msrs:SetProvider(Provider)
|
||||||
else
|
else
|
||||||
self:E(self.lid..string.format("ERROR: No SRS path specified!"))
|
MESSAGE:New(self.lid.."Set up SRS first before trying to change the provider!",30,"ATIS"):ToAll():ToLog()
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1594,8 +1629,16 @@ function ATIS:onafterStart( From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Info.
|
-- Info.
|
||||||
self:I( self.lid .. string.format( "Starting ATIS v%s for airbase %s on %.3f MHz Modulation=%d", ATIS.version, self.airbasename, self.frequency, self.modulation ) )
|
if type(self.frequency) == "table" then
|
||||||
|
local frequency = table.concat(self.frequency,"/")
|
||||||
|
local modulation = self.modulation
|
||||||
|
if type(self.modulation) == "table" then
|
||||||
|
modulation = table.concat(self.modulation,"/")
|
||||||
|
end
|
||||||
|
self:I( self.lid .. string.format( "Starting ATIS v%s for airbase %s on %s MHz Modulation=%s", ATIS.version, self.airbasename, frequency, modulation ) )
|
||||||
|
else
|
||||||
|
self:I( self.lid .. string.format( "Starting ATIS v%s for airbase %s on %.3f MHz Modulation=%d", ATIS.version, self.airbasename, self.frequency, self.modulation ) )
|
||||||
|
end
|
||||||
-- Start radio queue.
|
-- Start radio queue.
|
||||||
if not self.useSRS then
|
if not self.useSRS then
|
||||||
self.radioqueue = RADIOQUEUE:New( self.frequency, self.modulation, string.format( "ATIS %s", self.airbasename ) )
|
self.radioqueue = RADIOQUEUE:New( self.frequency, self.modulation, string.format( "ATIS %s", self.airbasename ) )
|
||||||
@@ -1653,7 +1696,17 @@ function ATIS:onafterStatus( From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Info text.
|
-- Info text.
|
||||||
local text = string.format( "State %s: Freq=%.3f MHz %s", fsmstate, self.frequency, UTILS.GetModulationName( self.modulation ) )
|
local text = ""
|
||||||
|
if type(self.frequency) == "table" then
|
||||||
|
local frequency = table.concat(self.frequency,"/")
|
||||||
|
local modulation = self.modulation
|
||||||
|
if type(self.modulation) == "table" then
|
||||||
|
modulation = table.concat(self.modulation,"/")
|
||||||
|
end
|
||||||
|
text = string.format( "State %s: Freq=%s MHz %s", fsmstate, frequency, modulation )
|
||||||
|
else
|
||||||
|
text = string.format( "State %s: Freq=%.3f MHz %s", fsmstate, self.frequency, UTILS.GetModulationName( self.modulation ) )
|
||||||
|
end
|
||||||
if self.useSRS then
|
if self.useSRS then
|
||||||
text = text .. string.format( ", SRS path=%s (%s), gender=%s, culture=%s, voice=%s", tostring( self.msrs.path ), tostring( self.msrs.port ), tostring( self.msrs.gender ), tostring( self.msrs.culture ), tostring( self.msrs.voice ) )
|
text = text .. string.format( ", SRS path=%s (%s), gender=%s, culture=%s, voice=%s", tostring( self.msrs.path ), tostring( self.msrs.port ), tostring( self.msrs.gender ), tostring( self.msrs.culture ), tostring( self.msrs.voice ) )
|
||||||
else
|
else
|
||||||
@@ -2919,8 +2972,17 @@ function ATIS:UpdateMarker( information, runact, wind, altimeter, temperature )
|
|||||||
if self.markerid then
|
if self.markerid then
|
||||||
self.airbase:GetCoordinate():RemoveMark( self.markerid )
|
self.airbase:GetCoordinate():RemoveMark( self.markerid )
|
||||||
end
|
end
|
||||||
|
local text = ""
|
||||||
local text = string.format( "ATIS on %.3f %s, %s:\n", self.frequency, UTILS.GetModulationName( self.modulation ), tostring( information ) )
|
if type(self.frequency) == "table" then
|
||||||
|
local frequency = table.concat(self.frequency,"/")
|
||||||
|
local modulation = self.modulation
|
||||||
|
if type(modulation) == "table" then
|
||||||
|
modulation = table.concat(self.modulation,"/")
|
||||||
|
end
|
||||||
|
text = string.format( "ATIS on %s %s, %s:\n", tostring(frequency), tostring(modulation), tostring( information ) )
|
||||||
|
else
|
||||||
|
text = string.format( "ATIS on %.3f %s, %s:\n", self.frequency, UTILS.GetModulationName( self.modulation ), tostring( information ) )
|
||||||
|
end
|
||||||
text = text .. string.format( "%s\n", tostring( runact ) )
|
text = text .. string.format( "%s\n", tostring( runact ) )
|
||||||
text = text .. string.format( "%s\n", tostring( wind ) )
|
text = text .. string.format( "%s\n", tostring( wind ) )
|
||||||
text = text .. string.format( "%s\n", tostring( altimeter ) )
|
text = text .. string.format( "%s\n", tostring( altimeter ) )
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Airwing).
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Airwing).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -56,6 +56,8 @@
|
|||||||
-- @field #boolean despawnAfterHolding Aircraft are despawned after holding.
|
-- @field #boolean despawnAfterHolding Aircraft are despawned after holding.
|
||||||
-- @field #boolean capOptionPatrolRaceTrack Use closer patrol race track or standard orbit auftrag.
|
-- @field #boolean capOptionPatrolRaceTrack Use closer patrol race track or standard orbit auftrag.
|
||||||
-- @field #number capFormation If capOptionPatrolRaceTrack is true, set the formation, also.
|
-- @field #number capFormation If capOptionPatrolRaceTrack is true, set the formation, also.
|
||||||
|
-- @field #number capOptionVaryStartTime If set, vary mission start time for CAP missions generated random between capOptionVaryStartTime and capOptionVaryEndTime
|
||||||
|
-- @field #number capOptionVaryEndTime If set, vary mission start time for CAP missions generated random between capOptionVaryStartTime and capOptionVaryEndTime
|
||||||
--
|
--
|
||||||
-- @extends Ops.Legion#LEGION
|
-- @extends Ops.Legion#LEGION
|
||||||
|
|
||||||
@@ -132,6 +134,8 @@ AIRWING = {
|
|||||||
markpoints = false,
|
markpoints = false,
|
||||||
capOptionPatrolRaceTrack = false,
|
capOptionPatrolRaceTrack = false,
|
||||||
capFormation = nil,
|
capFormation = nil,
|
||||||
|
capOptionVaryStartTime = nil,
|
||||||
|
capOptionVaryEndTime = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Payload data.
|
--- Payload data.
|
||||||
@@ -183,7 +187,7 @@ AIRWING = {
|
|||||||
|
|
||||||
--- AIRWING class version.
|
--- AIRWING class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRWING.version="0.9.4"
|
AIRWING.version="0.9.5"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -721,6 +725,17 @@ function AIRWING:SetCapCloseRaceTrack(OnOff)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set CAP mission start to vary randomly between Start end End seconds.
|
||||||
|
-- @param #AIRWING self
|
||||||
|
-- @param #number Start
|
||||||
|
-- @param #number End
|
||||||
|
-- @return #AIRWING self
|
||||||
|
function AIRWING:SetCapStartTimeVariation(Start, End)
|
||||||
|
self.capOptionVaryStartTime = Start or 5
|
||||||
|
self.capOptionVaryEndTime = End or 60
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Set number of TANKER flights with Boom constantly in the air.
|
--- Set number of TANKER flights with Boom constantly in the air.
|
||||||
-- @param #AIRWING self
|
-- @param #AIRWING self
|
||||||
-- @param #number Nboom Number of flights. Default 1.
|
-- @param #number Nboom Number of flights. Default 1.
|
||||||
@@ -1165,6 +1180,14 @@ function AIRWING:CheckCAP()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.capOptionVaryStartTime then
|
||||||
|
|
||||||
|
local ClockStart = math.random(self.capOptionVaryStartTime, self.capOptionVaryEndTime)
|
||||||
|
|
||||||
|
missionCAP:SetTime(ClockStart)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
missionCAP.patroldata=patrol
|
missionCAP.patroldata=patrol
|
||||||
|
|
||||||
patrol.noccupied=patrol.noccupied+1
|
patrol.noccupied=patrol.noccupied+1
|
||||||
@@ -1398,9 +1421,9 @@ function AIRWING:GetTankerForFlight(flightgroup)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add the ability to call back an Ops.Awacs#AWACS object with an FSM call "FlightOnMission(FlightGroup, Mission)".
|
--- Add the ability to call back an Ops.AWACS#AWACS object with an FSM call "FlightOnMission(FlightGroup, Mission)".
|
||||||
-- @param #AIRWING self
|
-- @param #AIRWING self
|
||||||
-- @param Ops.Awacs#AWACS ConnectecdAwacs
|
-- @param Ops.AWACS#AWACS ConnectecdAwacs
|
||||||
-- @return #AIRWING self
|
-- @return #AIRWING self
|
||||||
function AIRWING:SetUsingOpsAwacs(ConnectecdAwacs)
|
function AIRWING:SetUsingOpsAwacs(ConnectecdAwacs)
|
||||||
self:I(self.lid .. "Added AWACS Object: "..ConnectecdAwacs:GetName() or "unknown")
|
self:I(self.lid .. "Added AWACS Object: "..ConnectecdAwacs:GetName() or "unknown")
|
||||||
@@ -1409,7 +1432,7 @@ function AIRWING:SetUsingOpsAwacs(ConnectecdAwacs)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Remove the ability to call back an Ops.Awacs#AWACS object with an FSM call "FlightOnMission(FlightGroup, Mission)".
|
--- Remove the ability to call back an Ops.AWACS#AWACS object with an FSM call "FlightOnMission(FlightGroup, Mission)".
|
||||||
-- @param #AIRWING self
|
-- @param #AIRWING self
|
||||||
-- @return #AIRWING self
|
-- @return #AIRWING self
|
||||||
function AIRWING:RemoveUsingOpsAwacs()
|
function AIRWING:RemoveUsingOpsAwacs()
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions
|
-- ## Example Missions
|
||||||
--
|
--
|
||||||
-- Example missions can be found [here](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Airboss).
|
-- Example missions can be found [here](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Ops/Airboss).
|
||||||
-- They contain the latest development Moose.lua file.
|
-- They contain the latest development Moose.lua file.
|
||||||
--
|
--
|
||||||
-- ## IMPORTANT
|
-- ## IMPORTANT
|
||||||
@@ -3062,7 +3062,7 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
|
|||||||
-- SRS
|
-- SRS
|
||||||
local Frequency = self.AirbossRadio.frequency
|
local Frequency = self.AirbossRadio.frequency
|
||||||
local Modulation = self.AirbossRadio.modulation
|
local Modulation = self.AirbossRadio.modulation
|
||||||
self.SRS = MSRS:New(PathToSRS,Frequency,Modulation,Volume,AltBackend)
|
self.SRS = MSRS:New(PathToSRS,Frequency,Modulation,AltBackend)
|
||||||
self.SRS:SetCoalition(self:GetCoalition())
|
self.SRS:SetCoalition(self:GetCoalition())
|
||||||
self.SRS:SetCoordinate(self:GetCoordinate())
|
self.SRS:SetCoordinate(self:GetCoordinate())
|
||||||
self.SRS:SetCulture(Culture or "en-US")
|
self.SRS:SetCulture(Culture or "en-US")
|
||||||
@@ -3072,9 +3072,11 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
|
|||||||
self.SRS:SetPort(Port or 5002)
|
self.SRS:SetPort(Port or 5002)
|
||||||
self.SRS:SetLabel(self.AirbossRadio.alias or "AIRBOSS")
|
self.SRS:SetLabel(self.AirbossRadio.alias or "AIRBOSS")
|
||||||
self.SRS:SetCoordinate(self.carrier:GetCoordinate())
|
self.SRS:SetCoordinate(self.carrier:GetCoordinate())
|
||||||
|
self.SRS:SetVolume(Volume or 1)
|
||||||
--self.SRS:SetModulations(Modulations)
|
--self.SRS:SetModulations(Modulations)
|
||||||
if GoogleCreds then
|
if GoogleCreds then
|
||||||
self.SRS:SetGoogle(GoogleCreds)
|
self.SRS:SetProviderOptionsGoogle(GoogleCreds,GoogleCreds)
|
||||||
|
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
if Voice then
|
if Voice then
|
||||||
self.SRS:SetVoice(Voice)
|
self.SRS:SetVoice(Voice)
|
||||||
@@ -8212,7 +8214,7 @@ function AIRBOSS:OnEventBirth( EventData )
|
|||||||
self:E( EventData )
|
self:E( EventData )
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if EventData.IniUnit == nil then
|
if EventData.IniUnit == nil and (not EventData.IniObjectCategory == Object.Category.STATIC) then
|
||||||
self:E( self.lid .. "ERROR: EventData.IniUnit=nil in event BIRTH!" )
|
self:E( self.lid .. "ERROR: EventData.IniUnit=nil in event BIRTH!" )
|
||||||
self:E( EventData )
|
self:E( EventData )
|
||||||
return
|
return
|
||||||
@@ -11197,7 +11199,7 @@ function AIRBOSS:_AttitudeMonitor( playerData )
|
|||||||
end
|
end
|
||||||
text = text .. string.format( "\nPitch=%.1f° | Roll=%.1f° | Yaw=%.1f°", pitch, roll, yaw )
|
text = text .. string.format( "\nPitch=%.1f° | Roll=%.1f° | Yaw=%.1f°", pitch, roll, yaw )
|
||||||
text = text .. string.format( "\nClimb Angle=%.1f° | Rate=%d ft/min", unit:GetClimbAngle(), velo.y * 196.85 )
|
text = text .. string.format( "\nClimb Angle=%.1f° | Rate=%d ft/min", unit:GetClimbAngle(), velo.y * 196.85 )
|
||||||
local dist = self:_GetOptLandingCoordinate():Get3DDistance( playerData.unit )
|
local dist = self:_GetOptLandingCoordinate():Get3DDistance( playerData.unit:GetVec3() )
|
||||||
-- Get player velocity in km/h.
|
-- Get player velocity in km/h.
|
||||||
local vplayer = playerData.unit:GetVelocityKMH()
|
local vplayer = playerData.unit:GetVelocityKMH()
|
||||||
-- Get carrier velocity in km/h.
|
-- Get carrier velocity in km/h.
|
||||||
@@ -12121,16 +12123,18 @@ function AIRBOSS:_LSOgrade( playerData )
|
|||||||
local GIC, nIC = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.IC )
|
local GIC, nIC = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.IC )
|
||||||
local GAR, nAR = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.AR )
|
local GAR, nAR = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.AR )
|
||||||
|
|
||||||
|
-- VTOL approach, which is graded differently (currently only Harrier).
|
||||||
|
local vtol=playerData.actype==AIRBOSS.AircraftCarrier.AV8B
|
||||||
|
|
||||||
-- Put everything together.
|
-- Put everything together.
|
||||||
local G = GXX .. " " .. GIM .. " " .. " " .. GIC .. " " .. GAR
|
local G = GXX .. " " .. GIM .. " " .. " " .. GIC .. " " .. GAR
|
||||||
|
|
||||||
-- Count number of minor, normal and major deviations.
|
-- Count number of minor/small nS, normal nN and major/large deviations nL.
|
||||||
local N=nXX+nIM+nIC+nAR
|
local N=nXX+nIM+nIC+nAR
|
||||||
local Nv=nXX+nIM
|
|
||||||
local nL=count(G, '_')/2
|
local nL=count(G, '_')/2
|
||||||
local nS=count(G, '%(')
|
local nS=count(G, '%(')
|
||||||
local nN=N-nS-nL
|
local nN=N-nS-nL
|
||||||
local nNv=Nv-nS-nL
|
|
||||||
|
|
||||||
-- Groove time 15-18.99 sec for a unicorn. Or 60-65 for V/STOL unicorn.
|
-- Groove time 15-18.99 sec for a unicorn. Or 60-65 for V/STOL unicorn.
|
||||||
local Tgroove=playerData.Tgroove
|
local Tgroove=playerData.Tgroove
|
||||||
@@ -12146,34 +12150,64 @@ function AIRBOSS:_LSOgrade( playerData )
|
|||||||
G = "Unicorn"
|
G = "Unicorn"
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe.--Pene testing
|
if vtol then
|
||||||
-- Large devaitions still result in a No Grade, A Unicorn still requires a clean pass with no deviation.
|
|
||||||
if nL > 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
|
||||||
-- Larger deviations ==> "No grade" 2.0 points.
|
|
||||||
grade="--"
|
|
||||||
points=2.0
|
|
||||||
elseif nNv >= 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
|
||||||
-- Only average deviations ==> "Fair Pass" Pass with average deviations and corrections.
|
|
||||||
grade="(OK)"
|
|
||||||
points=3.0
|
|
||||||
elseif nNv < 1 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
|
||||||
-- Only minor average deviations ==> "OK" Pass with minor deviations and corrections. (test nNv<=1 and)
|
|
||||||
grade="OK"
|
|
||||||
points=4.0
|
|
||||||
elseif nL > 0 then
|
|
||||||
-- Larger deviations ==> "No grade" 2.0 points.
|
|
||||||
grade="--"
|
|
||||||
points=2.0
|
|
||||||
elseif nN> 0 then
|
|
||||||
-- No larger but average deviations ==> "Fair Pass" Pass with average deviations and corrections.
|
|
||||||
grade="(OK)"
|
|
||||||
points=3.0
|
|
||||||
else
|
|
||||||
-- Only minor corrections
|
|
||||||
grade="OK"
|
|
||||||
points=4.0
|
|
||||||
end
|
|
||||||
|
|
||||||
|
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe.--Pene testing
|
||||||
|
-- Large devaitions still result in a No Grade, A Unicorn still requires a clean pass with no deviation.
|
||||||
|
|
||||||
|
-- Normal laning part at the beginning
|
||||||
|
local Gb = GXX .. " " .. GIM
|
||||||
|
|
||||||
|
-- Number of deviations that occurred at the the beginning of the landing (XX or IM). These are graded like in non-VTOL landings, i.e. on deviations is
|
||||||
|
local N=nXX+nIM
|
||||||
|
local nL=count(Gb, '_')/2
|
||||||
|
local nS=count(Gb, '%(')
|
||||||
|
local nN=N-nS-nL
|
||||||
|
|
||||||
|
|
||||||
|
-- VTOL part of the landing
|
||||||
|
local Gv = GIC .. " " .. GAR
|
||||||
|
|
||||||
|
-- Number of deviations that occurred at the the end (VTOL part) of the landing (IC or AR).
|
||||||
|
local Nv=nIC+nAR
|
||||||
|
local nLv=count(Gv, '_')/2
|
||||||
|
local nSv=count(Gv, '%(')
|
||||||
|
local nNv=Nv-nSv-nLv
|
||||||
|
|
||||||
|
if nL>0 or nLv>1 then
|
||||||
|
-- Larger deviations at XX or IM or at least one larger deviation IC or AR==> "No grade" 2.0 points.
|
||||||
|
-- In other words, we allow one larger deviation at IC+AR
|
||||||
|
grade="--"
|
||||||
|
points=2.0
|
||||||
|
elseif nN>0 or nNv>1 or nLv==1 then
|
||||||
|
-- Average deviations at XX+IM or more than one normal deviation IC or AR ==> "Fair Pass" Pass with average deviations and corrections.
|
||||||
|
grade="(OK)"
|
||||||
|
points=3.0
|
||||||
|
else
|
||||||
|
-- Only minor corrections
|
||||||
|
grade="OK"
|
||||||
|
points=4.0
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- This is a normal (non-VTOL) landing.
|
||||||
|
|
||||||
|
if nL > 0 then
|
||||||
|
-- Larger deviations ==> "No grade" 2.0 points.
|
||||||
|
grade="--"
|
||||||
|
points=2.0
|
||||||
|
elseif nN> 0 then
|
||||||
|
-- No larger but average/normal deviations ==> "Fair Pass" Pass with average deviations and corrections.
|
||||||
|
grade="(OK)"
|
||||||
|
points=3.0
|
||||||
|
else
|
||||||
|
-- Only minor corrections ==> "Okay pass" 4.0 points.
|
||||||
|
grade="OK"
|
||||||
|
points=4.0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Replace" )"( and "__"
|
-- Replace" )"( and "__"
|
||||||
@@ -14957,7 +14991,7 @@ function AIRBOSS:SetSRSPilotVoice( Voice, Gender, Culture )
|
|||||||
self.PilotRadio.gender = Gender or "male"
|
self.PilotRadio.gender = Gender or "male"
|
||||||
self.PilotRadio.culture = Culture or "en-US"
|
self.PilotRadio.culture = Culture or "en-US"
|
||||||
|
|
||||||
if (not Voice) and self.SRS and self.SRS.google then
|
if (not Voice) and self.SRS and self.SRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J
|
self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -15606,6 +15640,11 @@ function AIRBOSS:_Number2Radio( radio, number, delay, interval, pilotcall )
|
|||||||
Sender = "PilotCall"
|
Sender = "PilotCall"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Sender=="" then
|
||||||
|
self:E( self.lid .. string.format( "ERROR: Sender unknown!") )
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Split string into characters.
|
-- Split string into characters.
|
||||||
local numbers = _split( number )
|
local numbers = _split( number )
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Armygroup).
|
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Armygroup).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
@@ -1860,6 +1860,7 @@ function ARMYGROUP:_UpdateEngageTarget()
|
|||||||
else
|
else
|
||||||
|
|
||||||
-- Could not get position of target (not alive any more?) ==> Disengage.
|
-- Could not get position of target (not alive any more?) ==> Disengage.
|
||||||
|
self:T(self.lid.."Could not get position of target ==> Disengage!")
|
||||||
self:Disengage()
|
self:Disengage()
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1867,6 +1868,7 @@ function ARMYGROUP:_UpdateEngageTarget()
|
|||||||
else
|
else
|
||||||
|
|
||||||
-- Target not alive any more ==> Disengage.
|
-- Target not alive any more ==> Disengage.
|
||||||
|
self:T(self.lid.."Target not ALIVE ==> Disengage!")
|
||||||
self:Disengage()
|
self:Disengage()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -434,6 +434,7 @@ _AUFTRAGSNR=0
|
|||||||
-- @field #string ARMORATTACK Armor attack.
|
-- @field #string ARMORATTACK Armor attack.
|
||||||
-- @field #string CASENHANCED Enhanced CAS.
|
-- @field #string CASENHANCED Enhanced CAS.
|
||||||
-- @field #string HOVER Hover.
|
-- @field #string HOVER Hover.
|
||||||
|
-- @field #string LANDATCOORDINATE Land at coordinate.
|
||||||
-- @field #string GROUNDATTACK Ground attack.
|
-- @field #string GROUNDATTACK Ground attack.
|
||||||
-- @field #string CARGOTRANSPORT Cargo transport.
|
-- @field #string CARGOTRANSPORT Cargo transport.
|
||||||
-- @field #string RELOCATECOHORT Relocate a cohort from one legion to another.
|
-- @field #string RELOCATECOHORT Relocate a cohort from one legion to another.
|
||||||
@@ -480,6 +481,7 @@ AUFTRAG.Type={
|
|||||||
ARMORATTACK="Armor Attack",
|
ARMORATTACK="Armor Attack",
|
||||||
CASENHANCED="CAS Enhanced",
|
CASENHANCED="CAS Enhanced",
|
||||||
HOVER="Hover",
|
HOVER="Hover",
|
||||||
|
LANDATCOORDINATE="Land at Coordinate",
|
||||||
GROUNDATTACK="Ground Attack",
|
GROUNDATTACK="Ground Attack",
|
||||||
CARGOTRANSPORT="Cargo Transport",
|
CARGOTRANSPORT="Cargo Transport",
|
||||||
RELOCATECOHORT="Relocate Cohort",
|
RELOCATECOHORT="Relocate Cohort",
|
||||||
@@ -1052,6 +1054,42 @@ function AUFTRAG:NewHOVER(Coordinate, Altitude, Time, Speed, MissionAlt)
|
|||||||
return mission
|
return mission
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- **[AIR ROTARY]** Create an LANDATCOORDINATE mission.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Where to land.
|
||||||
|
-- @param #number OuterRadius (Optional) Vary the coordinate by this many feet, e.g. get a new random coordinate between OuterRadius and (optionally) avoiding InnerRadius of the coordinate.
|
||||||
|
-- @param #number InnerRadius (Optional) Vary the coordinate by this many feet, e.g. get a new random coordinate between OuterRadius and (optionally) avoiding InnerRadius of the coordinate.
|
||||||
|
-- @param #number Time Time in seconds to stay. Default 300 seconds.
|
||||||
|
-- @param #number Speed Speed in knots to fly to the target coordinate. Default 150kn.
|
||||||
|
-- @param #number MissionAlt Altitude to fly towards the mission in feet AGL. Default 1000ft.
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:NewLANDATCOORDINATE(Coordinate, OuterRadius, InnerRadius, Time, Speed, MissionAlt)
|
||||||
|
|
||||||
|
local mission=AUFTRAG:New(AUFTRAG.Type.LANDATCOORDINATE)
|
||||||
|
|
||||||
|
mission:_TargetFromObject(Coordinate)
|
||||||
|
|
||||||
|
mission.stayTime = Time or 300
|
||||||
|
mission.stayAt = Coordinate
|
||||||
|
self:SetMissionSpeed(Speed or 150)
|
||||||
|
self:SetMissionAltitude(MissionAlt or 1000)
|
||||||
|
|
||||||
|
if OuterRadius then
|
||||||
|
mission.stayAt = Coordinate:GetRandomCoordinateInRadius(UTILS.FeetToMeters(OuterRadius),UTILS.FeetToMeters(InnerRadius or 0))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mission options:
|
||||||
|
mission.missionFraction=0.9
|
||||||
|
mission.optionROE=ENUMS.ROE.ReturnFire
|
||||||
|
mission.optionROT=ENUMS.ROT.PassiveDefense
|
||||||
|
|
||||||
|
mission.categories={AUFTRAG.Category.HELICOPTER}
|
||||||
|
|
||||||
|
mission.DCStask=mission:GetDCSMissionTask()
|
||||||
|
|
||||||
|
return mission
|
||||||
|
end
|
||||||
|
|
||||||
--- **[AIR]** Create an enhanced orbit race track mission. Planes will keep closer to the track.
|
--- **[AIR]** Create an enhanced orbit race track mission. Planes will keep closer to the track.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Core.Point#COORDINATE Coordinate Where to start the race track.
|
-- @param Core.Point#COORDINATE Coordinate Where to start the race track.
|
||||||
@@ -6443,7 +6481,19 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
param.missionAltitude = self.missionAltitude
|
param.missionAltitude = self.missionAltitude
|
||||||
|
|
||||||
DCStask.params=param
|
DCStask.params=param
|
||||||
|
|
||||||
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
|
elseif self.type==AUFTRAG.Type.LANDATCOORDINATE then
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
-- LANDATCOORDINATE Mission
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
local DCStask={}
|
||||||
|
local Vec2 = self.stayAt:GetVec2()
|
||||||
|
local DCStask = CONTROLLABLE.TaskLandAtVec2(nil,Vec2,self.stayTime)
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
elseif self.type==AUFTRAG.Type.ONGUARD or self.type==AUFTRAG.Type.ARMOREDGUARD then
|
elseif self.type==AUFTRAG.Type.ONGUARD or self.type==AUFTRAG.Type.ARMOREDGUARD then
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Awacs/).
|
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Awacs/).
|
||||||
--
|
--
|
||||||
-- ## Videos:
|
-- ## Videos:
|
||||||
--
|
--
|
||||||
-- Demo videos can be found on [Youtube](https://www.youtube.com/watch?v=ocdy8QzTNN4&list=PLFxp425SeXnq-oS0DSjam1HtddywH8i_k)
|
-- Demo videos can be found on [Youtube](https://www.youtube.com/watch?v=ocdy8QzTNN4&list=PLFxp425SeXnq-oS0DSjam1HtddywH8i_k)
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **applevangelist**
|
-- ### Author: **applevangelist**
|
||||||
-- @date Last Update July 2023
|
-- @date Last Update Jan 2024
|
||||||
-- @module Ops.AWACS
|
-- @module Ops.AWACS
|
||||||
-- @image OPS_AWACS.jpg
|
-- @image OPS_AWACS.jpg
|
||||||
|
|
||||||
@@ -121,6 +121,7 @@ do
|
|||||||
-- @field #number TacticalIncrFreq
|
-- @field #number TacticalIncrFreq
|
||||||
-- @field #number TacticalModulation
|
-- @field #number TacticalModulation
|
||||||
-- @field #number TacticalInterval
|
-- @field #number TacticalInterval
|
||||||
|
-- @field Core.Set#SET_GROUP DetectionSet
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
@@ -507,7 +508,7 @@ do
|
|||||||
-- @field #AWACS
|
-- @field #AWACS
|
||||||
AWACS = {
|
AWACS = {
|
||||||
ClassName = "AWACS", -- #string
|
ClassName = "AWACS", -- #string
|
||||||
version = "0.2.58", -- #string
|
version = "0.2.61", -- #string
|
||||||
lid = "", -- #string
|
lid = "", -- #string
|
||||||
coalition = coalition.side.BLUE, -- #number
|
coalition = coalition.side.BLUE, -- #number
|
||||||
coalitiontxt = "blue", -- #string
|
coalitiontxt = "blue", -- #string
|
||||||
@@ -603,6 +604,7 @@ AWACS = {
|
|||||||
TacticalIncrFreq = 0.5,
|
TacticalIncrFreq = 0.5,
|
||||||
TacticalModulation = radio.modulation.AM,
|
TacticalModulation = radio.modulation.AM,
|
||||||
TacticalInterval = 120,
|
TacticalInterval = 120,
|
||||||
|
DetectionSet = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1405,15 +1407,18 @@ function AWACS:SetTacticalRadios(BaseFreq,Increase,Modulation,Interval,Number)
|
|||||||
self.TacticalFrequencies[freq] = freq
|
self.TacticalFrequencies[freq] = freq
|
||||||
end
|
end
|
||||||
if self.AwacsSRS then
|
if self.AwacsSRS then
|
||||||
self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation,self.Volume)
|
self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation)
|
||||||
self.TacticalSRS:SetCoalition(self.coalition)
|
self.TacticalSRS:SetCoalition(self.coalition)
|
||||||
self.TacticalSRS:SetGender(self.Gender)
|
self.TacticalSRS:SetGender(self.Gender)
|
||||||
self.TacticalSRS:SetCulture(self.Culture)
|
self.TacticalSRS:SetCulture(self.Culture)
|
||||||
self.TacticalSRS:SetVoice(self.Voice)
|
self.TacticalSRS:SetVoice(self.Voice)
|
||||||
self.TacticalSRS:SetPort(self.Port)
|
self.TacticalSRS:SetPort(self.Port)
|
||||||
self.TacticalSRS:SetLabel("AWACS")
|
self.TacticalSRS:SetLabel("AWACS")
|
||||||
|
self.TacticalSRS:SetVolume(self.Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.TacticalSRS:SetGoogle(self.PathToGoogleKey)
|
--self.TacticalSRS:SetGoogle(self.PathToGoogleKey)
|
||||||
|
self.TacticalSRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.AccessKey)
|
||||||
|
self.TacticalSRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
self.TacticalSRSQ = MSRSQUEUE:New("Tactical AWACS")
|
self.TacticalSRSQ = MSRSQUEUE:New("Tactical AWACS")
|
||||||
end
|
end
|
||||||
@@ -2069,38 +2074,48 @@ function AWACS:AddGroupToDetection(Group)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Set AWACS SRS TTS details - see @{Sound.SRS} for details
|
--- [User] Set AWACS SRS TTS details - see @{Sound.SRS} for details. `SetSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #AWACS self
|
-- @param #AWACS self
|
||||||
-- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
-- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
-- @param #string Gender Defaults to "male"
|
-- @param #string Gender Defaults to "male"
|
||||||
-- @param #string Culture Defaults to "en-US"
|
-- @param #string Culture Defaults to "en-US"
|
||||||
-- @param #number Port Defaults to 5002
|
-- @param #number Port Defaults to 5002
|
||||||
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS#SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
||||||
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
||||||
-- @param #number Volume Volume - between 0.0 (silent) and 1.0 (loudest)
|
-- @param #number Volume Volume - between 0.0 (silent) and 1.0 (loudest)
|
||||||
-- @param #string PathToGoogleKey Path to your google key if you want to use google TTS
|
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS; if you use a config file for MSRS, hand in nil here.
|
||||||
|
-- @param #string AccessKey (Optional) Your Google API access key. This is necessary if DCS-gRPC is used as backend; if you use a config file for MSRS, hand in nil here.
|
||||||
-- @return #AWACS self
|
-- @return #AWACS self
|
||||||
function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
|
function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey)
|
||||||
self:T(self.lid.."SetSRS")
|
self:T(self.lid.."SetSRS")
|
||||||
self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
self.Gender = Gender or "male"
|
self.Gender = Gender or MSRS.gender or "male"
|
||||||
self.Culture = Culture or "en-US"
|
self.Culture = Culture or MSRS.culture or "en-US"
|
||||||
self.Port = Port or 5002
|
self.Port = Port or MSRS.port or 5002
|
||||||
self.Voice = Voice
|
self.Voice = Voice or MSRS.voice
|
||||||
self.PathToGoogleKey = PathToGoogleKey
|
self.PathToGoogleKey = PathToGoogleKey
|
||||||
|
self.AccessKey = AccessKey
|
||||||
self.Volume = Volume or 1.0
|
self.Volume = Volume or 1.0
|
||||||
|
|
||||||
self.AwacsSRS = MSRS:New(self.PathToSRS,self.MultiFrequency,self.MultiModulation,self.Volume)
|
self.AwacsSRS = MSRS:New(self.PathToSRS,self.MultiFrequency,self.MultiModulation)
|
||||||
self.AwacsSRS:SetCoalition(self.coalition)
|
self.AwacsSRS:SetCoalition(self.coalition)
|
||||||
self.AwacsSRS:SetGender(self.Gender)
|
self.AwacsSRS:SetGender(self.Gender)
|
||||||
self.AwacsSRS:SetCulture(self.Culture)
|
self.AwacsSRS:SetCulture(self.Culture)
|
||||||
self.AwacsSRS:SetVoice(self.Voice)
|
|
||||||
self.AwacsSRS:SetPort(self.Port)
|
self.AwacsSRS:SetPort(self.Port)
|
||||||
self.AwacsSRS:SetLabel("AWACS")
|
self.AwacsSRS:SetLabel("AWACS")
|
||||||
|
self.AwacsSRS:SetVolume(Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.AwacsSRS:SetGoogle(self.PathToGoogleKey)
|
--self.AwacsSRS:SetGoogle(self.PathToGoogleKey)
|
||||||
|
self.AwacsSRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.AccessKey)
|
||||||
|
self.AwacsSRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
|
-- Pre-configured Google?
|
||||||
|
if (not PathToGoogleKey) and self.AwacsSRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
|
self.PathToGoogleKey = MSRS.poptions.gcloud.credentials
|
||||||
|
self.Voice = Voice or MSRS.poptions.gcloud.voice
|
||||||
|
self.AccessKey = AccessKey or MSRS.poptions.gcloud.key
|
||||||
|
end
|
||||||
|
self.AwacsSRS:SetVoice(self.Voice)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2935,7 +2950,7 @@ function AWACS:_Picture(Group,IsGeneral)
|
|||||||
if not self.intel then
|
if not self.intel then
|
||||||
-- no intel yet!
|
-- no intel yet!
|
||||||
local picclean = self.gettext:GetEntry("PICCLEAN",self.locale)
|
local picclean = self.gettext:GetEntry("PICCLEAN",self.locale)
|
||||||
text = string.format(picclean,self.callsigntxt, gcallsign)
|
text = string.format(picclean,gcallsign,self.callsigntxt)
|
||||||
textScreen = text
|
textScreen = text
|
||||||
|
|
||||||
self:_NewRadioEntry(text,text,GID,false,true,true,false)
|
self:_NewRadioEntry(text,text,GID,false,true,true,false)
|
||||||
@@ -2988,7 +3003,10 @@ function AWACS:_Picture(Group,IsGeneral)
|
|||||||
|
|
||||||
if clustersAO == 0 and clustersEWR == 0 then
|
if clustersAO == 0 and clustersEWR == 0 then
|
||||||
-- clean
|
-- clean
|
||||||
self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false)
|
local picclean = self.gettext:GetEntry("PICCLEAN",self.locale)
|
||||||
|
text = string.format(picclean,gcallsign,self.callsigntxt)
|
||||||
|
textScreen = text
|
||||||
|
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
|
||||||
else
|
else
|
||||||
|
|
||||||
if clustersAO > 0 then
|
if clustersAO > 0 then
|
||||||
@@ -3663,7 +3681,7 @@ function AWACS:_CheckInAI(FlightGroup,Group,AuftragsNr)
|
|||||||
CAPVoice = self.CapVoices[math.floor(math.random(1,10))]
|
CAPVoice = self.CapVoices[math.floor(math.random(1,10))]
|
||||||
end
|
end
|
||||||
|
|
||||||
FlightGroup:SetSRS(self.PathToSRS,self.CAPGender,self.CAPCulture,CAPVoice,self.Port,self.PathToGoogleKey,"FLIGHT")
|
FlightGroup:SetSRS(self.PathToSRS,self.CAPGender,self.CAPCulture,CAPVoice,self.Port,self.PathToGoogleKey,"FLIGHT",1)
|
||||||
|
|
||||||
local checkai = self.gettext:GetEntry("CHECKINAI",self.locale)
|
local checkai = self.gettext:GetEntry("CHECKINAI",self.locale)
|
||||||
text = string.format(checkai,self.callsigntxt, managedgroup.CallSign, self.CAPTimeOnStation, self.AOName)
|
text = string.format(checkai,self.callsigntxt, managedgroup.CallSign, self.CAPTimeOnStation, self.AOName)
|
||||||
@@ -6595,7 +6613,7 @@ function AWACS:onafterCheckTacticalQueue(From,Event,To)
|
|||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
gtext = string.format("<speak><prosody rate='medium'>%s</prosody></speak>",gtext)
|
gtext = string.format("<speak><prosody rate='medium'>%s</prosody></speak>",gtext)
|
||||||
end
|
end
|
||||||
self.TacticalSRSQ:NewTransmission(gtext,nil,self.TacticalSRS,nil,0.5,nil,nil,nil,frequency,self.TacticalModulation,nil,nil,nil,nil,nil)
|
self.TacticalSRSQ:NewTransmission(gtext,nil,self.TacticalSRS,nil,0.5,nil,nil,nil,frequency,self.TacticalModulation)
|
||||||
|
|
||||||
self:T(RadioEntry.TextTTS)
|
self:T(RadioEntry.TextTTS)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Brigade).
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Brigade).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- ### [CSAR - Combat Search & Rescue](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20CSAR)
|
-- ### [CSAR - Combat Search & Rescue](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/CSAR)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
-- @image OPS_CSAR.jpg
|
-- @image OPS_CSAR.jpg
|
||||||
|
|
||||||
-- Date: May 2023
|
-- Date: May 2023
|
||||||
-- Last: Update Oct 2024
|
-- Last: Update Dec 2024
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||||
@@ -293,7 +293,7 @@ CSAR.AircraftType["Bronco-OV-10A"] = 2
|
|||||||
|
|
||||||
--- CSAR class version.
|
--- CSAR class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CSAR.version="1.0.18"
|
CSAR.version="1.0.19"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -536,6 +536,7 @@ function CSAR:New(Coalition, Template, Alias)
|
|||||||
-- @param #number Frequency Beacon frequency in kHz.
|
-- @param #number Frequency Beacon frequency in kHz.
|
||||||
-- @param #string Leadername Name of the #UNIT of the downed pilot.
|
-- @param #string Leadername Name of the #UNIT of the downed pilot.
|
||||||
-- @param #string CoordinatesText String of the position of the pilot. Format determined by self.coordtype.
|
-- @param #string CoordinatesText String of the position of the pilot. Format determined by self.coordtype.
|
||||||
|
-- @param #string Playername Player name if any given. Might be nil!
|
||||||
|
|
||||||
--- On After "Aproach" event. Heli close to downed Pilot.
|
--- On After "Aproach" event. Heli close to downed Pilot.
|
||||||
-- @function [parent=#CSAR] OnAfterApproach
|
-- @function [parent=#CSAR] OnAfterApproach
|
||||||
@@ -842,7 +843,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
|||||||
|
|
||||||
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet)
|
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet)
|
||||||
|
|
||||||
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
|
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage, _playerName) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1224,7 +1225,8 @@ end
|
|||||||
-- @param #string _GroupName Name of the Group
|
-- @param #string _GroupName Name of the Group
|
||||||
-- @param #number _freq Beacon frequency.
|
-- @param #number _freq Beacon frequency.
|
||||||
-- @param #boolean _nomessage Send message true or false.
|
-- @param #boolean _nomessage Send message true or false.
|
||||||
function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
|
-- @param #string _playername Name of the downed pilot if any
|
||||||
|
function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage, _playername)
|
||||||
self:T(self.lid .. " _InitSARForPilot")
|
self:T(self.lid .. " _InitSARForPilot")
|
||||||
local _leader = _downedGroup:GetUnit(1)
|
local _leader = _downedGroup:GetUnit(1)
|
||||||
local _groupName = _GroupName
|
local _groupName = _GroupName
|
||||||
@@ -1247,7 +1249,7 @@ function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- trigger FSM event
|
-- trigger FSM event
|
||||||
self:__PilotDown(2,_downedGroup, _freqk, _groupName, _coordinatesText)
|
self:__PilotDown(2,_downedGroup, _freqk, _groupName, _coordinatesText, _playername)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1923,7 +1925,7 @@ function CSAR:_DisplayToAllSAR(_message, _side, _messagetime)
|
|||||||
local messagetime = _messagetime or self.messageTime
|
local messagetime = _messagetime or self.messageTime
|
||||||
if self.msrs then
|
if self.msrs then
|
||||||
local voice = self.CSARVoice or MSRS.Voices.Google.Standard.en_GB_Standard_F
|
local voice = self.CSARVoice or MSRS.Voices.Google.Standard.en_GB_Standard_F
|
||||||
if self.msrs.google == nil then
|
if self.msrs:GetProvider() == MSRS.Provider.WINDOWS then
|
||||||
voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda
|
voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda
|
||||||
end
|
end
|
||||||
self:I("Voice = "..voice)
|
self:I("Voice = "..voice)
|
||||||
@@ -2310,7 +2312,8 @@ function CSAR:onafterStart(From, Event, To)
|
|||||||
self.msrs:SetVoice(self.SRSVoice)
|
self.msrs:SetVoice(self.SRSVoice)
|
||||||
self.msrs:SetGender(self.SRSGender)
|
self.msrs:SetGender(self.SRSGender)
|
||||||
if self.SRSGPathToCredentials then
|
if self.SRSGPathToCredentials then
|
||||||
self.msrs:SetGoogle(self.SRSGPathToCredentials)
|
self.msrs:SetProviderOptionsGoogle(self.SRSGPathToCredentials,self.SRSGPathToCredentials)
|
||||||
|
self.msrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
self.msrs:SetVolume(self.SRSVolume)
|
self.msrs:SetVolume(self.SRSVolume)
|
||||||
self.msrs:SetLabel("CSAR")
|
self.msrs:SetLabel("CSAR")
|
||||||
@@ -2542,8 +2545,9 @@ end
|
|||||||
-- @param #number Frequency Beacon frequency in kHz.
|
-- @param #number Frequency Beacon frequency in kHz.
|
||||||
-- @param #string Leadername Name of the #UNIT of the downed pilot.
|
-- @param #string Leadername Name of the #UNIT of the downed pilot.
|
||||||
-- @param #string CoordinatesText String of the position of the pilot. Format determined by self.coordtype.
|
-- @param #string CoordinatesText String of the position of the pilot. Format determined by self.coordtype.
|
||||||
function CSAR:onbeforePilotDown(From, Event, To, Group, Frequency, Leadername, CoordinatesText)
|
-- @param #string Playername Player name if any given. Might be nil!
|
||||||
self:T({From, Event, To, Group, Frequency, Leadername, CoordinatesText})
|
function CSAR:onbeforePilotDown(From, Event, To, Group, Frequency, Leadername, CoordinatesText, Playername)
|
||||||
|
self:T({From, Event, To, Group, Frequency, Leadername, CoordinatesText, tostring(Playername)})
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- ### [CTLD - Combat Troop & Logistics Deployment](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20CTLD)
|
-- ### [CTLD - Combat Troop & Logistics Deployment](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/CTLD)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
-- @module Ops.CTLD
|
-- @module Ops.CTLD
|
||||||
-- @image OPS_CTLD.jpg
|
-- @image OPS_CTLD.jpg
|
||||||
|
|
||||||
-- Last Update October 2023
|
-- Last Update December 2023
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|
||||||
@@ -741,7 +741,7 @@ do
|
|||||||
--
|
--
|
||||||
-- -- E.g. update unit capabilities for testing. Please stay realistic in your mission design.
|
-- -- E.g. update unit capabilities for testing. Please stay realistic in your mission design.
|
||||||
-- -- Make a Gazelle into a heavy truck, this type can load both crates and troops and eight of each type, up to 4000 kgs:
|
-- -- Make a Gazelle into a heavy truck, this type can load both crates and troops and eight of each type, up to 4000 kgs:
|
||||||
-- my_ctld:UnitCapabilities("SA342L", true, true, 8, 8, 12, 4000)
|
-- my_ctld:SetUnitCapabilities("SA342L", true, true, 8, 8, 12, 4000)
|
||||||
--
|
--
|
||||||
-- -- Default unit type capabilities are:
|
-- -- Default unit type capabilities are:
|
||||||
-- ["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
-- ["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
||||||
@@ -1200,14 +1200,14 @@ CTLD.CargoZoneType = {
|
|||||||
-- @field #CTLD_CARGO.Enum Type Type enumerator (for moves).
|
-- @field #CTLD_CARGO.Enum Type Type enumerator (for moves).
|
||||||
|
|
||||||
--- Unit capabilities.
|
--- Unit capabilities.
|
||||||
-- @type CTLD.UnitCapabilities
|
-- @type CTLD.UnitTypeCapabilities
|
||||||
-- @field #string type Unit type.
|
-- @field #string type Unit type.
|
||||||
-- @field #boolean crates Can transport crate.
|
-- @field #boolean crates Can transport crate.
|
||||||
-- @field #boolean troops Can transport troops.
|
-- @field #boolean troops Can transport troops.
|
||||||
-- @field #number cratelimit Number of crates transportable.
|
-- @field #number cratelimit Number of crates transportable.
|
||||||
-- @field #number trooplimit Number of troop units transportable.
|
-- @field #number trooplimit Number of troop units transportable.
|
||||||
-- @field #number cargoweightlimit Max loadable kgs of cargo.
|
-- @field #number cargoweightlimit Max loadable kgs of cargo.
|
||||||
CTLD.UnitTypes = {
|
CTLD.UnitTypeCapabilities = {
|
||||||
["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
||||||
["SA342L"] = {type="SA342L", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 12, cargoweightlimit = 400},
|
["SA342L"] = {type="SA342L", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 12, cargoweightlimit = 400},
|
||||||
["SA342M"] = {type="SA342M", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
["SA342M"] = {type="SA342M", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
|
||||||
@@ -1228,7 +1228,7 @@ CTLD.UnitTypes = {
|
|||||||
|
|
||||||
--- CTLD class version.
|
--- CTLD class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CTLD.version="1.0.41"
|
CTLD.version="1.0.45"
|
||||||
|
|
||||||
--- Instantiate a new CTLD.
|
--- Instantiate a new CTLD.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
@@ -1293,6 +1293,8 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
self:AddTransition("*", "CratesDropped", "*") -- CTLD deploy event.
|
self:AddTransition("*", "CratesDropped", "*") -- CTLD deploy event.
|
||||||
self:AddTransition("*", "CratesBuild", "*") -- CTLD build event.
|
self:AddTransition("*", "CratesBuild", "*") -- CTLD build event.
|
||||||
self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event.
|
self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event.
|
||||||
|
self:AddTransition("*", "CratesBuildStarted", "*") -- CTLD build event.
|
||||||
|
self:AddTransition("*", "CratesRepairStarted", "*") -- CTLD repair event.
|
||||||
self:AddTransition("*", "Load", "*") -- CTLD load event.
|
self:AddTransition("*", "Load", "*") -- CTLD load event.
|
||||||
self:AddTransition("*", "Save", "*") -- CTLD save event.
|
self:AddTransition("*", "Save", "*") -- CTLD save event.
|
||||||
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||||
@@ -1441,6 +1443,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop". Stops the CTLD and all its event handlers.
|
--- Triggers the FSM event "Stop". Stops the CTLD and all its event handlers.
|
||||||
|
-- @function [parent=#CTLD] Stop
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" after a delay. Stops the CTLD and all its event handlers.
|
--- Triggers the FSM event "Stop" after a delay. Stops the CTLD and all its event handlers.
|
||||||
@@ -1475,7 +1478,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
--- FSM Function OnBeforeTroopsPickedUp.
|
--- FSM Function OnBeforeTroopsPickedUp.
|
||||||
-- @function [parent=#CTLD] OnBeforeTroopsPickedUp
|
-- @function [parent=#CTLD] OnBeforeTroopsPickedUp
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param #string From State.
|
-- @param #string From State.
|
||||||
@@ -1627,6 +1630,46 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB build.
|
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB build.
|
||||||
-- @return #CTLD self
|
-- @return #CTLD self
|
||||||
|
|
||||||
|
--- FSM Function OnAfterCratesBuildStarted. Info event that a build has been started.
|
||||||
|
-- @function [parent=#CTLD] OnAfterCratesBuildStarted
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string From State.
|
||||||
|
-- @param #string Event Trigger.
|
||||||
|
-- @param #string To State.
|
||||||
|
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||||
|
-- @return #CTLD self
|
||||||
|
|
||||||
|
--- FSM Function OnAfterCratesRepairStarted. Info event that a repair has been started.
|
||||||
|
-- @function [parent=#CTLD] OnAfterCratesRepairStarted
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string From State.
|
||||||
|
-- @param #string Event Trigger.
|
||||||
|
-- @param #string To State.
|
||||||
|
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||||
|
-- @return #CTLD self
|
||||||
|
|
||||||
|
--- FSM Function OnBeforeCratesBuildStarted. Info event that a build has been started.
|
||||||
|
-- @function [parent=#CTLD] OnBeforeCratesBuildStarted
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string From State.
|
||||||
|
-- @param #string Event Trigger.
|
||||||
|
-- @param #string To State.
|
||||||
|
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||||
|
-- @return #CTLD self
|
||||||
|
|
||||||
|
--- FSM Function OnBeforeCratesRepairStarted. Info event that a repair has been started.
|
||||||
|
-- @function [parent=#CTLD] OnBeforeCratesRepairStarted
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string From State.
|
||||||
|
-- @param #string Event Trigger.
|
||||||
|
-- @param #string To State.
|
||||||
|
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||||
|
-- @return #CTLD self
|
||||||
|
|
||||||
--- FSM Function OnAfterCratesRepaired.
|
--- FSM Function OnAfterCratesRepaired.
|
||||||
-- @function [parent=#CTLD] OnAfterCratesRepaired
|
-- @function [parent=#CTLD] OnAfterCratesRepaired
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
@@ -1680,7 +1723,7 @@ function CTLD:_GetUnitCapabilities(Unit)
|
|||||||
self:T(self.lid .. " _GetUnitCapabilities")
|
self:T(self.lid .. " _GetUnitCapabilities")
|
||||||
local _unit = Unit -- Wrapper.Unit#UNIT
|
local _unit = Unit -- Wrapper.Unit#UNIT
|
||||||
local unittype = _unit:GetTypeName()
|
local unittype = _unit:GetTypeName()
|
||||||
local capabilities = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities
|
local capabilities = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
|
||||||
if not capabilities or capabilities == {} then
|
if not capabilities or capabilities == {} then
|
||||||
-- e.g. ["Ka-50"] = {type="Ka-50", crates=false, troops=false, cratelimit = 0, trooplimit = 0},
|
-- e.g. ["Ka-50"] = {type="Ka-50", crates=false, troops=false, cratelimit = 0, trooplimit = 0},
|
||||||
capabilities = {}
|
capabilities = {}
|
||||||
@@ -1701,7 +1744,7 @@ end
|
|||||||
function CTLD:_GenerateUHFrequencies()
|
function CTLD:_GenerateUHFrequencies()
|
||||||
self:T(self.lid .. " _GenerateUHFrequencies")
|
self:T(self.lid .. " _GenerateUHFrequencies")
|
||||||
self.FreeUHFFrequencies = {}
|
self.FreeUHFFrequencies = {}
|
||||||
self.FreeUHFFrequencies = UTILS.GenerateUHFrequencies()
|
self.FreeUHFFrequencies = UTILS.GenerateUHFrequencies(243,320)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1871,7 +1914,7 @@ function CTLD:_PreloadCrates(Group, Unit, Cargo, NumberOfCrates)
|
|||||||
local unitname = unit:GetName()
|
local unitname = unit:GetName()
|
||||||
-- see if this heli can load crates
|
-- see if this heli can load crates
|
||||||
local unittype = unit:GetTypeName()
|
local unittype = unit:GetTypeName()
|
||||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||||
local cancrates = capabilities.crates -- #boolean
|
local cancrates = capabilities.crates -- #boolean
|
||||||
local cratelimit = capabilities.cratelimit -- #number
|
local cratelimit = capabilities.cratelimit -- #number
|
||||||
if not cancrates then
|
if not cancrates then
|
||||||
@@ -2124,6 +2167,7 @@ function CTLD:_RepairObjectFromCrates(Group,Unit,Crates,Build,Number,Engineering
|
|||||||
desttimer:Start(self.repairtime - 1)
|
desttimer:Start(self.repairtime - 1)
|
||||||
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,object,true,NearestGroup:GetCoordinate())
|
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,object,true,NearestGroup:GetCoordinate())
|
||||||
buildtimer:Start(self.repairtime)
|
buildtimer:Start(self.repairtime)
|
||||||
|
self:__CratesRepairStarted(1,Group,Unit)
|
||||||
else
|
else
|
||||||
if not Engineering then
|
if not Engineering then
|
||||||
self:_SendMessage("Can't repair this unit with " .. build.Name, 10, false, Group)
|
self:_SendMessage("Can't repair this unit with " .. build.Name, 10, false, Group)
|
||||||
@@ -2308,7 +2352,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- avoid crate spam
|
-- avoid crate spam
|
||||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||||
local canloadcratesno = capabilities.cratelimit
|
local canloadcratesno = capabilities.cratelimit
|
||||||
local loaddist = self.CrateDistance or 35
|
local loaddist = self.CrateDistance or 35
|
||||||
local nearcrates, numbernearby = self:_FindCratesNearby(Group,Unit,loaddist,true)
|
local nearcrates, numbernearby = self:_FindCratesNearby(Group,Unit,loaddist,true)
|
||||||
@@ -2411,11 +2455,13 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
|
|||||||
realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,true,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],true,cargotype.PerCrateMass,nil,subcat)
|
realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,true,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],true,cargotype.PerCrateMass,nil,subcat)
|
||||||
table.insert(droppedcargo,realcargo)
|
table.insert(droppedcargo,realcargo)
|
||||||
else
|
else
|
||||||
realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,false,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],false,cargotype.PerCrateMass,nil,subcat)
|
realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,false,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],false,cargotype.PerCrateMass,nil,subcat)
|
||||||
Cargo:RemoveStock()
|
|
||||||
end
|
end
|
||||||
table.insert(self.Spawned_Cargo, realcargo)
|
table.insert(self.Spawned_Cargo, realcargo)
|
||||||
end
|
end
|
||||||
|
if not (drop or pack) then
|
||||||
|
Cargo:RemoveStock()
|
||||||
|
end
|
||||||
local text = string.format("Crates for %s have been positioned near you!",cratename)
|
local text = string.format("Crates for %s have been positioned near you!",cratename)
|
||||||
if drop then
|
if drop then
|
||||||
text = string.format("Crates for %s have been dropped!",cratename)
|
text = string.format("Crates for %s have been dropped!",cratename)
|
||||||
@@ -2518,6 +2564,40 @@ function CTLD:_ListCratesNearby( _group, _unit)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- (Internal) Function to find and Remove nearby crates.
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit
|
||||||
|
-- @return #CTLD self
|
||||||
|
function CTLD:_RemoveCratesNearby( _group, _unit)
|
||||||
|
self:T(self.lid .. " _RemoveCratesNearby")
|
||||||
|
local finddist = self.CrateDistance or 35
|
||||||
|
local crates,number = self:_FindCratesNearby(_group,_unit, finddist,true) -- #table
|
||||||
|
if number > 0 then
|
||||||
|
local text = REPORT:New("Removing Crates Found Nearby:")
|
||||||
|
text:Add("------------------------------------------------------------")
|
||||||
|
for _,_entry in pairs (crates) do
|
||||||
|
local entry = _entry -- #CTLD_CARGO
|
||||||
|
local name = entry:GetName() --#string
|
||||||
|
local dropped = entry:WasDropped()
|
||||||
|
if dropped then
|
||||||
|
text:Add(string.format("Crate for %s, %dkg removed",name, entry.PerCrateMass))
|
||||||
|
else
|
||||||
|
text:Add(string.format("Crate for %s, %dkg removed",name, entry.PerCrateMass))
|
||||||
|
end
|
||||||
|
entry:GetPositionable():Destroy(false)
|
||||||
|
end
|
||||||
|
if text:GetCount() == 1 then
|
||||||
|
text:Add(" N O N E")
|
||||||
|
end
|
||||||
|
text:Add("------------------------------------------------------------")
|
||||||
|
self:_SendMessage(text:Text(), 30, true, _group)
|
||||||
|
else
|
||||||
|
self:_SendMessage(string.format("No (loadable) crates within %d meters!",finddist), 10, false, _group)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Return distance in meters between two coordinates.
|
--- (Internal) Return distance in meters between two coordinates.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param Core.Point#COORDINATE _point1 Coordinate one
|
-- @param Core.Point#COORDINATE _point1 Coordinate one
|
||||||
@@ -2601,8 +2681,8 @@ function CTLD:_LoadCratesNearby(Group, Unit)
|
|||||||
local unitname = unit:GetName()
|
local unitname = unit:GetName()
|
||||||
-- see if this heli can load crates
|
-- see if this heli can load crates
|
||||||
local unittype = unit:GetTypeName()
|
local unittype = unit:GetTypeName()
|
||||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||||
--local capabilities = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities
|
--local capabilities = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
|
||||||
local cancrates = capabilities.crates -- #boolean
|
local cancrates = capabilities.crates -- #boolean
|
||||||
local cratelimit = capabilities.cratelimit -- #number
|
local cratelimit = capabilities.cratelimit -- #number
|
||||||
local grounded = not self:IsUnitInAir(Unit)
|
local grounded = not self:IsUnitInAir(Unit)
|
||||||
@@ -2753,7 +2833,7 @@ function CTLD:_GetMaxLoadableMass(Unit)
|
|||||||
if not Unit then return 0 end
|
if not Unit then return 0 end
|
||||||
local loadable = 0
|
local loadable = 0
|
||||||
local loadedmass = self:_GetUnitCargoMass(Unit)
|
local loadedmass = self:_GetUnitCargoMass(Unit)
|
||||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||||
local maxmass = capabilities.cargoweightlimit or 2000 -- max 2 tons
|
local maxmass = capabilities.cargoweightlimit or 2000 -- max 2 tons
|
||||||
loadable = maxmass - loadedmass
|
loadable = maxmass - loadedmass
|
||||||
return loadable
|
return loadable
|
||||||
@@ -2778,7 +2858,7 @@ function CTLD:_ListCargo(Group, Unit)
|
|||||||
self:T(self.lid .. " _ListCargo")
|
self:T(self.lid .. " _ListCargo")
|
||||||
local unitname = Unit:GetName()
|
local unitname = Unit:GetName()
|
||||||
local unittype = Unit:GetTypeName()
|
local unittype = Unit:GetTypeName()
|
||||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||||
local trooplimit = capabilities.trooplimit -- #boolean
|
local trooplimit = capabilities.trooplimit -- #boolean
|
||||||
local cratelimit = capabilities.cratelimit -- #number
|
local cratelimit = capabilities.cratelimit -- #number
|
||||||
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
|
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
|
||||||
@@ -2933,6 +3013,35 @@ function CTLD:IsHercules(Unit)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- (Internal) Function to set troops positions of a template to a nice circle
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Start coordinate to use
|
||||||
|
-- @param #number Radius Radius to be used
|
||||||
|
-- @param #number Heading Heading starting with
|
||||||
|
-- @param #string Template The group template name
|
||||||
|
-- @return #table Positions The positions table
|
||||||
|
function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template)
|
||||||
|
local Positions = {}
|
||||||
|
local template = _DATABASE:GetGroupTemplate(Template)
|
||||||
|
UTILS.PrintTableToLog(template)
|
||||||
|
local numbertroops = #template.units
|
||||||
|
local newcenter = Coordinate:Translate(Radius,((Heading+270)%360))
|
||||||
|
for i=1,360,math.floor(360/numbertroops) do
|
||||||
|
local phead = ((Heading+270+i)%360)
|
||||||
|
local post = newcenter:Translate(Radius,phead)
|
||||||
|
local pos1 = post:GetVec2()
|
||||||
|
local p1t = {
|
||||||
|
x = pos1.x,
|
||||||
|
y = pos1.y,
|
||||||
|
heading = phead,
|
||||||
|
}
|
||||||
|
table.insert(Positions,p1t)
|
||||||
|
end
|
||||||
|
UTILS.PrintTableToLog(Positions)
|
||||||
|
return Positions
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Function to unload troops from heli.
|
--- (Internal) Function to unload troops from heli.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param Wrapper.Group#GROUP Group
|
-- @param Wrapper.Group#GROUP Group
|
||||||
@@ -2984,14 +3093,29 @@ function CTLD:_UnloadTroops(Group, Unit)
|
|||||||
zoneradius = Unit:GetVelocityMPS() or 100
|
zoneradius = Unit:GetVelocityMPS() or 100
|
||||||
end
|
end
|
||||||
local zone = ZONE_GROUP:New(string.format("Unload zone-%s",unitname),Group,zoneradius*factor)
|
local zone = ZONE_GROUP:New(string.format("Unload zone-%s",unitname),Group,zoneradius*factor)
|
||||||
local randomcoord = zone:GetRandomCoordinate(10,30*factor):GetVec2()
|
local randomcoord = zone:GetRandomCoordinate(10,30*factor) --:GetVec2()
|
||||||
|
local heading = Group:GetHeading() or 0
|
||||||
|
-- Spawn troops left from us, closer when hovering, further off when landed
|
||||||
|
if hoverunload or grounded then
|
||||||
|
randomcoord = Group:GetCoordinate()
|
||||||
|
-- slightly left from us
|
||||||
|
local Angle = (heading+270)%360
|
||||||
|
local offset = hoverunload and 1.5 or 5
|
||||||
|
randomcoord:Translate(offset,Angle,nil,true)
|
||||||
|
end
|
||||||
|
local tempcount = 0
|
||||||
for _,_template in pairs(temptable) do
|
for _,_template in pairs(temptable) do
|
||||||
self.TroopCounter = self.TroopCounter + 1
|
self.TroopCounter = self.TroopCounter + 1
|
||||||
|
tempcount = tempcount+1
|
||||||
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
||||||
|
local rad = 2.5+tempcount
|
||||||
|
local Positions = self:_GetUnitPositions(randomcoord,rad,heading,_template)
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||||
:InitRandomizeUnits(true,20,2)
|
--:InitRandomizeUnits(true,20,2)
|
||||||
|
--:InitHeading(heading)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
:SpawnFromVec2(randomcoord)
|
:InitSetUnitAbsolutePositions(Positions)
|
||||||
|
:SpawnFromVec2(randomcoord:GetVec2())
|
||||||
self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter],type)
|
self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter],type)
|
||||||
end -- template loop
|
end -- template loop
|
||||||
cargo:SetWasDropped(true)
|
cargo:SetWasDropped(true)
|
||||||
@@ -3226,6 +3350,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering)
|
|||||||
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate())
|
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate())
|
||||||
buildtimer:Start(self.buildtime)
|
buildtimer:Start(self.buildtime)
|
||||||
self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group)
|
self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group)
|
||||||
|
self:__CratesBuildStarted(1,Group,Unit)
|
||||||
else
|
else
|
||||||
self:_BuildObjectFromCrates(Group,Unit,build)
|
self:_BuildObjectFromCrates(Group,Unit,build)
|
||||||
end
|
end
|
||||||
@@ -3536,13 +3661,19 @@ function CTLD:_RefreshF10Menus()
|
|||||||
if _group then
|
if _group then
|
||||||
-- get chopper capabilities
|
-- get chopper capabilities
|
||||||
local unittype = _unit:GetTypeName()
|
local unittype = _unit:GetTypeName()
|
||||||
local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitCapabilities
|
local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitTypeCapabilities
|
||||||
local cantroops = capabilities.troops
|
local cantroops = capabilities.troops
|
||||||
local cancrates = capabilities.crates
|
local cancrates = capabilities.crates
|
||||||
-- top menu
|
-- top menu
|
||||||
local topmenu = MENU_GROUP:New(_group,"CTLD",nil)
|
local topmenu = MENU_GROUP:New(_group,"CTLD",nil)
|
||||||
local toptroops = MENU_GROUP:New(_group,"Manage Troops",topmenu)
|
local toptroops = nil
|
||||||
local topcrates = MENU_GROUP:New(_group,"Manage Crates",topmenu)
|
local topcrates = nil
|
||||||
|
if cantroops then
|
||||||
|
toptroops = MENU_GROUP:New(_group,"Manage Troops",topmenu)
|
||||||
|
end
|
||||||
|
if cancrates then
|
||||||
|
topcrates = MENU_GROUP:New(_group,"Manage Crates",topmenu)
|
||||||
|
end
|
||||||
local listmenu = MENU_GROUP_COMMAND:New(_group,"List boarded cargo",topmenu, self._ListCargo, self, _group, _unit)
|
local listmenu = MENU_GROUP_COMMAND:New(_group,"List boarded cargo",topmenu, self._ListCargo, self, _group, _unit)
|
||||||
local invtry = MENU_GROUP_COMMAND:New(_group,"Inventory",topmenu, self._ListInventory, self, _group, _unit)
|
local invtry = MENU_GROUP_COMMAND:New(_group,"Inventory",topmenu, self._ListInventory, self, _group, _unit)
|
||||||
local rbcns = MENU_GROUP_COMMAND:New(_group,"List active zone beacons",topmenu, self._ListRadioBeacons, self, _group, _unit)
|
local rbcns = MENU_GROUP_COMMAND:New(_group,"List active zone beacons",topmenu, self._ListRadioBeacons, self, _group, _unit)
|
||||||
@@ -3587,6 +3718,7 @@ function CTLD:_RefreshF10Menus()
|
|||||||
local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit)
|
local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit)
|
||||||
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
|
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
|
||||||
local packmenu = MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
|
local packmenu = MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
|
||||||
|
local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates)
|
||||||
|
|
||||||
if self.usesubcats then
|
if self.usesubcats then
|
||||||
local subcatmenus = {}
|
local subcatmenus = {}
|
||||||
@@ -3622,6 +3754,7 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit)
|
listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit)
|
||||||
|
removecrates = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu, self._RemoveCratesNearby, self, _group, _unit)
|
||||||
local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit)
|
local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit)
|
||||||
if not self.nobuildmenu then
|
if not self.nobuildmenu then
|
||||||
local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit)
|
local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit)
|
||||||
@@ -3694,7 +3827,7 @@ end
|
|||||||
-- @param #CTLD_CARGO.Enum Type Type of cargo. I.e. VEHICLE or FOB. VEHICLE will move to destination zones when dropped/build, FOB stays put.
|
-- @param #CTLD_CARGO.Enum Type Type of cargo. I.e. VEHICLE or FOB. VEHICLE will move to destination zones when dropped/build, FOB stays put.
|
||||||
-- @param #number NoCrates Number of crates needed to build this cargo.
|
-- @param #number NoCrates Number of crates needed to build this cargo.
|
||||||
-- @param #number PerCrateMass Mass in kg of each crate
|
-- @param #number PerCrateMass Mass in kg of each crate
|
||||||
-- @param #number Stock Number of groups in stock. Nil for unlimited.
|
-- @param #number Stock Number of buildable groups in stock. Nil for unlimited.
|
||||||
-- @param #string SubCategory Name of sub-category (optional).
|
-- @param #string SubCategory Name of sub-category (optional).
|
||||||
function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory)
|
function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory)
|
||||||
self:T(self.lid .. " AddCratesCargo")
|
self:T(self.lid .. " AddCratesCargo")
|
||||||
@@ -4339,7 +4472,7 @@ end
|
|||||||
-- @param #number Trooplimit Unit can carry number of troops. Default 0.
|
-- @param #number Trooplimit Unit can carry number of troops. Default 0.
|
||||||
-- @param #number Length Unit lenght (in metres) for the load radius. Default 20.
|
-- @param #number Length Unit lenght (in metres) for the load radius. Default 20.
|
||||||
-- @param #number Maxcargoweight Maxmimum weight in kgs this helo can carry. Default 500.
|
-- @param #number Maxcargoweight Maxmimum weight in kgs this helo can carry. Default 500.
|
||||||
function CTLD:UnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
|
function CTLD:SetUnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
|
||||||
self:T(self.lid .. " UnitCapabilities")
|
self:T(self.lid .. " UnitCapabilities")
|
||||||
local unittype = nil
|
local unittype = nil
|
||||||
local unit = nil
|
local unit = nil
|
||||||
@@ -4353,13 +4486,13 @@ end
|
|||||||
end
|
end
|
||||||
local length = 20
|
local length = 20
|
||||||
local maxcargo = 500
|
local maxcargo = 500
|
||||||
local existingcaps = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities
|
local existingcaps = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
|
||||||
if existingcaps then
|
if existingcaps then
|
||||||
length = existingcaps.length or 20
|
length = existingcaps.length or 20
|
||||||
maxcargo = existingcaps.cargoweightlimit or 500
|
maxcargo = existingcaps.cargoweightlimit or 500
|
||||||
end
|
end
|
||||||
-- set capabilities
|
-- set capabilities
|
||||||
local capabilities = {} -- #CTLD.UnitCapabilities
|
local capabilities = {} -- #CTLD.UnitTypeCapabilities
|
||||||
capabilities.type = unittype
|
capabilities.type = unittype
|
||||||
capabilities.crates = Cancrates or false
|
capabilities.crates = Cancrates or false
|
||||||
capabilities.troops = Cantroops or false
|
capabilities.troops = Cantroops or false
|
||||||
@@ -4367,10 +4500,26 @@ end
|
|||||||
capabilities.trooplimit = Trooplimit or 0
|
capabilities.trooplimit = Trooplimit or 0
|
||||||
capabilities.length = Length or length
|
capabilities.length = Length or length
|
||||||
capabilities.cargoweightlimit = Maxcargoweight or maxcargo
|
capabilities.cargoweightlimit = Maxcargoweight or maxcargo
|
||||||
self.UnitTypes[unittype] = capabilities
|
self.UnitTypeCapabilities[unittype] = capabilities
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [Deprecated] - Function to add/adjust unittype capabilities. Has been replaced with `SetUnitCapabilities()` - pls use the new one going forward!
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string Unittype The unittype to adjust. If passed as Wrapper.Unit#UNIT, it will search for the unit in the mission.
|
||||||
|
-- @param #boolean Cancrates Unit can load crates. Default false.
|
||||||
|
-- @param #boolean Cantroops Unit can load troops. Default false.
|
||||||
|
-- @param #number Cratelimit Unit can carry number of crates. Default 0.
|
||||||
|
-- @param #number Trooplimit Unit can carry number of troops. Default 0.
|
||||||
|
-- @param #number Length Unit lenght (in metres) for the load radius. Default 20.
|
||||||
|
-- @param #number Maxcargoweight Maxmimum weight in kgs this helo can carry. Default 500.
|
||||||
|
function CTLD:UnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
|
||||||
|
self:I(self.lid.."This function been replaced with `SetUnitCapabilities()` - pls use the new one going forward!")
|
||||||
|
self:SetUnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- (Internal) Check if a unit is hovering *in parameters*.
|
--- (Internal) Check if a unit is hovering *in parameters*.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param Wrapper.Unit#UNIT Unit
|
-- @param Wrapper.Unit#UNIT Unit
|
||||||
@@ -4523,7 +4672,7 @@ end
|
|||||||
local unittype = Unit:GetTypeName()
|
local unittype = Unit:GetTypeName()
|
||||||
local unitname = Unit:GetName()
|
local unitname = Unit:GetName()
|
||||||
local Group = Unit:GetGroup()
|
local Group = Unit:GetGroup()
|
||||||
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities
|
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
|
||||||
local cancrates = capabilities.crates -- #boolean
|
local cancrates = capabilities.crates -- #boolean
|
||||||
local cratelimit = capabilities.cratelimit -- #number
|
local cratelimit = capabilities.cratelimit -- #number
|
||||||
if cancrates then
|
if cancrates then
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
-- @field Ops.Commander#COMMANDER commander Commander of assigned legions.
|
-- @field Ops.Commander#COMMANDER commander Commander of assigned legions.
|
||||||
-- @field #number Nsuccess Number of successful missions.
|
-- @field #number Nsuccess Number of successful missions.
|
||||||
-- @field #number Nfailure Number of failed mission.
|
-- @field #number Nfailure Number of failed mission.
|
||||||
-- @extends Ops.Intelligence#INTEL
|
-- @extends Ops.Intel#INTEL
|
||||||
|
|
||||||
--- *In preparing for battle I have always found that plans are useless, but planning is indispensable* -- Dwight D Eisenhower
|
--- *In preparing for battle I have always found that plans are useless, but planning is indispensable* -- Dwight D Eisenhower
|
||||||
--
|
--
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
-- When the chief detects a valid target, he will launch a certain number of selected assets. Only whole groups from SQUADRONs, PLATOONs or FLOTILLAs can be selected.
|
-- When the chief detects a valid target, he will launch a certain number of selected assets. Only whole groups from SQUADRONs, PLATOONs or FLOTILLAs can be selected.
|
||||||
-- In other words, it is not possible to specify the abount of individual *units*.
|
-- In other words, it is not possible to specify the abount of individual *units*.
|
||||||
--
|
--
|
||||||
-- By default, one group is selected for any detected target. This can, however, be customized with the @{CHIEF.SetResponseOnTarget}() function. The number of min and max
|
-- By default, one group is selected for any detected target. This can, however, be customized with the @{#CHIEF.SetResponseOnTarget}() function. The number of min and max
|
||||||
-- asset groups can be specified depending on threatlevel, category, mission type, number of units, defcon and strategy.
|
-- asset groups can be specified depending on threatlevel, category, mission type, number of units, defcon and strategy.
|
||||||
--
|
--
|
||||||
-- For example:
|
-- For example:
|
||||||
@@ -311,7 +311,7 @@ CHIEF.Strategy = {
|
|||||||
|
|
||||||
--- Resource list.
|
--- Resource list.
|
||||||
-- @type CHIEF.Resources
|
-- @type CHIEF.Resources
|
||||||
-- @field <#CHIEF.Resource> List of resources.
|
-- @field #CHIEF.Resource List of resources.
|
||||||
|
|
||||||
--- Resource.
|
--- Resource.
|
||||||
-- @type CHIEF.Resource
|
-- @type CHIEF.Resource
|
||||||
@@ -1096,7 +1096,7 @@ end
|
|||||||
|
|
||||||
--- Add an AIRWING to the chief's commander.
|
--- Add an AIRWING to the chief's commander.
|
||||||
-- @param #CHIEF self
|
-- @param #CHIEF self
|
||||||
-- @param Ops.AirWing#AIRWING Airwing The airwing to add.
|
-- @param Ops.Airwing#AIRWING Airwing The airwing to add.
|
||||||
-- @return #CHIEF self
|
-- @return #CHIEF self
|
||||||
function CHIEF:AddAirwing(Airwing)
|
function CHIEF:AddAirwing(Airwing)
|
||||||
|
|
||||||
@@ -1460,7 +1460,7 @@ end
|
|||||||
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
||||||
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
||||||
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
||||||
-- @return Ops.AirWing#AIRWING.PatrolZone The CAP zone data.
|
-- @return Ops.Airwing#AIRWING.PatrolZone The CAP zone data.
|
||||||
function CHIEF:AddCapZone(Zone, Altitude, Speed, Heading, Leg)
|
function CHIEF:AddCapZone(Zone, Altitude, Speed, Heading, Leg)
|
||||||
|
|
||||||
-- Hand over to commander.
|
-- Hand over to commander.
|
||||||
@@ -1476,7 +1476,7 @@ end
|
|||||||
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
||||||
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
||||||
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
||||||
-- @return Ops.AirWing#AIRWING.PatrolZone The CAP zone data.
|
-- @return Ops.Airwing#AIRWING.PatrolZone The CAP zone data.
|
||||||
function CHIEF:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
|
function CHIEF:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
|
||||||
|
|
||||||
-- Hand over to commander.
|
-- Hand over to commander.
|
||||||
@@ -1503,7 +1503,7 @@ end
|
|||||||
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
||||||
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
||||||
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
||||||
-- @return Ops.AirWing#AIRWING.PatrolZone The AWACS zone data.
|
-- @return Ops.Airwing#AIRWING.PatrolZone The AWACS zone data.
|
||||||
function CHIEF:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
|
function CHIEF:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
|
||||||
|
|
||||||
-- Hand over to commander.
|
-- Hand over to commander.
|
||||||
@@ -1531,7 +1531,7 @@ end
|
|||||||
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
||||||
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
||||||
-- @param #number RefuelSystem Refuelling system.
|
-- @param #number RefuelSystem Refuelling system.
|
||||||
-- @return Ops.AirWing#AIRWING.TankerZone The tanker zone data.
|
-- @return Ops.Airwing#AIRWING.TankerZone The tanker zone data.
|
||||||
function CHIEF:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSystem)
|
function CHIEF:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSystem)
|
||||||
|
|
||||||
-- Hand over to commander.
|
-- Hand over to commander.
|
||||||
@@ -1785,7 +1785,7 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Clean up missions where the contact was lost.
|
-- Clean up missions where the contact was lost.
|
||||||
for _,_contact in pairs(self.ContactsLost) do
|
for _,_contact in pairs(self.ContactsLost) do
|
||||||
local contact=_contact --Ops.Intelligence#INTEL.Contact
|
local contact=_contact --Ops.Intel#INTEL.Contact
|
||||||
|
|
||||||
if contact.mission and contact.mission:IsNotOver() then
|
if contact.mission and contact.mission:IsNotOver() then
|
||||||
|
|
||||||
@@ -1813,7 +1813,7 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
-- Create TARGETs for all new contacts.
|
-- Create TARGETs for all new contacts.
|
||||||
self.Nborder=0 ; self.Nconflict=0 ; self.Nattack=0
|
self.Nborder=0 ; self.Nconflict=0 ; self.Nattack=0
|
||||||
for _,_contact in pairs(self.Contacts) do
|
for _,_contact in pairs(self.Contacts) do
|
||||||
local contact=_contact --Ops.Intelligence#INTEL.Contact
|
local contact=_contact --Ops.Intel#INTEL.Contact
|
||||||
local group=contact.group --Wrapper.Group#GROUP
|
local group=contact.group --Wrapper.Group#GROUP
|
||||||
|
|
||||||
-- Check if contact inside of our borders.
|
-- Check if contact inside of our borders.
|
||||||
@@ -1964,7 +1964,7 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
if self.verbose>=2 and #self.Contacts>0 then
|
if self.verbose>=2 and #self.Contacts>0 then
|
||||||
local text="Contacts:"
|
local text="Contacts:"
|
||||||
for i,_contact in pairs(self.Contacts) do
|
for i,_contact in pairs(self.Contacts) do
|
||||||
local contact=_contact --Ops.Intelligence#INTEL.Contact
|
local contact=_contact --Ops.Intel#INTEL.Contact
|
||||||
|
|
||||||
local mtext="N/A"
|
local mtext="N/A"
|
||||||
if contact.mission then
|
if contact.mission then
|
||||||
|
|||||||
@@ -420,7 +420,7 @@ end
|
|||||||
|
|
||||||
--- Add an AIRWING to the commander.
|
--- Add an AIRWING to the commander.
|
||||||
-- @param #COMMANDER self
|
-- @param #COMMANDER self
|
||||||
-- @param Ops.AirWing#AIRWING Airwing The airwing to add.
|
-- @param Ops.Airwing#AIRWING Airwing The airwing to add.
|
||||||
-- @return #COMMANDER self
|
-- @return #COMMANDER self
|
||||||
function COMMANDER:AddAirwing(Airwing)
|
function COMMANDER:AddAirwing(Airwing)
|
||||||
|
|
||||||
@@ -667,10 +667,10 @@ end
|
|||||||
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
||||||
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
||||||
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
||||||
-- @return Ops.AirWing#AIRWING.PatrolZone The CAP zone data.
|
-- @return Ops.Airwing#AIRWING.PatrolZone The CAP zone data.
|
||||||
function COMMANDER:AddCapZone(Zone, Altitude, Speed, Heading, Leg)
|
function COMMANDER:AddCapZone(Zone, Altitude, Speed, Heading, Leg)
|
||||||
|
|
||||||
local patrolzone={} --Ops.AirWing#AIRWING.PatrolZone
|
local patrolzone={} --Ops.Airwing#AIRWING.PatrolZone
|
||||||
|
|
||||||
patrolzone.zone=Zone
|
patrolzone.zone=Zone
|
||||||
patrolzone.altitude=Altitude or 12000
|
patrolzone.altitude=Altitude or 12000
|
||||||
@@ -692,10 +692,10 @@ end
|
|||||||
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
||||||
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
||||||
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
||||||
-- @return Ops.AirWing#AIRWING.PatrolZone The CAP zone data.
|
-- @return Ops.Airwing#AIRWING.PatrolZone The CAP zone data.
|
||||||
function COMMANDER:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
|
function COMMANDER:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg)
|
||||||
|
|
||||||
local patrolzone={} --Ops.AirWing#AIRWING.PatrolZone
|
local patrolzone={} --Ops.Airwing#AIRWING.PatrolZone
|
||||||
|
|
||||||
patrolzone.zone=Zone
|
patrolzone.zone=Zone
|
||||||
patrolzone.altitude=Altitude or 12000
|
patrolzone.altitude=Altitude or 12000
|
||||||
@@ -715,7 +715,7 @@ end
|
|||||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||||
function COMMANDER:RemoveGciCapZone(Zone)
|
function COMMANDER:RemoveGciCapZone(Zone)
|
||||||
|
|
||||||
local patrolzone={} --Ops.AirWing#AIRWING.PatrolZone
|
local patrolzone={} --Ops.Airwing#AIRWING.PatrolZone
|
||||||
|
|
||||||
patrolzone.zone=Zone
|
patrolzone.zone=Zone
|
||||||
for i,_patrolzone in pairs(self.gcicapZones) do
|
for i,_patrolzone in pairs(self.gcicapZones) do
|
||||||
@@ -737,10 +737,10 @@ end
|
|||||||
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
-- @param #number Speed Orbit speed in KIAS. Default 350 kts.
|
||||||
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
||||||
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
||||||
-- @return Ops.AirWing#AIRWING.PatrolZone The AWACS zone data.
|
-- @return Ops.Airwing#AIRWING.PatrolZone The AWACS zone data.
|
||||||
function COMMANDER:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
|
function COMMANDER:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg)
|
||||||
|
|
||||||
local awacszone={} --Ops.AirWing#AIRWING.PatrolZone
|
local awacszone={} --Ops.Airwing#AIRWING.PatrolZone
|
||||||
|
|
||||||
awacszone.zone=Zone
|
awacszone.zone=Zone
|
||||||
awacszone.altitude=Altitude or 12000
|
awacszone.altitude=Altitude or 12000
|
||||||
@@ -760,7 +760,7 @@ end
|
|||||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||||
function COMMANDER:RemoveAwacsZone(Zone)
|
function COMMANDER:RemoveAwacsZone(Zone)
|
||||||
|
|
||||||
local awacszone={} --Ops.AirWing#AIRWING.PatrolZone
|
local awacszone={} --Ops.Airwing#AIRWING.PatrolZone
|
||||||
|
|
||||||
awacszone.zone=Zone
|
awacszone.zone=Zone
|
||||||
for i,_awacszone in pairs(self.awacsZones) do
|
for i,_awacszone in pairs(self.awacsZones) do
|
||||||
@@ -783,10 +783,10 @@ end
|
|||||||
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
|
||||||
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
-- @param #number Leg Length of race-track in NM. Default 30 NM.
|
||||||
-- @param #number RefuelSystem Refuelling system.
|
-- @param #number RefuelSystem Refuelling system.
|
||||||
-- @return Ops.AirWing#AIRWING.TankerZone The tanker zone data.
|
-- @return Ops.Airwing#AIRWING.TankerZone The tanker zone data.
|
||||||
function COMMANDER:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSystem)
|
function COMMANDER:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSystem)
|
||||||
|
|
||||||
local tankerzone={} --Ops.AirWing#AIRWING.TankerZone
|
local tankerzone={} --Ops.Airwing#AIRWING.TankerZone
|
||||||
|
|
||||||
tankerzone.zone=Zone
|
tankerzone.zone=Zone
|
||||||
tankerzone.altitude=Altitude or 12000
|
tankerzone.altitude=Altitude or 12000
|
||||||
@@ -807,7 +807,7 @@ end
|
|||||||
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
-- @param Core.Zone#ZONE Zone Zone, where the flight orbits.
|
||||||
function COMMANDER:RemoveTankerZone(Zone)
|
function COMMANDER:RemoveTankerZone(Zone)
|
||||||
|
|
||||||
local tankerzone={} --Ops.AirWing#AIRWING.PatrolZone
|
local tankerzone={} --Ops.Airwing#AIRWING.PatrolZone
|
||||||
|
|
||||||
tankerzone.zone=Zone
|
tankerzone.zone=Zone
|
||||||
for i,_tankerzone in pairs(self.tankerZones) do
|
for i,_tankerzone in pairs(self.tankerZones) do
|
||||||
@@ -997,7 +997,7 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Check CAP zones.
|
-- Check CAP zones.
|
||||||
for _,_patrolzone in pairs(self.capZones) do
|
for _,_patrolzone in pairs(self.capZones) do
|
||||||
local patrolzone=_patrolzone --Ops.AirWing#AIRWING.PatrolZone
|
local patrolzone=_patrolzone --Ops.Airwing#AIRWING.PatrolZone
|
||||||
-- Check if mission is nil or over.
|
-- Check if mission is nil or over.
|
||||||
if (not patrolzone.mission) or patrolzone.mission:IsOver() then
|
if (not patrolzone.mission) or patrolzone.mission:IsOver() then
|
||||||
local Coordinate=patrolzone.zone:GetCoordinate()
|
local Coordinate=patrolzone.zone:GetCoordinate()
|
||||||
@@ -1008,7 +1008,7 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Check GCICAP zones.
|
-- Check GCICAP zones.
|
||||||
for _,_patrolzone in pairs(self.gcicapZones) do
|
for _,_patrolzone in pairs(self.gcicapZones) do
|
||||||
local patrolzone=_patrolzone --Ops.AirWing#AIRWING.PatrolZone
|
local patrolzone=_patrolzone --Ops.Airwing#AIRWING.PatrolZone
|
||||||
-- Check if mission is nil or over.
|
-- Check if mission is nil or over.
|
||||||
if (not patrolzone.mission) or patrolzone.mission:IsOver() then
|
if (not patrolzone.mission) or patrolzone.mission:IsOver() then
|
||||||
local Coordinate=patrolzone.zone:GetCoordinate()
|
local Coordinate=patrolzone.zone:GetCoordinate()
|
||||||
@@ -1019,7 +1019,7 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Check AWACS zones.
|
-- Check AWACS zones.
|
||||||
for _,_awacszone in pairs(self.awacsZones) do
|
for _,_awacszone in pairs(self.awacsZones) do
|
||||||
local awacszone=_awacszone --Ops.AirWing#AIRWING.Patrol
|
local awacszone=_awacszone --Ops.Airwing#AIRWING.Patrol
|
||||||
-- Check if mission is nil or over.
|
-- Check if mission is nil or over.
|
||||||
if (not awacszone.mission) or awacszone.mission:IsOver() then
|
if (not awacszone.mission) or awacszone.mission:IsOver() then
|
||||||
local Coordinate=awacszone.zone:GetCoordinate()
|
local Coordinate=awacszone.zone:GetCoordinate()
|
||||||
@@ -1030,7 +1030,7 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Check Tanker zones.
|
-- Check Tanker zones.
|
||||||
for _,_tankerzone in pairs(self.tankerZones) do
|
for _,_tankerzone in pairs(self.tankerZones) do
|
||||||
local tankerzone=_tankerzone --Ops.AirWing#AIRWING.TankerZone
|
local tankerzone=_tankerzone --Ops.Airwing#AIRWING.TankerZone
|
||||||
-- Check if mission is nil or over.
|
-- Check if mission is nil or over.
|
||||||
if (not tankerzone.mission) or tankerzone.mission:IsOver() then
|
if (not tankerzone.mission) or tankerzone.mission:IsOver() then
|
||||||
local Coordinate=tankerzone.zone:GetCoordinate()
|
local Coordinate=tankerzone.zone:GetCoordinate()
|
||||||
|
|||||||
@@ -41,13 +41,12 @@
|
|||||||
-- @field #number coalition
|
-- @field #number coalition
|
||||||
-- @field #string alias
|
-- @field #string alias
|
||||||
-- @field #table wings
|
-- @field #table wings
|
||||||
-- @field Ops.Intelligence#INTEL Intel
|
-- @field Ops.Intel#INTEL Intel
|
||||||
-- @field #number resurrection
|
-- @field #number resurrection
|
||||||
-- @field #number capspeed
|
-- @field #number capspeed
|
||||||
-- @field #number capalt
|
-- @field #number capalt
|
||||||
-- @field #number capdir
|
-- @field #number capdir
|
||||||
-- @field #number capleg
|
-- @field #number capleg
|
||||||
-- @field #number capgrouping
|
|
||||||
-- @field #number maxinterceptsize
|
-- @field #number maxinterceptsize
|
||||||
-- @field #number missionrange
|
-- @field #number missionrange
|
||||||
-- @field #number noaltert5
|
-- @field #number noaltert5
|
||||||
@@ -65,6 +64,7 @@
|
|||||||
-- @field #boolean Monitor
|
-- @field #boolean Monitor
|
||||||
-- @field #boolean TankerInvisible
|
-- @field #boolean TankerInvisible
|
||||||
-- @field #number CapFormation
|
-- @field #number CapFormation
|
||||||
|
-- @field #table ReadyFlightGroups
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown.
|
--- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown.
|
||||||
@@ -141,14 +141,14 @@
|
|||||||
-- -- **Note** If you need different tanker types, i.e. Boom and Drogue, set them up at different AirWings!
|
-- -- **Note** If you need different tanker types, i.e. Boom and Drogue, set them up at different AirWings!
|
||||||
-- -- Add a tanker point
|
-- -- Add a tanker point
|
||||||
-- mywing:AddPatrolPointTanker(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone Tanker"):GetCoordinate(),20000,280,270,50)
|
-- mywing:AddPatrolPointTanker(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone Tanker"):GetCoordinate(),20000,280,270,50)
|
||||||
-- -- Add an AWACS squad - Radio 251 AM, TACAN 51Y
|
-- -- Add a tanker squad - Radio 251 AM, TACAN 51Y
|
||||||
-- mywing:AddTankerSquadron("Blue Tanker","Tanker Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.EXCELLENT,602,nil,251,radio.modulation.AM,51)
|
-- mywing:AddTankerSquadron("Blue Tanker","Tanker Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.EXCELLENT,602,nil,251,radio.modulation.AM,51)
|
||||||
--
|
--
|
||||||
-- ### Add an AWACS (optional)
|
-- ### Add an AWACS (optional)
|
||||||
--
|
--
|
||||||
-- -- Add an AWACS point
|
-- -- Add an AWACS point
|
||||||
-- mywing:AddPatrolPointAwacs(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone AWACS"):GetCoordinate(),25000,300,270,50)
|
-- mywing:AddPatrolPointAwacs(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone AWACS"):GetCoordinate(),25000,300,270,50)
|
||||||
-- -- Add a tanker squad - Radio 251 AM, TACAN 51Y
|
-- -- Add an AWACS squad - Radio 251 AM, TACAN 51Y
|
||||||
-- mywing:AddAWACSSquadron("Blue AWACS","AWACS Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.AVERAGE,702,nil,271,radio.modulation.AM)
|
-- mywing:AddAWACSSquadron("Blue AWACS","AWACS Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.AVERAGE,702,nil,271,radio.modulation.AM)
|
||||||
--
|
--
|
||||||
-- # Fine-Tuning
|
-- # Fine-Tuning
|
||||||
@@ -190,7 +190,6 @@ EASYGCICAP = {
|
|||||||
capalt = 25000,
|
capalt = 25000,
|
||||||
capdir = 45,
|
capdir = 45,
|
||||||
capleg = 15,
|
capleg = 15,
|
||||||
capgrouping = 2,
|
|
||||||
maxinterceptsize = 2,
|
maxinterceptsize = 2,
|
||||||
missionrange = 100,
|
missionrange = 100,
|
||||||
noaltert5 = 4,
|
noaltert5 = 4,
|
||||||
@@ -209,6 +208,7 @@ EASYGCICAP = {
|
|||||||
Monitor = false,
|
Monitor = false,
|
||||||
TankerInvisible = true,
|
TankerInvisible = true,
|
||||||
CapFormation = nil,
|
CapFormation = nil,
|
||||||
|
ReadyFlightGroups = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Internal Squadron data type
|
--- Internal Squadron data type
|
||||||
@@ -244,7 +244,7 @@ EASYGCICAP = {
|
|||||||
|
|
||||||
--- EASYGCICAP class version.
|
--- EASYGCICAP class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
EASYGCICAP.version="0.0.9"
|
EASYGCICAP.version="0.1.10"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -258,10 +258,10 @@ EASYGCICAP.version="0.0.9"
|
|||||||
|
|
||||||
--- Create a new GCICAP Manager
|
--- Create a new GCICAP Manager
|
||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @param #string Alias
|
-- @param #string Alias A Name for this GCICAP
|
||||||
-- @param #string AirbaseName
|
-- @param #string AirbaseName Name of the Home Airbase
|
||||||
-- @param #string Coalition
|
-- @param #string Coalition Coalition, e.g. "blue" or "red"
|
||||||
-- @param #string EWRName
|
-- @param #string EWRName (Partial) group name of the EWR system of the coalition, e.g. "Red EWR"
|
||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
|
function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
|
||||||
-- Inherit everything from FSM class.
|
-- Inherit everything from FSM class.
|
||||||
@@ -321,6 +321,7 @@ end
|
|||||||
-- @param #number Formation Formation to fly, defaults to ENUMS.Formation.FixedWing.FingerFour.Group
|
-- @param #number Formation Formation to fly, defaults to ENUMS.Formation.FixedWing.FingerFour.Group
|
||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:SetCAPFormation(Formation)
|
function EASYGCICAP:SetCAPFormation(Formation)
|
||||||
|
self:T(self.lid.."SetCAPFormation")
|
||||||
self.CapFormation = Formation
|
self.CapFormation = Formation
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -428,7 +429,7 @@ end
|
|||||||
--- Set default number of airframes standing by for intercept tasks (visible on the airfield)
|
--- Set default number of airframes standing by for intercept tasks (visible on the airfield)
|
||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @param #number Airframes defaults to 2
|
-- @param #number Airframes defaults to 2
|
||||||
-- @return #EASYGCICAP selfAirframes
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:SetDefaultNumberAlter5Standby(Airframes)
|
function EASYGCICAP:SetDefaultNumberAlter5Standby(Airframes)
|
||||||
self:T(self.lid.."SetDefaultNumberAlter5Standby")
|
self:T(self.lid.."SetDefaultNumberAlter5Standby")
|
||||||
self.noaltert5 = math.abs(Airframes) or 2
|
self.noaltert5 = math.abs(Airframes) or 2
|
||||||
@@ -438,13 +439,36 @@ end
|
|||||||
--- Set default engage range for intruders detected by CAP flights in NM.
|
--- Set default engage range for intruders detected by CAP flights in NM.
|
||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @param #number Range defaults to 50NM
|
-- @param #number Range defaults to 50NM
|
||||||
-- @return #EASYGCICAP selfAirframes
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:SetDefaultEngageRange(Range)
|
function EASYGCICAP:SetDefaultEngageRange(Range)
|
||||||
self:T(self.lid.."SetDefaultNumberAlter5Standby")
|
self:T(self.lid.."SetDefaultNumberAlter5Standby")
|
||||||
self.engagerange = Range or 50
|
self.engagerange = Range or 50
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set default overhead for intercept calculations
|
||||||
|
-- @param #EASYGCICAP self
|
||||||
|
-- @param #number Overhead The overhead to use.
|
||||||
|
-- @return #EASYGCICAP self
|
||||||
|
-- @usage Either a CAP Plane or a newly spawned GCI plane will take care of intruders. Standard overhead is 0.75, i.e. a group of 3 intrudes will
|
||||||
|
-- be managed by 2 planes from the assigned AirWing. There is an maximum missions limitation per AirWing, so we do not spam the skies.
|
||||||
|
function EASYGCICAP:SetDefaultOverhead(Overhead)
|
||||||
|
self:T(self.lid.."SetDefaultOverhead")
|
||||||
|
self.overhead = Overhead or 0.75
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set CAP mission start to vary randomly between Start end End seconds.
|
||||||
|
-- @param #EASYGCICAP self
|
||||||
|
-- @param #number Start
|
||||||
|
-- @param #number End
|
||||||
|
-- @return #EASYGCICAP self
|
||||||
|
function EASYGCICAP:SetCapStartTimeVariation(Start, End)
|
||||||
|
self.capOptionVaryStartTime = Start or 5
|
||||||
|
self.capOptionVaryEndTime = End or 60
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Add an AirWing to the manager
|
--- Add an AirWing to the manager
|
||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @param #string Airbasename
|
-- @param #string Airbasename
|
||||||
@@ -491,13 +515,18 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
|
|||||||
|
|
||||||
-- Create Airwing
|
-- Create Airwing
|
||||||
local CAP_Wing = AIRWING:New(Airbasename,Alias)
|
local CAP_Wing = AIRWING:New(Airbasename,Alias)
|
||||||
CAP_Wing:SetVerbosityLevel(3)
|
CAP_Wing:SetVerbosityLevel(0)
|
||||||
CAP_Wing:SetReportOff()
|
CAP_Wing:SetReportOff()
|
||||||
CAP_Wing:SetMarker(false)
|
CAP_Wing:SetMarker(false)
|
||||||
CAP_Wing:SetAirbase(AIRBASE:FindByName(Airbasename))
|
CAP_Wing:SetAirbase(AIRBASE:FindByName(Airbasename))
|
||||||
CAP_Wing:SetRespawnAfterDestroyed()
|
CAP_Wing:SetRespawnAfterDestroyed()
|
||||||
CAP_Wing:SetNumberCAP(self.capgrouping)
|
CAP_Wing:SetNumberCAP(self.capgrouping)
|
||||||
CAP_Wing:SetCapCloseRaceTrack(true)
|
CAP_Wing:SetCapCloseRaceTrack(true)
|
||||||
|
|
||||||
|
if self.capOptionVaryStartTime then
|
||||||
|
CAP_Wing:SetCapStartTimeVariation(self.capOptionVaryStartTime,self.capOptionVaryEndTime)
|
||||||
|
end
|
||||||
|
|
||||||
if CapFormation then
|
if CapFormation then
|
||||||
CAP_Wing:SetCAPFormation(CapFormation)
|
CAP_Wing:SetCAPFormation(CapFormation)
|
||||||
end
|
end
|
||||||
@@ -528,6 +557,7 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
|
|||||||
flightgroup:SetDespawnAfterHolding()
|
flightgroup:SetDespawnAfterHolding()
|
||||||
flightgroup:SetDestinationbase(AIRBASE:FindByName(Airbasename))
|
flightgroup:SetDestinationbase(AIRBASE:FindByName(Airbasename))
|
||||||
flightgroup:GetGroup():CommandEPLRS(true,5)
|
flightgroup:GetGroup():CommandEPLRS(true,5)
|
||||||
|
flightgroup:GetGroup():SetOptionRadarUsingForContinousSearch()
|
||||||
if Mission.type ~= AUFTRAG.Type.TANKER and Mission.type ~= AUFTRAG.Type.AWACS and Mission.type ~= AUFTRAG.Type.RECON then
|
if Mission.type ~= AUFTRAG.Type.TANKER and Mission.type ~= AUFTRAG.Type.AWACS and Mission.type ~= AUFTRAG.Type.RECON then
|
||||||
flightgroup:SetDetection(true)
|
flightgroup:SetDetection(true)
|
||||||
flightgroup:SetEngageDetectedOn(self.engagerange,{"Air"},self.GoZoneSet,self.NoGoZoneSet)
|
flightgroup:SetEngageDetectedOn(self.engagerange,{"Air"},self.GoZoneSet,self.NoGoZoneSet)
|
||||||
@@ -548,7 +578,7 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
|
|||||||
flightgroup:SetFuelLowRTB(true)
|
flightgroup:SetFuelLowRTB(true)
|
||||||
Intel:AddAgent(flightgroup)
|
Intel:AddAgent(flightgroup)
|
||||||
function flightgroup:OnAfterHolding(From,Event,To)
|
function flightgroup:OnAfterHolding(From,Event,To)
|
||||||
self:ClearToLand(5)
|
self:Despawn(1,true)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1045,6 +1075,172 @@ function EASYGCICAP:AddRejectZone(Zone)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (Internal) Try to assign the intercept to a FlightGroup already in air and ready.
|
||||||
|
-- @param #EASYGCICAP self
|
||||||
|
-- @param #table ReadyFlightGroups ReadyFlightGroups
|
||||||
|
-- @param Ops.Auftrag#AUFTRAG InterceptAuftrag The Auftrag
|
||||||
|
-- @param Wrapper.Group#GROUP Group The Target
|
||||||
|
-- @param #number WingSize Calculated number of Flights
|
||||||
|
-- @return #boolean assigned
|
||||||
|
-- @return #number leftover
|
||||||
|
function EASYGCICAP:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,Group,WingSize)
|
||||||
|
self:I("_TryAssignIntercept for size "..WingSize or 1)
|
||||||
|
local assigned = false
|
||||||
|
local wingsize = WingSize or 1
|
||||||
|
local mindist = 0
|
||||||
|
local disttable = {}
|
||||||
|
if Group and Group:IsAlive() then
|
||||||
|
local gcoord = Group:GetCoordinate() or COORDINATE:New(0,0,0)
|
||||||
|
self:I(self.lid..string.format("Assignment for %s",Group:GetName()))
|
||||||
|
for _name,_FG in pairs(ReadyFlightGroups or {}) do
|
||||||
|
local FG = _FG -- Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
local fcoord = FG:GetCoordinate()
|
||||||
|
local dist = math.floor(UTILS.Round(fcoord:Get2DDistance(gcoord)/1000,1))
|
||||||
|
self:I(self.lid..string.format("FG %s Distance %dkm",_name,dist))
|
||||||
|
disttable[#disttable+1] = { FG=FG, dist=dist}
|
||||||
|
if dist>mindist then mindist=dist end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sortDistance(a, b)
|
||||||
|
return a.dist < b.dist
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(disttable, sortDistance)
|
||||||
|
|
||||||
|
for _,_entry in ipairs(disttable) do
|
||||||
|
local FG = _entry.FG -- Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
FG:AddMission(InterceptAuftrag)
|
||||||
|
local cm = FG:GetMissionCurrent()
|
||||||
|
if cm then cm:Cancel() end
|
||||||
|
wingsize = wingsize - 1
|
||||||
|
self:I(self.lid..string.format("Assigned to FG %s Distance %dkm",FG:GetName(),_entry.dist))
|
||||||
|
if wingsize == 0 then
|
||||||
|
assigned = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return assigned, wingsize
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a zone to the rejected zones set.
|
||||||
|
-- @param #EASYGCICAP self
|
||||||
|
-- @param Ops.Intelligence#INTEL.Cluster Cluster
|
||||||
|
-- @return #EASYGCICAP self
|
||||||
|
function EASYGCICAP:_AssignIntercept(Cluster)
|
||||||
|
-- Here, we'll decide if we need to launch an intercepting flight, and from where
|
||||||
|
local overhead = self.overhead
|
||||||
|
local capspeed = self.capspeed + 100
|
||||||
|
local capalt = self.capalt
|
||||||
|
local maxsize = self.maxinterceptsize
|
||||||
|
local repeatsonfailure = self.repeatsonfailure
|
||||||
|
|
||||||
|
local wings = self.wings
|
||||||
|
local ctlpts = self.ManagedCP
|
||||||
|
local MaxAliveMissions = self.MaxAliveMissions * self.capgrouping
|
||||||
|
local nogozoneset = self.NoGoZoneSet
|
||||||
|
local ReadyFlightGroups = self.ReadyFlightGroups
|
||||||
|
|
||||||
|
-- Aircraft?
|
||||||
|
if Cluster.ctype ~= INTEL.Ctype.AIRCRAFT then return end
|
||||||
|
-- Threatlevel 0..10
|
||||||
|
local contact = self.Intel:GetHighestThreatContact(Cluster)
|
||||||
|
local name = contact.groupname --#string
|
||||||
|
local threat = contact.threatlevel --#number
|
||||||
|
local position = self.Intel:CalcClusterFuturePosition(Cluster,300)
|
||||||
|
-- calculate closest zone
|
||||||
|
local bestdistance = 2000*1000 -- 2000km
|
||||||
|
local targetairwing = nil -- Ops.AirWing#AIRWING
|
||||||
|
local targetawname = "" -- #string
|
||||||
|
local clustersize = self.Intel:ClusterCountUnits(Cluster) or 1
|
||||||
|
local wingsize = math.abs(overhead * (clustersize+1))
|
||||||
|
if wingsize > maxsize then wingsize = maxsize end
|
||||||
|
-- existing mission, and if so - done?
|
||||||
|
local retrymission = true
|
||||||
|
if Cluster.mission and (not Cluster.mission:IsOver()) then
|
||||||
|
retrymission = false
|
||||||
|
end
|
||||||
|
if (retrymission) and (wingsize >= 1) then
|
||||||
|
MESSAGE:New(string.format("**** %s Interceptors need wingsize %d", UTILS.GetCoalitionName(self.coalition), wingsize),15,"CAPGCI"):ToAllIf(self.debug):ToLog()
|
||||||
|
for _,_data in pairs (wings) do
|
||||||
|
local airwing = _data[1] -- Ops.AirWing#AIRWING
|
||||||
|
local zone = _data[2] -- Core.Zone#ZONE
|
||||||
|
local zonecoord = zone:GetCoordinate()
|
||||||
|
local name = _data[3] -- #string
|
||||||
|
local distance = position:DistanceFromPointVec2(zonecoord)
|
||||||
|
local airframes = airwing:CountAssets(true)
|
||||||
|
if distance < bestdistance and airframes >= wingsize then
|
||||||
|
bestdistance = distance
|
||||||
|
targetairwing = airwing
|
||||||
|
targetawname = name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _,_data in pairs (ctlpts) do
|
||||||
|
--local airwing = _data[1] -- Ops.AirWing#AIRWING
|
||||||
|
--local zone = _data[2] -- Core.Zone#ZONE
|
||||||
|
--local zonecoord = zone:GetCoordinate()
|
||||||
|
--local name = _data[3] -- #string
|
||||||
|
|
||||||
|
local data = _data -- #EASYGCICAP.CapPoint
|
||||||
|
local name = data.AirbaseName
|
||||||
|
local zonecoord = data.Coordinate
|
||||||
|
local airwing = wings[name][1]
|
||||||
|
|
||||||
|
local distance = position:DistanceFromPointVec2(zonecoord)
|
||||||
|
local airframes = airwing:CountAssets(true)
|
||||||
|
if distance < bestdistance and airframes >= wingsize then
|
||||||
|
bestdistance = distance
|
||||||
|
targetairwing = airwing -- Ops.AirWing#AIRWING
|
||||||
|
targetawname = name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local text = string.format("Closest Airwing is %s", targetawname)
|
||||||
|
local m = MESSAGE:New(text,10,"CAPGCI"):ToAllIf(self.debug):ToLog()
|
||||||
|
-- Do we have a matching airwing?
|
||||||
|
if targetairwing then
|
||||||
|
local AssetCount = targetairwing:CountAssetsOnMission(MissionTypes,Cohort)
|
||||||
|
-- Enough airframes on mission already?
|
||||||
|
self:T(self.lid.." Assets on Mission "..AssetCount)
|
||||||
|
if AssetCount <= MaxAliveMissions then
|
||||||
|
local repeats = repeatsonfailure
|
||||||
|
local InterceptAuftrag = AUFTRAG:NewINTERCEPT(contact.group)
|
||||||
|
:SetMissionRange(150)
|
||||||
|
:SetPriority(1,true,1)
|
||||||
|
--:SetRequiredAssets(wingsize)
|
||||||
|
:SetRepeatOnFailure(repeats)
|
||||||
|
:SetMissionSpeed(UTILS.KnotsToAltKIAS(capspeed,capalt))
|
||||||
|
:SetMissionAltitude(capalt)
|
||||||
|
|
||||||
|
if nogozoneset:Count() > 0 then
|
||||||
|
InterceptAuftrag:AddConditionSuccess(
|
||||||
|
function(group,zoneset)
|
||||||
|
local success = false
|
||||||
|
if group and group:IsAlive() then
|
||||||
|
local coord = group:GetCoordinate()
|
||||||
|
if coord and zoneset:IsCoordinateInZone(coord) then
|
||||||
|
success = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return success
|
||||||
|
end,
|
||||||
|
contact.group,
|
||||||
|
nogozoneset
|
||||||
|
)
|
||||||
|
end
|
||||||
|
local assigned, rest = self:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,contact.group,wingsize)
|
||||||
|
if not assigned then
|
||||||
|
InterceptAuftrag:SetRequiredAssets(rest)
|
||||||
|
targetairwing:AddMission(InterceptAuftrag)
|
||||||
|
end
|
||||||
|
Cluster.mission = InterceptAuftrag
|
||||||
|
end
|
||||||
|
else
|
||||||
|
MESSAGE:New("**** Not enough airframes available or max mission limit reached!",15,"CAPGCI"):ToAllIf(self.debug):ToLog()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Start detection.
|
--- (Internal) Start detection.
|
||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
@@ -1068,131 +1264,16 @@ function EASYGCICAP:_StartIntel()
|
|||||||
BlueIntel.debug = true
|
BlueIntel.debug = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Here, we'll decide if we need to launch an intercepting flight, and from where
|
local function AssignCluster(Cluster)
|
||||||
|
self:_AssignIntercept(Cluster)
|
||||||
local overhead = self.overhead
|
end
|
||||||
local capspeed = self.capspeed + 100
|
|
||||||
local capalt = self.capalt
|
|
||||||
local maxsize = self.maxinterceptsize
|
|
||||||
local repeatsonfailure = self.repeatsonfailure
|
|
||||||
|
|
||||||
local wings = self.wings
|
|
||||||
local ctlpts = self.ManagedCP
|
|
||||||
local MaxAliveMissions = self.MaxAliveMissions * self.capgrouping
|
|
||||||
local nogozoneset = self.NoGoZoneSet
|
|
||||||
|
|
||||||
function BlueIntel:OnAfterNewCluster(From,Event,To,Cluster)
|
function BlueIntel:OnAfterNewCluster(From,Event,To,Cluster)
|
||||||
-- Aircraft?
|
AssignCluster(Cluster)
|
||||||
if Cluster.ctype ~= INTEL.Ctype.AIRCRAFT then return end
|
|
||||||
-- Threatlevel 0..10
|
|
||||||
local contact = self:GetHighestThreatContact(Cluster)
|
|
||||||
local name = contact.groupname --#string
|
|
||||||
local threat = contact.threatlevel --#number
|
|
||||||
local position = self:CalcClusterFuturePosition(Cluster,300)
|
|
||||||
-- calculate closest zone
|
|
||||||
local bestdistance = 2000*1000 -- 2000km
|
|
||||||
local targetairwing = nil -- Ops.AirWing#AIRWING
|
|
||||||
local targetawname = "" -- #string
|
|
||||||
local clustersize = self:ClusterCountUnits(Cluster) or 1
|
|
||||||
local wingsize = math.abs(overhead * (clustersize+1))
|
|
||||||
if wingsize > maxsize then wingsize = maxsize end
|
|
||||||
-- existing mission, and if so - done?
|
|
||||||
local retrymission = true
|
|
||||||
if Cluster.mission and (not Cluster.mission:IsOver()) then
|
|
||||||
retrymission = false
|
|
||||||
end
|
|
||||||
if (retrymission) and (wingsize >= 1) then
|
|
||||||
MESSAGE:New(string.format("**** %s Interceptors need wingsize %d", UTILS.GetCoalitionName(self.coalition), wingsize),15,"CAPGCI"):ToAllIf(self.debug):ToLog()
|
|
||||||
for _,_data in pairs (wings) do
|
|
||||||
local airwing = _data[1] -- Ops.AirWing#AIRWING
|
|
||||||
local zone = _data[2] -- Core.Zone#ZONE
|
|
||||||
local zonecoord = zone:GetCoordinate()
|
|
||||||
local name = _data[3] -- #string
|
|
||||||
local distance = position:DistanceFromPointVec2(zonecoord)
|
|
||||||
local airframes = airwing:CountAssets(true)
|
|
||||||
if distance < bestdistance and airframes >= wingsize then
|
|
||||||
bestdistance = distance
|
|
||||||
targetairwing = airwing
|
|
||||||
targetawname = name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for _,_data in pairs (ctlpts) do
|
|
||||||
--local airwing = _data[1] -- Ops.AirWing#AIRWING
|
|
||||||
--local zone = _data[2] -- Core.Zone#ZONE
|
|
||||||
--local zonecoord = zone:GetCoordinate()
|
|
||||||
--local name = _data[3] -- #string
|
|
||||||
|
|
||||||
local data = _data -- #EASYGCICAP.CapPoint
|
|
||||||
local name = data.AirbaseName
|
|
||||||
local zonecoord = data.Coordinate
|
|
||||||
local airwing = wings[name][1]
|
|
||||||
|
|
||||||
local distance = position:DistanceFromPointVec2(zonecoord)
|
|
||||||
local airframes = airwing:CountAssets(true)
|
|
||||||
if distance < bestdistance and airframes >= wingsize then
|
|
||||||
bestdistance = distance
|
|
||||||
targetairwing = airwing -- Ops.AirWing#AIRWING
|
|
||||||
targetawname = name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local text = string.format("Closest Airwing is %s", targetawname)
|
|
||||||
local m = MESSAGE:New(text,10,"CAPGCI"):ToAllIf(self.debug):ToLog()
|
|
||||||
-- Do we have a matching airwing?
|
|
||||||
if targetairwing then
|
|
||||||
local AssetCount = targetairwing:CountAssetsOnMission(MissionTypes,Cohort)
|
|
||||||
--[[
|
|
||||||
local Assets = targetairwing:GetAssetsOnMission(AUFTRAG.Type.GCICAP)
|
|
||||||
for _,_asset in pairs(Assets) do
|
|
||||||
local asset = _asset -- Functional.Warehouse#WAREHOUSE.Assetitem
|
|
||||||
local fg = asset.flightgroup
|
|
||||||
local name = asset.spawngroupname
|
|
||||||
local mission = fg:GetMissionCurrent()
|
|
||||||
local mtype = mission.type
|
|
||||||
local distance = position:Get3DDistance(fg:GetCoordinate()) or 1000*1000
|
|
||||||
distance = distance / 1000
|
|
||||||
local text = string.format("FlightGroup %s on mission %s with distance %d km",name,mtype,distance)
|
|
||||||
local m = MESSAGE:New(text,15,"GCICAP"):ToAllIf(self.debug):ToLog()
|
|
||||||
end
|
|
||||||
--]]
|
|
||||||
-- Enough airframes on mission already?
|
|
||||||
self:T(self.lid.." Assets on Mission "..AssetCount)
|
|
||||||
if AssetCount <= MaxAliveMissions then
|
|
||||||
local repeats = repeatsonfailure
|
|
||||||
local InterceptAuftrag = AUFTRAG:NewINTERCEPT(contact.group)
|
|
||||||
:SetMissionRange(150)
|
|
||||||
:SetPriority(1,true,1)
|
|
||||||
:SetRequiredAssets(wingsize)
|
|
||||||
:SetRepeatOnFailure(repeats)
|
|
||||||
:SetMissionSpeed(UTILS.KnotsToAltKIAS(capspeed,capalt))
|
|
||||||
:SetMissionAltitude(capalt)
|
|
||||||
|
|
||||||
if nogozoneset:Count() > 0 then
|
|
||||||
InterceptAuftrag:AddConditionSuccess(
|
|
||||||
function(group,zoneset)
|
|
||||||
local success = false
|
|
||||||
if group and group:IsAlive() then
|
|
||||||
local coord = group:GetCoordinate()
|
|
||||||
if coord and zoneset:IsCoordinateInZone(coord) then
|
|
||||||
success = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return success
|
|
||||||
end,
|
|
||||||
contact.group,
|
|
||||||
nogozoneset
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
targetairwing:AddMission(InterceptAuftrag)
|
|
||||||
Cluster.mission = InterceptAuftrag
|
|
||||||
end
|
|
||||||
else
|
|
||||||
MESSAGE:New("**** Not enough airframes available or max mission limit reached!",15,"CAPGCI"):ToAllIf(self.debug):ToLog()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
self.Intel = BlueIntel
|
|
||||||
return self
|
self.Intel = BlueIntel
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
@@ -1266,6 +1347,24 @@ function EASYGCICAP:onafterStatus(From,Event,To)
|
|||||||
tankermission = tankermission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.TANKER})
|
tankermission = tankermission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.TANKER})
|
||||||
assets = assets + count
|
assets = assets + count
|
||||||
instock = instock + count2
|
instock = instock + count2
|
||||||
|
local assetsonmission = _wing[1]:GetAssetsOnMission({AUFTRAG.Type.GCICAP,AUFTRAG.Type.PATROLRACETRACK})
|
||||||
|
-- update ready groups
|
||||||
|
self.ReadyFlightGroups = nil
|
||||||
|
self.ReadyFlightGroups = {}
|
||||||
|
for _,_asset in pairs(assetsonmission or {}) do
|
||||||
|
local asset = _asset -- Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
local FG = asset.flightgroup -- Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
if FG then
|
||||||
|
local name = FG:GetName()
|
||||||
|
local engage = FG:IsEngaging()
|
||||||
|
local hasmissiles = FG:IsOutOfMissiles() == nil and true or false
|
||||||
|
local ready = hasmissiles and FG:IsFuelGood() and FG:IsAirborne()
|
||||||
|
--self:I(string.format("Flightgroup %s Engaging = %s Ready = %s",tostring(name),tostring(engage),tostring(ready)))
|
||||||
|
if ready then
|
||||||
|
self.ReadyFlightGroups[name] = FG
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if self.Monitor then
|
if self.Monitor then
|
||||||
local threatcount = #self.Intel.Clusters or 0
|
local threatcount = #self.Intel.Clusters or 0
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Fleet).
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Fleet).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20FlightControl).
|
-- Demo missions: None
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -207,9 +207,9 @@
|
|||||||
-- landing is `21L`.
|
-- landing is `21L`.
|
||||||
--
|
--
|
||||||
-- By default, the runways for landing and takeoff are determined from the wind direction as described above. For cases where this gives wrong results, you can set the active runways manually. This is
|
-- By default, the runways for landing and takeoff are determined from the wind direction as described above. For cases where this gives wrong results, you can set the active runways manually. This is
|
||||||
-- done via @{Wrappper.Airbase#AIRBASE} class.
|
-- done via @{Wrapper.Airbase#AIRBASE} class.
|
||||||
--
|
--
|
||||||
-- More specifically, you can use the @{Wrappper.Airbase#AIRBASE.SetActiveRunwayLanding} function to set the landing runway and the @{Wrappper.Airbase#AIRBASE.SetActiveRunwayTakeoff} function to set
|
-- More specifically, you can use the @{Wrapper.Airbase#AIRBASE.SetActiveRunwayLanding} function to set the landing runway and the @{Wrapper.Airbase#AIRBASE.SetActiveRunwayTakeoff} function to set
|
||||||
-- the runway for takeoff.
|
-- the runway for takeoff.
|
||||||
--
|
--
|
||||||
-- ## Example for Nellis AFB
|
-- ## Example for Nellis AFB
|
||||||
@@ -223,7 +223,7 @@
|
|||||||
--
|
--
|
||||||
-- # DCS ATC
|
-- # DCS ATC
|
||||||
--
|
--
|
||||||
-- You can disable the DCS ATC with the @{Wrappper.Airbase#AIRBASE.SetRadioSilentMode}(*true*). This does not remove the DCS ATC airbase from the F10 menu but makes the ATC unresponsive.
|
-- You can disable the DCS ATC with the @{Wrapper.Airbase#AIRBASE.SetRadioSilentMode}(*true*). This does not remove the DCS ATC airbase from the F10 menu but makes the ATC unresponsive.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- # Examples
|
-- # Examples
|
||||||
@@ -411,26 +411,36 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS, Port,
|
|||||||
self:SetRunwayRepairtime()
|
self:SetRunwayRepairtime()
|
||||||
self.nosubs = false
|
self.nosubs = false
|
||||||
|
|
||||||
-- Set SRS Port
|
|
||||||
self:SetSRSPort(Port or 5002)
|
|
||||||
|
|
||||||
-- Set Callsign Options
|
-- Set Callsign Options
|
||||||
self:SetCallSignOptions(true,true)
|
self:SetCallSignOptions(true,true)
|
||||||
|
|
||||||
-- Init msrs queue.
|
-- Init msrs queue.
|
||||||
self.msrsqueue=MSRSQUEUE:New(self.alias)
|
self.msrsqueue=MSRSQUEUE:New(self.alias)
|
||||||
|
|
||||||
|
-- Init msrs bases
|
||||||
|
local path = PathToSRS or MSRS.path
|
||||||
|
local port = Port or MSRS.port or 5002
|
||||||
|
|
||||||
|
-- Set SRS Port
|
||||||
|
self:SetSRSPort(port)
|
||||||
|
|
||||||
-- SRS for Tower.
|
-- SRS for Tower.
|
||||||
self.msrsTower=MSRS:New(PathToSRS, Frequency, Modulation)
|
self.msrsTower=MSRS:New(path, Frequency, Modulation)
|
||||||
self.msrsTower:SetPort(self.Port)
|
self.msrsTower:SetPort(port)
|
||||||
self.msrsTower:SetGoogle(GoogleKey)
|
if GoogleKey then
|
||||||
|
self.msrsTower:SetProviderOptionsGoogle(GoogleKey,GoogleKey)
|
||||||
|
self.msrsTower:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
self.msrsTower:SetCoordinate(self:GetCoordinate())
|
self.msrsTower:SetCoordinate(self:GetCoordinate())
|
||||||
self:SetSRSTower()
|
self:SetSRSTower()
|
||||||
|
|
||||||
-- SRS for Pilot.
|
-- SRS for Pilot.
|
||||||
self.msrsPilot=MSRS:New(PathToSRS, Frequency, Modulation)
|
self.msrsPilot=MSRS:New(PathToSRS, Frequency, Modulation)
|
||||||
self.msrsPilot:SetPort(self.Port)
|
self.msrsPilot:SetPort(self.Port)
|
||||||
self.msrsPilot:SetGoogle(GoogleKey)
|
if GoogleKey then
|
||||||
|
self.msrsPilot:SetProviderOptionsGoogle(GoogleKey,GoogleKey)
|
||||||
|
self.msrsPilot:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
self.msrsTower:SetCoordinate(self:GetCoordinate())
|
self.msrsTower:SetCoordinate(self:GetCoordinate())
|
||||||
self:SetSRSPilot()
|
self:SetSRSPilot()
|
||||||
|
|
||||||
@@ -633,7 +643,6 @@ function FLIGHTCONTROL:_SetSRSOptions(msrs, Gender, Culture, Voice, Volume, Labe
|
|||||||
msrs:SetVoice(Voice)
|
msrs:SetVoice(Voice)
|
||||||
msrs:SetVolume(Volume)
|
msrs:SetVolume(Volume)
|
||||||
msrs:SetLabel(Label)
|
msrs:SetLabel(Label)
|
||||||
msrs:SetGoogle(PathToGoogleCredentials)
|
|
||||||
msrs:SetCoalition(self:GetCoalition())
|
msrs:SetCoalition(self:GetCoalition())
|
||||||
msrs:SetPort(Port or self.Port or 5002)
|
msrs:SetPort(Port or self.Port or 5002)
|
||||||
end
|
end
|
||||||
@@ -648,12 +657,11 @@ end
|
|||||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`. See [Google Voices](https://cloud.google.com/text-to-speech/docs/voices).
|
-- @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 #number Volume Volume. Default 1.0.
|
||||||
-- @param #string Label Name under which SRS transmits. 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
|
-- @return #FLIGHTCONTROL self
|
||||||
function FLIGHTCONTROL:SetSRSTower(Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials)
|
function FLIGHTCONTROL:SetSRSTower(Gender, Culture, Voice, Volume, Label)
|
||||||
|
|
||||||
if self.msrsTower then
|
if self.msrsTower then
|
||||||
self:_SetSRSOptions(self.msrsTower, Gender or "female", Culture or "en-GB", Voice, Volume, Label or self.alias, PathToGoogleCredentials)
|
self:_SetSRSOptions(self.msrsTower, Gender or "female", Culture or "en-GB", Voice, Volume, Label or self.alias)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -666,12 +674,11 @@ end
|
|||||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
||||||
-- @param #number Volume Volume. Default 1.0.
|
-- @param #number Volume Volume. Default 1.0.
|
||||||
-- @param #string Label Name under which SRS transmits. Default "Pilot".
|
-- @param #string Label Name under which SRS transmits. Default "Pilot".
|
||||||
-- @param #string PathToGoogleCredentials Path to google credentials json file.
|
|
||||||
-- @return #FLIGHTCONTROL self
|
-- @return #FLIGHTCONTROL self
|
||||||
function FLIGHTCONTROL:SetSRSPilot(Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials)
|
function FLIGHTCONTROL:SetSRSPilot(Gender, Culture, Voice, Volume, Label)
|
||||||
|
|
||||||
if self.msrsPilot then
|
if self.msrsPilot then
|
||||||
self:_SetSRSOptions(self.msrsPilot, Gender or "male", Culture or "en-US", Voice, Volume, Label or "Pilot", PathToGoogleCredentials)
|
self:_SetSRSOptions(self.msrsPilot, Gender or "male", Culture or "en-US", Voice, Volume, Label or "Pilot")
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -876,7 +883,7 @@ end
|
|||||||
|
|
||||||
--- Set ATIS.
|
--- Set ATIS.
|
||||||
-- @param #FLIGHTCONTROL self
|
-- @param #FLIGHTCONTROL self
|
||||||
-- @param Ops.Atis#ATIS Atis ATIS.
|
-- @param Ops.ATIS#ATIS Atis ATIS.
|
||||||
-- @return #FLIGHTCONTROL self
|
-- @return #FLIGHTCONTROL self
|
||||||
function FLIGHTCONTROL:SetATIS(Atis)
|
function FLIGHTCONTROL:SetATIS(Atis)
|
||||||
self.atis=Atis
|
self.atis=Atis
|
||||||
@@ -2811,7 +2818,11 @@ function FLIGHTCONTROL:_PlayerInfoATIS(groupname)
|
|||||||
|
|
||||||
-- Radio message.
|
-- Radio message.
|
||||||
self:TransmissionPilot(rtext, flight)
|
self:TransmissionPilot(rtext, flight)
|
||||||
self:TransmissionTower(srstxt,flight,10)
|
if self.atis then
|
||||||
|
self:TransmissionTower(srstxt,flight,10)
|
||||||
|
else
|
||||||
|
self:TransmissionTower(text,flight,10)
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
self:E(self.lid..string.format("Cannot find flight group %s.", tostring(groupname)))
|
self:E(self.lid..string.format("Cannot find flight group %s.", tostring(groupname)))
|
||||||
@@ -4420,14 +4431,11 @@ end
|
|||||||
-- Misc Functions
|
-- Misc Functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Add parking guard in front of a parking aircraft.
|
--- [INTERNAL] Add parking guard in front of a parking aircraft - delayed for MP.
|
||||||
-- @param #FLIGHTCONTROL self
|
-- @param #FLIGHTCONTROL self
|
||||||
-- @param Wrapper.Unit#UNIT unit The aircraft.
|
-- @param Wrapper.Unit#UNIT unit The aircraft.
|
||||||
function FLIGHTCONTROL:SpawnParkingGuard(unit)
|
function FLIGHTCONTROL:_SpawnParkingGuard(unit)
|
||||||
|
-- Position of the unit.
|
||||||
if unit and self.parkingGuard then
|
|
||||||
|
|
||||||
-- Position of the unit.
|
|
||||||
local coordinate=unit:GetCoordinate()
|
local coordinate=unit:GetCoordinate()
|
||||||
|
|
||||||
-- Parking spot.
|
-- Parking spot.
|
||||||
@@ -4474,6 +4482,17 @@ function FLIGHTCONTROL:SpawnParkingGuard(unit)
|
|||||||
else
|
else
|
||||||
self:E(self.lid.."ERROR: Parking Guard already exists!")
|
self:E(self.lid.."ERROR: Parking Guard already exists!")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add parking guard in front of a parking aircraft.
|
||||||
|
-- @param #FLIGHTCONTROL self
|
||||||
|
-- @param Wrapper.Unit#UNIT unit The aircraft.
|
||||||
|
function FLIGHTCONTROL:SpawnParkingGuard(unit)
|
||||||
|
|
||||||
|
if unit and self.parkingGuard then
|
||||||
|
|
||||||
|
-- Schedule delay so in MP we get the heading of the client's plane
|
||||||
|
self:ScheduleOnce(1,FLIGHTCONTROL._SpawnParkingGuard,self,unit)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Flightgroup).
|
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Flightgroup).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -2333,7 +2333,8 @@ function FLIGHTGROUP:onafterCruise(From, Event, To)
|
|||||||
-- CLIENT
|
-- CLIENT
|
||||||
---
|
---
|
||||||
|
|
||||||
--self:_UpdateMenu(0.1)
|
-- Had this commented out (forgot why, probably because it was not necessary) but re-enabling it because of carrier launch.
|
||||||
|
self:_UpdateMenu(0.1)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2863,8 +2864,11 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
|||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
-- Check if not parking (could be on ALERT5 and just spawned (current mission=nil)
|
||||||
|
if not self:IsParking() then
|
||||||
self:T(self.lid..string.format("Passed Final WP but Tasks=%d or Missions=%d left in the queue. Wait!", nTasks, nMissions))
|
self:T(self.lid..string.format("Passed Final WP but Tasks=%d or Missions=%d left in the queue. Wait!", nTasks, nMissions))
|
||||||
self:__Wait(-1)
|
self:__Wait(-1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:T(self.lid..string.format("Passed Final WP but still have current Task (#%s) or Mission (#%s) left to do", tostring(self.taskcurrent), tostring(self.currentmission)))
|
self:T(self.lid..string.format("Passed Final WP but still have current Task (#%s) or Mission (#%s) left to do", tostring(self.taskcurrent), tostring(self.currentmission)))
|
||||||
@@ -3227,13 +3231,22 @@ function FLIGHTGROUP:_LandAtAirbase(airbase, SpeedTo, SpeedHold, SpeedLand)
|
|||||||
local TaskFinal = self.group:TaskFunction("FLIGHTGROUP._OnFinal", self)
|
local TaskFinal = self.group:TaskFunction("FLIGHTGROUP._OnFinal", self)
|
||||||
|
|
||||||
-- Final approach waypoint.
|
-- Final approach waypoint.
|
||||||
local papp=airbase:GetCoordinate():Translate(x1, runway.heading-180):SetAltitude(h1)
|
local rheading
|
||||||
|
if runway then
|
||||||
|
rheading = runway.heading-180
|
||||||
|
else
|
||||||
|
-- AB HeloBase w/o runway eg Naqoura
|
||||||
|
local wind = airbase:GetCoordinate():GetWind()
|
||||||
|
rheading = -wind
|
||||||
|
end
|
||||||
|
|
||||||
|
local papp=airbase:GetCoordinate():Translate(x1, rheading):SetAltitude(h1)
|
||||||
wp[#wp+1]=papp:WaypointAirTurningPoint("BARO", UTILS.KnotsToKmph(SpeedLand), {TaskFinal}, "Final Approach")
|
wp[#wp+1]=papp:WaypointAirTurningPoint("BARO", UTILS.KnotsToKmph(SpeedLand), {TaskFinal}, "Final Approach")
|
||||||
|
|
||||||
-- Okay, it looks like it's best to specify the coordinates not at the airbase but a bit away. This causes a more direct landing approach.
|
-- Okay, it looks like it's best to specify the coordinates not at the airbase but a bit away. This causes a more direct landing approach.
|
||||||
local pland=airbase:GetCoordinate():Translate(x2, runway.heading-180):SetAltitude(h2)
|
local pland=airbase:GetCoordinate():Translate(x2, rheading):SetAltitude(h2)
|
||||||
wp[#wp+1]=pland:WaypointAirLanding(UTILS.KnotsToKmph(SpeedLand), airbase, {}, "Landing")
|
wp[#wp+1]=pland:WaypointAirLanding(UTILS.KnotsToKmph(SpeedLand), airbase, {}, "Landing")
|
||||||
|
|
||||||
elseif airbase:IsShip() or airbase:IsHelipad() then
|
elseif airbase:IsShip() or airbase:IsHelipad() then
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
-- @field #table filterCategoryGroup Filter for group categories.
|
-- @field #table filterCategoryGroup Filter for group categories.
|
||||||
-- @field Core.Set#SET_ZONE acceptzoneset Set of accept zones. If defined, only contacts in these zones are considered.
|
-- @field Core.Set#SET_ZONE acceptzoneset Set of accept zones. If defined, only contacts in these zones are considered.
|
||||||
-- @field Core.Set#SET_ZONE rejectzoneset Set of reject zones. Contacts in these zones are not considered, even if they are in accept zones.
|
-- @field Core.Set#SET_ZONE rejectzoneset Set of reject zones. Contacts in these zones are not considered, even if they are in accept zones.
|
||||||
|
-- @field Core.Set#SET_ZONE conflictzoneset Set of conflict zones. Contacts in these zones are considered, even if they are not in accept zones or if they are in reject zones.
|
||||||
-- @field #table Contacts Table of detected items.
|
-- @field #table Contacts Table of detected items.
|
||||||
-- @field #table ContactsLost Table of lost detected items.
|
-- @field #table ContactsLost Table of lost detected items.
|
||||||
-- @field #table ContactsUnknown Table of new detected items.
|
-- @field #table ContactsUnknown Table of new detected items.
|
||||||
@@ -159,13 +160,12 @@ INTEL.Ctype={
|
|||||||
|
|
||||||
--- INTEL class version.
|
--- INTEL class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
INTEL.version="0.3.5"
|
INTEL.version="0.3.6"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: Make forget times user input. Currently these are hard coded.
|
|
||||||
-- TODO: Add min cluster size. Only create new clusters if they have a certain group size.
|
-- TODO: Add min cluster size. Only create new clusters if they have a certain group size.
|
||||||
-- TODO: process detected set asynchroniously for better performance.
|
-- TODO: process detected set asynchroniously for better performance.
|
||||||
-- DONE: Add statics.
|
-- DONE: Add statics.
|
||||||
@@ -266,6 +266,7 @@ function INTEL:New(DetectionSet, Coalition, Alias)
|
|||||||
self:SetForgetTime()
|
self:SetForgetTime()
|
||||||
self:SetAcceptZones()
|
self:SetAcceptZones()
|
||||||
self:SetRejectZones()
|
self:SetRejectZones()
|
||||||
|
self:SetConflictZones()
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
@@ -416,7 +417,7 @@ function INTEL:RemoveAcceptZone(AcceptZone)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Set reject zones. Contacts detected in this/these zone(s) are rejected and not reported by the detection.
|
--- Set reject zones. Contacts detected in this/these zone(s) are rejected and not reported by the detection.
|
||||||
-- Note that reject zones overrule accept zones, i.e. if a unit is inside and accept zone and inside a reject zone, it is rejected.
|
-- Note that reject zones overrule accept zones, i.e. if a unit is inside an accept zone and inside a reject zone, it is rejected.
|
||||||
-- @param #INTEL self
|
-- @param #INTEL self
|
||||||
-- @param Core.Set#SET_ZONE RejectZoneSet Set of reject zone(s).
|
-- @param Core.Set#SET_ZONE RejectZoneSet Set of reject zone(s).
|
||||||
-- @return #INTEL self
|
-- @return #INTEL self
|
||||||
@@ -426,7 +427,7 @@ function INTEL:SetRejectZones(RejectZoneSet)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Add a reject zone. Contacts detected in this zone are rejected and not reported by the detection.
|
--- Add a reject zone. Contacts detected in this zone are rejected and not reported by the detection.
|
||||||
-- Note that reject zones overrule accept zones, i.e. if a unit is inside and accept zone and inside a reject zone, it is rejected.
|
-- Note that reject zones overrule accept zones, i.e. if a unit is inside an accept zone and inside a reject zone, it is rejected.
|
||||||
-- @param #INTEL self
|
-- @param #INTEL self
|
||||||
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
|
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
|
||||||
-- @return #INTEL self
|
-- @return #INTEL self
|
||||||
@@ -444,6 +445,36 @@ function INTEL:RemoveRejectZone(RejectZone)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set conflict zones. Contacts detected in this/these zone(s) are reported by the detection.
|
||||||
|
-- Note that conflict zones overrule all other zones, i.e. if a unit is outside of an accept zone and inside a reject zone, it is still reported if inside a conflict zone.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param Core.Set#SET_ZONE ConflictZoneSet Set of conflict zone(s).
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:SetConflictZones(ConflictZoneSet)
|
||||||
|
self.conflictzoneset=ConflictZoneSet or SET_ZONE:New()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a conflict zone. Contacts detected in this zone are conflicted and not reported by the detection.
|
||||||
|
-- Note that conflict zones overrule all other zones, i.e. if a unit is outside of an accept zone and inside a reject zone, it is still reported if inside a conflict zone.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param Core.Zone#ZONE ConflictZone Add a zone to the conflict zone set.
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:AddConflictZone(ConflictZone)
|
||||||
|
self.conflictzoneset:AddZone(ConflictZone)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a conflict zone from the conflict zone set.
|
||||||
|
-- Note that conflict zones overrule all other zones, i.e. if a unit is outside of an accept zone and inside a reject zone, it is still reported if inside a conflict zone.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param Core.Zone#ZONE ConflictZone Remove a zone from the conflict zone set.
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:RemoveConflictZone(ConflictZone)
|
||||||
|
self.conflictzoneset:Remove(ConflictZone:GetName(), true)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- **OBSOLETE, will be removed in next version!** Set forget contacts time interval.
|
--- **OBSOLETE, will be removed in next version!** Set forget contacts time interval.
|
||||||
-- Previously known contacts that are not detected any more, are "lost" after this time.
|
-- Previously known contacts that are not detected any more, are "lost" after this time.
|
||||||
-- This avoids fast oscillations between a contact being detected and undetected.
|
-- This avoids fast oscillations between a contact being detected and undetected.
|
||||||
@@ -481,6 +512,33 @@ function INTEL:SetFilterCategory(Categories)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Method to make the radar detection less accurate, e.g. for WWII scenarios.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param #number minheight Minimum flight height to be detected, in meters AGL (above ground)
|
||||||
|
-- @param #number thresheight Threshold to escape the radar if flying below minheight, defaults to 90 (90% escape chance)
|
||||||
|
-- @param #number thresblur Threshold to be detected by the radar overall, defaults to 85 (85% chance to be found)
|
||||||
|
-- @param #number closing Closing-in in km - the limit of km from which on it becomes increasingly difficult to escape radar detection if flying towards the radar position. Should be about 1/3 of the radar detection radius in kilometers, defaults to 20.
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:SetRadarBlur(minheight,thresheight,thresblur,closing)
|
||||||
|
self.RadarBlur = true
|
||||||
|
self.RadarBlurMinHeight = minheight or 250 -- meters
|
||||||
|
self.RadarBlurThresHeight = thresheight or 90 -- 10% chance to find a low flying group
|
||||||
|
self.RadarBlurThresBlur = thresblur or 85 -- 25% chance to escape the radar overall
|
||||||
|
self.RadarBlurClosing = closing or 20 -- 20km
|
||||||
|
self.RadarBlurClosingSquare = self.RadarBlurClosing * self.RadarBlurClosing
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the accept range in kilometers from each of the recce. Only object closer than this range will be detected.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param #number Range Range in kilometers
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:SetAcceptRange(Range)
|
||||||
|
self.RadarAcceptRange = true
|
||||||
|
self.RadarAcceptRangeKilometers = Range or 75
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Filter group categories. Valid categories are:
|
--- Filter group categories. Valid categories are:
|
||||||
--
|
--
|
||||||
-- * Group.Category.AIRPLANE
|
-- * Group.Category.AIRPLANE
|
||||||
@@ -520,7 +578,7 @@ function INTEL:AddAgent(AgentGroup)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Add to detection set.
|
-- Add to detection set.
|
||||||
self.detectionset:AddGroup(AgentGroup)
|
self.detectionset:AddGroup(AgentGroup,true)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -780,7 +838,19 @@ function INTEL:UpdateIntel()
|
|||||||
local remove={}
|
local remove={}
|
||||||
for unitname,_unit in pairs(DetectedUnits) do
|
for unitname,_unit in pairs(DetectedUnits) do
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
local inconflictzone=false
|
||||||
|
-- Check if unit is in any of the conflict zones.
|
||||||
|
if self.conflictzoneset:Count()>0 then
|
||||||
|
for _,_zone in pairs(self.conflictzoneset.Set) do
|
||||||
|
local zone=_zone --Core.Zone#ZONE
|
||||||
|
if unit:IsInZone(zone) then
|
||||||
|
inconflictzone=true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if unit is in any of the accept zones.
|
-- Check if unit is in any of the accept zones.
|
||||||
if self.acceptzoneset:Count()>0 then
|
if self.acceptzoneset:Count()>0 then
|
||||||
local inzone=false
|
local inzone=false
|
||||||
@@ -793,7 +863,7 @@ function INTEL:UpdateIntel()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Unit is not in accept zone ==> remove!
|
-- Unit is not in accept zone ==> remove!
|
||||||
if not inzone then
|
if (not inzone) and (not inconflictzone) then
|
||||||
table.insert(remove, unitname)
|
table.insert(remove, unitname)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -810,7 +880,7 @@ function INTEL:UpdateIntel()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Unit is inside a reject zone ==> remove!
|
-- Unit is inside a reject zone ==> remove!
|
||||||
if inzone then
|
if inzone and (not inconflictzone) then
|
||||||
table.insert(remove, unitname)
|
table.insert(remove, unitname)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1036,8 +1106,8 @@ function INTEL:CreateDetectedItems(DetectedGroups, DetectedStatics, RecceDetecti
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Return the detected target groups of the controllable as a @{SET_GROUP}.
|
--- (Internal) Return the detected target groups of the controllable as a @{Core.Set#SET_GROUP}.
|
||||||
-- The optional parametes specify the detection methods that can be applied.
|
-- The optional parameters specify the detection methods that can be applied.
|
||||||
-- If no detection method is given, the detection will use all the available methods by default.
|
-- If no detection method is given, the detection will use all the available methods by default.
|
||||||
-- @param #INTEL self
|
-- @param #INTEL self
|
||||||
-- @param Wrapper.Unit#UNIT Unit The unit detecting.
|
-- @param Wrapper.Unit#UNIT Unit The unit detecting.
|
||||||
@@ -1053,6 +1123,7 @@ function INTEL:GetDetectedUnits(Unit, DetectedUnits, RecceDetecting, DetectVisua
|
|||||||
|
|
||||||
-- Get detected DCS units.
|
-- Get detected DCS units.
|
||||||
local reccename = Unit:GetName()
|
local reccename = Unit:GetName()
|
||||||
|
|
||||||
local detectedtargets=Unit:GetDetectedTargets(DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK)
|
local detectedtargets=Unit:GetDetectedTargets(DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK)
|
||||||
|
|
||||||
for DetectionObjectID, Detection in pairs(detectedtargets or {}) do
|
for DetectionObjectID, Detection in pairs(detectedtargets or {}) do
|
||||||
@@ -1071,11 +1142,47 @@ function INTEL:GetDetectedUnits(Unit, DetectedUnits, RecceDetecting, DetectVisua
|
|||||||
if status then
|
if status then
|
||||||
|
|
||||||
local unit=UNIT:FindByName(name)
|
local unit=UNIT:FindByName(name)
|
||||||
|
|
||||||
if unit and unit:IsAlive() then
|
if unit and unit:IsAlive() then
|
||||||
DetectedUnits[name]=unit
|
local DetectionAccepted = true
|
||||||
RecceDetecting[name]=reccename
|
|
||||||
self:T(string.format("Unit %s detect by %s", name, reccename))
|
if self.RadarAcceptRange then
|
||||||
|
local reccecoord = Unit:GetCoordinate()
|
||||||
|
local coord = unit:GetCoordinate()
|
||||||
|
local dist = math.floor(coord:Get2DDistance(reccecoord)/1000) -- km
|
||||||
|
if dist > self.RadarAcceptRangeKilometers then DetectionAccepted = false end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.RadarBlur then
|
||||||
|
local reccecoord = Unit:GetCoordinate()
|
||||||
|
local coord = unit:GetCoordinate()
|
||||||
|
local dist = math.floor(coord:Get2DDistance(reccecoord)/1000) -- km
|
||||||
|
local AGL = unit:GetAltitude(true)
|
||||||
|
local minheight = self.RadarBlurMinHeight or 250 -- meters
|
||||||
|
local thresheight = self.RadarBlurThresHeight or 90 -- 10% chance to find a low flying group
|
||||||
|
local thresblur = self.RadarBlurThresBlur or 85 -- 25% chance to escape the radar overall
|
||||||
|
--local dist = math.floor(Distance)
|
||||||
|
if dist <= self.RadarBlurClosing then
|
||||||
|
thresheight = (((dist*dist)/self.RadarBlurClosingSquare)*thresheight)
|
||||||
|
thresblur = (((dist*dist)/self.RadarBlurClosingSquare)*thresblur)
|
||||||
|
end
|
||||||
|
local fheight = math.floor(math.random(1,10000)/100)
|
||||||
|
local fblur = math.floor(math.random(1,10000)/100)
|
||||||
|
if fblur > thresblur then DetectionAccepted = false end
|
||||||
|
if AGL <= minheight and fheight < thresheight then DetectionAccepted = false end
|
||||||
|
if self.debug or self.verbose > 1 then
|
||||||
|
MESSAGE:New("Radar Blur",10):ToLogIf(self.debug):ToAllIf(self.verbose>1)
|
||||||
|
MESSAGE:New("Unit "..name.." is at "..math.floor(AGL).."m. Distance "..math.floor(dist).."km.",10):ToLogIf(self.debug):ToAllIf(self.verbose>1)
|
||||||
|
MESSAGE:New(string.format("fheight = %d/%d | fblur = %d/%d",fheight,thresheight,fblur,thresblur),10):ToLogIf(self.debug):ToAllIf(self.verbose>1)
|
||||||
|
MESSAGE:New("Detection Accepted = "..tostring(DetectionAccepted),10):ToLogIf(self.debug):ToAllIf(self.verbose>1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if DetectionAccepted then
|
||||||
|
DetectedUnits[name]=unit
|
||||||
|
RecceDetecting[name]=reccename
|
||||||
|
self:T(string.format("Unit %s detect by %s", name, reccename))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
if self.detectStatics then
|
if self.detectStatics then
|
||||||
local static=STATIC:FindByName(name, false)
|
local static=STATIC:FindByName(name, false)
|
||||||
@@ -1093,7 +1200,6 @@ function INTEL:GetDetectedUnits(Unit, DetectedUnits, RecceDetecting, DetectVisua
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2265,7 +2265,7 @@ function LEGION:RecruitAssetsForMission(Mission)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T(self.lid..string.format("Largest cargo bay available=%.1f", MaxWeight))
|
self:T(self.lid..string.format("Largest cargo bay available=%.1f", MaxWeight or 0))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -2745,7 +2745,7 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Now we have a long list with assets.
|
-- Now we have a long list with assets.
|
||||||
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, false)
|
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, false, TotalWeight)
|
||||||
|
|
||||||
|
|
||||||
-- Get payloads for air assets.
|
-- Get payloads for air assets.
|
||||||
@@ -2770,7 +2770,7 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Now find the best asset for the given payloads.
|
-- Now find the best asset for the given payloads.
|
||||||
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, true)
|
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, true, TotalWeight)
|
||||||
|
|
||||||
-- Number of assets. At most NreqMax.
|
-- Number of assets. At most NreqMax.
|
||||||
local Nassets=math.min(#Assets, NreqMax)
|
local Nassets=math.min(#Assets, NreqMax)
|
||||||
@@ -3114,8 +3114,9 @@ end
|
|||||||
-- @param #string MissionType Mission type for which the best assets are desired.
|
-- @param #string MissionType Mission type for which the best assets are desired.
|
||||||
-- @param DCS#Vec2 TargetVec2 Target 2D vector.
|
-- @param DCS#Vec2 TargetVec2 Target 2D vector.
|
||||||
-- @param #boolean IncludePayload If `true`, include the payload in the calulation if the asset has one attached.
|
-- @param #boolean IncludePayload If `true`, include the payload in the calulation if the asset has one attached.
|
||||||
|
-- @param #number TotalWeight The total weight of the cargo to be transported, if applicable.
|
||||||
-- @return #number Mission score.
|
-- @return #number Mission score.
|
||||||
function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload)
|
function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload, TotalWeight)
|
||||||
|
|
||||||
-- Mission score.
|
-- Mission score.
|
||||||
local score=0
|
local score=0
|
||||||
@@ -3209,8 +3210,18 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu
|
|||||||
|
|
||||||
-- TRANSPORT specific.
|
-- TRANSPORT specific.
|
||||||
if MissionType==AUFTRAG.Type.OPSTRANSPORT then
|
if MissionType==AUFTRAG.Type.OPSTRANSPORT then
|
||||||
-- Add 1 score point for each 10 kg of cargo bay.
|
if TotalWeight then
|
||||||
score=score+UTILS.Round(asset.cargobaymax/10, 0)
|
-- Add 1 score point for each 10 kg of cargo bay capacity up to the total cargo weight,
|
||||||
|
-- and then subtract 1 score point for each excess 10kg of cargo bay capacity.
|
||||||
|
if asset.cargobaymax < TotalWeight then
|
||||||
|
score=score+UTILS.Round(asset.cargobaymax/10, 0)
|
||||||
|
else
|
||||||
|
score=score+UTILS.Round(TotalWeight/10, 0)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Add 1 score point for each 10 kg of cargo bay.
|
||||||
|
score=score+UTILS.Round(asset.cargobaymax/10, 0)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: This could be vastly improved. Need to gather ideas during testing.
|
-- TODO: This could be vastly improved. Need to gather ideas during testing.
|
||||||
@@ -3231,14 +3242,15 @@ end
|
|||||||
-- @param #string MissionType Mission type.
|
-- @param #string MissionType Mission type.
|
||||||
-- @param DCS#Vec2 TargetVec2 Target position as 2D vector.
|
-- @param DCS#Vec2 TargetVec2 Target position as 2D vector.
|
||||||
-- @param #boolean IncludePayload If `true`, include the payload in the calulation if the asset has one attached.
|
-- @param #boolean IncludePayload If `true`, include the payload in the calulation if the asset has one attached.
|
||||||
function LEGION._OptimizeAssetSelection(assets, MissionType, TargetVec2, IncludePayload)
|
-- @param #number TotalWeight The total weight of the cargo to be transported, if applicable.
|
||||||
|
function LEGION._OptimizeAssetSelection(assets, MissionType, TargetVec2, IncludePayload, TotalWeight)
|
||||||
|
|
||||||
-- Calculate the mission score of all assets.
|
-- Calculate the mission score of all assets.
|
||||||
for _,_asset in pairs(assets) do
|
for _,_asset in pairs(assets) do
|
||||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
-- Calculate the asset score.
|
-- Calculate the asset score.
|
||||||
asset.score=LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload)
|
asset.score=LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload, TotalWeight)
|
||||||
|
|
||||||
if IncludePayload then
|
if IncludePayload then
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,9 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Navygroup)
|
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Navygroup)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Operation).
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Operation).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -100,7 +100,7 @@
|
|||||||
--
|
--
|
||||||
-- @field #OPSGROUP.Radio radio Current radio settings.
|
-- @field #OPSGROUP.Radio radio Current radio settings.
|
||||||
-- @field #OPSGROUP.Radio radioDefault Default radio settings.
|
-- @field #OPSGROUP.Radio radioDefault Default radio settings.
|
||||||
-- @field Core.RadioQueue#RADIOQUEUE radioQueue Radio queue.
|
-- @field Sound.Radio#RADIOQUEUE radioQueue Radio queue.
|
||||||
--
|
--
|
||||||
-- @field #OPSGROUP.Beacon tacan Current TACAN settings.
|
-- @field #OPSGROUP.Beacon tacan Current TACAN settings.
|
||||||
-- @field #OPSGROUP.Beacon tacanDefault Default TACAN settings.
|
-- @field #OPSGROUP.Beacon tacanDefault Default TACAN settings.
|
||||||
@@ -2314,14 +2314,17 @@ end
|
|||||||
-- @return #OPSGROUP self
|
-- @return #OPSGROUP self
|
||||||
function OPSGROUP:SetSRS(PathToSRS, Gender, Culture, Voice, Port, PathToGoogleKey, Label, Volume)
|
function OPSGROUP:SetSRS(PathToSRS, Gender, Culture, Voice, Port, PathToGoogleKey, Label, Volume)
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
self.msrs=MSRS:New(PathToSRS, self.frequency, self.modulation)
|
local path = PathToSRS or MSRS.path
|
||||||
|
local port = Port or MSRS.port
|
||||||
|
self.msrs=MSRS:New(path, self.frequency, self.modulation)
|
||||||
self.msrs:SetGender(Gender)
|
self.msrs:SetGender(Gender)
|
||||||
self.msrs:SetCulture(Culture)
|
self.msrs:SetCulture(Culture)
|
||||||
self.msrs:SetVoice(Voice)
|
self.msrs:SetVoice(Voice)
|
||||||
self.msrs:SetPort(Port)
|
self.msrs:SetPort(port)
|
||||||
self.msrs:SetLabel(Label)
|
self.msrs:SetLabel(Label)
|
||||||
if PathToGoogleKey then
|
if PathToGoogleKey then
|
||||||
self.msrs:SetGoogle(PathToGoogleKey)
|
self.msrs:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
|
||||||
|
self.msrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
self.msrs:SetCoalition(self:GetCoalition())
|
self.msrs:SetCoalition(self:GetCoalition())
|
||||||
self.msrs:SetVolume(Volume)
|
self.msrs:SetVolume(Volume)
|
||||||
@@ -3472,10 +3475,9 @@ function OPSGROUP:RemoveWaypoint(wpindex)
|
|||||||
|
|
||||||
-- Could be that the waypoint we are currently moving to was the LAST waypoint. Then we now passed the final waypoint.
|
-- Could be that the waypoint we are currently moving to was the LAST waypoint. Then we now passed the final waypoint.
|
||||||
if (self.adinfinitum or istemp) then
|
if (self.adinfinitum or istemp) then
|
||||||
self:_PassedFinalWaypoint(false, "Removed PASSED temporary waypoint ")
|
self:_PassedFinalWaypoint(false, "Removed PASSED temporary waypoint")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -5801,6 +5803,27 @@ function OPSGROUP:onafterMissionDone(From, Event, To, Mission)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.legion and self.legionReturn==false and self.waypoints and #self.waypoints==1 then
|
||||||
|
---
|
||||||
|
-- This is the case where a group was send on a mission (which is over now), has no addional
|
||||||
|
-- waypoints or tasks and should NOT return to its legion.
|
||||||
|
-- We create a new waypoint at the current position and let it hold here.
|
||||||
|
---
|
||||||
|
|
||||||
|
local Coordinate=self:GetCoordinate()
|
||||||
|
|
||||||
|
if self.isArmygroup then
|
||||||
|
ARMYGROUP.AddWaypoint(self, Coordinate, 0, nil, nil, false)
|
||||||
|
elseif self.isNavygroup then
|
||||||
|
NAVYGROUP.AddWaypoint(self,Coordinate, 0, nil, nil, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove original waypoint.
|
||||||
|
self:RemoveWaypoint(1)
|
||||||
|
|
||||||
|
self:_PassedFinalWaypoint(true, "Passed final waypoint as group is done with mission but should NOT return to its legion")
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if group is done.
|
-- Check if group is done.
|
||||||
self:_CheckGroupDone(delay)
|
self:_CheckGroupDone(delay)
|
||||||
|
|
||||||
@@ -7153,7 +7176,7 @@ function OPSGROUP:SetLaserTarget(Target)
|
|||||||
|
|
||||||
-- Scenery as target. Treat it like a coordinate. Set offset to 1 meter above ground.
|
-- Scenery as target. Treat it like a coordinate. Set offset to 1 meter above ground.
|
||||||
self.spot.TargetType=0
|
self.spot.TargetType=0
|
||||||
self.spot.offsetTarget={x=0, y=1, z=0}
|
self.spot.offsetTarget={x=0, y=3, z=0}
|
||||||
|
|
||||||
elseif Target:IsInstanceOf("POSITIONABLE") then
|
elseif Target:IsInstanceOf("POSITIONABLE") then
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Transport).
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Transport).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -605,6 +605,16 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo, DisembarkActi
|
|||||||
self:AddCargoGroups(group, TransportZoneCombo, DisembarkActivation)
|
self:AddCargoGroups(group, TransportZoneCombo, DisembarkActivation)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Use FSM function to keep the SET up-to-date. Note that it overwrites the user FMS function, which cannot be used any more now.
|
||||||
|
local groupset=GroupSet --Core.Set#SET_OPSGROUP
|
||||||
|
function groupset.OnAfterAdded(groupset, From, Event, To, ObjectName, Object)
|
||||||
|
|
||||||
|
self:T(self.lid..string.format("Adding Cargo Group %s", tostring(ObjectName)))
|
||||||
|
self:AddCargoGroups(Object, TransportZoneCombo, DisembarkActivation, DisembarkZone, DisembarkCarriers)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ OPSZONE.ZoneType={
|
|||||||
|
|
||||||
--- OPSZONE class version.
|
--- OPSZONE class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
OPSZONE.version="0.6.0"
|
OPSZONE.version="0.6.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -1277,7 +1277,7 @@ function OPSZONE:EvaluateZone()
|
|||||||
|
|
||||||
if Nblu>0 then
|
if Nblu>0 then
|
||||||
|
|
||||||
if not self:IsAttacked() then
|
if not self:IsAttacked() and self.Tnut>=self.threatlevelCapture then
|
||||||
self:Attacked(coalition.side.BLUE)
|
self:Attacked(coalition.side.BLUE)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1329,7 +1329,7 @@ function OPSZONE:EvaluateZone()
|
|||||||
|
|
||||||
if Nred>0 then
|
if Nred>0 then
|
||||||
|
|
||||||
if not self:IsAttacked() then
|
if not self:IsAttacked() and self.Tnut>=self.threatlevelCapture then
|
||||||
-- Red is attacking blue zone.
|
-- Red is attacking blue zone.
|
||||||
self:Attacked(coalition.side.RED)
|
self:Attacked(coalition.side.RED)
|
||||||
end
|
end
|
||||||
@@ -1483,11 +1483,11 @@ function OPSZONE:_GetZoneColor()
|
|||||||
local color={0,0,0}
|
local color={0,0,0}
|
||||||
|
|
||||||
if self.ownerCurrent==coalition.side.NEUTRAL then
|
if self.ownerCurrent==coalition.side.NEUTRAL then
|
||||||
color={1, 1, 1}
|
color=self.ZoneOwnerNeutral or {1, 1, 1}
|
||||||
elseif self.ownerCurrent==coalition.side.BLUE then
|
elseif self.ownerCurrent==coalition.side.BLUE then
|
||||||
color={0, 0, 1}
|
color=self.ZoneOwnerBlue or {0, 0, 1}
|
||||||
elseif self.ownerCurrent==coalition.side.RED then
|
elseif self.ownerCurrent==coalition.side.RED then
|
||||||
color={1, 0, 0}
|
color=self.ZoneOwnerRed or {1, 0, 0}
|
||||||
else
|
else
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1495,6 +1495,21 @@ function OPSZONE:_GetZoneColor()
|
|||||||
return color
|
return color
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set custom RGB color of zone depending on current owner.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #table Neutral Color is a table of RGB values 0..1 for Red, Green, and Blue respectively, e.g. {1,0,0} for red.
|
||||||
|
-- @param #table Blue Color is a table of RGB values 0..1 for Red, Green, and Blue respectively, e.g. {0,1,0} for green.
|
||||||
|
-- @param #table Red Color is a table of RGB values 0..1 for Red, Green, and Blue respectively, e.g. {0,0,1} for blue.
|
||||||
|
-- @return #OPSZONE self
|
||||||
|
function OPSZONE:SetZoneColor(Neutral, Blue, Red)
|
||||||
|
|
||||||
|
self.ZoneOwnerNeutral = Neutral or {1, 1, 1}
|
||||||
|
self.ZoneOwnerBlue = Blue or {0, 0, 1}
|
||||||
|
self.ZoneOwnerRed = Red or {1, 0, 0}
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Update marker on the F10 map.
|
--- Update marker on the F10 map.
|
||||||
-- @param #OPSZONE self
|
-- @param #OPSZONE self
|
||||||
function OPSZONE:_UpdateMarker()
|
function OPSZONE:_UpdateMarker()
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
-- @field Utilities.FiFo#FIFO TargetCache
|
-- @field Utilities.FiFo#FIFO TargetCache
|
||||||
-- @field #boolean smokeownposition
|
-- @field #boolean smokeownposition
|
||||||
-- @field #table SmokeOwn
|
-- @field #table SmokeOwn
|
||||||
|
-- @field #boolean smokeaveragetargetpos
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -104,7 +105,7 @@ PLAYERRECCE = {
|
|||||||
ClassName = "PLAYERRECCE",
|
ClassName = "PLAYERRECCE",
|
||||||
verbose = true,
|
verbose = true,
|
||||||
lid = nil,
|
lid = nil,
|
||||||
version = "0.0.21",
|
version = "0.1.23",
|
||||||
ViewZone = {},
|
ViewZone = {},
|
||||||
ViewZoneVisual = {},
|
ViewZoneVisual = {},
|
||||||
ViewZoneLaser = {},
|
ViewZoneLaser = {},
|
||||||
@@ -130,8 +131,9 @@ PLAYERRECCE = {
|
|||||||
ReferencePoint = nil,
|
ReferencePoint = nil,
|
||||||
TForget = 600,
|
TForget = 600,
|
||||||
TargetCache = nil,
|
TargetCache = nil,
|
||||||
smokeownposition = true,
|
smokeownposition = false,
|
||||||
SmokeOwn = {},
|
SmokeOwn = {},
|
||||||
|
smokeaveragetargetpos = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -469,8 +471,10 @@ function PLAYERRECCE:_GetClockDirection(unit, target)
|
|||||||
local _playerPosition = unit:GetCoordinate() -- get position of helicopter
|
local _playerPosition = unit:GetCoordinate() -- get position of helicopter
|
||||||
local _targetpostions = target:GetCoordinate() -- get position of downed pilot
|
local _targetpostions = target:GetCoordinate() -- get position of downed pilot
|
||||||
local _heading = unit:GetHeading() -- heading
|
local _heading = unit:GetHeading() -- heading
|
||||||
|
--self:I("Heading = ".._heading)
|
||||||
local DirectionVec3 = _playerPosition:GetDirectionVec3( _targetpostions )
|
local DirectionVec3 = _playerPosition:GetDirectionVec3( _targetpostions )
|
||||||
local Angle = _playerPosition:GetAngleDegrees( DirectionVec3 )
|
local Angle = _playerPosition:GetAngleDegrees( DirectionVec3 )
|
||||||
|
--self:I("Angle = "..Angle)
|
||||||
local clock = 12
|
local clock = 12
|
||||||
local hours = 0
|
local hours = 0
|
||||||
if _heading and Angle then
|
if _heading and Angle then
|
||||||
@@ -478,10 +482,13 @@ function PLAYERRECCE:_GetClockDirection(unit, target)
|
|||||||
--if angle == 0 then angle = 360 end
|
--if angle == 0 then angle = 360 end
|
||||||
clock = _heading-Angle
|
clock = _heading-Angle
|
||||||
hours = (clock/30)*-1
|
hours = (clock/30)*-1
|
||||||
|
--self:I("hours = "..hours)
|
||||||
clock = 12+hours
|
clock = 12+hours
|
||||||
clock = UTILS.Round(clock,0)
|
clock = UTILS.Round(clock,0)
|
||||||
if clock > 12 then clock = clock-12 end
|
if clock > 12 then clock = clock-12 end
|
||||||
end
|
if clock == 0 then clock = 12 end
|
||||||
|
end
|
||||||
|
--self:I("Clock ="..clock)
|
||||||
return clock
|
return clock
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -709,8 +716,8 @@ function PLAYERRECCE:_GetViewZone(unit, vheading, minview, maxview, angle, camon
|
|||||||
local heading2 = (vheading-90)%360
|
local heading2 = (vheading-90)%360
|
||||||
self:T({heading1,heading2})
|
self:T({heading1,heading2})
|
||||||
local startpos = startp:Translate(minview,vheading)
|
local startpos = startp:Translate(minview,vheading)
|
||||||
local pos1 = startpos:Translate(10,heading1)
|
local pos1 = startpos:Translate(12.5,heading1)
|
||||||
local pos2 = startpos:Translate(10,heading2)
|
local pos2 = startpos:Translate(12.5,heading2)
|
||||||
local pos3 = pos1:Translate(maxview,vheading)
|
local pos3 = pos1:Translate(maxview,vheading)
|
||||||
local pos4 = pos2:Translate(maxview,vheading)
|
local pos4 = pos2:Translate(maxview,vheading)
|
||||||
local array = {}
|
local array = {}
|
||||||
@@ -912,31 +919,49 @@ function PLAYERRECCE:_LaseTarget(client,targetset)
|
|||||||
else
|
else
|
||||||
laser = self.LaserSpots[playername]
|
laser = self.LaserSpots[playername]
|
||||||
end
|
end
|
||||||
|
-- old target
|
||||||
if self.LaserTarget[playername] then
|
if self.LaserTarget[playername] then
|
||||||
-- still looking at target?
|
-- still looking at target?
|
||||||
local target=self.LaserTarget[playername] -- Ops.Target#TARGET
|
local target=self.LaserTarget[playername] -- Ops.Target#TARGET
|
||||||
local oldtarget = target:GetObject() --or laser.Target
|
local oldtarget = target:GetObject() --or laser.Target
|
||||||
self:T("Targetstate: "..target:GetState())
|
self:T("Targetstate: "..target:GetState())
|
||||||
if not oldtarget or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then
|
self:T("Laser State: "..tostring(laser:IsLasing()))
|
||||||
|
if (not oldtarget) or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then
|
||||||
-- lost LOS or dead
|
-- lost LOS or dead
|
||||||
laser:LaseOff()
|
laser:LaseOff()
|
||||||
if target:IsDead() or target:IsDestroyed() or target:GetLife() < 2 then
|
if target:IsDead() or target:IsDestroyed() or target:GetLife() < 2 then
|
||||||
self:__Shack(-1,client,oldtarget)
|
self:__Shack(-1,client,oldtarget)
|
||||||
self.LaserTarget[playername] = nil
|
--self.LaserTarget[playername] = nil
|
||||||
else
|
else
|
||||||
self:__TargetLOSLost(-1,client,oldtarget)
|
self:__TargetLOSLost(-1,client,oldtarget)
|
||||||
self.LaserTarget[playername] = nil
|
--self.LaserTarget[playername] = nil
|
||||||
end
|
end
|
||||||
|
self.LaserTarget[playername] = nil
|
||||||
|
oldtarget = nil
|
||||||
|
self.LaserSpots[playername] = nil
|
||||||
|
elseif oldtarget and laser and (not laser:IsLasing()) then
|
||||||
|
--laser:LaseOff()
|
||||||
|
self:T("Switching laser back on ..")
|
||||||
|
local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688
|
||||||
|
local lasingtime = self.lasingtime or 60
|
||||||
|
--local targettype = target:GetTypeName()
|
||||||
|
laser:LaseOn(oldtarget,lasercode,lasingtime)
|
||||||
|
--self:__TargetLasing(-1,client,oldtarget,lasercode,lasingtime)
|
||||||
|
else
|
||||||
|
-- we should not be here...
|
||||||
|
self:T("Target alive and laser is on!")
|
||||||
|
--self.LaserSpots[playername] = nil
|
||||||
end
|
end
|
||||||
elseif not laser:IsLasing() and target then
|
-- new target
|
||||||
|
elseif (not laser:IsLasing()) and target then
|
||||||
local relativecam = self.LaserRelativePos[client:GetTypeName()]
|
local relativecam = self.LaserRelativePos[client:GetTypeName()]
|
||||||
laser:SetRelativeStartPosition(relativecam)
|
laser:SetRelativeStartPosition(relativecam)
|
||||||
local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688
|
local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688
|
||||||
local lasingtime = self.lasingtime or 60
|
local lasingtime = self.lasingtime or 60
|
||||||
local targettype = target:GetTypeName()
|
--local targettype = target:GetTypeName()
|
||||||
laser:LaseOn(target,lasercode,lasingtime)
|
laser:LaseOn(target,lasercode,lasingtime)
|
||||||
self.LaserTarget[playername] = TARGET:New(target)
|
self.LaserTarget[playername] = TARGET:New(target)
|
||||||
self.LaserTarget[playername].TStatus = 9
|
--self.LaserTarget[playername].TStatus = 9
|
||||||
self:__TargetLasing(-1,client,target,lasercode,lasingtime)
|
self:__TargetLasing(-1,client,target,lasercode,lasingtime)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
@@ -1018,6 +1043,13 @@ function PLAYERRECCE:_SwitchLasing(client,group,playername)
|
|||||||
MESSAGE:New("Lasing is now ON",10,self.Name or "FACA"):ToClient(client)
|
MESSAGE:New("Lasing is now ON",10,self.Name or "FACA"):ToClient(client)
|
||||||
else
|
else
|
||||||
self.AutoLase[playername] = false
|
self.AutoLase[playername] = false
|
||||||
|
if self.LaserSpots[playername] then
|
||||||
|
local laser = self.LaserSpots[playername] -- Core.Spot#SPOT
|
||||||
|
if laser:IsLasing() then
|
||||||
|
laser:LaseOff()
|
||||||
|
end
|
||||||
|
self.LaserSpots[playername] = nil
|
||||||
|
end
|
||||||
MESSAGE:New("Lasing is now OFF",10,self.Name or "FACA"):ToClient(client)
|
MESSAGE:New("Lasing is now OFF",10,self.Name or "FACA"):ToClient(client)
|
||||||
end
|
end
|
||||||
if self.ClientMenus[playername] then
|
if self.ClientMenus[playername] then
|
||||||
@@ -1079,9 +1111,8 @@ function PLAYERRECCE:_SmokeTargets(client,group,playername)
|
|||||||
self:T(self.lid.."_SmokeTargets")
|
self:T(self.lid.."_SmokeTargets")
|
||||||
local cameraset = self:_GetTargetSet(client,true) -- Core.Set#SET_UNIT
|
local cameraset = self:_GetTargetSet(client,true) -- Core.Set#SET_UNIT
|
||||||
local visualset = self:_GetTargetSet(client,false) -- Core.Set#SET_UNIT
|
local visualset = self:_GetTargetSet(client,false) -- Core.Set#SET_UNIT
|
||||||
cameraset:AddSet(visualset)
|
|
||||||
|
|
||||||
if cameraset:CountAlive() > 0 then
|
if cameraset:CountAlive() > 0 or visualset:CountAlive() > 0 then
|
||||||
self:__TargetsSmoked(-1,client,playername,cameraset)
|
self:__TargetsSmoked(-1,client,playername,cameraset)
|
||||||
else
|
else
|
||||||
return self
|
return self
|
||||||
@@ -1096,25 +1127,31 @@ function PLAYERRECCE:_SmokeTargets(client,group,playername)
|
|||||||
-- laser targer gets extra smoke
|
-- laser targer gets extra smoke
|
||||||
if laser and laser.Target and laser.Target:IsAlive() then
|
if laser and laser.Target and laser.Target:IsAlive() then
|
||||||
laser.Target:GetCoordinate():Smoke(lasersmoke)
|
laser.Target:GetCoordinate():Smoke(lasersmoke)
|
||||||
if cameraset:IsInSet(laser.Target) then
|
|
||||||
cameraset:Remove(laser.Target:GetName(),true)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- smoke everything else
|
local coord = visualset:GetCoordinate()
|
||||||
local coordinate = cameraset:GetCoordinate()
|
if coord and self.smokeaveragetargetpos then
|
||||||
local setthreat = cameraset:CalculateThreatLevelA2G()
|
coord:SetAtLandheight()
|
||||||
|
coord:Smoke(medsmoke)
|
||||||
if coordinate then
|
else
|
||||||
local color = lowsmoke
|
-- smoke everything
|
||||||
if setthreat > 7 then
|
for _,_unit in pairs(visualset.Set) do
|
||||||
color = medsmoke
|
local unit = _unit --Wrapper.Unit#UNIT
|
||||||
elseif setthreat > 2 then
|
if unit and unit:IsAlive() then
|
||||||
color = lowsmoke
|
local coord = unit:GetCoordinate()
|
||||||
|
local threat = unit:GetThreatLevel()
|
||||||
|
if coord then
|
||||||
|
local color = lowsmoke
|
||||||
|
if threat > 7 then
|
||||||
|
color = highsmoke
|
||||||
|
elseif threat > 2 then
|
||||||
|
color = medsmoke
|
||||||
|
end
|
||||||
|
coord:Smoke(color)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
coordinate:Smoke(color)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.SmokeOwn[playername] then
|
if self.SmokeOwn[playername] then
|
||||||
local cc = client:GetVec2()
|
local cc = client:GetVec2()
|
||||||
-- don't smoke mid-air
|
-- don't smoke mid-air
|
||||||
@@ -1155,15 +1192,15 @@ function PLAYERRECCE:_FlareTargets(client,group,playername)
|
|||||||
-- smoke everything else
|
-- smoke everything else
|
||||||
for _,_unit in pairs(cameraset.Set) do
|
for _,_unit in pairs(cameraset.Set) do
|
||||||
local unit = _unit --Wrapper.Unit#UNIT
|
local unit = _unit --Wrapper.Unit#UNIT
|
||||||
if unit then
|
if unit and unit:IsAlive() then
|
||||||
local coord = unit:GetCoordinate()
|
local coord = unit:GetCoordinate()
|
||||||
local threat = unit:GetThreatLevel()
|
local threat = unit:GetThreatLevel()
|
||||||
if coord then
|
if coord then
|
||||||
local color = lowsmoke
|
local color = lowsmoke
|
||||||
if threat > 7 then
|
if threat > 7 then
|
||||||
color = medsmoke
|
color = highsmoke
|
||||||
elseif threat > 2 then
|
elseif threat > 2 then
|
||||||
color = lowsmoke
|
color = medsmoke
|
||||||
end
|
end
|
||||||
coord:Flare(color)
|
coord:Flare(color)
|
||||||
end
|
end
|
||||||
@@ -1451,36 +1488,43 @@ end
|
|||||||
-- @param #string Gender (Optional) Defaults to "male"
|
-- @param #string Gender (Optional) Defaults to "male"
|
||||||
-- @param #string Culture (Optional) Defaults to "en-US"
|
-- @param #string Culture (Optional) Defaults to "en-US"
|
||||||
-- @param #number Port (Optional) Defaults to 5002
|
-- @param #number Port (Optional) Defaults to 5002
|
||||||
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS#SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
||||||
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
||||||
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
||||||
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
|
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
|
||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
|
function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
|
||||||
self:T(self.lid.."SetSRS")
|
self:T(self.lid.."SetSRS")
|
||||||
self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
|
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
|
||||||
self.Gender = Gender or "male" --
|
self.Gender = Gender or MSRS.gender or "male" --
|
||||||
self.Culture = Culture or "en-US" --
|
self.Culture = Culture or MSRS.culture or "en-US" --
|
||||||
self.Port = Port or 5002 --
|
self.Port = Port or MSRS.port or 5002 --
|
||||||
self.Voice = Voice --
|
self.Voice = Voice or MSRS.voice --
|
||||||
self.PathToGoogleKey = PathToGoogleKey --
|
self.PathToGoogleKey = PathToGoogleKey --
|
||||||
self.Volume = Volume or 1.0 --
|
self.Volume = Volume or 1.0 --
|
||||||
self.UseSRS = true
|
self.UseSRS = true
|
||||||
self.Frequency = Frequency or {127,251} --
|
self.Frequency = Frequency or {127,251} --
|
||||||
self.BCFrequency = self.Frequency
|
self.BCFrequency = self.Frequency
|
||||||
self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
|
self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
|
||||||
self.BCModulation = self.Modulation
|
self.BCModulation = self.Modulation
|
||||||
-- set up SRS
|
-- set up SRS
|
||||||
self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation,self.Volume)
|
self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation)
|
||||||
self.SRS:SetCoalition(self.Coalition)
|
self.SRS:SetCoalition(self.Coalition)
|
||||||
self.SRS:SetLabel(self.MenuName or self.Name)
|
self.SRS:SetLabel(self.MenuName or self.Name)
|
||||||
self.SRS:SetGender(self.Gender)
|
self.SRS:SetGender(self.Gender)
|
||||||
self.SRS:SetCulture(self.Culture)
|
self.SRS:SetCulture(self.Culture)
|
||||||
self.SRS:SetPort(self.Port)
|
self.SRS:SetPort(self.Port)
|
||||||
self.SRS:SetVoice(self.Voice)
|
self.SRS:SetVolume(self.Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.SRS:SetGoogle(self.PathToGoogleKey)
|
self.SRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.PathToGoogleKey)
|
||||||
|
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
|
-- Pre-configured Google?
|
||||||
|
if (not PathToGoogleKey) and self.SRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
|
self.PathToGoogleKey = MSRS.poptions.gcloud.credentials
|
||||||
|
self.Voice = Voice or MSRS.poptions.gcloud.voice
|
||||||
|
end
|
||||||
|
self.SRS:SetVoice(self.Voice)
|
||||||
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
|
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
|
||||||
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
||||||
return self
|
return self
|
||||||
@@ -1512,7 +1556,7 @@ end
|
|||||||
-- @param #PLAYERRECCE self
|
-- @param #PLAYERRECCE self
|
||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:EnableSmokeOwnPosition()
|
function PLAYERRECCE:EnableSmokeOwnPosition()
|
||||||
self:T(self.lid.."ENableSmokeOwnPosition")
|
self:T(self.lid.."EnableSmokeOwnPosition")
|
||||||
self.smokeownposition = true
|
self.smokeownposition = true
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1526,6 +1570,24 @@ function PLAYERRECCE:DisableSmokeOwnPosition()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Enable smoking of average target positions, instead of all targets visible. Loses smoke per threatlevel -- each is med threat. Default is - smoke all positions.
|
||||||
|
-- @param #PLAYERRECCE self
|
||||||
|
-- @return #PLAYERRECCE self
|
||||||
|
function PLAYERRECCE:EnableSmokeAverageTargetPosition()
|
||||||
|
self:T(self.lid.."ENableSmokeOwnPosition")
|
||||||
|
self.smokeaveragetargetpos = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [User] Disable smoking of average target positions, instead of all targets visible. Default is - smoke all positions.
|
||||||
|
-- @param #PLAYERRECCE self
|
||||||
|
-- @return #PLAYERRECCE
|
||||||
|
function PLAYERRECCE:DisableSmokeAverageTargetPosition()
|
||||||
|
self:T(self.lid.."DisableSmokeAverageTargetPosition")
|
||||||
|
self.smokeaveragetargetpos = false
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [Internal] Get text for text-to-speech.
|
--- [Internal] Get text for text-to-speech.
|
||||||
-- Numbers are spaced out, e.g. "Heading 180" becomes "Heading 1 8 0 ".
|
-- Numbers are spaced out, e.g. "Heading 180" becomes "Heading 1 8 0 ".
|
||||||
-- @param #PLAYERRECCE self
|
-- @param #PLAYERRECCE self
|
||||||
@@ -1668,7 +1730,7 @@ function PLAYERRECCE:onafterRecceOnStation(From, Event, To, Client, Playername)
|
|||||||
local text2tts = string.format("All stations, FACA %s on station at %s!",callsign, coordtext)
|
local text2tts = string.format("All stations, FACA %s on station at %s!",callsign, coordtext)
|
||||||
text2tts = self:_GetTextForSpeech(text2tts)
|
text2tts = self:_GetTextForSpeech(text2tts)
|
||||||
if self.debug then
|
if self.debug then
|
||||||
self:I(text2.."\n"..text2tts)
|
self:T(text2.."\n"..text2tts)
|
||||||
end
|
end
|
||||||
if self.UseSRS then
|
if self.UseSRS then
|
||||||
local grp = Client:GetGroup()
|
local grp = Client:GetGroup()
|
||||||
@@ -1707,7 +1769,7 @@ function PLAYERRECCE:onafterRecceOffStation(From, Event, To, Client, Playername)
|
|||||||
local texttts = string.format("All stations, FACA %s leaving station at %s, good bye!",callsign, coordtext)
|
local texttts = string.format("All stations, FACA %s leaving station at %s, good bye!",callsign, coordtext)
|
||||||
texttts = self:_GetTextForSpeech(texttts)
|
texttts = self:_GetTextForSpeech(texttts)
|
||||||
if self.debug then
|
if self.debug then
|
||||||
self:I(text.."\n"..texttts)
|
self:T(text.."\n"..texttts)
|
||||||
end
|
end
|
||||||
local text1 = "Going home!"
|
local text1 = "Going home!"
|
||||||
if self.UseSRS then
|
if self.UseSRS then
|
||||||
@@ -1983,7 +2045,7 @@ function PLAYERRECCE:onafterTargetLasing(From, Event, To, Client, Target, Laserc
|
|||||||
coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings)
|
coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings)
|
||||||
end
|
end
|
||||||
local coordtext = coord:ToStringA2G(client,Settings)
|
local coordtext = coord:ToStringA2G(client,Settings)
|
||||||
local text = string.format("All stations, %s lasing %s\nat %s!\nCode %d, Duration %d seconds!",callsign, targettype, coordtext, Lasercode, Lasingtime)
|
local text = string.format("All stations, %s lasing %s\nat %s!\nCode %d, Duration %d plus seconds!",callsign, targettype, coordtext, Lasercode, Lasingtime)
|
||||||
MESSAGE:New(text,15,self.Name or "FACA"):ToClient(client)
|
MESSAGE:New(text,15,self.Name or "FACA"):ToClient(client)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Example Missions:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20PlayerTask).
|
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/PlayerTask).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
-- @module Ops.PlayerTask
|
-- @module Ops.PlayerTask
|
||||||
-- @image OPS_PlayerTask.jpg
|
-- @image OPS_PlayerTask.jpg
|
||||||
-- @date Last Update Oct 2023
|
-- @date Last Update Jan 2024
|
||||||
|
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -45,8 +45,8 @@ do
|
|||||||
-- @field Wrapper.Marker#MARKER TargetMarker
|
-- @field Wrapper.Marker#MARKER TargetMarker
|
||||||
-- @field #number SmokeColor
|
-- @field #number SmokeColor
|
||||||
-- @field #number FlareColor
|
-- @field #number FlareColor
|
||||||
-- @field #table conditionSuccess = {},
|
-- @field #table conditionSuccess
|
||||||
-- @field #table conditionFailure = {},
|
-- @field #table conditionFailure
|
||||||
-- @field Ops.PlayerTask#PLAYERTASKCONTROLLER TaskController
|
-- @field Ops.PlayerTask#PLAYERTASKCONTROLLER TaskController
|
||||||
-- @field #number timestamp
|
-- @field #number timestamp
|
||||||
-- @field #number lastsmoketime
|
-- @field #number lastsmoketime
|
||||||
@@ -98,7 +98,7 @@ PLAYERTASK = {
|
|||||||
|
|
||||||
--- PLAYERTASK class version.
|
--- PLAYERTASK class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
PLAYERTASK.version="0.1.22"
|
PLAYERTASK.version="0.1.24"
|
||||||
|
|
||||||
--- Generic task condition.
|
--- Generic task condition.
|
||||||
-- @type PLAYERTASK.Condition
|
-- @type PLAYERTASK.Condition
|
||||||
@@ -974,7 +974,7 @@ do
|
|||||||
-- @field #string locale
|
-- @field #string locale
|
||||||
-- @field #boolean precisionbombing
|
-- @field #boolean precisionbombing
|
||||||
-- @field Ops.FlightGroup#FLIGHTGROUP LasingDrone
|
-- @field Ops.FlightGroup#FLIGHTGROUP LasingDrone
|
||||||
-- @field Core.MarkerOps_BASE#MARKEROPS_BASE MarkerOps
|
-- @field Core.MarkerOps_Base#MARKEROPS_BASE MarkerOps
|
||||||
-- @field #boolean taskinfomenu
|
-- @field #boolean taskinfomenu
|
||||||
-- @field #boolean MarkerReadOnly
|
-- @field #boolean MarkerReadOnly
|
||||||
-- @field #table FlashPlayer List of player who switched Flashing Direction Info on
|
-- @field #table FlashPlayer List of player who switched Flashing Direction Info on
|
||||||
@@ -1028,7 +1028,7 @@ do
|
|||||||
-- ## 1 Overview
|
-- ## 1 Overview
|
||||||
--
|
--
|
||||||
-- PLAYERTASKCONTROLLER is used to auto-create (optional) and control tasks for players. It can be set up as Air-to-Ground (A2G, main focus), Air-to-Ship (A2S) or Air-to-Air (A2A) controller.
|
-- PLAYERTASKCONTROLLER is used to auto-create (optional) and control tasks for players. It can be set up as Air-to-Ground (A2G, main focus), Air-to-Ship (A2S) or Air-to-Air (A2A) controller.
|
||||||
-- For the latter task type, also have a look at the @{Ops.Awacs#AWACS} class which allows for more complex scenarios.
|
-- For the latter task type, also have a look at the @{Ops.AWACS#AWACS} class which allows for more complex scenarios.
|
||||||
-- One task at a time can be joined by the player from the F10 menu. A task can be joined by multiple players. Once joined, task information is available via the F10 menu, the task location
|
-- One task at a time can be joined by the player from the F10 menu. A task can be joined by multiple players. Once joined, task information is available via the F10 menu, the task location
|
||||||
-- can be marked on the map and for A2G/S targets, the target can be marked with smoke and flares.
|
-- can be marked on the map and for A2G/S targets, the target can be marked with smoke and flares.
|
||||||
--
|
--
|
||||||
@@ -1552,7 +1552,7 @@ PLAYERTASKCONTROLLER.Messages = {
|
|||||||
|
|
||||||
--- PLAYERTASK class version.
|
--- PLAYERTASK class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
PLAYERTASKCONTROLLER.version="0.1.63"
|
PLAYERTASKCONTROLLER.version="0.1.64"
|
||||||
|
|
||||||
--- Create and run a new TASKCONTROLLER instance.
|
--- Create and run a new TASKCONTROLLER instance.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
@@ -1579,7 +1579,7 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
|
|||||||
self.ClusterRadius = 0.5
|
self.ClusterRadius = 0.5
|
||||||
self.TargetRadius = 500
|
self.TargetRadius = 500
|
||||||
|
|
||||||
self.ClientFilter = ClientFilter or ""
|
self.ClientFilter = ClientFilter --or ""
|
||||||
|
|
||||||
self.TargetQueue = FIFO:New() -- Utilities.FiFo#FIFO
|
self.TargetQueue = FIFO:New() -- Utilities.FiFo#FIFO
|
||||||
self.TaskQueue = FIFO:New() -- Utilities.FiFo#FIFO
|
self.TaskQueue = FIFO:New() -- Utilities.FiFo#FIFO
|
||||||
@@ -1965,6 +1965,9 @@ end
|
|||||||
-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FlightGroup (e.g. drone) to be used for lasing (one unit in one group only).
|
-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FlightGroup (e.g. drone) to be used for lasing (one unit in one group only).
|
||||||
-- Can optionally be handed as Ops.ArmyGroup#ARMYGROUP - **Note** might not find an LOS spot or get lost on the way. Cannot island-hop.
|
-- Can optionally be handed as Ops.ArmyGroup#ARMYGROUP - **Note** might not find an LOS spot or get lost on the way. Cannot island-hop.
|
||||||
-- @param #number LaserCode The lasercode to be used. Defaults to 1688.
|
-- @param #number LaserCode The lasercode to be used. Defaults to 1688.
|
||||||
|
-- @param Core.Point#COORDINATE HoldingPoint (Optional) Point where the drone should initially circle. If not set, defaults to BullsEye of the coalition.
|
||||||
|
-- @param #number Alt (Optional) Altitude in feet. Only applies if using a FLIGHTGROUP object! Defaults to 10000.
|
||||||
|
-- @param #number Speed (Optional) Speed in knots. Only applies if using a FLIGHTGROUP object! Defaults to 120.
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Set up precision bombing, FlightGroup as lasing unit
|
-- -- Set up precision bombing, FlightGroup as lasing unit
|
||||||
@@ -1979,7 +1982,7 @@ end
|
|||||||
-- ArmyGroup:Activate()
|
-- ArmyGroup:Activate()
|
||||||
-- taskmanager:EnablePrecisionBombing(ArmyGroup,1688)
|
-- taskmanager:EnablePrecisionBombing(ArmyGroup,1688)
|
||||||
--
|
--
|
||||||
function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode)
|
function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode,HoldingPoint, Alt, Speed)
|
||||||
self:T(self.lid.."EnablePrecisionBombing")
|
self:T(self.lid.."EnablePrecisionBombing")
|
||||||
if FlightGroup then
|
if FlightGroup then
|
||||||
if FlightGroup.ClassName and (FlightGroup.ClassName == "FLIGHTGROUP" or FlightGroup.ClassName == "ARMYGROUP")then
|
if FlightGroup.ClassName and (FlightGroup.ClassName == "FLIGHTGROUP" or FlightGroup.ClassName == "ARMYGROUP")then
|
||||||
@@ -1992,10 +1995,20 @@ function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode)
|
|||||||
self.LasingDrone:SetLaser(LaserCode)
|
self.LasingDrone:SetLaser(LaserCode)
|
||||||
self.LaserCode = LaserCode or 1688
|
self.LaserCode = LaserCode or 1688
|
||||||
self.LasingDroneTemplate = self.LasingDrone:_GetTemplate(true)
|
self.LasingDroneTemplate = self.LasingDrone:_GetTemplate(true)
|
||||||
|
self.LasingDroneAlt = Alt or 10000
|
||||||
|
self.LasingDroneSpeed = Speed or 120
|
||||||
-- let it orbit the BullsEye if FG
|
-- let it orbit the BullsEye if FG
|
||||||
if self.LasingDrone:IsFlightgroup() then
|
if self.LasingDrone:IsFlightgroup() then
|
||||||
|
self.LasingDroneIsFlightgroup = true
|
||||||
local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( self.Coalition ))
|
local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( self.Coalition ))
|
||||||
local Orbit = AUFTRAG:NewORBIT_CIRCLE(BullsCoordinate,10000,120)
|
if HoldingPoint then BullsCoordinate = HoldingPoint end
|
||||||
|
local Orbit = AUFTRAG:NewORBIT_CIRCLE(BullsCoordinate,self.LasingDroneAlt,self.LasingDroneSpeed)
|
||||||
|
self.LasingDrone:AddMission(Orbit)
|
||||||
|
elseif self.LasingDrone:IsArmygroup() then
|
||||||
|
self.LasingDroneIsArmygroup = true
|
||||||
|
local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( self.Coalition ))
|
||||||
|
if HoldingPoint then BullsCoordinate = HoldingPoint end
|
||||||
|
local Orbit = AUFTRAG:NewONGUARD(BullsCoordinate)
|
||||||
self.LasingDrone:AddMission(Orbit)
|
self.LasingDrone:AddMission(Orbit)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -2534,10 +2547,16 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
if self.LasingDrone then
|
if self.LasingDrone then
|
||||||
self.LasingDrone:_Respawn(1,nil,true)
|
self.LasingDrone:_Respawn(1,nil,true)
|
||||||
else
|
else
|
||||||
-- TODO: Handle ArmyGroup
|
-- DONE: Handle ArmyGroup
|
||||||
local FG = FLIGHTGROUP:New(self.LasingDroneTemplate)
|
if self.LasingDroneIsFlightgroup then
|
||||||
FG:Activate()
|
local FG = FLIGHTGROUP:New(self.LasingDroneTemplate)
|
||||||
self:EnablePrecisionBombing(FG,self.LaserCode or 1688)
|
FG:Activate()
|
||||||
|
self:EnablePrecisionBombing(FG,self.LaserCode or 1688)
|
||||||
|
else
|
||||||
|
local FG = ARMYGROUP:New(self.LasingDroneTemplate)
|
||||||
|
FG:Activate()
|
||||||
|
self:EnablePrecisionBombing(FG,self.LaserCode or 1688)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -2552,12 +2571,11 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
self.LasingDrone.playertask.inreach = false
|
self.LasingDrone.playertask.inreach = false
|
||||||
self.LasingDrone.playertask.reachmessage = false
|
self.LasingDrone.playertask.reachmessage = false
|
||||||
-- move the drone to target
|
-- move the drone to target
|
||||||
if self.LasingDrone:IsFlightgroup() then
|
if self.LasingDroneIsFlightgroup then
|
||||||
local auftrag = AUFTRAG:NewORBIT_CIRCLE(task.Target:GetCoordinate(),10000,120)
|
self.LasingDrone:CancelAllMissions()
|
||||||
local currmission = self.LasingDrone:GetMissionCurrent()
|
local auftrag = AUFTRAG:NewORBIT_CIRCLE(task.Target:GetCoordinate(),self.LasingDroneAlt,self.LasingDroneSpeed)
|
||||||
self.LasingDrone:AddMission(auftrag)
|
self.LasingDrone:AddMission(auftrag)
|
||||||
currmission:__Cancel(-2)
|
elseif self.LasingDroneIsArmygroup then
|
||||||
elseif self.LasingDrone:IsArmygroup() then
|
|
||||||
local tgtcoord = task.Target:GetCoordinate()
|
local tgtcoord = task.Target:GetCoordinate()
|
||||||
local tgtzone = ZONE_RADIUS:New("ArmyGroup-"..math.random(1,10000),tgtcoord:GetVec2(),3000)
|
local tgtzone = ZONE_RADIUS:New("ArmyGroup-"..math.random(1,10000),tgtcoord:GetVec2(),3000)
|
||||||
local finalpos=nil -- Core.Point#COORDINATE
|
local finalpos=nil -- Core.Point#COORDINATE
|
||||||
@@ -2570,11 +2588,10 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if finalpos then
|
if finalpos then
|
||||||
|
self.LasingDrone:CancelAllMissions()
|
||||||
-- yeah we got one
|
-- yeah we got one
|
||||||
local auftrag = AUFTRAG:NewARMOREDGUARD(finalpos,"Off road")
|
local auftrag = AUFTRAG:NewARMOREDGUARD(finalpos,"Off road")
|
||||||
local currmission = self.LasingDrone:GetMissionCurrent()
|
|
||||||
self.LasingDrone:AddMission(auftrag)
|
self.LasingDrone:AddMission(auftrag)
|
||||||
if currmission then currmission:__Cancel(-2) end
|
|
||||||
else
|
else
|
||||||
-- could not find LOS position!
|
-- could not find LOS position!
|
||||||
self:E("***Could not find LOS position to post ArmyGroup for lasing!")
|
self:E("***Could not find LOS position to post ArmyGroup for lasing!")
|
||||||
@@ -2606,6 +2623,7 @@ function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
|
|||||||
-- not done yet
|
-- not done yet
|
||||||
local dcoord = self.LasingDrone:GetCoordinate()
|
local dcoord = self.LasingDrone:GetCoordinate()
|
||||||
local tcoord = task.Target:GetCoordinate()
|
local tcoord = task.Target:GetCoordinate()
|
||||||
|
tcoord.y = tcoord.y + 2
|
||||||
local dist = dcoord:Get2DDistance(tcoord)
|
local dist = dcoord:Get2DDistance(tcoord)
|
||||||
-- close enough?
|
-- close enough?
|
||||||
if dist < 3000 and not self.LasingDrone:IsLasing() then
|
if dist < 3000 and not self.LasingDrone:IsLasing() then
|
||||||
@@ -3189,7 +3207,7 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Task, Group, Client)
|
|||||||
local islasing = self.LasingDrone:IsLasing() == true and yes or no
|
local islasing = self.LasingDrone:IsLasing() == true and yes or no
|
||||||
local prectext = self.gettext:GetEntry("POINTERTARGETREPORT",self.locale)
|
local prectext = self.gettext:GetEntry("POINTERTARGETREPORT",self.locale)
|
||||||
prectext = string.format(prectext,inreach,islasing)
|
prectext = string.format(prectext,inreach,islasing)
|
||||||
text = text .. prectext
|
text = text .. prectext.." ("..self.LaserCode..")"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Buddylasing
|
-- Buddylasing
|
||||||
@@ -3993,7 +4011,7 @@ function PLAYERTASKCONTROLLER:SetupIntel(RecceName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Set SRS TTS details - see @{Sound.SRS} for details
|
--- [User] Set SRS TTS details - see @{Sound.SRS} for details.`SetSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations!
|
-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations!
|
||||||
-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies!
|
-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies!
|
||||||
@@ -4001,20 +4019,22 @@ end
|
|||||||
-- @param #string Gender (Optional) Defaults to "male"
|
-- @param #string Gender (Optional) Defaults to "male"
|
||||||
-- @param #string Culture (Optional) Defaults to "en-US"
|
-- @param #string Culture (Optional) Defaults to "en-US"
|
||||||
-- @param #number Port (Optional) Defaults to 5002
|
-- @param #number Port (Optional) Defaults to 5002
|
||||||
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS#SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
||||||
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
||||||
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
||||||
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
|
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS; if you use a config file for MSRS, hand in nil here.
|
||||||
|
-- @param #string AccessKey (Optional) Your Google API access key. This is necessary if DCS-gRPC is used as backend; if you use a config file for MSRS, hand in nil here.
|
||||||
-- @param Core.Point#COORDINATE Coordinate Coordinate from which the controller radio is sending
|
-- @param Core.Point#COORDINATE Coordinate Coordinate from which the controller radio is sending
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,Coordinate)
|
function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey,Coordinate)
|
||||||
self:T(self.lid.."SetSRS")
|
self:T(self.lid.."SetSRS")
|
||||||
self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
|
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
|
||||||
self.Gender = Gender or "male" --
|
self.Gender = Gender or MSRS.gender or "male" --
|
||||||
self.Culture = Culture or "en-US" --
|
self.Culture = Culture or MSRS.culture or "en-US" --
|
||||||
self.Port = Port or 5002 --
|
self.Port = Port or MSRS.port or 5002 --
|
||||||
self.Voice = Voice --
|
self.Voice = Voice or MSRS.voice
|
||||||
self.PathToGoogleKey = PathToGoogleKey --
|
self.PathToGoogleKey = PathToGoogleKey --
|
||||||
|
self.AccessKey = AccessKey
|
||||||
self.Volume = Volume or 1.0 --
|
self.Volume = Volume or 1.0 --
|
||||||
self.UseSRS = true
|
self.UseSRS = true
|
||||||
self.Frequency = Frequency or {127,251} --
|
self.Frequency = Frequency or {127,251} --
|
||||||
@@ -4022,19 +4042,28 @@ function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Cultu
|
|||||||
self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
|
self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
|
||||||
self.BCModulation = self.Modulation
|
self.BCModulation = self.Modulation
|
||||||
-- set up SRS
|
-- set up SRS
|
||||||
self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation,self.Volume)
|
self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation)
|
||||||
self.SRS:SetCoalition(self.Coalition)
|
self.SRS:SetCoalition(self.Coalition)
|
||||||
self.SRS:SetLabel(self.MenuName or self.Name)
|
self.SRS:SetLabel(self.MenuName or self.Name)
|
||||||
self.SRS:SetGender(self.Gender)
|
self.SRS:SetGender(self.Gender)
|
||||||
self.SRS:SetCulture(self.Culture)
|
self.SRS:SetCulture(self.Culture)
|
||||||
self.SRS:SetPort(self.Port)
|
self.SRS:SetPort(self.Port)
|
||||||
self.SRS:SetVoice(self.Voice)
|
self.SRS:SetVolume(self.Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.SRS:SetGoogle(self.PathToGoogleKey)
|
--self.SRS:SetGoogle(self.PathToGoogleKey)
|
||||||
|
self.SRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.AccessKey)
|
||||||
|
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
|
-- Pre-configured Google?
|
||||||
|
if (not PathToGoogleKey) and self.SRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
|
self.PathToGoogleKey = MSRS.poptions.gcloud.credentials
|
||||||
|
self.Voice = Voice or MSRS.poptions.gcloud.voice
|
||||||
|
self.AccessKey = AccessKey or MSRS.poptions.gcloud.key
|
||||||
end
|
end
|
||||||
if Coordinate then
|
if Coordinate then
|
||||||
self.SRS:SetCoordinate(Coordinate)
|
self.SRS:SetCoordinate(Coordinate)
|
||||||
end
|
end
|
||||||
|
self.SRS:SetVoice(self.Voice)
|
||||||
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
|
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
|
||||||
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -526,11 +526,11 @@ function TARGET:IsAlive()
|
|||||||
|
|
||||||
for _,_target in pairs(self.targets) do
|
for _,_target in pairs(self.targets) do
|
||||||
local target=_target --Ops.Target#TARGET.Object
|
local target=_target --Ops.Target#TARGET.Object
|
||||||
if target.Status==TARGET.ObjectStatus.ALIVE then
|
if target.Status~=TARGET.ObjectStatus.DEAD then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1107,7 +1107,7 @@ function TARGET:GetTargetLife(Target)
|
|||||||
|
|
||||||
elseif Target.Type==TARGET.ObjectType.SCENERY then
|
elseif Target.Type==TARGET.ObjectType.SCENERY then
|
||||||
|
|
||||||
if Target.Object and Target.Object:IsAlive() then
|
if Target.Object and Target.Object:IsAlive(25) then
|
||||||
local life = Target.Object:GetLife()
|
local life = Target.Object:GetLife()
|
||||||
return life
|
return life
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -183,8 +183,10 @@ end
|
|||||||
-- @param #number Port SRS port. Default 5002.
|
-- @param #number Port SRS port. Default 5002.
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
function RADIOQUEUE:SetSRS(PathToSRS, Port)
|
function RADIOQUEUE:SetSRS(PathToSRS, Port)
|
||||||
self.msrs=MSRS:New(PathToSRS, self.frequency/1000000, self.modulation)
|
local path = PathToSRS or MSRS.path
|
||||||
self.msrs:SetPort(Port)
|
local port = Port or MSRS.port
|
||||||
|
self.msrs=MSRS:New(path, self.frequency/1000000, self.modulation)
|
||||||
|
self.msrs:SetPort(port)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -160,52 +160,63 @@ do -- Sound File
|
|||||||
-- @param #string FileName The name of the sound file, e.g. "Hello World.ogg".
|
-- @param #string FileName The name of the sound file, e.g. "Hello World.ogg".
|
||||||
-- @param #string Path The path of the directory, where the sound file is located. Default is "l10n/DEFAULT/" within the miz file.
|
-- @param #string Path The path of the directory, where the sound file is located. Default is "l10n/DEFAULT/" within the miz file.
|
||||||
-- @param #number Duration Duration in seconds, how long it takes to play the sound file. Default is 3 seconds.
|
-- @param #number Duration Duration in seconds, how long it takes to play the sound file. Default is 3 seconds.
|
||||||
|
-- @param #bolean UseSrs Set if SRS should be used to play this file. Default is false.
|
||||||
-- @return #SOUNDFILE self
|
-- @return #SOUNDFILE self
|
||||||
function SOUNDFILE:New(FileName, Path, Duration)
|
function SOUNDFILE:New(FileName, Path, Duration, UseSrs)
|
||||||
|
|
||||||
-- Inherit BASE.
|
-- Inherit BASE.
|
||||||
local self=BASE:Inherit(self, BASE:New()) -- #SOUNDFILE
|
local self=BASE:Inherit(self, BASE:New()) -- #SOUNDFILE
|
||||||
|
|
||||||
|
-- Debug info:
|
||||||
|
self:F( {FileName, Path, Duration, UseSrs} )
|
||||||
|
|
||||||
-- Set file name.
|
-- Set file name.
|
||||||
self:SetFileName(FileName)
|
self:SetFileName(FileName)
|
||||||
|
|
||||||
|
-- Set if SRS should be used to play this file
|
||||||
|
self:SetPlayWithSRS(UseSrs or false)
|
||||||
|
|
||||||
-- Set path.
|
-- Set path.
|
||||||
self:SetPath(Path)
|
self:SetPath(Path)
|
||||||
|
|
||||||
-- Set duration.
|
-- Set duration.
|
||||||
self:SetDuration(Duration)
|
self:SetDuration(Duration)
|
||||||
|
|
||||||
-- Debug info:
|
|
||||||
self:T(string.format("New SOUNDFILE: file name=%s, path=%s", self.filename, self.path))
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set path, where the sound file is located.
|
--- Set path, where the sound file is located.
|
||||||
-- @param #SOUNDFILE self
|
-- @param #SOUNDFILE self
|
||||||
-- @param #string Path Path to the directory, where the sound file is located. In case this is nil, it defaults to the DCS mission temp directory.
|
-- @param #string Path Path to the directory, where the sound file is located. In case this is nil, it defaults to the DCS mission temp directory.
|
||||||
-- @return #SOUNDFILE self
|
-- @return #SOUNDFILE self
|
||||||
function SOUNDFILE:SetPath(Path)
|
function SOUNDFILE:SetPath(Path)
|
||||||
|
self:F( {Path} )
|
||||||
|
|
||||||
-- Init path.
|
-- Init path.
|
||||||
self.path=Path or "l10n/DEFAULT/"
|
if not Path then
|
||||||
|
if self.useSRS then -- use path to mission temp dir
|
||||||
if not Path and self.useSRS then -- use path to mission temp dir
|
self.path = lfs.tempdir() .. "Mission\\l10n\\DEFAULT"
|
||||||
self.path = os.getenv('TMP') .. "\\DCS\\Mission\\l10n\\DEFAULT"
|
else -- use internal path in miz file
|
||||||
end
|
self.path="l10n/DEFAULT/"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.path = Path
|
||||||
|
end
|
||||||
|
|
||||||
-- Remove (back)slashes.
|
-- Remove (back)slashes.
|
||||||
local nmax=1000 ; local n=1
|
local nmax=1000 ; local n=1
|
||||||
while (self.path:sub(-1)=="/" or self.path:sub(-1)==[[\]]) and n<=nmax do
|
while (self.path:sub(-1)=="/" or self.path:sub(-1)==[[\]]) and n<=nmax do
|
||||||
self.path=self.path:sub(1,#self.path-1)
|
self.path=self.path:sub(1,#self.path-1)
|
||||||
n=n+1
|
n=n+1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Append slash.
|
-- Append slash.
|
||||||
self.path=self.path.."/"
|
self.path=self.path.."/"
|
||||||
|
|
||||||
|
self:T("self.path=".. self.path)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get path of the directory, where the sound file is located.
|
--- Get path of the directory, where the sound file is located.
|
||||||
-- @param #SOUNDFILE self
|
-- @param #SOUNDFILE self
|
||||||
@@ -228,7 +239,7 @@ do -- Sound File
|
|||||||
--- Get the sound file name.
|
--- Get the sound file name.
|
||||||
-- @param #SOUNDFILE self
|
-- @param #SOUNDFILE self
|
||||||
-- @return #string Name of the soud file. This does *not* include its path.
|
-- @return #string Name of the soud file. This does *not* include its path.
|
||||||
function SOUNDFILE:GetFileName()
|
function SOUNDFILE:GetFileName()
|
||||||
return self.filename
|
return self.filename
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -264,14 +275,16 @@ do -- Sound File
|
|||||||
-- @param #boolean Switch If true or nil, use SRS. If false, use DCS transmission.
|
-- @param #boolean Switch If true or nil, use SRS. If false, use DCS transmission.
|
||||||
-- @return #SOUNDFILE self
|
-- @return #SOUNDFILE self
|
||||||
function SOUNDFILE:SetPlayWithSRS(Switch)
|
function SOUNDFILE:SetPlayWithSRS(Switch)
|
||||||
|
self:F( {Switch} )
|
||||||
if Switch==true or Switch==nil then
|
if Switch==true or Switch==nil then
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
else
|
else
|
||||||
self.useSRS=false
|
self.useSRS=false
|
||||||
end
|
end
|
||||||
|
self:T("self.useSRS=".. tostring(self.useSRS))
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do -- Text-To-Speech
|
do -- Text-To-Speech
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ do -- UserSound
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Play the usersound to the given @{Wrapper.Unit}.
|
--- Play the usersound to the given @{Wrapper.Unit}.
|
||||||
-- @param #USERSOUND self
|
-- @param #USERSOUND self
|
||||||
-- @param Wrapper.Unit#UNIT Unit The @{Wrapper.Unit} to play the usersound to.
|
-- @param Wrapper.Unit#UNIT Unit The @{Wrapper.Unit} to play the usersound to.
|
||||||
-- @param #number Delay (Optional) Delay in seconds, before the sound is played. Default 0.
|
-- @param #number Delay (Optional) Delay in seconds, before the sound is played. Default 0.
|
||||||
@@ -159,4 +159,24 @@ do -- UserSound
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Play the usersound to the given @{Wrapper.Client}.
|
||||||
|
-- @param #USERSOUND self
|
||||||
|
-- @param Wrapper.Client#CLIENT The @{Wrapper.Client} to play the usersound to.
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the sound is played. Default 0.
|
||||||
|
-- @return #USERSOUND The usersound instance.
|
||||||
|
-- @usage
|
||||||
|
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
|
||||||
|
-- local PlayerUnit = CLIENT:FindByPlayerName("Karl Heinz")-- Search for the active client with playername "Karl Heinz", a human player.
|
||||||
|
-- BlueVictory:ToClient( PlayerUnit ) -- Play the victory sound to the player unit.
|
||||||
|
--
|
||||||
|
function USERSOUND:ToClient( Client, Delay )
|
||||||
|
Delay=Delay or 0
|
||||||
|
if Delay>0 then
|
||||||
|
SCHEDULER:New(nil, USERSOUND.ToClient,{self, Client}, Delay)
|
||||||
|
else
|
||||||
|
trigger.action.outSoundForUnit( Client:GetID(), self.UserSoundFileName )
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
-- ## Test Missions:
|
-- ## Test Missions:
|
||||||
--
|
--
|
||||||
-- Test missions can be located on the main GITHUB site.
|
-- Test missions can be located on the main GITHUB site.
|
||||||
--
|
--
|
||||||
-- [FlightControl-Master/MOOSE_MISSIONS/TAD - Task Dispatching/CGO - Cargo Dispatching/](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/TAD%20-%20Task%20Dispatching/CGO%20-%20Cargo%20Task%20Dispatching)
|
-- [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Tasking/Task_Cargo_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Tasking system.
|
-- ## Tasking system.
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ ENUMS = {}
|
|||||||
--- Suppress the error box
|
--- Suppress the error box
|
||||||
env.setErrorMessageBoxEnabled( false )
|
env.setErrorMessageBoxEnabled( false )
|
||||||
|
|
||||||
|
|
||||||
--- Rules of Engagement.
|
--- Rules of Engagement.
|
||||||
-- @type ENUMS.ROE
|
-- @type ENUMS.ROE
|
||||||
-- @field #number WeaponFree [AIR] AI will engage any enemy group it detects. Target prioritization is based based on the threat of the target.
|
-- @field #number WeaponFree [AIR] AI will engage any enemy group it detects. Target prioritization is based based on the threat of the target.
|
||||||
@@ -524,6 +523,7 @@ ENUMS.ReportingName =
|
|||||||
Hawkeye = "E-2D",
|
Hawkeye = "E-2D",
|
||||||
Sentry = "E-3A",
|
Sentry = "E-3A",
|
||||||
Stratotanker = "KC-135",
|
Stratotanker = "KC-135",
|
||||||
|
Gasstation = "KC-135MPRS",
|
||||||
Extender = "KC-10",
|
Extender = "KC-10",
|
||||||
Orion = "P-3C",
|
Orion = "P-3C",
|
||||||
Viking = "S-3B",
|
Viking = "S-3B",
|
||||||
@@ -567,6 +567,14 @@ ENUMS.ReportingName =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Enums for Link16 transmit power
|
||||||
|
-- @type ENUMS.Link16Power
|
||||||
|
ENUMS.Link16Power = {
|
||||||
|
none = 0,
|
||||||
|
low = 1,
|
||||||
|
medium = 2,
|
||||||
|
high = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
--- Enums for the STORAGE class for stores - which need to be in ""
|
--- Enums for the STORAGE class for stores - which need to be in ""
|
||||||
|
|||||||
@@ -441,21 +441,37 @@ UTILS.BasicSerialize = function(s)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Print a table to log in a nice format
|
||||||
|
-- @param #table table The table to print
|
||||||
|
-- @param #number indent Number of indents
|
||||||
|
-- @return #string text Text created on the fly of the log output
|
||||||
function UTILS.PrintTableToLog(table, indent)
|
function UTILS.PrintTableToLog(table, indent)
|
||||||
|
local text = "\n"
|
||||||
if not table then
|
if not table then
|
||||||
BASE:E("No table passed!")
|
env.warning("No table passed!")
|
||||||
return
|
return nil
|
||||||
end
|
end
|
||||||
if not indent then indent = 0 end
|
if not indent then indent = 0 end
|
||||||
for k, v in pairs(table) do
|
for k, v in pairs(table) do
|
||||||
|
if string.find(k," ") then k='"'..k..'"'end
|
||||||
if type(v) == "table" then
|
if type(v) == "table" then
|
||||||
BASE:I(string.rep(" ", indent) .. tostring(k) .. " = {")
|
env.info(string.rep(" ", indent) .. tostring(k) .. " = {")
|
||||||
UTILS.PrintTableToLog(v, indent + 1)
|
text = text ..string.rep(" ", indent) .. tostring(k) .. " = {\n"
|
||||||
BASE:I(string.rep(" ", indent) .. "}")
|
text = text .. tostring(UTILS.PrintTableToLog(v, indent + 1)).."\n"
|
||||||
|
env.info(string.rep(" ", indent) .. "},")
|
||||||
|
text = text .. string.rep(" ", indent) .. "},\n"
|
||||||
else
|
else
|
||||||
BASE:I(string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(v))
|
local value
|
||||||
|
if tostring(v) == "true" or tostring(v) == "false" or tonumber(v) ~= nil then
|
||||||
|
value=v
|
||||||
|
else
|
||||||
|
value = '"'..tostring(v)..'"'
|
||||||
|
end
|
||||||
|
env.info(string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n")
|
||||||
|
text = text .. string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns table in a easy readable string representation.
|
--- Returns table in a easy readable string representation.
|
||||||
@@ -809,6 +825,64 @@ UTILS.tostringLL = function( lat, lon, acc, DMS)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[acc:
|
||||||
|
in DM: decimal point of minutes.
|
||||||
|
In DMS: decimal point of seconds.
|
||||||
|
position after the decimal of the least significant digit:
|
||||||
|
So:
|
||||||
|
42.32 - acc of 2.
|
||||||
|
]]
|
||||||
|
UTILS.tostringLLM2KData = function( lat, lon, acc)
|
||||||
|
|
||||||
|
local latHemi, lonHemi
|
||||||
|
if lat > 0 then
|
||||||
|
latHemi = 'N'
|
||||||
|
else
|
||||||
|
latHemi = 'S'
|
||||||
|
end
|
||||||
|
|
||||||
|
if lon > 0 then
|
||||||
|
lonHemi = 'E'
|
||||||
|
else
|
||||||
|
lonHemi = 'W'
|
||||||
|
end
|
||||||
|
|
||||||
|
lat = math.abs(lat)
|
||||||
|
lon = math.abs(lon)
|
||||||
|
|
||||||
|
local latDeg = math.floor(lat)
|
||||||
|
local latMin = (lat - latDeg)*60
|
||||||
|
|
||||||
|
local lonDeg = math.floor(lon)
|
||||||
|
local lonMin = (lon - lonDeg)*60
|
||||||
|
|
||||||
|
-- degrees, decimal minutes.
|
||||||
|
latMin = UTILS.Round(latMin, acc)
|
||||||
|
lonMin = UTILS.Round(lonMin, acc)
|
||||||
|
|
||||||
|
if latMin == 60 then
|
||||||
|
latMin = 0
|
||||||
|
latDeg = latDeg + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if lonMin == 60 then
|
||||||
|
lonMin = 0
|
||||||
|
lonDeg = lonDeg + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local minFrmtStr -- create the formatting string for the minutes place
|
||||||
|
if acc <= 0 then -- no decimal place.
|
||||||
|
minFrmtStr = '%02d'
|
||||||
|
else
|
||||||
|
local width = 3 + acc -- 01.310 - that's a width of 6, for example.
|
||||||
|
minFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 024 23'N or 024 23.123'N
|
||||||
|
return latHemi..string.format('%02d:', latDeg) .. string.format(minFrmtStr, latMin), lonHemi..string.format('%02d:', lonDeg) .. string.format(minFrmtStr, lonMin)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
-- acc- the accuracy of each easting/northing. 0, 1, 2, 3, 4, or 5.
|
-- acc- the accuracy of each easting/northing. 0, 1, 2, 3, 4, or 5.
|
||||||
UTILS.tostringMGRS = function(MGRS, acc) --R2.1
|
UTILS.tostringMGRS = function(MGRS, acc) --R2.1
|
||||||
|
|
||||||
@@ -1048,9 +1122,9 @@ function UTILS.BeaufortScale(speed)
|
|||||||
return bn,bd
|
return bn,bd
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Split string at seperators. C.f. [split-string-in-lua](http://stackoverflow.com/questions/1426954/split-string-in-lua).
|
--- Split string at separators. C.f. [split-string-in-lua](http://stackoverflow.com/questions/1426954/split-string-in-lua).
|
||||||
-- @param #string str Sting to split.
|
-- @param #string str Sting to split.
|
||||||
-- @param #string sep Speparator for split.
|
-- @param #string sep Separator for split.
|
||||||
-- @return #table Split text.
|
-- @return #table Split text.
|
||||||
function UTILS.Split(str, sep)
|
function UTILS.Split(str, sep)
|
||||||
local result = {}
|
local result = {}
|
||||||
@@ -1345,6 +1419,11 @@ function UTILS.VecSubstract(a, b)
|
|||||||
return {x=a.x-b.x, y=a.y-b.y, z=a.z-b.z}
|
return {x=a.x-b.x, y=a.y-b.y, z=a.z-b.z}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Substract is not a word, don't want to rename the original function because it's been around since forever
|
||||||
|
function UTILS.VecSubtract(a, b)
|
||||||
|
return UTILS.VecSubstract(a, b)
|
||||||
|
end
|
||||||
|
|
||||||
--- Calculate the difference between two 2D vectors by substracting the x,y components from each other.
|
--- Calculate the difference between two 2D vectors by substracting the x,y components from each other.
|
||||||
-- @param DCS#Vec2 a Vector in 2D with x, y components.
|
-- @param DCS#Vec2 a Vector in 2D with x, y components.
|
||||||
-- @param DCS#Vec2 b Vector in 2D with x, y components.
|
-- @param DCS#Vec2 b Vector in 2D with x, y components.
|
||||||
@@ -1353,6 +1432,11 @@ function UTILS.Vec2Substract(a, b)
|
|||||||
return {x=a.x-b.x, y=a.y-b.y}
|
return {x=a.x-b.x, y=a.y-b.y}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Substract is not a word, don't want to rename the original function because it's been around since forever
|
||||||
|
function UTILS.Vec2Subtract(a, b)
|
||||||
|
return UTILS.Vec2Substract(a, b)
|
||||||
|
end
|
||||||
|
|
||||||
--- Calculate the total vector of two 3D vectors by adding the x,y,z components of each other.
|
--- Calculate the total vector of two 3D vectors by adding the x,y,z components of each other.
|
||||||
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
||||||
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
|
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
|
||||||
@@ -2120,17 +2204,17 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if string.find(type_name, "Bell-47") then -- bell aint got no doors so always ready to load injured soldiers
|
if type_name == "Bell-47" then -- bell aint got no doors so always ready to load injured soldiers
|
||||||
BASE:T(unit_name .. " door is open")
|
BASE:T(unit_name .. " door is open")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if string.find(type_name, "UH-60L") and (unit:getDrawArgumentValue(401) == 1 or unit:getDrawArgumentValue(402) == 1) then
|
if type_name == "UH-60L" and (unit:getDrawArgumentValue(401) == 1 or unit:getDrawArgumentValue(402) == 1) then
|
||||||
BASE:T(unit_name .. " cargo door is open")
|
BASE:T(unit_name .. " cargo door is open")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if string.find(type_name, "UH-60L" ) and (unit:getDrawArgumentValue(38) == 1 or unit:getDrawArgumentValue(400) == 1 ) then
|
if type_name == "UH-60L" and (unit:getDrawArgumentValue(38) > 0 or unit:getDrawArgumentValue(400) == 1 ) then
|
||||||
BASE:T(unit_name .. " front door(s) are open")
|
BASE:T(unit_name .. " front door(s) are open")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -2245,20 +2329,37 @@ function UTILS.GenerateVHFrequencies()
|
|||||||
return FreeVHFFrequencies
|
return FreeVHFFrequencies
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Function to generate valid UHF Frequencies in mHz (AM).
|
--- Function to generate valid UHF Frequencies in mHz (AM). Can be between 220 and 399 mHz. 243 is auto-excluded.
|
||||||
|
-- @param Start (Optional) Avoid frequencies between Start and End in mHz, e.g. 244
|
||||||
|
-- @param End (Optional) Avoid frequencies between Start and End in mHz, e.g. 320
|
||||||
-- @return #table UHF Frequencies
|
-- @return #table UHF Frequencies
|
||||||
function UTILS.GenerateUHFrequencies()
|
function UTILS.GenerateUHFrequencies(Start,End)
|
||||||
|
|
||||||
local FreeUHFFrequencies = {}
|
local FreeUHFFrequencies = {}
|
||||||
local _start = 220000000
|
local _start = 220000000
|
||||||
|
|
||||||
while _start < 399000000 do
|
if not Start then
|
||||||
if _start ~= 243000000 then
|
while _start < 399000000 do
|
||||||
table.insert(FreeUHFFrequencies, _start)
|
if _start ~= 243000000 then
|
||||||
|
table.insert(FreeUHFFrequencies, _start)
|
||||||
|
end
|
||||||
|
_start = _start + 500000
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local myend = End*1000000 or 399000000
|
||||||
|
local mystart = Start*1000000 or 220000000
|
||||||
|
|
||||||
|
while _start < 399000000 do
|
||||||
|
if _start ~= 243000000 and (_start < mystart or _start > myend) then
|
||||||
|
print(_start)
|
||||||
|
table.insert(FreeUHFFrequencies, _start)
|
||||||
|
end
|
||||||
|
_start = _start + 500000
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
_start = _start + 500000
|
|
||||||
end
|
|
||||||
|
|
||||||
return FreeUHFFrequencies
|
return FreeUHFFrequencies
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2391,7 +2492,7 @@ function UTILS.LoadFromFile(Path,Filename)
|
|||||||
-- Check if file exists.
|
-- Check if file exists.
|
||||||
local exists=UTILS.CheckFileExists(Path,Filename)
|
local exists=UTILS.CheckFileExists(Path,Filename)
|
||||||
if not exists then
|
if not exists then
|
||||||
BASE:E(string.format("ERROR: File %s does not exist!",filename))
|
BASE:I(string.format("ERROR: File %s does not exist!",filename))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3101,3 +3202,518 @@ function UTILS.PlotRacetrack(Coordinate, Altitude, Speed, Heading, Leg, Coalitio
|
|||||||
circle_center_two_three:CircleToAll(UTILS.NMToMeters(turn_radius), coalition, color, alpha, nil, 0, lineType)--, ReadOnly, Text)
|
circle_center_two_three:CircleToAll(UTILS.NMToMeters(turn_radius), coalition, color, alpha, nil, 0, lineType)--, ReadOnly, Text)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the current time in a "nice" format like 21:01:15
|
||||||
|
-- @return #string Returns string with the current time
|
||||||
|
function UTILS.TimeNow()
|
||||||
|
return UTILS.SecondsToClock(timer.getAbsTime(), false, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Given 2 "nice" time string, returns the difference between the two in seconds
|
||||||
|
-- @param #string start_time Time string like "07:15:22"
|
||||||
|
-- @param #string end_time Time string like "08:11:27"
|
||||||
|
-- @return #number Seconds between start_time and end_time
|
||||||
|
function UTILS.TimeDifferenceInSeconds(start_time, end_time)
|
||||||
|
return UTILS.ClockToSeconds(end_time) - UTILS.ClockToSeconds(start_time)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if the current time is later than time_string.
|
||||||
|
-- @param #string start_time Time string like "07:15:22"
|
||||||
|
-- @return #boolean True if later, False if before
|
||||||
|
function UTILS.TimeLaterThan(time_string)
|
||||||
|
if timer.getAbsTime() > UTILS.ClockToSeconds(time_string) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if the current time is before time_string.
|
||||||
|
-- @param #string start_time Time string like "07:15:22"
|
||||||
|
-- @return #boolean False if later, True if before
|
||||||
|
function UTILS.TimeBefore(time_string)
|
||||||
|
if timer.getAbsTime() < UTILS.ClockToSeconds(time_string) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Combines two time strings to give you a new time. For example "15:16:32" and "02:06:24" would return "17:22:56"
|
||||||
|
-- @param #string time_string_01 Time string like "07:15:22"
|
||||||
|
-- @param #string time_string_02 Time string like "08:11:27"
|
||||||
|
-- @return #string Result of the two time string combined
|
||||||
|
function UTILS.CombineTimeStrings(time_string_01, time_string_02)
|
||||||
|
local hours1, minutes1, seconds1 = time_string_01:match("(%d+):(%d+):(%d+)")
|
||||||
|
local hours2, minutes2, seconds2 = time_string_02:match("(%d+):(%d+):(%d+)")
|
||||||
|
local total_seconds = tonumber(seconds1) + tonumber(seconds2) + tonumber(minutes1) * 60 + tonumber(minutes2) * 60 + tonumber(hours1) * 3600 + tonumber(hours2) * 3600
|
||||||
|
|
||||||
|
total_seconds = total_seconds % (24 * 3600)
|
||||||
|
if total_seconds < 0 then
|
||||||
|
total_seconds = total_seconds + 24 * 3600
|
||||||
|
end
|
||||||
|
|
||||||
|
local hours = math.floor(total_seconds / 3600)
|
||||||
|
total_seconds = total_seconds - hours * 3600
|
||||||
|
local minutes = math.floor(total_seconds / 60)
|
||||||
|
local seconds = total_seconds % 60
|
||||||
|
|
||||||
|
return string.format("%02d:%02d:%02d", hours, minutes, seconds)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Subtracts two time string to give you a new time. For example "15:16:32" and "02:06:24" would return "13:10:08"
|
||||||
|
-- @param #string time_string_01 Time string like "07:15:22"
|
||||||
|
-- @param #string time_string_02 Time string like "08:11:27"
|
||||||
|
-- @return #string Result of the two time string subtracted
|
||||||
|
function UTILS.SubtractTimeStrings(time_string_01, time_string_02)
|
||||||
|
local hours1, minutes1, seconds1 = time_string_01:match("(%d+):(%d+):(%d+)")
|
||||||
|
local hours2, minutes2, seconds2 = time_string_02:match("(%d+):(%d+):(%d+)")
|
||||||
|
local total_seconds = tonumber(seconds1) - tonumber(seconds2) + tonumber(minutes1) * 60 - tonumber(minutes2) * 60 + tonumber(hours1) * 3600 - tonumber(hours2) * 3600
|
||||||
|
|
||||||
|
total_seconds = total_seconds % (24 * 3600)
|
||||||
|
if total_seconds < 0 then
|
||||||
|
total_seconds = total_seconds + 24 * 3600
|
||||||
|
end
|
||||||
|
|
||||||
|
local hours = math.floor(total_seconds / 3600)
|
||||||
|
total_seconds = total_seconds - hours * 3600
|
||||||
|
local minutes = math.floor(total_seconds / 60)
|
||||||
|
local seconds = total_seconds % 60
|
||||||
|
|
||||||
|
return string.format("%02d:%02d:%02d", hours, minutes, seconds)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks if the current time is in between start_time and end_time
|
||||||
|
-- @param #string time_string_01 Time string like "07:15:22"
|
||||||
|
-- @param #string time_string_02 Time string like "08:11:27"
|
||||||
|
-- @return #bool True if it is, False if it's not
|
||||||
|
function UTILS.TimeBetween(start_time, end_time)
|
||||||
|
return UTILS.TimeLaterThan(start_time) and UTILS.TimeBefore(end_time)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Easy to read one line to roll the dice on something. 1% is very unlikely to happen, 99% is very likely to happen
|
||||||
|
-- @param #number chance (optional) Percentage chance you want something to happen. Defaults to a random number if not given
|
||||||
|
-- @return #bool True if the dice roll was within the given percentage chance of happening
|
||||||
|
function UTILS.PercentageChance(chance)
|
||||||
|
chance = chance or math.random(0, 100)
|
||||||
|
chance = UTILS.Clamp(chance, 0, 100)
|
||||||
|
local percentage = math.random(0, 100)
|
||||||
|
if percentage < chance then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Easy to read one liner to clamp a value
|
||||||
|
-- @param #number value Input value
|
||||||
|
-- @param #number min Minimal value that should be respected
|
||||||
|
-- @param #number max Maximal value that should be respected
|
||||||
|
-- @return #number Clamped value
|
||||||
|
function UTILS.Clamp(value, min, max)
|
||||||
|
if value < min then value = min end
|
||||||
|
if value > max then value = max end
|
||||||
|
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Clamp an angle so that it's always between 0 and 360 while still being correct
|
||||||
|
-- @param #number value Input value
|
||||||
|
-- @return #number Clamped value
|
||||||
|
function UTILS.ClampAngle(value)
|
||||||
|
if value > 360 then return value - 360 end
|
||||||
|
if value < 0 then return value + 360 end
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remap an input to a new value in a given range. For example:
|
||||||
|
--- UTILS.RemapValue(20, 10, 30, 0, 200) would return 100
|
||||||
|
--- 20 is 50% between 10 and 30
|
||||||
|
--- 50% between 0 and 200 is 100
|
||||||
|
-- @param #number value Input value
|
||||||
|
-- @param #number old_min Min value to remap from
|
||||||
|
-- @param #number old_max Max value to remap from
|
||||||
|
-- @param #number new_min Min value to remap to
|
||||||
|
-- @param #number new_max Max value to remap to
|
||||||
|
-- @return #number Remapped value
|
||||||
|
function UTILS.RemapValue(value, old_min, old_max, new_min, new_max)
|
||||||
|
new_min = new_min or 0
|
||||||
|
new_max = new_max or 100
|
||||||
|
|
||||||
|
local old_range = old_max - old_min
|
||||||
|
local new_range = new_max - new_min
|
||||||
|
local percentage = (value - old_min) / old_range
|
||||||
|
return (new_range * percentage) + new_min
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Given a triangle made out of 3 vector 2s, return a vec2 that is a random number in this triangle
|
||||||
|
-- @param #Vec2 pt1 Min value to remap from
|
||||||
|
-- @param #Vec2 pt2 Max value to remap from
|
||||||
|
-- @param #Vec2 pt3 Max value to remap from
|
||||||
|
-- @return #Vec2 Random point in triangle
|
||||||
|
function UTILS.RandomPointInTriangle(pt1, pt2, pt3)
|
||||||
|
local pt = {math.random(), math.random()}
|
||||||
|
table.sort(pt)
|
||||||
|
local s = pt[1]
|
||||||
|
local t = pt[2] - pt[1]
|
||||||
|
local u = 1 - pt[2]
|
||||||
|
|
||||||
|
return {x = s * pt1.x + t * pt2.x + u * pt3.x,
|
||||||
|
y = s * pt1.y + t * pt2.y + u * pt3.y}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks if a given angle (heading) is between 2 other angles. Min and max have to be given in clockwise order For example:
|
||||||
|
--- UTILS.AngleBetween(350, 270, 15) would return True
|
||||||
|
--- UTILS.AngleBetween(22, 95, 20) would return False
|
||||||
|
-- @param #number angle Min value to remap from
|
||||||
|
-- @param #number min Max value to remap from
|
||||||
|
-- @param #number max Max value to remap from
|
||||||
|
-- @return #bool
|
||||||
|
function UTILS.AngleBetween(angle, min, max)
|
||||||
|
angle = (360 + (angle % 360)) % 360
|
||||||
|
min = (360 + min % 360) % 360
|
||||||
|
max = (360 + max % 360) % 360
|
||||||
|
|
||||||
|
if min < max then return min <= angle and angle <= max end
|
||||||
|
return min <= angle or angle <= max
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Easy to read one liner to write a JSON file. Everything in @data should be serializable
|
||||||
|
--- json.lua exists in the DCS install Scripts folder
|
||||||
|
-- @param #table data table to write
|
||||||
|
-- @param #string file_path File path
|
||||||
|
function UTILS.WriteJSON(data, file_path)
|
||||||
|
package.path = package.path .. ";.\\Scripts\\?.lua"
|
||||||
|
local JSON = require("json")
|
||||||
|
local pretty_json_text = JSON:encode_pretty(data)
|
||||||
|
local write_file = io.open(file_path, "w")
|
||||||
|
write_file:write(pretty_json_text)
|
||||||
|
write_file:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Easy to read one liner to read a JSON file.
|
||||||
|
--- json.lua exists in the DCS install Scripts folder
|
||||||
|
-- @param #string file_path File path
|
||||||
|
-- @return #table
|
||||||
|
function UTILS.ReadJSON(file_path)
|
||||||
|
package.path = package.path .. ";.\\Scripts\\?.lua"
|
||||||
|
local JSON = require("json")
|
||||||
|
local read_file = io.open(file_path, "r")
|
||||||
|
local contents = read_file:read( "*a" )
|
||||||
|
io.close(read_file)
|
||||||
|
return JSON:decode(contents)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the properties names and values of properties set up on a Zone in the Mission Editor.
|
||||||
|
--- This doesn't work for any zones created in MOOSE
|
||||||
|
-- @param #string zone_name Name of the zone as set up in the Mission Editor
|
||||||
|
-- @return #table with all the properties on a zone
|
||||||
|
function UTILS.GetZoneProperties(zone_name)
|
||||||
|
local return_table = {}
|
||||||
|
for _, zone in pairs(env.mission.triggers.zones) do
|
||||||
|
if zone["name"] == zone_name then
|
||||||
|
if table.length(zone["properties"]) > 0 then
|
||||||
|
for _, property in pairs(zone["properties"]) do
|
||||||
|
return_table[property["key"]] = property["value"]
|
||||||
|
end
|
||||||
|
return return_table
|
||||||
|
else
|
||||||
|
BASE:I(string.format("%s doesn't have any properties", zone_name))
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Rotates a point around another point with a given angle. Useful if you're loading in groups or
|
||||||
|
--- statics but you want to rotate them all as a collection. You can get the center point of everything
|
||||||
|
--- and then rotate all the positions of every object around this center point.
|
||||||
|
-- @param #Vec2 point Point that you want to rotate
|
||||||
|
-- @param #Vec2 pivot Pivot point of the rotation
|
||||||
|
-- @param #number angle How many degrees the point should be rotated
|
||||||
|
-- @return #Vec Rotated point
|
||||||
|
function UTILS.RotatePointAroundPivot(point, pivot, angle)
|
||||||
|
local radians = math.rad(angle)
|
||||||
|
|
||||||
|
local x = point.x - pivot.x
|
||||||
|
local y = point.y - pivot.y
|
||||||
|
|
||||||
|
local rotated_x = x * math.cos(radians) - y * math.sin(radians)
|
||||||
|
local rotatex_y = x * math.sin(radians) + y * math.cos(radians)
|
||||||
|
|
||||||
|
local original_x = rotated_x + pivot.x
|
||||||
|
local original_y = rotatex_y + pivot.y
|
||||||
|
|
||||||
|
return { x = original_x, y = original_y }
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Makes a string semi-unique by attaching a random number between 0 and 1 million to it
|
||||||
|
-- @param #string base String you want to unique-fy
|
||||||
|
-- @return #string Unique string
|
||||||
|
function UTILS.UniqueName(base)
|
||||||
|
base = base or ""
|
||||||
|
local ran = tostring(math.random(0, 1000000))
|
||||||
|
|
||||||
|
if base == "" then
|
||||||
|
return ran
|
||||||
|
end
|
||||||
|
return base .. "_" .. ran
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if a string starts with something
|
||||||
|
-- @param #string str String to check
|
||||||
|
-- @param #string value
|
||||||
|
-- @return #bool True if str starts with value
|
||||||
|
function string.startswith(str, value)
|
||||||
|
return string.sub(str,1,string.len(value)) == value
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if a string ends with something
|
||||||
|
-- @param #string str String to check
|
||||||
|
-- @param #string value
|
||||||
|
-- @return #bool True if str ends with value
|
||||||
|
function string.endswith(str, value)
|
||||||
|
return value == "" or str:sub(-#value) == value
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Splits a string on a separator. For example:
|
||||||
|
--- string.split("hello_dcs_world", "-") would return {"hello", "dcs", "world"}
|
||||||
|
-- @param #string input String to split
|
||||||
|
-- @param #string separator What to split on
|
||||||
|
-- @return #table individual strings
|
||||||
|
function string.split(input, separator)
|
||||||
|
local parts = {}
|
||||||
|
for part in input:gmatch("[^" .. separator .. "]+") do
|
||||||
|
table.insert(parts, part)
|
||||||
|
end
|
||||||
|
return parts
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Checks if a string contains a substring. Easier to remember for Python people :)
|
||||||
|
--- string.split("hello_dcs_world", "-") would return {"hello", "dcs", "world"}
|
||||||
|
-- @param #string str
|
||||||
|
-- @param #string value
|
||||||
|
-- @return #bool True if str contains value
|
||||||
|
function string.contains(str, value)
|
||||||
|
return string.match(str, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Given tbl is a indexed table ({"hello", "dcs", "world"}), checks if element exists in the table.
|
||||||
|
--- The table can be made up out of complex tables or values as well
|
||||||
|
-- @param #table tbl
|
||||||
|
-- @param #string element
|
||||||
|
-- @return #bool True if tbl contains element
|
||||||
|
function table.contains(tbl, element)
|
||||||
|
if element == nil or tbl == nil then return false end
|
||||||
|
|
||||||
|
local index = 1
|
||||||
|
while tbl[index] do
|
||||||
|
if tbl[index] == element then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks if a table contains a specific key.
|
||||||
|
-- @param #table tbl Table to check
|
||||||
|
-- @param #string key Key to look for
|
||||||
|
-- @return #bool True if tbl contains key
|
||||||
|
function table.contains_key(tbl, key)
|
||||||
|
if tbl[key] ~= nil then return true else return false end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Inserts a unique element into a table.
|
||||||
|
-- @param #table tbl Table to insert into
|
||||||
|
-- @param #string element Element to insert
|
||||||
|
function table.insert_unique(tbl, element)
|
||||||
|
if element == nil or tbl == nil then return end
|
||||||
|
|
||||||
|
if not table.contains(tbl, element) then
|
||||||
|
table.insert(tbl, element)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Removes an element from a table by its value.
|
||||||
|
-- @param #table tbl Table to remove from
|
||||||
|
-- @param #string element Element to remove
|
||||||
|
function table.remove_by_value(tbl, element)
|
||||||
|
local indices_to_remove = {}
|
||||||
|
local index = 1
|
||||||
|
for _, value in pairs(tbl) do
|
||||||
|
if value == element then
|
||||||
|
table.insert(indices_to_remove, index)
|
||||||
|
end
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, idx in pairs(indices_to_remove) do
|
||||||
|
table.remove(tbl, idx)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Removes an element from a table by its key.
|
||||||
|
-- @param #table table Table to remove from
|
||||||
|
-- @param #string key Key of the element to remove
|
||||||
|
-- @return #string Removed element
|
||||||
|
function table.remove_key(table, key)
|
||||||
|
local element = table[key]
|
||||||
|
table[key] = nil
|
||||||
|
return element
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Finds the index of an element in a table.
|
||||||
|
-- @param #table table Table to search
|
||||||
|
-- @param #string element Element to find
|
||||||
|
-- @return #int Index of the element, or nil if not found
|
||||||
|
function table.index_of(table, element)
|
||||||
|
for i, v in ipairs(table) do
|
||||||
|
if v == element then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Counts the number of elements in a table.
|
||||||
|
-- @param #table T Table to count
|
||||||
|
-- @return #int Number of elements in the table
|
||||||
|
function table.length(T)
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(T) do count = count + 1 end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Slices a table between two indices, much like Python's my_list[2:-1]
|
||||||
|
-- @param #table tbl Table to slice
|
||||||
|
-- @param #int first Starting index
|
||||||
|
-- @param #int last Ending index
|
||||||
|
-- @return #table Sliced table
|
||||||
|
function table.slice(tbl, first, last)
|
||||||
|
local sliced = {}
|
||||||
|
local start = first or 1
|
||||||
|
local stop = last or table.length(tbl)
|
||||||
|
local count = 1
|
||||||
|
|
||||||
|
for key, value in pairs(tbl) do
|
||||||
|
if count >= start and count <= stop then
|
||||||
|
sliced[key] = value
|
||||||
|
end
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return sliced
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Counts the number of occurrences of a value in a table.
|
||||||
|
-- @param #table tbl Table to search
|
||||||
|
-- @param #string value Value to count
|
||||||
|
-- @return #int Number of occurrences of the value
|
||||||
|
function table.count_value(tbl, value)
|
||||||
|
local count = 0
|
||||||
|
for _, item in pairs(tbl) do
|
||||||
|
if item == value then count = count + 1 end
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add 2 table together, t2 gets added to t1
|
||||||
|
-- @param #table t1 First table
|
||||||
|
-- @param #table t2 Second table
|
||||||
|
-- @return #table Combined table
|
||||||
|
function table.combine(t1, t2)
|
||||||
|
if t1 == nil and t2 == nil then
|
||||||
|
BASE:E("Both tables were empty!")
|
||||||
|
end
|
||||||
|
|
||||||
|
if t1 == nil then return t2 end
|
||||||
|
if t2 == nil then return t1 end
|
||||||
|
for i=1,#t2 do
|
||||||
|
t1[#t1+1] = t2[i]
|
||||||
|
end
|
||||||
|
return t1
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Merges two tables into one. If a key exists in both t1 and t2, the value of t1 with be overwritten by the value of t2
|
||||||
|
-- @param #table t1 First table
|
||||||
|
-- @param #table t2 Second table
|
||||||
|
-- @return #table Merged table
|
||||||
|
function table.merge(t1, t2)
|
||||||
|
for k, v in pairs(t2) do
|
||||||
|
if (type(v) == "table") and (type(t1[k] or false) == "table") then
|
||||||
|
table.merge(t1[k], t2[k])
|
||||||
|
else
|
||||||
|
t1[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return t1
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Adds an item to the end of a table.
|
||||||
|
-- @param #table tbl Table to add to
|
||||||
|
-- @param #string item Item to add
|
||||||
|
function table.add(tbl, item)
|
||||||
|
tbl[#tbl + 1] = item
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Shuffles the elements of a table.
|
||||||
|
-- @param #table tbl Table to shuffle
|
||||||
|
-- @return #table Shuffled table
|
||||||
|
function table.shuffle(tbl)
|
||||||
|
local new_table = {}
|
||||||
|
for _, value in ipairs(tbl) do
|
||||||
|
local pos = math.random(1, #new_table +1)
|
||||||
|
table.insert(new_table, pos, value)
|
||||||
|
end
|
||||||
|
return new_table
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Finds a key-value pair in a table.
|
||||||
|
-- @param #table tbl Table to search
|
||||||
|
-- @param #string key Key to find
|
||||||
|
-- @param #string value Value to find
|
||||||
|
-- @return #table Table containing the key-value pair, or nil if not found
|
||||||
|
function table.find_key_value_pair(tbl, key, value)
|
||||||
|
for k, v in pairs(tbl) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
local result = table.find_key_value_pair(v, key, value)
|
||||||
|
if result ~= nil then
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
elseif k == key and v == value then
|
||||||
|
return tbl
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Convert a decimal to octal
|
||||||
|
-- @param #number Number the number to convert
|
||||||
|
-- @return #number Octal
|
||||||
|
function UTILS.DecimalToOctal(Number)
|
||||||
|
if Number < 8 then return Number end
|
||||||
|
local number = tonumber(Number)
|
||||||
|
local octal = ""
|
||||||
|
local n=1
|
||||||
|
while number > 7 do
|
||||||
|
local number1 = number%8
|
||||||
|
octal = string.format("%d",number1)..octal
|
||||||
|
local number2 = math.abs(number/8)
|
||||||
|
if number2 < 8 then
|
||||||
|
octal = string.format("%d",number2)..octal
|
||||||
|
end
|
||||||
|
number = number2
|
||||||
|
n=n+1
|
||||||
|
end
|
||||||
|
return tonumber(octal)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Convert an octal to decimal
|
||||||
|
-- @param #number Number the number to convert
|
||||||
|
-- @return #number Decimal
|
||||||
|
function UTILS.OctalToDecimal(Number)
|
||||||
|
return tonumber(Number,8)
|
||||||
|
end
|
||||||
|
|||||||
@@ -239,6 +239,13 @@ AIRBASE.Nevada = {
|
|||||||
-- * AIRBASE.Normandy.Broglie
|
-- * AIRBASE.Normandy.Broglie
|
||||||
-- * AIRBASE.Normandy.Bernay_Saint_Martin
|
-- * AIRBASE.Normandy.Bernay_Saint_Martin
|
||||||
-- * AIRBASE.Normandy.Saint_Andre_de_lEure
|
-- * AIRBASE.Normandy.Saint_Andre_de_lEure
|
||||||
|
-- * AIRBASE.Normandy.Biggin_Hill
|
||||||
|
-- * AIRBASE.Normandy.Manston
|
||||||
|
-- * AIRBASE.Normandy.Detling
|
||||||
|
-- * AIRBASE.Normandy.Lympne
|
||||||
|
-- * AIRBASE.Normandy.Abbeville_Drucat
|
||||||
|
-- * AIRBASE.Normandy.Merville_Calonne
|
||||||
|
-- * AIRBASE.Normandy.Saint_Omer_Wizernes
|
||||||
--
|
--
|
||||||
-- @field Normandy
|
-- @field Normandy
|
||||||
AIRBASE.Normandy = {
|
AIRBASE.Normandy = {
|
||||||
@@ -311,7 +318,14 @@ AIRBASE.Normandy = {
|
|||||||
["Beaumont_le_Roger"] = "Beaumont-le-Roger",
|
["Beaumont_le_Roger"] = "Beaumont-le-Roger",
|
||||||
["Broglie"] = "Broglie",
|
["Broglie"] = "Broglie",
|
||||||
["Bernay_Saint_Martin"] = "Bernay Saint Martin",
|
["Bernay_Saint_Martin"] = "Bernay Saint Martin",
|
||||||
["Saint_Andre_de_lEure"] = "Saint-Andre-de-lEure",
|
["Saint_Andre_de_lEure"] = "Saint-Andre-de-lEure",
|
||||||
|
["Biggin_Hill"] = "Biggin Hill",
|
||||||
|
["Manston"] = "Manston",
|
||||||
|
["Detling"] = "Detling",
|
||||||
|
["Lympne"] = "Lympne",
|
||||||
|
["Abbeville_Drucat"] = "Abbeville Drucat",
|
||||||
|
["Merville_Calonne"] = "Merville Calonne",
|
||||||
|
["Saint_Omer_Wizernes"] = "Saint-Omer Wizernes",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Airbases of the Persion Gulf Map:
|
--- Airbases of the Persion Gulf Map:
|
||||||
@@ -1885,8 +1899,17 @@ function AIRBASE:_InitRunways(IncludeInverse)
|
|||||||
local heading=math.deg(bearing)
|
local heading=math.deg(bearing)
|
||||||
|
|
||||||
-- Data table.
|
-- Data table.
|
||||||
local runway={} --#AIRBASE.Runway
|
local runway={} --#AIRBASE.Runway
|
||||||
runway.name=string.format("%02d", tonumber(name))
|
|
||||||
|
local namefromheading = math.floor(heading/10)
|
||||||
|
|
||||||
|
if self.AirbaseName == AIRBASE.Syria.Beirut_Rafic_Hariri and math.abs(namefromheading-name) > 1 then
|
||||||
|
runway.name=string.format("%02d", tonumber(namefromheading))
|
||||||
|
else
|
||||||
|
runway.name=string.format("%02d", tonumber(name))
|
||||||
|
end
|
||||||
|
|
||||||
|
--runway.name=string.format("%02d", tonumber(name))
|
||||||
runway.magheading=tonumber(runway.name)*10
|
runway.magheading=tonumber(runway.name)*10
|
||||||
runway.heading=heading
|
runway.heading=heading
|
||||||
runway.width=width or 0
|
runway.width=width or 0
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
-- This method can also be used to **embed a function call when a certain waypoint has been reached**.
|
-- This method can also be used to **embed a function call when a certain waypoint has been reached**.
|
||||||
-- See below the **Tasks at Waypoints** section.
|
-- See below the **Tasks at Waypoints** section.
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [GRP-502 - Route at waypoint to random point](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/GRP%20-%20Group%20Commands/GRP-502%20-%20Route%20at%20waypoint%20to%20random%20point)
|
-- Demonstration Mission: [GRP-502 - Route at waypoint to random point](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Wrapper/Group/GRP-502%20-%20Route%20at%20waypoint%20to%20random%20point)
|
||||||
--
|
--
|
||||||
-- ## 2.5) Tasks at Waypoints
|
-- ## 2.5) Tasks at Waypoints
|
||||||
--
|
--
|
||||||
@@ -938,20 +938,22 @@ end
|
|||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param #number Frequency Radio frequency in MHz.
|
-- @param #number Frequency Radio frequency in MHz.
|
||||||
-- @param #number Modulation Radio modulation. Default `radio.modulation.AM`.
|
-- @param #number Modulation Radio modulation. Default `radio.modulation.AM`.
|
||||||
|
-- @param #number Power (Optional) Power of the Radio in Watts. Defaults to 10.
|
||||||
-- @param #number Delay (Optional) Delay in seconds before the frequency is set. Default is immediately.
|
-- @param #number Delay (Optional) Delay in seconds before the frequency is set. Default is immediately.
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:CommandSetFrequency( Frequency, Modulation, Delay )
|
function CONTROLLABLE:CommandSetFrequency( Frequency, Modulation, Power, Delay )
|
||||||
|
|
||||||
local CommandSetFrequency = {
|
local CommandSetFrequency = {
|
||||||
id = 'SetFrequency',
|
id = 'SetFrequency',
|
||||||
params = {
|
params = {
|
||||||
frequency = Frequency * 1000000,
|
frequency = Frequency * 1000000,
|
||||||
modulation = Modulation or radio.modulation.AM,
|
modulation = Modulation or radio.modulation.AM,
|
||||||
|
power=Power or 10,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if Delay and Delay > 0 then
|
if Delay and Delay > 0 then
|
||||||
SCHEDULER:New( nil, self.CommandSetFrequency, { self, Frequency, Modulation }, Delay )
|
SCHEDULER:New( nil, self.CommandSetFrequency, { self, Frequency, Modulation, Power } )
|
||||||
else
|
else
|
||||||
self:SetCommand( CommandSetFrequency )
|
self:SetCommand( CommandSetFrequency )
|
||||||
end
|
end
|
||||||
@@ -959,6 +961,32 @@ function CONTROLLABLE:CommandSetFrequency( Frequency, Modulation, Delay )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set radio frequency. See [DCS command EPLRS](https://wiki.hoggitworld.com/view/DCS_command_setFrequencyForUnit)
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number Frequency Radio frequency in MHz.
|
||||||
|
-- @param #number Modulation Radio modulation. Default `radio.modulation.AM`.
|
||||||
|
-- @param #number Power (Optional) Power of the Radio in Watts. Defaults to 10.
|
||||||
|
-- @param #UnitID UnitID (Optional, if your object is a UNIT) The UNIT ID this is for.
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds before the frequency is set. Default is immediately.
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:CommandSetFrequencyForUnit(Frequency,Modulation,Power,UnitID,Delay)
|
||||||
|
local CommandSetFrequencyForUnit={
|
||||||
|
id='SetFrequencyForUnit',
|
||||||
|
params={
|
||||||
|
frequency=Frequency*1000000,
|
||||||
|
modulation=Modulation or radio.modulation.AM,
|
||||||
|
unitId=UnitID or self:GetID(),
|
||||||
|
power=Power or 10,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
SCHEDULER:New(nil,self.CommandSetFrequencyForUnit,{self,Frequency,Modulation,Power,UnitID})
|
||||||
|
else
|
||||||
|
self:SetCommand(CommandSetFrequencyForUnit)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Set EPLRS data link on/off.
|
--- Set EPLRS data link on/off.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param #boolean SwitchOnOff If true (or nil) switch EPLRS on. If false switch off.
|
-- @param #boolean SwitchOnOff If true (or nil) switch EPLRS on. If false switch off.
|
||||||
@@ -2937,7 +2965,7 @@ function CONTROLLABLE:CopyRoute( Begin, End, Randomize, Radius )
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Return the detected targets of the controllable.
|
--- Return the detected targets of the controllable.
|
||||||
-- The optional parametes specify the detection methods that can be applied.
|
-- The optional parameters specify the detection methods that can be applied.
|
||||||
-- If no detection method is given, the detection will use all the available methods by default.
|
-- If no detection method is given, the detection will use all the available methods by default.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param #boolean DetectVisual (optional)
|
-- @param #boolean DetectVisual (optional)
|
||||||
@@ -3772,54 +3800,66 @@ function CONTROLLABLE:OptionProhibitAfterburner( Prohibit )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Defines the usage of Electronic Counter Measures by airborne forces. Disables the ability for AI to use their ECM.
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number ECMvalue Can be - 0=Never on, 1=if locked by radar, 2=if detected by radar, 3=always on, defaults to 1
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:OptionECM_Never()
|
function CONTROLLABLE:OptionECM( ECMvalue )
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
if self:IsAir() then
|
local DCSControllable = self:GetDCSObject()
|
||||||
self:SetOption( AI.Option.Air.id.ECM_USING, 0 )
|
if DCSControllable then
|
||||||
|
local Controller = self:_GetController()
|
||||||
|
|
||||||
|
if self:IsAir() then
|
||||||
|
Controller:setOption( AI.Option.Air.id.ECM_USING, ECMvalue or 1 )
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Defines the usage of Electronic Counter Measures by airborne forces. If the AI is actively being locked by an enemy radar they will enable their ECM jammer.
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. Disables the ability for AI to use their ECM.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:OptionECM_Never()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
|
self:OptionECM(0)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. If the AI is actively being locked by an enemy radar they will enable their ECM jammer.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:OptionECM_OnlyLockByRadar()
|
function CONTROLLABLE:OptionECM_OnlyLockByRadar()
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
if self:IsAir() then
|
self:OptionECM(1)
|
||||||
self:SetOption( AI.Option.Air.id.ECM_USING, 1 )
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Defines the usage of Electronic Counter Measures by airborne forces. If the AI is being detected by a radar they will enable their ECM.
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. If the AI is being detected by a radar they will enable their ECM.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:OptionECM_DetectedLockByRadar()
|
function CONTROLLABLE:OptionECM_DetectedLockByRadar()
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
if self:IsAir() then
|
self:OptionECM(2)
|
||||||
self:SetOption( AI.Option.Air.id.ECM_USING, 2 )
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Defines the usage of Electronic Counter Measures by airborne forces. AI will leave their ECM on all the time.
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. AI will leave their ECM on all the time.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:OptionECM_AlwaysOn()
|
function CONTROLLABLE:OptionECM_AlwaysOn()
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
if self:IsAir() then
|
self:OptionECM(3)
|
||||||
self:SetOption( AI.Option.Air.id.ECM_USING, 3 )
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -3974,7 +4014,7 @@ function CONTROLLABLE:OptionAAAttackRange( range )
|
|||||||
local Controller = self:_GetController()
|
local Controller = self:_GetController()
|
||||||
if Controller then
|
if Controller then
|
||||||
if self:IsAir() then
|
if self:IsAir() then
|
||||||
self:SetOption( AI.Option.Air.val.MISSILE_ATTACK, range )
|
self:SetOption( AI.Option.Air.id.MISSILE_ATTACK, range )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
@@ -4006,6 +4046,62 @@ function CONTROLLABLE:OptionEngageRange( EngageRange )
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI uses the onboard radar.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number Option Options are: `NEVER = 0, FOR_ATTACK_ONLY = 1,FOR_SEARCH_IF_REQUIRED = 2, FOR_CONTINUOUS_SEARCH = 3`
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionRadarUsing(Option)
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption(AI.Option.Air.id.RADAR_USING,Option)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI uses the onboard radar. Here: never.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionRadarUsingNever()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption(AI.Option.Air.id.RADAR_USING,0)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI uses the onboard radar, here: for attack only.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionRadarUsingForAttackOnly()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption(AI.Option.Air.id.RADAR_USING,1)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI uses the onboard radar, here: when required for searching.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionRadarUsingForSearchIfRequired()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption(AI.Option.Air.id.RADAR_USING,2)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI uses the onboard radar, here: always on.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionRadarUsingForContinousSearch()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption(AI.Option.Air.id.RADAR_USING,3)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- (GROUND) Relocate controllable to a random point within a given radius; use e.g.for evasive actions; Note that not all ground controllables can actually drive, also the alarm state of the controllable might stop it from moving.
|
--- (GROUND) Relocate controllable to a random point within a given radius; use e.g.for evasive actions; Note that not all ground controllables can actually drive, also the alarm state of the controllable might stop it from moving.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param #number speed Speed of the controllable, default 20
|
-- @param #number speed Speed of the controllable, default 20
|
||||||
@@ -4013,14 +4109,22 @@ end
|
|||||||
-- @param #boolean onroad If true, route on road (less problems with AI way finding), default true
|
-- @param #boolean onroad If true, route on road (less problems with AI way finding), default true
|
||||||
-- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false
|
-- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false
|
||||||
-- @param #string formation Formation string as in the mission editor, e.g. "Vee", "Diamond", "Line abreast", etc. Defaults to "Off Road"
|
-- @param #string formation Formation string as in the mission editor, e.g. "Vee", "Diamond", "Line abreast", etc. Defaults to "Off Road"
|
||||||
|
-- @param #boolean onland (optional) If true, try up to 50 times to get a coordinate on land.SurfaceType.LAND. Note - this descriptor value is not reliably implemented on all maps.
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:RelocateGroundRandomInRadius( speed, radius, onroad, shortcut, formation )
|
function CONTROLLABLE:RelocateGroundRandomInRadius( speed, radius, onroad, shortcut, formation, onland )
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
local _coord = self:GetCoordinate()
|
local _coord = self:GetCoordinate()
|
||||||
local _radius = radius or 500
|
local _radius = radius or 500
|
||||||
local _speed = speed or 20
|
local _speed = speed or 20
|
||||||
local _tocoord = _coord:GetRandomCoordinateInRadius( _radius, 100 )
|
local _tocoord = _coord:GetRandomCoordinateInRadius( _radius, 100 )
|
||||||
|
if onland then
|
||||||
|
for i=1,50 do
|
||||||
|
local island = _tocoord:GetSurfaceType() == land.SurfaceType.LAND and true or false
|
||||||
|
if island then break end
|
||||||
|
_tocoord = _coord:GetRandomCoordinateInRadius( _radius, 100 )
|
||||||
|
end
|
||||||
|
end
|
||||||
local _onroad = onroad or true
|
local _onroad = onroad or true
|
||||||
local _grptsk = {}
|
local _grptsk = {}
|
||||||
local _candoroad = false
|
local _candoroad = false
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ end
|
|||||||
|
|
||||||
--- Find the first(!) GROUP matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
--- Find the first(!) GROUP matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
|
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
|
||||||
-- @return #GROUP The GROUP.
|
-- @return #GROUP The GROUP.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Find a group with a partial group name
|
-- -- Find a group with a partial group name
|
||||||
@@ -327,7 +327,7 @@ end
|
|||||||
|
|
||||||
--- Find all GROUP objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
--- Find all GROUP objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
|
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
|
||||||
-- @return #table Groups Table of matching #GROUP objects found
|
-- @return #table Groups Table of matching #GROUP objects found
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Find all group with a partial group name
|
-- -- Find all group with a partial group name
|
||||||
@@ -689,7 +689,15 @@ function GROUP:GetUnits()
|
|||||||
local DCSUnits = DCSGroup:getUnits() or {}
|
local DCSUnits = DCSGroup:getUnits() or {}
|
||||||
local Units = {}
|
local Units = {}
|
||||||
for Index, UnitData in pairs( DCSUnits ) do
|
for Index, UnitData in pairs( DCSUnits ) do
|
||||||
Units[#Units+1] = UNIT:Find( UnitData )
|
|
||||||
|
local unit=UNIT:Find( UnitData )
|
||||||
|
if unit then
|
||||||
|
Units[#Units+1] = UNIT:Find( UnitData )
|
||||||
|
else
|
||||||
|
local UnitName=UnitData:getName()
|
||||||
|
unit=_DATABASE:AddUnit(UnitName)
|
||||||
|
Units[#Units+1]=unit
|
||||||
|
end
|
||||||
end
|
end
|
||||||
self:T3( Units )
|
self:T3( Units )
|
||||||
return Units
|
return Units
|
||||||
@@ -1124,8 +1132,9 @@ function GROUP:GetAverageVec3()
|
|||||||
-- Average.
|
-- Average.
|
||||||
local Vec3={x=x/n, y=y/n, z=z/n} --DCS#Vec3
|
local Vec3={x=x/n, y=y/n, z=z/n} --DCS#Vec3
|
||||||
return Vec3
|
return Vec3
|
||||||
end
|
else
|
||||||
return nil
|
return self:GetVec3()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission.
|
--- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission.
|
||||||
@@ -1157,9 +1166,15 @@ function GROUP:GetAverageCoordinate()
|
|||||||
local coord = COORDINATE:NewFromVec3(vec3)
|
local coord = COORDINATE:NewFromVec3(vec3)
|
||||||
local Heading = self:GetHeading()
|
local Heading = self:GetHeading()
|
||||||
coord.Heading = Heading
|
coord.Heading = Heading
|
||||||
|
return coord
|
||||||
else
|
else
|
||||||
BASE:E( { "Cannot GetAverageCoordinate", Group = self, Alive = self:IsAlive() } )
|
local coord = self:GetCoordinate()
|
||||||
return nil
|
if coord then
|
||||||
|
return coord
|
||||||
|
else
|
||||||
|
BASE:E( { "Cannot GetAverageCoordinate", Group = self, Alive = self:IsAlive() } )
|
||||||
|
return nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2762,7 +2777,7 @@ end
|
|||||||
|
|
||||||
--- Switch on/off invisible flag for the group.
|
--- Switch on/off invisible flag for the group.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #boolean switch If true, emission is enabled. If false, emission is disabled.
|
-- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled.
|
||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:SetCommandInvisible(switch)
|
function GROUP:SetCommandInvisible(switch)
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
@@ -2776,7 +2791,7 @@ end
|
|||||||
|
|
||||||
--- Switch on/off immortal flag for the group.
|
--- Switch on/off immortal flag for the group.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #boolean switch If true, emission is enabled. If false, emission is disabled.
|
-- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled.
|
||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:SetCommandImmortal(switch)
|
function GROUP:SetCommandImmortal(switch)
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
@@ -2922,7 +2937,7 @@ function GROUP:GetCustomCallSign(ShortCallsign,Keepnumber,CallsignTranslations)
|
|||||||
return callsign
|
return callsign
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
--- Set a GROUP to act as recovery tanker
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param Wrapper.Group#GROUP CarrierGroup.
|
-- @param Wrapper.Group#GROUP CarrierGroup.
|
||||||
-- @param #number Speed Speed in knots.
|
-- @param #number Speed Speed in knots.
|
||||||
@@ -2948,3 +2963,70 @@ function GROUP:SetAsRecoveryTanker(CarrierGroup,Speed,ToKIAS,Altitude,Delay,Last
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get a list of Link16 S/TN data from a GROUP. Can (as of Nov 2023) be obtained from F-18, F-16, F-15E (not the user flyable one) and A-10C-II groups.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #table Table of data entries, indexed by unit name, each entry is a table containing STN, VCL (voice call label), VCN (voice call number), and Lead (#boolean, if true it's the flight lead)
|
||||||
|
-- @return #string Report Formatted report of all data
|
||||||
|
function GROUP:GetGroupSTN()
|
||||||
|
local tSTN = {} -- table
|
||||||
|
local units = self:GetUnits()
|
||||||
|
local gname = self:GetName()
|
||||||
|
gname = string.gsub(gname,"(#%d+)$","")
|
||||||
|
local report = REPORT:New()
|
||||||
|
report:Add("Link16 S/TN Report")
|
||||||
|
report:Add("Group: "..gname)
|
||||||
|
report:Add("==================")
|
||||||
|
for _,_unit in pairs(units) do
|
||||||
|
local unit = _unit -- Wrapper.Unit#UNIT
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
local STN, VCL, VCN, Lead = unit:GetSTN()
|
||||||
|
local name = unit:GetName()
|
||||||
|
tSTN[name] = {
|
||||||
|
STN=STN,
|
||||||
|
VCL=VCL,
|
||||||
|
VCN=VCN,
|
||||||
|
Lead=Lead,
|
||||||
|
}
|
||||||
|
local lead = Lead == true and "(*)" or ""
|
||||||
|
report:Add(string.format("| %s%s %s %s",tostring(VCL),tostring(VCN),tostring(STN),lead))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
report:Add("==================")
|
||||||
|
local text = report:Text()
|
||||||
|
return tSTN,text
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [GROUND] Determine if a GROUP is a SAM unit, i.e. has radar or optical tracker and is no mobile AAA.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #boolean IsSAM True if SAM, else false
|
||||||
|
function GROUP:IsSAM()
|
||||||
|
local issam = false
|
||||||
|
local units = self:GetUnits()
|
||||||
|
for _,_unit in pairs(units or {}) do
|
||||||
|
local unit = _unit -- Wrapper.Unit#UNIT
|
||||||
|
if unit:HasSEAD() and unit:IsGround() and (not unit:HasAttribute("Mobile AAA")) then
|
||||||
|
issam = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return issam
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [GROUND] Determine if a GROUP has a AAA unit, i.e. has no radar or optical tracker but the AAA = true or the "Mobile AAA" = true attribute.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #boolean IsSAM True if AAA, else false
|
||||||
|
function GROUP:IsAAA()
|
||||||
|
local issam = false
|
||||||
|
local units = self:GetUnits()
|
||||||
|
for _,_unit in pairs(units or {}) do
|
||||||
|
local unit = _unit -- Wrapper.Unit#UNIT
|
||||||
|
local desc = unit:GetDesc() or {}
|
||||||
|
local attr = desc.attributes or {}
|
||||||
|
if unit:HasSEAD() then return false end
|
||||||
|
if attr["AAA"] or attr["SAM related"] then
|
||||||
|
issam = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return issam
|
||||||
|
end
|
||||||
|
|||||||
@@ -123,18 +123,38 @@ end
|
|||||||
|
|
||||||
--- Check if SCENERY Object is alive.
|
--- Check if SCENERY Object is alive.
|
||||||
--@param #SCENERY self
|
--@param #SCENERY self
|
||||||
|
--@param #number Threshold (Optional) If given, SCENERY counts as alive above this relative life in percent (1..100).
|
||||||
--@return #number life
|
--@return #number life
|
||||||
function SCENERY:IsAlive()
|
function SCENERY:IsAlive(Threshold)
|
||||||
return self:GetLife() >= 1 and true or false
|
if not Threshold then
|
||||||
|
return self:GetLife() >= 1 and true or false
|
||||||
|
else
|
||||||
|
return self:GetRelativeLife() > Threshold and true or false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if SCENERY Object is dead.
|
--- Check if SCENERY Object is dead.
|
||||||
--@param #SCENERY self
|
--@param #SCENERY self
|
||||||
|
--@param #number Threshold (Optional) If given, SCENERY counts as dead below this relative life in percent (1..100).
|
||||||
--@return #number life
|
--@return #number life
|
||||||
function SCENERY:IsDead()
|
function SCENERY:IsDead(Threshold)
|
||||||
return self:GetLife() < 1 and true or false
|
if not Threshold then
|
||||||
|
return self:GetLife() < 1 and true or false
|
||||||
|
else
|
||||||
|
return self:GetRelativeLife() <= Threshold and true or false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get SCENERY relative life in percent, e.g. 75.
|
||||||
|
--@param #SCENERY self
|
||||||
|
--@return #number rlife
|
||||||
|
function SCENERY:GetRelativeLife()
|
||||||
|
local life = self:GetLife()
|
||||||
|
local life0 = self:GetLife0()
|
||||||
|
local rlife = math.floor((life/life0)*100)
|
||||||
|
return rlife
|
||||||
|
end
|
||||||
|
|
||||||
--- Get the threat level of a SCENERY object. Always 0 as scenery does not pose a threat to anyone.
|
--- Get the threat level of a SCENERY object. Always 0 as scenery does not pose a threat to anyone.
|
||||||
--@param #SCENERY self
|
--@param #SCENERY self
|
||||||
--@return #number Threat level 0.
|
--@return #number Threat level 0.
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ end
|
|||||||
|
|
||||||
--- Find the first(!) UNIT matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
--- Find the first(!) UNIT matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
|
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
|
||||||
-- @return #UNIT The UNIT.
|
-- @return #UNIT The UNIT.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Find a group with a partial group name
|
-- -- Find a group with a partial group name
|
||||||
@@ -189,7 +189,7 @@ end
|
|||||||
|
|
||||||
--- Find all UNIT objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
--- Find all UNIT objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
|
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
|
||||||
-- @return #table Units Table of matching #UNIT objects found
|
-- @return #table Units Table of matching #UNIT objects found
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Find all group with a partial group name
|
-- -- Find all group with a partial group name
|
||||||
@@ -1659,3 +1659,36 @@ function UNIT:GetSkill()
|
|||||||
local skill = _DATABASE.Templates.Units[name].Template.skill or "Random"
|
local skill = _DATABASE.Templates.Units[name].Template.skill or "Random"
|
||||||
return skill
|
return skill
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get Link16 STN or SADL TN and other datalink info from Unit, if any.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #string STN STN or TN Octal as string, or nil if not set/capable.
|
||||||
|
-- @return #string VCL Voice Callsign Label or nil if not set/capable.
|
||||||
|
-- @return #string VCN Voice Callsign Number or nil if not set/capable.
|
||||||
|
-- @return #string Lead If true, unit is Flight Lead, else false or nil.
|
||||||
|
function UNIT:GetSTN()
|
||||||
|
self:F2(self.UnitName)
|
||||||
|
local STN = nil -- STN/TN
|
||||||
|
local VCL = nil -- VoiceCallsignLabel
|
||||||
|
local VCN = nil -- VoiceCallsignNumber
|
||||||
|
local FGL = false -- FlightGroupLeader
|
||||||
|
local template = self:GetTemplate()
|
||||||
|
if template.AddPropAircraft then
|
||||||
|
if template.AddPropAircraft.STN_L16 then
|
||||||
|
STN = template.AddPropAircraft.STN_L16
|
||||||
|
elseif template.AddPropAircraft.SADL_TN then
|
||||||
|
STN = template.AddPropAircraft.SADL_TN
|
||||||
|
end
|
||||||
|
VCN = template.AddPropAircraft.VoiceCallsignNumber
|
||||||
|
VCL = template.AddPropAircraft.VoiceCallsignLabel
|
||||||
|
end
|
||||||
|
if template.datalinks and template.datalinks.Link16 and template.datalinks.Link16.settings then
|
||||||
|
FGL = template.datalinks.Link16.settings.flightLead
|
||||||
|
end
|
||||||
|
-- A10CII
|
||||||
|
if template.datalinks and template.datalinks.SADL and template.datalinks.SADL.settings then
|
||||||
|
FGL = template.datalinks.SADL.settings.flightLead
|
||||||
|
end
|
||||||
|
|
||||||
|
return STN, VCL, VCN, FGL
|
||||||
|
end
|
||||||
|
|||||||
@@ -12,9 +12,11 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Example Missions:
|
-- ## Additional Material:
|
||||||
--
|
--
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/WRAPPER%20-%20Weapon).
|
-- * **Demo Missions:** [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Wrapper/Weapon)
|
||||||
|
-- * **YouTube videos:** None
|
||||||
|
-- * **Guides:** None
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -223,7 +225,15 @@ function WEAPON:New(WeaponObject)
|
|||||||
|
|
||||||
-- Set log ID.
|
-- Set log ID.
|
||||||
self.lid=string.format("[%s] %s | ", self.typeName, self.name)
|
self.lid=string.format("[%s] %s | ", self.typeName, self.name)
|
||||||
|
|
||||||
|
if self.launcherUnit then
|
||||||
|
self.releaseHeading = self.launcherUnit:GetHeading()
|
||||||
|
self.releaseAltitudeASL = self.launcherUnit:GetAltitude()
|
||||||
|
self.releaseAltitudeAGL = self.launcherUnit:GetAltitude(true)
|
||||||
|
self.releaseCoordinate = self.launcherUnit:GetCoordinate()
|
||||||
|
self.releasePitch = self.launcherUnit:GetPitch()
|
||||||
|
end
|
||||||
|
|
||||||
-- Set default parameters
|
-- Set default parameters
|
||||||
self:SetTimeStepTrack()
|
self:SetTimeStepTrack()
|
||||||
self:SetDistanceInterceptPoint()
|
self:SetDistanceInterceptPoint()
|
||||||
@@ -552,6 +562,52 @@ function WEAPON:GetImpactCoordinate()
|
|||||||
return self.impactCoord
|
return self.impactCoord
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the heading on which the weapon was released
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @param #bool AccountForMagneticInclination (Optional) If true will account for the magnetic declination of the current map. Default is true
|
||||||
|
-- @return #number Heading
|
||||||
|
function WEAPON:GetReleaseHeading(AccountForMagneticInclination)
|
||||||
|
AccountForMagneticInclination = AccountForMagneticInclination or true
|
||||||
|
if AccountForMagneticInclination then return UTILS.ClampAngle(self.releaseHeading - UTILS.GetMagneticDeclination()) else return UTILS.ClampAngle(self.releaseHeading) end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the altitude above sea level at which the weapon was released
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return #number Altitude in meters
|
||||||
|
function WEAPON:GetReleaseAltitudeASL()
|
||||||
|
return self.releaseAltitudeASL
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the altitude above ground level at which the weapon was released
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return #number Altitude in meters
|
||||||
|
function WEAPON:GetReleaseAltitudeAGL()
|
||||||
|
return self.releaseAltitudeAGL
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the coordinate where the weapon was released
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return Core.Point#COORDINATE Impact coordinate (if any).
|
||||||
|
function WEAPON:GetReleaseCoordinate()
|
||||||
|
return self.releaseCoordinate
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the pitch of the unit when the weapon was released
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return #number Degrees
|
||||||
|
function WEAPON:GetReleasePitch()
|
||||||
|
return self.releasePitch
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the heading of the weapon when it impacted. Note that this might not exist if the weapon has not impacted yet!
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @param #bool AccountForMagneticInclination (Optional) If true will account for the magnetic declination of the current map. Default is true
|
||||||
|
-- @return #number Heading
|
||||||
|
function WEAPON:GetImpactHeading(AccountForMagneticInclination)
|
||||||
|
AccountForMagneticInclination = AccountForMagneticInclination or true
|
||||||
|
if AccountForMagneticInclination then return UTILS.ClampAngle(self.impactHeading - UTILS.GetMagneticDeclination()) else return self.impactHeading end
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if weapon is in the air. Obviously not really useful for torpedos. Well, then again, this is DCS...
|
--- Check if weapon is in the air. Obviously not really useful for torpedos. Well, then again, this is DCS...
|
||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
-- @return #boolean If `true`, weapon is in the air and `false` if not. Returns `nil` if weapon object itself is `nil`.
|
-- @return #boolean If `true`, weapon is in the air and `false` if not. Returns `nil` if weapon object itself is `nil`.
|
||||||
@@ -712,7 +768,10 @@ function WEAPON:_TrackWeapon(time)
|
|||||||
|
|
||||||
-- Update coordinate.
|
-- Update coordinate.
|
||||||
self.coordinate:UpdateFromVec3(self.vec3)
|
self.coordinate:UpdateFromVec3(self.vec3)
|
||||||
|
|
||||||
|
-- Safe the last velocity of the weapon. This is needed to get the impact heading
|
||||||
|
self.last_velocity = self.weapon:getVelocity()
|
||||||
|
|
||||||
-- Keep on tracking by returning the next time below.
|
-- Keep on tracking by returning the next time below.
|
||||||
self.tracking=true
|
self.tracking=true
|
||||||
|
|
||||||
@@ -781,7 +840,10 @@ function WEAPON:_TrackWeapon(time)
|
|||||||
|
|
||||||
-- Safe impact coordinate.
|
-- Safe impact coordinate.
|
||||||
self.impactCoord=COORDINATE:NewFromVec3(self.vec3)
|
self.impactCoord=COORDINATE:NewFromVec3(self.vec3)
|
||||||
|
|
||||||
|
-- Safe impact heading, using last_velocity because self:GetVelocityVec3() is no longer possible
|
||||||
|
self.impactHeading = UTILS.VecHdg(self.last_velocity)
|
||||||
|
|
||||||
-- Mark impact point on F10 map.
|
-- Mark impact point on F10 map.
|
||||||
if self.impactMark then
|
if self.impactMark then
|
||||||
self.impactCoord:MarkToAll(string.format("Impact point of weapon %s\ntype=%s\nlauncher=%s", self.name, self.typeName, self.launcherName))
|
self.impactCoord:MarkToAll(string.format("Impact point of weapon %s\ntype=%s\nlauncher=%s", self.name, self.typeName, self.launcherName))
|
||||||
|
|||||||
@@ -18,5 +18,7 @@ __Moose.Include = function( IncludeFile )
|
|||||||
end
|
end
|
||||||
|
|
||||||
__Moose.Includes = {}
|
__Moose.Includes = {}
|
||||||
|
if not MOOSE_DEVELOPMENT_FOLDER then
|
||||||
__Moose.Include( 'Scripts/Moose/Modules.lua' )
|
MOOSE_DEVELOPMENT_FOLDER='Scripts'
|
||||||
|
end
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Modules.lua' )
|
||||||
|
|||||||
@@ -1,2 +1,51 @@
|
|||||||
|
|
||||||
|
-- Automatic dynamic loading of development files, if they exists.
|
||||||
|
-- Try to load Moose as individual script files from <DcsInstallDir\Script\Moose
|
||||||
|
-- which should be a Junction link to the MOOSE repository subfolder "Moose Development\Moose".
|
||||||
|
-- This method is used by Moose developers and not mission builders.
|
||||||
|
if not MOOSE_DEVELOPMENT_FOLDER then
|
||||||
|
MOOSE_DEVELOPMENT_FOLDER='Scripts'
|
||||||
|
end
|
||||||
|
|
||||||
|
ModuleLoader = MOOSE_DEVELOPMENT_FOLDER..'/Moose/Modules.lua'
|
||||||
|
|
||||||
|
if io then
|
||||||
|
local f=io.open(ModuleLoader,"r")
|
||||||
|
if f~=nil then
|
||||||
|
io.close(f)
|
||||||
|
|
||||||
|
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
|
||||||
|
|
||||||
|
local base = _G
|
||||||
|
|
||||||
|
__Moose = {}
|
||||||
|
|
||||||
|
__Moose.Include = function( IncludeFile )
|
||||||
|
if not __Moose.Includes[ IncludeFile ] then
|
||||||
|
__Moose.Includes[IncludeFile] = IncludeFile
|
||||||
|
local f = assert( base.loadfile( IncludeFile ) )
|
||||||
|
if f == nil then
|
||||||
|
error ("Moose: Could not load Moose file " .. IncludeFile )
|
||||||
|
else
|
||||||
|
env.info( "Moose: " .. IncludeFile .. " dynamically loaded." )
|
||||||
|
return f()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
__Moose.Includes = {}
|
||||||
|
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Modules.lua' )
|
||||||
|
BASE:TraceOnOff( true )
|
||||||
|
env.info( '*** MOOSE INCLUDE END *** ' )
|
||||||
|
|
||||||
|
-- Skip the static part of this file completly
|
||||||
|
do return end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
env.info( '*** MOOSE DYNAMIC INCLUDE NOT POSSIBLE (Desanitize io to use it) *** ' )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Individual Moose files are not found. Use the static code below.
|
||||||
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
|
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Utilities/Profiler.lua
|
|||||||
Utilities/Templates.lua
|
Utilities/Templates.lua
|
||||||
Utilities/STTS.lua
|
Utilities/STTS.lua
|
||||||
Utilities/FiFo.lua
|
Utilities/FiFo.lua
|
||||||
|
Utilities/Socket.lua
|
||||||
|
|
||||||
Core/Base.lua
|
Core/Base.lua
|
||||||
Core/Beacon.lua
|
Core/Beacon.lua
|
||||||
@@ -32,6 +33,8 @@ Core/TextAndSound.lua
|
|||||||
Core/Condition.lua
|
Core/Condition.lua
|
||||||
Core/Pathline.lua
|
Core/Pathline.lua
|
||||||
Core/ClientMenu.lua
|
Core/ClientMenu.lua
|
||||||
|
Core/Astar.lua
|
||||||
|
Core/MarkerOps_Base.lua
|
||||||
|
|
||||||
Wrapper/Object.lua
|
Wrapper/Object.lua
|
||||||
Wrapper/Identifiable.lua
|
Wrapper/Identifiable.lua
|
||||||
@@ -79,6 +82,9 @@ Functional/Shorad.lua
|
|||||||
Functional/Autolase.lua
|
Functional/Autolase.lua
|
||||||
Functional/AICSAR.lua
|
Functional/AICSAR.lua
|
||||||
Functional/AmmoTruck.lua
|
Functional/AmmoTruck.lua
|
||||||
|
Functional/ZoneGoalCargo.lua
|
||||||
|
Functional/Tiresias.lua
|
||||||
|
Functional/Stratego.lua
|
||||||
|
|
||||||
Ops/Airboss.lua
|
Ops/Airboss.lua
|
||||||
Ops/RecoveryTanker.lua
|
Ops/RecoveryTanker.lua
|
||||||
@@ -107,6 +113,10 @@ Ops/FlightControl.lua
|
|||||||
Ops/PlayerTask.lua
|
Ops/PlayerTask.lua
|
||||||
Ops/PlayerRecce.lua
|
Ops/PlayerRecce.lua
|
||||||
Ops/EasyGCICAP.lua
|
Ops/EasyGCICAP.lua
|
||||||
|
Ops/OpsZone.lua
|
||||||
|
Ops/ArmyGroup.lua
|
||||||
|
Ops/OpsTransport.lua
|
||||||
|
Ops/Target.lua
|
||||||
|
|
||||||
AI/AI_Balancer.lua
|
AI/AI_Balancer.lua
|
||||||
AI/AI_Air.lua
|
AI/AI_Air.lua
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ while( MooseSource ) do
|
|||||||
MooseSource = string.gsub(MooseSource, "\r", "")
|
MooseSource = string.gsub(MooseSource, "\r", "")
|
||||||
|
|
||||||
if MooseSource ~= "" then
|
if MooseSource ~= "" then
|
||||||
MooseSource = string.match( MooseSource, "Scripts/Moose/(.+)'" )
|
MooseSource = string.match( MooseSource, "/Moose/(.+)'" )
|
||||||
local MooseFilePath = MooseDevelopmentPath .. "/" .. MooseSource
|
local MooseFilePath = MooseDevelopmentPath .. "/" .. MooseSource
|
||||||
if MooseDynamicStatic == "D" then
|
if MooseDynamicStatic == "D" then
|
||||||
print( "Load dynamic: " .. MooseFilePath )
|
print( "Load dynamic: " .. MooseFilePath )
|
||||||
|
|||||||
77
docs/beginner/ask-for-help.md
Normal file
77
docs/beginner/ask-for-help.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
parent: Beginner
|
||||||
|
nav_order: 06
|
||||||
|
---
|
||||||
|
# How to ask for help
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
1. Table of contents
|
||||||
|
{:toc}
|
||||||
|
|
||||||
|
After you have tried to solve the problem on your own, you can also get help
|
||||||
|
from the community.
|
||||||
|
|
||||||
|
{: .highlight }
|
||||||
|
> But it is important to follow certain rules! Read them below.
|
||||||
|
|
||||||
|
## Communities
|
||||||
|
|
||||||
|
There are two ways to communicate with the community.
|
||||||
|
The fastest way is to use Discord:
|
||||||
|
|
||||||
|
- <https://discord.gg/gj68fm969S>{:target="_blank"}
|
||||||
|
|
||||||
|
But if you don't like Discord, you are able to post in the DCS forum.
|
||||||
|
Check out the MOOSE thread here:
|
||||||
|
|
||||||
|
- <https://forums.eagle.ru/showthread.php?t=138043>
|
||||||
|
|
||||||
|
## How to post requests
|
||||||
|
|
||||||
|
MOOSE is a community project and support is community based.
|
||||||
|
|
||||||
|
Please remember when posting a question:
|
||||||
|
|
||||||
|
- Before posting anything follow the [troubleshooting steps].
|
||||||
|
- **Read your logs**.
|
||||||
|
|
||||||
|
A post should contain the following:
|
||||||
|
|
||||||
|
1. A describtion what you expected to happen and what actually happened.
|
||||||
|
- Do not use vague words this stuff is hard to help with! Be specific.
|
||||||
|
|
||||||
|
2. Describe what happens instead.
|
||||||
|
- The less detail you offer, the less chance you can be helped.
|
||||||
|
- Don’t say it doesn’t work. Or is it broken. Say what it actually does.
|
||||||
|
|
||||||
|
3. Post your code in Discord as formatted code:
|
||||||
|
|
||||||
|
- Wrap a single line of code in backticks \` like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Multiple lines of code should be posted like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Post your log lines with the error or warning messages. Format them like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Some complex problems need the mission (.miz file) also.
|
||||||
|
|
||||||
|
- But post your mission only when requested.
|
||||||
|
- Try to simplify your mission if it is complex!
|
||||||
|
|
||||||
|
There are people in the Discord and in the forum, who spend their free time to
|
||||||
|
help you. <br />
|
||||||
|
It is your responsibility to make their "work" as easy as possible.
|
||||||
|
|
||||||
|
Welcome to MOOSE and good luck!
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
Last but not least some [tipps and tricks].
|
||||||
|
|
||||||
|
[troubleshooting steps]: problems.md
|
||||||
|
[tipps and tricks]: tipps-and-tricks.md
|
||||||
58
docs/beginner/demo-missions.md
Normal file
58
docs/beginner/demo-missions.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
parent: Beginner
|
||||||
|
nav_order: 04
|
||||||
|
---
|
||||||
|
|
||||||
|
# Demo missions
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
1. Table of contents
|
||||||
|
{:toc}
|
||||||
|
|
||||||
|
The best way to get comfortable with a Moose class is to try the demo missions
|
||||||
|
of the class you want to learn. The Moose team created a lot of demo missions
|
||||||
|
for most of the classes.
|
||||||
|
|
||||||
|
## Download demo missions
|
||||||
|
|
||||||
|
Go to the repository [MOOSE_MISSIONS]{:target="_blank"}, search the folder of
|
||||||
|
the class, download the mission (`.miz`) and run them.
|
||||||
|
|
||||||
|
## Read the mission script
|
||||||
|
|
||||||
|
In the same folder a `.lua` file with the same name is placed which is the
|
||||||
|
included mission script. You can watch these mission scripts easily online at
|
||||||
|
GitHub to understand what is happening in the mission.
|
||||||
|
|
||||||
|
## Read documentation
|
||||||
|
|
||||||
|
Next step is to read the [documentation]{:target="_blank"} of the class to
|
||||||
|
understand the code of the demo mission.
|
||||||
|
|
||||||
|
{: .note }
|
||||||
|
> The documentation is quite long and might be confusing for beginners.
|
||||||
|
> Start by looking at the description at the top of the documentation of a
|
||||||
|
> class. It often contains examples and explanations. <br /><br />
|
||||||
|
> Then search for the function names and look at the description of the
|
||||||
|
> functions and its parameters.
|
||||||
|
|
||||||
|
## Make small changes to the script
|
||||||
|
|
||||||
|
Download the `.lua` file, change the parameters to suit your needs in
|
||||||
|
[Notepad++]{:target="_blank"}, add it to the mission and rerun the mission.
|
||||||
|
Observe what happens and adapt the code.
|
||||||
|
|
||||||
|
If you want to use more functions combine them all up.
|
||||||
|
|
||||||
|
{: .note }
|
||||||
|
> But it is wise to do this in small steps. So it is easier to find errors.
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
If the mission does not show the expected behaviour take a look at section
|
||||||
|
[problems].
|
||||||
|
|
||||||
|
[MOOSE_MISSIONS]: https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop
|
||||||
|
[documentation]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/index.html
|
||||||
|
[Notepad++]: https://notepad-plus-plus.org/downloads/
|
||||||
|
[problems]: problems.md
|
||||||
181
docs/beginner/hello-world-build.md
Normal file
181
docs/beginner/hello-world-build.md
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
---
|
||||||
|
parent: Beginner
|
||||||
|
nav_order: 03
|
||||||
|
---
|
||||||
|
|
||||||
|
# Create your own Hello world
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
1. Table of contents
|
||||||
|
{:toc}
|
||||||
|
|
||||||
|
This page will lead you step by step through the process of creating a mission
|
||||||
|
with MOOSE. This time we include a simple mission script, which sends only
|
||||||
|
a "Hello world" message to all players. But the steps are the same to add
|
||||||
|
another mission script, which will do whatever class(es) you want to use.
|
||||||
|
|
||||||
|
## Create Mission script
|
||||||
|
|
||||||
|
At first we will create the mission script. It is a simple text file and can be
|
||||||
|
changed with a lot of different tools. Theoretically even the Microsoft Notepad
|
||||||
|
editor can be used. But it lacks a lot of features, which helps you to avoid
|
||||||
|
errors.
|
||||||
|
|
||||||
|
For this guide we suggest you to download, install and use [Notepad++]{:target="_blank"}.
|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> Windows hides filename extensions by default. So when you create a text file
|
||||||
|
> and name it `hello-world.lua` it's name is `hello-world.lua.txt` in reality.
|
||||||
|
> You must activate the display of the file name extension.
|
||||||
|
> Open a `File Explorer`, switch to menu `View` and find the option
|
||||||
|
> `File name extensions` in the section `Show/hide`. Activate it.
|
||||||
|
|
||||||
|
- Open a File Explorer.
|
||||||
|
- Go to the subfolder `Missions` of your [Saved Games folder]{:target="_blank"}.
|
||||||
|
- Create a new text file and name it `hello-world.lua`.
|
||||||
|
- Add the following content and save the file:
|
||||||
|
|
||||||
|
`MESSAGE:New( "Hello World! This messages is printed by MOOSE", 35, "INFO" ):ToAll()`
|
||||||
|
|
||||||
|
## Get Moose
|
||||||
|
|
||||||
|
To download Moose click on the following link:
|
||||||
|
|
||||||
|
- [Moose_.lua from develop branch]{:target="_blank"}
|
||||||
|
|
||||||
|
Press `Ctrl + S` to save the file on your hard disk next to your mission script.
|
||||||
|
|
||||||
|
## Create the mission
|
||||||
|
|
||||||
|
- Start DCS.
|
||||||
|
- In the main menu choose `MISSION EDITOR`.
|
||||||
|
- Click on `create new mission`.
|
||||||
|
- In the dialog `NEW MISSION SETTINGS`:
|
||||||
|
- Choose map `Caucasus`.
|
||||||
|
- In the drop box upper left choose `Modern` as coalition preset.
|
||||||
|
- Click on `OK`.
|
||||||
|
- The mission editor will load with a fresh new and empty mission.
|
||||||
|
- Click on `File` in the menu bar and `SAVE` or Press `Ctrl + S`.
|
||||||
|
- Open `My Missions` and save the file with the name `hello-world.miz`.
|
||||||
|
|
||||||
|
## Add Moose to the mission
|
||||||
|
|
||||||
|
- On the left side activate `TRIGGERS`:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- On the right side the `TRIGGERS` dialog opens with a lot of options.
|
||||||
|
- Click on `NEW`, choose `4 MISSION START` as **TYPE**.
|
||||||
|
- Give it the `Load MOOSE` as **NAME**.
|
||||||
|
- Leave the **EVENT** option set to `NO EVENT`.
|
||||||
|
- Optional: Choose a color for easy recognition (e.g. yellow).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- In the middle part the `CONDITIONS` will be shown.
|
||||||
|
For this trigger we do not configure any conditions.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> The trigger type `4 MISSION START` does not support `CONDITIONS`. <br />
|
||||||
|
> So `CONDITIONS` must left blank when using it. <br />
|
||||||
|
> **If you add a condition the trigger will never be executed!**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- On the right side `ACTIONS` is shown.
|
||||||
|
- We need to click on `NEW`.
|
||||||
|
- Choose **ACTION** `Do SCRIPT FILE` and ignore all other actions.
|
||||||
|
- Click **OPEN** and navigate to the downloaded `Moose_.lua` file.
|
||||||
|
- The result should look like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Add the mission script
|
||||||
|
|
||||||
|
- Click on `NEW`, choose `1 ONCE` as **TYPE**.
|
||||||
|
- Give it the `Load Mission Script` as **NAME**.
|
||||||
|
- Leave the **EVENT** option set to `NO EVENT`.
|
||||||
|
- Optional: Choose a color for easy recognition (e.g. green).
|
||||||
|
- The result should look like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Switch to the middle part, the `CONDITIONS` section. <br />
|
||||||
|
For this trigger we add one condition:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- The combination of `1 ONCE` with `TIME MORE(1)` will ensure, that the mission
|
||||||
|
script is executed 1 second after the mission is started.
|
||||||
|
|
||||||
|
- On the right side under `ACTIONS` you need to add the script:
|
||||||
|
- Click on `NEW`.
|
||||||
|
- Choose **ACTION** `Do SCRIPT FILE`.
|
||||||
|
- Click **OPEN** and navigate to the created `hello-world.lua` file.
|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> Most important is the fact, that the mission script (`hello-world.lua`)
|
||||||
|
> is executed **after** `Moose_.lua`, because the mission script needs the
|
||||||
|
> classes defined in `Moose_.lua`. And they are only available when `Moose_.lua`
|
||||||
|
> is executed before the mission script.
|
||||||
|
|
||||||
|
## Test the mission
|
||||||
|
|
||||||
|
- Save the mission again.
|
||||||
|
- Click on the green **Fly mission** cirlce on the left tool side bar.
|
||||||
|
- It is an empty mission, so skip `BRIEFING` with `START` and then `FLY`.
|
||||||
|
- You spawn as a spectator. After some seconds you will see this message in
|
||||||
|
the upper right corner:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This is the same result as already seen in the last chapter, but this time you
|
||||||
|
have create everything on your own.
|
||||||
|
|
||||||
|
{: .note }
|
||||||
|
> You can use this mission as a template for your own missions. So you don't
|
||||||
|
> need to do alle these steps again and again.
|
||||||
|
|
||||||
|
## Update mission script
|
||||||
|
|
||||||
|
- Open the `hello-world.lua` with Notepad++ again.
|
||||||
|
- Change the text a little bit, like `Hello Dude! ...` and save the file.
|
||||||
|
- Run the mission again.
|
||||||
|
- The text will not be changed in the mission. Why?
|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
The mission editor copies the script into the mission file when you add it.
|
||||||
|
Every change on the script file on your hard disk is not recognized by mission
|
||||||
|
editor. **You have to add the file after each change again!**
|
||||||
|
|
||||||
|
There is also another method available to dynamically load mission scripts.
|
||||||
|
But this method has some brawbacks and will be explained in the advanced section.
|
||||||
|
|
||||||
|
Now we add the mission script again:
|
||||||
|
|
||||||
|
- On the left side of the `TRIGGERS` dialog click on `Load Mission Script`.
|
||||||
|
- On the right side under `ACTIONS` you need to add the script again:
|
||||||
|
- Click **OPEN** and navigate to the created `hello-world.lua` file.
|
||||||
|
- Save the mission and test it again.
|
||||||
|
- Now the new text should be shown.
|
||||||
|
|
||||||
|
## Update Moose
|
||||||
|
|
||||||
|
Moose is constantly being developed so that new functionallity is added or
|
||||||
|
existing errors are corrected. Also from time to time changes of the DCS
|
||||||
|
scripting engine comes with a new DCS version. It may therefore be useful or
|
||||||
|
necessary to update Moose.
|
||||||
|
|
||||||
|
- To update Moose download it again and add it again in the same way you did
|
||||||
|
with the mission script in the last step.
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
Let's move on to the [demo missions].
|
||||||
|
|
||||||
|
[Notepad++]: https://notepad-plus-plus.org/downloads/
|
||||||
|
[Saved Games folder]: tipps-and-tricks.md#find-the-saved-games-folder
|
||||||
|
[Moose_.lua from develop branch]: https://raw.githubusercontent.com/FlightControl-Master/MOOSE_INCLUDE/develop/Moose_Include_Static/Moose_.lua
|
||||||
|
[demo missions]: demo-missions.md
|
||||||
178
docs/beginner/hello-world.md
Normal file
178
docs/beginner/hello-world.md
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
---
|
||||||
|
parent: Beginner
|
||||||
|
nav_order: 02
|
||||||
|
---
|
||||||
|
|
||||||
|
# Hello world mission
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
1. Table of contents
|
||||||
|
{:toc}
|
||||||
|
|
||||||
|
## Let's see MOOSE in action
|
||||||
|
|
||||||
|
It is tradition that the first piece of code is a very simple example on showing
|
||||||
|
a "Hello world!" to the user. We have prepared this example mission for you. So
|
||||||
|
you can download and run it. Later on we will analyze it to explain the basics
|
||||||
|
on how to add MOOSE to your own missions.
|
||||||
|
|
||||||
|
- Download the demo mission [001-hello-world.miz] by clicking on the link.
|
||||||
|
- Put the .miz file into your Missions subfolder of your [Saved Games folder].
|
||||||
|
- Start DCS, choose `MISSION` in the menu on the right side:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Click on `My Missions`, choose the `hello-world` mission and click on `OK`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- It is an empty mission, so skip `BRIEFING` with `START` and then `FLY`.
|
||||||
|
- You spawn as a spectator. After some seconds you will see this message in
|
||||||
|
the upper right corner:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Ok, that's all. There is nothing more to see in this mission. This is not
|
||||||
|
particularly impressive and can also be achieved using standard Lua in DCS
|
||||||
|
(i.e. without MOOSE), but we want to keep it simple at the beginning.
|
||||||
|
|
||||||
|
{: .note }
|
||||||
|
> If the text don't show up, the mission might be corrupted. Please contact the
|
||||||
|
> team on Discord for futher instructions.
|
||||||
|
|
||||||
|
## Let's take a look under the hood
|
||||||
|
|
||||||
|
- Go back to the main window and open the `MISSION EDITOR`.
|
||||||
|
- Choose `open mission` navigate to `My Missions` and open 001-hello-world.miz.
|
||||||
|
- On the left side activate `TRIGGERS`:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- On the right side the `TRIGGERS` dialog opens with a lot of options.
|
||||||
|
- First take a look at the available triggers:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- You will see two:
|
||||||
|
- One in yellow with type `4 MISSION START` and name `Load MOOSE` and
|
||||||
|
- one in green with type `1 ONCE` and name `Load Mission Script`.
|
||||||
|
|
||||||
|
### Execution of Moose
|
||||||
|
|
||||||
|
- Click on the yellow one to show all of it options.
|
||||||
|
|
||||||
|
- In the middle part the `CONDITIONS` will be shown.
|
||||||
|
For this trigger there are no conditions configured.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> The trigger type `4 MISSION START` does not support `CONDITIONS`. <br />
|
||||||
|
> So `CONDITIONS` must left blank when using it. <br />
|
||||||
|
> **If you add a condition the trigger will never be executed!**
|
||||||
|
|
||||||
|
- On the right side the `ACTIONS` will be shown:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- A `DO SCRIPT FILE` is configured, which executes the file `Moose_.lua`
|
||||||
|
|
||||||
|
{: .highlight }
|
||||||
|
> This is the execution of the Moose framework included in the mission as one single file. <br />
|
||||||
|
> The difference between `Moose_.lua` and `Moose.lua` will be explained later. <br />
|
||||||
|
> This doesn't matter at this time.
|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> The trigger `4 MISSION START` will be executed **before** the mission is started! <br />
|
||||||
|
> This is important, because Moose **must** be executed before other scripts, that want to use Moose!
|
||||||
|
|
||||||
|
### Execution of the mission script
|
||||||
|
|
||||||
|
- Now move back to the left `TRIGGERS` area and click on the green trigger <br />
|
||||||
|
`1 ONCE (Load Mission Script ...)`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- The configured options will be shown. <br />
|
||||||
|
In the middle part the `CONDITIONS` will be shown. <br />
|
||||||
|
For this trigger there is one condition configured:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- The combination of `1 ONCE` with `TIME MORE(1)` will ensure, that the mission
|
||||||
|
script is executed 1 second after the mission is started.
|
||||||
|
|
||||||
|
- On the right side the `ACTIONS` will be shown:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- A `DO SCRIPT FILE` is configured, which executes the file `001-hello-world.lua`.
|
||||||
|
|
||||||
|
{: .highlight }
|
||||||
|
> This is the execution of the mission script, which you will create in the future.
|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> Most important is the fact, that the mission script (`001-hello-world.lua`)
|
||||||
|
> is executed **after** `Moose_.lua`, because the mission script needs the
|
||||||
|
> classes defined in `Moose_.lua`. And they are only available when `Moose_.lua`
|
||||||
|
> is executed before the mission script.
|
||||||
|
|
||||||
|
### Inspect the code of the mission script
|
||||||
|
|
||||||
|
The file `001-hello-world.lua` consists of following code:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
--
|
||||||
|
-- Simple example mission to show the very basics of MOOSE
|
||||||
|
--
|
||||||
|
MESSAGE:New( "Hello World! This messages is printed by MOOSE", 35, "INFO" ):ToAll()
|
||||||
|
```
|
||||||
|
|
||||||
|
- The first three lines starting with `--` are comments and will be ignored.
|
||||||
|
|
||||||
|
- Line 4 is the one with the "magic":
|
||||||
|
|
||||||
|
- With `MESSAGE` we use the class [Core.Message].
|
||||||
|
|
||||||
|
The part before the dot (Core) is the section where the class is placed.
|
||||||
|
It is important for the Moose programmes to have a structure where the classes
|
||||||
|
are placed. But in the code itself it is not used.
|
||||||
|
|
||||||
|
#### What is a class?
|
||||||
|
|
||||||
|
{: .highlight }
|
||||||
|
> In object-oriented programming, a class is an extensible program-code-template
|
||||||
|
> for creating objects, providing initial values for state (member variables)
|
||||||
|
> and implementations of behavior (member functions or methods). <br />
|
||||||
|
> *Source [Wikipedia:Class]{:target="_blank"}*
|
||||||
|
|
||||||
|
After the class name we call a method of that class. We do this with semicolon
|
||||||
|
followed by the name of the method and a pair of round brackets.
|
||||||
|
Here we call the method `New`, which creates a new MESSAGE object.
|
||||||
|
|
||||||
|
We give it three parameters within the round brackets, which are divided by commas:
|
||||||
|
1. The text we want to show: `"Hello World! ..."`
|
||||||
|
1. The time in seconds the messages should be visible: `35`
|
||||||
|
1. And the type of message: `"INFO"`
|
||||||
|
|
||||||
|
- With `New` the MESSAGE object is created, but the message is still not printed
|
||||||
|
to the screen.
|
||||||
|
- This is done by `:ToAll()`. Another method of [Core.Message] which sends the
|
||||||
|
message to all players, no matter if they belong to the RED or BLUE coalition.
|
||||||
|
|
||||||
|
If you you want to read more about [Core.Message] click on the link.
|
||||||
|
The page with all the Methods and Fields is very long and this might be
|
||||||
|
daunting, but for the copy and paste approach, you won't need it often.
|
||||||
|
|
||||||
|
And if you want to learn how to use more of that stuff, you will become
|
||||||
|
compftable in filtering these informations fast.
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
Now it is time to [create your own Hello world] mission.
|
||||||
|
|
||||||
|
[Saved Games folder]: ../beginner/tipps-and-tricks.md#find-the-saved-games-folder
|
||||||
|
[hello-world demo mission]: https://raw.githubusercontent.com/FlightControl-Master/MOOSE_MISSIONS/master/Core/Message/001-hello-world.miz
|
||||||
|
[Core.Message]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Message.html
|
||||||
|
[Wikipedia:Class]: https://en.wikipedia.org/wiki/Class_(computer_programming)
|
||||||
|
[create your own Hello world]: hello-world-build.md
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user