mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Compare commits
497 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6058160160 | ||
|
|
479dfc28b9 | ||
|
|
8392788cdb | ||
|
|
55242edbde | ||
|
|
2c5d9f043e | ||
|
|
2b2acbe244 | ||
|
|
7d4e103660 | ||
|
|
86798ae9ea | ||
|
|
2830e6d199 | ||
|
|
8c07573f8f | ||
|
|
f3af0262df | ||
|
|
0f270a6a35 | ||
|
|
8432f46e48 | ||
|
|
faccee88e7 | ||
|
|
e8246b3b90 | ||
|
|
eb4e7b9281 | ||
|
|
1e2190a6cc | ||
|
|
1644c1dc5b | ||
|
|
5fc3798c42 | ||
|
|
fae81cdb1b | ||
|
|
dbae37f151 | ||
|
|
f7d58a0b76 | ||
|
|
2e0d1fd90f | ||
|
|
69e6497655 | ||
|
|
ef8c7c9084 | ||
|
|
e4eaf72769 | ||
|
|
5138ced630 | ||
|
|
534f445f8c | ||
|
|
b2cc3e5329 | ||
|
|
efde321616 | ||
|
|
3a61581608 | ||
|
|
3a10f0b946 | ||
|
|
6dc6972bdb | ||
|
|
405235a59d | ||
|
|
9c148625e4 | ||
|
|
a08d82a3d9 | ||
|
|
48b51f21de | ||
|
|
3260279cb7 | ||
|
|
1e60a0a32a | ||
|
|
146f869aaa | ||
|
|
0bd35727f4 | ||
|
|
5183fcc316 | ||
|
|
bf7596521c | ||
|
|
a85b6c960c | ||
|
|
a1aebf0575 | ||
|
|
0f42218681 | ||
|
|
5404f9ef19 | ||
|
|
8a84be19df | ||
|
|
fd4ea81e46 | ||
|
|
3df79aedb1 | ||
|
|
4141aa35ba | ||
|
|
6e45ee558e | ||
|
|
db138be5f3 | ||
|
|
5ae6495e69 | ||
|
|
58f1bc5531 | ||
|
|
935b52c489 | ||
|
|
aace98545a | ||
|
|
f39236c8fd | ||
|
|
43b4a6834b | ||
|
|
aa3978b04d | ||
|
|
b51e758516 | ||
|
|
5be1832c09 | ||
|
|
362652ac6c | ||
|
|
aec69884dc | ||
|
|
8fb4d4c7c6 | ||
|
|
b5524b9a69 | ||
|
|
ec0ff7afcd | ||
|
|
d0cf68c2e2 | ||
|
|
3beb98a5e9 | ||
|
|
dd83ebe0e2 | ||
|
|
6fdf3957bd | ||
|
|
f3d586d455 | ||
|
|
c2f0ce0fa2 | ||
|
|
354490d149 | ||
|
|
c5b0be5d21 | ||
|
|
5e8676cf8a | ||
|
|
f4264cd149 | ||
|
|
65d1c4187e | ||
|
|
cda1432d04 | ||
|
|
09e5fca1a5 | ||
|
|
e38d73df8b | ||
|
|
7df90b2d30 | ||
|
|
a917ee8f1e | ||
|
|
44f3c776eb | ||
|
|
873879ff79 | ||
|
|
6c1907f7e0 | ||
|
|
42ecdd3b14 | ||
|
|
297164a0ee | ||
|
|
323f09b06c | ||
|
|
e003b91bbe | ||
|
|
f1636fc5a9 | ||
|
|
db053398d2 | ||
|
|
417caf1b62 | ||
|
|
cc76851614 | ||
|
|
27fe314c1e | ||
|
|
2c12cfe4fd | ||
|
|
9adf342dd8 | ||
|
|
facac82130 | ||
|
|
3e095711f4 | ||
|
|
ca1ddb4013 | ||
|
|
8169235d2f | ||
|
|
4553785918 | ||
|
|
78b3efcf00 | ||
|
|
67cb844550 | ||
|
|
b9cf1e46af | ||
|
|
4a04d7cce7 | ||
|
|
35f15435a3 | ||
|
|
4c97d966a2 | ||
|
|
674c6eec81 | ||
|
|
c75c3d8777 | ||
|
|
4fa63986dc | ||
|
|
029f7a3f5c | ||
|
|
e9194c59f4 | ||
|
|
c8d693c8e7 | ||
|
|
2341014882 | ||
|
|
eb15fadcfe | ||
|
|
13fa8f373e | ||
|
|
b318e8ae13 | ||
|
|
7e963bef41 | ||
|
|
933000ffc7 | ||
|
|
9b217e1c97 | ||
|
|
324f4944b4 | ||
|
|
f735f1eb53 | ||
|
|
7149226283 | ||
|
|
4164a5288a | ||
|
|
1992276b07 | ||
|
|
21a7023b7b | ||
|
|
f094716b73 | ||
|
|
4b1888a34d | ||
|
|
b9be3aa7f8 | ||
|
|
fd2dacaefb | ||
|
|
cc60e85901 | ||
|
|
f172f6efeb | ||
|
|
b6b6686873 | ||
|
|
5e724e7a3f | ||
|
|
90f1d1df2a | ||
|
|
a5726c0ed8 | ||
|
|
23ff128ac8 | ||
|
|
7d3fc1740a | ||
|
|
b2a084d669 | ||
|
|
30203668e4 | ||
|
|
ebecc70693 | ||
|
|
74712b6e27 | ||
|
|
40253ea8bb | ||
|
|
4e56078d2a | ||
|
|
4bbf20ca4e | ||
|
|
a462c5a493 | ||
|
|
367014ebf3 | ||
|
|
326b20b08d | ||
|
|
11b0ce6275 | ||
|
|
03763e16d6 | ||
|
|
c1e8ee12e0 | ||
|
|
ac8cc408c1 | ||
|
|
ada38fa3ea | ||
|
|
2ee0597d48 | ||
|
|
7ae4cdc8f1 | ||
|
|
8c92a578ed | ||
|
|
096f2caf9c | ||
|
|
0b37c909b3 | ||
|
|
1b18ae1597 | ||
|
|
c9ac6d73e6 | ||
|
|
0e836973fd | ||
|
|
be40d7be9a | ||
|
|
f3b7740041 | ||
|
|
7d7488db6f | ||
|
|
4964cc2f2d | ||
|
|
f0a4c5b008 | ||
|
|
1b6412821b | ||
|
|
926a0733e4 | ||
|
|
da70f4ce6c | ||
|
|
727cb3276c | ||
|
|
33e63a4819 | ||
|
|
3543b2c79a | ||
|
|
4489efff94 | ||
|
|
6a4bddde99 | ||
|
|
dc2511942c | ||
|
|
f0c257c4a5 | ||
|
|
068d21612f | ||
|
|
773461aad9 | ||
|
|
f9257b2b0d | ||
|
|
9e0f03a3cd | ||
|
|
a467fabdc8 | ||
|
|
a2ab84c45a | ||
|
|
9fd6729967 | ||
|
|
f1d4f1753a | ||
|
|
6d9c3fd0aa | ||
|
|
28ae63bd8d | ||
|
|
42e7e3f94f | ||
|
|
6466c5e95e | ||
|
|
829f5af25f | ||
|
|
0d1147bac4 | ||
|
|
24b47b02e0 | ||
|
|
3cabc07d58 | ||
|
|
b0546b1e60 | ||
|
|
a988e67490 | ||
|
|
2594c5bbf0 | ||
|
|
db70fa341c | ||
|
|
763e3852ac | ||
|
|
8ec86973c6 | ||
|
|
eb2c6ac6f2 | ||
|
|
cbcc893ce5 | ||
|
|
382b049c5f | ||
|
|
a53763221c | ||
|
|
b7bac28113 | ||
|
|
a9edb16554 | ||
|
|
0aeb1fc6af | ||
|
|
eeeeda4e5e | ||
|
|
f5881eda53 | ||
|
|
c1997d9f70 | ||
|
|
bb1caa6642 | ||
|
|
dd5ca93f26 | ||
|
|
1889df4952 | ||
|
|
7ca219748d | ||
|
|
2fc16ba694 | ||
|
|
a4feafab8e | ||
|
|
997baf21a0 | ||
|
|
b126cc00d0 | ||
|
|
09b7922b84 | ||
|
|
7a5b9a75f3 | ||
|
|
4bab2ee1de | ||
|
|
d7defe6f7f | ||
|
|
db869bcb6d | ||
|
|
ea4a1f9ff9 | ||
|
|
20406e40ca | ||
|
|
3b50fee5a0 | ||
|
|
804004198b | ||
|
|
5b8b8a5566 | ||
|
|
0468bacc0b | ||
|
|
7eba1349ae | ||
|
|
b6074a4795 | ||
|
|
36c9f551d9 | ||
|
|
89c3f7310b | ||
|
|
a6b622ed31 | ||
|
|
f1af3a50b8 | ||
|
|
0c90e90c18 | ||
|
|
f97ef25104 | ||
|
|
069c0aa03f | ||
|
|
b145588ed5 | ||
|
|
3ad60a95ce | ||
|
|
ac4b620f16 | ||
|
|
ccada18a6a | ||
|
|
1547d66327 | ||
|
|
8042e8bfaf | ||
|
|
dd7b87e9cd | ||
|
|
460d2768ff | ||
|
|
3c74272749 | ||
|
|
82c409d77a | ||
|
|
195aac4504 | ||
|
|
08d8f3e25f | ||
|
|
6f72697e26 | ||
|
|
0f6439cf9f | ||
|
|
2c10943cb1 | ||
|
|
544db963ea | ||
|
|
207698a2dd | ||
|
|
d1ae2c0f5e | ||
|
|
0392417189 | ||
|
|
be4beea9d0 | ||
|
|
5da899138b | ||
|
|
1ec1e00bde | ||
|
|
5d93b33d42 | ||
|
|
b2077bfc74 | ||
|
|
6fdf9a649f | ||
|
|
d013bbc751 | ||
|
|
e0092fdba0 | ||
|
|
fbeada439f | ||
|
|
6c8858d2f5 | ||
|
|
e2b77878df | ||
|
|
53d7972858 | ||
|
|
04a55e4104 | ||
|
|
d11acecdac | ||
|
|
49c11073e6 | ||
|
|
1a156e7e12 | ||
|
|
1856754614 | ||
|
|
6ac452ff15 | ||
|
|
d707a4775c | ||
|
|
ffccc31e38 | ||
|
|
0405af2bde | ||
|
|
e50e572c78 | ||
|
|
3083599158 | ||
|
|
b7b6c1ea19 | ||
|
|
5b107ce2da | ||
|
|
5c1e342a79 | ||
|
|
ddf33da787 | ||
|
|
b0a192a767 | ||
|
|
986c340211 | ||
|
|
2109537f86 | ||
|
|
690db7f12f | ||
|
|
4f3fd06cc9 | ||
|
|
4074023ed3 | ||
|
|
6c00b0c7eb | ||
|
|
76dc0d690a | ||
|
|
d783f7be99 | ||
|
|
b66e91b11f | ||
|
|
dc83af4d02 | ||
|
|
0a38700edb | ||
|
|
659615114a | ||
|
|
4955fe4d92 | ||
|
|
792aa73832 | ||
|
|
a915452e6e | ||
|
|
be8405b72b | ||
|
|
5ca3e3b2b8 | ||
|
|
618a8744a2 | ||
|
|
23aeef7a20 | ||
|
|
9ac4f136aa | ||
|
|
c9a09c2fc9 | ||
|
|
6028c91f81 | ||
|
|
3c57928f46 | ||
|
|
32f0bb33c3 | ||
|
|
31d0410284 | ||
|
|
87c436ba34 | ||
|
|
6e9727e265 | ||
|
|
94ee76fe62 | ||
|
|
ea23162ca9 | ||
|
|
683388faee | ||
|
|
56ec3920c5 | ||
|
|
f335ffc4ec | ||
|
|
4976cd86f2 | ||
|
|
c00eff8b23 | ||
|
|
3c710613a8 | ||
|
|
45ebf9a3c7 | ||
|
|
c808e4a4e2 | ||
|
|
e2612b97d7 | ||
|
|
70e9d91bb5 | ||
|
|
0b8810f8b3 | ||
|
|
41b867a4ca | ||
|
|
1c0a8d9380 | ||
|
|
2b0b9d44eb | ||
|
|
2fc7a3b542 | ||
|
|
12b596a47f | ||
|
|
8ef781a9ac | ||
|
|
43eeaede65 | ||
|
|
749c5f87de | ||
|
|
a520daeb56 | ||
|
|
f9ba96f228 | ||
|
|
a49bd23a2a | ||
|
|
cea2f18228 | ||
|
|
fd2d8a5119 | ||
|
|
fa4e0447dd | ||
|
|
31aa604fc4 | ||
|
|
f44db27565 | ||
|
|
9b1abab73a | ||
|
|
cad8f15b61 | ||
|
|
1d08bcf2e0 | ||
|
|
9487a5ae91 | ||
|
|
96337cc5df | ||
|
|
bc9eee22b7 | ||
|
|
f74d25b31c | ||
|
|
1156971d94 | ||
|
|
c79b5c37c4 | ||
|
|
a2b650a9e3 | ||
|
|
905b442e9b | ||
|
|
18fe3112bd | ||
|
|
cc057744ba | ||
|
|
db1779e1db | ||
|
|
d25a723fc7 | ||
|
|
f0fe1b431d | ||
|
|
8e286edd25 | ||
|
|
74520b1359 | ||
|
|
d06e44d37b | ||
|
|
35348d9b81 | ||
|
|
4b16e94eaf | ||
|
|
d983676330 | ||
|
|
03c30f3cce | ||
|
|
99b93266ad | ||
|
|
e307b57e67 | ||
|
|
5ef9bb2acd | ||
|
|
4aacdc1567 | ||
|
|
57552f4300 | ||
|
|
09d53f7d8c | ||
|
|
d9948d1a19 | ||
|
|
5f7a4f2bbb | ||
|
|
1b6945e0b0 | ||
|
|
4fd55b1bd6 | ||
|
|
20b8deb6de | ||
|
|
6af836c118 | ||
|
|
f87b8a2c2a | ||
|
|
daffd7412a | ||
|
|
bfb60b318e | ||
|
|
a55959dfbb | ||
|
|
4d24eb82be | ||
|
|
e26caa2f74 | ||
|
|
b75fff60c8 | ||
|
|
4ac57fce7a | ||
|
|
25a9a0120a | ||
|
|
66a1fa8af5 | ||
|
|
1b4033cfce | ||
|
|
48bc41873a | ||
|
|
068a1ab99c | ||
|
|
6551383070 | ||
|
|
b03978cc3d | ||
|
|
82f4c5790a | ||
|
|
5957124e9e | ||
|
|
92a05ca74a | ||
|
|
d02b5db6dd | ||
|
|
bd074728fe | ||
|
|
61b7b3ead6 | ||
|
|
7f7999e3e5 | ||
|
|
b522b38d31 | ||
|
|
b2dc7bc232 | ||
|
|
def622a02c | ||
|
|
30bedb39f1 | ||
|
|
fbcc4ee32b | ||
|
|
63c68d729b | ||
|
|
04f8f6d512 | ||
|
|
b74d46f762 | ||
|
|
02decc3901 | ||
|
|
dcdea16624 | ||
|
|
2635cf6345 | ||
|
|
e86069d39c | ||
|
|
fdcf153b0b | ||
|
|
8523b7e20a | ||
|
|
29b992bf81 | ||
|
|
4c52509d6d | ||
|
|
9bc067f2e8 | ||
|
|
5fbe0d9a70 | ||
|
|
474f767e56 | ||
|
|
f9030be843 | ||
|
|
538e35d8f0 | ||
|
|
203f0c8abc | ||
|
|
d0736b0b56 | ||
|
|
15b1ed028e | ||
|
|
008617a35c | ||
|
|
6144a61a2e | ||
|
|
5d192abd25 | ||
|
|
62337f445a | ||
|
|
b38c1c5827 | ||
|
|
c08cee2317 | ||
|
|
0f7759d070 | ||
|
|
4a0842bea6 | ||
|
|
3b3666c5f7 | ||
|
|
45912911ee | ||
|
|
9916afaa49 | ||
|
|
55c5a23616 | ||
|
|
6bee1cc88e | ||
|
|
43ab4d5f38 | ||
|
|
0427c0d3a7 | ||
|
|
014750ea7f | ||
|
|
e4bbfce314 | ||
|
|
359429b17e | ||
|
|
6001f6abda | ||
|
|
fd9b5d8d16 | ||
|
|
b6f184388a | ||
|
|
d8471698ab | ||
|
|
6204cecbbd | ||
|
|
ddeca49916 | ||
|
|
d8dcf37886 | ||
|
|
5ae41a208b | ||
|
|
0462d900e6 | ||
|
|
0f962461e1 | ||
|
|
aadc03c38d | ||
|
|
683fa13bb2 | ||
|
|
e4408a964d | ||
|
|
f97f33ab59 | ||
|
|
f59102ee09 | ||
|
|
e42e4e1ddf | ||
|
|
a30079c45b | ||
|
|
50ffd9aba6 | ||
|
|
936fec1f49 | ||
|
|
9625d87dd5 | ||
|
|
802139205c | ||
|
|
fb918cb2a4 | ||
|
|
abb4de46d7 | ||
|
|
dce9631399 | ||
|
|
6c773786d2 | ||
|
|
8939963187 | ||
|
|
f9747d1c4c | ||
|
|
60a3d3409e | ||
|
|
b72124c0d9 | ||
|
|
d51e761b26 | ||
|
|
1445ef61a0 | ||
|
|
dfe2ed2a98 | ||
|
|
be87103b53 | ||
|
|
2fb460c4bb | ||
|
|
216ea230a8 | ||
|
|
90096163ee | ||
|
|
cd178d6a8c | ||
|
|
2aa0b5ddfb | ||
|
|
37f819458a | ||
|
|
168f4301d2 | ||
|
|
d5a406c60f | ||
|
|
cb16210577 | ||
|
|
8c0e0de45f | ||
|
|
3524cba4ef | ||
|
|
5f8d1cf5b0 | ||
|
|
846aa823d4 | ||
|
|
68298fc585 | ||
|
|
e9d75f6d94 | ||
|
|
8fa5277417 | ||
|
|
231f1f236d | ||
|
|
ece0a46f97 | ||
|
|
2c9b0b8376 | ||
|
|
a798f2d61c | ||
|
|
ae08c87822 | ||
|
|
ae880e9d1c | ||
|
|
101d2e1de5 | ||
|
|
f6b7708567 | ||
|
|
051286acd1 |
@ -1953,7 +1953,7 @@ local function refct_from_id(id) -- refct = refct_from_id(CTypeID)
|
||||
unsigned = refct.unsigned,
|
||||
size = bit.band(bit.rshift(ctype.info, 16), 127),
|
||||
}
|
||||
refct.bool, refct.const, refct.volatile, refct.unsigned = nil
|
||||
refct.bool, refct.const, refct.volatile, refct.unsigned = nil, nil, nil, nil
|
||||
end
|
||||
|
||||
if CT[4] then -- Merge sibling attributes onto this type.
|
||||
|
||||
@ -17,7 +17,9 @@
|
||||
|
||||
--- The AI_A2A_CAP class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
|
||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_CAP is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_CAP process can be started using the **Start** event.
|
||||
|
||||
@ -32,7 +32,9 @@
|
||||
-- [DCS WORLD - MOOSE - A2A GCICAP - Build an automatic A2A Defense System](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0S4KMNUUJpaUs6zZHjLKNx)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # QUICK START GUIDE
|
||||
--
|
||||
-- There are basically two classes available to model an A2A defense system.
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_GCI is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_GCI process can be started using the **Start** event.
|
||||
--
|
||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
|
||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_PATROL process can be started using the **Start** event.
|
||||
|
||||
@ -16,7 +16,9 @@
|
||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
|
||||
@ -36,6 +36,8 @@
|
||||
--
|
||||
-- # QUICK START GUIDE
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The following class is available to model an A2G defense system.
|
||||
--
|
||||
-- AI_A2G_DISPATCHER is the main A2G defense class that models the A2G defense system.
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
|
||||
--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2G_SEAD is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_SEAD process can be started using the **Start** event.
|
||||
--
|
||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
--- The AI_AIR class implements the core functions to operate an AI @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # 1) AI_AIR constructor
|
||||
--
|
||||
@ -657,8 +658,8 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
|
||||
--- Create a route point of type air.
|
||||
local FromRTBRoutePoint = FromCoord:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
RTBSpeed,
|
||||
true
|
||||
)
|
||||
@ -666,8 +667,8 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
|
||||
--- Create a route point of type air.
|
||||
local ToRTBRoutePoint = ToAirbaseCoord:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
RTBSpeed,
|
||||
true
|
||||
)
|
||||
@ -761,10 +762,10 @@ function AI_AIR:onafterRefuel( AIGroup, From, Event, To )
|
||||
local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
||||
|
||||
--- Create a route point of type air.
|
||||
local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true)
|
||||
local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToRefuelSpeed, true)
|
||||
|
||||
--- Create a route point of type air. NOT used!
|
||||
local ToRefuelRoutePoint = Tanker:GetCoordinate():WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true)
|
||||
local ToRefuelRoutePoint = Tanker:GetCoordinate():WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToRefuelSpeed, true)
|
||||
|
||||
self:F( { ToRefuelSpeed = ToRefuelSpeed } )
|
||||
|
||||
|
||||
@ -36,6 +36,8 @@
|
||||
--
|
||||
-- # QUICK START GUIDE
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The following class is available to model an AIR defense system.
|
||||
--
|
||||
-- AI_AIR_DISPATCHER is the main AIR defense class that models the AIR defense system.
|
||||
|
||||
@ -13,12 +13,14 @@
|
||||
|
||||
|
||||
|
||||
-- @type AI_AIR_ENGAGE
|
||||
--- @type AI_AIR_ENGAGE
|
||||
-- @extends AI.AI_AIR#AI_AIR
|
||||
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_AIR_ENGAGE is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_ENGAGE process can be started using the **Start** event.
|
||||
--
|
||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||
@ -453,7 +455,7 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
|
||||
|
||||
--- Calculate the target route point.
|
||||
|
||||
local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
|
||||
local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
|
||||
|
||||
EngageRoute[#EngageRoute+1] = FromWP
|
||||
|
||||
@ -462,7 +464,7 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
|
||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
|
||||
|
||||
local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
|
||||
local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
|
||||
|
||||
EngageRoute[#EngageRoute+1] = ToWP
|
||||
|
||||
@ -536,7 +538,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
|
||||
local EngageRoute = {}
|
||||
local AttackTasks = {}
|
||||
|
||||
local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
|
||||
local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
|
||||
EngageRoute[#EngageRoute+1] = FromWP
|
||||
|
||||
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
||||
@ -544,7 +546,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
|
||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
|
||||
|
||||
local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
|
||||
local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
|
||||
EngageRoute[#EngageRoute+1] = ToWP
|
||||
|
||||
-- TODO: A factor of * 3 this way too low. This causes the AI NOT to engage until very close or even merged sometimes. Some A2A missiles have a much longer range! Needs more frequent updates of the task!
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
--- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group}
|
||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_AIR_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_PATROL process can be started using the **Start** event.
|
||||
@ -309,7 +311,7 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
||||
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
||||
local speedkmh=ToTargetSpeed
|
||||
|
||||
local FromWP = CurrentCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true)
|
||||
local FromWP = CurrentCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToTargetSpeed, true)
|
||||
PatrolRoute[#PatrolRoute+1] = FromWP
|
||||
|
||||
if self.racetrack then
|
||||
@ -359,9 +361,9 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
||||
else
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToWP = ToTargetCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true)
|
||||
local ToWP = ToTargetCoord:WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToTargetSpeed, true)
|
||||
PatrolRoute[#PatrolRoute+1] = ToWP
|
||||
|
||||
|
||||
local Tasks = {}
|
||||
Tasks[#Tasks+1] = AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self)
|
||||
PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks )
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
|
||||
-- @type AI_AIR_SQUADRON
|
||||
--- @type AI_AIR_SQUADRON
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
|
||||
@ -38,6 +38,8 @@
|
||||
|
||||
--- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
|
||||
--
|
||||
-- 
|
||||
@ -174,8 +176,7 @@ function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Engage.
|
||||
@ -522,12 +523,12 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||
|
||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||
local CurrentAltitude = self.Controllable:GetAltitude()
|
||||
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local ToEngageZoneSpeed = self.PatrolMaxSpeed
|
||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
self.EngageSpeed,
|
||||
true
|
||||
)
|
||||
@ -578,13 +579,13 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||
self:T2( ToTargetVec2 )
|
||||
|
||||
--- Obtain a 3D @{Point} from the 2D point + altitude.
|
||||
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
|
||||
local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
self.EngageSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
@ -33,8 +33,9 @@
|
||||
-- @field Wrapper.Group#GROUP Test
|
||||
-- @extends Core.Fsm#FSM_SET
|
||||
|
||||
|
||||
--- Monitors and manages as many replacement AI groups as there are
|
||||
--- 
|
||||
--
|
||||
-- Monitors and manages as many replacement AI groups as there are
|
||||
-- CLIENTS in a SET\_CLIENT collection, which are not occupied by human players.
|
||||
-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.
|
||||
--
|
||||
@ -220,16 +221,9 @@ function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
|
||||
AIGroup:MessageToRed( "Returning to home base ...", 30 )
|
||||
else
|
||||
-- Okay, we need to send this Group back to the nearest base of the Coalition of the AI.
|
||||
--TODO: i need to rework the POINT_VEC2 thing.
|
||||
local PointVec2 = POINT_VEC2:New( AIGroup:GetVec2().x, AIGroup:GetVec2().y )
|
||||
local PointVec2 = COORDINATE:New(AIGroup:GetVec2().x, 0, AIGroup:GetVec2().y)
|
||||
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
|
||||
self:T( ClosestAirbase.AirbaseName )
|
||||
--[[
|
||||
AIGroup:MessageToRed( "Returning to " .. ClosestAirbase:GetName().. " ...", 30 )
|
||||
local RTBRoute = AIGroup:RouteReturnToAirbase( ClosestAirbase )
|
||||
AIGroupTemplate.route = RTBRoute
|
||||
AIGroup:Respawn( AIGroupTemplate )
|
||||
]]
|
||||
AIGroup:RouteRTB(ClosestAirbase)
|
||||
end
|
||||
|
||||
|
||||
@ -39,6 +39,8 @@
|
||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}
|
||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_CAP_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
|
||||
@ -423,12 +425,12 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
||||
|
||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||
local CurrentAltitude = self.Controllable:GetAltitude()
|
||||
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local ToEngageZoneSpeed = self.PatrolMaxSpeed
|
||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
ToEngageZoneSpeed,
|
||||
true
|
||||
)
|
||||
@ -445,13 +447,13 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
||||
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
|
||||
|
||||
--- Obtain a 3D @{Point} from the 2D point + altitude.
|
||||
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
|
||||
local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToPatrolRoutePoint = ToTargetPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
ToTargetSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
@ -38,6 +38,9 @@
|
||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||
|
||||
--- Implements the core functions to provide Close Air Support in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
|
||||
--
|
||||
-- 
|
||||
@ -466,12 +469,12 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||
|
||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||
local CurrentAltitude = self.Controllable:GetAltitude()
|
||||
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local ToEngageZoneSpeed = self.PatrolMaxSpeed
|
||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
self.EngageSpeed,
|
||||
true
|
||||
)
|
||||
@ -508,13 +511,13 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||
self:T2( ToTargetVec2 )
|
||||
|
||||
--- Obtain a 3D @{Point} from the 2D point + altitude.
|
||||
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
|
||||
local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
self.EngageSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
@ -9,12 +9,14 @@
|
||||
-- @module AI.AI_Cargo
|
||||
-- @image Cargo.JPG
|
||||
|
||||
-- @type AI_CARGO
|
||||
--- @type AI_CARGO
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
--- Base class for the dynamic cargo handling capability for AI groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
-- The AI_CARGO module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI_CARGO object recognize the cargo.
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
|
||||
--- Brings a dynamic cargo handling capability for an AI vehicle group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Armoured Personnel Carriers (APC), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
|
||||
|
||||
--- Brings a dynamic cargo handling capability for an AI airplane group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Airplane carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation between airbases.
|
||||
--
|
||||
@ -440,7 +442,7 @@ function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed, Height, Uncontrolled
|
||||
|
||||
-- To point.
|
||||
local AirbasePointVec2 = Airbase:GetPointVec2()
|
||||
local ToWaypoint = AirbasePointVec2:WaypointAir(POINT_VEC3.RoutePointAltType.BARO, "Land", "Landing", Speed or Airplane:GetSpeedMax()*0.8, true, Airbase)
|
||||
local ToWaypoint = AirbasePointVec2:WaypointAir(COORDINATE.WaypointAltType.BARO, "Land", "Landing", Speed or Airplane:GetSpeedMax()*0.8, true, Airbase)
|
||||
|
||||
--ToWaypoint["airdromeId"] = Airbase:GetID()
|
||||
--ToWaypoint["speed_locked"] = true
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # The dispatcher concept.
|
||||
--
|
||||
-- Carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
|
||||
@ -36,6 +36,8 @@
|
||||
|
||||
--- A dynamic cargo transportation capability for AI groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Armoured Personnel APCs (APC), Trucks, Jeeps and other carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_APC module is derived from the AI_CARGO_DISPATCHER module.
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
|
||||
--- Brings a dynamic cargo handling capability for AI groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Airplanes can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_AIRPLANE module is derived from the AI_CARGO_DISPATCHER module.
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
|
||||
--- A dynamic cargo handling capability for AI helicopter groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
--
|
||||
|
||||
@ -29,6 +29,8 @@
|
||||
|
||||
--- A dynamic cargo transportation capability for AI groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Naval vessels can be mobilized to semi-intelligently transport cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_SHIP module is derived from the AI_CARGO_DISPATCHER module.
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
|
||||
--- Brings a dynamic cargo handling capability for an AI helicopter group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Helicopter carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
@ -367,8 +369,8 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
|
||||
-- local CoordinateFrom = Helicopter:GetCoordinate()
|
||||
-- local WaypointFrom = CoordinateFrom:WaypointAir(
|
||||
-- "RADIO",
|
||||
-- POINT_VEC3.RoutePointType.TurningPoint,
|
||||
-- POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
-- COORDINATE.WaypointType.TurningPoint,
|
||||
-- COORDINATE.WaypointAction.TurningPoint,
|
||||
-- Speed,
|
||||
-- true
|
||||
-- )
|
||||
@ -380,8 +382,8 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
|
||||
|
||||
local WaypointTo = CoordinateTo:WaypointAir(
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
50,
|
||||
true
|
||||
)
|
||||
@ -427,7 +429,7 @@ function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordina
|
||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
|
||||
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, 50, true)
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, 50, true)
|
||||
Route[#Route+1] = WaypointTo
|
||||
|
||||
local Tasks = {}
|
||||
@ -496,14 +498,14 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin
|
||||
local CoordinateFrom = Helicopter:GetCoordinate()
|
||||
|
||||
--- Create a route point of type air.
|
||||
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true)
|
||||
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
|
||||
|
||||
--- Create a route point of type air.
|
||||
local CoordinateTo = Coordinate
|
||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
|
||||
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint,_speed, true)
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint,_speed, true)
|
||||
|
||||
Route[#Route+1] = WaypointFrom
|
||||
Route[#Route+1] = WaypointTo
|
||||
@ -563,7 +565,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
||||
|
||||
--- Create a route point of type air.
|
||||
local CoordinateFrom = Helicopter:GetCoordinate()
|
||||
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true)
|
||||
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
|
||||
Route[#Route+1] = WaypointFrom
|
||||
Route[#Route+1] = WaypointFrom
|
||||
|
||||
@ -573,7 +575,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
|
||||
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true)
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
|
||||
|
||||
Route[#Route+1] = WaypointTo
|
||||
Route[#Route+1] = WaypointTo
|
||||
@ -631,7 +633,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
||||
--- Create a route point of type air.
|
||||
local CoordinateFrom = Helicopter:GetCoordinate()
|
||||
|
||||
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, Speed, true)
|
||||
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true)
|
||||
Route[#Route+1] = WaypointFrom
|
||||
|
||||
--- Create a route point of type air.
|
||||
@ -639,7 +641,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||
CoordinateTo.y = landheight + Height -- flight height should be 50m above ground
|
||||
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, Speed, true)
|
||||
local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true)
|
||||
|
||||
Route[#Route+1] = WaypointTo
|
||||
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
|
||||
--- Brings a dynamic cargo handling capability for an AI naval group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Naval ships can be utilized to transport cargo around the map following naval shipping lanes.
|
||||
-- The AI_CARGO_SHIP class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- @{Cargo.Cargo} must be declared within the mission or warehouse to make the AI_CARGO_SHIP recognize the cargo.
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
--
|
||||
-- Allows you to interact with escorting AI on your flight and take the lead.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
|
||||
--
|
||||
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.
|
||||
|
||||
@ -23,6 +23,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
|
||||
--- Models the assignment of AI escorts to player flights upon request using the radio menu.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
--
|
||||
-- Allows you to interact with escorting AI on your flight and take the lead.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
|
||||
--
|
||||
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
|
||||
|
||||
--- Build large formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- AI_FORMATION makes AI @{Wrapper.Group#GROUP}s fly in formation of various compositions.
|
||||
-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
|
||||
@ -158,7 +160,6 @@ AI_FORMATION.__Enum.Mode = {
|
||||
-- @field #number GroundRadar
|
||||
-- @field #number Ground
|
||||
AI_FORMATION.__Enum.ReportType = {
|
||||
Airborne = "*",
|
||||
Airborne = "A",
|
||||
GroundRadar = "R",
|
||||
Ground = "G",
|
||||
@ -725,7 +726,7 @@ function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, X
|
||||
|
||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||
|
||||
local PointVec3 = POINT_VEC3:New()
|
||||
local PointVec3 = COORDINATE:New()
|
||||
PointVec3:SetX( XStart + i * XSpace )
|
||||
PointVec3:SetY( YStart + i * YSpace )
|
||||
PointVec3:SetZ( ZStart + i * ZSpace )
|
||||
@ -877,7 +878,7 @@ function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event ,
|
||||
|
||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||
|
||||
local PointVec3 = POINT_VEC3:New()
|
||||
local PointVec3 = COORDINATE:New()
|
||||
|
||||
local Side = ( i % 2 == 0 ) and 1 or -1
|
||||
local Row = i / 2 + 1
|
||||
@ -936,7 +937,7 @@ function AI_FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XS
|
||||
|
||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||
|
||||
local PointVec3 = POINT_VEC3:New()
|
||||
local PointVec3 = COORDINATE:New()
|
||||
|
||||
local ZIndex = i % ZLevels
|
||||
local XIndex = math.floor( i / ZLevels )
|
||||
@ -1222,7 +1223,6 @@ function AI_FORMATION:FollowMe(FollowGroup, ClientUnit, CT1, CV1, CT2, CV2)
|
||||
local CVI = {
|
||||
x = CV2.x + CS * 10 * math.sin(Ca),
|
||||
y = GH2.y + Inclination, -- + FollowFormation.y,
|
||||
y = GH2.y,
|
||||
z = CV2.z + CS * 10 * math.cos(Ca),
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,8 @@
|
||||
|
||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_PATROL_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
|
||||
@ -751,12 +753,12 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
|
||||
if not CurrentVec2 then return end
|
||||
--Done: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||
local CurrentAltitude = self.Controllable:GetAltitude()
|
||||
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
|
||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TakeOffParking,
|
||||
POINT_VEC3.RoutePointAction.FromParkingArea,
|
||||
COORDINATE.WaypointType.TakeOffParking,
|
||||
COORDINATE.WaypointAction.FromParkingArea,
|
||||
ToPatrolZoneSpeed,
|
||||
true
|
||||
)
|
||||
@ -767,12 +769,12 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
|
||||
if not CurrentVec2 then return end
|
||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||
local CurrentAltitude = self.Controllable:GetAltitude()
|
||||
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
|
||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
ToPatrolZoneSpeed,
|
||||
true
|
||||
)
|
||||
@ -792,13 +794,13 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
|
||||
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
|
||||
|
||||
--- Obtain a 3D @{Point} from the 2D point + altitude.
|
||||
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
|
||||
local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
ToTargetSpeed,
|
||||
true
|
||||
)
|
||||
@ -846,7 +848,6 @@ function AI_PATROL_ZONE:onafterStatus()
|
||||
OldAIControllable:SetTask( TimedOrbitTask, 10 )
|
||||
|
||||
RTB = true
|
||||
else
|
||||
end
|
||||
|
||||
-- TODO: Check GROUP damage function.
|
||||
@ -856,6 +857,16 @@ function AI_PATROL_ZONE:onafterStatus()
|
||||
RTB = true
|
||||
end
|
||||
|
||||
if self:IsInstanceOf("AI_CAS") or self:IsInstanceOf("AI_BAI") then
|
||||
local atotal,shells,rockets,bombs,missiles = self.Controllable:GetAmmunition()
|
||||
local arelevant = rockets+bombs
|
||||
if arelevant == 0 or missiles == 0 then
|
||||
RTB = true
|
||||
self:T({total=atotal,shells=shells,rockets=rockets,bombs=bombs,missiles=missiles})
|
||||
self:T( self.Controllable:GetName() .. " is out of ammo, RTB!" )
|
||||
end
|
||||
end
|
||||
|
||||
if RTB == true then
|
||||
self:RTB()
|
||||
else
|
||||
@ -881,12 +892,12 @@ function AI_PATROL_ZONE:onafterRTB()
|
||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||
--local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
|
||||
local CurrentAltitude = self.Controllable:GetAltitude()
|
||||
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
|
||||
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
|
||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
COORDINATE.WaypointType.TurningPoint,
|
||||
COORDINATE.WaypointAction.TurningPoint,
|
||||
ToPatrolZoneSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occurring on UNITs.
|
||||
--
|
||||
-- 
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@ -8,9 +8,11 @@
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
do -- ACT_ACCOUNT
|
||||
|
||||
|
||||
--- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ## ACT_ACCOUNT state machine:
|
||||
--
|
||||
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
||||
@ -133,7 +135,7 @@ do -- ACT_ACCOUNT
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function ACT_ACCOUNT:onafterEvent( ProcessUnit, From, Event, To, Event )
|
||||
function ACT_ACCOUNT:onafterEvent( ProcessUnit, From, Event, To )
|
||||
|
||||
self:__NoMore( 1 )
|
||||
end
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
--- (SP) (MP) (FSM) Accept or reject process for player (task) assignments.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
|
||||
--
|
||||
-- 
|
||||
-- ## ACT_ASSIST state machine:
|
||||
--
|
||||
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
-- ## ACT_ROUTE state machine:
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # 1) MOOSE Cargo System.
|
||||
--
|
||||
-- #### Those who have used the mission editor, know that the DCS mission editor provides cargo facilities.
|
||||
@ -275,14 +277,14 @@
|
||||
-- The cargo must be in the **Loaded** state.
|
||||
-- @function [parent=#CARGO] UnBoard
|
||||
-- @param #CARGO self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
|
||||
-- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
|
||||
|
||||
--- UnBoards the cargo to a Carrier. The event will create a movement (= running or driving) of the cargo from the Carrier.
|
||||
-- The cargo must be in the **Loaded** state.
|
||||
-- @function [parent=#CARGO] __UnBoard
|
||||
-- @param #CARGO self
|
||||
-- @param #number DelaySeconds The amount of seconds to delay the action.
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
|
||||
-- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
|
||||
|
||||
|
||||
-- Load
|
||||
@ -307,14 +309,14 @@
|
||||
-- The cargo must be in the **Loaded** state.
|
||||
-- @function [parent=#CARGO] UnLoad
|
||||
-- @param #CARGO self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
|
||||
-- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
|
||||
|
||||
--- UnLoads the cargo to a Carrier. The event will unload the cargo from the Carrier. There will be no movement simulated of the cargo loading.
|
||||
-- The cargo must be in the **Loaded** state.
|
||||
-- @function [parent=#CARGO] __UnLoad
|
||||
-- @param #CARGO self
|
||||
-- @param #number DelaySeconds The amount of seconds to delay the action.
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
|
||||
-- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
|
||||
|
||||
-- State Transition Functions
|
||||
|
||||
@ -467,7 +469,7 @@ do -- CARGO
|
||||
self.Type = Type
|
||||
self.Name = Name
|
||||
self.Weight = Weight or 0
|
||||
self.CargoObject = nil
|
||||
self.CargoObject = nil -- Wrapper.Group#GROUP
|
||||
self.CargoCarrier = nil -- Wrapper.Client#CLIENT
|
||||
self.Representable = false
|
||||
self.Slingloadable = false
|
||||
@ -897,7 +899,7 @@ do -- CARGO
|
||||
|
||||
--- Get the current PointVec2 of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @return Core.Point#POINT_VEC2
|
||||
-- @return Core.Point#COORDINATE
|
||||
function CARGO:GetPointVec2()
|
||||
return self.CargoObject:GetPointVec2()
|
||||
end
|
||||
@ -1094,7 +1096,7 @@ do -- CARGO_REPRESENTABLE
|
||||
|
||||
--- Route a cargo unit to a PointVec2.
|
||||
-- @param #CARGO_REPRESENTABLE self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param Core.Point#COORDINATE ToPointVec2
|
||||
-- @param #number Speed
|
||||
-- @return #CARGO_REPRESENTABLE
|
||||
function CARGO_REPRESENTABLE:RouteTo( ToPointVec2, Speed )
|
||||
|
||||
@ -22,6 +22,9 @@ do -- CARGO_CRATE
|
||||
-- @type CARGO_CRATE
|
||||
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
|
||||
|
||||
---
|
||||
-- 
|
||||
--
|
||||
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
|
||||
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers.
|
||||
--
|
||||
@ -114,7 +117,7 @@ do -- CARGO_CRATE
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2
|
||||
-- @param Core.Point#COORDINATE
|
||||
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
||||
--self:T( { ToPointVec2, From, Event, To } )
|
||||
|
||||
|
||||
@ -22,9 +22,12 @@ do -- CARGO_GROUP
|
||||
--- @type CARGO_GROUP
|
||||
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
|
||||
-- @field #string GroupName The name of the CargoGroup.
|
||||
-- @field Wrapper.Group#GROUÜ CargoCarrier The carrier group.
|
||||
-- @extends Cargo.Cargo#CARGO_REPORTABLE
|
||||
|
||||
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
|
||||
--
|
||||
-- 
|
||||
-- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers.
|
||||
--
|
||||
-- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo:
|
||||
@ -410,7 +413,7 @@ do -- CARGO_GROUP
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param Core.Point#COORDINATE ToPointVec2
|
||||
-- @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, ... )
|
||||
self:T( {From, Event, To, ToPointVec2, NearRadius } )
|
||||
@ -453,7 +456,7 @@ do -- CARGO_GROUP
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param Core.Point#COORDINATE ToPointVec2
|
||||
-- @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, ... )
|
||||
--self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
@ -491,7 +494,7 @@ do -- CARGO_GROUP
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param Core.Point#COORDINATE ToPointVec2
|
||||
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
|
||||
--self:T( { From, Event, To, ToPointVec2 } )
|
||||
|
||||
@ -771,3 +774,4 @@ do -- CARGO_GROUP
|
||||
|
||||
|
||||
end -- CARGO_GROUP
|
||||
|
||||
|
||||
@ -32,6 +32,8 @@ do -- CARGO_SLINGLOAD
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
|
||||
@ -30,6 +30,8 @@ do -- CARGO_UNIT
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
@ -72,7 +74,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param Core.Point#COORDINATE ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 25 m.
|
||||
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
@ -145,7 +147,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param Core.Point#COORDINATE ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
@ -171,7 +173,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param Core.Point#COORDINATE ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
@ -197,7 +199,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2
|
||||
-- @param Core.Point#COORDINATE
|
||||
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
||||
self:T( { ToPointVec2, From, Event, To } )
|
||||
|
||||
|
||||
@ -34,11 +34,12 @@ local _TraceClassMethod = {}
|
||||
|
||||
local _ClassID = 0
|
||||
|
||||
---
|
||||
--- Base class of everything
|
||||
-- @type BASE
|
||||
-- @field ClassName The name of the class.
|
||||
-- @field ClassID The ID number of the class.
|
||||
-- @field ClassNameAndID The name of the class concatenated with the ID number of the class.
|
||||
-- @field #string ClassName The name of the class.
|
||||
-- @field #number ClassID The ID number of the class.
|
||||
-- @field #string ClassNameAndID The name of the class concatenated with the ID number of the class.
|
||||
-- @field Core.Scheduler#SCHEDULER Scheduler The scheduler object.
|
||||
|
||||
--- BASE class
|
||||
--
|
||||
@ -200,6 +201,7 @@ BASE = {
|
||||
States = {},
|
||||
Debug = debug,
|
||||
Scheduler = nil,
|
||||
Properties = {},
|
||||
}
|
||||
|
||||
-- @field #BASE.__
|
||||
@ -210,14 +212,6 @@ BASE._ = {
|
||||
Schedules = {}, --- Contains the Schedulers Active
|
||||
}
|
||||
|
||||
--- The Formation Class
|
||||
-- @type FORMATION
|
||||
-- @field Cone A cone formation.
|
||||
FORMATION = {
|
||||
Cone = "Cone",
|
||||
Vee = "Vee",
|
||||
}
|
||||
|
||||
--- BASE constructor.
|
||||
--
|
||||
-- This is an example how to use the BASE:New() constructor in a new class definition when inheriting from BASE.
|
||||
@ -980,7 +974,7 @@ do -- Scheduling
|
||||
-- @param #BASE self
|
||||
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
|
||||
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
|
||||
-- @param #table ... Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
||||
-- @param ... Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
||||
-- @return #string The Schedule ID of the planned schedule.
|
||||
function BASE:ScheduleOnce( Start, SchedulerFunction, ... )
|
||||
|
||||
@ -1116,6 +1110,31 @@ function BASE:ClearState( Object, StateName )
|
||||
end
|
||||
end
|
||||
|
||||
--- Set one property of an object.
|
||||
-- @param #BASE self
|
||||
-- @param Key The key that is used as a reference of the value. Note that the key can be a #string, but it can also be any other type!
|
||||
-- @param Value The value that is stored. Note that the value can be a #string, but it can also be any other type!
|
||||
function BASE:SetProperty(Key,Value)
|
||||
self.Properties = self.Properties or {}
|
||||
self.Properties[Key] = Value
|
||||
end
|
||||
|
||||
--- Get one property of an object by the key.
|
||||
-- @param #BASE self
|
||||
-- @param Key The key that is used as a reference of the value. Note that the key can be a #string, but it can also be any other type!
|
||||
-- @return Value The value that is stored. Note that the value can be a #string, but it can also be any other type! Nil if not found.
|
||||
function BASE:GetProperty(Key)
|
||||
self.Properties = self.Properties or {}
|
||||
return self.Properties[Key]
|
||||
end
|
||||
|
||||
--- Get all of the properties of an object in a table.
|
||||
-- @param #BASE self
|
||||
-- @return #table of values, indexed by keys.
|
||||
function BASE:GetProperties()
|
||||
return self.Properties
|
||||
end
|
||||
|
||||
-- Trace section
|
||||
|
||||
-- Log a trace (only shown when trace is on)
|
||||
@ -1416,7 +1435,7 @@ function BASE:E( Arguments )
|
||||
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "E", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
||||
else
|
||||
env.info( string.format( "%1s:%30s%05d(%s)", "E", self.ClassName, self.ClassID, BASE:_Serialize(Arguments) ) )
|
||||
env.info( string.format( "%1s:%30s%05d(%s)", "E", self.ClassName, self.ClassID, UTILS.BasicSerialize(Arguments) ) )
|
||||
end
|
||||
|
||||
end
|
||||
@ -1443,8 +1462,7 @@ function BASE:I( Arguments )
|
||||
|
||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "I", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
||||
else
|
||||
env.info( string.format( "%1s:%30s%05d(%s)", "I", self.ClassName, self.ClassID, BASE:_Serialize(Arguments)) )
|
||||
env.info( string.format( "%1s:%30s%05d(%s)", "I", self.ClassName, self.ClassID, UTILS.BasicSerialize(Arguments)) )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -211,10 +211,9 @@ function DATABASE:AddStatic( DCSStaticName )
|
||||
|
||||
if not self.STATICS[DCSStaticName] then
|
||||
self.STATICS[DCSStaticName] = STATIC:Register( DCSStaticName )
|
||||
return self.STATICS[DCSStaticName]
|
||||
end
|
||||
|
||||
return nil
|
||||
return self.STATICS[DCSStaticName]
|
||||
end
|
||||
|
||||
|
||||
@ -224,12 +223,11 @@ function DATABASE:DeleteStatic( DCSStaticName )
|
||||
self.STATICS[DCSStaticName] = nil
|
||||
end
|
||||
|
||||
--- Finds a STATIC based on the StaticName.
|
||||
--- Finds a STATIC based on the Static Name.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string StaticName
|
||||
-- @param #string StaticName Name of the static object.
|
||||
-- @return Wrapper.Static#STATIC The found STATIC.
|
||||
function DATABASE:FindStatic( StaticName )
|
||||
|
||||
local StaticFound = self.STATICS[StaticName]
|
||||
return StaticFound
|
||||
end
|
||||
@ -241,9 +239,8 @@ end
|
||||
function DATABASE:AddDynamicCargo( Name )
|
||||
if not self.DYNAMICCARGO[Name] then
|
||||
self.DYNAMICCARGO[Name] = DYNAMICCARGO:Register(Name)
|
||||
return self.DYNAMICCARGO[Name]
|
||||
end
|
||||
return nil
|
||||
return self.DYNAMICCARGO[Name]
|
||||
end
|
||||
|
||||
--- Finds a DYNAMICCARGO based on the Dynamic Cargo Name.
|
||||
@ -580,13 +577,19 @@ do -- Zones and Pathlines
|
||||
-- For a rectangular polygon drawing, we have the width (y) and height (x).
|
||||
local w=objectData.width
|
||||
local h=objectData.height
|
||||
local rotation = UTILS.ToRadian(objectData.angle or 0)
|
||||
|
||||
-- Create points from center using with and height (width for y and height for x is a bit confusing, but this is how ED implemented it).
|
||||
local points={}
|
||||
points[1]={x=vec2.x-h/2, y=vec2.y+w/2} --Upper left
|
||||
points[2]={x=vec2.x+h/2, y=vec2.y+w/2} --Upper right
|
||||
points[3]={x=vec2.x+h/2, y=vec2.y-w/2} --Lower right
|
||||
points[4]={x=vec2.x-h/2, y=vec2.y-w/2} --Lower left
|
||||
local sinRot = math.sin(rotation)
|
||||
local cosRot = math.cos(rotation)
|
||||
local dx = h / 2
|
||||
local dy = w / 2
|
||||
|
||||
local points = {
|
||||
{ x = -dx * cosRot - (-dy * sinRot) + vec2.x, y = -dx * sinRot + (-dy * cosRot) + vec2.y },
|
||||
{ x = dx * cosRot - (-dy * sinRot) + vec2.x, y = dx * sinRot + (-dy * cosRot) + vec2.y },
|
||||
{ x = dx * cosRot - (dy * sinRot) + vec2.x, y = dx * sinRot + (dy * cosRot) + vec2.y },
|
||||
{ x = -dx * cosRot - (dy * sinRot) + vec2.x, y = -dx * sinRot + (dy * cosRot) + vec2.y },
|
||||
}
|
||||
|
||||
--local coord=COORDINATE:NewFromVec2(vec2):MarkToAll("MapX, MapY")
|
||||
|
||||
@ -875,6 +878,8 @@ end
|
||||
-- @return Wrapper.Group#GROUP The found GROUP.
|
||||
function DATABASE:FindGroup( GroupName )
|
||||
|
||||
if type(GroupName) ~= "string" or GroupName == "" then return end
|
||||
|
||||
local GroupFound = self.GROUPS[GroupName]
|
||||
|
||||
if GroupFound == nil and GroupName ~= nil and self.Templates.Groups[GroupName] == nil then
|
||||
@ -1113,7 +1118,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
|
||||
self:E("WARNING: Invalid STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
|
||||
else
|
||||
self.STNS[stn] = UnitTemplate.name
|
||||
self:I("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
|
||||
self:T("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
|
||||
end
|
||||
end
|
||||
if UnitTemplate.AddPropAircraft.SADL_TN then
|
||||
@ -1122,7 +1127,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
|
||||
self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
|
||||
else
|
||||
self.SADL[sadl] = UnitTemplate.name
|
||||
self:I("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
|
||||
self:T("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1383,7 +1388,7 @@ function DATABASE:GetCoalitionFromClientTemplate( ClientName )
|
||||
if self.Templates.ClientsByName[ClientName] then
|
||||
return self.Templates.ClientsByName[ClientName].CoalitionID
|
||||
end
|
||||
self:E("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||
self:T("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -1395,7 +1400,7 @@ function DATABASE:GetCategoryFromClientTemplate( ClientName )
|
||||
if self.Templates.ClientsByName[ClientName] then
|
||||
return self.Templates.ClientsByName[ClientName].CategoryID
|
||||
end
|
||||
self:E("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||
self:T("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -1407,7 +1412,7 @@ function DATABASE:GetCountryFromClientTemplate( ClientName )
|
||||
if self.Templates.ClientsByName[ClientName] then
|
||||
return self.Templates.ClientsByName[ClientName].CountryID
|
||||
end
|
||||
self:E("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||
self:T("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -1582,12 +1587,29 @@ end
|
||||
-- @param DCS#Airbase airbase Airbase.
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterAirbase(airbase)
|
||||
|
||||
|
||||
local IsSyria = UTILS.GetDCSMap() == "Syria" and true or false
|
||||
local countHSyria = 0
|
||||
|
||||
if airbase then
|
||||
|
||||
-- Get the airbase name.
|
||||
local DCSAirbaseName = airbase:getName()
|
||||
|
||||
|
||||
-- DCS 2.9.8.1107 added 143 helipads all named H with the same object ID ..
|
||||
if IsSyria and DCSAirbaseName == "H" and countHSyria > 0 then
|
||||
--[[
|
||||
local p = airbase:getPosition().p
|
||||
local mgrs = COORDINATE:New(p.x,p.z,p.y):ToStringMGRS()
|
||||
self:I("Airbase on Syria map named H @ "..mgrs)
|
||||
countHSyria = countHSyria + 1
|
||||
if countHSyria > 1 then return self end
|
||||
--]]
|
||||
return self
|
||||
elseif IsSyria and DCSAirbaseName == "H" and countHSyria == 0 then
|
||||
countHSyria = countHSyria + 1
|
||||
end
|
||||
|
||||
-- This gave the incorrect value to be inserted into the airdromeID for DCS 2.5.6. Is fixed now.
|
||||
local airbaseID=airbase:getID()
|
||||
|
||||
@ -1683,7 +1705,7 @@ function DATABASE:_EventOnBirth( Event )
|
||||
if PlayerName then
|
||||
|
||||
-- Debug info.
|
||||
self:I(string.format("Player '%s' joined unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
|
||||
self:I(string.format("Player '%s' joined unit '%s' (%s) of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniTypeName), tostring(Event.IniDCSGroupName)))
|
||||
|
||||
-- Add client in case it does not exist already.
|
||||
if client == nil or (client and client:CountPlayers() == 0) then
|
||||
|
||||
@ -1329,6 +1329,7 @@ function EVENT:onEvent( Event )
|
||||
end
|
||||
|
||||
Event.IniDCSGroupName = Event.IniUnit and Event.IniUnit.GroupName or ""
|
||||
Event.IniGroupName=Event.IniDCSGroupName --At least set the group name because group might not exist any more
|
||||
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
|
||||
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
|
||||
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
||||
@ -1371,11 +1372,12 @@ function EVENT:onEvent( Event )
|
||||
-- Scenery
|
||||
---
|
||||
Event.IniDCSUnit = Event.initiator
|
||||
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
||||
Event.IniDCSUnitName = ( Event.IniDCSUnit and Event.IniDCSUnit.getName ) and Event.IniDCSUnit:getName() or "Scenery no name "..math.random(1,20000)
|
||||
Event.IniUnitName = Event.IniDCSUnitName
|
||||
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
|
||||
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
||||
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY"
|
||||
Event.IniCategory = (Event.IniDCSUnit and Event.IniDCSUnit.getDesc ) and Event.IniDCSUnit:getDesc().category
|
||||
Event.IniTypeName = (Event.initiator and Event.initiator.isExist
|
||||
and Event.initiator:isExist() and Event.IniDCSUnit and Event.IniDCSUnit.getTypeName) and Event.IniDCSUnit:getTypeName() or "SCENERY"
|
||||
|
||||
elseif Event.IniObjectCategory == Object.Category.BASE then
|
||||
---
|
||||
@ -1473,11 +1475,13 @@ function EVENT:onEvent( Event )
|
||||
-- SCENERY
|
||||
---
|
||||
Event.TgtDCSUnit = Event.target
|
||||
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
|
||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||
Event.TgtDCSUnitName = Event.TgtDCSUnit.getName and Event.TgtDCSUnit.getName() or nil
|
||||
if Event.TgtDCSUnitName~=nil then
|
||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
|
||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1504,7 +1508,9 @@ function EVENT:onEvent( Event )
|
||||
else
|
||||
if Event.place:isExist() and Object.getCategory(Event.place) ~= Object.Category.SCENERY then
|
||||
Event.Place=AIRBASE:Find(Event.place)
|
||||
Event.PlaceName=Event.Place:GetName()
|
||||
if Event.Place then
|
||||
Event.PlaceName=Event.Place:GetName()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -50,7 +50,7 @@ MARKEROPS_BASE = {
|
||||
ClassName = "MARKEROPS",
|
||||
Tag = "mytag",
|
||||
Keywords = {},
|
||||
version = "0.1.3",
|
||||
version = "0.1.4",
|
||||
debug = false,
|
||||
Casesensitive = true,
|
||||
}
|
||||
@ -108,26 +108,30 @@ function MARKEROPS_BASE:New(Tagname,Keywords,Casesensitive)
|
||||
--- On after "MarkAdded" event. Triggered when a Marker is added to the F10 map.
|
||||
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkAdded
|
||||
-- @param #MARKEROPS_BASE self
|
||||
-- @param #string From The From state
|
||||
-- @param #string Event The Event called
|
||||
-- @param #string To The To state
|
||||
-- @param #string Text The text on the marker
|
||||
-- @param #table Keywords Table of matching keywords found in the Event text
|
||||
-- @param #string From The From state.
|
||||
-- @param #string Event The Event called.
|
||||
-- @param #string To The To state.
|
||||
-- @param #string Text The text on the marker.
|
||||
-- @param #table Keywords Table of matching keywords found in the Event text.
|
||||
-- @param Core.Point#COORDINATE Coord Coordinate of the marker.
|
||||
-- @param #number MarkerID Id of this marker
|
||||
-- @param #number CoalitionNumber Coalition of the marker creator
|
||||
-- @param #number MarkerID Id of this marker.
|
||||
-- @param #number CoalitionNumber Coalition of the marker creator.
|
||||
-- @param #string PlayerName Name of the player creating/changing the mark. nil if it cannot be obtained.
|
||||
-- @param Core.Event#EVENTDATA EventData the event data table.
|
||||
|
||||
--- On after "MarkChanged" event. Triggered when a Marker is changed on the F10 map.
|
||||
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkChanged
|
||||
-- @param #MARKEROPS_BASE self
|
||||
-- @param #string From The From state
|
||||
-- @param #string Event The Event called
|
||||
-- @param #string To The To state
|
||||
-- @param #string Text The text on the marker
|
||||
-- @param #table Keywords Table of matching keywords found in the Event text
|
||||
-- @param #string From The From state.
|
||||
-- @param #string Event The Event called.
|
||||
-- @param #string To The To state.
|
||||
-- @param #string Text The text on the marker.
|
||||
-- @param #table Keywords Table of matching keywords found in the Event text.
|
||||
-- @param Core.Point#COORDINATE Coord Coordinate of the marker.
|
||||
-- @param #number MarkerID Id of this marker
|
||||
-- @param #number CoalitionNumber Coalition of the marker creator
|
||||
-- @param #number MarkerID Id of this marker.
|
||||
-- @param #number CoalitionNumber Coalition of the marker creator.
|
||||
-- @param #string PlayerName Name of the player creating/changing the mark. nil if it cannot be obtained.
|
||||
-- @param Core.Event#EVENTDATA EventData the event data table
|
||||
|
||||
--- On after "MarkDeleted" event. Triggered when a Marker is deleted from the F10 map.
|
||||
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkDeleted
|
||||
@ -150,14 +154,7 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
||||
self:E("Skipping onEvent. Event or Event.idx unknown.")
|
||||
return true
|
||||
end
|
||||
--position
|
||||
local vec3={y=Event.pos.y, x=Event.pos.x, z=Event.pos.z}
|
||||
local coord=COORDINATE:NewFromVec3(vec3)
|
||||
if self.debug then
|
||||
local coordtext = coord:ToStringLLDDM()
|
||||
local text = tostring(Event.text)
|
||||
local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
|
||||
end
|
||||
|
||||
local coalition = Event.MarkCoalition
|
||||
-- decision
|
||||
if Event.id==world.event.S_EVENT_MARK_ADDED then
|
||||
@ -166,8 +163,14 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
||||
local Eventtext = tostring(Event.text)
|
||||
if Eventtext~=nil then
|
||||
if self:_MatchTag(Eventtext) then
|
||||
local matchtable = self:_MatchKeywords(Eventtext)
|
||||
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition)
|
||||
local coord=COORDINATE:NewFromVec3({y=Event.pos.y, x=Event.pos.x, z=Event.pos.z})
|
||||
if self.debug then
|
||||
local coordtext = coord:ToStringLLDDM()
|
||||
local text = tostring(Event.text)
|
||||
local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
|
||||
end
|
||||
local matchtable = self:_MatchKeywords(Eventtext)
|
||||
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
||||
end
|
||||
end
|
||||
elseif Event.id==world.event.S_EVENT_MARK_CHANGE then
|
||||
@ -176,8 +179,14 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
||||
local Eventtext = tostring(Event.text)
|
||||
if Eventtext~=nil then
|
||||
if self:_MatchTag(Eventtext) then
|
||||
local matchtable = self:_MatchKeywords(Eventtext)
|
||||
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition)
|
||||
local coord=COORDINATE:NewFromVec3({y=Event.pos.y, x=Event.pos.x, z=Event.pos.z})
|
||||
if self.debug then
|
||||
local coordtext = coord:ToStringLLDDM()
|
||||
local text = tostring(Event.text)
|
||||
local m = MESSAGE:New(string.format("Mark changed at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
|
||||
end
|
||||
local matchtable = self:_MatchKeywords(Eventtext)
|
||||
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
||||
end
|
||||
end
|
||||
elseif Event.id==world.event.S_EVENT_MARK_REMOVED then
|
||||
|
||||
@ -105,6 +105,7 @@ function MENU_INDEX:PrepareCoalition( CoalitionSide )
|
||||
self.Coalition[CoalitionSide] = self.Coalition[CoalitionSide] or {}
|
||||
self.Coalition[CoalitionSide].Menus = self.Coalition[CoalitionSide].Menus or {}
|
||||
end
|
||||
|
||||
---
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
function MENU_INDEX:PrepareGroup( Group )
|
||||
@ -118,9 +119,11 @@ end
|
||||
function MENU_INDEX:HasMissionMenu( Path )
|
||||
return self.MenuMission.Menus[Path]
|
||||
end
|
||||
|
||||
function MENU_INDEX:SetMissionMenu( Path, Menu )
|
||||
self.MenuMission.Menus[Path] = Menu
|
||||
end
|
||||
|
||||
function MENU_INDEX:ClearMissionMenu( Path )
|
||||
self.MenuMission.Menus[Path] = nil
|
||||
end
|
||||
@ -128,9 +131,11 @@ end
|
||||
function MENU_INDEX:HasCoalitionMenu( Coalition, Path )
|
||||
return self.Coalition[Coalition].Menus[Path]
|
||||
end
|
||||
|
||||
function MENU_INDEX:SetCoalitionMenu( Coalition, Path, Menu )
|
||||
self.Coalition[Coalition].Menus[Path] = Menu
|
||||
end
|
||||
|
||||
function MENU_INDEX:ClearCoalitionMenu( Coalition, Path )
|
||||
self.Coalition[Coalition].Menus[Path] = nil
|
||||
end
|
||||
@ -138,19 +143,24 @@ end
|
||||
function MENU_INDEX:HasGroupMenu( Group, Path )
|
||||
if Group and Group:IsAlive() then
|
||||
local MenuGroupName = Group:GetName()
|
||||
return self.Group[MenuGroupName].Menus[Path]
|
||||
if self.Group[MenuGroupName] and self.Group[MenuGroupName].Menus and self.Group[MenuGroupName].Menus[Path] then
|
||||
return self.Group[MenuGroupName].Menus[Path]
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function MENU_INDEX:SetGroupMenu( Group, Path, Menu )
|
||||
local MenuGroupName = Group:GetName()
|
||||
Group:F({MenuGroupName=MenuGroupName,Path=Path})
|
||||
--Group:F({MenuGroupName=MenuGroupName,Path=Path})
|
||||
self.Group[MenuGroupName].Menus[Path] = Menu
|
||||
end
|
||||
|
||||
function MENU_INDEX:ClearGroupMenu( Group, Path )
|
||||
local MenuGroupName = Group:GetName()
|
||||
self.Group[MenuGroupName].Menus[Path] = nil
|
||||
end
|
||||
|
||||
function MENU_INDEX:Refresh( Group )
|
||||
for MenuID, Menu in pairs( self.MenuMission.Menus ) do
|
||||
Menu:Refresh()
|
||||
|
||||
@ -75,35 +75,37 @@ MESSAGE.Type = {
|
||||
|
||||
--- Creates a new MESSAGE object. Note that these MESSAGE objects are not yet displayed on the display panel. You must use the functions @{#MESSAGE.ToClient} or @{#MESSAGE.ToCoalition} or @{#MESSAGE.ToAll} to send these Messages to the respective recipients.
|
||||
-- @param self
|
||||
-- @param #string MessageText is the text of the Message.
|
||||
-- @param #number MessageDuration is a number in seconds of how long the MESSAGE should be shown on the display panel.
|
||||
-- @param #string MessageCategory (optional) is a string expressing the "category" of the Message. The category will be shown as the first text in the message followed by a ": ".
|
||||
-- @param #string Text is the text of the Message.
|
||||
-- @param #number Duration Duration in seconds how long the message text is shown.
|
||||
-- @param #string Category (Optional) String expressing the "category" of the Message. The category will be shown as the first text in the message followed by a ": ".
|
||||
-- @param #boolean ClearScreen (optional) Clear all previous messages if true.
|
||||
-- @return #MESSAGE
|
||||
-- @return #MESSAGE self
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a series of new Messages.
|
||||
-- -- MessageAll is meant to be sent to all players, for 25 seconds, and is classified as "Score".
|
||||
-- -- MessageRED is meant to be sent to the RED players only, for 10 seconds, and is classified as "End of Mission", with ID "Win".
|
||||
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
||||
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
||||
-- -- Create a series of new Messages.
|
||||
-- -- MessageAll is meant to be sent to all players, for 25 seconds, and is classified as "Score".
|
||||
-- -- MessageRED is meant to be sent to the RED players only, for 10 seconds, and is classified as "End of Mission", with ID "Win".
|
||||
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
||||
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
||||
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", 25, "End of Mission" )
|
||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty" )
|
||||
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" )
|
||||
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score")
|
||||
--
|
||||
function MESSAGE:New( MessageText, MessageDuration, MessageCategory, ClearScreen )
|
||||
function MESSAGE:New( Text, Duration, Category, ClearScreen )
|
||||
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( { MessageText, MessageDuration, MessageCategory } )
|
||||
|
||||
self:F( { Text, Duration, Category } )
|
||||
|
||||
self.MessageType = nil
|
||||
|
||||
-- When no MessageCategory is given, we don't show it as a title...
|
||||
if MessageCategory and MessageCategory ~= "" then
|
||||
if MessageCategory:sub( -1 ) ~= "\n" then
|
||||
self.MessageCategory = MessageCategory .. ": "
|
||||
if Category and Category ~= "" then
|
||||
if Category:sub( -1 ) ~= "\n" then
|
||||
self.MessageCategory = Category .. ": "
|
||||
else
|
||||
self.MessageCategory = MessageCategory:sub( 1, -2 ) .. ":\n"
|
||||
self.MessageCategory = Category:sub( 1, -2 ) .. ":\n"
|
||||
end
|
||||
else
|
||||
self.MessageCategory = ""
|
||||
@ -114,9 +116,9 @@ function MESSAGE:New( MessageText, MessageDuration, MessageCategory, ClearScreen
|
||||
self.ClearScreen = ClearScreen
|
||||
end
|
||||
|
||||
self.MessageDuration = MessageDuration or 5
|
||||
self.MessageDuration = Duration or 5
|
||||
self.MessageTime = timer.getTime()
|
||||
self.MessageText = MessageText:gsub( "^\n", "", 1 ):gsub( "\n$", "", 1 )
|
||||
self.MessageText = Text:gsub( "^\n", "", 1 ):gsub( "\n$", "", 1 )
|
||||
|
||||
self.MessageSent = false
|
||||
self.MessageGroup = false
|
||||
@ -204,7 +206,7 @@ end
|
||||
function MESSAGE:ToGroup( Group, Settings )
|
||||
self:F( Group.GroupName )
|
||||
|
||||
if Group then
|
||||
if Group and Group:IsAlive() then
|
||||
|
||||
if self.MessageType then
|
||||
local Settings = Settings or (Group and _DATABASE:GetPlayerSettings( Group:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS
|
||||
@ -229,7 +231,7 @@ end
|
||||
function MESSAGE:ToUnit( Unit, Settings )
|
||||
self:F( Unit.IdentifiableName )
|
||||
|
||||
if Unit then
|
||||
if Unit and Unit:IsAlive() then
|
||||
|
||||
if self.MessageType then
|
||||
local Settings = Settings or ( Unit and _DATABASE:GetPlayerSettings( Unit:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
|
||||
@ -450,7 +452,7 @@ end
|
||||
_MESSAGESRS = {}
|
||||
|
||||
--- 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 (optional) Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone" or your configuration file setting.
|
||||
-- @param #string PathToSRS (optional) Path to SRS TTS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone\\ExternalAudio" or your configuration file setting.
|
||||
-- @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 Google.
|
||||
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
|
||||
@ -462,16 +464,17 @@ _MESSAGESRS = {}
|
||||
-- @param #number Volume (optional) Volume, can be between 0.0 and 1.0 (loudest).
|
||||
-- @param #string Label (optional) Label, defaults to "MESSAGE" or the Message Category set.
|
||||
-- @param Core.Point#COORDINATE Coordinate (optional) Coordinate this messages originates from.
|
||||
-- @param #string Backend (optional) Backend to be used, can be MSRS.Backend.SRSEXE or MSRS.Backend.GRPC
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||
--
|
||||
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
|
||||
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate,Backend)
|
||||
|
||||
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
|
||||
|
||||
_MESSAGESRS.frequency = Frequency or MSRS.frequencies or 243
|
||||
_MESSAGESRS.modulation = Modulation or MSRS.modulations or radio.modulation.AM
|
||||
@ -487,6 +490,10 @@ function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,G
|
||||
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
||||
end
|
||||
|
||||
if Backend then
|
||||
_MESSAGESRS.MSRS:SetBackend(Backend)
|
||||
end
|
||||
|
||||
_MESSAGESRS.Culture = Culture or MSRS.culture or "en-GB"
|
||||
_MESSAGESRS.MSRS:SetCulture(Culture)
|
||||
|
||||
@ -528,7 +535,7 @@ end
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||
--
|
||||
@ -560,7 +567,7 @@ end
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSBlue()
|
||||
--
|
||||
@ -582,7 +589,7 @@ end
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.RED)
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.RED)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSRed()
|
||||
--
|
||||
@ -604,7 +611,7 @@ end
|
||||
-- @usage
|
||||
-- -- Mind the dot here, not using the colon this time around!
|
||||
-- -- Needed once only
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.NEUTRAL)
|
||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.NEUTRAL)
|
||||
-- -- later on in your code
|
||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSAll()
|
||||
--
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -175,7 +175,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
||||
local Name = Info.name or "?"
|
||||
|
||||
local ErrorHandler = function( errmsg )
|
||||
env.info( "Error in timer function: " .. errmsg )
|
||||
env.info( "Error in timer function: " .. errmsg or "" )
|
||||
if BASE.Debug ~= nil then
|
||||
env.info( BASE.Debug.traceback() )
|
||||
end
|
||||
@ -326,7 +326,7 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
|
||||
local Schedule = self.Schedule[Scheduler][CallID] -- #SCHEDULEDISPATCHER.ScheduleData
|
||||
|
||||
-- Only stop when there is a ScheduleID defined for the CallID. So, when the scheduler was stopped before, do nothing.
|
||||
if Schedule.ScheduleID then
|
||||
if Schedule and Schedule.ScheduleID then
|
||||
|
||||
self:T( string.format( "SCHEDULEDISPATCHER stopping scheduler CallID=%s, ScheduleID=%s", tostring( CallID ), tostring( Schedule.ScheduleID ) ) )
|
||||
|
||||
|
||||
@ -289,7 +289,14 @@ do -- SET_BASE
|
||||
|
||||
-- Debug info.
|
||||
--self:T2( { ObjectName = ObjectName, Object = Object } )
|
||||
|
||||
|
||||
-- Error ahndling
|
||||
if not ObjectName or ObjectName == "" then
|
||||
self:E("SET_BASE:Add - Invalid ObjectName handed")
|
||||
self:E({ObjectName=ObjectName, Object=Object})
|
||||
return self
|
||||
end
|
||||
|
||||
-- Ensure that the existing element is removed from the Set before a new one is inserted to the Set
|
||||
if self.Set[ObjectName] then
|
||||
self:Remove( ObjectName, true )
|
||||
@ -524,6 +531,21 @@ do -- SET_BASE
|
||||
|
||||
return self.SomeIteratorLimit or self:Count()
|
||||
end
|
||||
|
||||
--- Get max threat level of all objects in the SET.
|
||||
-- @param #SET_BASE self
|
||||
-- @return #number Max threat level found.
|
||||
function SET_BASE:GetThreatLevelMax()
|
||||
local ThreatMax = 0
|
||||
for _,_unit in pairs(self.Set or {}) do
|
||||
local unit = _unit -- Wrapper.Unit#UNIT
|
||||
local threat = unit.GetThreatLevel and unit:GetThreatLevel() or 0
|
||||
if threat > ThreatMax then
|
||||
ThreatMax = threat
|
||||
end
|
||||
end
|
||||
return ThreatMax
|
||||
end
|
||||
|
||||
--- Filters for the defined collection.
|
||||
-- @param #SET_BASE self
|
||||
@ -607,14 +629,14 @@ do -- SET_BASE
|
||||
return self
|
||||
end
|
||||
|
||||
--- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#POINT_VEC2}.
|
||||
--- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#COORDINATE}.
|
||||
-- @param #SET_BASE self
|
||||
-- @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.
|
||||
-- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object (but **not** a simple DCS#Vec2!) from where to evaluate the closest object in the set.
|
||||
-- @return Core.Base#BASE The closest object.
|
||||
-- @usage
|
||||
-- myset:FindNearestObjectFromPointVec2( ZONE:New("Test Zone"):GetCoordinate() )
|
||||
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
|
||||
--self:F2( PointVec2 )
|
||||
function SET_BASE:FindNearestObjectFromPointVec2( Coordinate )
|
||||
--self:F2( Coordinate )
|
||||
|
||||
local NearestObject = nil
|
||||
local ClosestDistance = nil
|
||||
@ -622,9 +644,9 @@ do -- SET_BASE
|
||||
for ObjectID, ObjectData in pairs( self.Set ) do
|
||||
if NearestObject == nil then
|
||||
NearestObject = ObjectData
|
||||
ClosestDistance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() )
|
||||
ClosestDistance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
|
||||
else
|
||||
local Distance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() )
|
||||
local Distance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
|
||||
if Distance < ClosestDistance then
|
||||
NearestObject = ObjectData
|
||||
ClosestDistance = Distance
|
||||
@ -936,7 +958,26 @@ do -- SET_BASE
|
||||
|
||||
return ObjectNames
|
||||
end
|
||||
|
||||
--- Get a *new* set table that only contains alive objects.
|
||||
-- @param #SET_BASE self
|
||||
-- @return #table Set table of alive objects.
|
||||
function SET_BASE:GetAliveSet()
|
||||
--self:F2()
|
||||
|
||||
local AliveSet = {}
|
||||
-- Clean the Set before returning with only the alive Objects.
|
||||
for ObjectName, Object in pairs( self.Set ) do
|
||||
if Object then
|
||||
if Object:IsAlive() then
|
||||
AliveSet[#AliveSet+1] = Object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return AliveSet or {}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
@ -1103,25 +1144,25 @@ do
|
||||
|
||||
end
|
||||
|
||||
--- Get a *new* set that only contains alive groups.
|
||||
--- Get a *new* set table that only contains alive groups.
|
||||
-- @param #SET_GROUP self
|
||||
-- @return #SET_GROUP Set of alive groups.
|
||||
-- @return #table Set of alive groups.
|
||||
function SET_GROUP:GetAliveSet()
|
||||
--self:F2()
|
||||
|
||||
local AliveSet = SET_GROUP:New()
|
||||
|
||||
--local AliveSet = SET_GROUP:New()
|
||||
local AliveSet = {}
|
||||
-- Clean the Set before returning with only the alive Groups.
|
||||
for GroupName, GroupObject in pairs( self.Set ) do
|
||||
local GroupObject = GroupObject -- Wrapper.Group#GROUP
|
||||
if GroupObject then
|
||||
if GroupObject:IsAlive() then
|
||||
AliveSet:Add( GroupName, GroupObject )
|
||||
AliveSet[GroupName] = GroupObject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return AliveSet.Set or {}
|
||||
return AliveSet or {}
|
||||
end
|
||||
|
||||
--- Returns a report of of unit types.
|
||||
@ -1220,12 +1261,12 @@ do
|
||||
return GroupFound
|
||||
end
|
||||
|
||||
--- Iterate the SET_GROUP while identifying the nearest object from a @{Core.Point#POINT_VEC2}.
|
||||
--- Iterate the SET_GROUP while identifying the nearest object from a @{Core.Point#COORDINATE}.
|
||||
-- @param #SET_GROUP 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#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest object in the set.
|
||||
-- @return Wrapper.Group#GROUP The closest group.
|
||||
function SET_GROUP:FindNearestGroupFromPointVec2( PointVec2 )
|
||||
--self:F2( PointVec2 )
|
||||
function SET_GROUP:FindNearestGroupFromPointVec2( Coordinate )
|
||||
--self:F2( Coordinate )
|
||||
|
||||
local NearestGroup = nil -- Wrapper.Group#GROUP
|
||||
local ClosestDistance = nil
|
||||
@ -1235,9 +1276,9 @@ do
|
||||
for ObjectID, ObjectData in pairs( Set ) do
|
||||
if NearestGroup == nil then
|
||||
NearestGroup = ObjectData
|
||||
ClosestDistance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() )
|
||||
ClosestDistance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
|
||||
else
|
||||
local Distance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() )
|
||||
local Distance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
|
||||
if Distance < ClosestDistance then
|
||||
NearestGroup = ObjectData
|
||||
ClosestDistance = Distance
|
||||
@ -1538,6 +1579,13 @@ do
|
||||
local size = 1
|
||||
if Event.IniDCSGroup then
|
||||
size = Event.IniDCSGroup:getSize()
|
||||
elseif Event.IniDCSGroupName then
|
||||
local grp = Group.getByName(Event.IniDCSGroupName)
|
||||
if grp then
|
||||
size = grp:getSize()
|
||||
end
|
||||
elseif Object:IsAlive() then
|
||||
size = Object:CountAliveUnits()
|
||||
end
|
||||
if size == 1 then -- Only remove if the last unit of the group was destroyed.
|
||||
self:Remove( ObjectName )
|
||||
@ -1709,7 +1757,7 @@ do
|
||||
|
||||
--- Iterate the SET_GROUP and return true if all the @{Wrapper.Group#GROUP} are completely in the @{Core.Zone#ZONE}
|
||||
-- @param #SET_GROUP self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #boolean true if all the @{Wrapper.Group#GROUP} are completely in the @{Core.Zone#ZONE}, false otherwise
|
||||
-- @usage
|
||||
-- local MyZone = ZONE:New("Zone1")
|
||||
@ -1756,7 +1804,7 @@ do
|
||||
|
||||
--- Iterate the SET_GROUP and return true if at least one of the @{Wrapper.Group#GROUP} is completely inside the @{Core.Zone#ZONE}
|
||||
-- @param #SET_GROUP self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is completely inside the @{Core.Zone#ZONE}, false otherwise.
|
||||
-- @usage
|
||||
-- local MyZone = ZONE:New("Zone1")
|
||||
@ -1781,7 +1829,7 @@ do
|
||||
|
||||
--- Iterate the SET_GROUP and return true if at least one @{#UNIT} of one @{Wrapper.Group#GROUP} of the @{#SET_GROUP} is in @{Core.Zone}
|
||||
-- @param #SET_GROUP self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completely inside the @{Core.Zone#ZONE}, false otherwise.
|
||||
-- @usage
|
||||
-- local MyZone = ZONE:New("Zone1")
|
||||
@ -1807,7 +1855,7 @@ do
|
||||
--- Iterate the SET_GROUP and return true if at least one @{Wrapper.Group#GROUP} of the @{#SET_GROUP} is partly in @{Core.Zone}.
|
||||
-- Will return false if a @{Wrapper.Group#GROUP} is fully in the @{Core.Zone}
|
||||
-- @param #SET_GROUP self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completely inside the @{Core.Zone#ZONE}, false otherwise.
|
||||
-- @usage
|
||||
-- local MyZone = ZONE:New("Zone1")
|
||||
@ -1842,7 +1890,7 @@ do
|
||||
-- This could also be achieved with `not SET_GROUP:AnyPartlyInZone(Zone)`, but it's easier for the
|
||||
-- mission designer to add a dedicated method
|
||||
-- @param #SET_GROUP self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #boolean true if no @{Wrapper.Group#GROUP} is inside the @{Core.Zone#ZONE} in any way, false otherwise.
|
||||
-- @usage
|
||||
-- local MyZone = ZONE:New("Zone1")
|
||||
@ -1869,7 +1917,7 @@ do
|
||||
-- That could easily be done with SET_GROUP:ForEachGroupCompletelyInZone(), but this function
|
||||
-- provides an easy to use shortcut...
|
||||
-- @param #SET_GROUP self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #number the number of GROUPs completely in the Zone
|
||||
-- @usage
|
||||
-- local MyZone = ZONE:New("Zone1")
|
||||
@ -1891,7 +1939,7 @@ do
|
||||
|
||||
--- Iterate the SET_GROUP and count how many UNITs are completely in the Zone
|
||||
-- @param #SET_GROUP self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #number the number of GROUPs completely in the Zone
|
||||
-- @usage
|
||||
-- local MyZone = ZONE:New("Zone1")
|
||||
@ -2490,6 +2538,35 @@ do -- SET_UNIT
|
||||
)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Builds a set of units which belong to groups with certain **group names**.
|
||||
-- @param #SET_UNIT self
|
||||
-- @param #string Prefixes The (partial) group names to look for. Can be a single string or a table of strings.
|
||||
-- @return #SET_UNIT self
|
||||
function SET_UNIT:FilterGroupPrefixes(Prefixes)
|
||||
if type(Prefixes) == "string" then
|
||||
Prefixes = {Prefixes}
|
||||
end
|
||||
self:FilterFunction(
|
||||
function(unit,prefixes)
|
||||
local outcome = false
|
||||
if unit then
|
||||
local grp = unit:GetGroup()
|
||||
local gname = grp ~= nil and grp:GetName() or "none"
|
||||
for _,_fix in pairs(prefixes or {}) do
|
||||
if string.find(gname,_fix) then
|
||||
outcome = true
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
return outcome
|
||||
end, Prefixes
|
||||
)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Builds a set of units having a radar of give types.
|
||||
-- All the units having a radar of a given type will be included within the set.
|
||||
@ -2537,18 +2614,16 @@ do -- SET_UNIT
|
||||
|
||||
--- Gets the alive set.
|
||||
-- @param #SET_UNIT self
|
||||
-- @return #table Table of SET objects
|
||||
-- @return #table Table of alive UNIT 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
|
||||
|
||||
for GroupName, GroupObject in pairs(self.Set) do
|
||||
if GroupObject and GroupObject:IsAlive() then
|
||||
AliveSet:Add(GroupName, GroupObject)
|
||||
AliveSet[GroupName] = GroupObject
|
||||
end
|
||||
end
|
||||
|
||||
@ -2706,7 +2781,7 @@ do -- SET_UNIT
|
||||
|
||||
--- Check if no element of the SET_UNIT is in the Zone.
|
||||
-- @param #SET_UNIT self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #boolean
|
||||
function SET_UNIT:IsNotInZone( Zone )
|
||||
|
||||
@ -3746,7 +3821,7 @@ do -- SET_STATIC
|
||||
|
||||
--- Check if no element of the SET_STATIC is in the Zone.
|
||||
-- @param #SET_STATIC self
|
||||
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
||||
-- @param Core.Zone#ZONE Zone The Zone to be tested for.
|
||||
-- @return #boolean
|
||||
function SET_STATIC:IsNotInZone( Zone )
|
||||
|
||||
@ -4405,6 +4480,35 @@ do -- SET_CLIENT
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Builds a set of clients which belong to groups with certain **group names**.
|
||||
-- @param #SET_CLIENT self
|
||||
-- @param #string Prefixes The (partial) group names to look for. Can be anywhere in the group name. Can be a single string or a table of strings.
|
||||
-- @return #SET_CLIENT self
|
||||
function SET_CLIENT:FilterGroupPrefixes(Prefixes)
|
||||
if type(Prefixes) == "string" then
|
||||
Prefixes = {Prefixes}
|
||||
end
|
||||
self:FilterFunction(
|
||||
function(unit,prefixes)
|
||||
local outcome = false
|
||||
if unit then
|
||||
local grp = unit:GetGroup()
|
||||
local gname = grp ~= nil and grp:GetName() or "none"
|
||||
for _,_fix in pairs(prefixes or {}) do
|
||||
if string.find(gname,_fix) then
|
||||
outcome = true
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
return outcome
|
||||
end, Prefixes
|
||||
)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Builds a set of clients that are only active.
|
||||
-- Only the clients that are active will be included within the set.
|
||||
@ -4582,6 +4686,16 @@ do -- SET_CLIENT
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Make the SET handle CA slots **only** (GROUND units used by any player). Needs active filtering with `FilterStart()`
|
||||
-- @param #SET_CLIENT self
|
||||
-- @return #SET_CLIENT self
|
||||
function SET_CLIENT:HandleCASlots()
|
||||
self:HandleEvent(EVENTS.PlayerEnterUnit,SET_CLIENT._EventPlayerEnterUnit)
|
||||
self:HandleEvent(EVENTS.PlayerLeaveUnit,SET_CLIENT._EventPlayerLeaveUnit)
|
||||
self:FilterFunction(function(client) if client and client:IsAlive() and client:IsGround() then return true else return false end end)
|
||||
return self
|
||||
end
|
||||
|
||||
--- 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!
|
||||
@ -4687,18 +4801,16 @@ do -- SET_CLIENT
|
||||
-- @return #table Table of SET objects
|
||||
function SET_CLIENT:GetAliveSet()
|
||||
|
||||
local AliveSet = SET_CLIENT:New()
|
||||
local AliveSet = {}
|
||||
|
||||
-- Clean the Set before returning with only the alive Groups.
|
||||
for GroupName, GroupObject in pairs(self.Set) do
|
||||
local GroupObject=GroupObject --Wrapper.Client#CLIENT
|
||||
|
||||
for GroupName, GroupObject in pairs(self.Set) do
|
||||
if GroupObject and GroupObject:IsAlive() then
|
||||
AliveSet:Add(GroupName, GroupObject)
|
||||
AliveSet[GroupName] = GroupObject
|
||||
end
|
||||
end
|
||||
|
||||
return AliveSet.Set or {}
|
||||
return AliveSet or {}
|
||||
end
|
||||
|
||||
--- [User] Add a custom condition function.
|
||||
@ -5364,6 +5476,7 @@ do -- SET_AIRBASE
|
||||
Airbases = {},
|
||||
Filter = {
|
||||
Coalitions = nil,
|
||||
Zones = nil,
|
||||
},
|
||||
FilterMeta = {
|
||||
Coalitions = {
|
||||
@ -5515,6 +5628,31 @@ do -- SET_AIRBASE
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Builds a set of airbase objects in zones.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param #table Zones Table of Core.Zone#ZONE Zone objects, or a Core.Set#SET_ZONE
|
||||
-- @return #SET_AIRBASE self
|
||||
function SET_AIRBASE:FilterZones( Zones )
|
||||
if not self.Filter.Zones then
|
||||
self.Filter.Zones = {}
|
||||
end
|
||||
local zones = {}
|
||||
if Zones.ClassName and Zones.ClassName == "SET_ZONE" then
|
||||
zones = Zones.Set
|
||||
elseif type( Zones ) ~= "table" or (type( Zones ) == "table" and Zones.ClassName ) then
|
||||
self:E("***** FilterZones needs either a table of ZONE Objects or a SET_ZONE as parameter!")
|
||||
return self
|
||||
else
|
||||
zones = Zones
|
||||
end
|
||||
for _,Zone in pairs( zones ) do
|
||||
local zonename = Zone:GetName()
|
||||
--self:T((zonename)
|
||||
self.Filter.Zones[zonename] = Zone
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Starts the filtering.
|
||||
-- @param #SET_AIRBASE self
|
||||
@ -5605,14 +5743,14 @@ do -- SET_AIRBASE
|
||||
return self
|
||||
end
|
||||
|
||||
--- Iterate the SET_AIRBASE while identifying the nearest @{Wrapper.Airbase#AIRBASE} from a @{Core.Point#POINT_VEC2}.
|
||||
--- Iterate the SET_AIRBASE while identifying the nearest @{Wrapper.Airbase#AIRBASE} from a @{Core.Point#COORDINATE}.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest @{Wrapper.Airbase#AIRBASE}.
|
||||
-- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest @{Wrapper.Airbase#AIRBASE}.
|
||||
-- @return Wrapper.Airbase#AIRBASE The closest @{Wrapper.Airbase#AIRBASE}.
|
||||
function SET_AIRBASE:FindNearestAirbaseFromPointVec2( PointVec2 )
|
||||
--self:F2( PointVec2 )
|
||||
function SET_AIRBASE:FindNearestAirbaseFromPointVec2( Coordinate )
|
||||
--self:F2( Coordinate )
|
||||
|
||||
local NearestAirbase = self:FindNearestObjectFromPointVec2( PointVec2 )
|
||||
local NearestAirbase = self:FindNearestObjectFromPointVec2( Coordinate )
|
||||
return NearestAirbase
|
||||
end
|
||||
|
||||
@ -5653,6 +5791,20 @@ do -- SET_AIRBASE
|
||||
--self:T(( { "Evaluated Category", MAirbaseCategory } )
|
||||
MAirbaseInclude = MAirbaseInclude and MAirbaseCategory
|
||||
end
|
||||
|
||||
if self.Filter.Zones and MAirbaseInclude then
|
||||
local MAirbaseZone = false
|
||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||
--self:T(( "Zone:", ZoneName )
|
||||
local coord = MAirbase:GetCoordinate()
|
||||
if coord and Zone:IsCoordinateInZone(coord) then
|
||||
MAirbaseZone = true
|
||||
end
|
||||
--self:T(( { "Evaluated Zone", MSceneryZone } )
|
||||
end
|
||||
MAirbaseInclude = MAirbaseInclude and MAirbaseZone
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if self.Filter.Functions and MAirbaseInclude then
|
||||
@ -5928,17 +6080,19 @@ do -- SET_CARGO
|
||||
return self
|
||||
end
|
||||
|
||||
--- (R2.1) Iterate the SET_CARGO while identifying the nearest @{Cargo.Cargo#CARGO} from a @{Core.Point#POINT_VEC2}.
|
||||
--- (R2.1) Iterate the SET_CARGO while identifying the nearest @{Cargo.Cargo#CARGO} from a @{Core.Point#COORDINATE}.
|
||||
-- @param #SET_CARGO self
|
||||
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest @{Cargo.Cargo#CARGO}.
|
||||
-- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest @{Cargo.Cargo#CARGO}.
|
||||
-- @return Cargo.Cargo#CARGO The closest @{Cargo.Cargo#CARGO}.
|
||||
function SET_CARGO:FindNearestCargoFromPointVec2( PointVec2 ) -- R2.1
|
||||
--self:F2( PointVec2 )
|
||||
function SET_CARGO:FindNearestCargoFromPointVec2( Coordinate ) -- R2.1
|
||||
--self:F2( Coordinate )
|
||||
|
||||
local NearestCargo = self:FindNearestObjectFromPointVec2( PointVec2 )
|
||||
local NearestCargo = self:FindNearestObjectFromPointVec2( Coordinate )
|
||||
return NearestCargo
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- @param #SET_CARGO self
|
||||
function SET_CARGO:FirstCargoWithState( State )
|
||||
|
||||
local FirstCargo = nil
|
||||
@ -5953,6 +6107,8 @@ do -- SET_CARGO
|
||||
return FirstCargo
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #SET_CARGO self
|
||||
function SET_CARGO:FirstCargoWithStateAndNotDeployed( State )
|
||||
|
||||
local FirstCargo = nil
|
||||
@ -6535,6 +6691,8 @@ do -- SET_ZONE
|
||||
--
|
||||
-- -- Stop watching after 1 hour
|
||||
-- zoneset:__TriggerStop(3600)
|
||||
-- -- Call :SetPartlyInside() on any zone (or SET_ZONE) if you want GROUPs to count as inside when any of their units enters even if they are far apart.
|
||||
-- -- Make sure to call :SetPartlyInside() before :Trigger()!.
|
||||
function SET_ZONE:Trigger(Objects)
|
||||
--self:I("Added Set_Zone Trigger")
|
||||
self:AddTransition("*","TriggerStart","TriggerRunning")
|
||||
@ -6585,6 +6743,20 @@ do -- SET_ZONE
|
||||
-- @param Core.Zone#ZONE_BASE Zone The zone left.
|
||||
end
|
||||
|
||||
--- Toggle “partly-inside” handling for every zone in the set when those zones are used with :Trigger().
|
||||
-- * Call with no argument or **true** → enable for all.
|
||||
-- * Call with **false** → disable again (handy if it was enabled before).
|
||||
-- @param #SET_ZONE self
|
||||
-- @return #SET_ZONE self
|
||||
function SET_ZONE:SetPartlyInside(state)
|
||||
for _,Zone in pairs(self.Set) do
|
||||
if Zone.SetPartlyInside then
|
||||
Zone:SetPartlyInside(state)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- (Internal) Check the assigned objects for being in/out of the zone
|
||||
-- @param #SET_ZONE self
|
||||
-- @param #boolean fromstart If true, do the init of the objects
|
||||
@ -6620,8 +6792,13 @@ do -- SET_ZONE
|
||||
-- has not been tagged previously - wasn't in set!
|
||||
obj.TriggerInZone[_zone.ZoneName] = false
|
||||
end
|
||||
-- is obj in zone?
|
||||
local inzone = _zone:IsCoordinateInZone(obj:GetCoordinate())
|
||||
-- is obj in this zone?
|
||||
local inzone
|
||||
if _zone.PartlyInside and obj.ClassName == "GROUP" then
|
||||
inzone = obj:IsAnyInZone(_zone) -- TRUE as soon as any unit is inside
|
||||
else
|
||||
inzone = _zone:IsCoordinateInZone(obj:GetCoordinate()) -- original centroid test
|
||||
end
|
||||
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
|
||||
if inzone and not obj.TriggerInZone[_zone.ZoneName] then
|
||||
-- wasn't in zone before
|
||||
@ -7688,6 +7865,28 @@ do -- SET_OPSGROUP
|
||||
return self
|
||||
end
|
||||
|
||||
--- Iterate the SET_OPSGROUP and count how many GROUPs and UNITs are alive.
|
||||
-- @param #SET_GROUP self
|
||||
-- @return #number The number of GROUPs alive.
|
||||
-- @return #number The number of UNITs alive.
|
||||
function SET_OPSGROUP:CountAlive()
|
||||
local CountG = 0
|
||||
local CountU = 0
|
||||
|
||||
local Set = self:GetSet()
|
||||
|
||||
for GroupID, GroupData in pairs( Set ) do -- For each GROUP in SET_GROUP
|
||||
if GroupData and GroupData:IsAlive() then
|
||||
CountG = CountG + 1
|
||||
-- Count Units.
|
||||
CountU = CountU + GroupData:GetGroup():CountAliveUnits()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return CountG, CountU
|
||||
end
|
||||
|
||||
--- Finds an OPSGROUP based on the group name.
|
||||
-- @param #SET_OPSGROUP self
|
||||
-- @param #string GroupName Name of the group.
|
||||
@ -7936,22 +8135,31 @@ do -- SET_OPSGROUP
|
||||
--- Handles the OnBirth event for the Set.
|
||||
-- @param #SET_OPSGROUP self
|
||||
-- @param Core.Event#EVENTDATA Event Event data.
|
||||
function SET_OPSGROUP:_EventOnBirth( Event )
|
||||
function SET_OPSGROUP:_EventOnBirth(Event)
|
||||
--self:F3( { Event } )
|
||||
|
||||
if Event.IniDCSUnit and Event.IniDCSGroup then
|
||||
local DCSgroup=Event.IniDCSGroup --DCS#Group
|
||||
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
|
||||
-- group:CountAliveUnits() alternative as this fails for Respawn/Teleport
|
||||
local CountAliveActive = 0
|
||||
for index, data in pairs(DCSgroup:getUnits()) do
|
||||
if data:isExist() and data:isActive() then
|
||||
CountAliveActive = CountAliveActive + 1
|
||||
end
|
||||
end
|
||||
|
||||
if DCSgroup:getInitialSize() == DCSgroup:getSize() then
|
||||
|
||||
local groupname, group = self:AddInDatabase(Event)
|
||||
|
||||
-- group:CountAliveUnits() alternative
|
||||
if group and CountAliveActive == DCSgroup:getInitialSize() then
|
||||
if group and self:IsIncludeObject(group) then
|
||||
self:Add(groupname, group)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -7962,7 +8170,7 @@ do -- SET_OPSGROUP
|
||||
function SET_OPSGROUP:_EventOnDeadOrCrash( Event )
|
||||
--self:F( { Event } )
|
||||
|
||||
if Event.IniDCSUnit then
|
||||
if Event.IniDCSGroup then
|
||||
local ObjectName, Object = self:FindInDatabase( Event )
|
||||
if ObjectName then
|
||||
if Event.IniDCSGroup:getSize() == 1 then -- Only remove if the last unit of the group was destroyed.
|
||||
@ -8355,14 +8563,17 @@ do -- SET_SCENERY
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return Core.Point#COORDINATE The center coordinate of all the objects in the set.
|
||||
function SET_SCENERY:GetCoordinate()
|
||||
|
||||
--[[
|
||||
local Coordinate = COORDINATE:New({0,0,0})
|
||||
|
||||
|
||||
local Item = self:GetRandomSurely()
|
||||
|
||||
if Item then
|
||||
Coordinate:GetCoordinate()
|
||||
end
|
||||
--]]
|
||||
|
||||
local Coordinate = self:GetFirst():GetCoordinate()
|
||||
|
||||
local x1 = Coordinate.x
|
||||
local x2 = Coordinate.x
|
||||
@ -8602,7 +8813,6 @@ do -- SET_DYNAMICCARGO
|
||||
-- @field #SET_DYNAMICCARGO SET_DYNAMICCARGO
|
||||
SET_DYNAMICCARGO = {
|
||||
ClassName = "SET_DYNAMICCARGO",
|
||||
Filter = {},
|
||||
Set = {},
|
||||
List = {},
|
||||
Index = {},
|
||||
|
||||
@ -494,7 +494,7 @@ do -- SETTINGS
|
||||
return (self.A2ASystem and self.A2ASystem == "MGRS") or (not self.A2ASystem and _SETTINGS:IsA2A_MGRS())
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
-- @param Wrapper.Group#GROUP MenuGroup Group for which to add menus.
|
||||
-- @param #table RootMenu Root menu table
|
||||
-- @return #SETTINGS
|
||||
@ -948,49 +948,49 @@ do -- SETTINGS
|
||||
return self
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:A2GMenuSystem( MenuGroup, RootMenu, A2GSystem )
|
||||
self.A2GSystem = A2GSystem
|
||||
MESSAGE:New( string.format( "Settings: Default A2G coordinate system set to %s for all players!", A2GSystem ), 5 ):ToAll()
|
||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:A2AMenuSystem( MenuGroup, RootMenu, A2ASystem )
|
||||
self.A2ASystem = A2ASystem
|
||||
MESSAGE:New( string.format( "Settings: Default A2A coordinate system set to %s for all players!", A2ASystem ), 5 ):ToAll()
|
||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuLL_DDM_Accuracy( MenuGroup, RootMenu, LL_Accuracy )
|
||||
self.LL_Accuracy = LL_Accuracy
|
||||
MESSAGE:New( string.format( "Settings: Default LL accuracy set to %s for all players!", LL_Accuracy ), 5 ):ToAll()
|
||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuMGRS_Accuracy( MenuGroup, RootMenu, MGRS_Accuracy )
|
||||
self.MGRS_Accuracy = MGRS_Accuracy
|
||||
MESSAGE:New( string.format( "Settings: Default MGRS accuracy set to %s for all players!", MGRS_Accuracy ), 5 ):ToAll()
|
||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuMWSystem( MenuGroup, RootMenu, MW )
|
||||
self.Metric = MW
|
||||
MESSAGE:New( string.format( "Settings: Default measurement format set to %s for all players!", MW and "Metric" or "Imperial" ), 5 ):ToAll()
|
||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuMessageTimingsSystem( MenuGroup, RootMenu, MessageType, MessageTime )
|
||||
self:SetMessageTime( MessageType, MessageTime )
|
||||
MESSAGE:New( string.format( "Settings: Default message time set for %s to %d.", MessageType, MessageTime ), 5 ):ToAll()
|
||||
end
|
||||
|
||||
do
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuGroupA2GSystem( PlayerUnit, PlayerGroup, PlayerName, A2GSystem )
|
||||
--BASE:E( {PlayerUnit:GetName(), A2GSystem } )
|
||||
self.A2GSystem = A2GSystem
|
||||
@ -1001,7 +1001,7 @@ do -- SETTINGS
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuGroupA2ASystem( PlayerUnit, PlayerGroup, PlayerName, A2ASystem )
|
||||
self.A2ASystem = A2ASystem
|
||||
MESSAGE:New( string.format( "Settings: A2A format set to %s for player %s.", A2ASystem, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||
@ -1011,7 +1011,7 @@ do -- SETTINGS
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuGroupLL_DDM_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, LL_Accuracy )
|
||||
self.LL_Accuracy = LL_Accuracy
|
||||
MESSAGE:New( string.format( "Settings: LL format accuracy set to %d decimal places for player %s.", LL_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||
@ -1021,7 +1021,7 @@ do -- SETTINGS
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuGroupMGRS_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, MGRS_Accuracy )
|
||||
self.MGRS_Accuracy = MGRS_Accuracy
|
||||
MESSAGE:New( string.format( "Settings: MGRS format accuracy set to %d for player %s.", MGRS_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||
@ -1031,7 +1031,7 @@ do -- SETTINGS
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuGroupMWSystem( PlayerUnit, PlayerGroup, PlayerName, MW )
|
||||
self.Metric = MW
|
||||
MESSAGE:New( string.format( "Settings: Measurement format set to %s for player %s.", MW and "Metric" or "Imperial", PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||
@ -1041,7 +1041,7 @@ do -- SETTINGS
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #SETTINGS self
|
||||
--- @param #SETTINGS self
|
||||
function SETTINGS:MenuGroupMessageTimingsSystem( PlayerUnit, PlayerGroup, PlayerName, MessageType, MessageTime )
|
||||
self:SetMessageTime( MessageType, MessageTime )
|
||||
MESSAGE:New( string.format( "Settings: Default message time set for %s to %d.", MessageType, MessageTime ), 5 ):ToGroup( PlayerGroup )
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -105,7 +105,7 @@
|
||||
--
|
||||
-- * @{#SPAWNSTATIC.Spawn}(Heading, NewName) spawns the static with the set parameters. Optionally, heading and name can be given. The name **must be unique**!
|
||||
-- * @{#SPAWNSTATIC.SpawnFromCoordinate}(Coordinate, Heading, NewName) spawn the static at the given coordinate. Optionally, heading and name can be given. The name **must be unique**!
|
||||
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a POINT_VEC2 coordinate. Optionally, heading and name can be given. The name **must be unique**!
|
||||
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a COORDINATE coordinate. Optionally, heading and name can be given. The name **must be unique**!
|
||||
-- * @{#SPAWNSTATIC.SpawnFromZone}(Zone, Heading, NewName) spawns the static at the center of a @{Core.Zone}. Optionally, heading and name can be given. The name **must be unique**!
|
||||
--
|
||||
-- @field #SPAWNSTATIC SPAWNSTATIC
|
||||
@ -149,6 +149,7 @@ function SPAWNSTATIC:NewFromStatic(SpawnTemplateName, SpawnCountryID)
|
||||
self.CategoryID = CategoryID
|
||||
self.CoalitionID = CoalitionID
|
||||
self.SpawnIndex = 0
|
||||
self.StaticCopyFrom = SpawnTemplateName
|
||||
else
|
||||
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. tostring(SpawnTemplateName) .. "'" )
|
||||
end
|
||||
@ -302,12 +303,16 @@ end
|
||||
-- @param #number CallsignID Callsign ID. Default 1 (="London").
|
||||
-- @param #number Frequency Frequency in MHz. Default 127.5 MHz.
|
||||
-- @param #number Modulation Modulation 0=AM, 1=FM.
|
||||
-- @param #boolean DynamicSpawns If true, allow Dynamic Spawns
|
||||
-- @param #boolean DynamicHotStarts If true, and DynamicSpawns is true, then allow Dynamic Spawns with hot starts.
|
||||
-- @return #SPAWNSTATIC self
|
||||
function SPAWNSTATIC:InitFARP(CallsignID, Frequency, Modulation)
|
||||
function SPAWNSTATIC:InitFARP(CallsignID, Frequency, Modulation, DynamicSpawns,DynamicHotStarts)
|
||||
self.InitFarp=true
|
||||
self.InitFarpCallsignID=CallsignID or 1
|
||||
self.InitFarpFreq=Frequency or 127.5
|
||||
self.InitFarpModu=Modulation or 0
|
||||
self.InitFarpDynamicSpawns = DynamicSpawns
|
||||
self.InitFarpDynamicHotStarts = (DynamicSpawns == true and DynamicHotStarts == true) and true or nil
|
||||
return self
|
||||
end
|
||||
|
||||
@ -373,6 +378,20 @@ function SPAWNSTATIC:InitLinkToUnit(Unit, OffsetX, OffsetY, OffsetAngle)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Uses Disposition and other fallback logic to find a better and valid ground spawn position.
|
||||
--- NOTE: This is not a spawn randomizer.
|
||||
--- It will try to a find clear ground location avoiding trees, water, roads, runways, map scenery, other statics and other units in the area.
|
||||
--- Uses the initial position if it's a valid location.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param #boolean OnOff Enable/disable the feature.
|
||||
-- @param #number MaxRadius (Optional) Max radius to search for a valid ground location in meters. Default is 10 times the max radius of the static.
|
||||
-- @return #SPAWNSTATIC self
|
||||
function SPAWNSTATIC:InitValidateAndRepositionStatic(OnOff, MaxRadius)
|
||||
self.ValidateAndRepositionStatic = OnOff
|
||||
self.ValidateAndRepositionStaticMaxRadius = MaxRadius
|
||||
return self
|
||||
end
|
||||
|
||||
--- Allows to place a CallFunction hook when a new static spawns.
|
||||
-- The provided method will be called when a new group is spawned, including its given parameters.
|
||||
-- The first parameter of the SpawnFunction is the @{Wrapper.Static#STATIC} that was spawned.
|
||||
@ -411,9 +430,9 @@ function SPAWNSTATIC:Spawn(Heading, NewName)
|
||||
|
||||
end
|
||||
|
||||
--- Creates a new @{Wrapper.Static} from a POINT_VEC2.
|
||||
--- Creates a new @{Wrapper.Static} from a COORDINATE.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
|
||||
-- @param Core.Point#COORDINATE PointVec2 The 2D coordinate where to spawn the static.
|
||||
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
||||
-- @param #string NewName (Optional) The name of the new static.
|
||||
-- @return Wrapper.Static#STATIC The static spawned.
|
||||
@ -459,8 +478,9 @@ end
|
||||
function SPAWNSTATIC:SpawnFromZone(Zone, Heading, NewName)
|
||||
|
||||
-- Spawn the new static at the center of the zone.
|
||||
local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
|
||||
|
||||
--local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
|
||||
local Static = self:SpawnFromCoordinate(Zone:GetCoordinate(), Heading, NewName)
|
||||
|
||||
return Static
|
||||
end
|
||||
|
||||
@ -535,15 +555,17 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
||||
-- Name of the spawned static.
|
||||
Template.name = self.InitStaticName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex)
|
||||
|
||||
-- Add and register the new static.
|
||||
local mystatic=_DATABASE:AddStatic(Template.name)
|
||||
|
||||
-- Debug output.
|
||||
self:T(Template)
|
||||
|
||||
-- Add static to the game.
|
||||
local Static=nil --DCS#StaticObject
|
||||
|
||||
if self.ValidateAndRepositionStatic then
|
||||
local validPos = UTILS.ValidateAndRepositionStatic(CountryID, Template.category, Template.type, Template, Template.shape_name, self.ValidateAndRepositionStaticMaxRadius)
|
||||
if validPos then
|
||||
Template.x = validPos.x
|
||||
Template.y = validPos.y
|
||||
end
|
||||
end
|
||||
|
||||
if self.InitFarp then
|
||||
|
||||
local TemplateGroup={}
|
||||
@ -555,6 +577,13 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
||||
TemplateGroup.x=Template.x
|
||||
TemplateGroup.y=Template.y
|
||||
TemplateGroup.name=Template.name
|
||||
|
||||
if self.InitFarpDynamicSpawns == true then
|
||||
TemplateGroup.units[1].dynamicSpawn = true
|
||||
if self.InitFarpDynamicHotStarts == true then
|
||||
TemplateGroup.units[1].allowHotStart = true
|
||||
end
|
||||
end
|
||||
|
||||
self:T("Spawning FARP")
|
||||
self:T({Template=Template})
|
||||
@ -562,7 +591,8 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
||||
|
||||
-- ED's dirty way to spawn FARPS.
|
||||
Static=coalition.addGroup(CountryID, -1, TemplateGroup)
|
||||
|
||||
--Static=coalition.addStaticObject(CountryID, Template)
|
||||
|
||||
-- Currently DCS 2.8 does not trigger birth events if FARPS are spawned!
|
||||
-- We create such an event. The airbase is registered in Core.Event
|
||||
local Event = {
|
||||
@ -577,13 +607,41 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
||||
self:T("Spawning Static")
|
||||
self:T2({Template=Template})
|
||||
Static=coalition.addStaticObject(CountryID, Template)
|
||||
|
||||
if Static then
|
||||
self:T(string.format("Succesfully spawned static object \"%s\" ID=%d", Static:getName(), Static:getID()))
|
||||
--[[
|
||||
local static=StaticObject.getByName(Static:getName())
|
||||
if static then
|
||||
env.info(string.format("FF got static from StaticObject.getByName"))
|
||||
else
|
||||
env.error(string.format("FF error did NOT get static from StaticObject.getByName"))
|
||||
end ]]
|
||||
else
|
||||
self:E(string.format("ERROR: DCS static object \"%s\" is nil!", tostring(Template.name)))
|
||||
end
|
||||
end
|
||||
|
||||
-- Add and register the new static.
|
||||
local mystatic=_DATABASE:AddStatic(Template.name)
|
||||
|
||||
-- If there is a SpawnFunction hook defined, call it.
|
||||
if self.SpawnFunctionHook then
|
||||
-- delay calling this for .3 seconds so that it hopefully comes after the BIRTH event of the group.
|
||||
self:ScheduleOnce(0.3,self.SpawnFunctionHook,mystatic, unpack(self.SpawnFunctionArguments))
|
||||
self:ScheduleOnce(0.3, self.SpawnFunctionHook, mystatic, unpack(self.SpawnFunctionArguments))
|
||||
end
|
||||
|
||||
if self.StaticCopyFrom ~= nil then
|
||||
mystatic.StaticCopyFrom = self.StaticCopyFrom
|
||||
end
|
||||
|
||||
local TemplateGroup={}
|
||||
TemplateGroup.units={}
|
||||
TemplateGroup.units[1]=Template
|
||||
TemplateGroup.x=Template.x
|
||||
TemplateGroup.y=Template.y
|
||||
TemplateGroup.name=Template.name
|
||||
_DATABASE:_RegisterStaticTemplate( TemplateGroup, self.CoalitionID, self.CategoryID, CountryID )
|
||||
|
||||
return mystatic
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,8 @@
|
||||
-- @module Core.Zone_Detection
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
--- @type ZONE_DETECTION
|
||||
---
|
||||
-- @type ZONE_DETECTION
|
||||
-- @field DCS#Vec2 Vec2 The current location of the zone.
|
||||
-- @field DCS#Distance Radius The radius of the zone.
|
||||
-- @extends #ZONE_BASE
|
||||
@ -106,7 +107,7 @@ function ZONE_DETECTION:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset )
|
||||
local Radial = ( Angle + AngleOffset ) * RadialBase / 360
|
||||
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
||||
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
|
||||
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Smoke( SmokeColor )
|
||||
COORDINATE:New( Point.x, AddHeight, Point.y):Smoke( SmokeColor )
|
||||
end
|
||||
|
||||
return self
|
||||
@ -137,7 +138,7 @@ function ZONE_DETECTION:FlareZone( FlareColor, Points, Azimuth, AddHeight )
|
||||
local Radial = Angle * RadialBase / 360
|
||||
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
||||
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
|
||||
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Flare( FlareColor, Azimuth )
|
||||
COORDINATE:New( Point.x, AddHeight, Point.y ):Flare( FlareColor, Azimuth )
|
||||
end
|
||||
|
||||
return self
|
||||
@ -201,4 +202,3 @@ function ZONE_DETECTION:IsVec3InZone( Vec3 )
|
||||
|
||||
return InZone
|
||||
end
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ do -- world
|
||||
-- @field #world.event event [https://wiki.hoggitworld.com/view/DCS_enum_world](https://wiki.hoggitworld.com/view/DCS_enum_world)
|
||||
-- @field #world.BirthPlace BirthPlace The birthplace enumerator is used to define where an aircraft or helicopter has spawned in association with birth events.
|
||||
-- @field #world.VolumeType VolumeType The volumeType enumerator defines the types of 3d geometery used within the [world.searchObjects](https://wiki.hoggitworld.com/view/DCS_func_searchObjects) function.
|
||||
-- @field #world.weather weather Weather functions for fog etc.
|
||||
|
||||
--- The world singleton contains functions centered around two different but extremely useful functions.
|
||||
-- * Events and event handlers are all governed within world.
|
||||
@ -132,6 +133,36 @@ do -- world
|
||||
-- @function [parent=#world] getAirbases
|
||||
-- @param #number coalitionId The coalition side number ID. Default is all airbases are returned.
|
||||
-- @return #table Table of DCS airbase objects.
|
||||
|
||||
|
||||
--- Weather functions.
|
||||
-- @type world.weather
|
||||
|
||||
--- Fog animation data structure.
|
||||
-- @type world.FogAnimation
|
||||
-- @field #number time
|
||||
-- @field #number visibility
|
||||
-- @field #number thickness
|
||||
|
||||
--- Returns the current fog thickness.
|
||||
-- @function [parent=#world.weather] getFogThickness Returns the fog thickness.
|
||||
-- @return #number Fog thickness in meters. If there is no fog, zero is returned.
|
||||
|
||||
--- Sets the fog thickness instantly. Any current fog animation is discarded.
|
||||
-- @function [parent=#world.weather] setFogThickness
|
||||
-- @param #number thickness Fog thickness in meters. Set to zero to disable fog.
|
||||
|
||||
--- Returns the current fog visibility distance.
|
||||
-- @function [parent=#world.weather] getFogVisibilityDistance Returns the current maximum visibility distance in meters. Returns zero if fog is not present.
|
||||
|
||||
--- Instantly sets the maximum visibility distance of fog at sea level when looking at the horizon. Any current fog animation is discarded. Set zero to disable the fog.
|
||||
-- @function [parent=#world.weather] setFogVisibilityDistance
|
||||
-- @param #number visibility Max fog visibility in meters. Set to zero to disable fog.
|
||||
|
||||
--- Sets fog animation keys. Time is set in seconds and relative to the current simulation time, where time=0 is the current moment.
|
||||
-- Time must be increasing. Previous animation is always discarded despite the data being correct.
|
||||
-- @function [parent=#world.weather] setFogAnimation
|
||||
-- @param #world.FogAnimation animation List of fog animations
|
||||
|
||||
end -- world
|
||||
|
||||
@ -167,7 +198,7 @@ end -- env
|
||||
|
||||
do -- radio
|
||||
|
||||
---@type radio
|
||||
--@type radio
|
||||
-- @field #radio.modulation modulation
|
||||
|
||||
---
|
||||
@ -407,7 +438,7 @@ do -- coalition
|
||||
-- @param #table groupData Group data table.
|
||||
-- @return DCS#Group The spawned Group object.
|
||||
|
||||
--- Dynamically spawns a static object. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_addGroup)
|
||||
--- Dynamically spawns a static object. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_addStaticObject)
|
||||
-- @function [parent=#coalition] addStaticObject
|
||||
-- @param #number countryId Id of the country.
|
||||
-- @param #table groupData Group data table.
|
||||
@ -420,6 +451,7 @@ end -- coalition
|
||||
|
||||
do -- Types
|
||||
|
||||
--- Descriptors.
|
||||
-- @type Desc
|
||||
-- @field #number speedMax0 Max speed in meters/second at zero altitude.
|
||||
-- @field #number massEmpty Empty mass in kg.
|
||||
@ -598,9 +630,13 @@ do -- Object
|
||||
--- @function [parent=#Object] destroy
|
||||
-- @param #Object self
|
||||
|
||||
--- @function [parent=#Object] getCategory
|
||||
--- Returns an enumerator of the category for the specific object.
|
||||
-- The enumerator returned is dependent on the category of the object and how the function is called.
|
||||
-- As of DCS 2.9.2 when this function is called on an Object, Unit, Weapon, or Airbase a 2nd value will be returned which details the object sub-category value.
|
||||
-- @function [parent=#Object] getCategory
|
||||
-- @param #Object self
|
||||
-- @return #Object.Category
|
||||
-- @return #Object.Category The object category (1=UNIT, 2=WEAPON, 3=STATIC, 4=BASE, 5=SCENERY, 6=Cargo)
|
||||
-- @return #number The subcategory of the passed object, e.g. Unit.Category if a unit object was passed.
|
||||
|
||||
--- Returns type name of the Object.
|
||||
-- @function [parent=#Object] getTypeName
|
||||
@ -1013,14 +1049,16 @@ do -- Spot
|
||||
end -- Spot
|
||||
|
||||
do -- Controller
|
||||
|
||||
--- Controller is an object that performs A.I.-tasks. Other words controller is an instance of A.I.. Controller stores current main task, active enroute tasks and behavior options. Controller performs commands. Please, read DCS A-10C GUI Manual EN.pdf chapter "Task Planning for Unit Groups", page 91 to understand A.I. system of DCS:A-10C.
|
||||
--
|
||||
-- This class has 2 types of functions:
|
||||
--
|
||||
-- * Tasks
|
||||
-- * Commands: Commands are instant actions those required zero time to perform. Commands may be used both for control unit/group behavior and control game mechanics.
|
||||
-- * Commands: Commands are instant actions those required zero time to perform. Commands may be used both for control unit/group behavior and control game mechanics.
|
||||
--
|
||||
-- @type Controller
|
||||
-- @field #Controller.Detection Detection Enum contains identifiers of surface types.
|
||||
-- @field #Controller.Detection Detection Enum contains identifiers of surface types.
|
||||
|
||||
--- Enables and disables the controller.
|
||||
-- Note: Now it works only for ground / naval groups!
|
||||
@ -1079,18 +1117,18 @@ do -- Controller
|
||||
|
||||
-- Detection
|
||||
|
||||
--- Enum contains identifiers of surface types.
|
||||
--- Enum containing detection types.
|
||||
-- @type Controller.Detection
|
||||
-- @field VISUAL
|
||||
-- @field OPTIC
|
||||
-- @field RADAR
|
||||
-- @field IRST
|
||||
-- @field RWR
|
||||
-- @field DLINK
|
||||
-- @field #number VISUAL Visual detection. Numeric value 1.
|
||||
-- @field #number OPTIC Optical detection. Numeric value 2.
|
||||
-- @field #number RADAR Radar detection. Numeric value 4.
|
||||
-- @field #number IRST Infra-red search and track detection. Numeric value 8.
|
||||
-- @field #number RWR Radar Warning Receiver detection. Numeric value 16.
|
||||
-- @field #number DLINK Data link detection. Numeric value 32.
|
||||
|
||||
--- Detected target.
|
||||
-- @type DetectedTarget
|
||||
-- @field Wrapper.Object#Object object The target
|
||||
-- @type Controller.DetectedTarget
|
||||
-- @field DCS#Object object The target
|
||||
-- @field #boolean visible The target is visible
|
||||
-- @field #boolean type The target type is known
|
||||
-- @field #boolean distance Distance to the target is known
|
||||
@ -1103,9 +1141,9 @@ do -- Controller
|
||||
-- @param #Controller.Detection detection Controller.Detection detection1, Controller.Detection detection2, ... Controller.Detection detectionN
|
||||
-- @return #boolean detected True if the target is detected.
|
||||
-- @return #boolean visible Has effect only if detected is true. True if the target is visible now.
|
||||
-- @return #boolean type Has effect only if detected is true. True if the target type is known.
|
||||
-- @return #boolean distance Has effect only if detected is true. True if the distance to the target is known.
|
||||
-- @return #ModelTime lastTime Has effect only if visible is false. Last time when target was seen.
|
||||
-- @return #boolean type Has effect only if detected is true. True if the target type is known.
|
||||
-- @return #boolean distance Has effect only if detected is true. True if the distance to the target is known.
|
||||
-- @return #Vec3 lastPos Has effect only if visible is false. Last position of the target when it was seen.
|
||||
-- @return #Vec3 lastVel Has effect only if visible is false. Last velocity of the target when it was seen.
|
||||
|
||||
@ -1131,6 +1169,7 @@ end -- Controller
|
||||
|
||||
do -- Unit
|
||||
|
||||
--- Unit.
|
||||
-- @type Unit
|
||||
-- @extends #CoalitionObject
|
||||
-- @field ID Identifier of an unit. It assigned to an unit by the Mission Editor automatically.
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
-- ### Author: FlightControl - Framework Design & Programming
|
||||
-- ### Refactoring to use the Runway auto-detection: Applevangelist
|
||||
-- @date August 2022
|
||||
-- Last Update Nov 2023
|
||||
-- Last Update Feb 2025
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@ -416,7 +416,7 @@ end
|
||||
-- @field #ATC_GROUND_UNIVERSAL
|
||||
ATC_GROUND_UNIVERSAL = {
|
||||
ClassName = "ATC_GROUND_UNIVERSAL",
|
||||
Version = "0.0.1",
|
||||
Version = "0.0.2",
|
||||
SetClient = nil,
|
||||
Airbases = nil,
|
||||
AirbaseList = nil,
|
||||
@ -441,17 +441,25 @@ function ATC_GROUND_UNIVERSAL:New(AirbaseList)
|
||||
self:T( { self.ClassName } )
|
||||
|
||||
self.Airbases = {}
|
||||
|
||||
for _name,_ in pairs(_DATABASE.AIRBASES) do
|
||||
self.Airbases[_name]={}
|
||||
end
|
||||
|
||||
self.AirbaseList = AirbaseList
|
||||
|
||||
if not self.AirbaseList then
|
||||
self.AirbaseList = {}
|
||||
for _name,_ in pairs(_DATABASE.AIRBASES) do
|
||||
self.AirbaseList[_name]=_name
|
||||
for _name,_base in pairs(_DATABASE.AIRBASES) do
|
||||
-- DONE exclude FARPS and Ships
|
||||
if _base and _base.isAirdrome == true then
|
||||
self.AirbaseList[_name]=_name
|
||||
self.Airbases[_name]={}
|
||||
end
|
||||
end
|
||||
else
|
||||
for _,_name in pairs(AirbaseList) do
|
||||
-- DONE exclude FARPS and Ships
|
||||
local airbase = _DATABASE:FindAirbase(_name)
|
||||
if airbase and (airbase.isAirdrome == true) then
|
||||
self.Airbases[_name]={}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -721,14 +729,18 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
||||
|
||||
if NotInRunwayZone then
|
||||
|
||||
local Taxi = Client:GetState( self, "Taxi" )
|
||||
|
||||
if IsOnGround then
|
||||
local Taxi = Client:GetState( self, "Taxi" )
|
||||
|
||||
self:T( Taxi )
|
||||
if Taxi == false then
|
||||
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
|
||||
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
|
||||
Velocity:ToString() , 20, "ATC" )
|
||||
Client:SetState( self, "Taxi", true )
|
||||
Client:SetState( self, "Speeding", false )
|
||||
Client:SetState( self, "Warnings", 0 )
|
||||
end
|
||||
|
||||
-- TODO: GetVelocityKMH function usage
|
||||
@ -737,7 +749,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
||||
local IsAboveRunway = Client:IsAboveRunway()
|
||||
self:T( {IsAboveRunway, IsOnGround, Velocity:Get() })
|
||||
|
||||
if IsOnGround then
|
||||
if IsOnGround and not Taxi then
|
||||
local Speeding = false
|
||||
if AirbaseMeta.MaximumKickSpeed then
|
||||
if Velocity:Get() > AirbaseMeta.MaximumKickSpeed then
|
||||
@ -749,15 +761,17 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
||||
end
|
||||
end
|
||||
if Speeding == true then
|
||||
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() ..
|
||||
" has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
||||
Client:Destroy()
|
||||
Client:SetState( self, "Speeding", false )
|
||||
Client:SetState( self, "Warnings", 0 )
|
||||
--MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() ..
|
||||
-- " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
||||
--Client:Destroy()
|
||||
Client:SetState( self, "Speeding", true )
|
||||
local SpeedingWarnings = Client:GetState( self, "Warnings" )
|
||||
Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
|
||||
Client:Message( "Warning " .. SpeedingWarnings .. "/3! Airbase traffic rule violation! Slow down now! Your speed is " ..
|
||||
Velocity:ToString(), 5, "ATC" )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if IsOnGround then
|
||||
|
||||
local Speeding = false
|
||||
@ -1035,23 +1049,23 @@ end
|
||||
-- The following airbases are monitored at the Nevada region.
|
||||
-- Use the @{Wrapper.Airbase#AIRBASE.Nevada} enumeration to select the airbases to be monitored.
|
||||
--
|
||||
-- * `AIRBASE.Nevada.Beatty_Airport`
|
||||
-- * `AIRBASE.Nevada.Boulder_City_Airport`
|
||||
-- * `AIRBASE.Nevada.Creech_AFB`
|
||||
-- * `AIRBASE.Nevada.Beatty`
|
||||
-- * `AIRBASE.Nevada.Boulder_City`
|
||||
-- * `AIRBASE.Nevada.Creech`
|
||||
-- * `AIRBASE.Nevada.Echo_Bay`
|
||||
-- * `AIRBASE.Nevada.Groom_Lake_AFB`
|
||||
-- * `AIRBASE.Nevada.Henderson_Executive_Airport`
|
||||
-- * `AIRBASE.Nevada.Jean_Airport`
|
||||
-- * `AIRBASE.Nevada.Laughlin_Airport`
|
||||
-- * `AIRBASE.Nevada.Groom_Lake`
|
||||
-- * `AIRBASE.Nevada.Henderson_Executive`
|
||||
-- * `AIRBASE.Nevada.Jean`
|
||||
-- * `AIRBASE.Nevada.Laughlin`
|
||||
-- * `AIRBASE.Nevada.Lincoln_County`
|
||||
-- * `AIRBASE.Nevada.McCarran_International_Airport`
|
||||
-- * `AIRBASE.Nevada.McCarran_International`
|
||||
-- * `AIRBASE.Nevada.Mesquite`
|
||||
-- * `AIRBASE.Nevada.Mina_Airport`
|
||||
-- * `AIRBASE.Nevada.Nellis_AFB`
|
||||
-- * `AIRBASE.Nevada.Mina`
|
||||
-- * `AIRBASE.Nevada.Nellis`
|
||||
-- * `AIRBASE.Nevada.North_Las_Vegas`
|
||||
-- * `AIRBASE.Nevada.Pahute_Mesa_Airstrip`
|
||||
-- * `AIRBASE.Nevada.Tonopah_Airport`
|
||||
-- * `AIRBASE.Nevada.Tonopah_Test_Range_Airfield`
|
||||
-- * `AIRBASE.Nevada.Pahute_Mesa`
|
||||
-- * `AIRBASE.Nevada.Tonopah`
|
||||
-- * `AIRBASE.Nevada.Tonopah_Test_Range`
|
||||
--
|
||||
-- # Installation
|
||||
--
|
||||
@ -1088,10 +1102,10 @@ end
|
||||
--
|
||||
-- -- Monitor specific airbases.
|
||||
-- ATC_Ground = ATC_GROUND_NEVADA:New(
|
||||
-- { AIRBASE.Nevada.Laughlin_Airport,
|
||||
-- { AIRBASE.Nevada.Laughlin,
|
||||
-- AIRBASE.Nevada.Lincoln_County,
|
||||
-- AIRBASE.Nevada.North_Las_Vegas,
|
||||
-- AIRBASE.Nevada.McCarran_International_Airport
|
||||
-- AIRBASE.Nevada.McCarran_International
|
||||
-- }
|
||||
-- )
|
||||
--
|
||||
@ -1330,33 +1344,33 @@ end
|
||||
-- The following airbases are monitored at the PersianGulf region.
|
||||
-- Use the @{Wrapper.Airbase#AIRBASE.PersianGulf} enumeration to select the airbases to be monitored.
|
||||
--
|
||||
-- * `AIRBASE.PersianGulf.Abu_Musa_Island_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Al_Dhafra_AB`
|
||||
-- * `AIRBASE.PersianGulf.Abu_Musa_Island`
|
||||
-- * `AIRBASE.PersianGulf.Al_Dhafra_AFB`
|
||||
-- * `AIRBASE.PersianGulf.Al_Maktoum_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Al_Minhad_AB`
|
||||
-- * `AIRBASE.PersianGulf.Al_Minhad_AFB`
|
||||
-- * `AIRBASE.PersianGulf.Bandar_Abbas_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Bandar_Lengeh`
|
||||
-- * `AIRBASE.PersianGulf.Dubai_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Fujairah_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Havadarya`
|
||||
-- * `AIRBASE.PersianGulf.Kerman_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Kerman`
|
||||
-- * `AIRBASE.PersianGulf.Khasab`
|
||||
-- * `AIRBASE.PersianGulf.Lar_Airbase`
|
||||
-- * `AIRBASE.PersianGulf.Lar`
|
||||
-- * `AIRBASE.PersianGulf.Qeshm_Island`
|
||||
-- * `AIRBASE.PersianGulf.Sharjah_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Shiraz_International_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Shiraz_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Sir_Abu_Nuayr`
|
||||
-- * `AIRBASE.PersianGulf.Sirri_Island`
|
||||
-- * `AIRBASE.PersianGulf.Tunb_Island_AFB`
|
||||
-- * `AIRBASE.PersianGulf.Tunb_Kochak`
|
||||
-- * `AIRBASE.PersianGulf.Sas_Al_Nakheel_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Bandar_e_Jask_airfield`
|
||||
-- * `AIRBASE.PersianGulf.Abu_Dhabi_International_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Al_Bateen_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Kish_International_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Al_Ain_International_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Lavan_Island_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Jiroft_Airport`
|
||||
-- * `AIRBASE.PersianGulf.Sas_Al_Nakheel`
|
||||
-- * `AIRBASE.PersianGulf.Bandar_e_Jask`
|
||||
-- * `AIRBASE.PersianGulf.Abu_Dhabi_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Al_Bateen`
|
||||
-- * `AIRBASE.PersianGulf.Kish_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Al_Ain_Intl`
|
||||
-- * `AIRBASE.PersianGulf.Lavan_Island`
|
||||
-- * `AIRBASE.PersianGulf.Jiroft`
|
||||
--
|
||||
-- # Installation
|
||||
--
|
||||
@ -1391,8 +1405,8 @@ end
|
||||
-- AirbasePoliceCaucasus = ATC_GROUND_PERSIANGULF:New()
|
||||
--
|
||||
-- ATC_Ground = ATC_GROUND_PERSIANGULF:New(
|
||||
-- { AIRBASE.PersianGulf.Kerman_Airport,
|
||||
-- AIRBASE.PersianGulf.Al_Minhad_AB
|
||||
-- { AIRBASE.PersianGulf.Kerman,
|
||||
-- AIRBASE.PersianGulf.Al_Minhad_AFB
|
||||
-- }
|
||||
-- )
|
||||
--
|
||||
@ -1441,11 +1455,10 @@ function ATC_GROUND_PERSIANGULF:Start( RepeatScanSeconds )
|
||||
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
||||
end
|
||||
|
||||
|
||||
-- @type ATC_GROUND_MARIANAISLANDS
|
||||
---
|
||||
-- @type ATC_GROUND_MARIANAISLANDS
|
||||
-- @extends #ATC_GROUND
|
||||
|
||||
|
||||
|
||||
--- # ATC\_GROUND\_MARIANA, extends @{#ATC_GROUND}
|
||||
--
|
||||
|
||||
@ -619,63 +619,148 @@ ARTY.WeaponType={
|
||||
}
|
||||
|
||||
--- Database of common artillery unit properties.
|
||||
-- @type ARTY.dbitem
|
||||
-- @field #string displayname Name displayed in ME.
|
||||
-- @field #number minrange Minimum firing range in meters.
|
||||
-- @field #number maxrange Maximum firing range in meters.
|
||||
-- @field #number reloadtime Reload time in seconds.
|
||||
|
||||
--- Database of common artillery unit properties.
|
||||
-- Table key is the "type name" and table value is and `ARTY.dbitem`.
|
||||
-- @type ARTY.db
|
||||
ARTY.db={
|
||||
["2B11 mortar"] = { -- type "2B11 mortar"
|
||||
minrange = 500, -- correct?
|
||||
maxrange = 7000, -- 7 km
|
||||
reloadtime = 30, -- 30 sec
|
||||
["LeFH_18-40-105"] = {
|
||||
displayname = "FH LeFH-18 105mm", -- name displayed in the ME
|
||||
minrange = 500, -- min range (green circle) in meters
|
||||
maxrange = 10500, -- max range (red circle) in meters
|
||||
reloadtime = nil, -- reload time in seconds
|
||||
},
|
||||
["SPH 2S1 Gvozdika"] = { -- type "SAU Gvozdika"
|
||||
minrange = 300, -- correct?
|
||||
maxrange = 15000, -- 15 km
|
||||
reloadtime = nil, -- unknown
|
||||
["M2A1-105"] = {
|
||||
displayname = "FH M2A1 105mm",
|
||||
minrange = 500,
|
||||
maxrange = 11500,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["SPH 2S19 Msta"] = { --type "SAU Msta", alias "2S19 Msta"
|
||||
minrange = 300, -- correct?
|
||||
maxrange = 23500, -- 23.5 km
|
||||
reloadtime = nil, -- unknown
|
||||
["Pak40"] = {
|
||||
displayname = "FH Pak 40 75mm",
|
||||
minrange = 500,
|
||||
maxrange = 3000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["L118_Unit"] = {
|
||||
displayname = "L118 Light Artillery Gun",
|
||||
minrange = 500,
|
||||
maxrange = 17500,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["SPH 2S3 Akatsia"] = { -- type "SAU Akatsia", alias "2S3 Akatsia"
|
||||
minrange = 300, -- correct?
|
||||
maxrange = 17000, -- 17 km
|
||||
reloadtime = nil, -- unknown
|
||||
["Smerch"] = {
|
||||
displayname = "MLRS 9A52 Smerch CM 300mm",
|
||||
minrange = 20000,
|
||||
maxrange = 70000,
|
||||
reloadtime = 2160,
|
||||
},
|
||||
["SPH 2S9 Nona"] = { --type "SAU 2-C9"
|
||||
minrange = 500, -- correct?
|
||||
maxrange = 7000, -- 7 km
|
||||
reloadtime = nil, -- unknown
|
||||
["Smerch_HE"] = {
|
||||
displayname = "MLRS 9A52 Smerch HE 300mm",
|
||||
minrange = 20000,
|
||||
maxrange = 70000,
|
||||
reloadtime = 2160,
|
||||
},
|
||||
["SPH M109 Paladin"] = { -- type "M-109", alias "M109"
|
||||
minrange = 300, -- correct?
|
||||
maxrange = 22000, -- 22 km
|
||||
reloadtime = nil, -- unknown
|
||||
["Uragan_BM-27"] = {
|
||||
displayname = "MLRS 9K57 Uragan BM-27 220mm",
|
||||
minrange = 11500,
|
||||
maxrange = 35800,
|
||||
reloadtime = 840,
|
||||
},
|
||||
["SpGH Dana"] = { -- type "SpGH_Dana"
|
||||
minrange = 300, -- correct?
|
||||
maxrange = 18700, -- 18.7 km
|
||||
reloadtime = nil, -- unknown
|
||||
["Grad-URAL"] = {
|
||||
displayname = "MLRS BM-21 Grad 122mm",
|
||||
minrange = 5000,
|
||||
maxrange = 19000,
|
||||
reloadtime = 420,
|
||||
},
|
||||
["MLRS BM-21 Grad"] = { --type "Grad-URAL", alias "MLRS BM-21 Grad"
|
||||
minrange = 5000, -- 5 km
|
||||
maxrange = 19000, -- 19 km
|
||||
reloadtime = 420, -- 7 min
|
||||
["HL_B8M1"] = {
|
||||
displayname = "MLRS HL with B8M1 80mm",
|
||||
minrange = 500,
|
||||
maxrange = 5000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["MLRS 9K57 Uragan BM-27"] = { -- type "Uragan_BM-27"
|
||||
minrange = 11500, -- 11.5 km
|
||||
maxrange = 35800, -- 35.8 km
|
||||
reloadtime = 840, -- 14 min
|
||||
["tt_B8M1"] = {
|
||||
displayname = "MLRS LC with B8M1 80mm",
|
||||
minrange = 500,
|
||||
maxrange = 5000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["MLRS 9A52 Smerch"] = { -- type "Smerch"
|
||||
minrange = 20000, -- 20 km
|
||||
maxrange = 70000, -- 70 km
|
||||
reloadtime = 2160, -- 36 min
|
||||
["MLRS"] = {
|
||||
displayname = "MLRS M270 227mm",
|
||||
minrange = 10000,
|
||||
maxrange = 32000,
|
||||
reloadtime = 540,
|
||||
},
|
||||
["MLRS M270"] = { --type "MRLS", alias "M270 MRLS"
|
||||
minrange = 10000, -- 10 km
|
||||
maxrange = 32000, -- 32 km
|
||||
reloadtime = 540, -- 9 min
|
||||
["2B11 mortar"] = {
|
||||
displayname = "Mortar 2B11 120mm",
|
||||
minrange = 500,
|
||||
maxrange = 7000,
|
||||
reloadtime = 30,
|
||||
},
|
||||
["PLZ05"] = {
|
||||
displayname = "PLZ-05",
|
||||
minrange = 500,
|
||||
maxrange = 23500,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["SAU Gvozdika"] = {
|
||||
displayname = "SPH 2S1 Gvozdika 122mm",
|
||||
minrange = 300,
|
||||
maxrange = 15000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["SAU Msta"] = {
|
||||
displayname = "SPH 2S19 Msta 152mm",
|
||||
minrange = 300,
|
||||
maxrange = 23500,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["SAU Akatsia"] = {
|
||||
displayname = "SPH 2S3 Akatsia 152mm",
|
||||
minrange = 300,
|
||||
maxrange = 17000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["SpGH_Dana"] = {
|
||||
displayname = "SPH Dana vz77 152mm",
|
||||
minrange = 300,
|
||||
maxrange = 18700,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["M-109"] = {
|
||||
displayname = "SPH M109 Paladin 155mm",
|
||||
minrange = 300,
|
||||
maxrange = 22000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["M12_GMC"] = {
|
||||
displayname = "SPH M12 GMC 155mm",
|
||||
minrange = 300,
|
||||
maxrange = 18200,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["Wespe124"] = {
|
||||
displayname = "SPH Sd.Kfz.124 Wespe 105mm",
|
||||
minrange = 300,
|
||||
maxrange = 7000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["T155_Firtina"] = {
|
||||
displayname = "SPH T155 Firtina 155mm",
|
||||
minrange = 300,
|
||||
maxrange = 41000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
["SAU 2-C9"] = {
|
||||
displayname = "SPM 2S9 Nona 120mm M",
|
||||
minrange = 500,
|
||||
maxrange = 7000,
|
||||
reloadtime = nil,
|
||||
},
|
||||
}
|
||||
|
||||
--- Target.
|
||||
@ -695,7 +780,7 @@ ARTY.db={
|
||||
|
||||
--- Arty script version.
|
||||
-- @field #string version
|
||||
ARTY.version="1.3.1"
|
||||
ARTY.version="1.3.3"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -797,8 +882,8 @@ function ARTY:New(group, alias)
|
||||
-- Maximum speed in km/h.
|
||||
self.SpeedMax=group:GetSpeedMax()
|
||||
|
||||
-- Group is mobile or not (e.g. mortars).
|
||||
if self.SpeedMax>1 then
|
||||
-- Group is mobile or not (e.g. mortars). Some immobile units have a speed of 1 m/s = 3.6 km/h. So we check this number.
|
||||
if self.SpeedMax>3.6 then
|
||||
self.ismobile=true
|
||||
else
|
||||
self.ismobile=false
|
||||
@ -1923,7 +2008,7 @@ function ARTY:onafterStart(Controllable, From, Event, To)
|
||||
end
|
||||
|
||||
-- Check if we have and arty type that is in the DB.
|
||||
local _dbproperties=self:_CheckDB(self.DisplayName)
|
||||
local _dbproperties=self:_CheckDB(self.Type)
|
||||
self:T({dbproperties=_dbproperties})
|
||||
if _dbproperties~=nil then
|
||||
for property,value in pairs(_dbproperties) do
|
||||
@ -1969,8 +2054,8 @@ function ARTY:onafterStart(Controllable, From, Event, To)
|
||||
text=text..string.format("Type = %s\n", self.Type)
|
||||
text=text..string.format("Display Name = %s\n", self.DisplayName)
|
||||
text=text..string.format("Number of units = %d\n", self.IniGroupStrength)
|
||||
text=text..string.format("Speed max = %d km/h\n", self.SpeedMax)
|
||||
text=text..string.format("Speed default = %d km/h\n", self.Speed)
|
||||
text=text..string.format("Speed max = %.1f km/h\n", self.SpeedMax)
|
||||
text=text..string.format("Speed default = %.1f km/h\n", self.Speed)
|
||||
text=text..string.format("Is mobile = %s\n", tostring(self.ismobile))
|
||||
text=text..string.format("Is cargo = %s\n", tostring(self.iscargo))
|
||||
text=text..string.format("Min range = %.1f km\n", self.minrange/1000)
|
||||
@ -3049,7 +3134,7 @@ function ARTY:onafterOpenFire(Controllable, From, Event, To, target)
|
||||
local nfire=Narty
|
||||
local _type="shots"
|
||||
if target.weapontype==ARTY.WeaponType.Auto then
|
||||
nfire=Narty
|
||||
nfire=Nammo -- We take everything that is available
|
||||
_type="shots"
|
||||
elseif target.weapontype==ARTY.WeaponType.Cannon then
|
||||
nfire=Narty
|
||||
@ -3070,6 +3155,8 @@ function ARTY:onafterOpenFire(Controllable, From, Event, To, target)
|
||||
nfire=Nmissiles
|
||||
_type="cruise missiles"
|
||||
end
|
||||
|
||||
--env.info(string.format("FF type=%s, Nrockets=%d, Nfire=%d target.nshells=%d", _type, Nrockets, nfire, target.nshells))
|
||||
|
||||
-- Adjust if less than requested ammo is left.
|
||||
target.nshells=math.min(target.nshells, nfire)
|
||||
|
||||
@ -354,7 +354,7 @@ function CLEANUP_AIRBASE.__:EventAddForCleanUp( Event )
|
||||
self:F({Event})
|
||||
|
||||
|
||||
if Event.IniDCSUnit and Event.IniCategory == Object.Category.UNIT then
|
||||
if Event.IniDCSUnit and Event.IniUnit and Event.IniCategory == Object.Category.UNIT then
|
||||
if self.CleanUpList[Event.IniDCSUnitName] == nil then
|
||||
if self:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
||||
self:AddForCleanUp( Event.IniUnit, Event.IniDCSUnitName )
|
||||
@ -362,7 +362,7 @@ function CLEANUP_AIRBASE.__:EventAddForCleanUp( Event )
|
||||
end
|
||||
end
|
||||
|
||||
if Event.TgtDCSUnit and Event.TgtCategory == Object.Category.UNIT then
|
||||
if Event.TgtDCSUnit and Event.TgtUnit and Event.TgtCategory == Object.Category.UNIT then
|
||||
if self.CleanUpList[Event.TgtDCSUnitName] == nil then
|
||||
if self:IsInAirbase( Event.TgtUnit:GetVec2() ) then
|
||||
self:AddForCleanUp( Event.TgtUnit, Event.TgtDCSUnitName )
|
||||
@ -384,7 +384,7 @@ function CLEANUP_AIRBASE.__:CleanUpSchedule()
|
||||
local CleanUpUnit = CleanUpListData.CleanUpUnit -- Wrapper.Unit#UNIT
|
||||
local CleanUpGroupName = CleanUpListData.CleanUpGroupName
|
||||
|
||||
if CleanUpUnit:IsAlive() ~= nil then
|
||||
if CleanUpUnit and CleanUpUnit:IsAlive() ~= nil then
|
||||
|
||||
if self:IsInAirbase( CleanUpUnit:GetVec2() ) then
|
||||
|
||||
@ -411,7 +411,7 @@ function CLEANUP_AIRBASE.__:CleanUpSchedule()
|
||||
end
|
||||
end
|
||||
-- Clean Units which are waiting for a very long time in the CleanUpZone.
|
||||
if CleanUpUnit and not CleanUpUnit:GetPlayerName() then
|
||||
if CleanUpUnit and (CleanUpUnit.GetPlayerName == nil or not CleanUpUnit:GetPlayerName()) then
|
||||
local CleanUpUnitVelocity = CleanUpUnit:GetVelocityKMH()
|
||||
if CleanUpUnitVelocity < 1 then
|
||||
if CleanUpListData.CleanUpMoved then
|
||||
|
||||
@ -652,7 +652,7 @@ do -- DETECTION_BASE
|
||||
|
||||
if DetectedObject:isExist() then
|
||||
|
||||
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity = DetectionUnit:IsTargetDetected(
|
||||
local TargetIsDetected, TargetIsVisible, TargetKnowType, TargetKnowDistance, TargetLastTime, TargetLastPos, TargetLastVelocity = DetectionUnit:IsTargetDetected(
|
||||
DetectedObject,
|
||||
self.DetectVisual,
|
||||
self.DetectOptical,
|
||||
|
||||
@ -1154,8 +1154,6 @@ function ESCORT:_ReportTargetsScheduler()
|
||||
|
||||
if self.EscortGroup:IsAlive() and self.EscortClient:IsAlive() then
|
||||
|
||||
if true then
|
||||
|
||||
local EscortGroupName = self.EscortGroup:GetName()
|
||||
|
||||
self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
|
||||
@ -1226,177 +1224,6 @@ function ESCORT:_ReportTargetsScheduler()
|
||||
end
|
||||
|
||||
return true
|
||||
else
|
||||
-- local EscortGroupName = self.EscortGroup:GetName()
|
||||
-- local EscortTargets = self.EscortGroup:GetDetectedTargets()
|
||||
--
|
||||
-- local ClientEscortTargets = self.EscortClient._EscortGroups[EscortGroupName].Targets
|
||||
--
|
||||
-- local EscortTargetMessages = ""
|
||||
-- for EscortTargetID, EscortTarget in pairs( EscortTargets ) do
|
||||
-- local EscortObject = EscortTarget.object
|
||||
-- self:T( EscortObject )
|
||||
-- if EscortObject and EscortObject:isExist() and EscortObject.id_ < 50000000 then
|
||||
--
|
||||
-- local EscortTargetUnit = UNIT:Find( EscortObject )
|
||||
-- local EscortTargetUnitName = EscortTargetUnit:GetName()
|
||||
--
|
||||
--
|
||||
--
|
||||
-- -- local EscortTargetIsDetected,
|
||||
-- -- EscortTargetIsVisible,
|
||||
-- -- EscortTargetLastTime,
|
||||
-- -- EscortTargetKnowType,
|
||||
-- -- EscortTargetKnowDistance,
|
||||
-- -- EscortTargetLastPos,
|
||||
-- -- EscortTargetLastVelocity
|
||||
-- -- = self.EscortGroup:IsTargetDetected( EscortObject )
|
||||
-- --
|
||||
-- -- self:T( { EscortTargetIsDetected,
|
||||
-- -- EscortTargetIsVisible,
|
||||
-- -- EscortTargetLastTime,
|
||||
-- -- EscortTargetKnowType,
|
||||
-- -- EscortTargetKnowDistance,
|
||||
-- -- EscortTargetLastPos,
|
||||
-- -- EscortTargetLastVelocity } )
|
||||
--
|
||||
--
|
||||
-- local EscortTargetUnitVec3 = EscortTargetUnit:GetVec3()
|
||||
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
||||
-- local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
|
||||
-- ( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
|
||||
-- ( EscortTargetUnitVec3.z - EscortVec3.z )^2
|
||||
-- ) ^ 0.5 / 1000
|
||||
--
|
||||
-- self:T( { self.EscortGroup:GetName(), EscortTargetUnit:GetName(), Distance, EscortTarget } )
|
||||
--
|
||||
-- if Distance <= 15 then
|
||||
--
|
||||
-- if not ClientEscortTargets[EscortTargetUnitName] then
|
||||
-- ClientEscortTargets[EscortTargetUnitName] = {}
|
||||
-- end
|
||||
-- ClientEscortTargets[EscortTargetUnitName].AttackUnit = EscortTargetUnit
|
||||
-- ClientEscortTargets[EscortTargetUnitName].visible = EscortTarget.visible
|
||||
-- ClientEscortTargets[EscortTargetUnitName].type = EscortTarget.type
|
||||
-- ClientEscortTargets[EscortTargetUnitName].distance = EscortTarget.distance
|
||||
-- else
|
||||
-- if ClientEscortTargets[EscortTargetUnitName] then
|
||||
-- ClientEscortTargets[EscortTargetUnitName] = nil
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- self:T( { "Sorting Targets Table:", ClientEscortTargets } )
|
||||
-- table.sort( ClientEscortTargets, function( a, b ) return a.Distance < b.Distance end )
|
||||
-- self:T( { "Sorted Targets Table:", ClientEscortTargets } )
|
||||
--
|
||||
-- -- Remove the sub menus of the Attack menu of the Escort for the EscortGroup.
|
||||
-- self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
|
||||
--
|
||||
-- if self.EscortMenuTargetAssistance then
|
||||
-- self.EscortMenuTargetAssistance:RemoveSubMenus()
|
||||
-- end
|
||||
--
|
||||
-- --for MenuIndex = 1, #self.EscortMenuAttackTargets do
|
||||
-- -- self:T( { "Remove Menu:", self.EscortMenuAttackTargets[MenuIndex] } )
|
||||
-- -- self.EscortMenuAttackTargets[MenuIndex] = self.EscortMenuAttackTargets[MenuIndex]:Remove()
|
||||
-- --end
|
||||
--
|
||||
--
|
||||
-- if ClientEscortTargets then
|
||||
-- for ClientEscortTargetUnitName, ClientEscortTargetData in pairs( ClientEscortTargets ) do
|
||||
--
|
||||
-- for ClientEscortGroupName, EscortGroupData in pairs( self.EscortClient._EscortGroups ) do
|
||||
--
|
||||
-- if ClientEscortTargetData and ClientEscortTargetData.AttackUnit:IsAlive() then
|
||||
--
|
||||
-- local EscortTargetMessage = ""
|
||||
-- local EscortTargetCategoryName = ClientEscortTargetData.AttackUnit:GetCategoryName()
|
||||
-- local EscortTargetCategoryType = ClientEscortTargetData.AttackUnit:GetTypeName()
|
||||
-- if ClientEscortTargetData.type then
|
||||
-- EscortTargetMessage = EscortTargetMessage .. EscortTargetCategoryName .. " (" .. EscortTargetCategoryType .. ") at "
|
||||
-- else
|
||||
-- EscortTargetMessage = EscortTargetMessage .. "Unknown target at "
|
||||
-- end
|
||||
--
|
||||
-- local EscortTargetUnitVec3 = ClientEscortTargetData.AttackUnit:GetVec3()
|
||||
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
||||
-- local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
|
||||
-- ( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
|
||||
-- ( EscortTargetUnitVec3.z - EscortVec3.z )^2
|
||||
-- ) ^ 0.5 / 1000
|
||||
--
|
||||
-- self:T( { self.EscortGroup:GetName(), ClientEscortTargetData.AttackUnit:GetName(), Distance, ClientEscortTargetData.AttackUnit } )
|
||||
-- if ClientEscortTargetData.visible == false then
|
||||
-- EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " estimated km"
|
||||
-- else
|
||||
-- EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " km"
|
||||
-- end
|
||||
--
|
||||
-- if ClientEscortTargetData.visible then
|
||||
-- EscortTargetMessage = EscortTargetMessage .. ", visual"
|
||||
-- end
|
||||
--
|
||||
-- if ClientEscortGroupName == EscortGroupName then
|
||||
--
|
||||
-- MENU_GROUP_COMMAND:New( self.EscortClient,
|
||||
-- EscortTargetMessage,
|
||||
-- self.EscortMenuAttackNearbyTargets,
|
||||
-- ESCORT._AttackTarget,
|
||||
-- { ParamSelf = self,
|
||||
-- ParamUnit = ClientEscortTargetData.AttackUnit
|
||||
-- }
|
||||
-- )
|
||||
-- EscortTargetMessages = EscortTargetMessages .. "\n - " .. EscortTargetMessage
|
||||
-- else
|
||||
-- if self.EscortMenuTargetAssistance then
|
||||
-- local MenuTargetAssistance = MENU_GROUP:New( self.EscortClient, EscortGroupData.EscortName, self.EscortMenuTargetAssistance )
|
||||
-- MENU_GROUP_COMMAND:New( self.EscortClient,
|
||||
-- EscortTargetMessage,
|
||||
-- MenuTargetAssistance,
|
||||
-- ESCORT._AssistTarget,
|
||||
-- self,
|
||||
-- EscortGroupData.EscortGroup,
|
||||
-- ClientEscortTargetData.AttackUnit
|
||||
-- )
|
||||
-- end
|
||||
-- end
|
||||
-- else
|
||||
-- ClientEscortTargetData = nil
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- if EscortTargetMessages ~= "" and self.ReportTargets == true then
|
||||
-- self.EscortGroup:MessageToClient( "Detected targets within 15 km range:" .. EscortTargetMessages:gsub("\n$",""), 20, self.EscortClient )
|
||||
-- else
|
||||
-- self.EscortGroup:MessageToClient( "No targets detected!", 20, self.EscortClient )
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- if self.EscortMenuResumeMission then
|
||||
-- self.EscortMenuResumeMission:RemoveSubMenus()
|
||||
--
|
||||
-- -- if self.EscortMenuResumeWayPoints then
|
||||
-- -- for MenuIndex = 1, #self.EscortMenuResumeWayPoints do
|
||||
-- -- self:T( { "Remove Menu:", self.EscortMenuResumeWayPoints[MenuIndex] } )
|
||||
-- -- self.EscortMenuResumeWayPoints[MenuIndex] = self.EscortMenuResumeWayPoints[MenuIndex]:Remove()
|
||||
-- -- end
|
||||
-- -- end
|
||||
--
|
||||
-- local TaskPoints = self:RegisterRoute()
|
||||
-- for WayPointID, WayPoint in pairs( TaskPoints ) do
|
||||
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
||||
-- local Distance = ( ( WayPoint.x - EscortVec3.x )^2 +
|
||||
-- ( WayPoint.y - EscortVec3.z )^2
|
||||
-- ) ^ 0.5 / 1000
|
||||
-- MENU_GROUP_COMMAND:New( self.EscortClient, "Waypoint " .. WayPointID .. " at " .. string.format( "%.2f", Distance ).. "km", self.EscortMenuResumeMission, ESCORT._ResumeMission, { ParamSelf = self, ParamWayPoint = WayPointID } )
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
@ -141,7 +141,6 @@ FOX = {
|
||||
explosiondist = 200,
|
||||
explosiondist2 = 500,
|
||||
bigmissilemass = 50,
|
||||
destroy = nil,
|
||||
dt50 = 5,
|
||||
dt10 = 1,
|
||||
dt05 = 0.5,
|
||||
@ -1060,7 +1059,7 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
|
||||
-- Tracking info and init of last bomb position.
|
||||
local text=string.format("FOX: Tracking missile %s(%s) - target %s - shooter %s", missile.missileType, missile.missileName, tostring(missile.targetName), missile.shooterName)
|
||||
self:I(FOX.lid..text)
|
||||
self:T(FOX.lid..text)
|
||||
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
||||
|
||||
-- Loop over players.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -53,6 +53,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE.
|
||||
-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality.
|
||||
--
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -107,6 +107,9 @@
|
||||
-- @field Sound.SRS#MSRSQUEUE instructsrsQ SRS queue for range instructor.
|
||||
-- @field #number Coalition Coalition side for the menu, if any.
|
||||
-- @field Core.Menu#MENU_MISSION menuF10root Specific user defined root F10 menu.
|
||||
-- @field #number ceilingaltitude Range ceiling altitude in ft MSL. Aircraft above this altitude are not considered to be in the range. Default is 20000 ft.
|
||||
-- @field #boolean ceilingenabled Range has a ceiling and is not unlimited. Default is false.
|
||||
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- *Don't only practice your art, but force your way into its secrets; art deserves that, for it and knowledge can raise man to the Divine.* - Ludwig van Beethoven
|
||||
@ -273,6 +276,10 @@
|
||||
-- -- Create a range object.
|
||||
-- GoldwaterRange=RANGE:New("Goldwater Range")
|
||||
--
|
||||
-- -- Set and enable the range ceiling altitude in feet MSL. If aircraft are above this altitude they are not considered to be in the range.
|
||||
-- GoldwaterRange:SetRangeCeiling(20000)
|
||||
-- GoldwaterRange:EnableRangeCeiling(true)
|
||||
--
|
||||
-- -- Distance between strafe target and foul line. You have to specify the names of the unit or static objects.
|
||||
-- -- Note that this could also be done manually by simply measuring the distance between the target and the foul line in the ME.
|
||||
-- GoldwaterRange:GetFoullineDistance("GWR Strafe Pit Left 1", "GWR Foul Line Left")
|
||||
@ -358,6 +365,8 @@ RANGE = {
|
||||
targetpath = nil,
|
||||
targetprefix = nil,
|
||||
Coalition = nil,
|
||||
ceilingaltitude = 20000,
|
||||
ceilingenabled = false,
|
||||
}
|
||||
|
||||
--- Default range parameters.
|
||||
@ -1085,6 +1094,37 @@ function RANGE:SetRangeZone( zone )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set range ceiling altitude in feet MSL.
|
||||
-- @param #RANGE self
|
||||
-- @param #number altitude (optional) Ceiling altitude of the range in ft MSL. Default 20000ft MSL
|
||||
-- @return #RANGE self
|
||||
function RANGE:SetRangeCeiling( altitude )
|
||||
self:T(self.lid.."SetRangeCeiling")
|
||||
if altitude and type(altitude) == "number" then
|
||||
self.ceilingaltitude=altitude
|
||||
else
|
||||
self:E(self.lid.."Altitude either not provided or is not a number, using default setting (20000).")
|
||||
self.ceilingaltitude=20000
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Enable range ceiling. Aircraft must be below the ceiling altitude to be considered in the range zone.
|
||||
-- @param #RANGE self
|
||||
-- @param #boolean enabled True if you would like to enable the ceiling check. If no value give, will Default to false.
|
||||
-- @return #RANGE self
|
||||
function RANGE:EnableRangeCeiling( enabled )
|
||||
self:T(self.lid.."EnableRangeCeiling")
|
||||
if enabled and type(enabled) == "boolean" then
|
||||
self.ceilingenabled=enabled
|
||||
else
|
||||
self:E(self.lid.."Enabled either not provide or is not a boolean, using default setting (false).")
|
||||
self.ceilingenabled=false
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set smoke color for marking bomb targets. By default bomb targets are marked by red smoke.
|
||||
-- @param #RANGE self
|
||||
-- @param Utilities.Utils#SMOKECOLOR colorid Color id. Default `SMOKECOLOR.Red`.
|
||||
@ -1893,7 +1933,7 @@ function RANGE:OnEventHit( EventData )
|
||||
local _currentTarget = self.strafeStatus[_unitID] --#RANGE.StrafeStatus
|
||||
|
||||
-- Player has rolled in on a strafing target.
|
||||
if _currentTarget and target:IsAlive() then
|
||||
if _currentTarget and target and target:IsAlive() then
|
||||
|
||||
local playerPos = _unit:GetCoordinate()
|
||||
local targetPos = target:GetCoordinate()
|
||||
@ -2062,7 +2102,12 @@ function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackV
|
||||
result.attackHdg = attackHdg
|
||||
result.attackVel = attackVel
|
||||
result.attackAlt = attackAlt
|
||||
result.date=os and os.date() or "n/a"
|
||||
if os and os.date then
|
||||
result.date=os.date()
|
||||
else
|
||||
self:E(self.lid.."os or os.date() not available")
|
||||
result.date = "n/a"
|
||||
end
|
||||
|
||||
-- Add to table.
|
||||
table.insert( _results, result )
|
||||
@ -2987,7 +3032,7 @@ function RANGE:_DisplayBombTargets( _unitname )
|
||||
end
|
||||
end
|
||||
|
||||
self:_DisplayMessageToGroup( _unit, _text, 120, true, true, _multiplayer )
|
||||
self:_DisplayMessageToGroup( _unit, _text, 150, true, true, _multiplayer )
|
||||
end
|
||||
end
|
||||
|
||||
@ -3112,7 +3157,10 @@ function RANGE:_CheckPlayers()
|
||||
|
||||
if unit and unit:IsAlive() then
|
||||
|
||||
if unit:IsInZone( self.rangezone ) then
|
||||
local unitalt = unit:GetAltitude(false)
|
||||
local unitaltinfeet = UTILS.MetersToFeet(unitalt)
|
||||
|
||||
if unit:IsInZone(self.rangezone) and (not self.ceilingenabled or unitaltinfeet < self.ceilingaltitude) then
|
||||
|
||||
------------------------------
|
||||
-- Player INSIDE Range Zone --
|
||||
@ -3453,10 +3501,10 @@ function RANGE:_AddF10Commands( _unitName )
|
||||
-- Range menu
|
||||
local _rangePath = MENU_GROUP:New( group, self.rangename, _rootMenu )
|
||||
|
||||
local _statsPath = MENU_GROUP:New( group, "Statistics", _rangePath )
|
||||
local _markPath = MENU_GROUP:New( group, "Mark Targets", _rangePath )
|
||||
local _settingsPath = MENU_GROUP:New( group, "My Settings", _rangePath )
|
||||
local _infoPath = MENU_GROUP:New( group, "Range Info", _rangePath )
|
||||
local _markPath = MENU_GROUP:New( group, "Mark Targets", _rangePath )
|
||||
local _statsPath = MENU_GROUP:New( group, "Statistics", _rangePath )
|
||||
local _settingsPath = MENU_GROUP:New( group, "My Settings", _rangePath )
|
||||
|
||||
-- F10/On the Range/<Range Name>/My Settings/
|
||||
local _mysmokePath = MENU_GROUP:New( group, "Smoke Color", _settingsPath )
|
||||
|
||||
@ -320,8 +320,10 @@ function SCORING:New( GameName, SavePath, AutoSave )
|
||||
|
||||
-- Create the CSV file.
|
||||
self.AutoSavePath = SavePath
|
||||
self.AutoSave = AutoSave or true
|
||||
self:OpenCSV( GameName )
|
||||
self.AutoSave = (AutoSave == nil or AutoSave == true) and true or false
|
||||
if self.AutoSavePath and self.AutoSave == true then
|
||||
self:OpenCSV( GameName )
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
@ -985,6 +987,7 @@ function SCORING:_EventOnHit( Event )
|
||||
local TargetUnitCoalition = nil
|
||||
local TargetUnitCategory = nil
|
||||
local TargetUnitType = nil
|
||||
local TargetIsScenery = false
|
||||
|
||||
if Event.IniDCSUnit then
|
||||
|
||||
@ -1025,6 +1028,12 @@ function SCORING:_EventOnHit( Event )
|
||||
TargetCategory = Event.TgtCategory
|
||||
TargetType = Event.TgtTypeName
|
||||
|
||||
-- Scenery hit
|
||||
if (not TargetCategory) and TargetUNIT ~= nil and TargetUnit:IsInstanceOf("SCENERY") then
|
||||
TargetCategory = Unit.Category.STRUCTURE
|
||||
TargetIsScenery = true
|
||||
end
|
||||
|
||||
TargetUnitCoalition = _SCORINGCoalition[TargetCoalition]
|
||||
TargetUnitCategory = _SCORINGCategory[TargetCategory]
|
||||
TargetUnitType = TargetType
|
||||
@ -1117,17 +1126,22 @@ function SCORING:_EventOnHit( Event )
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
else
|
||||
elseif TargetIsScenery ~= true then
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " ..
|
||||
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
elseif TargetIsScenery == true then
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit scenery object." .. " Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
end
|
||||
self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
end
|
||||
else -- A scenery object was hit.
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit scenery object.",
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit nothing special.",
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
@ -1923,7 +1937,7 @@ function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes,
|
||||
TargetUnitType = TargetUnitType or ""
|
||||
TargetUnitName = TargetUnitName or ""
|
||||
|
||||
if lfs and io and os and self.AutoSave then
|
||||
if lfs and io and os and self.AutoSave == true and self.CSVFile ~= nil then
|
||||
self.CSVFile:write(
|
||||
'"' .. self.GameName .. '"' .. ',' ..
|
||||
'"' .. self.RunTime .. '"' .. ',' ..
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
--
|
||||
-- ### Authors: **applevangelist**, **FlightControl**
|
||||
--
|
||||
-- Last Update: Dec 2023
|
||||
-- Last Update: Dec 2024
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@ -28,6 +28,16 @@
|
||||
|
||||
---
|
||||
-- @type SEAD
|
||||
-- @field #string ClassName The Class Name.
|
||||
-- @field #table TargetSkill Table of target skills.
|
||||
-- @field #table SEADGroupPrefixes Table of SEAD prefixes.
|
||||
-- @field #table SuppressedGroups Table of currently suppressed groups.
|
||||
-- @field #number EngagementRange Engagement Range.
|
||||
-- @field #number Padding Padding in seconds.
|
||||
-- @field #function CallBack Callback function for suppression plans.
|
||||
-- @field #boolean UseCallBack Switch for callback function to be used.
|
||||
-- @field #boolean debug Debug switch.
|
||||
-- @field #boolen WeaponTrack Track switch, if true track weapon speed for 30 secs.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||
@ -56,10 +66,11 @@ SEAD = {
|
||||
SEADGroupPrefixes = {},
|
||||
SuppressedGroups = {},
|
||||
EngagementRange = 75, -- default 75% engagement range Feature Request #1355
|
||||
Padding = 10,
|
||||
Padding = 15,
|
||||
CallBack = nil,
|
||||
UseCallBack = false,
|
||||
debug = false,
|
||||
WeaponTrack = false,
|
||||
}
|
||||
|
||||
--- Missile enumerators
|
||||
@ -69,6 +80,7 @@ SEAD = {
|
||||
["AGM_122"] = "AGM_122",
|
||||
["AGM_84"] = "AGM_84",
|
||||
["AGM_45"] = "AGM_45",
|
||||
["AGM_65"] = "AGM_65",
|
||||
["ALARM"] = "ALARM",
|
||||
["LD-10"] = "LD-10",
|
||||
["X_58"] = "X_58",
|
||||
@ -88,6 +100,7 @@ SEAD = {
|
||||
-- km and mach
|
||||
["AGM_88"] = { 150, 3},
|
||||
["AGM_45"] = { 12, 2},
|
||||
["AGM_65"] = { 16, 0.9},
|
||||
["AGM_122"] = { 16.5, 2.3},
|
||||
["AGM_84"] = { 280, 0.8},
|
||||
["ALARM"] = { 45, 2},
|
||||
@ -144,7 +157,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
|
||||
self:AddTransition("*", "ManageEvasion", "*")
|
||||
self:AddTransition("*", "CalculateHitZone", "*")
|
||||
|
||||
self:I("*** SEAD - Started Version 0.4.6")
|
||||
self:I("*** SEAD - Started Version 0.4.9")
|
||||
return self
|
||||
end
|
||||
|
||||
@ -371,7 +384,7 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
|
||||
reach = wpndata[1] * 1.1
|
||||
local mach = wpndata[2]
|
||||
wpnspeed = math.floor(mach * 340.29)
|
||||
if Weapon then
|
||||
if Weapon and Weapon:GetSpeed() > 0 then
|
||||
wpnspeed = Weapon:GetSpeed()
|
||||
self:T(string.format("*** SEAD - Weapon Speed from WEAPON: %f m/s",wpnspeed))
|
||||
end
|
||||
@ -452,29 +465,38 @@ end
|
||||
-- @return #SEAD self
|
||||
function SEAD:HandleEventShot( EventData )
|
||||
self:T( { EventData.id } )
|
||||
local SEADPlane = EventData.IniUnit -- Wrapper.Unit#UNIT
|
||||
local SEADGroup = EventData.IniGroup -- Wrapper.Group#GROUP
|
||||
local SEADPlanePos = SEADPlane:GetCoordinate() -- Core.Point#COORDINATE
|
||||
local SEADUnit = EventData.IniDCSUnit
|
||||
local SEADUnitName = EventData.IniDCSUnitName
|
||||
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
||||
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
||||
|
||||
local WeaponWrapper = WEAPON:New(EventData.Weapon)
|
||||
--local SEADWeaponSpeed = WeaponWrapper:GetSpeed() -- mps
|
||||
|
||||
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
||||
--self:T({ SEADWeapon })
|
||||
|
||||
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
||||
local SEADWeaponName = EventData.WeaponName or "None" -- return weapon type
|
||||
|
||||
if self:_CheckHarms(SEADWeaponName) then
|
||||
--UTILS.PrintTableToLog(EventData)
|
||||
local SEADPlane = EventData.IniUnit -- Wrapper.Unit#UNIT
|
||||
|
||||
if not SEADPlane then return self end -- case IniUnit is empty
|
||||
|
||||
local SEADGroup = EventData.IniGroup -- Wrapper.Group#GROUP
|
||||
local SEADPlanePos = SEADPlane:GetCoordinate() -- Core.Point#COORDINATE
|
||||
local SEADUnit = EventData.IniDCSUnit
|
||||
local SEADUnitName = EventData.IniDCSUnitName
|
||||
|
||||
local WeaponWrapper = WEAPON:New(EventData.Weapon) -- Wrapper.Weapon#WEAPON
|
||||
|
||||
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
||||
|
||||
self:T( '*** SEAD - Weapon Match' )
|
||||
if self.WeaponTrack == true then
|
||||
WeaponWrapper:SetFuncTrack(function(weapon) env.info(string.format("*** Weapon Speed: %d m/s",weapon:GetSpeed() or -1)) end)
|
||||
WeaponWrapper:StartTrack(0.1)
|
||||
WeaponWrapper:StopTrack(30)
|
||||
end
|
||||
local _targetskill = "Random"
|
||||
local _targetgroupname = "none"
|
||||
local _target = EventData.Weapon:getTarget() -- Identify target
|
||||
if not _target or self.debug then -- AGM-88 or 154 w/o target data
|
||||
self:E("***** SEAD - No target data for " .. (SEADWeaponName or "None"))
|
||||
if string.find(SEADWeaponName,"AGM_88",1,true) or string.find(SEADWeaponName,"AGM_154",1,true) then
|
||||
self:I("**** Tracking AGM-88/154 with no target data.")
|
||||
self:T("**** Tracking AGM-88/154 with no target data.")
|
||||
local pos0 = SEADPlane:GetCoordinate()
|
||||
local fheight = SEADPlane:GetHeight()
|
||||
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup,SEADWeaponName)
|
||||
@ -520,7 +542,7 @@ function SEAD:HandleEventShot( EventData )
|
||||
end
|
||||
if SEADGroupFound == true then -- yes we are being attacked
|
||||
if string.find(SEADWeaponName,"ADM_141",1,true) then
|
||||
self:__ManageEvasion(2,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
|
||||
self:__ManageEvasion(2,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,2,WeaponWrapper)
|
||||
else
|
||||
self:ManageEvasion(_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
|
||||
end
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
-- @image Functional.Shorad.jpg
|
||||
--
|
||||
-- Date: Nov 2021
|
||||
-- Last Update: Nov 2023
|
||||
-- Last Update: Jan 2025
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **SHORAD** class, extends Core.Base#BASE
|
||||
@ -113,7 +113,7 @@ SHORAD = {
|
||||
SkateNumber = 3,
|
||||
SkateZones = nil,
|
||||
minscootdist = 100,
|
||||
minscootdist = 3000,
|
||||
maxscootdist = 3000,
|
||||
scootrandomcoord = false,
|
||||
}
|
||||
|
||||
@ -443,7 +443,9 @@ do
|
||||
for _,_groups in pairs (shoradset) do
|
||||
local groupname = _groups:GetName()
|
||||
if string.find(groupname, tgtgrp, 1, true) then
|
||||
returnname = true
|
||||
if _groups:IsSAM() then
|
||||
returnname = true
|
||||
end
|
||||
end
|
||||
end
|
||||
return returnname
|
||||
@ -470,6 +472,7 @@ do
|
||||
-- @param #number Radius Radius of the #ZONE
|
||||
-- @param #number ActiveTimer Number of seconds to stay active
|
||||
-- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC
|
||||
-- @param #boolean ShotAt If true, function is called after a shot
|
||||
-- @return #SHORAD self
|
||||
-- @usage Use this function to integrate with other systems, example
|
||||
--
|
||||
@ -479,7 +482,7 @@ do
|
||||
-- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
|
||||
-- mymantis:AddShorad(myshorad,720)
|
||||
-- mymantis:Start()
|
||||
function SHORAD:onafterWakeUpShorad(From, Event, To, TargetGroup, Radius, ActiveTimer, TargetCat)
|
||||
function SHORAD:onafterWakeUpShorad(From, Event, To, TargetGroup, Radius, ActiveTimer, TargetCat, ShotAt)
|
||||
self:T(self.lid .. " WakeUpShorad")
|
||||
self:T({TargetGroup, Radius, ActiveTimer, TargetCat})
|
||||
local targetcat = TargetCat or Object.Category.UNIT
|
||||
@ -521,7 +524,27 @@ do
|
||||
-- go through set and find the one(s) to activate
|
||||
local TDiff = 4
|
||||
for _,_group in pairs (shoradset) do
|
||||
if _group:IsAnyInZone(targetzone) then
|
||||
|
||||
local groupname = _group:GetName()
|
||||
|
||||
if groupname == TargetGroup and ShotAt==true then
|
||||
-- Shot at a SHORAD group
|
||||
if self.UseEmOnOff then
|
||||
_group:EnableEmission(false)
|
||||
end
|
||||
_group:OptionAlarmStateGreen()
|
||||
self.ActiveGroups[groupname] = nil
|
||||
local text = string.format("Shot at SHORAD %s! Evading!", _group:GetName())
|
||||
self:T(text)
|
||||
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
|
||||
|
||||
--Shoot and Scoot
|
||||
if self.shootandscoot then
|
||||
self:__ShootAndScoot(1,_group)
|
||||
end
|
||||
|
||||
elseif _group:IsAnyInZone(targetzone) or groupname == TargetGroup then
|
||||
-- shot at a group we protect
|
||||
local text = string.format("Waking up SHORAD %s", _group:GetName())
|
||||
self:T(text)
|
||||
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
|
||||
@ -529,7 +552,6 @@ do
|
||||
_group:EnableEmission(true)
|
||||
end
|
||||
_group:OptionAlarmStateRed()
|
||||
local groupname = _group:GetName()
|
||||
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
|
||||
self.ActiveGroups[groupname] = { Timing = ActiveTimer }
|
||||
local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit
|
||||
@ -607,7 +629,7 @@ do
|
||||
_targetgroupname = tgtgrp:GetName() -- group name
|
||||
_targetskill = tgtgrp:GetUnit(1):GetSkill()
|
||||
self:T("*** Found Target = ".. _targetgroupname)
|
||||
self:WakeUpShorad(_targetgroupname, self.Radius, self.ActiveTimer, Object.Category.UNIT)
|
||||
self:WakeUpShorad(_targetgroupname, self.Radius, self.ActiveTimer, Object.Category.UNIT,true)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -736,7 +758,7 @@ do
|
||||
-- if being shot at, find closest SHORADs to activate
|
||||
if shotatsams or shotatus then
|
||||
self:T({shotatsams=shotatsams,shotatus=shotatus})
|
||||
self:WakeUpShorad(targetgroupname, self.Radius, self.ActiveTimer, targetcat)
|
||||
self:WakeUpShorad(targetgroupname, self.Radius, self.ActiveTimer, targetcat, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -3153,7 +3153,7 @@ end
|
||||
-- @param #WAREHOUSE self
|
||||
-- @return Core.Point#COORDINATE The coordinate of the warehouse.
|
||||
function WAREHOUSE:GetCoordinate()
|
||||
return self.warehouse:GetCoordinate()
|
||||
return self.warehouse:GetCoord()
|
||||
end
|
||||
|
||||
--- Get 3D vector of warehouse static.
|
||||
@ -4247,6 +4247,16 @@ function WAREHOUSE:_AssetItemInfo(asset)
|
||||
self:T3({Template=asset.template})
|
||||
end
|
||||
|
||||
--- This function uses Disposition and other fallback logic to find better ground positions for ground units.
|
||||
--- NOTE: This is not a spawn randomizer.
|
||||
--- It will try to find clear ground locations avoiding trees, water, roads, runways, map scenery, statics and other units in the area and modifies the provided positions table.
|
||||
--- Maintains the original layout and unit positions as close as possible by searching for the next closest valid position to each unit.
|
||||
--- Uses UTILS.ValidateAndRepositionGroundUnits.
|
||||
-- @param #boolean Enabled Enable/disable the feature.
|
||||
function WAREHOUSE:SetValidateAndRepositionGroundUnits(Enabled)
|
||||
self.ValidateAndRepositionGroundUnits = Enabled
|
||||
end
|
||||
|
||||
--- On after "NewAsset" event. A new asset has been added to the warehouse stock.
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param #string From From state.
|
||||
@ -5965,6 +5975,10 @@ function WAREHOUSE:_SpawnAssetGroundNaval(alias, asset, request, spawnzone, late
|
||||
template.y = coord.z
|
||||
template.alt = coord.y
|
||||
|
||||
if self.ValidateAndRepositionGroundUnits then
|
||||
UTILS.ValidateAndRepositionGroundUnits(template.units)
|
||||
end
|
||||
|
||||
-- Spawn group.
|
||||
local group=_DATABASE:Spawn(template) --Wrapper.Group#GROUP
|
||||
|
||||
@ -6047,7 +6061,7 @@ function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrol
|
||||
|
||||
else
|
||||
|
||||
if #parking<#template.units and not airstart then
|
||||
if parking and #parking<#template.units and not airstart then
|
||||
local text=string.format("ERROR: Not enough parking! Free parking = %d < %d aircraft to be spawned.", #parking, #template.units)
|
||||
self:_DebugMessage(text)
|
||||
return nil
|
||||
@ -6089,7 +6103,7 @@ function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrol
|
||||
terminal=parking[i].TerminalID
|
||||
end
|
||||
|
||||
if self.Debug then
|
||||
if self.Debug and terminal then
|
||||
local text=string.format("Spawnplace unit %s terminal %d.", unit.name, terminal)
|
||||
coord:MarkToAll(text)
|
||||
env.info(text)
|
||||
@ -6893,7 +6907,7 @@ function WAREHOUSE:_CheckConquered()
|
||||
for _,_unit in pairs(units) do
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
local distance=coord:Get2DDistance(unit:GetCoordinate())
|
||||
local distance=coord:Get2DDistance(unit:GetCoord())
|
||||
|
||||
-- Filter only alive groud units. Also check distance again, because the scan routine might give some larger distances.
|
||||
if unit:IsGround() and unit:IsAlive() and distance <= radius then
|
||||
@ -8122,9 +8136,11 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
|
||||
-- Debug output for occupied spots.
|
||||
if self.Debug then
|
||||
local coord=problem.coord --Core.Point#COORDINATE
|
||||
local text=string.format("Obstacle %s [type=%s] blocking spot=%d! Size=%.1f m and distance=%.1f m.", problem.name, problem.type, _termid, problem.size, problem.dist)
|
||||
self:I(self.lid..text)
|
||||
coord:MarkToAll(string.format(text))
|
||||
if coord then
|
||||
local text=string.format("Obstacle %s [type=%s] blocking spot=%d! Size=%.1f m and distance=%.1f m.", problem.name, problem.type, _termid, problem.size, problem.dist)
|
||||
self:I(self.lid..text)
|
||||
coord:MarkToAll(text)
|
||||
end
|
||||
else
|
||||
self:T(self.lid..string.format("Parking spot %d is occupied or not big enough!", _termid))
|
||||
end
|
||||
@ -8433,12 +8449,14 @@ function WAREHOUSE:_GetAttribute(group)
|
||||
local attribute=WAREHOUSE.Attribute.OTHER_UNKNOWN --#WAREHOUSE.Attribute
|
||||
|
||||
if group then
|
||||
|
||||
local groupCat=group:GetCategory()
|
||||
|
||||
-----------
|
||||
--- Air ---
|
||||
-----------
|
||||
-- Planes
|
||||
local transportplane=group:HasAttribute("Transports") and group:HasAttribute("Planes")
|
||||
local transportplane=group:HasAttribute("Transports") and group:HasAttribute("Planes") and groupCat==Group.Category.AIRPLANE
|
||||
local awacs=group:HasAttribute("AWACS")
|
||||
local fighter=group:HasAttribute("Fighters") or group:HasAttribute("Interceptors") or group:HasAttribute("Multirole fighters") or (group:HasAttribute("Bombers") and not group:HasAttribute("Strategic bombers"))
|
||||
local bomber=group:HasAttribute("Strategic bombers")
|
||||
@ -8593,7 +8611,6 @@ end
|
||||
-- @param #WAREHOUSE.Queueitem qitem Item of queue to be removed.
|
||||
-- @param #table queue The queue from which the item should be deleted.
|
||||
function WAREHOUSE:_DeleteQueueItem(qitem, queue)
|
||||
self:F({qitem=qitem, queue=queue})
|
||||
|
||||
for i=1,#queue do
|
||||
local _item=queue[i] --#WAREHOUSE.Queueitem
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
|
||||
@ -10,7 +10,7 @@ _SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.ScheduleDispatcher#SCHEDU
|
||||
_DATABASE = DATABASE:New() -- Core.Database#DATABASE
|
||||
|
||||
--- Settings
|
||||
_SETTINGS = SETTINGS:Set()
|
||||
_SETTINGS = SETTINGS:Set() -- Core.Settings#SETTINGS
|
||||
_SETTINGS:SetPlayerMenuOn()
|
||||
|
||||
--- Register cargos.
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Enums.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Utils.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Profiler.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Templates.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/STTS.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/FiFo.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Socket.lua' )
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
-- * Option to present information in imperial or metric units
|
||||
-- * Runway length and airfield elevation (optional)
|
||||
-- * Frequencies/channels of nav aids (ILS, VOR, NDB, TACAN, PRMG, RSBN) (optional)
|
||||
-- * SRS Simple-Text-To-Speech (STTS) integration (no sound files necessary)
|
||||
-- * SRS Simple-Text-To-Speech (MSRS) integration (no sound files necessary)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@ -291,7 +291,7 @@
|
||||
-- ## Nevada: Nellis AFB
|
||||
--
|
||||
-- -- ATIS Nellis AFB on 270.10 MHz AM.
|
||||
-- atisNellis=ATIS:New(AIRBASE.Nevada.Nellis_AFB, 270.1)
|
||||
-- atisNellis=ATIS:New(AIRBASE.Nevada.Nellis, 270.1)
|
||||
-- atisNellis:SetRadioRelayUnitName("Radio Relay Nellis")
|
||||
-- atisNellis:SetActiveRunway("21L")
|
||||
-- atisNellis:SetTowerFrequencies({327.000, 132.550})
|
||||
@ -302,7 +302,7 @@
|
||||
-- ## Persian Gulf: Abu Dhabi International Airport
|
||||
--
|
||||
-- -- ATIS Abu Dhabi International on 125.1 MHz AM.
|
||||
-- atisAbuDhabi=ATIS:New(AIRBASE.PersianGulf.Abu_Dhabi_International_Airport, 125.1)
|
||||
-- atisAbuDhabi=ATIS:New(AIRBASE.PersianGulf.Abu_Dhabi_Intl, 125.1)
|
||||
-- atisAbuDhabi:SetRadioRelayUnitName("Radio Relay Abu Dhabi International Airport")
|
||||
-- atisAbuDhabi:SetMetricUnits()
|
||||
-- atisAbuDhabi:SetActiveRunway("L")
|
||||
@ -498,6 +498,10 @@ ATIS.Alphabet = {
|
||||
-- @field #number Syria +5° (East).
|
||||
-- @field #number MarianaIslands +2° (East).
|
||||
-- @field #number SinaiMap +5° (East).
|
||||
-- @field #number Kola +15° (East).
|
||||
-- @field #number Afghanistan +3° (East).
|
||||
-- @field #number Iraq +4.4° (East).
|
||||
-- @field #number GermanyCW +0.1° (East).
|
||||
ATIS.RunwayM2T = {
|
||||
Caucasus = 0,
|
||||
Nevada = 12,
|
||||
@ -508,6 +512,10 @@ ATIS.RunwayM2T = {
|
||||
MarianaIslands = 2,
|
||||
Falklands = 12,
|
||||
SinaiMap = 5,
|
||||
Kola = 15,
|
||||
Afghanistan = 3,
|
||||
Iraq=4.4,
|
||||
GermanyCW=0.1,
|
||||
}
|
||||
|
||||
--- Whether ICAO phraseology is used for ATIS broadcasts.
|
||||
@ -521,6 +529,10 @@ ATIS.RunwayM2T = {
|
||||
-- @field #boolean MarianaIslands true.
|
||||
-- @field #boolean Falklands true.
|
||||
-- @field #boolean SinaiMap true.
|
||||
-- @field #boolean Kola true.
|
||||
-- @field #boolean Afghanistan true.
|
||||
-- @field #boolean Iraq true.
|
||||
-- @field #boolean GermanyCW true.
|
||||
ATIS.ICAOPhraseology = {
|
||||
Caucasus = true,
|
||||
Nevada = false,
|
||||
@ -531,6 +543,10 @@ ATIS.ICAOPhraseology = {
|
||||
MarianaIslands = true,
|
||||
Falklands = true,
|
||||
SinaiMap = true,
|
||||
Kola = true,
|
||||
Afghanistan = true,
|
||||
Iraq = true,
|
||||
GermanyCW = true,
|
||||
}
|
||||
|
||||
--- Nav point data.
|
||||
@ -619,83 +635,83 @@ ATIS.ICAOPhraseology = {
|
||||
-- @field #ATIS.Soundfile TACANChannel
|
||||
-- @field #ATIS.Soundfile VORFrequency
|
||||
ATIS.Sound = {
|
||||
ActiveRunway = { filename = "ActiveRunway.ogg", duration = 0.99 },
|
||||
ActiveRunwayDeparture = { filename = "ActiveRunwayDeparture.ogg", duration = 0.99 },
|
||||
ActiveRunwayArrival = { filename = "ActiveRunwayArrival.ogg", duration = 0.99 },
|
||||
AdviceOnInitial = { filename = "AdviceOnInitial.ogg", duration = 3.00 },
|
||||
Airport = { filename = "Airport.ogg", duration = 0.66 },
|
||||
Altimeter = { filename = "Altimeter.ogg", duration = 0.68 },
|
||||
At = { filename = "At.ogg", duration = 0.41 },
|
||||
CloudBase = { filename = "CloudBase.ogg", duration = 0.82 },
|
||||
CloudCeiling = { filename = "CloudCeiling.ogg", duration = 0.61 },
|
||||
CloudsBroken = { filename = "CloudsBroken.ogg", duration = 1.07 },
|
||||
CloudsFew = { filename = "CloudsFew.ogg", duration = 0.99 },
|
||||
CloudsNo = { filename = "CloudsNo.ogg", duration = 1.01 },
|
||||
CloudsNotAvailable = { filename = "CloudsNotAvailable.ogg", duration = 2.35 },
|
||||
CloudsOvercast = { filename = "CloudsOvercast.ogg", duration = 0.83 },
|
||||
CloudsScattered = { filename = "CloudsScattered.ogg", duration = 1.18 },
|
||||
Decimal = { filename = "Decimal.ogg", duration = 0.54 },
|
||||
DegreesCelsius = { filename = "DegreesCelsius.ogg", duration = 1.27 },
|
||||
DegreesFahrenheit = { filename = "DegreesFahrenheit.ogg", duration = 1.23 },
|
||||
DewPoint = { filename = "DewPoint.ogg", duration = 0.65 },
|
||||
Dust = { filename = "Dust.ogg", duration = 0.54 },
|
||||
Elevation = { filename = "Elevation.ogg", duration = 0.78 },
|
||||
EndOfInformation = { filename = "EndOfInformation.ogg", duration = 1.15 },
|
||||
Feet = { filename = "Feet.ogg", duration = 0.45 },
|
||||
Fog = { filename = "Fog.ogg", duration = 0.47 },
|
||||
Gusting = { filename = "Gusting.ogg", duration = 0.55 },
|
||||
HectoPascal = { filename = "HectoPascal.ogg", duration = 1.15 },
|
||||
Hundred = { filename = "Hundred.ogg", duration = 0.47 },
|
||||
InchesOfMercury = { filename = "InchesOfMercury.ogg", duration = 1.16 },
|
||||
Information = { filename = "Information.ogg", duration = 0.85 },
|
||||
Kilometers = { filename = "Kilometers.ogg", duration = 0.78 },
|
||||
Knots = { filename = "Knots.ogg", duration = 0.59 },
|
||||
Left = { filename = "Left.ogg", duration = 0.54 },
|
||||
MegaHertz = { filename = "MegaHertz.ogg", duration = 0.87 },
|
||||
Meters = { filename = "Meters.ogg", duration = 0.59 },
|
||||
MetersPerSecond = { filename = "MetersPerSecond.ogg", duration = 1.14 },
|
||||
Miles = { filename = "Miles.ogg", duration = 0.60 },
|
||||
MillimetersOfMercury = { filename = "MillimetersOfMercury.ogg", duration = 1.53 },
|
||||
Minus = { filename = "Minus.ogg", duration = 0.64 },
|
||||
N0 = { filename = "N-0.ogg", duration = 0.55 },
|
||||
N1 = { filename = "N-1.ogg", duration = 0.41 },
|
||||
N2 = { filename = "N-2.ogg", duration = 0.37 },
|
||||
N3 = { filename = "N-3.ogg", duration = 0.41 },
|
||||
N4 = { filename = "N-4.ogg", duration = 0.37 },
|
||||
N5 = { filename = "N-5.ogg", duration = 0.43 },
|
||||
N6 = { filename = "N-6.ogg", duration = 0.55 },
|
||||
N7 = { filename = "N-7.ogg", duration = 0.43 },
|
||||
N8 = { filename = "N-8.ogg", duration = 0.38 },
|
||||
N9 = { filename = "N-9.ogg", duration = 0.55 },
|
||||
NauticalMiles = { filename = "NauticalMiles.ogg", duration = 1.04 },
|
||||
None = { filename = "None.ogg", duration = 0.43 },
|
||||
QFE = { filename = "QFE.ogg", duration = 0.63 },
|
||||
QNH = { filename = "QNH.ogg", duration = 0.71 },
|
||||
Rain = { filename = "Rain.ogg", duration = 0.41 },
|
||||
Right = { filename = "Right.ogg", duration = 0.44 },
|
||||
Snow = { filename = "Snow.ogg", duration = 0.48 },
|
||||
SnowStorm = { filename = "SnowStorm.ogg", duration = 0.82 },
|
||||
StatuteMiles = { filename = "StatuteMiles.ogg", duration = 1.15 },
|
||||
SunriseAt = { filename = "SunriseAt.ogg", duration = 0.92 },
|
||||
SunsetAt = { filename = "SunsetAt.ogg", duration = 0.95 },
|
||||
Temperature = { filename = "Temperature.ogg", duration = 0.64 },
|
||||
Thousand = { filename = "Thousand.ogg", duration = 0.55 },
|
||||
ThunderStorm = { filename = "ThunderStorm.ogg", duration = 0.81 },
|
||||
TimeLocal = { filename = "TimeLocal.ogg", duration = 0.90 },
|
||||
TimeZulu = { filename = "TimeZulu.ogg", duration = 0.86 },
|
||||
TowerFrequency = { filename = "TowerFrequency.ogg", duration = 1.19 },
|
||||
Visibilty = { filename = "Visibility.ogg", duration = 0.79 },
|
||||
WeatherPhenomena = { filename = "WeatherPhenomena.ogg", duration = 1.07 },
|
||||
WindFrom = { filename = "WindFrom.ogg", duration = 0.60 },
|
||||
ActiveRunway = { filename = "ActiveRunway.ogg", duration = 0.85 },
|
||||
ActiveRunwayDeparture = { filename = "ActiveRunwayDeparture.ogg", duration = 1.50 },
|
||||
ActiveRunwayArrival = { filename = "ActiveRunwayArrival.ogg", duration = 1.38 },
|
||||
AdviceOnInitial = { filename = "AdviceOnInitial.ogg", duration = 2.98 },
|
||||
Airport = { filename = "Airport.ogg", duration = 0.55 },
|
||||
Altimeter = { filename = "Altimeter.ogg", duration = 0.91 },
|
||||
At = { filename = "At.ogg", duration = 0.32 },
|
||||
CloudBase = { filename = "CloudBase.ogg", duration = 0.69 },
|
||||
CloudCeiling = { filename = "CloudCeiling.ogg", duration = 0.53 },
|
||||
CloudsBroken = { filename = "CloudsBroken.ogg", duration = 0.81 },
|
||||
CloudsFew = { filename = "CloudsFew.ogg", duration = 0.74 },
|
||||
CloudsNo = { filename = "CloudsNo.ogg", duration = 0.69},
|
||||
CloudsNotAvailable = { filename = "CloudsNotAvailable.ogg", duration = 2.64 },
|
||||
CloudsOvercast = { filename = "CloudsOvercast.ogg", duration = 0.82 },
|
||||
CloudsScattered = { filename = "CloudsScattered.ogg", duration = 0.89 },
|
||||
Decimal = { filename = "Decimal.ogg", duration = 0.71 },
|
||||
DegreesCelsius = { filename = "DegreesCelsius.ogg", duration = 1.08 },
|
||||
DegreesFahrenheit = { filename = "DegreesFahrenheit.ogg", duration = 1.07 },
|
||||
DewPoint = { filename = "DewPoint.ogg", duration = 0.59 },
|
||||
Dust = { filename = "Dust.ogg", duration = 0.37 },
|
||||
Elevation = { filename = "Elevation.ogg", duration = 0.92 },
|
||||
EndOfInformation = { filename = "EndOfInformation.ogg", duration = 1.24 },
|
||||
Feet = { filename = "Feet.ogg", duration = 0.34 },
|
||||
Fog = { filename = "Fog.ogg", duration = 0.41 },
|
||||
Gusting = { filename = "Gusting.ogg", duration = 0.58 },
|
||||
HectoPascal = { filename = "HectoPascal.ogg", duration = 0.92 },
|
||||
Hundred = { filename = "Hundred.ogg", duration = 0.53 },
|
||||
ILSFrequency = { filename = "ILSFrequency.ogg", duration = 1.30 },
|
||||
InnerNDBFrequency = { filename = "InnerNDBFrequency.ogg", duration = 1.56 },
|
||||
OuterNDBFrequency = { filename = "OuterNDBFrequency.ogg", duration = 1.59 },
|
||||
RunwayLength = { filename = "RunwayLength.ogg", duration = 0.91 },
|
||||
VORFrequency = { filename = "VORFrequency.ogg", duration = 1.38 },
|
||||
TACANChannel = { filename = "TACANChannel.ogg", duration = 0.88 },
|
||||
PRMGChannel = { filename = "PRMGChannel.ogg", duration = 1.18 },
|
||||
RSBNChannel = { filename = "RSBNChannel.ogg", duration = 1.14 },
|
||||
Zulu = { filename = "Zulu.ogg", duration = 0.62 },
|
||||
InchesOfMercury = { filename = "InchesOfMercury.ogg", duration = 1.26 },
|
||||
Information = { filename = "Information.ogg", duration = 0.99 },
|
||||
InnerNDBFrequency = { filename = "InnerNDBFrequency.ogg", duration = 1.69 },
|
||||
Kilometers = { filename = "Kilometers.ogg", duration = 0.93 },
|
||||
Knots = { filename = "Knots.ogg", duration = 0.46 },
|
||||
Left = { filename = "Left.ogg", duration = 0.41 },
|
||||
MegaHertz = { filename = "MegaHertz.ogg", duration = 0.83 },
|
||||
Meters = { filename = "Meters.ogg", duration = 0.55 },
|
||||
MetersPerSecond = { filename = "MetersPerSecond.ogg", duration = 1.03 },
|
||||
Miles = { filename = "Miles.ogg", duration = 0.44 },
|
||||
MillimetersOfMercury = { filename = "MillimetersOfMercury.ogg", duration = 1.59 },
|
||||
Minus = { filename = "Minus.ogg", duration = 0.55 },
|
||||
N0 = { filename = "N-0.ogg", duration = 0.52 },
|
||||
N1 = { filename = "N-1.ogg", duration = 0.35 },
|
||||
N2 = { filename = "N-2.ogg", duration = 0.41 },
|
||||
N3 = { filename = "N-3.ogg", duration = 0.34 },
|
||||
N4 = { filename = "N-4.ogg", duration = 0.37 },
|
||||
N5 = { filename = "N-5.ogg", duration = 0.40 },
|
||||
N6 = { filename = "N-6.ogg", duration = 0.46 },
|
||||
N7 = { filename = "N-7.ogg", duration = 0.52 },
|
||||
N8 = { filename = "N-8.ogg", duration = 0.36 },
|
||||
N9 = { filename = "N-9.ogg", duration = 0.51 },
|
||||
NauticalMiles = { filename = "NauticalMiles.ogg", duration = 0.93 },
|
||||
None = { filename = "None.ogg", duration = 0.33 },
|
||||
OuterNDBFrequency = { filename = "OuterNDBFrequency.ogg", duration = 1.70 },
|
||||
PRMGChannel = { filename = "PRMGChannel.ogg", duration = 1.27 },
|
||||
QFE = { filename = "QFE.ogg", duration = 0.90 },
|
||||
QNH = { filename = "QNH.ogg", duration = 0.94 },
|
||||
Rain = { filename = "Rain.ogg", duration = 0.35 },
|
||||
Right = { filename = "Right.ogg", duration = 0.31 },
|
||||
RSBNChannel = { filename = "RSBNChannel.ogg", duration = 1.26 },
|
||||
RunwayLength = { filename = "RunwayLength.ogg", duration = 0.81 },
|
||||
Snow = { filename = "Snow.ogg", duration = 0.40 },
|
||||
SnowStorm = { filename = "SnowStorm.ogg", duration = 0.73 },
|
||||
StatuteMiles = { filename = "StatuteMiles.ogg", duration = 0.90 },
|
||||
SunriseAt = { filename = "SunriseAt.ogg", duration = 0.82 },
|
||||
SunsetAt = { filename = "SunsetAt.ogg", duration = 0.87 },
|
||||
TACANChannel = { filename = "TACANChannel.ogg", duration = 0.81 },
|
||||
Temperature = { filename = "Temperature.ogg", duration = 0.70 },
|
||||
Thousand = { filename = "Thousand.ogg", duration = 0.58 },
|
||||
ThunderStorm = { filename = "ThunderStorm.ogg", duration = 0.79 },
|
||||
TimeLocal = { filename = "TimeLocal.ogg", duration = 0.83 },
|
||||
TimeZulu = { filename = "TimeZulu.ogg", duration = 0.83 },
|
||||
TowerFrequency = { filename = "TowerFrequency.ogg", duration = 1.05 },
|
||||
Visibilty = { filename = "Visibility.ogg", duration = 1.16 },
|
||||
VORFrequency = { filename = "VORFrequency.ogg", duration = 1.28 },
|
||||
WeatherPhenomena = { filename = "WeatherPhenomena.ogg", duration = 1.09 },
|
||||
WindFrom = { filename = "WindFrom.ogg", duration = 0.63 },
|
||||
Zulu = { filename = "Zulu.ogg", duration = 0.51 },
|
||||
}
|
||||
|
||||
---
|
||||
@ -954,7 +970,7 @@ _ATIS = {}
|
||||
|
||||
--- ATIS class version.
|
||||
-- @field #string version
|
||||
ATIS.version = "1.0.0"
|
||||
ATIS.version = "1.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@ -2037,12 +2053,14 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
local sunrise = coord:GetSunrise()
|
||||
--self:I(sunrise)
|
||||
local SUNRISE = "no time"
|
||||
local NorthPolar = true
|
||||
if tostring(sunrise) ~= "N/S" and tostring(sunrise) ~= "N/R" then
|
||||
sunrise = UTILS.Split( sunrise, ":" )
|
||||
SUNRISE = string.format( "%s%s", sunrise[1], sunrise[2] )
|
||||
if self.useSRS then
|
||||
SUNRISE = string.format( "%s %s %s", sunrise[1], sunrise[2], hours )
|
||||
end
|
||||
NorthPolar = false
|
||||
end
|
||||
|
||||
local sunset = coord:GetSunset()
|
||||
@ -2054,6 +2072,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
if self.useSRS then
|
||||
SUNSET = string.format( "%s %s %s", sunset[1], sunset[2], hours )
|
||||
end
|
||||
NorthPolar = false
|
||||
end
|
||||
|
||||
---------------------------------
|
||||
@ -2080,34 +2099,32 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
---------------
|
||||
|
||||
-- Get mission weather info. Most of this is static.
|
||||
local clouds, visibility, turbulence, fog, dust, static = self:GetMissionWeather()
|
||||
|
||||
-- Check that fog is actually "thick" enough to reach the airport. If an airport is in the mountains, fog might not affect it as it is measured from sea level.
|
||||
if fog and fog.thickness < height + 25 then
|
||||
fog = nil
|
||||
end
|
||||
|
||||
-- Dust only up to 1500 ft = 457 m ASL.
|
||||
if dust and height + 25 > UTILS.FeetToMeters( 1500 ) then
|
||||
dust = nil
|
||||
end
|
||||
local clouds, visibility, turbulence, dustdens, static = self:GetMissionWeather()
|
||||
|
||||
local dust=false
|
||||
local fog=false
|
||||
|
||||
------------------
|
||||
--- Visibility ---
|
||||
------------------
|
||||
|
||||
-- Get min visibility.
|
||||
local visibilitymin = visibility
|
||||
|
||||
if fog then
|
||||
if fog.visibility < visibilitymin then
|
||||
visibilitymin = fog.visibility
|
||||
if dustdens then
|
||||
|
||||
-- Dust only up to 1500 ft = 457 m ASL.
|
||||
if UTILS.FeetToMeters( 1500 )> height+25 then
|
||||
dust=true
|
||||
visibility=math.min(visibility, dustdens)
|
||||
end
|
||||
end
|
||||
|
||||
if dust then
|
||||
if dust < visibilitymin then
|
||||
visibilitymin = dust
|
||||
|
||||
else -- As of DCS 2.9.10.3948 (December 2024), fog and dust are mutually exclusive!
|
||||
|
||||
-- Get current fog visibility and thickness
|
||||
local fvis=world.weather.getFogVisibilityDistance()
|
||||
local fheight=world.weather.getFogThickness()
|
||||
|
||||
if fvis>0 and fheight>height+25 then
|
||||
fog=true
|
||||
visibility=math.min(visibility, fvis)
|
||||
end
|
||||
end
|
||||
|
||||
@ -2115,7 +2132,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
|
||||
if self.metric then
|
||||
-- Visibility in km.
|
||||
local reportedviz = UTILS.Round( visibilitymin / 1000 )
|
||||
local reportedviz = UTILS.Round( visibility / 1000 )
|
||||
-- max reported visibility 9999 m
|
||||
if reportedviz > 10 then
|
||||
reportedviz = 10
|
||||
@ -2123,7 +2140,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
VISIBILITY = string.format( "%d", reportedviz )
|
||||
else
|
||||
-- max reported visibility 10 NM
|
||||
local reportedviz = UTILS.Round( UTILS.MetersToSM( visibilitymin ) )
|
||||
local reportedviz = UTILS.Round( UTILS.MetersToSM( visibility ) )
|
||||
if reportedviz > 10 then
|
||||
reportedviz = 10
|
||||
end
|
||||
@ -2395,7 +2412,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
local sunrise = self.gettext:GetEntry("SUNRISEAT",self.locale)
|
||||
--subtitle = string.format( "Sunrise at %s local time", SUNRISE )
|
||||
subtitle = string.format( sunrise, SUNRISE )
|
||||
if not self.useSRS then
|
||||
if not self.useSRS and NorthPolar == false then
|
||||
self:Transmission( self.Sound.SunriseAt, 0.5, subtitle )
|
||||
self.radioqueue:Number2Transmission( SUNRISE, nil, 0.2 )
|
||||
self:Transmission( self.Sound.TimeLocal, 0.2 )
|
||||
@ -2406,7 +2423,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
local sunset = self.gettext:GetEntry("SUNSETAT",self.locale)
|
||||
--subtitle = string.format( "Sunset at %s local time", SUNSET )
|
||||
subtitle = string.format( sunset, SUNSET )
|
||||
if not self.useSRS then
|
||||
if not self.useSRS and NorthPolar == false then
|
||||
self:Transmission( self.Sound.SunsetAt, 0.5, subtitle )
|
||||
self.radioqueue:Number2Transmission( SUNSET, nil, 0.5 )
|
||||
self:Transmission( self.Sound.TimeLocal, 0.2 )
|
||||
@ -2781,7 +2798,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
|
||||
end
|
||||
_RUNACT = subtitle
|
||||
alltext = alltext .. ";\n" .. subtitle
|
||||
--alltext = alltext .. ";\n" .. subtitle
|
||||
|
||||
-- Runway length.
|
||||
if self.rwylength then
|
||||
@ -3350,28 +3367,13 @@ function ATIS:GetMissionWeather()
|
||||
dust = weather.dust_density
|
||||
end
|
||||
|
||||
-- Fog
|
||||
--[[
|
||||
["enable_fog"] = false,
|
||||
["fog"] =
|
||||
{
|
||||
["thickness"] = 0,
|
||||
["visibility"] = 25,
|
||||
}, -- end of ["fog"]
|
||||
]]
|
||||
local fog = nil
|
||||
if weather.enable_fog == true then
|
||||
fog = weather.fog
|
||||
end
|
||||
|
||||
self:T( "FF weather:" )
|
||||
self:T( { clouds = clouds } )
|
||||
self:T( { visibility = visibility } )
|
||||
self:T( { turbulence = turbulence } )
|
||||
self:T( { fog = fog } )
|
||||
self:T( { dust = dust } )
|
||||
self:T( { static = static } )
|
||||
return clouds, visibility, turbulence, fog, dust, static
|
||||
return clouds, visibility, turbulence, dust, static
|
||||
end
|
||||
|
||||
--- Get thousands of a number.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -997,6 +997,8 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
||||
|
||||
-- Init status updates in 10 seconds.
|
||||
self:__Status(10)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
@ -963,6 +963,8 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
|
||||
-- Init status check
|
||||
self:__Status(1)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- On after Status event. Checks player status.
|
||||
|
||||
@ -72,7 +72,7 @@ end
|
||||
|
||||
--- Checks if a point is contained within the circle.
|
||||
-- @param #table point The point to check
|
||||
-- @return #bool True if the point is contained, false otherwise
|
||||
-- @return #boolean True if the point is contained, false otherwise
|
||||
function CIRCLE:ContainsPoint(point)
|
||||
if ((point.x - self.CenterVec2.x) ^ 2 + (point.y - self.CenterVec2.y) ^ 2) ^ 0.5 <= self.Radius then
|
||||
return true
|
||||
@ -226,6 +226,11 @@ end
|
||||
--- Returns a random Vec2 within the circle.
|
||||
-- @return #table The random Vec2
|
||||
function CIRCLE:GetRandomVec2()
|
||||
|
||||
math.random()
|
||||
math.random()
|
||||
math.random()
|
||||
|
||||
local angle = math.random() * 2 * math.pi
|
||||
|
||||
local rx = math.random(0, self.Radius) * math.cos(angle) + self.CenterVec2.x
|
||||
@ -237,6 +242,11 @@ end
|
||||
--- Returns a random Vec2 on the border of the circle.
|
||||
-- @return #table The random Vec2
|
||||
function CIRCLE:GetRandomVec2OnBorder()
|
||||
|
||||
math.random()
|
||||
math.random()
|
||||
math.random()
|
||||
|
||||
local angle = math.random() * 2 * math.pi
|
||||
|
||||
local rx = self.Radius * math.cos(angle) + self.CenterVec2.x
|
||||
|
||||
@ -352,6 +352,7 @@ end
|
||||
--- Returns a random Vec2 within the polygon. The Vec2 is weighted by the areas of the triangles that make up the polygon.
|
||||
-- @return #table The random Vec2
|
||||
function POLYGON:GetRandomVec2()
|
||||
|
||||
local weights = {}
|
||||
for _, triangle in pairs(self.Triangles) do
|
||||
weights[triangle] = triangle.SurfaceArea / self.SurfaceArea
|
||||
|
||||
@ -73,6 +73,11 @@ end
|
||||
-- @param #table points The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it
|
||||
-- @return #table The random Vec2
|
||||
function TRIANGLE:GetRandomVec2(points)
|
||||
|
||||
math.random()
|
||||
math.random()
|
||||
math.random()
|
||||
|
||||
points = points or self.Points
|
||||
local pt = {math.random(), math.random()}
|
||||
table.sort(pt)
|
||||
|
||||
@ -380,7 +380,8 @@ function RADIOQUEUE:Broadcast(transmission)
|
||||
self:T(self.lid..string.format("Broadcasting from aircraft %s", sender:GetName()))
|
||||
|
||||
|
||||
if not self.senderinit then
|
||||
--if not self.senderinit then
|
||||
-- TODO Seems to be a DCS bug - if I explode ANY unit in a group the BC assignment gets lost
|
||||
|
||||
-- Command to set the Frequency for the transmission.
|
||||
local commandFrequency={
|
||||
@ -394,7 +395,7 @@ function RADIOQUEUE:Broadcast(transmission)
|
||||
sender:SetCommand(commandFrequency)
|
||||
|
||||
self.senderinit=true
|
||||
end
|
||||
--end
|
||||
|
||||
-- Set subtitle only if duration>0 sec.
|
||||
local subtitle=nil
|
||||
|
||||
@ -52,6 +52,7 @@
|
||||
-- @field #table poptions Provider options. Each element is a data structure of type `MSRS.ProvierOptions`.
|
||||
-- @field #string provider Provider of TTS (win, gcloud, azure, amazon).
|
||||
-- @field #string backend Backend used as interface to SRS (MSRS.Backend.SRSEXE or MSRS.Backend.GRPC).
|
||||
-- @field #boolean UsePowerShell Use PowerShell to execute the command and not cmd.exe
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *It is a very sad thing that nowadays there is so little useless information.* - Oscar Wilde
|
||||
@ -256,15 +257,145 @@ MSRS = {
|
||||
ConfigFilePath = "Config\\",
|
||||
ConfigLoaded = false,
|
||||
poptions = {},
|
||||
UsePowerShell = false,
|
||||
}
|
||||
|
||||
--- MSRS class version.
|
||||
-- @field #string version
|
||||
MSRS.version="0.3.0"
|
||||
MSRS.version="0.3.3"
|
||||
|
||||
--- Voices
|
||||
-- @type MSRS.Voices
|
||||
MSRS.Voices = {
|
||||
Amazon = {
|
||||
Generative = {
|
||||
en_AU = {
|
||||
Olivia = "Olivia",
|
||||
},
|
||||
en_GB = {
|
||||
Amy = "Amy",
|
||||
},
|
||||
en_US = {
|
||||
Danielle = "Danielle",
|
||||
Joanna = "Joanna",
|
||||
Ruth = "Ruth",
|
||||
Stephen = "Stephen",
|
||||
},
|
||||
fr_FR = {
|
||||
["Léa"] = "Léa",
|
||||
["Rémi"] = "Rémi",
|
||||
},
|
||||
de_DE = {
|
||||
Vicki = "Vicki",
|
||||
Daniel = "Daniel",
|
||||
},
|
||||
it_IT = {
|
||||
Bianca = "Bianca",
|
||||
Adriano = "Adriano",
|
||||
},
|
||||
es_ES = {
|
||||
Lucia = "Lucia",
|
||||
Sergio = "Sergio",
|
||||
},
|
||||
},
|
||||
LongForm = {
|
||||
en_US = {
|
||||
Danielle = "Danielle",
|
||||
Gregory = "Gregory",
|
||||
Ivy = "Ivy",
|
||||
Ruth = "Ruth",
|
||||
Patrick = "Patrick",
|
||||
},
|
||||
es_ES = {
|
||||
Alba = "Alba",
|
||||
["Raúl"] = "Raúl",
|
||||
},
|
||||
},
|
||||
Neural = {
|
||||
en_AU = {
|
||||
Olivia = "Olivia",
|
||||
},
|
||||
en_GB = {
|
||||
Amy = "Amy",
|
||||
Emma = "Emma",
|
||||
Brian = "Brian",
|
||||
Arthur = "Arthur",
|
||||
},
|
||||
en_US = {
|
||||
Danielle = "Danielle",
|
||||
Gregory = "Gregory",
|
||||
Ivy = "Ivy",
|
||||
Joanna = "Joanna",
|
||||
Kendra = "Kendra",
|
||||
Kimberly = "Kimberly",
|
||||
Salli = "Salli",
|
||||
Joey = "Joey",
|
||||
Kevin = "Kevin",
|
||||
Ruth = "Ruth",
|
||||
Stephen = "Stephen",
|
||||
},
|
||||
fr_FR = {
|
||||
["Léa"] = "Léa",
|
||||
["Rémi"] = "Rémi",
|
||||
},
|
||||
de_DE = {
|
||||
Vicki = "Vicki",
|
||||
Daniel = "Daniel",
|
||||
},
|
||||
it_IT = {
|
||||
Bianca = "Bianca",
|
||||
Adriano = "Adriano",
|
||||
},
|
||||
es_ES = {
|
||||
Lucia = "Lucia",
|
||||
Sergio = "Sergio",
|
||||
},
|
||||
},
|
||||
Standard = {
|
||||
en_AU = {
|
||||
Nicole = "Nicole",
|
||||
Russel = "Russel",
|
||||
},
|
||||
en_GB = {
|
||||
Amy = "Amy",
|
||||
Emma = "Emma",
|
||||
Brian = "Brian",
|
||||
},
|
||||
en_IN = {
|
||||
Aditi = "Aditi",
|
||||
Raveena = "Raveena",
|
||||
},
|
||||
en_US = {
|
||||
Ivy = "Ivy",
|
||||
Joanna = "Joanna",
|
||||
Kendra = "Kendra",
|
||||
Kimberly = "Kimberly",
|
||||
Salli = "Salli",
|
||||
Joey = "Joey",
|
||||
Kevin = "Kevin",
|
||||
},
|
||||
fr_FR = {
|
||||
Celine = "Celine",
|
||||
["Léa"] = "Léa",
|
||||
Mathieu = "Mathieu",
|
||||
},
|
||||
de_DE = {
|
||||
Marlene = "Marlene",
|
||||
Vicki = "Vicki",
|
||||
Hans = "Hans",
|
||||
},
|
||||
it_IT = {
|
||||
Carla = "Carla",
|
||||
Bianca = "Bianca",
|
||||
Giorgio = "Giorgio",
|
||||
},
|
||||
es_ES = {
|
||||
Conchita = "Conchita",
|
||||
Lucia = "Lucia",
|
||||
Enrique = "Enrique",
|
||||
},
|
||||
},
|
||||
},
|
||||
Microsoft = { -- working ones if not using gRPC and MS
|
||||
["Hedda"] = "Microsoft Hedda Desktop", -- de-DE
|
||||
["Hazel"] = "Microsoft Hazel Desktop", -- en-GB
|
||||
@ -312,88 +443,254 @@ MSRS.Voices = {
|
||||
["en_AU_Standard_B"] = 'en-AU-Standard-B', -- [2] MALE
|
||||
["en_AU_Standard_C"] = 'en-AU-Standard-C', -- [3] FEMALE
|
||||
["en_AU_Standard_D"] = 'en-AU-Standard-D', -- [4] MALE
|
||||
["en_IN_Standard_A"] = 'en-IN-Standard-A', -- [5] FEMALE
|
||||
["en_IN_Standard_B"] = 'en-IN-Standard-B', -- [6] MALE
|
||||
["en_IN_Standard_C"] = 'en-IN-Standard-C', -- [7] MALE
|
||||
["en_IN_Standard_D"] = 'en-IN-Standard-D', -- [8] FEMALE
|
||||
["en_GB_Standard_A"] = 'en-GB-Standard-A', -- [9] FEMALE
|
||||
["en_GB_Standard_B"] = 'en-GB-Standard-B', -- [10] MALE
|
||||
["en_GB_Standard_C"] = 'en-GB-Standard-C', -- [11] FEMALE
|
||||
["en_GB_Standard_D"] = 'en-GB-Standard-D', -- [12] MALE
|
||||
["en_GB_Standard_F"] = 'en-GB-Standard-F', -- [13] FEMALE
|
||||
["en_US_Standard_A"] = 'en-US-Standard-A', -- [14] MALE
|
||||
["en_US_Standard_B"] = 'en-US-Standard-B', -- [15] MALE
|
||||
["en_US_Standard_C"] = 'en-US-Standard-C', -- [16] FEMALE
|
||||
["en_US_Standard_D"] = 'en-US-Standard-D', -- [17] MALE
|
||||
["en_US_Standard_E"] = 'en-US-Standard-E', -- [18] FEMALE
|
||||
["en_US_Standard_F"] = 'en-US-Standard-F', -- [19] FEMALE
|
||||
["en_US_Standard_G"] = 'en-US-Standard-G', -- [20] FEMALE
|
||||
["en_US_Standard_H"] = 'en-US-Standard-H', -- [21] FEMALE
|
||||
["en_US_Standard_I"] = 'en-US-Standard-I', -- [22] MALE
|
||||
["en_US_Standard_J"] = 'en-US-Standard-J', -- [23] MALE
|
||||
["fr_FR_Standard_A"] = "fr-FR-Standard-A", -- Female
|
||||
["fr_FR_Standard_B"] = "fr-FR-Standard-B", -- Male
|
||||
["fr_FR_Standard_C"] = "fr-FR-Standard-C", -- Female
|
||||
["fr_FR_Standard_D"] = "fr-FR-Standard-D", -- Male
|
||||
["fr_FR_Standard_E"] = "fr-FR-Standard-E", -- Female
|
||||
["de_DE_Standard_A"] = "de-DE-Standard-A", -- Female
|
||||
["de_DE_Standard_B"] = "de-DE-Standard-B", -- Male
|
||||
["de_DE_Standard_C"] = "de-DE-Standard-C", -- Female
|
||||
["de_DE_Standard_D"] = "de-DE-Standard-D", -- Male
|
||||
["de_DE_Standard_E"] = "de-DE-Standard-E", -- Male
|
||||
["de_DE_Standard_F"] = "de-DE-Standard-F", -- Female
|
||||
["es_ES_Standard_A"] = "es-ES-Standard-A", -- Female
|
||||
["es_ES_Standard_B"] = "es-ES-Standard-B", -- Male
|
||||
["es_ES_Standard_C"] = "es-ES-Standard-C", -- Female
|
||||
["es_ES_Standard_D"] = "es-ES-Standard-D", -- Female
|
||||
["it_IT_Standard_A"] = "it-IT-Standard-A", -- Female
|
||||
["it_IT_Standard_B"] = "it-IT-Standard-B", -- Female
|
||||
["it_IT_Standard_C"] = "it-IT-Standard-C", -- Male
|
||||
["it_IT_Standard_D"] = "it-IT-Standard-D", -- Male
|
||||
-- IN
|
||||
["en_IN_Standard_A"] = 'en-IN-Standard-A', -- Female
|
||||
["en_IN_Standard_B"] = 'en-IN-Standard-B', -- Male
|
||||
["en_IN_Standard_C"] = 'en-IN-Standard-C', -- Male
|
||||
["en_IN_Standard_D"] = 'en-IN-Standard-D', -- Female
|
||||
["en_IN_Standard_E"] = 'en-IN-Standard-E', -- Female
|
||||
["en_IN_Standard_F"] = 'en-IN-Standard-F', -- Male
|
||||
-- 2025 changes
|
||||
["en_GB_Standard_A"] = 'en-GB-Standard-A', -- Female
|
||||
["en_GB_Standard_B"] = 'en-GB-Standard-B', -- Male
|
||||
["en_GB_Standard_C"] = 'en-GB-Standard-C', -- Female
|
||||
["en_GB_Standard_D"] = 'en-GB-Standard-D', -- Male
|
||||
["en_GB_Standard_F"] = 'en-GB-Standard-F', -- Female
|
||||
["en_GB_Standard_N"] = 'en-GB-Standard-N', -- Female
|
||||
["en_GB_Standard_O"] = 'en-GB-Standard-O', -- Male
|
||||
-- US
|
||||
["en_US_Standard_A"] = 'en-US-Standard-A', -- Male
|
||||
["en_US_Standard_B"] = 'en-US-Standard-B', -- Male
|
||||
["en_US_Standard_C"] = 'en-US-Standard-C', -- Female
|
||||
["en_US_Standard_D"] = 'en-US-Standard-D', -- Male
|
||||
["en_US_Standard_E"] = 'en-US-Standard-E', -- Female
|
||||
["en_US_Standard_F"] = 'en-US-Standard-F', -- Female
|
||||
["en_US_Standard_G"] = 'en-US-Standard-G', -- Female
|
||||
["en_US_Standard_H"] = 'en-US-Standard-H', -- Female
|
||||
["en_US_Standard_I"] = 'en-US-Standard-I', -- Male
|
||||
["en_US_Standard_J"] = 'en-US-Standard-J', -- Male
|
||||
-- 2025 catalog changes
|
||||
["fr_FR_Standard_A"] = "fr-FR-Standard-F", -- Female
|
||||
["fr_FR_Standard_B"] = "fr-FR-Standard-G", -- Male
|
||||
["fr_FR_Standard_C"] = "fr-FR-Standard-F", -- Female
|
||||
["fr_FR_Standard_D"] = "fr-FR-Standard-G", -- Male
|
||||
["fr_FR_Standard_E"] = "fr-FR-Standard-F", -- Female
|
||||
["fr_FR_Standard_G"] = "fr-FR-Standard-G", -- Male
|
||||
["fr_FR_Standard_F"] = "fr-FR-Standard-F", -- Female
|
||||
-- 2025 catalog changes
|
||||
["de_DE_Standard_A"] = 'de-DE-Standard-A', -- Female
|
||||
["de_DE_Standard_B"] = 'de-DE-Standard-B', -- Male
|
||||
["de_DE_Standard_C"] = 'de-DE-Standard-C', -- Female
|
||||
["de_DE_Standard_D"] = 'de-DE-Standard-D', -- Male
|
||||
["de_DE_Standard_E"] = 'de-DE-Standard-E', -- Male
|
||||
["de_DE_Standard_F"] = 'de-DE-Standard-F', -- Female
|
||||
["de_DE_Standard_G"] = 'de-DE-Standard-G', -- Female
|
||||
["de_DE_Standard_H"] = 'de-DE-Standard-H', -- Male
|
||||
-- ES
|
||||
["es_ES_Standard_A"] = "es-ES-Standard-E", -- Female
|
||||
["es_ES_Standard_B"] = "es-ES-Standard-F", -- Male
|
||||
["es_ES_Standard_C"] = "es-ES-Standard-E", -- Female
|
||||
["es_ES_Standard_D"] = "es-ES-Standard-F", -- Male
|
||||
["es_ES_Standard_E"] = "es-ES-Standard-E", -- Female
|
||||
["es_ES_Standard_F"] = "es-ES-Standard-F", -- Male
|
||||
-- 2025 catalog changes
|
||||
["it_IT_Standard_A"] = "it-IT-Standard-E", -- Female
|
||||
["it_IT_Standard_B"] = "it-IT-Standard-E", -- Female
|
||||
["it_IT_Standard_C"] = "it-IT-Standard-F", -- Male
|
||||
["it_IT_Standard_D"] = "it-IT-Standard-F", -- Male
|
||||
["it_IT_Standard_E"] = "it-IT-Standard-E", -- Female
|
||||
["it_IT_Standard_F"] = "it-IT-Standard-F", -- Male
|
||||
},
|
||||
Wavenet = {
|
||||
["en_AU_Wavenet_A"] = 'en-AU-Wavenet-A', -- [1] FEMALE
|
||||
["en_AU_Wavenet_B"] = 'en-AU-Wavenet-B', -- [2] MALE
|
||||
["en_AU_Wavenet_C"] = 'en-AU-Wavenet-C', -- [3] FEMALE
|
||||
["en_AU_Wavenet_D"] = 'en-AU-Wavenet-D', -- [4] MALE
|
||||
["en_IN_Wavenet_A"] = 'en-IN-Wavenet-A', -- [5] FEMALE
|
||||
["en_IN_Wavenet_B"] = 'en-IN-Wavenet-B', -- [6] MALE
|
||||
["en_IN_Wavenet_C"] = 'en-IN-Wavenet-C', -- [7] MALE
|
||||
["en_IN_Wavenet_D"] = 'en-IN-Wavenet-D', -- [8] FEMALE
|
||||
["en_AU_Wavenet_A"] = 'en-AU-Wavenet-A', -- Female
|
||||
["en_AU_Wavenet_B"] = 'en-AU-Wavenet-B', -- Male
|
||||
["en_AU_Wavenet_C"] = 'en-AU-Wavenet-C', -- Female
|
||||
["en_AU_Wavenet_D"] = 'en-AU-Wavenet-D', -- Male
|
||||
-- IN
|
||||
["en_IN_Wavenet_A"] = 'en-IN-Wavenet-A', -- Female
|
||||
["en_IN_Wavenet_B"] = 'en-IN-Wavenet-B', -- Male
|
||||
["en_IN_Wavenet_C"] = 'en-IN-Wavenet-C', -- Male
|
||||
["en_IN_Wavenet_D"] = 'en-IN-Wavenet-D', -- Female
|
||||
["en_IN_Wavenet_E"] = 'en-IN-Wavenet-E', -- Female
|
||||
["en_IN_Wavenet_F"] = 'en-IN-Wavenet-F', -- Male
|
||||
-- 2025 changes
|
||||
["en_GB_Wavenet_A"] = 'en-GB-Wavenet-A', -- [9] FEMALE
|
||||
["en_GB_Wavenet_B"] = 'en-GB-Wavenet-B', -- [10] MALE
|
||||
["en_GB_Wavenet_C"] = 'en-GB-Wavenet-C', -- [11] FEMALE
|
||||
["en_GB_Wavenet_D"] = 'en-GB-Wavenet-D', -- [12] MALE
|
||||
["en_GB_Wavenet_F"] = 'en-GB-Wavenet-F', -- [13] FEMALE
|
||||
["en_US_Wavenet_A"] = 'en-US-Wavenet-A', -- [14] MALE
|
||||
["en_US_Wavenet_B"] = 'en-US-Wavenet-B', -- [15] MALE
|
||||
["en_US_Wavenet_C"] = 'en-US-Wavenet-C', -- [16] FEMALE
|
||||
["en_US_Wavenet_D"] = 'en-US-Wavenet-D', -- [17] MALE
|
||||
["en_US_Wavenet_E"] = 'en-US-Wavenet-E', -- [18] FEMALE
|
||||
["en_US_Wavenet_F"] = 'en-US-Wavenet-F', -- [19] FEMALE
|
||||
["en_US_Wavenet_G"] = 'en-US-Wavenet-G', -- [20] FEMALE
|
||||
["en_US_Wavenet_H"] = 'en-US-Wavenet-H', -- [21] FEMALE
|
||||
["en_US_Wavenet_I"] = 'en-US-Wavenet-I', -- [22] MALE
|
||||
["en_US_Wavenet_J"] = 'en-US-Wavenet-J', -- [23] MALE
|
||||
["fr_FR_Wavenet_A"] = "fr-FR-Wavenet-A", -- Female
|
||||
["fr_FR_Wavenet_B"] = "fr-FR-Wavenet-B", -- Male
|
||||
["fr_FR_Wavenet_C"] = "fr-FR-Wavenet-C", -- Female
|
||||
["fr_FR_Wavenet_D"] = "fr-FR-Wavenet-D", -- Male
|
||||
["fr_FR_Wavenet_E"] = "fr-FR-Wavenet-E", -- Female
|
||||
["de_DE_Wavenet_A"] = "de-DE-Wavenet-A", -- Female
|
||||
["de_DE_Wavenet_B"] = "de-DE-Wavenet-B", -- Male
|
||||
["de_DE_Wavenet_C"] = "de-DE-Wavenet-C", -- Female
|
||||
["de_DE_Wavenet_D"] = "de-DE-Wavenet-D", -- Male
|
||||
["de_DE_Wavenet_E"] = "de-DE-Wavenet-E", -- Male
|
||||
["de_DE_Wavenet_F"] = "de-DE-Wavenet-F", -- Female
|
||||
["es_ES_Wavenet_B"] = "es-ES-Wavenet-B", -- Male
|
||||
["es_ES_Wavenet_C"] = "es-ES-Wavenet-C", -- Female
|
||||
["es_ES_Wavenet_D"] = "es-ES-Wavenet-D", -- Female
|
||||
["it_IT_Wavenet_A"] = "it-IT-Wavenet-A", -- Female
|
||||
["it_IT_Wavenet_B"] = "it-IT-Wavenet-B", -- Female
|
||||
["it_IT_Wavenet_C"] = "it-IT-Wavenet-C", -- Male
|
||||
["it_IT_Wavenet_D"] = "it-IT-Wavenet-D", -- Male
|
||||
["en_GB_Wavenet_O"] = 'en-GB-Wavenet-O', -- [12] MALE
|
||||
["en_GB_Wavenet_N"] = 'en-GB-Wavenet-N', -- [13] FEMALE
|
||||
-- US
|
||||
["en_US_Wavenet_A"] = 'en-US-Wavenet-A', -- Male
|
||||
["en_US_Wavenet_B"] = 'en-US-Wavenet-B', -- Male
|
||||
["en_US_Wavenet_C"] = 'en-US-Wavenet-C', -- Female
|
||||
["en_US_Wavenet_D"] = 'en-US-Wavenet-D', -- Male
|
||||
["en_US_Wavenet_E"] = 'en-US-Wavenet-E', -- Female
|
||||
["en_US_Wavenet_F"] = 'en-US-Wavenet-F', -- Female
|
||||
["en_US_Wavenet_G"] = 'en-US-Wavenet-G', -- Female
|
||||
["en_US_Wavenet_H"] = 'en-US-Wavenet-H', -- Female
|
||||
["en_US_Wavenet_I"] = 'en-US-Wavenet-I', -- Male
|
||||
["en_US_Wavenet_J"] = 'en-US-Wavenet-J', -- Male
|
||||
-- 2025 catalog changes
|
||||
["fr_FR_Wavenet_A"] = "fr-FR-Wavenet-F", -- Female
|
||||
["fr_FR_Wavenet_B"] = "fr-FR-Wavenet-G", -- Male
|
||||
["fr_FR_Wavenet_C"] = "fr-FR-Wavenet-F", -- Female
|
||||
["fr_FR_Wavenet_D"] = "fr-FR-Wavenet-G", -- Male
|
||||
["fr_FR_Wavenet_E"] = "fr-FR-Wavenet-F", -- Female
|
||||
["fr_FR_Wavenet_G"] = "fr-FR-Wavenet-G", -- Male
|
||||
["fr_FR_Wavenet_F"] = "fr-FR-Wavenet-F", -- Female
|
||||
-- 2025 catalog changes
|
||||
["de_DE_Wavenet_A"] = 'de-DE-Wavenet-A', -- Female
|
||||
["de_DE_Wavenet_B"] = 'de-DE-Wavenet-B', -- Male
|
||||
["de_DE_Wavenet_C"] = 'de-DE-Wavenet-C', -- Female
|
||||
["de_DE_Wavenet_D"] = 'de-DE-Wavenet-D', -- Male
|
||||
["de_DE_Wavenet_E"] = 'de-DE-Wavenet-E', -- Male
|
||||
["de_DE_Wavenet_F"] = 'de-DE-Wavenet-F', -- Female
|
||||
["de_DE_Wavenet_G"] = 'de-DE-Wavenet-G', -- Female
|
||||
["de_DE_Wavenet_H"] = 'de-DE-Wavenet-H', -- Male
|
||||
-- ES
|
||||
["es_ES_Wavenet_B"] = "es-ES-Wavenet-E", -- Male
|
||||
["es_ES_Wavenet_C"] = "es-ES-Wavenet-F", -- Female
|
||||
["es_ES_Wavenet_D"] = "es-ES-Wavenet-E", -- Female
|
||||
["es_ES_Wavenet_E"] = "es-ES-Wavenet-E", -- Male
|
||||
["es_ES_Wavenet_F"] = "es-ES-Wavenet-F", -- Female
|
||||
-- 2025 catalog changes
|
||||
["it_IT_Wavenet_A"] = "it-IT-Wavenet-E", -- Female
|
||||
["it_IT_Wavenet_B"] = "it-IT-Wavenet-E", -- Female
|
||||
["it_IT_Wavenet_C"] = "it-IT-Wavenet-F", -- Male
|
||||
["it_IT_Wavenet_D"] = "it-IT-Wavenet-F", -- Male
|
||||
["it_IT_Wavenet_E"] = "it-IT-Wavenet-E", -- Female
|
||||
["it_IT_Wavenet_F"] = "it-IT-Wavenet-F", -- Male
|
||||
} ,
|
||||
Chirp3HD = {
|
||||
["en_GB_Chirp3_HD_Aoede"] = 'en-GB-Chirp3-HD-Aoede', -- Female
|
||||
["en_GB_Chirp3_HD_Charon"] = 'en-GB-Chirp3-HD-Charon', -- Male
|
||||
["en_GB_Chirp3_HD_Fenrir"] = 'en-GB-Chirp3-HD-Fenrir', -- Male
|
||||
["en_GB_Chirp3_HD_Kore"] = 'en-GB-Chirp3-HD-Kore', -- Female
|
||||
["en_GB_Chirp3_HD_Leda"] = 'en-GB-Chirp3-HD-Leda', -- Female
|
||||
["en_GB_Chirp3_HD_Orus"] = 'en-GB-Chirp3-HD-Orus', -- Male
|
||||
["en_GB_Chirp3_HD_Puck"] = 'en-GB-Chirp3-HD-Puck', -- Male
|
||||
["en_GB_Chirp3_HD_Zephyr"] = 'en-GB-Chirp3-HD-Zephyr', -- Female
|
||||
--["de_DE_Chirp3_HD_Aoede"] = 'de-DE-Chirp3-HD-Aoede', -- Female (Datenfehler im Original)
|
||||
["en_US_Chirp3_HD_Charon"] = 'en-US-Chirp3-HD-Charon', -- Male
|
||||
["en_US_Chirp3_HD_Fenrir"] = 'en-US-Chirp3-HD-Fenrir', -- Male
|
||||
["en_US_Chirp3_HD_Kore"] = 'en-US-Chirp3-HD-Kore', -- Female
|
||||
["en_US_Chirp3_HD_Leda"] = 'en-US-Chirp3-HD-Leda', -- Female
|
||||
["en_US_Chirp3_HD_Orus"] = 'en-US-Chirp3-HD-Orus', -- Male
|
||||
["en_US_Chirp3_HD_Puck"] = 'en-US-Chirp3-HD-Puck', -- Male
|
||||
--["de_DE_Chirp3_HD_Zephyr"] = 'de-DE-Chirp3-HD-Zephyr', -- Female (Datenfehler im Original)
|
||||
-- DE
|
||||
["de_DE_Chirp3_HD_Aoede"] = 'de-DE-Chirp3-HD-Aoede', -- Female
|
||||
["de_DE_Chirp3_HD_Charon"] = 'de-DE-Chirp3-HD-Charon', -- Male
|
||||
["de_DE_Chirp3_HD_Fenrir"] = 'de-DE-Chirp3-HD-Fenrir', -- Male
|
||||
["de_DE_Chirp3_HD_Kore"] = 'de-DE-Chirp3-HD-Kore', -- Female
|
||||
["de_DE_Chirp3_HD_Leda"] = 'de-DE-Chirp3-HD-Leda', -- Female
|
||||
["de_DE_Chirp3_HD_Orus"] = 'de-DE-Chirp3-HD-Orus', -- Male
|
||||
["de_DE_Chirp3_HD_Puck"] = 'de-DE-Chirp3-HD-Puck', -- Male
|
||||
["de_DE_Chirp3_HD_Zephyr"] = 'de-DE-Chirp3-HD-Zephyr', -- Female
|
||||
-- AU
|
||||
["en_AU_Chirp3_HD_Aoede"] = 'en-AU-Chirp3-HD-Aoede', -- Female
|
||||
["en_AU_Chirp3_HD_Charon"] = 'en-AU-Chirp3-HD-Charon', -- Male
|
||||
["en_AU_Chirp3_HD_Fenrir"] = 'en-AU-Chirp3-HD-Fenrir', -- Male
|
||||
["en_AU_Chirp3_HD_Kore"] = 'en-AU-Chirp3-HD-Kore', -- Female
|
||||
["en_AU_Chirp3_HD_Leda"] = 'en-AU-Chirp3-HD-Leda', -- Female
|
||||
["en_AU_Chirp3_HD_Orus"] = 'en-AU-Chirp3-HD-Orus', -- Male
|
||||
["en_AU_Chirp3_HD_Puck"] = 'en-AU-Chirp3-HD-Puck', -- Male
|
||||
["en_AU_Chirp3_HD_Zephyr"] = 'en-AU-Chirp3-HD-Zephyr', -- Female
|
||||
-- IN
|
||||
["en_IN_Chirp3_HD_Aoede"] = 'en-IN-Chirp3-HD-Aoede', -- Female
|
||||
["en_IN_Chirp3_HD_Charon"] = 'en-IN-Chirp3-HD-Charon', -- Male
|
||||
["en_IN_Chirp3_HD_Fenrir"] = 'en-IN-Chirp3-HD-Fenrir', -- Male
|
||||
["en_IN_Chirp3_HD_Kore"] = 'en-IN-Chirp3-HD-Kore', -- Female
|
||||
["en_IN_Chirp3_HD_Leda"] = 'en-IN-Chirp3-HD-Leda', -- Female
|
||||
["en_IN_Chirp3_HD_Orus"] = 'en-IN-Chirp3-HD-Orus', -- Male
|
||||
},
|
||||
ChirpHD = {
|
||||
["en_US_Chirp_HD_D"] = 'en-US-Chirp-HD-D', -- Male
|
||||
["en_US_Chirp_HD_F"] = 'en-US-Chirp-HD-F', -- Female
|
||||
["en_US_Chirp_HD_O"] = 'en-US-Chirp-HD-O', -- Female
|
||||
-- DE
|
||||
["de_DE_Chirp_HD_D"] = 'de-DE-Chirp-HD-D', -- Male
|
||||
["de_DE_Chirp_HD_F"] = 'de-DE-Chirp-HD-F', -- Female
|
||||
["de_DE_Chirp_HD_O"] = 'de-DE-Chirp-HD-O', -- Female
|
||||
-- AU
|
||||
["en_AU_Chirp_HD_D"] = 'en-AU-Chirp-HD-D', -- Male
|
||||
["en_AU_Chirp_HD_F"] = 'en-AU-Chirp-HD-F', -- Female
|
||||
["en_AU_Chirp_HD_O"] = 'en-AU-Chirp-HD-O', -- Female
|
||||
-- IN
|
||||
["en_IN_Chirp_HD_D"] = 'en-IN-Chirp-HD-D', -- Male
|
||||
["en_IN_Chirp_HD_F"] = 'en-IN-Chirp-HD-F', -- Female
|
||||
["en_IN_Chirp_HD_O"] = 'en-IN-Chirp-HD-O', -- Female
|
||||
},
|
||||
},
|
||||
Neural2 = {
|
||||
["en_GB_Neural2_A"] = 'en-GB-Neural2-A', -- Female
|
||||
["en_GB_Neural2_B"] = 'en-GB-Neural2-B', -- Male
|
||||
["en_GB_Neural2_C"] = 'en-GB-Neural2-C', -- Female
|
||||
["en_GB_Neural2_D"] = 'en-GB-Neural2-D', -- Male
|
||||
["en_GB_Neural2_F"] = 'en-GB-Neural2-F', -- Female
|
||||
["en_GB_Neural2_N"] = 'en-GB-Neural2-N', -- Female
|
||||
["en_GB_Neural2_O"] = 'en-GB-Neural2-O', -- Male
|
||||
-- US
|
||||
["en_US_Neural2_A"] = 'en-US-Neural2-A', -- Male
|
||||
["en_US_Neural2_C"] = 'en-US-Neural2-C', -- Female
|
||||
["en_US_Neural2_D"] = 'en-US-Neural2-D', -- Male
|
||||
["en_US_Neural2_E"] = 'en-US-Neural2-E', -- Female
|
||||
["en_US_Neural2_F"] = 'en-US-Neural2-F', -- Female
|
||||
["en_US_Neural2_G"] = 'en-US-Neural2-G', -- Female
|
||||
["en_US_Neural2_H"] = 'en-US-Neural2-H', -- Female
|
||||
["en_US_Neural2_I"] = 'en-US-Neural2-I', -- Male
|
||||
["en_US_Neural2_J"] = 'en-US-Neural2-J', -- Male
|
||||
-- DE
|
||||
["de_DE_Neural2_G"] = 'de-DE-Neural2-G', -- Female
|
||||
["de_DE_Neural2_H"] = 'de-DE-Neural2-H', -- Male
|
||||
-- AU
|
||||
["en_AU_Neural2_A"] = 'en-AU-Neural2-A', -- Female
|
||||
["en_AU_Neural2_B"] = 'en-AU-Neural2-B', -- Male
|
||||
["en_AU_Neural2_C"] = 'en-AU-Neural2-C', -- Female
|
||||
["en_AU_Neural2_D"] = 'en-AU-Neural2-D', -- Male
|
||||
-- IN
|
||||
["en_IN_Neural2_A"] = 'en-IN-Neural2-A', -- Female
|
||||
["en_IN_Neural2_B"] = 'en-IN-Neural2-B', -- Male
|
||||
["en_IN_Neural2_C"] = 'en-IN-Neural2-C', -- Male
|
||||
["en_IN_Neural2_D"] = 'en-IN-Neural2-D', -- Female
|
||||
},
|
||||
News = {
|
||||
["en_GB_News_G"] = 'en-GB-News-G', -- Female
|
||||
["en_GB_News_H"] = 'en-GB-News-H', -- Female
|
||||
["en_GB_News_I"] = 'en-GB-News-I', -- Female
|
||||
["en_GB_News_J"] = 'en-GB-News-J', -- Male
|
||||
["en_GB_News_K"] = 'en-GB-News-K', -- Male
|
||||
["en_GB_News_L"] = 'en-GB-News-L', -- Male
|
||||
["en_GB_News_M"] = 'en-GB-News-M', -- Male
|
||||
-- US
|
||||
["en_US_News_K"] = 'en-US-News-K', -- Female
|
||||
["en_US_News_L"] = 'en-US-News-L', -- Female
|
||||
["en_US_News_N"] = 'en-US-News-N', -- Male
|
||||
-- AU
|
||||
["en_AU_News_E"] = 'en-AU-News-E', -- Female
|
||||
["en_AU_News_F"] = 'en-AU-News-F', -- Female
|
||||
["en_AU_News_G"] = 'en-AU-News-G', -- Male
|
||||
},
|
||||
Casual = {
|
||||
["en_US_Casual_K"] = 'en-US-Casual-K', -- Male
|
||||
},
|
||||
Polyglot = {
|
||||
["en_US_Polyglot_1"] = 'en-US-Polyglot-1', -- Male
|
||||
["de_DE_Polyglot_1"] = 'de-DE-Polyglot-1', -- Male
|
||||
["en_AU_Polyglot_1"] = 'en-AU-Polyglot-1', -- Male
|
||||
},
|
||||
Studio = {
|
||||
-- Englisch (UK) - Studio
|
||||
["en_GB_Studio_B"] = 'en-GB-Studio-B', -- Male
|
||||
["en_GB_Studio_C"] = 'en-GB-Studio-C', -- Female
|
||||
-- Englisch (USA) - Studio
|
||||
["en_US_Studio_O"] = 'en-US-Studio-O', -- Female
|
||||
["en_US_Studio_Q"] = 'en-US-Studio-Q', -- Male
|
||||
-- DE
|
||||
["de_DE_Studio_B"] = 'de-DE-Studio-B', -- Male
|
||||
["de_DE_Studio_C"] = 'de-DE-Studio-C', -- Female
|
||||
},
|
||||
}
|
||||
|
||||
@ -473,7 +770,7 @@ end
|
||||
-- set the path to the exe file via @{#MSRS.SetPath}.
|
||||
--
|
||||
-- @param #MSRS self
|
||||
-- @param #string Path Path to SRS directory. Default `C:\\Program Files\\DCS-SimpleRadio-Standalone`.
|
||||
-- @param #string Path Path to SRS directory. Default `C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio`.
|
||||
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. Can also be given as a #table of multiple frequencies.
|
||||
-- @param #number Modulation Radio modulation: 0=AM (default), 1=FM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. Can also be given as a #table of multiple modulations.
|
||||
-- @param #string Backend Backend used: `MSRS.Backend.SRSEXE` (default) or `MSRS.Backend.GRPC`.
|
||||
@ -588,7 +885,7 @@ function MSRS:SetBackendSRSEXE()
|
||||
end
|
||||
|
||||
--- Set the default backend.
|
||||
-- @param #MSRS self
|
||||
-- @param #string Backend
|
||||
function MSRS.SetDefaultBackend(Backend)
|
||||
MSRS.backend=Backend or MSRS.Backend.SRSEXE
|
||||
end
|
||||
@ -608,13 +905,13 @@ end
|
||||
|
||||
--- Set path to SRS install directory. More precisely, path to where the `DCS-SR-ExternalAudio.exe` is located.
|
||||
-- @param #MSRS self
|
||||
-- @param #string Path Path to the directory, where the sound file is located. Default is `C:\\Program Files\\DCS-SimpleRadio-Standalone`.
|
||||
-- @param #string Path Path to the directory, where the sound file is located. Default is `C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio`.
|
||||
-- @return #MSRS self
|
||||
function MSRS:SetPath(Path)
|
||||
self:F( {Path=Path} )
|
||||
|
||||
-- Set path.
|
||||
self.path=Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||
self.path=Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
|
||||
|
||||
-- Remove (back)slashes.
|
||||
local n=1 ; local nmax=1000
|
||||
@ -944,7 +1241,7 @@ end
|
||||
-- - `MSRS.Provider.WINDOWS`: Microsoft Windows (default)
|
||||
-- - `MSRS.Provider.GOOGLE`: Google Cloud
|
||||
-- - `MSRS.Provider.AZURE`: Microsoft Azure (only with DCS-gRPC backend)
|
||||
-- - `MSRS.Provier.AMAZON`: Amazone Web Service (only with DCS-gRPC backend)
|
||||
-- - `MSRS.Provier.AMAZON`: Amazon Web Service (only with DCS-gRPC backend)
|
||||
--
|
||||
-- Note that all providers except Microsoft Windows need as additonal information the credentials of your account.
|
||||
--
|
||||
@ -1154,7 +1451,8 @@ function MSRS:PlaySoundFile(Soundfile, Delay)
|
||||
|
||||
-- Append file.
|
||||
command=command..' --file="'..tostring(soundfile)..'"'
|
||||
|
||||
command=string.gsub(command,"--ssml","-h")
|
||||
|
||||
-- Execute command.
|
||||
self:_ExecCommand(command)
|
||||
|
||||
@ -1375,20 +1673,25 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
|
||||
modus=modus:gsub("1", "FM")
|
||||
|
||||
-- Command.
|
||||
local pwsh = string.format('Start-Process -WindowStyle Hidden -WorkingDirectory \"%s\" -FilePath \"%s\" -ArgumentList \'-f "%s" -m "%s" -c %s -p %s -n "%s" -v "%.1f"', path, exe, freqs, modus, coal, port, label,volume )
|
||||
|
||||
local command=string.format('"%s\\%s" -f "%s" -m "%s" -c %s -p %s -n "%s" -v "%.1f"', path, exe, freqs, modus, coal, port, label,volume)
|
||||
|
||||
-- Set voice or gender/culture.
|
||||
if voice then
|
||||
if voice and self.UsePowerShell ~= true then
|
||||
-- Use a specific voice (no need for gender and/or culture.
|
||||
command=command..string.format(" --voice=\"%s\"", tostring(voice))
|
||||
pwsh=pwsh..string.format(" --voice=\"%s\"", tostring(voice))
|
||||
else
|
||||
-- Add gender.
|
||||
if gender and gender~="female" then
|
||||
command=command..string.format(" -g %s", tostring(gender))
|
||||
pwsh=pwsh..string.format(" -g %s", tostring(gender))
|
||||
end
|
||||
-- Add culture.
|
||||
if culture and culture~="en-GB" then
|
||||
command=command..string.format(" -l %s", tostring(culture))
|
||||
pwsh=pwsh..string.format(" -l %s", tostring(culture))
|
||||
end
|
||||
end
|
||||
|
||||
@ -1396,16 +1699,18 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
|
||||
if coordinate then
|
||||
local lat,lon,alt=self:_GetLatLongAlt(coordinate)
|
||||
command=command..string.format(" -L %.4f -O %.4f -A %d", lat, lon, alt)
|
||||
pwsh=pwsh..string.format(" -L %.4f -O %.4f -A %d", lat, lon, alt)
|
||||
end
|
||||
|
||||
-- Set provider options
|
||||
if self.provider==MSRS.Provider.GOOGLE then
|
||||
local pops=self:GetProviderOptions()
|
||||
command=command..string.format(' --ssml -G "%s"', pops.credentials)
|
||||
pwsh=pwsh..string.format(' --ssml -G "%s"', pops.credentials)
|
||||
elseif self.provider==MSRS.Provider.WINDOWS then
|
||||
-- Nothing to do.
|
||||
else
|
||||
self:E("ERROR: SRS only supports WINWOWS and GOOGLE as TTS providers! Use DCS-gRPC backend for other providers such as ")
|
||||
self:E("ERROR: SRS only supports WINDOWS and GOOGLE as TTS providers! Use DCS-gRPC backend for other providers such as AWS and Azure.")
|
||||
end
|
||||
|
||||
if not UTILS.FileExists(fullPath) then
|
||||
@ -1415,8 +1720,12 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
|
||||
|
||||
-- Debug output.
|
||||
self:T("MSRS command from _GetCommand="..command)
|
||||
|
||||
return command
|
||||
|
||||
if self.UsePowerShell == true then
|
||||
return pwsh
|
||||
else
|
||||
return command
|
||||
end
|
||||
end
|
||||
|
||||
--- Execute SRS command to play sound using the `DCS-SR-ExternalAudio.exe`.
|
||||
@ -1424,7 +1733,7 @@ end
|
||||
-- @param #string command Command to executer
|
||||
-- @return #number Return value of os.execute() command.
|
||||
function MSRS:_ExecCommand(command)
|
||||
self:F( {command=command} )
|
||||
self:T2( {command=command} )
|
||||
|
||||
-- Skip this function if _GetCommand was not able to find the executable
|
||||
if string.find(command, "CommandNotFound") then return 0 end
|
||||
@ -1432,7 +1741,13 @@ function MSRS:_ExecCommand(command)
|
||||
local batContent = command.." && exit"
|
||||
-- Create a tmp file.
|
||||
local filename=os.getenv('TMP').."\\MSRS-"..MSRS.uuid()..".bat"
|
||||
|
||||
|
||||
if self.UsePowerShell == true then
|
||||
filename=os.getenv('TMP').."\\MSRS-"..MSRS.uuid()..".ps1"
|
||||
batContent = command .. "\'"
|
||||
self:T({batContent=batContent})
|
||||
end
|
||||
|
||||
local script=io.open(filename, "w+")
|
||||
script:write(batContent)
|
||||
script:close()
|
||||
@ -1441,7 +1756,7 @@ function MSRS:_ExecCommand(command)
|
||||
self:T("MSRS batch content: "..batContent)
|
||||
|
||||
local res=nil
|
||||
if true then
|
||||
if self.UsePowerShell ~= true then
|
||||
|
||||
-- Create a tmp file.
|
||||
local filenvbs = os.getenv('TMP') .. "\\MSRS-"..MSRS.uuid()..".vbs"
|
||||
@ -1469,23 +1784,20 @@ function MSRS:_ExecCommand(command)
|
||||
timer.scheduleFunction(os.remove, filenvbs, timer.getTime()+1)
|
||||
self:T("MSRS vbs and batch file removed")
|
||||
|
||||
elseif false then
|
||||
|
||||
-- Create a tmp file.
|
||||
local filenvbs = os.getenv('TMP') .. "\\MSRS-"..MSRS.uuid()..".vbs"
|
||||
|
||||
-- VBS script
|
||||
local script = io.open(filenvbs, "w+")
|
||||
script:write(string.format('Set oShell = CreateObject ("Wscript.Shell")\n'))
|
||||
script:write(string.format('Dim strArgs\n'))
|
||||
script:write(string.format('strArgs = "cmd /c %s"\n', filename))
|
||||
script:write(string.format('oShell.Run strArgs, 0, false'))
|
||||
script:close()
|
||||
|
||||
local runvbs=string.format('cscript.exe //Nologo //B "%s"', filenvbs)
|
||||
elseif self.UsePowerShell == true then
|
||||
|
||||
local pwsh = string.format('start /min "" powershell.exe -ExecutionPolicy Unrestricted -WindowStyle Hidden -Command "%s"',filename)
|
||||
--env.info("[MSRS] TextToSpeech Command :\n" .. pwsh.."\n")
|
||||
|
||||
if string.len(pwsh) > 255 then
|
||||
self:E("[MSRS] - pwsh string too long")
|
||||
end
|
||||
|
||||
-- Play file in 0.01 seconds
|
||||
res=os.execute(runvbs)
|
||||
res=os.execute(pwsh)
|
||||
|
||||
-- Remove file in 1 second.
|
||||
timer.scheduleFunction(os.remove, filename, timer.getTime()+1)
|
||||
|
||||
else
|
||||
-- Play command.
|
||||
@ -1616,11 +1928,11 @@ function MSRS:_DCSgRPCtts(Text, Frequencies, Gender, Culture, Voice, Volume, Lab
|
||||
ssml=string.format("<voice%s%s>%s</voice>", gender, language, Text)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
for _,freq in pairs(Frequencies) do
|
||||
self:F("Calling GRPC.tts with the following parameter:")
|
||||
self:F({ssml=ssml, freq=freq, options=options})
|
||||
self:F(options.provider[provider])
|
||||
self:T("Calling GRPC.tts with the following parameter:")
|
||||
self:T({ssml=ssml, freq=freq, options=options})
|
||||
self:T(options.provider[provider])
|
||||
GRPC.tts(ssml, freq*1e6, options)
|
||||
end
|
||||
|
||||
@ -1643,7 +1955,7 @@ end
|
||||
--
|
||||
-- -- Moose MSRS default Config
|
||||
-- MSRS_Config = {
|
||||
-- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- Path to SRS install directory.
|
||||
-- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio", -- Path to SRS install directory.
|
||||
-- Port = 5002, -- Port of SRS server. Default 5002.
|
||||
-- Backend = "srsexe", -- Interface to SRS: "srsexe" or "grpc".
|
||||
-- Frequency = {127, 243}, -- Default frequences. Must be a table 1..n entries!
|
||||
@ -1663,7 +1975,7 @@ end
|
||||
-- -- Google Cloud
|
||||
-- gcloud = {
|
||||
-- voice = "en-GB-Standard-A", -- The Google Cloud voice to use (see https://cloud.google.com/text-to-speech/docs/voices).
|
||||
-- credentials="C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourfilename.json", -- Full path to credentials JSON file (only for SRS-TTS.exe backend)
|
||||
-- credentials="C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio\\yourfilename.json", -- Full path to credentials JSON file (only for SRS-TTS.exe backend)
|
||||
-- key="Your access Key", -- Google API access key (only for DCS-gRPC backend)
|
||||
-- },
|
||||
-- -- Amazon Web Service
|
||||
@ -1731,7 +2043,7 @@ function MSRS:LoadConfigFile(Path,Filename)
|
||||
|
||||
local Self = self or MSRS --#MSRS
|
||||
|
||||
Self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||
Self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
|
||||
Self.port = MSRS_Config.Port or 5002
|
||||
Self.backend = MSRS_Config.Backend or MSRS.Backend.SRSEXE
|
||||
Self.frequencies = MSRS_Config.Frequency or {127,243}
|
||||
@ -1942,7 +2254,7 @@ end
|
||||
-- @param Core.Point#COORDINATE coordinate Coordinate to be used
|
||||
-- @return #MSRSQUEUE.Transmission Radio transmission table.
|
||||
function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation, gender, culture, voice, volume, label,coordinate)
|
||||
|
||||
self:T({Text=text, Dur=duration, start=tstart, int=interval, sub=subgroups, subt=subtitle, sudb=subduration, F=frequency, M=modulation, G=gender, C=culture, V=voice, Vol=volume, L=label})
|
||||
if self.TransmitOnlyWithPlayers then
|
||||
if self.PlayerSet and self.PlayerSet:CountAlive() == 0 then
|
||||
return self
|
||||
@ -1982,7 +2294,7 @@ function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgr
|
||||
transmission.volume = volume or msrs.volume
|
||||
transmission.label = label or msrs.Label
|
||||
transmission.coordinate = coordinate or msrs.coordinate
|
||||
|
||||
|
||||
-- Add transmission to queue.
|
||||
self:AddTransmission(transmission)
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Create a SOUNDFILE object (mp3 or ogg) to be played via DCS or SRS transmissions
|
||||
-- * Create a SOUNDTEXT object for text-to-speech output vis SRS Simple-Text-To-Speech (STTS)
|
||||
-- * Create a SOUNDTEXT object for text-to-speech output vis SRS Simple-Text-To-Speech (MSRS)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
|
||||
@ -29,6 +29,8 @@
|
||||
|
||||
|
||||
--- Governs multiple missions, the tasking and the reporting.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Command centers govern missions, communicates the task assignments between human players of the coalition, and manages the menu flow.
|
||||
-- It can assign a random task to a player when requested.
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
-- The @{#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
|
||||
-- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 1.1) DETECTION_MANAGER constructor:
|
||||
-- -----------------------------------
|
||||
-- * @{#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
|
||||
|
||||
@ -27,6 +27,8 @@
|
||||
|
||||
--- Models goals to be achieved and can contain multiple tasks to be executed to achieve the goals.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- A mission contains multiple tasks and can be of different task types.
|
||||
-- These tasks need to be assigned to human players to be executed.
|
||||
--
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # 1) Tasking from a player perspective.
|
||||
--
|
||||
-- Tasking can be controlled by using the "other" menu in the radio menu of the player group.
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
---
|
||||
-- # TASKINFO class, extends @{Core.Base#BASE}
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ## The TASKINFO class implements the methods to contain information and display information of a task.
|
||||
--
|
||||
-- # Developer Note
|
||||
|
||||
@ -20,6 +20,9 @@ do -- TASK_A2A
|
||||
|
||||
--- Defines Air To Air tasks for a @{Core.Set} of Target Units,
|
||||
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The TASK_A2A is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
||||
--
|
||||
-- * **None**: Start of the process
|
||||
|
||||
@ -30,6 +30,8 @@ do -- TASK_A2A_DISPATCHER
|
||||
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
||||
|
||||
--- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Core.Set} of EWR installation groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
|
||||
@ -20,6 +20,9 @@ do -- TASK_A2G
|
||||
|
||||
--- The TASK_A2G class defines Air To Ground tasks for a @{Core.Set} of Target Units,
|
||||
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The TASK_A2G is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
||||
--
|
||||
-- * **None**: Start of the process
|
||||
|
||||
@ -33,6 +33,8 @@ do -- TASK_A2G_DISPATCHER
|
||||
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
||||
|
||||
--- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Functional.Detection} object.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- It uses the Tasking System within the MOOSE framework, which is a multi-player Tasking Orchestration system.
|
||||
-- It provides a truly dynamic battle environment for pilots and ground commanders to engage upon,
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ## Test Missions:
|
||||
--
|
||||
-- Test missions can be located on the main GITHUB site.
|
||||
@ -1176,7 +1178,7 @@ do -- TASK_CARGO
|
||||
end
|
||||
|
||||
|
||||
---@param Color Might be SMOKECOLOR.Blue, SMOKECOLOR.Red SMOKECOLOR.Orange, SMOKECOLOR.White or SMOKECOLOR.Green
|
||||
--@param Color Might be SMOKECOLOR.Blue, SMOKECOLOR.Red SMOKECOLOR.Orange, SMOKECOLOR.White or SMOKECOLOR.Green
|
||||
function TASK_CARGO:SetSmokeColor(SmokeColor)
|
||||
-- Makes sure Coloe is set
|
||||
if SmokeColor == nil then
|
||||
|
||||
@ -76,6 +76,8 @@ do -- TASK_CAPTURE_DISPATCHER
|
||||
|
||||
--- Implements the dynamic dispatching of capture zone tasks.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The **TASK_CAPTURE_DISPATCHER** allows you to setup various tasks for let human
|
||||
-- players capture zones in a co-operation effort.
|
||||
--
|
||||
|
||||
@ -20,6 +20,8 @@ do -- TASK_ZONE_GOAL
|
||||
|
||||
--- # TASK_ZONE_GOAL class, extends @{Tasking.Task#TASK}
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The TASK_ZONE_GOAL class defines the task to protect or capture a protection zone.
|
||||
-- The TASK_ZONE_GOAL is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
||||
--
|
||||
|
||||
@ -44,6 +44,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Please read through the @{Tasking.Task_CARGO} process to understand the mechanisms of tasking and cargo tasking and handling.
|
||||
--
|
||||
-- The cargo will be a downed pilot, which is located somwhere on the battlefield. Use the menus system and facilities to
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user