mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Compare commits
877 Commits
v0.4.3-alp
...
v1.0.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
119a6f620c | ||
|
|
3e22247f76 | ||
|
|
854bef15e0 | ||
|
|
aacf6d99bc | ||
|
|
a8595a97d8 | ||
|
|
c630fe3045 | ||
|
|
05c7d8166b | ||
|
|
1d3d8ca705 | ||
|
|
97a11d6873 | ||
|
|
15e23564c2 | ||
|
|
42782c60a4 | ||
|
|
62b2b13d75 | ||
|
|
8bf2048d4d | ||
|
|
0fee5c8e7f | ||
|
|
b5e47fdbe6 | ||
|
|
c85e923899 | ||
|
|
a897401975 | ||
|
|
2f43a84224 | ||
|
|
274c16851e | ||
|
|
e77356cb61 | ||
|
|
f4e77b1f5b | ||
|
|
95247062a3 | ||
|
|
959b083a60 | ||
|
|
395409ecae | ||
|
|
5a2b050104 | ||
|
|
732b837a46 | ||
|
|
d60d2e78ef | ||
|
|
a15d2e2ec7 | ||
|
|
df1839cee0 | ||
|
|
1b4d3dd832 | ||
|
|
0e414850bd | ||
|
|
40e984982b | ||
|
|
d7c278b034 | ||
|
|
4e679344d0 | ||
|
|
b0ab0ae8cf | ||
|
|
6edcd8a5ce | ||
|
|
aa0cca67a1 | ||
|
|
c477dcd065 | ||
|
|
6db4455d5a | ||
|
|
54bf19d410 | ||
|
|
52833cadee | ||
|
|
6a45bc9e79 | ||
|
|
88d17d1cb3 | ||
|
|
8c27fdb53c | ||
|
|
e7777a2a48 | ||
|
|
fa4a0ccecb | ||
|
|
b54aa45377 | ||
|
|
eecdcad8e7 | ||
|
|
d68ac6cf2b | ||
|
|
e39b6b5eea | ||
|
|
4eb1b3ef6d | ||
|
|
4204a4b150 | ||
|
|
b64d336922 | ||
|
|
19c1ae82a2 | ||
|
|
61dc9c8b31 | ||
|
|
d078105eb7 | ||
|
|
7ee9946f49 | ||
|
|
5507bca68d | ||
|
|
535b95242c | ||
|
|
e40b79d2c4 | ||
|
|
ecd0581942 | ||
|
|
4f7c3988a0 | ||
|
|
5b7e63b02d | ||
|
|
ef99c21380 | ||
|
|
e0ad679b57 | ||
|
|
61fb80d67f | ||
|
|
a9a0332465 | ||
|
|
4494a5ccbb | ||
|
|
f0c4b10084 | ||
|
|
0bdf362174 | ||
|
|
a53cca8dda | ||
|
|
9aad81588a | ||
|
|
5ba1498802 | ||
|
|
539b183da8 | ||
|
|
396c061a3e | ||
|
|
8c7f6abb1c | ||
|
|
5cc42dd9cf | ||
|
|
f52b5f419e | ||
|
|
3b38ca5920 | ||
|
|
86cfb4fb2f | ||
|
|
166631d618 | ||
|
|
013546a45b | ||
|
|
a2c8563adf | ||
|
|
0c8de2dcf3 | ||
|
|
4f3491062b | ||
|
|
cc8c25a283 | ||
|
|
70740233a9 | ||
|
|
f2d4f0b0ca | ||
|
|
153ca01b96 | ||
|
|
f667410a56 | ||
|
|
f13545eae9 | ||
|
|
7ee24b1c7c | ||
|
|
29784310fc | ||
|
|
3427fcea7e | ||
|
|
c99b5ed19f | ||
|
|
2118ded496 | ||
|
|
4401261446 | ||
|
|
a6ec3a8cd0 | ||
|
|
6e6da64c51 | ||
|
|
a84e190548 | ||
|
|
e0238c2680 | ||
|
|
a60f2e7b62 | ||
|
|
4782596e3c | ||
|
|
832568aa00 | ||
|
|
05e0cc393a | ||
|
|
c74258e3ad | ||
|
|
2e1c3ec4b9 | ||
|
|
9a571132c8 | ||
|
|
acb55044d1 | ||
|
|
14679bd7d8 | ||
|
|
3c9af59051 | ||
|
|
8390a25c50 | ||
|
|
97b277edda | ||
|
|
462fa53c80 | ||
|
|
945c45803b | ||
|
|
20917da437 | ||
|
|
cd25509d3d | ||
|
|
4c3f80d7d7 | ||
|
|
fac32476d4 | ||
|
|
3fa88f3cdf | ||
|
|
46135f7ae0 | ||
|
|
f6e9503045 | ||
|
|
39c28ffb04 | ||
|
|
6373fd300d | ||
|
|
04f281db56 | ||
|
|
5f2fb60e1f | ||
|
|
4efd48c4b9 | ||
|
|
fb6ac40af8 | ||
|
|
9daa683b42 | ||
|
|
baffc9af49 | ||
|
|
bc6c70928f | ||
|
|
9e1503c106 | ||
|
|
57a700d2d2 | ||
|
|
5ca6c97cbe | ||
|
|
55f3bd5adb | ||
|
|
bf7c4beccd | ||
|
|
14d44babe7 | ||
|
|
30a90a96d8 | ||
|
|
c621b5dd85 | ||
|
|
63bdf44e17 | ||
|
|
029decf969 | ||
|
|
b5c7eaf36e | ||
|
|
99de17a858 | ||
|
|
5765ade7f8 | ||
|
|
59a8fba14d | ||
|
|
965b67b8ab | ||
|
|
0ef3abbffa | ||
|
|
2124e9cd42 | ||
|
|
2f1a0ad7d3 | ||
|
|
24e6c219f5 | ||
|
|
daec6dab5b | ||
|
|
3708d4150c | ||
|
|
11518485de | ||
|
|
29118e1ea1 | ||
|
|
aa5b62c1d2 | ||
|
|
f320cb122c | ||
|
|
bb7738724f | ||
|
|
df7eebed39 | ||
|
|
21040da195 | ||
|
|
be625fdca9 | ||
|
|
7ee3fb883b | ||
|
|
c2f6edfd74 | ||
|
|
4f5023b45c | ||
|
|
f0ab43d320 | ||
|
|
d2e803ab82 | ||
|
|
ca45b8b906 | ||
|
|
ec020f7b5d | ||
|
|
f2161da162 | ||
|
|
613aed2d2b | ||
|
|
1d38bd6fea | ||
|
|
6f7b251094 | ||
|
|
a9d873a05f | ||
|
|
05f98b2738 | ||
|
|
1568c65492 | ||
|
|
4a5c4ed7d7 | ||
|
|
ff7385cf49 | ||
|
|
a0de159234 | ||
|
|
d56a95cfa3 | ||
|
|
497f718e4b | ||
|
|
9942ff476b | ||
|
|
c042d2b6f5 | ||
|
|
b9201d583c | ||
|
|
3f67125f20 | ||
|
|
4f72f10642 | ||
|
|
89fb0a9da1 | ||
|
|
0e9b249bba | ||
|
|
0f0ba4c725 | ||
|
|
5542109daf | ||
|
|
ec91b597c8 | ||
|
|
d0f85ae977 | ||
|
|
7d6930fba9 | ||
|
|
2232a114b7 | ||
|
|
33ce537993 | ||
|
|
1ab8e9a16f | ||
|
|
73b1714191 | ||
|
|
cb793e9d0f | ||
|
|
7686a60bfd | ||
|
|
38027b6ff3 | ||
|
|
a512b0e405 | ||
|
|
46fb6a98d5 | ||
|
|
1a8a19ae5c | ||
|
|
8865ded4bd | ||
|
|
7adfe9cce4 | ||
|
|
85e5a6a309 | ||
|
|
d681d3cee0 | ||
|
|
c5650ba29a | ||
|
|
ef0a2d2ddc | ||
|
|
f143e8d874 | ||
|
|
89c1660988 | ||
|
|
4e7c8ef856 | ||
|
|
8024db9579 | ||
|
|
a0634a7f99 | ||
|
|
7bf6c1bb23 | ||
|
|
a62ae4e21e | ||
|
|
6c466a8bb8 | ||
|
|
36f828acb1 | ||
|
|
046e096b9e | ||
|
|
82df3cb316 | ||
|
|
1ba16f82e7 | ||
|
|
72c6bb0086 | ||
|
|
8bb4334187 | ||
|
|
59a9069d4b | ||
|
|
ba534f1786 | ||
|
|
72bb54bde0 | ||
|
|
cb3f46303c | ||
|
|
57f021f995 | ||
|
|
bf4b2272e4 | ||
|
|
31999ec00c | ||
|
|
086b6736b0 | ||
|
|
bf93b8e90a | ||
|
|
4d6bd6c6e9 | ||
|
|
c9dc5eb2f5 | ||
|
|
5fdb704d68 | ||
|
|
6d18e25232 | ||
|
|
7391006a2f | ||
|
|
9207585f5b | ||
|
|
cb53da3a71 | ||
|
|
d2ac5aeff8 | ||
|
|
b646087026 | ||
|
|
82e60cd2cf | ||
|
|
9d46a1c73f | ||
|
|
955057183d | ||
|
|
0396d6bf9c | ||
|
|
ee1d89007c | ||
|
|
4245927a6c | ||
|
|
f585828936 | ||
|
|
7450c9e506 | ||
|
|
d957cd6655 | ||
|
|
ef91f840ae | ||
|
|
17c74fbe91 | ||
|
|
17a7a1889e | ||
|
|
24ed96b348 | ||
|
|
15e8c9e791 | ||
|
|
de14f6c738 | ||
|
|
92b1a46e8a | ||
|
|
cbaadb6fc9 | ||
|
|
44295673dc | ||
|
|
8bf0f403e2 | ||
|
|
917a0d10e5 | ||
|
|
9c65411733 | ||
|
|
6c315d89e1 | ||
|
|
b5f1a459c2 | ||
|
|
6b12000979 | ||
|
|
1aec7f8081 | ||
|
|
5f0e96e2e6 | ||
|
|
678a8585a9 | ||
|
|
e632e379b6 | ||
|
|
1a7d2b5028 | ||
|
|
ce28d49510 | ||
|
|
0ac632cc9b | ||
|
|
47e4757b6e | ||
|
|
d21ee2a7b6 | ||
|
|
0cec61afea | ||
|
|
ff04364178 | ||
|
|
0cf2733d55 | ||
|
|
f5319ed654 | ||
|
|
cfef9f4bc4 | ||
|
|
6abf7f059a | ||
|
|
c0c1ff6e17 | ||
|
|
856dba83a5 | ||
|
|
2f37916595 | ||
|
|
f36a29570b | ||
|
|
62a3719163 | ||
|
|
e9511e9233 | ||
|
|
51cf15b8cc | ||
|
|
278d0bdd3c | ||
|
|
0a07f85fcf | ||
|
|
7face05e12 | ||
|
|
22ad5d5972 | ||
|
|
2e194d557a | ||
|
|
1a76df2056 | ||
|
|
787bf13f3c | ||
|
|
10f1c6a862 | ||
|
|
0366cc38e2 | ||
|
|
603018d1ef | ||
|
|
66ae06056b | ||
|
|
17486ab40c | ||
|
|
6cae91b06f | ||
|
|
9c055e0d71 | ||
|
|
db4aeca47d | ||
|
|
c29a368e5a | ||
|
|
dbe2442bb7 | ||
|
|
2108fc4b26 | ||
|
|
48f962ca4b | ||
|
|
e80a5e8ca1 | ||
|
|
fb2ecc75eb | ||
|
|
ee95291418 | ||
|
|
46796fce13 | ||
|
|
ee08f57abe | ||
|
|
eb86d8dfca | ||
|
|
c75e20e58f | ||
|
|
2c403a9283 | ||
|
|
27c78d6a67 | ||
|
|
e0d33760e0 | ||
|
|
2d339d7161 | ||
|
|
243f58ecf3 | ||
|
|
378dbfc085 | ||
|
|
cee6839b5d | ||
|
|
f1a836c222 | ||
|
|
cbf4b56ecb | ||
|
|
e2e3da6a0f | ||
|
|
3a96808aa5 | ||
|
|
d1ccccae18 | ||
|
|
d31242124f | ||
|
|
8c4996f466 | ||
|
|
59b89dc638 | ||
|
|
f54ac5c3d8 | ||
|
|
666b3e0383 | ||
|
|
d8893e21a1 | ||
|
|
5391b567b9 | ||
|
|
ad7ea014f2 | ||
|
|
ceb00a239f | ||
|
|
81ab1aa05d | ||
|
|
7bf232f146 | ||
|
|
3f07271931 | ||
|
|
1c30bb006b | ||
|
|
34594ac836 | ||
|
|
cee58800e1 | ||
|
|
ab3b487024 | ||
|
|
91b393eb35 | ||
|
|
edb4ddc287 | ||
|
|
f9fd5caa9f | ||
|
|
d5653a9b1d | ||
|
|
ec5ff1bf0c | ||
|
|
41912d1057 | ||
|
|
228452fd17 | ||
|
|
484d3dd28f | ||
|
|
a52e7e7b1a | ||
|
|
92a08f6278 | ||
|
|
8e3da65433 | ||
|
|
3f625c03b9 | ||
|
|
4423d5f3d5 | ||
|
|
d0fc286c43 | ||
|
|
b5443ab0a8 | ||
|
|
e6c34306c9 | ||
|
|
532a83fe91 | ||
|
|
293b928764 | ||
|
|
38d62df75d | ||
|
|
fbd42ade6e | ||
|
|
9af1cffe08 | ||
|
|
b0d92906e5 | ||
|
|
0329e27713 | ||
|
|
2d39862b1b | ||
|
|
5c1782ec7f | ||
|
|
6c6117aee3 | ||
|
|
1798e62315 | ||
|
|
2b2ed76aa3 | ||
|
|
38d72a5cd0 | ||
|
|
14ec4a8610 | ||
|
|
bdc7a5bb46 | ||
|
|
131f30405c | ||
|
|
dbf21e0af9 | ||
|
|
9094f8fdc6 | ||
|
|
aa0b0a585c | ||
|
|
ad61037452 | ||
|
|
66ed1a99e0 | ||
|
|
d7dc5769a8 | ||
|
|
b0ee653bff | ||
|
|
5a950e22ce | ||
|
|
0459d5c625 | ||
|
|
43d28ebe19 | ||
|
|
187b9be57a | ||
|
|
564a650403 | ||
|
|
0e403e8b74 | ||
|
|
840cdd9049 | ||
|
|
e5e7e9be14 | ||
|
|
e677968ba7 | ||
|
|
d24b955d52 | ||
|
|
48860ff514 | ||
|
|
0e78b7559b | ||
|
|
25edfc45e5 | ||
|
|
885825e5cc | ||
|
|
344413ae74 | ||
|
|
fa0643987b | ||
|
|
dcff462b32 | ||
|
|
fa04e5f8bb | ||
|
|
c8d5f9ce0e | ||
|
|
55642a89b1 | ||
|
|
f305aa3929 | ||
|
|
47ee88c339 | ||
|
|
022e041f68 | ||
|
|
0cc53890c1 | ||
|
|
e37f7a4977 | ||
|
|
8d03c6a767 | ||
|
|
e29fdfd8c7 | ||
|
|
af619c3687 | ||
|
|
6afb6682ea | ||
|
|
9c2c7f45c6 | ||
|
|
7fbc19e90a | ||
|
|
8f2f73dc0e | ||
|
|
24a1681337 | ||
|
|
304e8ba3a0 | ||
|
|
45b840fa72 | ||
|
|
82704f042b | ||
|
|
87d71da55e | ||
|
|
71cf7c67f7 | ||
|
|
62142ed976 | ||
|
|
f56bd514dc | ||
|
|
e30f161d1d | ||
|
|
720bfb3118 | ||
|
|
4100a3cc67 | ||
|
|
942993ff6d | ||
|
|
fbf435c799 | ||
|
|
8fdb0d82e8 | ||
|
|
dcbebab61b | ||
|
|
7b10afae43 | ||
|
|
81d8a88abd | ||
|
|
cb14158a0f | ||
|
|
38fc60352a | ||
|
|
3748f0d6e3 | ||
|
|
edd626d5e5 | ||
|
|
f785e75686 | ||
|
|
9a46ed70b7 | ||
|
|
532c09a815 | ||
|
|
e430d38c63 | ||
|
|
289b36de6d | ||
|
|
7e01f40e5c | ||
|
|
cac4bb5f13 | ||
|
|
c8bb041887 | ||
|
|
9302c5c6d1 | ||
|
|
84a3313f2c | ||
|
|
1eb3beeb2e | ||
|
|
d0e6ef8c6c | ||
|
|
5da1df7e20 | ||
|
|
16fa6d9805 | ||
|
|
0ca7766689 | ||
|
|
4342575418 | ||
|
|
4cdb73a60d | ||
|
|
a23c53bcb8 | ||
|
|
19ac4f92e0 | ||
|
|
0b8f48b4fd | ||
|
|
d2fa94a6cb | ||
|
|
da1c674911 | ||
|
|
7184bc1eb2 | ||
|
|
37f30a0f1a | ||
|
|
04f4b3e78a | ||
|
|
dbdc162fae | ||
|
|
563f673fb3 | ||
|
|
423e799a82 | ||
|
|
4734b89414 | ||
|
|
6f708e7733 | ||
|
|
f0c3f95189 | ||
|
|
93ca0e3f22 | ||
|
|
d94432636f | ||
|
|
60fca35d80 | ||
|
|
db71462d1c | ||
|
|
86f522176a | ||
|
|
94ee71c48f | ||
|
|
fda0b21fb0 | ||
|
|
775148cec8 | ||
|
|
f2dc4a1a00 | ||
|
|
eda5723a3c | ||
|
|
b044d9a6c0 | ||
|
|
125d5396b9 | ||
|
|
17b8b35a43 | ||
|
|
4bd017e3c7 | ||
|
|
37447a7fd3 | ||
|
|
1ed1dec65e | ||
|
|
5e2e465813 | ||
|
|
335655406e | ||
|
|
bf12d6330c | ||
|
|
3cca3187ad | ||
|
|
f4388a2cff | ||
|
|
7cf5d324eb | ||
|
|
ec9ef2b0fb | ||
|
|
6c852d93a9 | ||
|
|
290067932e | ||
|
|
4aa3a43604 | ||
|
|
3c33696452 | ||
|
|
3ea1ab8f30 | ||
|
|
76801f773d | ||
|
|
de7eeec94a | ||
|
|
0723a3ab95 | ||
|
|
8ef48ad977 | ||
|
|
ed24d1af60 | ||
|
|
e3dffb8245 | ||
|
|
74310a5ad3 | ||
|
|
a2223165e8 | ||
|
|
a879761dc2 | ||
|
|
124b909aa4 | ||
|
|
858e9eb066 | ||
|
|
7415e0cb97 | ||
|
|
915020ddc3 | ||
|
|
95915489b2 | ||
|
|
3e39c3351a | ||
|
|
244d32e7d2 | ||
|
|
16a79827b7 | ||
|
|
bd6a36e9ea | ||
|
|
771695af59 | ||
|
|
e811c7bd46 | ||
|
|
20f99c287f | ||
|
|
f464c9ae76 | ||
|
|
15ccb3dc04 | ||
|
|
defe40d48f | ||
|
|
0f2622e821 | ||
|
|
b442d238cd | ||
|
|
00f2a3c19d | ||
|
|
dcbfdf8666 | ||
|
|
6e84423032 | ||
|
|
912ab75a96 | ||
|
|
1022fc2f0c | ||
|
|
65edce855b | ||
|
|
0ba05d5795 | ||
|
|
1b17e17290 | ||
|
|
87957df1fb | ||
|
|
d3f8d4eff7 | ||
|
|
3ffeed3b39 | ||
|
|
4197e4402c | ||
|
|
1cfe6f5583 | ||
|
|
ad5cb83abf | ||
|
|
f4a4882dbc | ||
|
|
ecb2cf182a | ||
|
|
6aea839e04 | ||
|
|
e20d2fa95a | ||
|
|
806d0cc52f | ||
|
|
2a2baaf324 | ||
|
|
74989ec015 | ||
|
|
31af3a53ce | ||
|
|
361d51b55d | ||
|
|
a12c09eba5 | ||
|
|
bcfe0653bd | ||
|
|
c43bc763f3 | ||
|
|
85325c17ac | ||
|
|
178706f8de | ||
|
|
51defbb8b2 | ||
|
|
84cf9aa27a | ||
|
|
a66098e080 | ||
|
|
283b9e682e | ||
|
|
8b5956e76b | ||
|
|
017a89b945 | ||
|
|
5bc685182b | ||
|
|
f47fc2fb19 | ||
|
|
11d6f25606 | ||
|
|
331692e3d3 | ||
|
|
7483225e0d | ||
|
|
f00df5ca3f | ||
|
|
22ae882032 | ||
|
|
fbab82e4de | ||
|
|
ca81d1c4ce | ||
|
|
a1884ab19f | ||
|
|
8905cd5e85 | ||
|
|
8d5ed33ad8 | ||
|
|
b747752b76 | ||
|
|
4e13daa270 | ||
|
|
c00096bd9a | ||
|
|
210c1fbecf | ||
|
|
4a54011aac | ||
|
|
b89c5142b6 | ||
|
|
0421f6b8fe | ||
|
|
0c50141be6 | ||
|
|
a71b8806e7 | ||
|
|
e0a27c574f | ||
|
|
8d7a49a31f | ||
|
|
25e2c50438 | ||
|
|
e3423ea9a3 | ||
|
|
812112858c | ||
|
|
8db1357904 | ||
|
|
bba0aa9f52 | ||
|
|
1cc549b24a | ||
|
|
7cafeb73ca | ||
|
|
772f082913 | ||
|
|
9f7efe3018 | ||
|
|
a28584b08b | ||
|
|
5cba46a482 | ||
|
|
a15b7620eb | ||
|
|
9ef6efa3e0 | ||
|
|
49bff88c4e | ||
|
|
80af34fa3e | ||
|
|
1d6f2644aa | ||
|
|
dc61d364d1 | ||
|
|
78de9dd538 | ||
|
|
ccaea5b9d1 | ||
|
|
e02e9de55d | ||
|
|
40da192dbb | ||
|
|
c8254238c7 | ||
|
|
9caee0c77c | ||
|
|
b9830f0190 | ||
|
|
02a0a9b783 | ||
|
|
ea1758a1a9 | ||
|
|
b43afd4e9c | ||
|
|
7700aa2030 | ||
|
|
d5d8391f63 | ||
|
|
b508d2301b | ||
|
|
01b3336709 | ||
|
|
6ba37aefd6 | ||
|
|
e68683acb7 | ||
|
|
a804904ff5 | ||
|
|
eacb89176c | ||
|
|
ec971aa822 | ||
|
|
e1f404c647 | ||
|
|
5f1e32d610 | ||
|
|
732ee2bbb9 | ||
|
|
1e461250d5 | ||
|
|
f727174044 | ||
|
|
7edc687f7b | ||
|
|
596fbf0b87 | ||
|
|
8dc48c10c3 | ||
|
|
5db90e5896 | ||
|
|
dd811def07 | ||
|
|
5273291e9a | ||
|
|
130dbda499 | ||
|
|
769aea7e4e | ||
|
|
fa3d65bde6 | ||
|
|
073281135c | ||
|
|
4c7f979e56 | ||
|
|
a5bfb4f8d2 | ||
|
|
a04780f311 | ||
|
|
aad0fd22ad | ||
|
|
bc1c3994d3 | ||
|
|
840033aa6a | ||
|
|
9cc6e9e790 | ||
|
|
b1ad2f409e | ||
|
|
7106646042 | ||
|
|
31405119f0 | ||
|
|
2e5ee93361 | ||
|
|
f981a661d5 | ||
|
|
7e05bbf5e3 | ||
|
|
4465f4a3bb | ||
|
|
ade4f183cd | ||
|
|
99dc61799f | ||
|
|
a213b94606 | ||
|
|
6600ed8cbb | ||
|
|
826bf12bd6 | ||
|
|
528e0db79c | ||
|
|
11a5fec195 | ||
|
|
c0f3f3a40a | ||
|
|
88844db23a | ||
|
|
31710b4e28 | ||
|
|
42d2f6400b | ||
|
|
2701d6adc0 | ||
|
|
5a4b203937 | ||
|
|
74cb7877cb | ||
|
|
f954338c27 | ||
|
|
cc729b1d25 | ||
|
|
4a4b1d6b00 | ||
|
|
d14741f3b1 | ||
|
|
94684fff9f | ||
|
|
44deef4a5a | ||
|
|
67079e1c0b | ||
|
|
005ffc55ce | ||
|
|
1691b0b30c | ||
|
|
e4e55430ca | ||
|
|
4d31d9d748 | ||
|
|
1413f596fb | ||
|
|
c0aee94da5 | ||
|
|
8e545346e6 | ||
|
|
2b1272c70d | ||
|
|
121f9b6ec3 | ||
|
|
6f9722143e | ||
|
|
5bf62f4b93 | ||
|
|
79319dd006 | ||
|
|
fdcff53697 | ||
|
|
24cd2729db | ||
|
|
9ca2703f16 | ||
|
|
1a579c5755 | ||
|
|
7344c761fe | ||
|
|
203a981fed | ||
|
|
d3faf65900 | ||
|
|
5efbf81090 | ||
|
|
9ffab7d531 | ||
|
|
0886ff1be1 | ||
|
|
2893182713 | ||
|
|
478bb18ab2 | ||
|
|
eae07ca6cc | ||
|
|
2264faabfc | ||
|
|
4cdf82cb14 | ||
|
|
5a7e511dac | ||
|
|
a29eb3d343 | ||
|
|
3c65aefe61 | ||
|
|
867d7697d2 | ||
|
|
ebee6610a3 | ||
|
|
c26691c2fc | ||
|
|
a038d6e999 | ||
|
|
aa1550ca01 | ||
|
|
80eaa643c9 | ||
|
|
d67d9c1afd | ||
|
|
af15fc123d | ||
|
|
0ce56e6529 | ||
|
|
258164c285 | ||
|
|
746617deb0 | ||
|
|
c51d00673d | ||
|
|
bedd21522a | ||
|
|
382013d0ca | ||
|
|
3794207d97 | ||
|
|
2805323cfa | ||
|
|
0db2e56e32 | ||
|
|
a33ad18322 | ||
|
|
885ef6b357 | ||
|
|
2435072b07 | ||
|
|
d462bd16b5 | ||
|
|
b08a3835dc | ||
|
|
ace0908d84 | ||
|
|
5186fffb5e | ||
|
|
c5160c9baa | ||
|
|
63acc94558 | ||
|
|
fc82407d9a | ||
|
|
a0ac9eb285 | ||
|
|
fc835eaba7 | ||
|
|
f7b3e5bf77 | ||
|
|
e41484186b | ||
|
|
e0bfe6a96c | ||
|
|
228f184548 | ||
|
|
892ce4c453 | ||
|
|
569d45d58a | ||
|
|
ce5f00e075 | ||
|
|
4da407008e | ||
|
|
96e79cc8ae | ||
|
|
ee93806e19 | ||
|
|
fcb02602a0 | ||
|
|
5d4fdf1e76 | ||
|
|
9af59fb51c | ||
|
|
6493d37b7c | ||
|
|
a82c033da0 | ||
|
|
91484e1c98 | ||
|
|
3db5202cdf | ||
|
|
5a28974027 | ||
|
|
4d694f1f74 | ||
|
|
5035c408e7 | ||
|
|
d209f98265 | ||
|
|
85b1404321 | ||
|
|
72c6e4e94e | ||
|
|
eb46ed2768 | ||
|
|
7f4f01c9e8 | ||
|
|
691d2746e6 | ||
|
|
d41dfc1e0d | ||
|
|
493898bd4a | ||
|
|
8ebe427269 | ||
|
|
48d4ff97a0 | ||
|
|
83769bf539 | ||
|
|
0954bf2923 | ||
|
|
a2f5f82e28 | ||
|
|
a82af04fca | ||
|
|
a1a876429c | ||
|
|
58830fa53e | ||
|
|
15c8e32fef | ||
|
|
59c915d8bc | ||
|
|
968ff61979 | ||
|
|
94901849e6 | ||
|
|
ff42126b0e | ||
|
|
39ddf10ca7 | ||
|
|
7a24e5d39d | ||
|
|
e9100504a0 | ||
|
|
099cbfdf75 | ||
|
|
28afef8847 | ||
|
|
010b1e1cce | ||
|
|
274ce76c2b | ||
|
|
f3155e618b | ||
|
|
18307caab3 | ||
|
|
2e279b8876 | ||
|
|
0da878f50f | ||
|
|
ecfb3644be | ||
|
|
c87d18fd8e | ||
|
|
5810f9232a | ||
|
|
fb8eb6f357 | ||
|
|
7eb76ff32d | ||
|
|
c3d3de9984 | ||
|
|
cc2549dbdf | ||
|
|
7efa8eab18 | ||
|
|
376ae9ec1c | ||
|
|
9882b2999f | ||
|
|
3667a75244 | ||
|
|
4089448b53 | ||
|
|
fec11869a8 | ||
|
|
e7e56d1cdb | ||
|
|
9db01d6060 | ||
|
|
ed38397631 | ||
|
|
b3dddc0570 | ||
|
|
6fa06de245 | ||
|
|
834ddde1d0 | ||
|
|
5d4348f8a7 | ||
|
|
36f2917995 | ||
|
|
eedbec175d | ||
|
|
344ec86722 | ||
|
|
952d1e5895 | ||
|
|
a371484f38 | ||
|
|
1567a6fd27 | ||
|
|
e0f96b5cca | ||
|
|
8f6e48642c | ||
|
|
0c4c10dc1a | ||
|
|
de6b78d762 | ||
|
|
6b77f32548 | ||
|
|
fd2b7a00e1 | ||
|
|
818886a65e | ||
|
|
0ca31afc91 | ||
|
|
024a73da63 | ||
|
|
744b0063d8 | ||
|
|
355923f680 | ||
|
|
44332a2004 | ||
|
|
2f125e3d0e | ||
|
|
588228c050 | ||
|
|
8977ba9b6d | ||
|
|
ad06117b78 | ||
|
|
01b30ccf12 | ||
|
|
7f75905d5d | ||
|
|
798856c649 | ||
|
|
9acd358080 | ||
|
|
31c112157a | ||
|
|
d2e162edbf | ||
|
|
6aaffe20d9 | ||
|
|
6d32b20117 | ||
|
|
bd894704b1 | ||
|
|
7af2162b50 | ||
|
|
c735d108d4 | ||
|
|
6a2ffc936e | ||
|
|
74d5480587 | ||
|
|
89c39c7038 | ||
|
|
61f955cfeb | ||
|
|
744adee94c | ||
|
|
267c0b037d | ||
|
|
860414b7b2 | ||
|
|
09bf361d44 | ||
|
|
e2f80c5788 | ||
|
|
a96a6eb57d | ||
|
|
803f9a7fd6 | ||
|
|
71a141e0b8 | ||
|
|
a99b85e646 | ||
|
|
333169d18c | ||
|
|
a08eb418a6 | ||
|
|
cbb878cf96 | ||
|
|
d684f91a5a | ||
|
|
f2de4cd34c | ||
|
|
3d076a605b | ||
|
|
3607f88e18 | ||
|
|
a0d2bb11ed | ||
|
|
ede245a37d | ||
|
|
aca1e112d2 | ||
|
|
bf5d6dac18 | ||
|
|
182ce4da42 | ||
|
|
41e2e6fa59 | ||
|
|
fe0e964a5a | ||
|
|
bee35f9ee9 | ||
|
|
e66a1bb5b4 | ||
|
|
8490997604 | ||
|
|
6898d1df6d | ||
|
|
4d863bb894 | ||
|
|
a338e5fa26 | ||
|
|
695adc8acb | ||
|
|
fab7d26191 | ||
|
|
3959139dd8 | ||
|
|
1298669f1c | ||
|
|
4fe40f5ff7 | ||
|
|
a10c113c42 | ||
|
|
d5f4b5c711 | ||
|
|
93707af56b | ||
|
|
0ae694c1a8 | ||
|
|
0b53fb19b7 | ||
|
|
cc386e86b9 | ||
|
|
a922d7de31 | ||
|
|
8e7d64f0e4 | ||
|
|
0bc406538b | ||
|
|
9547559e00 | ||
|
|
70783dc828 | ||
|
|
85bdd791b8 | ||
|
|
9d7e61556d | ||
|
|
eb80c39b98 | ||
|
|
07b69fe96f | ||
|
|
e0a3fd1795 |
45
.github/workflows/build_package.yml
vendored
Normal file
45
.github/workflows/build_package.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: Build & package
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main", "release-candidate" ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Add MSBuild to PATH
|
||||||
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
|
|
||||||
|
- name: Setup vcpkg
|
||||||
|
run: |
|
||||||
|
bootstrap-vcpkg
|
||||||
|
vcpkg integrate install
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
working-directory: .
|
||||||
|
run: "./build_package.bat"
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Upload a Build Artifact
|
||||||
|
uses: actions/upload-artifact@v3.1.3
|
||||||
|
with:
|
||||||
|
name: development_build_not_a_release
|
||||||
|
path: ./package
|
||||||
|
|
||||||
|
- name: Upload a Build Artifact
|
||||||
|
uses: actions/upload-artifact@v3.1.3
|
||||||
|
with:
|
||||||
|
name: zip_only_package
|
||||||
|
path: ./zip
|
||||||
|
|
||||||
|
|
||||||
44
.gitignore
vendored
44
.gitignore
vendored
@@ -1,12 +1,42 @@
|
|||||||
bin
|
bin
|
||||||
/scripts/old
|
|
||||||
.vs
|
.vs
|
||||||
x64
|
x64
|
||||||
core.user
|
|
||||||
core.vcxproj.user
|
|
||||||
*.user
|
|
||||||
Output
|
Output
|
||||||
node_modules
|
node_modules
|
||||||
/client/TODO.txt
|
hgt
|
||||||
/client/public/javascripts/bundle.js
|
|
||||||
!client/bin
|
/backend/vcpkg_installed
|
||||||
|
|
||||||
|
/frontend/server/TODO.txt
|
||||||
|
/frontend/server/public/javascripts/bundle.js
|
||||||
|
/frontend/server/public/plugins
|
||||||
|
/frontend/server/plugins/controltips/index.js
|
||||||
|
/frontend/server/public/databases/units/old
|
||||||
|
/frontend/server/plugins/databasemanager/index.js
|
||||||
|
|
||||||
|
/src/html
|
||||||
|
/src/latex
|
||||||
|
|
||||||
|
/package
|
||||||
|
/build
|
||||||
|
/DCS Olympus backups
|
||||||
|
/zip
|
||||||
|
|
||||||
|
*.user
|
||||||
|
*.aps
|
||||||
|
|
||||||
|
L.Path.Drag.js
|
||||||
|
leaflet-gesture-handling.css
|
||||||
|
leaflet.nauticscale.js
|
||||||
|
leaflet.css
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
!frontend/server/bin
|
||||||
|
/mock-dcs
|
||||||
|
/frontend/setup
|
||||||
|
frontend/server/public/plugins/controltipsplugin/index.js
|
||||||
|
frontend/website/plugins/controltips/index.js
|
||||||
|
/frontend/server/public/maps
|
||||||
|
*.pyc
|
||||||
|
/scripts/**/*.jpg
|
||||||
|
manager/manager.log
|
||||||
|
|||||||
BIN
DCS Olympus Manager.lnk
Normal file
BIN
DCS Olympus Manager.lnk
Normal file
Binary file not shown.
59
INSTRUCTIONS.txt
Normal file
59
INSTRUCTIONS.txt
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
_____ _____ _____ ____ _
|
||||||
|
| __ \ / ____|/ ____| / __ \| |
|
||||||
|
| | | | | | (___ | | | | |_ _ _ __ ___ _ __ _ _ ___
|
||||||
|
| | | | | \___ \ | | | | | | | | '_ ` _ \| '_ \| | | / __|
|
||||||
|
| |__| | |____ ____) | | |__| | | |_| | | | | | | |_) | |_| \__ \
|
||||||
|
|_____/ \_____|_____/ \____/|_|\__, |_| |_| |_| .__/ \__,_|___/
|
||||||
|
__/ | | |
|
||||||
|
|___/ |_|
|
||||||
|
|
||||||
|
{{OLYMPUS_VERSION_NUMBER}}
|
||||||
|
|
||||||
|
==========================================
|
||||||
|
INSTALLATION INSTRUCTIONS
|
||||||
|
|
||||||
|
1) Close any applications which may interfere with installation, including Digital Combat Simulator (DCS) and previous versions of Olympus.
|
||||||
|
|
||||||
|
2) If you DO NOT have Olympus already installed, SKIP THIS STEP. If you have already installed Olympus, do the following:
|
||||||
|
NOTE: If you made any changes to your unit databases or mods.lua file (e.g. to support a third party mod) make a backup of the edited files before proceeding or changes will be lost;
|
||||||
|
a) If you installed DCS Olympus v1.0.3 using the installer, simply remove it using Windows's "Add or remove programs" application.
|
||||||
|
b) If you installed DCS Olympus v1.0.3 using the archived version, remove it by deleting the "...<DCS Saved Games folder>\Mods\Services\Olympus" folder. Do this for every DCS instance you installed Olympus in.
|
||||||
|
Remember to delete any shortcuts you created. Don't worry, they will be created automatically again by the installation script provided in this package.
|
||||||
|
|
||||||
|
3) Create a folder named "DCS Olympus" in your "Saved Games" directory and extract all the contents of the downloaded package into it.
|
||||||
|
NOTE:
|
||||||
|
a) Do not extract the contents of the package directly in your Saved Games folder or in your DCS Saved Games folder.
|
||||||
|
b) Unlike previous version of Olympus, it is no longer necessary to copy the packaged files into each DCS instance folder.
|
||||||
|
|
||||||
|
4) Execute the "installer.bat" script by double-clicking on it. It is located in the folder you created in step 3. Wait for the installation script to complete. Installation may take a couple of minutes, after which the Manager will start automatically.
|
||||||
|
NOTE: depending on your Windows configuration, the script may be called "installer" (without .bat at the end).
|
||||||
|
|
||||||
|
5) The Olympus Manager will open. This will allow you to add/remove Olympus to individual DCS instances.
|
||||||
|
Use the Olympus Manager and follow the instructions to install and setup Olympus.
|
||||||
|
|
||||||
|
6) Start DCS and run a mission. Make sure it is UNPAUSED.
|
||||||
|
|
||||||
|
7) Open Olympus via the shortcut and login using any username and the Game Master password set using the Manager. (NOTE: not your DCS server password).
|
||||||
|
Local installation: run the client from the provided desktop shortcut or start it using the "View and manage instances" page of the Manager.
|
||||||
|
Dedicated server: users must first start the Olympus server from the provided desktop shortcut or using the "View and manage instances" page of the Manager.
|
||||||
|
Then log in using any browser and visiting "http:\\<server IP>:<frontend port>" (frontend port is 3000 by default, but can be edited using the Manager)
|
||||||
|
|
||||||
|
8) You can use the manager at any time to change the ports and/or passwords. If you do, REMEMBER TO RESTART OLYMPUS AND DCS.
|
||||||
|
|
||||||
|
|
||||||
|
NOTES:
|
||||||
|
a) when launching the Manager you will be prompted to allow Electron to create a firewall rule. This is optional and can be denied without effect on the operation of the Manager;
|
||||||
|
b) if you are using Olympus on a dedicated server with a router, you must enable port forwarding on the frontend port (3000 by default);
|
||||||
|
c) unlike Olympus v1.0.3, running the netsh command is no longer required. It is also no longer required to create firewall rules or port forwarding for the backend port. (Optional) If you already performed this steps in the past you can delete the firewall and netsh rules.
|
||||||
|
|
||||||
|
|
||||||
|
==========================================
|
||||||
|
UPDATING INSTRUCTIONS
|
||||||
|
|
||||||
|
IF YOU ARE UPDATING FROM DCS OLYMPUS v1.0.3, FOLLOW THE "INSTALLATION INSTRUCTIONS".
|
||||||
|
|
||||||
|
To update your Olympus installation you have two options:
|
||||||
|
a) download the new package from the GitHub releases page, delete the old unpacked package folder, then follow the INSTALLATION INSTRUCTIONS;
|
||||||
|
b) run the Olympus Manager. If an update is available you will be given the option to automatically update Olympus from there.
|
||||||
|
|
||||||
|
For either options a) or b), remember to close any applications which may interfere with installation, including Digital Combat Simulator (DCS) and previous versions of Olympus.
|
||||||
@@ -1,4 +1,34 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
DCS Olympus
|
||||||
|
|
||||||
|
A real-time AI unit control mod for DCS World
|
||||||
|
|
||||||
|
Copyright (C) 2023 Veltro & Gang (the "DCS Olympus Team" or the
|
||||||
|
"Rightsholders")
|
||||||
|
|
||||||
|
DCS Olympus (the "MATERIAL" or "Software") is provided completely free
|
||||||
|
to users subject to the it under both the terms of version 3 of the GNU
|
||||||
|
General Public License ("GPLv3") as published by the Free Software Foundation,
|
||||||
|
and the additional terms set out below (the "Additional Terms"). In the event
|
||||||
|
that the terms of GPLv3 conflict with the Additional Terms, the
|
||||||
|
Additional Terms shall prevail.
|
||||||
|
|
||||||
|
The authors and/or copyright holders of the Software have not received any
|
||||||
|
financial benefit in connection with the Software. In any event, the
|
||||||
|
Software is provided “as is”, without warranty of any kind, express or
|
||||||
|
implied, including but not limited to the warranties of merchantability,
|
||||||
|
fitness for a particular purpose and non-infringement. In no event shall
|
||||||
|
the authors and/or copyright holders be liable for any claim, damages or
|
||||||
|
other liability, whether in an action of contract, tort or otherwise,
|
||||||
|
arising from, out of or in connection with the Software or the use or
|
||||||
|
other dealings in the Software.
|
||||||
|
|
||||||
|
THIS MATERIAL IS NOT MADE OR SUPPORTED BY EAGLE DYNAMICS SA.
|
||||||
|
|
||||||
|
Any party making use of the Software in any manner agrees to be bound by
|
||||||
|
the entirety of this document.
|
||||||
|
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
@@ -618,57 +648,31 @@ an absolute waiver of all civil liability in connection with the
|
|||||||
Program, unless a warranty or assumption of liability accompanies a
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
copy of the Program in return for a fee.
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF GNU GENERAL PUBLIC LICENCE
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
ADDITIONAL TERMS & CONDITIONS
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
1. Governing Law
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
Save where specifically provided for otherwise, the provisions of the
|
||||||
to attach them to the start of each source file to most effectively
|
GNU General Public Licence Version 3 above shall be governed by and
|
||||||
state the exclusion of warranty; and each file should have at least
|
interpreted in accordance with English Law and the parties submit to the
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
exclusive jurisdiction of the English Courts.
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
2. Entire Agreement
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
The text of this document contains the entire understanding between
|
||||||
it under the terms of the GNU General Public License as published by
|
you, the licensee, and the authors and/or copyright holders of the
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
Software with respect to the subject matter to which it pertains.
|
||||||
(at your option) any later version.
|
It supersedes all prior agreements and understandings (if applicable),
|
||||||
|
oral or written, with respect to such matters.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
3. Unilateral Modification
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
The parties agree that the DCS Olympus Team shall have the right to
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
unilaterally modify these terms (i.e. the agreement between you and the
|
||||||
|
DCS Olympus Team for the use of the Software), and that parties shall
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
be bound by such terms as modified from time to time. The DCS Olympus Team
|
||||||
|
shall not have an obligation to inform you of such modification, save that
|
||||||
If the program does terminal interaction, make it output a short
|
such changes will be published on the DCS Olympus Github Repository located at
|
||||||
notice like this when it starts in an interactive mode:
|
https://github.com/Pax1601/DCSOlympus.
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
||||||
103
README.md
103
README.md
@@ -1,40 +1,85 @@
|
|||||||
# Important note: DCS Olympus is in alpha state. No official release has been produced yet. The first public version is planned for Q4 2023.
|
<img align="left" width="30" src="https://github.com/Pax1601/DCSOlympus/assets/103559271/0ecff279-a87c-4e2d-a4c7-da98c74adf38">
|
||||||
|
|
||||||
|
[**Join our Discord**](https://discord.gg/kNAQkhUHnQ)
|
||||||
|
|
||||||
|
<img align="left" width="30" src="https://github.com/Pax1601/DCSOlympus/assets/103559271/1c0dd3fd-339c-4b03-94da-3e5215b0358a">
|
||||||
|
|
||||||
|
[**YouTube**](https://www.youtube.com/@DCSOlympus)
|
||||||
|
|
||||||
|
|
||||||
# DCS Olympus
|
# DCS Olympus
|
||||||
*A real-time web interface to spawn and control units in DCS World*
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### What is this?
|
### What is this?
|
||||||
DCS Olympus is a mod for DCS World. It allows users to spawn, control, task, group, and remove units from a DCS World server using a real-time map interface, similarly to Real Time Strategy games. The user interface also provides useful informations units, like loadouts, fuel, tasking, and so on. In the future, more features for DCS World GCI and JTAC will be available.
|
DCS: Olympus is a free and open-source mod for DCS that enables dynamic real-time control through a map interface. The user is able to spawn units/groups, deploy a variety of effects such as smoke, flares, or explosions, and waypoints/tasks can be given to AI units in real-time in a way similar to a classic RTS game.
|
||||||
|
|
||||||
### Features and how to use it
|
Additionally Olympus is able to run several effects and unit behaviours beyond the core DCS offerings. This includes such things as napalm and white phosphosous explosions, or setting up AA units to fire at players and miss, and more.
|
||||||
- Spawn air and ground units, with preset loadouts
|
|
||||||
- Double click on the map to spawn a blue and red units, both in the air and in the ground, with preset loadouts for air-to-air or air-to-ground tasks;
|
It even includes Red and Blue modes which limit your view and powers to just seeing what your coalition sees, with a spawning budget you could play against your friends even with no-one in the game piloting, or have a Red commander working against a squadron of blue pilots, and/or a blue commander working with them.
|
||||||
- Control units
|
|
||||||
- Select one ore more units to move them around. Hold down ctrl and click to create a route for the unit to follow;
|
Even better it requires no client mods be installed if used on a server
|
||||||
- Attack other units
|
|
||||||
- After selecting one ore more units, double click on another unit and select "Attack" to attack it, depending on the available weapons.
|
The full feature list is simply too long to enumerate in a short summary but needless to say Olympus offers up a lot of unique gameplay that has previously not existed, and enhances many other elements of DCS in exciting ways
|
||||||
|
|
||||||
### Installing DCS Olympus
|
### Installing DCS Olympus
|
||||||
A prebuilt installer will soon be released and available here
|
Check the [Wiki](https://github.com/Pax1601/DCSOlympus/wiki) for installation instructions
|
||||||
|
|
||||||
### Building DCS Olympus
|
# Frequently Asked Questions
|
||||||
DCS Olympus is comprised of two modules:
|
|
||||||
|
|
||||||
A "core" c++ .dll module, which is run by DCS and exposes all the necessary data, and provides endpoints for commands from a REST server. A Visual Studio 2017/2019/2022 solution is provided, and requires no additional configuration. The core dll solution has two dependencies, both can be installed using vcpkg (https://vcpkg.io/en/getting-started.html):
|
### I need troubleshooting guidance, please help? ###
|
||||||
- cpprestsdk: `vcpkg install cpprestsdk:x64-windows`
|
Read through the [Installation Guide](https://github.com/Pax1601/DCSOlympus/wiki) to ensure you have setup Olympus correctly.
|
||||||
- geographiclib: `vcpkg install geographiclib:x64-windows`
|
|
||||||
|
Read through [Setup Troubleshooting](https://github.com/Pax1601/DCSOlympus/wiki/Setup-Troubleshooting) for common issues and solutions.
|
||||||
|
|
||||||
A "client" node.js typescript web app, which can be hosted on the server using express.js. A Visual Studio Code configuration is provided for debugging. The client requires node.js to be installed for building (https://nodejs.org/en/). After installing node.js, move in the client folder and run the following commands:
|
Read through the [Olympus User Guide](https://github.com/Pax1601/DCSOlympus/wiki/2.-User-Guide) to learn how to use Olympus.
|
||||||
- `npm install`
|
|
||||||
- `npm -g install`
|
If you're still having issues after trying the steps above, please post in the community-support channel with the following:
|
||||||
|
|
||||||
After installing all the necessary dependencies you can start a development server executing the *client/debug.bat* batch file, and visiting http:\\localhost:3000 with any modern browser (tested with updated Chrome, Firefox and Edge). However, it is highly suggested to simply run the `Launch Chrome against localhost` debug configuration in Visual Studio Code.
|
A detailed description of your issue
|
||||||
|
Your Olympus log file \user home folder\AppData\Local\Temp\Olympus_log.txt for some it might be in \DCS Saved Games folder\Logs\Olympus_log.txt
|
||||||
|
Your DCS log file \DCS Saved Games folder\Logs\dcs.log
|
||||||
|
|
||||||
|
Screenshots of any relevant screens or issues and any other pertinent information.
|
||||||
|
|
||||||
|
### Can I join up and help out with the project? ###
|
||||||
|
Absolutely, join the discord and ping any of the developers to get briefed.
|
||||||
|
|
||||||
|
### Can I be a beta/alpha-tester? ###
|
||||||
|
Same as above!
|
||||||
|
|
||||||
|
### Do you have a roadmap? ###
|
||||||
|
We do not have a roadmap no, we have a laundry list of things we are hoping to do.
|
||||||
|
|
||||||
|
These include but are not limited to:
|
||||||
|
1) Enhancements to helicopter play
|
||||||
|
2) More features around use of ground units
|
||||||
|
3) More unique effects and behaviours
|
||||||
|
4) ATC/AIC features
|
||||||
|
5) Usability features like unit painters etc
|
||||||
|
|
||||||
|
However we cannot commit to specific features, feature release order, or timelines, please remember this isn't our job and we work on it in our free time because we love DCS
|
||||||
|
|
||||||
|
### Does Olympus support mods? ###
|
||||||
|
Generally OIympus will not have any issues with other mods, however you may need to tell olympus about modded units in order to be able to dynamically spawn them etc
|
||||||
|
Keep in mind that any mods you do choose to spawn your players will need to have, some mod unit just appear as a su27 or leo2 etc. When a player is missing them, others can cause client crashes. So be smart about how you use them.
|
||||||
|
|
||||||
|
### Is Olympus compatible with mission scripts? ###
|
||||||
|
We have tried hard to keep Olympus from interfering with other scripts, we have tested with a variety of new and old mission scripts and generally expect it will not be an issue.
|
||||||
|
|
||||||
|
However we cannot foresee everything people come up with so we suggest testing with what you have in mind once olympus releases
|
||||||
|
|
||||||
|
### How does it work? ###
|
||||||
|
The quick answer is magic.
|
||||||
|
The long answer is well all the code is there for you to read.
|
||||||
|
The middle answer is a bit like SRS does. Olympus consists of two parts.
|
||||||
|
|
||||||
|
(A) Olympus back end: A dll, run by DCS, that sends data out and gets commands in via a REST API;
|
||||||
|
(B) Webserver exe: The one you start when starting the server via the desktop shortcut.
|
||||||
|
|
||||||
|
A and B never communicate when you connect the client you download the web page and some other minor stuff from B, and you get the DCS data from and send commands to A.
|
||||||
|
|
||||||
|
### How much does Olympus impact performance? ###
|
||||||
|
Olympus by itself should not have a noticeable impact on server performance, however the ability for the user to spawn arbitrary units and command engagements means Olympus can be used in such a way that brings the game to it's knees.
|
||||||
|
|
||||||
|
Be cognizant of how you play, whether it's done through Olympus or the mission editor 500 MLRS units firing at once is not going to go over well with most servers
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
12
backend/DCSOlympus.props
Normal file
12
backend/DCSOlympus.props
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ImportGroup Label="PropertySheets" />
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup />
|
||||||
|
<PropertyGroup Label="Vcpkg">
|
||||||
|
<VcpkgEnableManifest>true</VcpkgEnableManifest>
|
||||||
|
<VcpkgAutoLink>true</VcpkgAutoLink>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup />
|
||||||
|
<ItemGroup />
|
||||||
|
</Project>
|
||||||
110
backend/core/core.rc
Normal file
110
backend/core/core.rc
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Italian (Italy) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||||
|
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
#endif // Italian (Italy) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (United Kingdom) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,4,0
|
||||||
|
PRODUCTVERSION 1,0,3,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "DCS Olympus"
|
||||||
|
VALUE "FileDescription", "DCS Olympus"
|
||||||
|
VALUE "FileVersion", "1.0.4.0"
|
||||||
|
VALUE "InternalName", "core.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||||
|
VALUE "OriginalFilename", "core.dll"
|
||||||
|
VALUE "ProductName", "DCS Olympus"
|
||||||
|
VALUE "ProductVersion", "1.0.4.0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (United Kingdom) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
@@ -37,7 +37,6 @@
|
|||||||
<ClInclude Include="include\airunit.h" />
|
<ClInclude Include="include\airunit.h" />
|
||||||
<ClInclude Include="include\commands.h" />
|
<ClInclude Include="include\commands.h" />
|
||||||
<ClInclude Include="include\datatypes.h" />
|
<ClInclude Include="include\datatypes.h" />
|
||||||
<ClInclude Include="include\measure.h" />
|
|
||||||
<ClInclude Include="include\groundunit.h" />
|
<ClInclude Include="include\groundunit.h" />
|
||||||
<ClInclude Include="include\helicopter.h" />
|
<ClInclude Include="include\helicopter.h" />
|
||||||
<ClInclude Include="include\navyunit.h" />
|
<ClInclude Include="include\navyunit.h" />
|
||||||
@@ -48,6 +47,7 @@
|
|||||||
<ClInclude Include="include\unitsmanager.h" />
|
<ClInclude Include="include\unitsmanager.h" />
|
||||||
<ClInclude Include="include\weapon.h" />
|
<ClInclude Include="include\weapon.h" />
|
||||||
<ClInclude Include="include\weaponsmanager.h" />
|
<ClInclude Include="include\weaponsmanager.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\aircraft.cpp" />
|
<ClCompile Include="src\aircraft.cpp" />
|
||||||
@@ -55,7 +55,6 @@
|
|||||||
<ClCompile Include="src\commands.cpp" />
|
<ClCompile Include="src\commands.cpp" />
|
||||||
<ClCompile Include="src\core.cpp" />
|
<ClCompile Include="src\core.cpp" />
|
||||||
<ClCompile Include="src\datatypes.cpp" />
|
<ClCompile Include="src\datatypes.cpp" />
|
||||||
<ClCompile Include="src\measure.cpp" />
|
|
||||||
<ClCompile Include="src\groundunit.cpp" />
|
<ClCompile Include="src\groundunit.cpp" />
|
||||||
<ClCompile Include="src\helicopter.cpp" />
|
<ClCompile Include="src\helicopter.cpp" />
|
||||||
<ClCompile Include="src\navyunit.cpp" />
|
<ClCompile Include="src\navyunit.cpp" />
|
||||||
@@ -67,6 +66,9 @@
|
|||||||
<ClCompile Include="src\weapon.cpp" />
|
<ClCompile Include="src\weapon.cpp" />
|
||||||
<ClCompile Include="src\weaponsmanager.cpp" />
|
<ClCompile Include="src\weaponsmanager.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="core.rc" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
@@ -108,22 +110,26 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>.\..\..\bin\</OutDir>
|
<OutDir>.\..\..\build\backend\bin\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -176,6 +182,7 @@
|
|||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
<AdditionalDependencies>lua.lib; GeographicLib-i.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>lua.lib; GeographicLib-i.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
||||||
|
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@@ -45,15 +45,13 @@
|
|||||||
<ClInclude Include="include\weapon.h">
|
<ClInclude Include="include\weapon.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="include\measure.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="include\datatypes.h">
|
<ClInclude Include="include\datatypes.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="include\weaponsmanager.h">
|
<ClInclude Include="include\weaponsmanager.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\aircraft.cpp">
|
<ClCompile Include="src\aircraft.cpp">
|
||||||
@@ -95,9 +93,6 @@
|
|||||||
<ClCompile Include="src\weapon.cpp">
|
<ClCompile Include="src\weapon.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\measure.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\datatypes.cpp">
|
<ClCompile Include="src\datatypes.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -105,4 +100,7 @@
|
|||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="core.rc" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
20
backend/core/include/aircraft.h
Normal file
20
backend/core/include/aircraft.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "airunit.h"
|
||||||
|
|
||||||
|
#define AIRCRAFT_DEST_DIST_THR 2000 // Meters
|
||||||
|
|
||||||
|
class Aircraft : public AirUnit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Aircraft(json::value json, unsigned int ID);
|
||||||
|
|
||||||
|
static void loadDatabase(string path);
|
||||||
|
|
||||||
|
virtual void changeSpeed(string change);
|
||||||
|
virtual void changeAltitude(string change);
|
||||||
|
|
||||||
|
virtual double getDestinationReachedThreshold() { return AIRCRAFT_DEST_DIST_THR; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static json::value database;
|
||||||
|
};
|
||||||
@@ -17,6 +17,7 @@ public:
|
|||||||
|
|
||||||
virtual void changeSpeed(string change) = 0;
|
virtual void changeSpeed(string change) = 0;
|
||||||
virtual void changeAltitude(string change) = 0;
|
virtual void changeAltitude(string change) = 0;
|
||||||
|
virtual double getDestinationReachedThreshold() { return AIR_DEST_DIST_THR; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void AIloop();
|
virtual void AIloop();
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "luatools.h"
|
#include "luatools.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include "datatypes.h"
|
||||||
|
|
||||||
namespace CommandPriority {
|
namespace CommandPriority {
|
||||||
enum CommandPriorities { LOW, MEDIUM, HIGH, IMMEDIATE };
|
enum CommandPriorities { LOW, MEDIUM, HIGH, IMMEDIATE };
|
||||||
@@ -94,19 +95,26 @@ namespace ECMUse {
|
|||||||
class Command
|
class Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Command(function<void(void)> callback) : callback(callback) {};
|
||||||
unsigned int getPriority() { return priority; }
|
unsigned int getPriority() { return priority; }
|
||||||
virtual string getString() = 0;
|
virtual string getString() = 0;
|
||||||
virtual unsigned int getLoad() = 0;
|
virtual unsigned int getLoad() = 0;
|
||||||
|
const string getHash() { return hash; }
|
||||||
|
void executeCallback() { callback(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned int priority = CommandPriority::LOW;
|
unsigned int priority = CommandPriority::LOW;
|
||||||
|
const string hash = random_string(16);
|
||||||
|
function<void(void)> callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Simple low priority move command (from user click) */
|
/* Simple low priority move command (from user click) */
|
||||||
class Move : public Command
|
class Move : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Move(string groupName, Coords destination, double speed, string speedType, double altitude, string altitudeType, string taskOptions, string category):
|
Move(string groupName, Coords destination, double speed, string speedType, double altitude,
|
||||||
|
string altitudeType, string taskOptions, string category, bool onRoad, function<void(void)> callback = []() {}) :
|
||||||
|
Command(callback),
|
||||||
groupName(groupName),
|
groupName(groupName),
|
||||||
destination(destination),
|
destination(destination),
|
||||||
speed(speed),
|
speed(speed),
|
||||||
@@ -114,12 +122,13 @@ public:
|
|||||||
altitude(altitude),
|
altitude(altitude),
|
||||||
altitudeType(altitudeType),
|
altitudeType(altitudeType),
|
||||||
taskOptions(taskOptions),
|
taskOptions(taskOptions),
|
||||||
category(category)
|
category(category),
|
||||||
|
onRoad(onRoad)
|
||||||
{
|
{
|
||||||
priority = CommandPriority::HIGH;
|
priority = CommandPriority::MEDIUM;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return 2; }
|
virtual unsigned int getLoad() { return onRoad? 45: 5; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string groupName;
|
const string groupName;
|
||||||
@@ -130,13 +139,15 @@ private:
|
|||||||
const string altitudeType;
|
const string altitudeType;
|
||||||
const string taskOptions;
|
const string taskOptions;
|
||||||
const string category;
|
const string category;
|
||||||
|
const bool onRoad;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Smoke command */
|
/* Smoke command */
|
||||||
class Smoke : public Command
|
class Smoke : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Smoke(string color, Coords location) :
|
Smoke(string color, Coords location, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
color(color),
|
color(color),
|
||||||
location(location)
|
location(location)
|
||||||
{
|
{
|
||||||
@@ -154,23 +165,22 @@ private:
|
|||||||
class SpawnGroundUnits : public Command
|
class SpawnGroundUnits : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpawnGroundUnits(string coalition, vector<string> unitTypes, vector<Coords> locations, vector<string> liveryIDs, bool immediate) :
|
SpawnGroundUnits(string coalition, vector<SpawnOptions> spawnOptions, string country, bool immediate, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
coalition(coalition),
|
coalition(coalition),
|
||||||
unitTypes(unitTypes),
|
spawnOptions(spawnOptions),
|
||||||
locations(locations),
|
country(country),
|
||||||
liveryIDs(liveryIDs),
|
|
||||||
immediate(immediate)
|
immediate(immediate)
|
||||||
{
|
{
|
||||||
priority = immediate? CommandPriority::IMMEDIATE: CommandPriority::LOW;
|
priority = immediate? CommandPriority::IMMEDIATE: CommandPriority::LOW;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return immediate? 1: 30; }
|
virtual unsigned int getLoad() { return immediate? 5: 30; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string coalition;
|
const string coalition;
|
||||||
const vector<string> unitTypes;
|
const vector<SpawnOptions> spawnOptions;
|
||||||
const vector<Coords> locations;
|
const string country;
|
||||||
const vector<string> liveryIDs;
|
|
||||||
const bool immediate;
|
const bool immediate;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -178,23 +188,22 @@ private:
|
|||||||
class SpawnNavyUnits : public Command
|
class SpawnNavyUnits : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpawnNavyUnits(string coalition, vector<string> unitTypes, vector<Coords> locations, vector<string> liveryIDs, bool immediate) :
|
SpawnNavyUnits(string coalition, vector<SpawnOptions> spawnOptions, string country, bool immediate, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
coalition(coalition),
|
coalition(coalition),
|
||||||
unitTypes(unitTypes),
|
spawnOptions(spawnOptions),
|
||||||
locations(locations),
|
country(country),
|
||||||
liveryIDs(liveryIDs),
|
|
||||||
immediate(immediate)
|
immediate(immediate)
|
||||||
{
|
{
|
||||||
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
|
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return immediate ? 1 : 30; }
|
virtual unsigned int getLoad() { return immediate ? 5 : 60; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string coalition;
|
const string coalition;
|
||||||
const vector<string> unitTypes;
|
const vector<SpawnOptions> spawnOptions;
|
||||||
const vector<Coords> locations;
|
const string country;
|
||||||
const vector<string> liveryIDs;
|
|
||||||
const bool immediate;
|
const bool immediate;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -202,56 +211,49 @@ private:
|
|||||||
class SpawnAircrafts : public Command
|
class SpawnAircrafts : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpawnAircrafts(string coalition, vector<string> unitTypes, vector<Coords> locations, vector<string> loadouts, vector<string> liveryIDs, string airbaseName, bool immediate) :
|
SpawnAircrafts(string coalition, vector<SpawnOptions> spawnOptions, string airbaseName, string country, bool immediate, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
coalition(coalition),
|
coalition(coalition),
|
||||||
unitTypes(unitTypes),
|
spawnOptions(spawnOptions),
|
||||||
locations(locations),
|
|
||||||
loadouts(loadouts),
|
|
||||||
liveryIDs(liveryIDs),
|
|
||||||
airbaseName(airbaseName),
|
airbaseName(airbaseName),
|
||||||
|
country(country),
|
||||||
immediate(immediate)
|
immediate(immediate)
|
||||||
{
|
{
|
||||||
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
|
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return immediate ? 1 : 30; }
|
virtual unsigned int getLoad() { return immediate ? 5 : 45; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string coalition;
|
const string coalition;
|
||||||
const vector<string> unitTypes;
|
const vector<SpawnOptions> spawnOptions;
|
||||||
const vector<Coords> locations;
|
|
||||||
const vector<string> loadouts;
|
|
||||||
const vector<string> liveryIDs;
|
|
||||||
const string airbaseName;
|
const string airbaseName;
|
||||||
|
const string country;
|
||||||
const bool immediate;
|
const bool immediate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Spawn helicopter command */
|
/* Spawn helicopter command */
|
||||||
class SpawnHelicopters : public Command
|
class SpawnHelicopters : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpawnHelicopters(string coalition, vector<string> unitTypes, vector<Coords> locations, vector<string> loadouts, vector<string> liveryIDs, string airbaseName, bool immediate) :
|
SpawnHelicopters(string coalition, vector<SpawnOptions> spawnOptions, string airbaseName, string country, bool immediate, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
coalition(coalition),
|
coalition(coalition),
|
||||||
unitTypes(unitTypes),
|
spawnOptions(spawnOptions),
|
||||||
locations(locations),
|
|
||||||
loadouts(loadouts),
|
|
||||||
liveryIDs(liveryIDs),
|
|
||||||
airbaseName(airbaseName),
|
airbaseName(airbaseName),
|
||||||
|
country(country),
|
||||||
immediate(immediate)
|
immediate(immediate)
|
||||||
{
|
{
|
||||||
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
|
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return immediate ? 1 : 30; }
|
virtual unsigned int getLoad() { return immediate ? 5 : 45; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string coalition;
|
const string coalition;
|
||||||
const vector<string> unitTypes;
|
const vector<SpawnOptions> spawnOptions;
|
||||||
const vector<Coords> locations;
|
|
||||||
const vector<string> loadouts;
|
|
||||||
const vector<string> liveryIDs;
|
|
||||||
const string airbaseName;
|
const string airbaseName;
|
||||||
|
const string country;
|
||||||
const bool immediate;
|
const bool immediate;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -259,9 +261,10 @@ private:
|
|||||||
class Clone : public Command
|
class Clone : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Clone(unsigned int ID, Coords location) :
|
Clone(vector<CloneOptions> cloneOptions, bool deleteOriginal, function<void(void)> callback = [](){}) :
|
||||||
ID(ID),
|
Command(callback),
|
||||||
location(location)
|
cloneOptions(cloneOptions),
|
||||||
|
deleteOriginal(deleteOriginal)
|
||||||
{
|
{
|
||||||
priority = CommandPriority::LOW;
|
priority = CommandPriority::LOW;
|
||||||
};
|
};
|
||||||
@@ -269,28 +272,31 @@ public:
|
|||||||
virtual unsigned int getLoad() { return 30; }
|
virtual unsigned int getLoad() { return 30; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const unsigned int ID;
|
const vector<CloneOptions> cloneOptions;
|
||||||
const Coords location;
|
const bool deleteOriginal;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Delete unit command */
|
/* Delete unit command */
|
||||||
class Delete : public Command
|
class Delete : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Delete(unsigned int ID, bool explosion, bool immediate ) :
|
Delete(unsigned int ID, bool explosion, string explosionType, bool immediate, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
ID(ID),
|
ID(ID),
|
||||||
explosion(explosion),
|
explosion(explosion),
|
||||||
|
explosionType(explosionType),
|
||||||
immediate(immediate)
|
immediate(immediate)
|
||||||
{
|
{
|
||||||
priority = CommandPriority::HIGH;
|
priority = CommandPriority::HIGH;
|
||||||
immediate = immediate;
|
immediate = immediate;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return immediate? 1: 5; }
|
virtual unsigned int getLoad() { return immediate? 1: 30; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const unsigned int ID;
|
const unsigned int ID;
|
||||||
const bool explosion;
|
const bool explosion;
|
||||||
|
const string explosionType;
|
||||||
const bool immediate;
|
const bool immediate;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -298,14 +304,15 @@ private:
|
|||||||
class SetTask : public Command
|
class SetTask : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetTask(string groupName, string task) :
|
SetTask(string groupName, string task, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
groupName(groupName),
|
groupName(groupName),
|
||||||
task(task)
|
task(task)
|
||||||
{
|
{
|
||||||
priority = CommandPriority::MEDIUM;
|
priority = CommandPriority::MEDIUM;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return 1; }
|
virtual unsigned int getLoad() { return 5; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string groupName;
|
const string groupName;
|
||||||
@@ -316,13 +323,14 @@ private:
|
|||||||
class ResetTask : public Command
|
class ResetTask : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ResetTask(string groupName) :
|
ResetTask(string groupName, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
groupName(groupName)
|
groupName(groupName)
|
||||||
{
|
{
|
||||||
priority = CommandPriority::HIGH;
|
priority = CommandPriority::HIGH;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return 1; }
|
virtual unsigned int getLoad() { return 5; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string groupName;
|
const string groupName;
|
||||||
@@ -332,14 +340,15 @@ private:
|
|||||||
class SetCommand : public Command
|
class SetCommand : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetCommand(string groupName, string command) :
|
SetCommand(string groupName, string command, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
groupName(groupName),
|
groupName(groupName),
|
||||||
command(command)
|
command(command)
|
||||||
{
|
{
|
||||||
priority = CommandPriority::HIGH;
|
priority = CommandPriority::HIGH;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return 1; }
|
virtual unsigned int getLoad() { return 5; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string groupName;
|
const string groupName;
|
||||||
@@ -350,7 +359,8 @@ private:
|
|||||||
class SetOption : public Command
|
class SetOption : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetOption(string groupName, unsigned int optionID, unsigned int optionValue) :
|
SetOption(string groupName, unsigned int optionID, unsigned int optionValue, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
groupName(groupName),
|
groupName(groupName),
|
||||||
optionID(optionID),
|
optionID(optionID),
|
||||||
optionValue(optionValue),
|
optionValue(optionValue),
|
||||||
@@ -360,7 +370,8 @@ public:
|
|||||||
priority = CommandPriority::HIGH;
|
priority = CommandPriority::HIGH;
|
||||||
};
|
};
|
||||||
|
|
||||||
SetOption(string groupName, unsigned int optionID, bool optionBool) :
|
SetOption(string groupName, unsigned int optionID, bool optionBool, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
groupName(groupName),
|
groupName(groupName),
|
||||||
optionID(optionID),
|
optionID(optionID),
|
||||||
optionValue(0),
|
optionValue(0),
|
||||||
@@ -370,7 +381,7 @@ public:
|
|||||||
priority = CommandPriority::HIGH;
|
priority = CommandPriority::HIGH;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return 1; }
|
virtual unsigned int getLoad() { return 5; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string groupName;
|
const string groupName;
|
||||||
@@ -384,14 +395,15 @@ private:
|
|||||||
class SetOnOff : public Command
|
class SetOnOff : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SetOnOff(string groupName, bool onOff) :
|
SetOnOff(string groupName, bool onOff, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
groupName(groupName),
|
groupName(groupName),
|
||||||
onOff(onOff)
|
onOff(onOff)
|
||||||
{
|
{
|
||||||
priority = CommandPriority::HIGH;
|
priority = CommandPriority::HIGH;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return 1; }
|
virtual unsigned int getLoad() { return 5; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const string groupName;
|
const string groupName;
|
||||||
@@ -402,16 +414,19 @@ private:
|
|||||||
class Explosion : public Command
|
class Explosion : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Explosion(unsigned int intensity, Coords location) :
|
Explosion(unsigned int intensity, string explosionType, Coords location, function<void(void)> callback = [](){}) :
|
||||||
|
Command(callback),
|
||||||
location(location),
|
location(location),
|
||||||
intensity(intensity)
|
intensity(intensity),
|
||||||
|
explosionType(explosionType)
|
||||||
{
|
{
|
||||||
priority = CommandPriority::MEDIUM;
|
priority = CommandPriority::MEDIUM;
|
||||||
};
|
};
|
||||||
virtual string getString();
|
virtual string getString();
|
||||||
virtual unsigned int getLoad() { return 4; }
|
virtual unsigned int getLoad() { return 5; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Coords location;
|
const Coords location;
|
||||||
const unsigned int intensity;
|
const unsigned int intensity;
|
||||||
|
const string explosionType;
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
namespace DataIndex {
|
namespace DataIndex {
|
||||||
enum DataIndexes {
|
enum DataIndexes {
|
||||||
@@ -19,9 +19,12 @@ namespace DataIndex {
|
|||||||
hasTask,
|
hasTask,
|
||||||
position,
|
position,
|
||||||
speed,
|
speed,
|
||||||
|
horizontalVelocity,
|
||||||
|
verticalVelocity,
|
||||||
heading,
|
heading,
|
||||||
isTanker,
|
track,
|
||||||
isAWACS,
|
isActiveTanker,
|
||||||
|
isActiveAWACS,
|
||||||
onOff,
|
onOff,
|
||||||
followRoads,
|
followRoads,
|
||||||
fuel,
|
fuel,
|
||||||
@@ -43,6 +46,10 @@ namespace DataIndex {
|
|||||||
contacts,
|
contacts,
|
||||||
activePath,
|
activePath,
|
||||||
isLeader,
|
isLeader,
|
||||||
|
operateAs,
|
||||||
|
shotsScatter,
|
||||||
|
shotsIntensity,
|
||||||
|
health,
|
||||||
lastIndex,
|
lastIndex,
|
||||||
endOfData = 255
|
endOfData = 255
|
||||||
};
|
};
|
||||||
@@ -64,7 +71,33 @@ namespace State
|
|||||||
BOMB_POINT,
|
BOMB_POINT,
|
||||||
CARPET_BOMB,
|
CARPET_BOMB,
|
||||||
BOMB_BUILDING,
|
BOMB_BUILDING,
|
||||||
FIRE_AT_AREA
|
FIRE_AT_AREA,
|
||||||
|
SIMULATE_FIRE_FIGHT,
|
||||||
|
SCENIC_AAA,
|
||||||
|
MISS_ON_PURPOSE,
|
||||||
|
LAND_AT_POINT
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ShotsScatter
|
||||||
|
{
|
||||||
|
enum ShotsScatters
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
HIGH,
|
||||||
|
MEDIUM,
|
||||||
|
LOW
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ShotsIntensity
|
||||||
|
{
|
||||||
|
enum ShotsIntensities
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
LOW,
|
||||||
|
MEDIUM,
|
||||||
|
HIGH
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,3 +147,16 @@ bool operator==(const DataTypes::Radio& lhs, const DataTypes::Radio& rhs);
|
|||||||
bool operator==(const DataTypes::GeneralSettings& lhs, const DataTypes::GeneralSettings& rhs);
|
bool operator==(const DataTypes::GeneralSettings& lhs, const DataTypes::GeneralSettings& rhs);
|
||||||
bool operator==(const DataTypes::Ammo& lhs, const DataTypes::Ammo& rhs);
|
bool operator==(const DataTypes::Ammo& lhs, const DataTypes::Ammo& rhs);
|
||||||
bool operator==(const DataTypes::Contact& lhs, const DataTypes::Contact& rhs);
|
bool operator==(const DataTypes::Contact& lhs, const DataTypes::Contact& rhs);
|
||||||
|
|
||||||
|
struct SpawnOptions {
|
||||||
|
string unitType;
|
||||||
|
Coords location;
|
||||||
|
string loadout;
|
||||||
|
string skill;
|
||||||
|
string liveryID;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CloneOptions {
|
||||||
|
unsigned int ID;
|
||||||
|
Coords location;
|
||||||
|
};
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
|
|
||||||
#define GROUND_DEST_DIST_THR 100
|
#define GROUND_DEST_DIST_THR 10
|
||||||
|
|
||||||
class GroundUnit : public Unit
|
class GroundUnit : public Unit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GroundUnit(json::value json, unsigned int ID);
|
GroundUnit(json::value json, unsigned int ID);
|
||||||
|
|
||||||
|
static void loadDatabase(string path);
|
||||||
|
|
||||||
virtual void setState(unsigned char newState);
|
virtual void setState(unsigned char newState);
|
||||||
virtual void setDefaults(bool force = false);
|
virtual void setDefaults(bool force = false);
|
||||||
|
|
||||||
@@ -15,6 +17,9 @@ public:
|
|||||||
virtual void setOnOff(bool newOnOff, bool force = false);
|
virtual void setOnOff(bool newOnOff, bool force = false);
|
||||||
virtual void setFollowRoads(bool newFollowRoads, bool force = false);
|
virtual void setFollowRoads(bool newFollowRoads, bool force = false);
|
||||||
|
|
||||||
|
void aimAtPoint(Coords aimTarget);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void AIloop();
|
virtual void AIloop();
|
||||||
|
static json::value database;
|
||||||
};
|
};
|
||||||
20
backend/core/include/helicopter.h
Normal file
20
backend/core/include/helicopter.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "airunit.h"
|
||||||
|
|
||||||
|
#define HELICOPTER_DEST_DIST_THR 500 // Meters
|
||||||
|
|
||||||
|
class Helicopter : public AirUnit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Helicopter(json::value json, unsigned int ID);
|
||||||
|
|
||||||
|
static void loadDatabase(string path);
|
||||||
|
|
||||||
|
virtual void changeSpeed(string change);
|
||||||
|
virtual void changeAltitude(string change);
|
||||||
|
|
||||||
|
virtual double getDestinationReachedThreshold() { return HELICOPTER_DEST_DIST_THR; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static json::value database;
|
||||||
|
};
|
||||||
@@ -8,6 +8,8 @@ class NavyUnit : public Unit
|
|||||||
public:
|
public:
|
||||||
NavyUnit(json::value json, unsigned int ID);
|
NavyUnit(json::value json, unsigned int ID);
|
||||||
|
|
||||||
|
static void loadDatabase(string path);
|
||||||
|
|
||||||
virtual void setState(unsigned char newState);
|
virtual void setState(unsigned char newState);
|
||||||
virtual void setDefaults(bool force = false);
|
virtual void setDefaults(bool force = false);
|
||||||
|
|
||||||
@@ -16,5 +18,5 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void AIloop();
|
virtual void AIloop();
|
||||||
|
static json::value database;
|
||||||
};
|
};
|
||||||
@@ -11,38 +11,40 @@ public:
|
|||||||
|
|
||||||
void appendCommand(Command* command);
|
void appendCommand(Command* command);
|
||||||
void execute(lua_State* L);
|
void execute(lua_State* L);
|
||||||
void handleRequest(string key, json::value value, string username);
|
void handleRequest(string key, json::value value, string username, json::value& answer);
|
||||||
bool checkSpawnPoints(int spawnPoints, string coalition);
|
bool checkSpawnPoints(int spawnPoints, string coalition);
|
||||||
|
bool isCommandExecuted(string commandHash) { return (find(executedCommandsHashes.begin(), executedCommandsHashes.end(), commandHash) != executedCommandsHashes.end()); }
|
||||||
|
|
||||||
void setFrameRate(double newFrameRate) { frameRate = newFrameRate; }
|
void setFrameRate(double newFrameRate) { frameRate = newFrameRate; }
|
||||||
void setRestrictSpawns(bool newRestrictSpawns) { restrictSpawns = newRestrictSpawns; }
|
void setRestrictSpawns(bool newRestrictSpawns) { restrictSpawns = newRestrictSpawns; }
|
||||||
void setRestrictToCoalition(bool newRestrictToCoalition) { restrictToCoalition = newRestrictToCoalition; }
|
void setRestrictToCoalition(bool newRestrictToCoalition) { restrictToCoalition = newRestrictToCoalition; }
|
||||||
void setSetupTime(unsigned int newSetupTime) { setupTime = newSetupTime; }
|
void setSetupTime(unsigned int newSetupTime) { setupTime = newSetupTime; }
|
||||||
void setBlueSpawnPoints(unsigned int newBlueSpawnPoints) { blueSpawnPoints = newBlueSpawnPoints; }
|
void setBlueSpawnPoints(int newBlueSpawnPoints) { blueSpawnPoints = newBlueSpawnPoints; }
|
||||||
void setRedSpawnPoints(unsigned int newRedSpawnPoints) { redSpawnPoints = newRedSpawnPoints; }
|
void setRedSpawnPoints(int newRedSpawnPoints) { redSpawnPoints = newRedSpawnPoints; }
|
||||||
void setEras(vector<string> newEras) { eras = newEras; }
|
void setEras(vector<string> newEras) { eras = newEras; }
|
||||||
void setCommandModeOptions(json::value newOptions);
|
void setCommandModeOptions(json::value newOptions);
|
||||||
|
|
||||||
int getFrameRate() { return frameRate; };
|
int getFrameRate() { return static_cast<int>(round(frameRate)); };
|
||||||
int getLoad();
|
int getLoad();
|
||||||
bool getRestrictSpawns() { return restrictSpawns; }
|
bool getRestrictSpawns() { return restrictSpawns; }
|
||||||
bool getRestrictToCoalition() { return restrictToCoalition; }
|
bool getRestrictToCoalition() { return restrictToCoalition; }
|
||||||
unsigned int getSetupTime() { return setupTime; }
|
unsigned int getSetupTime() { return setupTime; }
|
||||||
unsigned int getBlueSpawnPoints() { return blueSpawnPoints; }
|
int getBlueSpawnPoints() { return blueSpawnPoints; }
|
||||||
unsigned int getRedSpawnPoints() { return redSpawnPoints; }
|
int getRedSpawnPoints() { return redSpawnPoints; }
|
||||||
vector<string> getEras() { return eras; }
|
vector<string> getEras() { return eras; }
|
||||||
json::value getCommandModeOptions();
|
json::value getCommandModeOptions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
list<Command*> commands;
|
list<Command*> commands;
|
||||||
unsigned int load;
|
list<string> executedCommandsHashes;
|
||||||
double frameRate;
|
unsigned int load = 0;
|
||||||
|
double frameRate = 0;
|
||||||
|
|
||||||
bool restrictSpawns = false;
|
bool restrictSpawns = false;
|
||||||
bool restrictToCoalition = false;
|
bool restrictToCoalition = false;
|
||||||
unsigned int setupTime = 300;
|
unsigned int setupTime = 300;
|
||||||
unsigned int blueSpawnPoints = 10000;
|
int blueSpawnPoints = 10000;
|
||||||
unsigned int redSpawnPoints = 10000;
|
int redSpawnPoints = 10000;
|
||||||
vector<string> eras = { "WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern" };
|
vector<string> eras = { "WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern" };
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5,7 +5,11 @@
|
|||||||
function Olympus.protectedCall(...)\n\n \
|
function Olympus.protectedCall(...)\n\n \
|
||||||
local status, retval = pcall(...)\n \
|
local status, retval = pcall(...)\n \
|
||||||
if not status then\n \
|
if not status then\n \
|
||||||
trigger.action.outText(\"ERROR: \" ..retval, 20)\n \
|
if Olympus.log ~= nil then\n \
|
||||||
|
Olympus.log:error(retval)\n \
|
||||||
|
else\n \
|
||||||
|
trigger.action.outText(\"Olympus critical error: \" ..retval, 20)\n \
|
||||||
|
end\n \
|
||||||
end\n \
|
end\n \
|
||||||
end\n \
|
end\n \
|
||||||
trigger.action.outText(\"Olympus.protectedCall registered successfully\", 10)\n"
|
trigger.action.outText(\"Olympus.protectedCall registered successfully\", 10)\n"
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "dcstools.h"
|
#include "dcstools.h"
|
||||||
#include "luatools.h"
|
#include "luatools.h"
|
||||||
#include "measure.h"
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
@@ -54,6 +53,9 @@ public:
|
|||||||
void resetTask();
|
void resetTask();
|
||||||
bool checkTaskFailed();
|
bool checkTaskFailed();
|
||||||
void resetTaskFailedCounter();
|
void resetTaskFailedCounter();
|
||||||
|
void setHasTaskAssigned(bool newHasTaskAssigned);
|
||||||
|
void setEnableTaskCheckFailed(bool newEnableTaskCheckFailed) { enableTaskFailedCheck = newEnableTaskCheckFailed; }
|
||||||
|
bool getEnableTaskCheckFailed() { return enableTaskFailedCheck; }
|
||||||
|
|
||||||
void triggerUpdate(unsigned char datumIndex);
|
void triggerUpdate(unsigned char datumIndex);
|
||||||
|
|
||||||
@@ -72,12 +74,15 @@ public:
|
|||||||
virtual void setGroupName(string newValue) { updateValue(groupName, newValue, DataIndex::groupName); }
|
virtual void setGroupName(string newValue) { updateValue(groupName, newValue, DataIndex::groupName); }
|
||||||
virtual void setState(unsigned char newValue) { updateValue(state, newValue, DataIndex::state); };
|
virtual void setState(unsigned char newValue) { updateValue(state, newValue, DataIndex::state); };
|
||||||
virtual void setTask(string newValue) { updateValue(task, newValue, DataIndex::task); }
|
virtual void setTask(string newValue) { updateValue(task, newValue, DataIndex::task); }
|
||||||
virtual void setHasTask(bool newValue) { updateValue(hasTask, newValue, DataIndex::hasTask); }
|
virtual void setHasTask(bool newValue);
|
||||||
virtual void setPosition(Coords newValue) { updateValue(position, newValue, DataIndex::position); }
|
virtual void setPosition(Coords newValue) { updateValue(position, newValue, DataIndex::position); }
|
||||||
virtual void setSpeed(double newValue) { updateValue(speed, newValue, DataIndex::speed); }
|
virtual void setSpeed(double newValue) { updateValue(speed, newValue, DataIndex::speed); }
|
||||||
|
virtual void setHorizontalVelocity(double newValue) { updateValue(horizontalVelocity, newValue, DataIndex::horizontalVelocity); }
|
||||||
|
virtual void setVerticalVelocity(double newValue) { updateValue(verticalVelocity, newValue, DataIndex::verticalVelocity); }
|
||||||
virtual void setHeading(double newValue) { updateValue(heading, newValue, DataIndex::heading); }
|
virtual void setHeading(double newValue) { updateValue(heading, newValue, DataIndex::heading); }
|
||||||
virtual void setIsTanker(bool newValue);
|
virtual void setTrack(double newValue) { updateValue(track, newValue, DataIndex::track); }
|
||||||
virtual void setIsAWACS(bool newValue);
|
virtual void setIsActiveTanker(bool newValue);
|
||||||
|
virtual void setIsActiveAWACS(bool newValue);
|
||||||
virtual void setOnOff(bool newValue, bool force = false) { updateValue(onOff, newValue, DataIndex::onOff); };
|
virtual void setOnOff(bool newValue, bool force = false) { updateValue(onOff, newValue, DataIndex::onOff); };
|
||||||
virtual void setFollowRoads(bool newValue, bool force = false) { updateValue(followRoads, newValue, DataIndex::followRoads); };
|
virtual void setFollowRoads(bool newValue, bool force = false) { updateValue(followRoads, newValue, DataIndex::followRoads); };
|
||||||
virtual void setFuel(unsigned short newValue) { updateValue(fuel, newValue, DataIndex::fuel); }
|
virtual void setFuel(unsigned short newValue) { updateValue(fuel, newValue, DataIndex::fuel); }
|
||||||
@@ -99,6 +104,10 @@ public:
|
|||||||
virtual void setContacts(vector<DataTypes::Contact> newValue);
|
virtual void setContacts(vector<DataTypes::Contact> newValue);
|
||||||
virtual void setActivePath(list<Coords> newValue);
|
virtual void setActivePath(list<Coords> newValue);
|
||||||
virtual void setIsLeader(bool newValue) { updateValue(isLeader, newValue, DataIndex::isLeader); }
|
virtual void setIsLeader(bool newValue) { updateValue(isLeader, newValue, DataIndex::isLeader); }
|
||||||
|
virtual void setOperateAs(unsigned char newValue) { updateValue(operateAs, newValue, DataIndex::operateAs); }
|
||||||
|
virtual void setShotsScatter(unsigned char newValue) { updateValue(shotsScatter, newValue, DataIndex::shotsScatter); }
|
||||||
|
virtual void setShotsIntensity(unsigned char newValue) { updateValue(shotsIntensity, newValue, DataIndex::shotsIntensity); }
|
||||||
|
virtual void setHealth(unsigned char newValue) { updateValue(health, newValue, DataIndex::health); }
|
||||||
|
|
||||||
/********** Getters **********/
|
/********** Getters **********/
|
||||||
virtual string getCategory() { return category; };
|
virtual string getCategory() { return category; };
|
||||||
@@ -115,9 +124,12 @@ public:
|
|||||||
virtual bool getHasTask() { return hasTask; }
|
virtual bool getHasTask() { return hasTask; }
|
||||||
virtual Coords getPosition() { return position; }
|
virtual Coords getPosition() { return position; }
|
||||||
virtual double getSpeed() { return speed; }
|
virtual double getSpeed() { return speed; }
|
||||||
|
virtual double getHorizontalVelocity() { return horizontalVelocity; }
|
||||||
|
virtual double getVerticalVelocity() { return verticalVelocity; }
|
||||||
virtual double getHeading() { return heading; }
|
virtual double getHeading() { return heading; }
|
||||||
virtual bool getIsTanker() { return isTanker; }
|
virtual double getTrack() { return track; }
|
||||||
virtual bool getIsAWACS() { return isAWACS; }
|
virtual bool getIsActiveTanker() { return isActiveTanker; }
|
||||||
|
virtual bool getIsActiveAWACS() { return isActiveAWACS; }
|
||||||
virtual bool getOnOff() { return onOff; };
|
virtual bool getOnOff() { return onOff; };
|
||||||
virtual bool getFollowRoads() { return followRoads; };
|
virtual bool getFollowRoads() { return followRoads; };
|
||||||
virtual unsigned short getFuel() { return fuel; }
|
virtual unsigned short getFuel() { return fuel; }
|
||||||
@@ -136,9 +148,13 @@ public:
|
|||||||
virtual DataTypes::Radio getRadio() { return radio; }
|
virtual DataTypes::Radio getRadio() { return radio; }
|
||||||
virtual DataTypes::GeneralSettings getGeneralSettings() { return generalSettings; }
|
virtual DataTypes::GeneralSettings getGeneralSettings() { return generalSettings; }
|
||||||
virtual vector<DataTypes::Ammo> getAmmo() { return ammo; }
|
virtual vector<DataTypes::Ammo> getAmmo() { return ammo; }
|
||||||
virtual vector<DataTypes::Contact> getTargets() { return contacts; }
|
virtual vector<DataTypes::Contact> getContacts() { return contacts; }
|
||||||
virtual list<Coords> getActivePath() { return activePath; }
|
virtual list<Coords> getActivePath() { return activePath; }
|
||||||
virtual bool getIsLeader() { return isLeader; }
|
virtual bool getIsLeader() { return isLeader; }
|
||||||
|
virtual unsigned char getOperateAs() { return operateAs; }
|
||||||
|
virtual unsigned char getShotsScatter() { return shotsScatter; }
|
||||||
|
virtual unsigned char getShotsIntensity() { return shotsIntensity; }
|
||||||
|
virtual unsigned char getHealth() { return health; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned int ID;
|
unsigned int ID;
|
||||||
@@ -157,16 +173,19 @@ protected:
|
|||||||
bool hasTask = false;
|
bool hasTask = false;
|
||||||
Coords position = Coords(NULL);
|
Coords position = Coords(NULL);
|
||||||
double speed = NULL;
|
double speed = NULL;
|
||||||
|
double horizontalVelocity = NULL;
|
||||||
|
double verticalVelocity = NULL;
|
||||||
double heading = NULL;
|
double heading = NULL;
|
||||||
bool isTanker = false;
|
double track = NULL;
|
||||||
bool isAWACS = false;
|
bool isActiveTanker = false;
|
||||||
|
bool isActiveAWACS = false;
|
||||||
bool onOff = true;
|
bool onOff = true;
|
||||||
bool followRoads = false;
|
bool followRoads = false;
|
||||||
unsigned short fuel = 0;
|
unsigned short fuel = 0;
|
||||||
double desiredSpeed = 0;
|
double desiredSpeed = 0;
|
||||||
bool desiredSpeedType = 1;
|
bool desiredSpeedType = 0; /* CAS */
|
||||||
double desiredAltitude = 0;
|
double desiredAltitude = 1;
|
||||||
bool desiredAltitudeType = 1;
|
bool desiredAltitudeType = 0; /* ASL */
|
||||||
unsigned int leaderID = NULL;
|
unsigned int leaderID = NULL;
|
||||||
Offset formationOffset = Offset(NULL);
|
Offset formationOffset = Offset(NULL);
|
||||||
unsigned int targetID = NULL;
|
unsigned int targetID = NULL;
|
||||||
@@ -181,19 +200,27 @@ protected:
|
|||||||
vector<DataTypes::Contact> contacts;
|
vector<DataTypes::Contact> contacts;
|
||||||
list<Coords> activePath;
|
list<Coords> activePath;
|
||||||
bool isLeader = false;
|
bool isLeader = false;
|
||||||
|
unsigned char operateAs = 2;
|
||||||
Coords activeDestination = Coords(NULL);
|
Coords activeDestination = Coords(NULL);
|
||||||
|
unsigned char shotsScatter = 2;
|
||||||
|
unsigned char shotsIntensity = 2;
|
||||||
|
unsigned char health = 100;
|
||||||
|
|
||||||
/********** Other **********/
|
/********** Other **********/
|
||||||
unsigned int taskCheckCounter = 0;
|
unsigned int taskCheckCounter = 0;
|
||||||
|
unsigned int internalCounter = 0;
|
||||||
|
Unit* missOnPurposeTarget = nullptr;
|
||||||
|
bool hasTaskAssigned = false;
|
||||||
double initialFuel = 0;
|
double initialFuel = 0;
|
||||||
map<unsigned char, unsigned long long> updateTimeMap;
|
map<unsigned char, unsigned long long> updateTimeMap;
|
||||||
unsigned long long lastLoopTime = 0;
|
unsigned long long lastLoopTime = 0;
|
||||||
|
bool enableTaskFailedCheck = false;
|
||||||
|
|
||||||
/********** Private methods **********/
|
/********** Private methods **********/
|
||||||
virtual void AIloop() = 0;
|
virtual void AIloop() = 0;
|
||||||
|
|
||||||
void appendString(stringstream& ss, const unsigned char& datumIndex, const string& datumValue) {
|
void appendString(stringstream& ss, const unsigned char& datumIndex, const string& datumValue) {
|
||||||
const unsigned short size = datumValue.size();
|
const unsigned short size = static_cast<unsigned short>(datumValue.size());
|
||||||
ss.write((const char*)&datumIndex, sizeof(unsigned char));
|
ss.write((const char*)&datumIndex, sizeof(unsigned char));
|
||||||
ss.write((const char*)&size, sizeof(unsigned short));
|
ss.write((const char*)&size, sizeof(unsigned short));
|
||||||
ss << datumValue;
|
ss << datumValue;
|
||||||
@@ -218,7 +245,7 @@ protected:
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void appendVector(stringstream& ss, const unsigned char& datumIndex, vector<T>& datumValue) {
|
void appendVector(stringstream& ss, const unsigned char& datumIndex, vector<T>& datumValue) {
|
||||||
const unsigned short size = datumValue.size();
|
const unsigned short size = static_cast<unsigned short>(datumValue.size());
|
||||||
ss.write((const char*)&datumIndex, sizeof(unsigned char));
|
ss.write((const char*)&datumIndex, sizeof(unsigned char));
|
||||||
ss.write((const char*)&size, sizeof(unsigned short));
|
ss.write((const char*)&size, sizeof(unsigned short));
|
||||||
|
|
||||||
@@ -228,7 +255,7 @@ protected:
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void appendList(stringstream& ss, const unsigned char& datumIndex, list<T>& datumValue) {
|
void appendList(stringstream& ss, const unsigned char& datumIndex, list<T>& datumValue) {
|
||||||
const unsigned short size = datumValue.size();
|
const unsigned short size = static_cast<unsigned short>(datumValue.size());;
|
||||||
ss.write((const char*)&datumIndex, sizeof(unsigned char));
|
ss.write((const char*)&datumIndex, sizeof(unsigned char));
|
||||||
ss.write((const char*)&size, sizeof(unsigned short));
|
ss.write((const char*)&size, sizeof(unsigned short));
|
||||||
|
|
||||||
@@ -20,9 +20,12 @@ public:
|
|||||||
void update(json::value& missionData, double dt);
|
void update(json::value& missionData, double dt);
|
||||||
void runAILoop();
|
void runAILoop();
|
||||||
void getUnitData(stringstream &ss, unsigned long long time);
|
void getUnitData(stringstream &ss, unsigned long long time);
|
||||||
void deleteUnit(unsigned int ID, bool explosion, bool immediate);
|
void deleteUnit(unsigned int ID, bool explosion, string explosionType, bool immediate);
|
||||||
void acquireControl(unsigned int ID);
|
void acquireControl(unsigned int ID);
|
||||||
|
void loadDatabases();
|
||||||
|
Unit* getClosestUnit(Unit* unit, unsigned char coalition, vector<string> categories, double &distance);
|
||||||
|
map<Unit*, double> getUnitsInRange(Unit* unit, unsigned char coalition, vector<string> categories, double range);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
map<unsigned int, Unit*> units;
|
map<unsigned int, Unit*> units;
|
||||||
json::value missionDB;
|
json::value missionDB;
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "dcstools.h"
|
#include "dcstools.h"
|
||||||
#include "luatools.h"
|
#include "luatools.h"
|
||||||
#include "measure.h"
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
@@ -60,7 +59,7 @@ protected:
|
|||||||
|
|
||||||
/********** Private methods **********/
|
/********** Private methods **********/
|
||||||
void appendString(stringstream& ss, const unsigned char& datumIndex, const string& datumValue) {
|
void appendString(stringstream& ss, const unsigned char& datumIndex, const string& datumValue) {
|
||||||
const unsigned short size = datumValue.size();
|
const unsigned short size = static_cast<unsigned short>(datumValue.size());
|
||||||
ss.write((const char*)&datumIndex, sizeof(unsigned char));
|
ss.write((const char*)&datumIndex, sizeof(unsigned char));
|
||||||
ss.write((const char*)&size, sizeof(unsigned short));
|
ss.write((const char*)&size, sizeof(unsigned short));
|
||||||
ss << datumValue;
|
ss << datumValue;
|
||||||
14
backend/core/resource.h
Normal file
14
backend/core/resource.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by core.rc
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -11,6 +11,20 @@ using namespace GeographicLib;
|
|||||||
|
|
||||||
extern Scheduler* scheduler;
|
extern Scheduler* scheduler;
|
||||||
extern UnitsManager* unitsManager;
|
extern UnitsManager* unitsManager;
|
||||||
|
json::value Aircraft::database = json::value();
|
||||||
|
extern string instancePath;
|
||||||
|
|
||||||
|
void Aircraft::loadDatabase(string path) {
|
||||||
|
std::ifstream ifstream(instancePath + path);
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << ifstream.rdbuf();
|
||||||
|
std::error_code errorCode;
|
||||||
|
database = json::value::parse(ss.str(), errorCode);
|
||||||
|
if (database.is_object())
|
||||||
|
log("Aircrafts database loaded correctly from " + instancePath + path);
|
||||||
|
else
|
||||||
|
log("Error reading Aircrafts database file");
|
||||||
|
}
|
||||||
|
|
||||||
/* Aircraft */
|
/* Aircraft */
|
||||||
Aircraft::Aircraft(json::value json, unsigned int ID) : AirUnit(json, ID)
|
Aircraft::Aircraft(json::value json, unsigned int ID) : AirUnit(json, ID)
|
||||||
@@ -20,7 +34,6 @@ Aircraft::Aircraft(json::value json, unsigned int ID) : AirUnit(json, ID)
|
|||||||
setCategory("Aircraft");
|
setCategory("Aircraft");
|
||||||
setDesiredSpeed(knotsToMs(300));
|
setDesiredSpeed(knotsToMs(300));
|
||||||
setDesiredAltitude(ftToM(20000));
|
setDesiredAltitude(ftToM(20000));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Aircraft::changeSpeed(string change)
|
void Aircraft::changeSpeed(string change)
|
||||||
@@ -34,11 +47,6 @@ void Aircraft::changeSpeed(string change)
|
|||||||
|
|
||||||
if (getDesiredSpeed() < knotsToMs(50))
|
if (getDesiredSpeed() < knotsToMs(50))
|
||||||
setDesiredSpeed(knotsToMs(50));
|
setDesiredSpeed(knotsToMs(50));
|
||||||
|
|
||||||
if (state == State::IDLE)
|
|
||||||
resetTask();
|
|
||||||
else
|
|
||||||
goToDestination(); /* Send the command to reach the destination */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Aircraft::changeAltitude(string change)
|
void Aircraft::changeAltitude(string change)
|
||||||
@@ -55,14 +63,9 @@ void Aircraft::changeAltitude(string change)
|
|||||||
if (getDesiredAltitude() > 5000)
|
if (getDesiredAltitude() > 5000)
|
||||||
setDesiredAltitude(getDesiredAltitude() + ftToM(2500));
|
setDesiredAltitude(getDesiredAltitude() + ftToM(2500));
|
||||||
else if (getDesiredAltitude() >= 0)
|
else if (getDesiredAltitude() >= 0)
|
||||||
setDesiredAltitude(getDesiredAltitude() + ftToM(500));
|
setDesiredAltitude(getDesiredAltitude() + ftToM(500));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getDesiredAltitude() < 0)
|
if (getDesiredAltitude() < 0)
|
||||||
setDesiredAltitude(0);
|
setDesiredAltitude(0);
|
||||||
|
|
||||||
if (state == State::IDLE)
|
|
||||||
resetTask();
|
|
||||||
else
|
|
||||||
goToDestination(); /* Send the command to reach the destination */
|
|
||||||
}
|
}
|
||||||
@@ -40,6 +40,8 @@ void AirUnit::setDefaults(bool force)
|
|||||||
|
|
||||||
void AirUnit::setState(unsigned char newState)
|
void AirUnit::setState(unsigned char newState)
|
||||||
{
|
{
|
||||||
|
Coords currentTargetPosition = getTargetPosition();
|
||||||
|
|
||||||
/************ Perform any action required when LEAVING a state ************/
|
/************ Perform any action required when LEAVING a state ************/
|
||||||
if (newState != state) {
|
if (newState != state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -69,6 +71,9 @@ void AirUnit::setState(unsigned char newState)
|
|||||||
setTargetPosition(Coords(NULL));
|
setTargetPosition(Coords(NULL));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case State::LAND_AT_POINT: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -77,15 +82,18 @@ void AirUnit::setState(unsigned char newState)
|
|||||||
/************ Perform any action required when ENTERING a state ************/
|
/************ Perform any action required when ENTERING a state ************/
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
case State::IDLE: {
|
case State::IDLE: {
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
clearActivePath();
|
clearActivePath();
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::REACH_DESTINATION: {
|
case State::REACH_DESTINATION: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::ATTACK: {
|
case State::ATTACK: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
if (isTargetAlive()) {
|
if (isTargetAlive()) {
|
||||||
Unit* target = unitsManager->getUnit(targetID);
|
Unit* target = unitsManager->getUnit(targetID);
|
||||||
Coords targetPosition = Coords(target->getPosition().lat, target->getPosition().lng, 0);
|
Coords targetPosition = Coords(target->getPosition().lat, target->getPosition().lng, 0);
|
||||||
@@ -96,67 +104,85 @@ void AirUnit::setState(unsigned char newState)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::FOLLOW: {
|
case State::FOLLOW: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
clearActivePath();
|
clearActivePath();
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::LAND: {
|
case State::LAND: {
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::REFUEL: {
|
case State::REFUEL: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
initialFuel = fuel;
|
initialFuel = fuel;
|
||||||
clearActivePath();
|
clearActivePath();
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::BOMB_POINT: {
|
case State::BOMB_POINT:
|
||||||
clearActivePath();
|
case State::CARPET_BOMB:
|
||||||
resetActiveDestination();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case State::CARPET_BOMB: {
|
|
||||||
clearActivePath();
|
|
||||||
resetActiveDestination();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case State::BOMB_BUILDING: {
|
case State::BOMB_BUILDING: {
|
||||||
|
setTargetPosition(currentTargetPosition);
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
clearActivePath();
|
clearActivePath();
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case State::LAND_AT_POINT: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
resetTask();
|
setHasTask(false);
|
||||||
|
resetTaskFailedCounter();
|
||||||
|
|
||||||
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
|
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
|
||||||
state = newState;
|
state = newState;
|
||||||
|
|
||||||
triggerUpdate(DataIndex::state);
|
triggerUpdate(DataIndex::state);
|
||||||
|
|
||||||
|
AIloop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AirUnit::AIloop()
|
void AirUnit::AIloop()
|
||||||
{
|
{
|
||||||
|
srand(static_cast<unsigned int>(time(NULL)) + ID);
|
||||||
|
|
||||||
/* State machine */
|
/* State machine */
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case State::IDLE: {
|
case State::IDLE: {
|
||||||
setTask("Idle");
|
if (isActiveTanker)
|
||||||
|
setTask("Tanker racetrack");
|
||||||
|
else if (isActiveAWACS)
|
||||||
|
setTask("AWACS racetrack");
|
||||||
|
else
|
||||||
|
setTask("Idle");
|
||||||
|
|
||||||
if (!getHasTask())
|
if (!getHasTask())
|
||||||
{
|
{
|
||||||
std::ostringstream taskSS;
|
std::ostringstream taskSS;
|
||||||
if (isTanker) {
|
if (isActiveTanker) {
|
||||||
taskSS << "{ [1] = { id = 'Tanker' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " << desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitudeType << "' } }";
|
taskSS << "{ [1] = { id = 'Tanker' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " <<
|
||||||
|
desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" <<
|
||||||
|
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "' }}";
|
||||||
}
|
}
|
||||||
else if (isAWACS) {
|
else if (isActiveAWACS) {
|
||||||
taskSS << "{ [1] = { id = 'AWACS' }, [2] = { id = 'Orbit', pattern = 'Circle', altitude = " << desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitudeType << "' } }";
|
taskSS << "{ [1] = { id = 'AWACS' }, [2] = { id = 'Orbit', pattern = 'Circle', altitude = " <<
|
||||||
|
desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" <<
|
||||||
|
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "' }}";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
taskSS << "{ id = 'Orbit', pattern = 'Circle', altitude = " << desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitudeType << "' }";
|
taskSS << "{ id = 'Orbit', pattern = 'Circle', altitude = " <<
|
||||||
|
desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" <<
|
||||||
|
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "'}";
|
||||||
}
|
}
|
||||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(true);
|
setHasTask(true);
|
||||||
}
|
}
|
||||||
@@ -166,12 +192,12 @@ void AirUnit::AIloop()
|
|||||||
string enrouteTask = "";
|
string enrouteTask = "";
|
||||||
bool looping = false;
|
bool looping = false;
|
||||||
|
|
||||||
if (isTanker)
|
if (isActiveTanker)
|
||||||
{
|
{
|
||||||
enrouteTask = "{ id = 'Tanker' }";
|
enrouteTask = "{ id = 'Tanker' }";
|
||||||
setTask("Tanker");
|
setTask("Tanker");
|
||||||
}
|
}
|
||||||
else if (isAWACS)
|
else if (isActiveAWACS)
|
||||||
{
|
{
|
||||||
enrouteTask = "{ id = 'AWACS' }";
|
enrouteTask = "{ id = 'AWACS' }";
|
||||||
setTask("AWACS");
|
setTask("AWACS");
|
||||||
@@ -190,7 +216,7 @@ void AirUnit::AIloop()
|
|||||||
goToDestination(enrouteTask);
|
goToDestination(enrouteTask);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isDestinationReached(AIR_DEST_DIST_THR)) {
|
if (isDestinationReached(getDestinationReachedThreshold())) {
|
||||||
if (updateActivePath(looping) && setActiveDestination())
|
if (updateActivePath(looping) && setActiveDestination())
|
||||||
goToDestination(enrouteTask);
|
goToDestination(enrouteTask);
|
||||||
else
|
else
|
||||||
@@ -261,7 +287,7 @@ void AirUnit::AIloop()
|
|||||||
<< "z = " << formationOffset.z
|
<< "z = " << formationOffset.z
|
||||||
<< "},"
|
<< "},"
|
||||||
<< "}";
|
<< "}";
|
||||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(true);
|
setHasTask(true);
|
||||||
}
|
}
|
||||||
@@ -277,7 +303,7 @@ void AirUnit::AIloop()
|
|||||||
taskSS << "{"
|
taskSS << "{"
|
||||||
<< "id = 'Refuel'"
|
<< "id = 'Refuel'"
|
||||||
<< "}";
|
<< "}";
|
||||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(true);
|
setHasTask(true);
|
||||||
}
|
}
|
||||||
@@ -285,25 +311,31 @@ void AirUnit::AIloop()
|
|||||||
setState(State::IDLE);
|
setState(State::IDLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case State::BOMB_POINT: {
|
case State::BOMB_POINT: {
|
||||||
setTask("Bombing point");
|
setTask("Bombing point");
|
||||||
|
|
||||||
if (!getHasTask()) {
|
if (!getHasTask()) {
|
||||||
std::ostringstream taskSS;
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
|
||||||
taskSS << "{id = 'Bombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
|
taskSS << "{id = 'Bombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
|
||||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(true);
|
setHasTask(true);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case State::CARPET_BOMB: {
|
case State::CARPET_BOMB: {
|
||||||
setTask("Carpet bombing");
|
setTask("Carpet bombing");
|
||||||
|
|
||||||
if (!getHasTask()) {
|
if (!getHasTask()) {
|
||||||
std::ostringstream taskSS;
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
|
||||||
taskSS << "{id = 'CarpetBombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
|
taskSS << "{id = 'CarpetBombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
|
||||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(true);
|
setHasTask(true);
|
||||||
}
|
}
|
||||||
@@ -314,8 +346,28 @@ void AirUnit::AIloop()
|
|||||||
|
|
||||||
if (!getHasTask()) {
|
if (!getHasTask()) {
|
||||||
std::ostringstream taskSS;
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
|
||||||
taskSS << "{id = 'AttackMapObject', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
|
taskSS << "{id = 'AttackMapObject', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
|
||||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::LAND_AT_POINT: {
|
||||||
|
setTask("Landing at point");
|
||||||
|
|
||||||
|
if (!getHasTask()) {
|
||||||
|
setActiveDestination();
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10),
|
||||||
|
taskSS << "{"
|
||||||
|
<< "id = 'LandAtPoint', "
|
||||||
|
<< "lat = " << activeDestination.lat << ", "
|
||||||
|
<< "lng = " << activeDestination.lng
|
||||||
|
<< "}";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(true);
|
setHasTask(true);
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,6 @@ extern UnitsManager* unitsManager;
|
|||||||
/* Move command */
|
/* Move command */
|
||||||
string Move::getString()
|
string Move::getString()
|
||||||
{
|
{
|
||||||
|
|
||||||
std::ostringstream commandSS;
|
std::ostringstream commandSS;
|
||||||
commandSS.precision(10);
|
commandSS.precision(10);
|
||||||
commandSS << "Olympus.move, "
|
commandSS << "Olympus.move, "
|
||||||
@@ -40,16 +39,16 @@ string Smoke::getString()
|
|||||||
/* Spawn ground units command */
|
/* Spawn ground units command */
|
||||||
string SpawnGroundUnits::getString()
|
string SpawnGroundUnits::getString()
|
||||||
{
|
{
|
||||||
if (unitTypes.size() != locations.size()) return "";
|
|
||||||
|
|
||||||
std::ostringstream unitsSS;
|
std::ostringstream unitsSS;
|
||||||
unitsSS.precision(10);
|
unitsSS.precision(10);
|
||||||
for (int i = 0; i < unitTypes.size(); i++) {
|
for (int i = 0; i < spawnOptions.size(); i++) {
|
||||||
unitsSS << "[" << i + 1 << "] = {"
|
unitsSS << "[" << i + 1 << "] = {"
|
||||||
<< "unitType = " << "\"" << unitTypes[i] << "\"" << ", "
|
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
|
||||||
<< "lat = " << locations[i].lat << ", "
|
<< "lat = " << spawnOptions[i].location.lat << ", "
|
||||||
<< "lng = " << locations[i].lng << ", "
|
<< "lng = " << spawnOptions[i].location.lng << ", "
|
||||||
<< "liveryID = " << "\"" << liveryIDs[i] << "\"" << " }, ";
|
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
|
||||||
|
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream commandSS;
|
std::ostringstream commandSS;
|
||||||
@@ -57,6 +56,7 @@ string SpawnGroundUnits::getString()
|
|||||||
commandSS << "Olympus.spawnUnits, {"
|
commandSS << "Olympus.spawnUnits, {"
|
||||||
<< "category = " << "\"" << "GroundUnit" << "\"" << ", "
|
<< "category = " << "\"" << "GroundUnit" << "\"" << ", "
|
||||||
<< "coalition = " << "\"" << coalition << "\"" << ", "
|
<< "coalition = " << "\"" << coalition << "\"" << ", "
|
||||||
|
<< "country = \"" << country << "\", "
|
||||||
<< "units = " << "{" << unitsSS.str() << "}" << "}";
|
<< "units = " << "{" << unitsSS.str() << "}" << "}";
|
||||||
return commandSS.str();
|
return commandSS.str();
|
||||||
}
|
}
|
||||||
@@ -65,16 +65,15 @@ string SpawnGroundUnits::getString()
|
|||||||
/* Spawn ground units command */
|
/* Spawn ground units command */
|
||||||
string SpawnNavyUnits::getString()
|
string SpawnNavyUnits::getString()
|
||||||
{
|
{
|
||||||
if (unitTypes.size() != locations.size()) return "";
|
|
||||||
|
|
||||||
std::ostringstream unitsSS;
|
std::ostringstream unitsSS;
|
||||||
unitsSS.precision(10);
|
unitsSS.precision(10);
|
||||||
for (int i = 0; i < unitTypes.size(); i++) {
|
for (int i = 0; i < spawnOptions.size(); i++) {
|
||||||
unitsSS << "[" << i + 1 << "] = {"
|
unitsSS << "[" << i + 1 << "] = {"
|
||||||
<< "unitType = " << "\"" << unitTypes[i] << "\"" << ", "
|
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
|
||||||
<< "lat = " << locations[i].lat << ", "
|
<< "lat = " << spawnOptions[i].location.lat << ", "
|
||||||
<< "lng = " << locations[i].lng << ", "
|
<< "lng = " << spawnOptions[i].location.lng << ", "
|
||||||
<< "liveryID = " << "\"" << liveryIDs[i] << "\"" << " }, ";
|
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
|
||||||
|
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream commandSS;
|
std::ostringstream commandSS;
|
||||||
@@ -82,6 +81,7 @@ string SpawnNavyUnits::getString()
|
|||||||
commandSS << "Olympus.spawnUnits, {"
|
commandSS << "Olympus.spawnUnits, {"
|
||||||
<< "category = " << "\"" << "NavyUnit" << "\"" << ", "
|
<< "category = " << "\"" << "NavyUnit" << "\"" << ", "
|
||||||
<< "coalition = " << "\"" << coalition << "\"" << ", "
|
<< "coalition = " << "\"" << coalition << "\"" << ", "
|
||||||
|
<< "country = \"" << country << "\", "
|
||||||
<< "units = " << "{" << unitsSS.str() << "}" << "}";
|
<< "units = " << "{" << unitsSS.str() << "}" << "}";
|
||||||
return commandSS.str();
|
return commandSS.str();
|
||||||
}
|
}
|
||||||
@@ -89,18 +89,17 @@ string SpawnNavyUnits::getString()
|
|||||||
/* Spawn aircrafts command */
|
/* Spawn aircrafts command */
|
||||||
string SpawnAircrafts::getString()
|
string SpawnAircrafts::getString()
|
||||||
{
|
{
|
||||||
if (unitTypes.size() != locations.size() || unitTypes.size() != loadouts.size()) return "";
|
|
||||||
|
|
||||||
std::ostringstream unitsSS;
|
std::ostringstream unitsSS;
|
||||||
unitsSS.precision(10);
|
unitsSS.precision(10);
|
||||||
for (int i = 0; i < unitTypes.size(); i++) {
|
for (int i = 0; i < spawnOptions.size(); i++) {
|
||||||
unitsSS << "[" << i + 1 << "] = {"
|
unitsSS << "[" << i + 1 << "] = {"
|
||||||
<< "unitType = " << "\"" << unitTypes[i] << "\"" << ", "
|
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
|
||||||
<< "lat = " << locations[i].lat << ", "
|
<< "lat = " << spawnOptions[i].location.lat << ", "
|
||||||
<< "lng = " << locations[i].lng << ", "
|
<< "lng = " << spawnOptions[i].location.lng << ", "
|
||||||
<< "alt = " << locations[i].alt << ", "
|
<< "alt = " << spawnOptions[i].location.alt << ", "
|
||||||
<< "loadout = \"" << loadouts[i] << "\"" << ", "
|
<< "loadout = \"" << spawnOptions[i].loadout << "\"" << ", "
|
||||||
<< "liveryID = " << "\"" << liveryIDs[i] << "\"" << " }, ";
|
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
|
||||||
|
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream commandSS;
|
std::ostringstream commandSS;
|
||||||
@@ -109,6 +108,7 @@ string SpawnAircrafts::getString()
|
|||||||
<< "category = " << "\"" << "Aircraft" << "\"" << ", "
|
<< "category = " << "\"" << "Aircraft" << "\"" << ", "
|
||||||
<< "coalition = " << "\"" << coalition << "\"" << ", "
|
<< "coalition = " << "\"" << coalition << "\"" << ", "
|
||||||
<< "airbaseName = \"" << airbaseName << "\", "
|
<< "airbaseName = \"" << airbaseName << "\", "
|
||||||
|
<< "country = \"" << country << "\", "
|
||||||
<< "units = " << "{" << unitsSS.str() << "}" << "}";
|
<< "units = " << "{" << unitsSS.str() << "}" << "}";
|
||||||
return commandSS.str();
|
return commandSS.str();
|
||||||
}
|
}
|
||||||
@@ -117,18 +117,17 @@ string SpawnAircrafts::getString()
|
|||||||
/* Spawn helicopters command */
|
/* Spawn helicopters command */
|
||||||
string SpawnHelicopters::getString()
|
string SpawnHelicopters::getString()
|
||||||
{
|
{
|
||||||
if (unitTypes.size() != locations.size() || unitTypes.size() != loadouts.size()) return "";
|
|
||||||
|
|
||||||
std::ostringstream unitsSS;
|
std::ostringstream unitsSS;
|
||||||
unitsSS.precision(10);
|
unitsSS.precision(10);
|
||||||
for (int i = 0; i < unitTypes.size(); i++) {
|
for (int i = 0; i < spawnOptions.size(); i++) {
|
||||||
unitsSS << "[" << i + 1 << "] = {"
|
unitsSS << "[" << i + 1 << "] = {"
|
||||||
<< "unitType = " << "\"" << unitTypes[i] << "\"" << ", "
|
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
|
||||||
<< "lat = " << locations[i].lat << ", "
|
<< "lat = " << spawnOptions[i].location.lat << ", "
|
||||||
<< "lng = " << locations[i].lng << ", "
|
<< "lng = " << spawnOptions[i].location.lng << ", "
|
||||||
<< "alt = " << locations[i].alt << ", "
|
<< "alt = " << spawnOptions[i].location.alt << ", "
|
||||||
<< "loadout = \"" << loadouts[i] << "\"" << ", "
|
<< "loadout = \"" << spawnOptions[i].loadout << "\"" << ", "
|
||||||
<< "liveryID = " << "\"" << liveryIDs[i] << "\"" << " }, ";
|
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
|
||||||
|
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream commandSS;
|
std::ostringstream commandSS;
|
||||||
@@ -137,30 +136,30 @@ string SpawnHelicopters::getString()
|
|||||||
<< "category = " << "\"" << "Helicopter" << "\"" << ", "
|
<< "category = " << "\"" << "Helicopter" << "\"" << ", "
|
||||||
<< "coalition = " << "\"" << coalition << "\"" << ", "
|
<< "coalition = " << "\"" << coalition << "\"" << ", "
|
||||||
<< "airbaseName = \"" << airbaseName << "\", "
|
<< "airbaseName = \"" << airbaseName << "\", "
|
||||||
|
<< "country = \"" << country << "\", "
|
||||||
<< "units = " << "{" << unitsSS.str() << "}" << "}";
|
<< "units = " << "{" << unitsSS.str() << "}" << "}";
|
||||||
return commandSS.str();
|
return commandSS.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Clone unit command */
|
/* Clone unit command */
|
||||||
string Clone::getString()
|
string Clone::getString()
|
||||||
{
|
{
|
||||||
Unit* unit = unitsManager->getUnit(ID);
|
std::ostringstream unitsSS;
|
||||||
if (unit != nullptr)
|
unitsSS.precision(10);
|
||||||
{
|
for (int i = 0; i < cloneOptions.size(); i++) {
|
||||||
std::ostringstream commandSS;
|
unitsSS << "[" << i + 1 << "] = {"
|
||||||
commandSS.precision(10);
|
<< "ID = " << cloneOptions[i].ID << ", "
|
||||||
commandSS << "Olympus.clone, "
|
<< "lat = " << cloneOptions[i].location.lat << ", "
|
||||||
<< ID << ", "
|
<< "lng = " << cloneOptions[i].location.lng << " }, ";
|
||||||
<< location.lat << ", "
|
|
||||||
<< location.lng << ", "
|
|
||||||
<< "\"" << unit->getCategory() << "\"";
|
|
||||||
return commandSS.str();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostringstream commandSS;
|
||||||
|
commandSS.precision(10);
|
||||||
|
commandSS << "Olympus.clone, "
|
||||||
|
<< "{" << unitsSS.str() << "}" << ", "
|
||||||
|
<< (deleteOriginal ? "true" : "false");
|
||||||
|
return commandSS.str();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete unit command */
|
/* Delete unit command */
|
||||||
@@ -170,7 +169,8 @@ string Delete::getString()
|
|||||||
commandSS.precision(10);
|
commandSS.precision(10);
|
||||||
commandSS << "Olympus.delete, "
|
commandSS << "Olympus.delete, "
|
||||||
<< ID << ", "
|
<< ID << ", "
|
||||||
<< (explosion ? "true" : "false");
|
<< (explosion ? "true" : "false") << ", "
|
||||||
|
<< "\"" << explosionType << "\"";
|
||||||
return commandSS.str();
|
return commandSS.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +249,7 @@ string Explosion::getString()
|
|||||||
commandSS.precision(10);
|
commandSS.precision(10);
|
||||||
commandSS << "Olympus.explosion, "
|
commandSS << "Olympus.explosion, "
|
||||||
<< intensity << ", "
|
<< intensity << ", "
|
||||||
|
<< "\"" << explosionType << "\"" << ", "
|
||||||
<< location.lat << ", "
|
<< location.lat << ", "
|
||||||
<< location.lng;
|
<< location.lng;
|
||||||
return commandSS.str();
|
return commandSS.str();
|
||||||
@@ -25,6 +25,7 @@ json::value missionData = json::value::object();
|
|||||||
|
|
||||||
mutex mutexLock;
|
mutex mutexLock;
|
||||||
string sessionHash;
|
string sessionHash;
|
||||||
|
string instancePath;
|
||||||
|
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
|
||||||
@@ -51,9 +52,16 @@ extern "C" DllExport int coreDeinit(lua_State* L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Called when DCS simulation starts. All singletons are instantiated, and the custom Lua functions are registered in the Lua state. */
|
/* Called when DCS simulation starts. All singletons are instantiated, and the custom Lua functions are registered in the Lua state. */
|
||||||
extern "C" DllExport int coreInit(lua_State* L)
|
extern "C" DllExport int coreInit(lua_State* L, const char* path)
|
||||||
{
|
{
|
||||||
|
instancePath = path;
|
||||||
|
|
||||||
|
log("Initializing core.dll with instance path " + instancePath);
|
||||||
|
|
||||||
sessionHash = random_string(16);
|
sessionHash = random_string(16);
|
||||||
|
|
||||||
|
log("Random session hash " + sessionHash);
|
||||||
|
|
||||||
unitsManager = new UnitsManager(L);
|
unitsManager = new UnitsManager(L);
|
||||||
weaponsManager = new WeaponsManager(L);
|
weaponsManager = new WeaponsManager(L);
|
||||||
server = new Server(L);
|
server = new Server(L);
|
||||||
@@ -63,6 +71,8 @@ extern "C" DllExport int coreInit(lua_State* L)
|
|||||||
|
|
||||||
server->start(L);
|
server->start(L);
|
||||||
|
|
||||||
|
unitsManager->loadDatabases();
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
@@ -78,7 +88,7 @@ extern "C" DllExport int coreFrame(lua_State* L)
|
|||||||
frameCounter++;
|
frameCounter++;
|
||||||
|
|
||||||
const std::chrono::duration<double> executionDuration = std::chrono::system_clock::now() - lastExecution;
|
const std::chrono::duration<double> executionDuration = std::chrono::system_clock::now() - lastExecution;
|
||||||
if (executionDuration.count() > FRAMERATE_TIME_INTERVAL) {
|
if (executionDuration.count() > (20 * FRAMERATE_TIME_INTERVAL)) {
|
||||||
if (executionDuration.count() > 0) {
|
if (executionDuration.count() > 0) {
|
||||||
scheduler->setFrameRate(frameCounter / executionDuration.count());
|
scheduler->setFrameRate(frameCounter / executionDuration.count());
|
||||||
frameCounter = 0;
|
frameCounter = 0;
|
||||||
566
backend/core/src/groundunit.cpp
Normal file
566
backend/core/src/groundunit.cpp
Normal file
@@ -0,0 +1,566 @@
|
|||||||
|
#include "groundunit.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "commands.h"
|
||||||
|
#include "scheduler.h"
|
||||||
|
#include "defines.h"
|
||||||
|
#include "unitsmanager.h"
|
||||||
|
|
||||||
|
#include <GeographicLib/Geodesic.hpp>
|
||||||
|
using namespace GeographicLib;
|
||||||
|
|
||||||
|
extern Scheduler* scheduler;
|
||||||
|
extern UnitsManager* unitsManager;
|
||||||
|
json::value GroundUnit::database = json::value();
|
||||||
|
extern string instancePath;
|
||||||
|
|
||||||
|
#define RANDOM_ZERO_TO_ONE (double)(rand()) / (double)(RAND_MAX)
|
||||||
|
#define RANDOM_MINUS_ONE_TO_ONE (((double)(rand()) / (double)(RAND_MAX) - 0.5) * 2)
|
||||||
|
|
||||||
|
void GroundUnit::loadDatabase(string path) {
|
||||||
|
std::ifstream ifstream(instancePath + path);
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << ifstream.rdbuf();
|
||||||
|
std::error_code errorCode;
|
||||||
|
database = json::value::parse(ss.str(), errorCode);
|
||||||
|
if (database.is_object())
|
||||||
|
log("GroundUnits database loaded correctly from " + instancePath + path);
|
||||||
|
else
|
||||||
|
log("Error reading GroundUnits database file");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ground unit */
|
||||||
|
GroundUnit::GroundUnit(json::value json, unsigned int ID) : Unit(json, ID)
|
||||||
|
{
|
||||||
|
log("New Ground Unit created with ID: " + to_string(ID));
|
||||||
|
|
||||||
|
setCategory("GroundUnit");
|
||||||
|
setDesiredSpeed(10);
|
||||||
|
};
|
||||||
|
|
||||||
|
void GroundUnit::setDefaults(bool force)
|
||||||
|
{
|
||||||
|
if (!getAlive() || !getControlled() || getHuman() || !getIsLeader()) return;
|
||||||
|
|
||||||
|
/* Set the default IDLE state */
|
||||||
|
setState(State::IDLE);
|
||||||
|
|
||||||
|
/* Set the default options */
|
||||||
|
setROE(ROE::WEAPON_FREE, force);
|
||||||
|
setOnOff(onOff, force);
|
||||||
|
setFollowRoads(followRoads, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroundUnit::setState(unsigned char newState)
|
||||||
|
{
|
||||||
|
Coords currentTargetPosition = getTargetPosition();
|
||||||
|
|
||||||
|
/************ Perform any action required when LEAVING a state ************/
|
||||||
|
if (newState != state) {
|
||||||
|
switch (state) {
|
||||||
|
case State::IDLE: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::REACH_DESTINATION: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::ATTACK: {
|
||||||
|
setTargetID(NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::FIRE_AT_AREA:
|
||||||
|
case State::SIMULATE_FIRE_FIGHT:
|
||||||
|
case State::SCENIC_AAA:
|
||||||
|
case State::MISS_ON_PURPOSE: {
|
||||||
|
setTargetPosition(Coords(NULL));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************ Perform any action required when ENTERING a state ************/
|
||||||
|
switch (newState) {
|
||||||
|
case State::IDLE: {
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::REACH_DESTINATION: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::ATTACK: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::FIRE_AT_AREA: {
|
||||||
|
setTargetPosition(currentTargetPosition);
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::SIMULATE_FIRE_FIGHT: {
|
||||||
|
setTargetPosition(currentTargetPosition);
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::SCENIC_AAA: {
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::MISS_ON_PURPOSE: {
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHasTask(false);
|
||||||
|
resetTaskFailedCounter();
|
||||||
|
|
||||||
|
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
|
||||||
|
state = newState;
|
||||||
|
|
||||||
|
triggerUpdate(DataIndex::state);
|
||||||
|
|
||||||
|
AIloop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroundUnit::AIloop()
|
||||||
|
{
|
||||||
|
srand(static_cast<unsigned int>(time(NULL)) + ID);
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case State::IDLE: {
|
||||||
|
setTask("Idle");
|
||||||
|
if (getHasTask())
|
||||||
|
resetTask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::REACH_DESTINATION: {
|
||||||
|
setTask("Reaching destination");
|
||||||
|
|
||||||
|
string enrouteTask = "";
|
||||||
|
bool looping = false;
|
||||||
|
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS << "{ id = 'FollowRoads', value = " << (getFollowRoads() ? "true" : "false") << " }";
|
||||||
|
enrouteTask = taskSS.str();
|
||||||
|
|
||||||
|
if (activeDestination == NULL || !getHasTask())
|
||||||
|
{
|
||||||
|
if (!setActiveDestination())
|
||||||
|
setState(State::IDLE);
|
||||||
|
else
|
||||||
|
goToDestination(enrouteTask);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isDestinationReached(GROUND_DEST_DIST_THR)) {
|
||||||
|
if (updateActivePath(looping) && setActiveDestination())
|
||||||
|
goToDestination(enrouteTask);
|
||||||
|
else
|
||||||
|
setState(State::IDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::ATTACK: {
|
||||||
|
Unit* target = unitsManager->getUnit(getTargetID());
|
||||||
|
if (target != nullptr) {
|
||||||
|
setTask("Attacking " + target->getUnitName());
|
||||||
|
|
||||||
|
if (!getHasTask()) {
|
||||||
|
/* Send the command */
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'AttackUnit', unitID = " << target->getID() << " }";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setState(State::IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::FIRE_AT_AREA: {
|
||||||
|
setTask("Firing at area");
|
||||||
|
|
||||||
|
if (!getHasTask()) {
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 100}";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::SIMULATE_FIRE_FIGHT: {
|
||||||
|
setTask("Simulating fire fight");
|
||||||
|
|
||||||
|
if (internalCounter == 0 && targetPosition != Coords(NULL) && scheduler->getLoad() < 30) {
|
||||||
|
/* Get the distance and bearing to the target */
|
||||||
|
Coords scatteredTargetPosition = targetPosition;
|
||||||
|
double distance;
|
||||||
|
double bearing1;
|
||||||
|
double bearing2;
|
||||||
|
Geodesic::WGS84().Inverse(getPosition().lat, getPosition().lng, scatteredTargetPosition.lat, scatteredTargetPosition.lng, distance, bearing1, bearing2);
|
||||||
|
|
||||||
|
/* Compute the scattered position applying a random scatter to the shot */
|
||||||
|
double scatterDistance = distance * tan(10 /* degs */ * (ShotsScatter::LOW - shotsScatter) / 57.29577 + 2 / 57.29577 /* degs */) * RANDOM_MINUS_ONE_TO_ONE;
|
||||||
|
Geodesic::WGS84().Direct(scatteredTargetPosition.lat, scatteredTargetPosition.lng, bearing1 + 90, scatterDistance, scatteredTargetPosition.lat, scatteredTargetPosition.lng);
|
||||||
|
|
||||||
|
/* Recover the data from the database */
|
||||||
|
double aimTime = 2; /* s */
|
||||||
|
bool indirectFire = false;
|
||||||
|
double shotsBaseInterval = 15; /* s */
|
||||||
|
if (database.has_object_field(to_wstring(name))) {
|
||||||
|
json::value databaseEntry = database[to_wstring(name)];
|
||||||
|
if (databaseEntry.has_number_field(L"aimTime"))
|
||||||
|
aimTime = databaseEntry[L"aimTime"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_boolean_field(L"indirectFire"))
|
||||||
|
indirectFire = databaseEntry[L"indirectFire"].as_bool();
|
||||||
|
if (databaseEntry.has_number_field(L"shotsBaseInterval"))
|
||||||
|
shotsBaseInterval = databaseEntry[L"shotsBaseInterval"].as_number().to_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the unit is of the indirect fire type, like a mortar, simply shoot at the target */
|
||||||
|
if (indirectFire) {
|
||||||
|
log(unitName + "(" + name + ")" + " simulating fire fight with indirect fire");
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'FireAtPoint', lat = " << scatteredTargetPosition.lat << ", lng = " << scatteredTargetPosition.lng << ", radius = 100}";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
}
|
||||||
|
/* Otherwise use the aim method */
|
||||||
|
else {
|
||||||
|
log(unitName + "(" + name + ")" + " simulating fire fight with aim at point method");
|
||||||
|
aimAtPoint(scatteredTargetPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait an amout of time depending on the shots intensity */
|
||||||
|
internalCounter = static_cast<unsigned int>(((ShotsIntensity::HIGH - shotsIntensity) * shotsBaseInterval + aimTime) / FRAMERATE_TIME_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetPosition == Coords(NULL))
|
||||||
|
setState(State::IDLE);
|
||||||
|
|
||||||
|
/* Fallback if something went wrong */
|
||||||
|
if (internalCounter == 0)
|
||||||
|
internalCounter = static_cast<unsigned int>(3 / FRAMERATE_TIME_INTERVAL);
|
||||||
|
internalCounter--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::SCENIC_AAA: {
|
||||||
|
setTask("Scenic AAA");
|
||||||
|
|
||||||
|
/* Only perform scenic functions when the scheduler is "free" */
|
||||||
|
if (((!getHasTask() && scheduler->getLoad() < 30) || internalCounter == 0)) {
|
||||||
|
double distance = 0;
|
||||||
|
unsigned char unitCoalition = coalition == 0 ? getOperateAs() : coalition;
|
||||||
|
unsigned char targetCoalition = unitCoalition == 2 ? 1 : 2;
|
||||||
|
Unit* target = unitsManager->getClosestUnit(this, targetCoalition, { "Aircraft", "Helicopter" }, distance);
|
||||||
|
|
||||||
|
/* Recover the data from the database */
|
||||||
|
double aimTime = 2; /* s */
|
||||||
|
double shotsBaseInterval = 15; /* s */
|
||||||
|
if (database.has_object_field(to_wstring(name))) {
|
||||||
|
json::value databaseEntry = database[to_wstring(name)];
|
||||||
|
if (databaseEntry.has_number_field(L"aimTime"))
|
||||||
|
aimTime = databaseEntry[L"aimTime"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"shotsBaseInterval"))
|
||||||
|
shotsBaseInterval = databaseEntry[L"shotsBaseInterval"].as_number().to_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only run if an enemy air unit is closer than 20km to avoid useless load */
|
||||||
|
if (target != nullptr && distance < 20000 /* m */) {
|
||||||
|
double r = 15; /* m */
|
||||||
|
double barrelElevation = r * tan(acos(((double)(rand()) / (double)(RAND_MAX))));
|
||||||
|
|
||||||
|
double lat = 0;
|
||||||
|
double lng = 0;
|
||||||
|
double randomBearing = ((double)(rand()) / (double)(RAND_MAX)) * 360;
|
||||||
|
Geodesic::WGS84().Direct(position.lat, position.lng, randomBearing, r, lat, lng);
|
||||||
|
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'FireAtPoint', lat = " << lat << ", lng = " << lng << ", alt = " << position.alt + barrelElevation << ", radius = 0.001}";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
|
||||||
|
/* Wait an amout of time depending on the shots intensity */
|
||||||
|
internalCounter = static_cast<unsigned int>(((ShotsIntensity::HIGH - shotsIntensity) * shotsBaseInterval + aimTime) / FRAMERATE_TIME_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (internalCounter == 0)
|
||||||
|
internalCounter = static_cast<unsigned int>(3 / FRAMERATE_TIME_INTERVAL);
|
||||||
|
internalCounter--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::MISS_ON_PURPOSE: {
|
||||||
|
setTask("Missing on purpose");
|
||||||
|
|
||||||
|
/* Check that the unit can perform AAA duties */
|
||||||
|
bool canAAA = false;
|
||||||
|
if (database.has_object_field(to_wstring(name))) {
|
||||||
|
json::value databaseEntry = database[to_wstring(name)];
|
||||||
|
if (databaseEntry.has_boolean_field(L"canAAA"))
|
||||||
|
canAAA = databaseEntry[L"canAAA"].as_bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canAAA) {
|
||||||
|
/* Only perform scenic functions when the scheduler is "free" */
|
||||||
|
/* Only run this when the internal counter reaches 0 to avoid excessive computations when no nearby target */
|
||||||
|
if (scheduler->getLoad() < 30 && internalCounter == 0) {
|
||||||
|
double distance = 0;
|
||||||
|
unsigned char unitCoalition = coalition == 0 ? getOperateAs() : coalition;
|
||||||
|
unsigned char targetCoalition = unitCoalition == 2 ? 1 : 2;
|
||||||
|
|
||||||
|
/* Default gun values */
|
||||||
|
double barrelHeight = 1.0; /* m */
|
||||||
|
double muzzleVelocity = 860; /* m/s */
|
||||||
|
double aimTime = 10; /* s */
|
||||||
|
unsigned int shotsToFire = 10;
|
||||||
|
double shotsBaseInterval = 15; /* s */
|
||||||
|
double shotsBaseScatter = 2; /* degs */
|
||||||
|
double engagementRange = 10000; /* m */
|
||||||
|
double targetingRange = 0; /* m */
|
||||||
|
double aimMethodRange = 0; /* m */
|
||||||
|
double acquisitionRange = 0; /* m */
|
||||||
|
|
||||||
|
/* Load gun values from database */
|
||||||
|
if (database.has_object_field(to_wstring(name))) {
|
||||||
|
json::value databaseEntry = database[to_wstring(name)];
|
||||||
|
if (databaseEntry.has_number_field(L"barrelHeight"))
|
||||||
|
barrelHeight = databaseEntry[L"barrelHeight"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"muzzleVelocity"))
|
||||||
|
muzzleVelocity = databaseEntry[L"muzzleVelocity"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"aimTime"))
|
||||||
|
aimTime = databaseEntry[L"aimTime"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"shotsToFire"))
|
||||||
|
shotsToFire = databaseEntry[L"shotsToFire"].as_number().to_uint32();
|
||||||
|
if (databaseEntry.has_number_field(L"engagementRange"))
|
||||||
|
engagementRange = databaseEntry[L"engagementRange"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"shotsBaseInterval"))
|
||||||
|
shotsBaseInterval = databaseEntry[L"shotsBaseInterval"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"shotsBaseScatter"))
|
||||||
|
shotsBaseScatter = databaseEntry[L"shotsBaseScatter"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"targetingRange"))
|
||||||
|
targetingRange = databaseEntry[L"targetingRange"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"aimMethodRange"))
|
||||||
|
aimMethodRange = databaseEntry[L"aimMethodRange"].as_number().to_double();
|
||||||
|
if (databaseEntry.has_number_field(L"acquisitionRange"))
|
||||||
|
acquisitionRange = databaseEntry[L"acquisitionRange"].as_number().to_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get all the units in range and select one at random */
|
||||||
|
double range = max(max(engagementRange, aimMethodRange), acquisitionRange);
|
||||||
|
map<Unit*, double> targets = unitsManager->getUnitsInRange(this, targetCoalition, { "Aircraft", "Helicopter" }, range);
|
||||||
|
|
||||||
|
Unit* target = nullptr;
|
||||||
|
unsigned int index = static_cast<unsigned int>((RANDOM_ZERO_TO_ONE * (targets.size() - 1)));
|
||||||
|
for (auto const& p : targets) {
|
||||||
|
if (index-- == 0) {
|
||||||
|
target = p.first;
|
||||||
|
distance = p.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only do if we have a valid target close enough for AAA */
|
||||||
|
if (target != nullptr) {
|
||||||
|
/* Approximate the flight time */
|
||||||
|
if (muzzleVelocity != 0)
|
||||||
|
aimTime += distance / muzzleVelocity;
|
||||||
|
|
||||||
|
/* If the target is in targeting range and we are in highest precision mode, target it */
|
||||||
|
if (distance < targetingRange && shotsScatter == ShotsScatter::LOW) {
|
||||||
|
/* Send the command */
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'AttackUnit', unitID = " << target->getID() << " }";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
|
||||||
|
internalCounter = static_cast<unsigned int>((aimTime + (ShotsIntensity::HIGH - shotsIntensity) * shotsBaseInterval + 2) / FRAMERATE_TIME_INTERVAL);
|
||||||
|
}
|
||||||
|
/* Else, do miss on purpose */
|
||||||
|
else {
|
||||||
|
/* Compute where the target will be in aimTime seconds, plus the effect of scatter. */
|
||||||
|
double scatterDistance = distance * tan(shotsBaseScatter * (ShotsScatter::LOW - shotsScatter) / 57.29577) * (RANDOM_ZERO_TO_ONE - 0.1);
|
||||||
|
double aimDistance = target->getHorizontalVelocity() * aimTime + scatterDistance;
|
||||||
|
double aimLat = 0;
|
||||||
|
double aimLng = 0;
|
||||||
|
Geodesic::WGS84().Direct(target->getPosition().lat, target->getPosition().lng, target->getTrack() * 57.29577, aimDistance, aimLat, aimLng); /* TODO make util to convert degrees and radians function */
|
||||||
|
double aimAlt = target->getPosition().alt + target->getVerticalVelocity() * aimTime + distance * tan(shotsBaseScatter * (ShotsScatter::LOW - shotsScatter) / 57.29577) * RANDOM_ZERO_TO_ONE; // Force to always miss high never low
|
||||||
|
|
||||||
|
/* Send the command */
|
||||||
|
if (distance < engagementRange) {
|
||||||
|
/* If the unit is closer than the engagement range, use the fire at point method */
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'FireAtPoint', lat = " << aimLat << ", lng = " << aimLng << ", alt = " << aimAlt << ", radius = 0.001, expendQty = " << shotsToFire << " }";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
setTargetPosition(Coords(aimLat, aimLng, target->getPosition().alt));
|
||||||
|
internalCounter = static_cast<unsigned int>((aimTime + (ShotsIntensity::HIGH - shotsIntensity) * shotsBaseInterval + 2) / FRAMERATE_TIME_INTERVAL);
|
||||||
|
}
|
||||||
|
else if (distance < aimMethodRange) {
|
||||||
|
/* If the unit is closer than the aim method range, use the aim method range */
|
||||||
|
aimAtPoint(Coords(aimLat, aimLng, aimAlt));
|
||||||
|
setTargetPosition(Coords(aimLat, aimLng, target->getPosition().alt));
|
||||||
|
internalCounter = static_cast<unsigned int>((aimTime + (ShotsIntensity::HIGH - shotsIntensity) * shotsBaseInterval + 2) / FRAMERATE_TIME_INTERVAL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Else just wake the unit up with an impossible command */
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'FireAtPoint', lat = " << 0 << ", lng = " << 0 << ", alt = " << 0 << ", radius = 0.001, expendQty = " << 0 << " }";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
setTargetPosition(Coords(NULL));
|
||||||
|
|
||||||
|
/* Don't wait too long before checking again */
|
||||||
|
internalCounter = static_cast<unsigned int>(5 / FRAMERATE_TIME_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
missOnPurposeTarget = target;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (getHasTask())
|
||||||
|
resetTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no valid target was detected */
|
||||||
|
if (internalCounter == 0) {
|
||||||
|
double alertnessTimeConstant = 10; /* s */
|
||||||
|
if (database.has_object_field(to_wstring(name))) {
|
||||||
|
json::value databaseEntry = database[to_wstring(name)];
|
||||||
|
if (databaseEntry.has_number_field(L"alertnessTimeConstant"))
|
||||||
|
alertnessTimeConstant = databaseEntry[L"alertnessTimeConstant"].as_number().to_double();
|
||||||
|
}
|
||||||
|
internalCounter = static_cast<unsigned int>((5 + RANDOM_ZERO_TO_ONE * alertnessTimeConstant * 0 /* TODO: remove to enable alertness again */) / FRAMERATE_TIME_INTERVAL);
|
||||||
|
missOnPurposeTarget = nullptr;
|
||||||
|
setTargetPosition(Coords(NULL));
|
||||||
|
}
|
||||||
|
internalCounter--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setState(State::IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GroundUnit::aimAtPoint(Coords aimTarget) {
|
||||||
|
double dist;
|
||||||
|
double bearing1;
|
||||||
|
double bearing2;
|
||||||
|
Geodesic::WGS84().Inverse(position.lat, position.lng, aimTarget.lat, aimTarget.lng, dist, bearing1, bearing2);
|
||||||
|
|
||||||
|
/* Aim point distance */
|
||||||
|
double r = 15; /* m */
|
||||||
|
|
||||||
|
/* Default gun values */
|
||||||
|
double barrelHeight = 1.0; /* m */
|
||||||
|
double muzzleVelocity = 860; /* m/s */
|
||||||
|
double shotsBaseScatter = 5; /* degs */
|
||||||
|
if (database.has_object_field(to_wstring(name))) {
|
||||||
|
json::value databaseEntry = database[to_wstring(name)];
|
||||||
|
if (databaseEntry.has_number_field(L"barrelHeight") && databaseEntry.has_number_field(L"muzzleVelocity")) {
|
||||||
|
barrelHeight = databaseEntry[L"barrelHeight"].as_number().to_double();
|
||||||
|
muzzleVelocity = databaseEntry[L"muzzleVelocity"].as_number().to_double();
|
||||||
|
}
|
||||||
|
if (databaseEntry.has_number_field(L"shotsBaseScatter"))
|
||||||
|
shotsBaseScatter = databaseEntry[L"shotsBaseScatter"].as_number().to_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the elevation angle of the gun*/
|
||||||
|
double deltaHeight = (aimTarget.alt - (position.alt + barrelHeight));
|
||||||
|
double alpha = 9.81 / 2 * dist * dist / (muzzleVelocity * muzzleVelocity);
|
||||||
|
double inner = dist * dist - 4 * alpha * (alpha + deltaHeight);
|
||||||
|
|
||||||
|
/* Check we can reach the target*/
|
||||||
|
if (inner > 0) {
|
||||||
|
/* Compute elevation and bearing */
|
||||||
|
double barrelElevation = r * (dist - sqrt(inner)) / (2 * alpha);
|
||||||
|
|
||||||
|
double lat = 0;
|
||||||
|
double lng = 0;
|
||||||
|
Geodesic::WGS84().Direct(position.lat, position.lng, bearing1, r, lat, lng);
|
||||||
|
|
||||||
|
log(unitName + "(" + name + ")" + " shooting with aim at point method. Barrel elevation: " + to_string(barrelElevation * 57.29577) + "°, bearing: " + to_string(bearing1) + "°");
|
||||||
|
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'FireAtPoint', lat = " << lat << ", lng = " << lng << ", alt = " << position.alt + barrelElevation + barrelHeight << ", radius = 0.001}";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log("Target out of range for " + unitName + "(" + name + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroundUnit::changeSpeed(string change)
|
||||||
|
{
|
||||||
|
if (change.compare("stop") == 0)
|
||||||
|
setState(State::IDLE);
|
||||||
|
else if (change.compare("slow") == 0)
|
||||||
|
setDesiredSpeed(getDesiredSpeed() - knotsToMs(5));
|
||||||
|
else if (change.compare("fast") == 0)
|
||||||
|
setDesiredSpeed(getDesiredSpeed() + knotsToMs(5));
|
||||||
|
|
||||||
|
if (getDesiredSpeed() < 0)
|
||||||
|
setDesiredSpeed(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroundUnit::setOnOff(bool newOnOff, bool force)
|
||||||
|
{
|
||||||
|
if (newOnOff != onOff || force) {
|
||||||
|
Unit::setOnOff(newOnOff, force);
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetOnOff(groupName, onOff));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroundUnit::setFollowRoads(bool newFollowRoads, bool force)
|
||||||
|
{
|
||||||
|
if (newFollowRoads != followRoads || force) {
|
||||||
|
Unit::setFollowRoads(newFollowRoads, force);
|
||||||
|
resetActiveDestination(); /* Reset active destination to apply option*/
|
||||||
|
}
|
||||||
|
}
|
||||||
71
backend/core/src/helicopter.cpp
Normal file
71
backend/core/src/helicopter.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#include "helicopter.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "commands.h"
|
||||||
|
#include "scheduler.h"
|
||||||
|
#include "defines.h"
|
||||||
|
#include "unitsManager.h"
|
||||||
|
|
||||||
|
#include <GeographicLib/Geodesic.hpp>
|
||||||
|
using namespace GeographicLib;
|
||||||
|
|
||||||
|
extern Scheduler* scheduler;
|
||||||
|
extern UnitsManager* unitsManager;
|
||||||
|
json::value Helicopter::database = json::value();
|
||||||
|
extern string instancePath;
|
||||||
|
|
||||||
|
void Helicopter::loadDatabase(string path) {
|
||||||
|
std::ifstream ifstream(instancePath + path);
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << ifstream.rdbuf();
|
||||||
|
std::error_code errorCode;
|
||||||
|
database = json::value::parse(ss.str(), errorCode);
|
||||||
|
if (database.is_object())
|
||||||
|
log("Helicopters database loaded correctly from " + instancePath + path);
|
||||||
|
else
|
||||||
|
log("Error reading Helicopters database file");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helicopter */
|
||||||
|
Helicopter::Helicopter(json::value json, unsigned int ID) : AirUnit(json, ID)
|
||||||
|
{
|
||||||
|
log("New Helicopter created with ID: " + to_string(ID));
|
||||||
|
|
||||||
|
setCategory("Helicopter");
|
||||||
|
setDesiredSpeed(knotsToMs(100));
|
||||||
|
setDesiredAltitude(ftToM(5000));
|
||||||
|
};
|
||||||
|
|
||||||
|
void Helicopter::changeSpeed(string change)
|
||||||
|
{
|
||||||
|
if (change.compare("stop") == 0)
|
||||||
|
setState(State::IDLE);
|
||||||
|
else if (change.compare("slow") == 0)
|
||||||
|
setDesiredSpeed(getDesiredSpeed() - knotsToMs(10));
|
||||||
|
else if (change.compare("fast") == 0)
|
||||||
|
setDesiredSpeed(getDesiredSpeed() + knotsToMs(10));
|
||||||
|
|
||||||
|
if (getDesiredSpeed() < knotsToMs(0))
|
||||||
|
setDesiredSpeed(knotsToMs(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helicopter::changeAltitude(string change)
|
||||||
|
{
|
||||||
|
if (change.compare("descend") == 0)
|
||||||
|
{
|
||||||
|
if (getDesiredAltitude() > 100)
|
||||||
|
setDesiredAltitude(getDesiredAltitude() - ftToM(100));
|
||||||
|
else if (getDesiredAltitude() > 0)
|
||||||
|
setDesiredAltitude(getDesiredAltitude() - ftToM(10));
|
||||||
|
}
|
||||||
|
else if (change.compare("climb") == 0)
|
||||||
|
{
|
||||||
|
if (getDesiredAltitude() > 100)
|
||||||
|
setDesiredAltitude(getDesiredAltitude() + ftToM(100));
|
||||||
|
else if (getDesiredAltitude() >= 0)
|
||||||
|
setDesiredAltitude(getDesiredAltitude() + ftToM(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getDesiredAltitude() < 0)
|
||||||
|
setDesiredAltitude(0);
|
||||||
|
}
|
||||||
@@ -11,6 +11,20 @@ using namespace GeographicLib;
|
|||||||
|
|
||||||
extern Scheduler* scheduler;
|
extern Scheduler* scheduler;
|
||||||
extern UnitsManager* unitsManager;
|
extern UnitsManager* unitsManager;
|
||||||
|
json::value NavyUnit::database = json::value();
|
||||||
|
extern string instancePath;
|
||||||
|
|
||||||
|
void NavyUnit::loadDatabase(string path) {
|
||||||
|
std::ifstream ifstream(instancePath + path);
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << ifstream.rdbuf();
|
||||||
|
std::error_code errorCode;
|
||||||
|
database = json::value::parse(ss.str(), errorCode);
|
||||||
|
if (database.is_object())
|
||||||
|
log("NavyUnits database loaded correctly from " + instancePath + path);
|
||||||
|
else
|
||||||
|
log("Error reading NavyUnits database file");
|
||||||
|
}
|
||||||
|
|
||||||
/* Navy Unit */
|
/* Navy Unit */
|
||||||
NavyUnit::NavyUnit(json::value json, unsigned int ID) : Unit(json, ID)
|
NavyUnit::NavyUnit(json::value json, unsigned int ID) : Unit(json, ID)
|
||||||
@@ -29,13 +43,15 @@ void NavyUnit::setDefaults(bool force)
|
|||||||
setState(State::IDLE);
|
setState(State::IDLE);
|
||||||
|
|
||||||
/* Set the default options */
|
/* Set the default options */
|
||||||
setROE(ROE::OPEN_FIRE_WEAPON_FREE, force);
|
setROE(ROE::WEAPON_FREE, force);
|
||||||
setOnOff(onOff, force);
|
setOnOff(onOff, force);
|
||||||
setFollowRoads(followRoads, force);
|
setFollowRoads(followRoads, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavyUnit::setState(unsigned char newState)
|
void NavyUnit::setState(unsigned char newState)
|
||||||
{
|
{
|
||||||
|
Coords currentTargetPosition = getTargetPosition();
|
||||||
|
|
||||||
/************ Perform any action required when LEAVING a state ************/
|
/************ Perform any action required when LEAVING a state ************/
|
||||||
if (newState != state) {
|
if (newState != state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -45,7 +61,14 @@ void NavyUnit::setState(unsigned char newState)
|
|||||||
case State::REACH_DESTINATION: {
|
case State::REACH_DESTINATION: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::FIRE_AT_AREA: {
|
case State::ATTACK: {
|
||||||
|
setTargetID(NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::FIRE_AT_AREA:
|
||||||
|
case State::SIMULATE_FIRE_FIGHT:
|
||||||
|
case State::SCENIC_AAA:
|
||||||
|
case State::MISS_ON_PURPOSE: {
|
||||||
setTargetPosition(Coords(NULL));
|
setTargetPosition(Coords(NULL));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -57,15 +80,44 @@ void NavyUnit::setState(unsigned char newState)
|
|||||||
/************ Perform any action required when ENTERING a state ************/
|
/************ Perform any action required when ENTERING a state ************/
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
case State::IDLE: {
|
case State::IDLE: {
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
clearActivePath();
|
clearActivePath();
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::REACH_DESTINATION: {
|
case State::REACH_DESTINATION: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::ATTACK: {
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
|
clearActivePath();
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::FIRE_AT_AREA: {
|
case State::FIRE_AT_AREA: {
|
||||||
|
setTargetPosition(currentTargetPosition);
|
||||||
|
setEnableTaskCheckFailed(true);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::SIMULATE_FIRE_FIGHT: {
|
||||||
|
setTargetPosition(currentTargetPosition);
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::SCENIC_AAA: {
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
|
clearActivePath();
|
||||||
|
resetActiveDestination();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::MISS_ON_PURPOSE: {
|
||||||
|
setEnableTaskCheckFailed(false);
|
||||||
clearActivePath();
|
clearActivePath();
|
||||||
resetActiveDestination();
|
resetActiveDestination();
|
||||||
break;
|
break;
|
||||||
@@ -74,17 +126,21 @@ void NavyUnit::setState(unsigned char newState)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newState != state)
|
setHasTask(false);
|
||||||
resetTask();
|
resetTaskFailedCounter();
|
||||||
|
|
||||||
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
|
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
|
||||||
state = newState;
|
state = newState;
|
||||||
|
|
||||||
triggerUpdate(DataIndex::state);
|
triggerUpdate(DataIndex::state);
|
||||||
|
|
||||||
|
AIloop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavyUnit::AIloop()
|
void NavyUnit::AIloop()
|
||||||
{
|
{
|
||||||
|
srand(static_cast<unsigned int>(time(NULL)) + ID);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case State::IDLE: {
|
case State::IDLE: {
|
||||||
setTask("Idle");
|
setTask("Idle");
|
||||||
@@ -111,6 +167,28 @@ void NavyUnit::AIloop()
|
|||||||
setState(State::IDLE);
|
setState(State::IDLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::ATTACK: {
|
||||||
|
Unit* target = unitsManager->getUnit(getTargetID());
|
||||||
|
if (target != nullptr) {
|
||||||
|
setTask("Attacking " + target->getUnitName());
|
||||||
|
|
||||||
|
if (!getHasTask()) {
|
||||||
|
/* Send the command */
|
||||||
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
taskSS << "{id = 'AttackUnit', unitID = " << target->getID() << " }";
|
||||||
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
|
scheduler->appendCommand(command);
|
||||||
|
setHasTask(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setState(State::IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::FIRE_AT_AREA: {
|
case State::FIRE_AT_AREA: {
|
||||||
@@ -118,11 +196,23 @@ void NavyUnit::AIloop()
|
|||||||
|
|
||||||
if (!getHasTask()) {
|
if (!getHasTask()) {
|
||||||
std::ostringstream taskSS;
|
std::ostringstream taskSS;
|
||||||
|
taskSS.precision(10);
|
||||||
|
|
||||||
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 1000}";
|
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 1000}";
|
||||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
|
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(true);
|
setHasTask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case State::SIMULATE_FIRE_FIGHT: {
|
||||||
|
setTask("Simulating fire fight");
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
setState(State::IDLE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -7,12 +7,9 @@
|
|||||||
|
|
||||||
extern UnitsManager* unitsManager;
|
extern UnitsManager* unitsManager;
|
||||||
|
|
||||||
Scheduler::Scheduler(lua_State* L) :
|
Scheduler::Scheduler(lua_State* L)
|
||||||
load(0)
|
|
||||||
{
|
{
|
||||||
LogInfo(L, "Scheduler constructor called successfully");
|
LogInfo(L, "Scheduler constructor called successfully");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scheduler::~Scheduler()
|
Scheduler::~Scheduler()
|
||||||
@@ -20,6 +17,7 @@ Scheduler::~Scheduler()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Appends a */
|
||||||
void Scheduler::appendCommand(Command* newCommand)
|
void Scheduler::appendCommand(Command* newCommand)
|
||||||
{
|
{
|
||||||
for (auto command : commands) {
|
for (auto command : commands) {
|
||||||
@@ -58,8 +56,16 @@ void Scheduler::execute(lua_State* L)
|
|||||||
log("Error executing command " + commandString);
|
log("Error executing command " + commandString);
|
||||||
else
|
else
|
||||||
log("Command '" + commandString + "' executed correctly, current load " + to_string(getLoad()));
|
log("Command '" + commandString + "' executed correctly, current load " + to_string(getLoad()));
|
||||||
load = command->getLoad();
|
|
||||||
|
/* Adjust the load depending on the fps */
|
||||||
|
double fpsMultiplier = 20;
|
||||||
|
if (getFrameRate() + 3 > 0)
|
||||||
|
fpsMultiplier = static_cast<unsigned int>(max(1, 60 / (getFrameRate() + 3))); /* Multiplier between 1 and 20 */
|
||||||
|
|
||||||
|
load = static_cast<unsigned int>(command->getLoad() * fpsMultiplier);
|
||||||
commands.remove(command);
|
commands.remove(command);
|
||||||
|
executedCommandsHashes.push_back(command->getHash());
|
||||||
|
command->executeCallback(); /* Execute the command callback (this is a lambda function that can be used to execute a function when the command is run) */
|
||||||
delete command;
|
delete command;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -82,7 +88,7 @@ void Scheduler::setCommandModeOptions(json::value value) {
|
|||||||
setRedSpawnPoints(value[L"spawnPoints"][L"red"].as_number().to_int32());
|
setRedSpawnPoints(value[L"spawnPoints"][L"red"].as_number().to_int32());
|
||||||
}
|
}
|
||||||
if (value.has_array_field(L"eras")) {
|
if (value.has_array_field(L"eras")) {
|
||||||
int length = value[L"eras"].as_array().size();
|
int length = static_cast<int>(value[L"eras"].as_array().size());
|
||||||
vector<string> newEras;
|
vector<string> newEras;
|
||||||
for (int idx = 0; idx < length; idx++)
|
for (int idx = 0; idx < length; idx++)
|
||||||
newEras.push_back(to_string(value[L"eras"].as_array().at(idx)));
|
newEras.push_back(to_string(value[L"eras"].as_array().at(idx)));
|
||||||
@@ -132,15 +138,18 @@ bool Scheduler::checkSpawnPoints(int spawnPoints, string coalition)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::handleRequest(string key, json::value value, string username)
|
void Scheduler::handleRequest(string key, json::value value, string username, json::value& answer)
|
||||||
{
|
{
|
||||||
Command* command = nullptr;
|
Command* command = nullptr;
|
||||||
|
|
||||||
log("Received request with ID: " + key);
|
log("Received request with ID: " + key);
|
||||||
log(L"Incoming command raw value: " + value.serialize());
|
log(L"Incoming command raw value: " + value.serialize());
|
||||||
|
|
||||||
|
/************************/
|
||||||
if (key.compare("setPath") == 0)
|
if (key.compare("setPath") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
@@ -148,7 +157,6 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
if (unit != nullptr)
|
if (unit != nullptr)
|
||||||
{
|
{
|
||||||
string unitName = unit->getUnitName();
|
|
||||||
json::value path = value[L"path"];
|
json::value path = value[L"path"];
|
||||||
list<Coords> newPath;
|
list<Coords> newPath;
|
||||||
for (unsigned int i = 0; i < path.as_array().size(); i++)
|
for (unsigned int i = 0; i < path.as_array().size(); i++)
|
||||||
@@ -162,31 +170,33 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
|
|
||||||
unit->setActivePath(newPath);
|
unit->setActivePath(newPath);
|
||||||
unit->setState(State::REACH_DESTINATION);
|
unit->setState(State::REACH_DESTINATION);
|
||||||
log(username + " updated destination path for unit " + unitName, true);
|
log(username + " updated destination path for unit " + unit->getUnitName() + "(" + unit->getName() + ")", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("smoke") == 0)
|
else if (key.compare("smoke") == 0)
|
||||||
{
|
{
|
||||||
string color = to_string(value[L"color"]);
|
string color = to_string(value[L"color"]);
|
||||||
double lat = value[L"location"][L"lat"].as_double();
|
double lat = value[L"location"][L"lat"].as_double();
|
||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
log(username + " added a " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")", true);
|
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
command = dynamic_cast<Command*>(new Smoke(color, loc));
|
command = dynamic_cast<Command*>(new Smoke(color, loc));
|
||||||
|
log(username + " added a " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")", true);
|
||||||
}
|
}
|
||||||
else if (key.compare("spawnAircrafts") == 0)
|
/************************/
|
||||||
|
else if (key.compare("spawnAircrafts") == 0 || key.compare("spawnHelicopters") == 0)
|
||||||
{
|
{
|
||||||
bool immediate = value[L"immediate"].as_bool();
|
bool immediate = value[L"immediate"].as_bool();
|
||||||
string coalition = to_string(value[L"coalition"]);
|
string coalition = to_string(value[L"coalition"]);
|
||||||
string airbaseName = to_string(value[L"airbaseName"]);
|
string airbaseName = to_string(value[L"airbaseName"]);
|
||||||
|
string country = to_string(value[L"country"]);
|
||||||
|
|
||||||
|
|
||||||
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
||||||
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
||||||
|
|
||||||
vector<string> unitTypes;
|
vector<SpawnOptions> spawnOptions;
|
||||||
vector<Coords> locations;
|
|
||||||
vector<string> loadouts;
|
|
||||||
vector<string> liveryIDs;
|
|
||||||
for (auto unit : value[L"units"].as_array()) {
|
for (auto unit : value[L"units"].as_array()) {
|
||||||
string unitType = to_string(unit[L"unitType"]);
|
string unitType = to_string(unit[L"unitType"]);
|
||||||
double lat = unit[L"location"][L"lat"].as_double();
|
double lat = unit[L"location"][L"lat"].as_double();
|
||||||
@@ -195,99 +205,46 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
|
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
|
||||||
string loadout = to_string(unit[L"loadout"]);
|
string loadout = to_string(unit[L"loadout"]);
|
||||||
string liveryID = to_string(unit[L"liveryID"]);
|
string liveryID = to_string(unit[L"liveryID"]);
|
||||||
|
string skill = to_string(unit[L"skill"]);
|
||||||
|
|
||||||
unitTypes.push_back(unitType);
|
spawnOptions.push_back({unitType, location, loadout, skill, liveryID});
|
||||||
locations.push_back(location);
|
log(username + " spawned a " + coalition + " " + unitType , true);
|
||||||
loadouts.push_back(loadout);
|
|
||||||
liveryIDs.push_back(liveryID);
|
|
||||||
log(username + " spawned a " + coalition + " " + unitType, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
command = dynamic_cast<Command*>(new SpawnAircrafts(coalition, unitTypes, locations, loadouts, liveryIDs, airbaseName, immediate));
|
if (key.compare("spawnAircrafts") == 0)
|
||||||
|
command = dynamic_cast<Command*>(new SpawnAircrafts(coalition, spawnOptions, airbaseName, country, immediate));
|
||||||
|
else
|
||||||
|
command = dynamic_cast<Command*>(new SpawnHelicopters(coalition, spawnOptions, airbaseName, country, immediate));
|
||||||
}
|
}
|
||||||
else if (key.compare("spawnHelicopters") == 0)
|
/************************/
|
||||||
|
else if (key.compare("spawnGroundUnits") == 0 || key.compare("spawnNavyUnits") == 0)
|
||||||
{
|
{
|
||||||
bool immediate = value[L"immediate"].as_bool();
|
bool immediate = value[L"immediate"].as_bool();
|
||||||
string coalition = to_string(value[L"coalition"]);
|
string coalition = to_string(value[L"coalition"]);
|
||||||
string airbaseName = to_string(value[L"airbaseName"]);
|
string country = to_string(value[L"country"]);
|
||||||
|
|
||||||
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
||||||
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
||||||
|
|
||||||
vector<string> unitTypes;
|
vector<SpawnOptions> spawnOptions;
|
||||||
vector<Coords> locations;
|
|
||||||
vector<string> loadouts;
|
|
||||||
vector<string> liveryIDs;
|
|
||||||
for (auto unit : value[L"units"].as_array()) {
|
|
||||||
string unitType = to_string(unit[L"unitType"]);
|
|
||||||
double lat = unit[L"location"][L"lat"].as_double();
|
|
||||||
double lng = unit[L"location"][L"lng"].as_double();
|
|
||||||
double alt = unit[L"altitude"].as_double();
|
|
||||||
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
|
|
||||||
string loadout = to_string(unit[L"loadout"]);
|
|
||||||
string liveryID = to_string(unit[L"liveryID"]);
|
|
||||||
|
|
||||||
unitTypes.push_back(unitType);
|
|
||||||
locations.push_back(location);
|
|
||||||
loadouts.push_back(loadout);
|
|
||||||
liveryIDs.push_back(liveryID);
|
|
||||||
log(username + " spawned a " + coalition + " " + unitType, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
command = dynamic_cast<Command*>(new SpawnHelicopters(coalition, unitTypes, locations, loadouts, liveryIDs, airbaseName, immediate));
|
|
||||||
}
|
|
||||||
else if (key.compare("spawnGroundUnits") == 0)
|
|
||||||
{
|
|
||||||
bool immediate = value[L"immediate"].as_bool();
|
|
||||||
string coalition = to_string(value[L"coalition"]);
|
|
||||||
|
|
||||||
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
|
||||||
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
|
||||||
|
|
||||||
vector<string> unitTypes;
|
|
||||||
vector<Coords> locations;
|
|
||||||
vector<string> liveryIDs;
|
|
||||||
for (auto unit : value[L"units"].as_array()) {
|
for (auto unit : value[L"units"].as_array()) {
|
||||||
string unitType = to_string(unit[L"unitType"]);
|
string unitType = to_string(unit[L"unitType"]);
|
||||||
double lat = unit[L"location"][L"lat"].as_double();
|
double lat = unit[L"location"][L"lat"].as_double();
|
||||||
double lng = unit[L"location"][L"lng"].as_double();
|
double lng = unit[L"location"][L"lng"].as_double();
|
||||||
Coords location; location.lat = lat; location.lng = lng;
|
Coords location; location.lat = lat; location.lng = lng;
|
||||||
string liveryID = to_string(unit[L"liveryID"]);
|
string liveryID = to_string(unit[L"liveryID"]);
|
||||||
|
string skill = to_string(unit[L"skill"]);
|
||||||
|
|
||||||
unitTypes.push_back(unitType);
|
spawnOptions.push_back({ unitType, location, "", skill, liveryID});
|
||||||
locations.push_back(location);
|
|
||||||
liveryIDs.push_back(liveryID);
|
|
||||||
log(username + " spawned a " + coalition + " " + unitType, true);
|
log(username + " spawned a " + coalition + " " + unitType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
command = dynamic_cast<Command*>(new SpawnGroundUnits(coalition, unitTypes, locations, liveryIDs, immediate));
|
if (key.compare("spawnGroundUnits") == 0)
|
||||||
}
|
command = dynamic_cast<Command*>(new SpawnGroundUnits(coalition, spawnOptions, country, immediate));
|
||||||
else if (key.compare("spawnNavyUnits") == 0)
|
else
|
||||||
{
|
command = dynamic_cast<Command*>(new SpawnNavyUnits(coalition, spawnOptions, country, immediate));
|
||||||
bool immediate = value[L"immediate"].as_bool();
|
|
||||||
string coalition = to_string(value[L"coalition"]);
|
|
||||||
|
|
||||||
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
|
|
||||||
if (!checkSpawnPoints(spawnPoints, coalition)) return;
|
|
||||||
|
|
||||||
vector<string> unitTypes;
|
|
||||||
vector<Coords> locations;
|
|
||||||
vector<string> liveryIDs;
|
|
||||||
for (auto unit : value[L"units"].as_array()) {
|
|
||||||
string unitType = to_string(unit[L"unitType"]);
|
|
||||||
double lat = unit[L"location"][L"lat"].as_double();
|
|
||||||
double lng = unit[L"location"][L"lng"].as_double();
|
|
||||||
Coords location; location.lat = lat; location.lng = lng;
|
|
||||||
string liveryID = to_string(unit[L"liveryID"]);
|
|
||||||
|
|
||||||
unitTypes.push_back(unitType);
|
|
||||||
locations.push_back(location);
|
|
||||||
liveryIDs.push_back(liveryID);
|
|
||||||
log(username + " spawned a " + coalition + " " + unitType, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
command = dynamic_cast<Command*>(new SpawnNavyUnits(coalition, unitTypes, locations, liveryIDs, immediate));
|
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("attackUnit") == 0)
|
else if (key.compare("attackUnit") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
@@ -297,28 +254,18 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
Unit* target = unitsManager->getUnit(targetID);
|
Unit* target = unitsManager->getUnit(targetID);
|
||||||
|
|
||||||
string unitName;
|
if (unit != nullptr && target != nullptr) {
|
||||||
string targetName;
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to attack unit " + target->getUnitName() + "(" + target->getName() + ")", true);
|
||||||
|
unit->setTargetID(targetID);
|
||||||
if (unit != nullptr)
|
unit->setState(State::ATTACK);
|
||||||
unitName = unit->getUnitName();
|
}
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (target != nullptr)
|
|
||||||
targetName = target->getUnitName();
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
log(username + " tasked unit " + unitName + " to attack unit " + targetName, true);
|
|
||||||
unit->setTargetID(targetID);
|
|
||||||
unit->setState(State::ATTACK);
|
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("followUnit") == 0)
|
else if (key.compare("followUnit") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
unsigned int leaderID = value[L"targetID"].as_double();
|
unsigned int leaderID = value[L"targetID"].as_integer();
|
||||||
double offsetX = value[L"offsetX"].as_double();
|
double offsetX = value[L"offsetX"].as_double();
|
||||||
double offsetY = value[L"offsetY"].as_double();
|
double offsetY = value[L"offsetY"].as_double();
|
||||||
double offsetZ = value[L"offsetZ"].as_double();
|
double offsetZ = value[L"offsetZ"].as_double();
|
||||||
@@ -326,135 +273,172 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
Unit* leader = unitsManager->getUnit(leaderID);
|
Unit* leader = unitsManager->getUnit(leaderID);
|
||||||
|
|
||||||
string unitName;
|
if (unit != nullptr && leader != nullptr) {
|
||||||
string leaderName;
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to follow unit " + leader->getUnitName() + "(" + leader->getName() + ")", true);
|
||||||
|
unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ));
|
||||||
if (unit != nullptr)
|
unit->setLeaderID(leaderID);
|
||||||
unitName = unit->getUnitName();
|
unit->setState(State::FOLLOW);
|
||||||
else
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
if (leader != nullptr)
|
|
||||||
leaderName = leader->getUnitName();
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
log(username + " tasked unit " + unitName + " to follow unit " + leaderName, true);
|
|
||||||
unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ));
|
|
||||||
unit->setLeaderID(leaderID);
|
|
||||||
unit->setState(State::FOLLOW);
|
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("changeSpeed") == 0)
|
else if (key.compare("changeSpeed") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
if (unit != nullptr)
|
if (unit != nullptr) {
|
||||||
unit->changeSpeed(to_string(value[L"change"]));
|
unit->changeSpeed(to_string(value[L"change"]));
|
||||||
|
log(username + " changed " + unit->getUnitName() + "(" + unit->getName() + ") speed: " + to_string(value[L"change"]), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("changeAltitude") == 0)
|
else if (key.compare("changeAltitude") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
if (unit != nullptr)
|
if (unit != nullptr) {
|
||||||
unit->changeAltitude(to_string(value[L"change"]));
|
unit->changeAltitude(to_string(value[L"change"]));
|
||||||
|
log(username + " changed " + unit->getUnitName() + "(" + unit->getName() + ") altitude: " + to_string(value[L"change"]), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setSpeed") == 0)
|
else if (key.compare("setSpeed") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
if (unit != nullptr)
|
if (unit != nullptr) {
|
||||||
unit->setDesiredSpeed(value[L"speed"].as_double());
|
unit->setDesiredSpeed(value[L"speed"].as_double());
|
||||||
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") speed: " + to_string(value[L"speed"].as_double()), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setSpeedType") == 0)
|
else if (key.compare("setSpeedType") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
if (unit != nullptr)
|
if (unit != nullptr) {
|
||||||
unit->setDesiredSpeedType(to_string(value[L"speedType"]));
|
unit->setDesiredSpeedType(to_string(value[L"speedType"]));
|
||||||
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") speed type: " + to_string(value[L"speedType"]), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setAltitude") == 0)
|
else if (key.compare("setAltitude") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
if (unit != nullptr)
|
if (unit != nullptr) {
|
||||||
unit->setDesiredAltitude(value[L"altitude"].as_double());
|
unit->setDesiredAltitude(value[L"altitude"].as_double());
|
||||||
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") altitude: " + to_string(value[L"altitude"].as_double()), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setAltitudeType") == 0)
|
else if (key.compare("setAltitudeType") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
if (unit != nullptr)
|
if (unit != nullptr) {
|
||||||
unit->setDesiredAltitudeType(to_string(value[L"altitudeType"]));
|
unit->setDesiredAltitudeType(to_string(value[L"altitudeType"]));
|
||||||
|
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") altitude type: " + to_string(value[L"altitudeType"]), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (key.compare("cloneUnit") == 0)
|
/************************/
|
||||||
|
else if (key.compare("cloneUnits") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
vector<CloneOptions> cloneOptions;
|
||||||
double lat = value[L"location"][L"lat"].as_double();
|
bool deleteOriginal = value[L"deleteOriginal"].as_bool();
|
||||||
double lng = value[L"location"][L"lng"].as_double();
|
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
for (auto unit : value[L"units"].as_array()) {
|
||||||
command = dynamic_cast<Command*>(new Clone(ID, loc));
|
unsigned int ID = unit[L"ID"].as_integer();
|
||||||
|
double lat = unit[L"location"][L"lat"].as_double();
|
||||||
|
double lng = unit[L"location"][L"lng"].as_double();
|
||||||
|
|
||||||
|
Coords location; location.lat = lat; location.lng = lng;
|
||||||
|
cloneOptions.push_back({ ID, location });
|
||||||
|
log(username + " cloning unit with ID " + to_string(ID), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
command = dynamic_cast<Command*>(new Clone(cloneOptions, deleteOriginal));
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setROE") == 0)
|
else if (key.compare("setROE") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unsigned char ROE = value[L"ROE"].as_number().to_uint32();
|
if (unit != nullptr) {
|
||||||
unit->setROE(ROE);
|
unsigned char ROE = value[L"ROE"].as_number().to_uint32();
|
||||||
log(username + " set unit " + unit->getName() + " ROE to " + to_string(ROE), true);
|
unit->setROE(ROE);
|
||||||
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") ROE to " + to_string(ROE), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setReactionToThreat") == 0)
|
else if (key.compare("setReactionToThreat") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().to_uint32();
|
if (unit != nullptr) {
|
||||||
unit->setReactionToThreat(reactionToThreat);
|
unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().to_uint32();
|
||||||
log(username + " set unit " + unit->getName() + " reaction to threat to " + to_string(reactionToThreat), true);
|
unit->setReactionToThreat(reactionToThreat);
|
||||||
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") reaction to threat to " + to_string(reactionToThreat), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setEmissionsCountermeasures") == 0)
|
else if (key.compare("setEmissionsCountermeasures") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().to_uint32();
|
if (unit != nullptr) {
|
||||||
unit->setEmissionsCountermeasures(emissionsCountermeasures);
|
unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().to_uint32();
|
||||||
log(username + " set unit " + unit->getName() + " emissions and countermeasures to " + to_string(emissionsCountermeasures), true);
|
unit->setEmissionsCountermeasures(emissionsCountermeasures);
|
||||||
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") emissions and countermeasures to " + to_string(emissionsCountermeasures), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("landAt") == 0)
|
else if (key.compare("landAt") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
double lat = value[L"location"][L"lat"].as_double();
|
if (unit != nullptr) {
|
||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lat = value[L"location"][L"lat"].as_double();
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
unit->landAt(loc);
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
log(username + " tasked unit " + unit->getName() + " to land", true);
|
unit->landAt(loc);
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to land", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("deleteUnit") == 0)
|
else if (key.compare("deleteUnit") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
bool explosion = value[L"explosion"].as_bool();
|
bool explosion = value[L"explosion"].as_bool();
|
||||||
|
string explosionType = to_string(value[L"explosionType"]);
|
||||||
bool immediate = value[L"immediate"].as_bool();
|
bool immediate = value[L"immediate"].as_bool();
|
||||||
unitsManager->deleteUnit(ID, explosion, immediate);
|
|
||||||
Unit* unit = unitsManager->getUnit(ID);
|
Unit* unit = unitsManager->getUnit(ID);
|
||||||
log(username + " deleted unit " + unit->getName(), true);
|
if (unit != nullptr) {
|
||||||
|
unitsManager->deleteUnit(ID, explosion, explosionType, immediate);
|
||||||
|
log(username + " deleted unit " + unit->getUnitName() + "(" + unit->getName() + ")", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("refuel") == 0)
|
else if (key.compare("refuel") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::REFUEL);
|
if (unit != nullptr) {
|
||||||
log(username + " tasked unit " + unit->getName() + " to refuel", true);
|
unit->setState(State::REFUEL);
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to refuel", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setAdvancedOptions") == 0)
|
else if (key.compare("setAdvancedOptions") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
@@ -463,8 +447,8 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
if (unit != nullptr)
|
if (unit != nullptr)
|
||||||
{
|
{
|
||||||
/* Advanced tasking */
|
/* Advanced tasking */
|
||||||
unit->setIsTanker(value[L"isTanker"].as_bool());
|
unit->setIsActiveTanker(value[L"isActiveTanker"].as_bool());
|
||||||
unit->setIsAWACS(value[L"isAWACS"].as_bool());
|
unit->setIsActiveAWACS(value[L"isActiveAWACS"].as_bool());
|
||||||
|
|
||||||
/* TACAN Options */
|
/* TACAN Options */
|
||||||
DataTypes::TACAN TACAN;
|
DataTypes::TACAN TACAN;
|
||||||
@@ -494,33 +478,46 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
});
|
});
|
||||||
|
|
||||||
unit->resetActiveDestination();
|
unit->resetActiveDestination();
|
||||||
|
|
||||||
|
log(username + " updated unit " + unit->getUnitName() + "(" + unit->getName() + ") advancedOptions", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setFollowRoads") == 0)
|
else if (key.compare("setFollowRoads") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
bool followRoads = value[L"followRoads"].as_bool();
|
bool followRoads = value[L"followRoads"].as_bool();
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setFollowRoads(followRoads);
|
if (unit != nullptr) {
|
||||||
|
unit->setFollowRoads(followRoads);
|
||||||
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") followRoads to: " + (followRoads ? "true" : "false"), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("setOnOff") == 0)
|
else if (key.compare("setOnOff") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
unitsManager->acquireControl(ID);
|
unitsManager->acquireControl(ID);
|
||||||
bool onOff = value[L"onOff"].as_bool();
|
bool onOff = value[L"onOff"].as_bool();
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setOnOff(onOff);
|
if (unit != nullptr) {
|
||||||
|
unit->setOnOff(onOff);
|
||||||
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") onOff to: " + (onOff? "true": "false"), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("explosion") == 0)
|
else if (key.compare("explosion") == 0)
|
||||||
{
|
{
|
||||||
unsigned int intensity = value[L"intensity"].as_integer();
|
unsigned int intensity = value[L"intensity"].as_integer();
|
||||||
|
string explosionType = to_string(value[L"explosionType"]);
|
||||||
double lat = value[L"location"][L"lat"].as_double();
|
double lat = value[L"location"][L"lat"].as_double();
|
||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
log("Adding " + to_string(intensity) + " explosion at (" + to_string(lat) + ", " + to_string(lng) + ")");
|
log("Adding explosion of type " + explosionType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
command = dynamic_cast<Command*>(new Explosion(intensity, loc));
|
command = dynamic_cast<Command*>(new Explosion(intensity, explosionType, loc));
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("bombPoint") == 0)
|
else if (key.compare("bombPoint") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
@@ -529,10 +526,13 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::BOMB_POINT);
|
if (unit != nullptr) {
|
||||||
unit->setTargetPosition(loc);
|
unit->setTargetPosition(loc);
|
||||||
log(username + " tasked unit " + unit->getName() + " to bomb a point", true);
|
unit->setState(State::BOMB_POINT);
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to bomb a point", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("carpetBomb") == 0)
|
else if (key.compare("carpetBomb") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
@@ -541,10 +541,14 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::CARPET_BOMB);
|
if (unit != nullptr) {
|
||||||
unit->setTargetPosition(loc);
|
unit->setTargetPosition(loc);
|
||||||
log(username + " tasked unit " + unit->getName() + " to perform carpet bombing", true);
|
unit->setState(State::CARPET_BOMB);
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to perform carpet bombing", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
|
/* TODO: this command does not appear to be working in DCS and has been disabled */
|
||||||
else if (key.compare("bombBuilding") == 0)
|
else if (key.compare("bombBuilding") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
@@ -553,9 +557,12 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::BOMB_BUILDING);
|
if (unit != nullptr) {
|
||||||
unit->setTargetPosition(loc);
|
unit->setTargetPosition(loc);
|
||||||
|
unit->setState(State::BOMB_BUILDING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
else if (key.compare("fireAtArea") == 0)
|
else if (key.compare("fireAtArea") == 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = value[L"ID"].as_integer();
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
@@ -564,14 +571,114 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
double lng = value[L"location"][L"lng"].as_double();
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
unit->setState(State::FIRE_AT_AREA);
|
if (unit != nullptr) {
|
||||||
unit->setTargetPosition(loc);
|
unit->setTargetPosition(loc);
|
||||||
log(username + " tasked unit " + unit->getName() + " to fire at area", true);
|
unit->setState(State::FIRE_AT_AREA);
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to fire at area", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (key.compare("setCommandModeOptions") == 0) {
|
/************************/
|
||||||
|
else if (key.compare("simulateFireFight") == 0)
|
||||||
|
{
|
||||||
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
|
unitsManager->acquireControl(ID);
|
||||||
|
double lat = value[L"location"][L"lat"].as_double();
|
||||||
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
|
double alt = value[L"altitude"].as_double();
|
||||||
|
Coords loc; loc.lat = lat; loc.lng = lng; loc.alt = alt;
|
||||||
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
|
if (unit != nullptr) {
|
||||||
|
unit->setTargetPosition(loc);
|
||||||
|
unit->setState(State::SIMULATE_FIRE_FIGHT);
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to simulate a fire fight", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************/
|
||||||
|
else if (key.compare("scenicAAA") == 0)
|
||||||
|
{
|
||||||
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
|
unitsManager->acquireControl(ID);
|
||||||
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
|
if (unit != nullptr) {
|
||||||
|
unit->setState(State::SCENIC_AAA);
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to enter scenic AAA state", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************/
|
||||||
|
else if (key.compare("missOnPurpose") == 0)
|
||||||
|
{
|
||||||
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
|
unitsManager->acquireControl(ID);
|
||||||
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
|
if (unit != nullptr) {
|
||||||
|
unit->setState(State::MISS_ON_PURPOSE);
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to enter Miss On Purpose state", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************/
|
||||||
|
else if (key.compare("setOperateAs") == 0)
|
||||||
|
{
|
||||||
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
|
unitsManager->acquireControl(ID);
|
||||||
|
unsigned char operateAs = value[L"operateAs"].as_number().to_uint32();
|
||||||
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
|
if (unit != nullptr)
|
||||||
|
unit->setOperateAs(operateAs);
|
||||||
|
}
|
||||||
|
/************************/
|
||||||
|
else if (key.compare("landAtPoint") == 0)
|
||||||
|
{
|
||||||
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
|
unitsManager->acquireControl(ID);
|
||||||
|
double lat = value[L"location"][L"lat"].as_double();
|
||||||
|
double lng = value[L"location"][L"lng"].as_double();
|
||||||
|
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||||
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
|
|
||||||
|
if (unit != nullptr) {
|
||||||
|
list<Coords> newPath;
|
||||||
|
newPath.push_back(loc);
|
||||||
|
unit->setActivePath(newPath);
|
||||||
|
unit->setState(State::LAND_AT_POINT);
|
||||||
|
|
||||||
|
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to land at point", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************/
|
||||||
|
else if (key.compare("setShotsScatter") == 0)
|
||||||
|
{
|
||||||
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
|
unitsManager->acquireControl(ID);
|
||||||
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
|
if (unit != nullptr) {
|
||||||
|
unsigned char shotsScatter = value[L"shotsScatter"].as_number().to_uint32();
|
||||||
|
unit->setShotsScatter(shotsScatter);
|
||||||
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") shots scatter to " + to_string(shotsScatter), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************/
|
||||||
|
else if (key.compare("setShotsIntensity") == 0)
|
||||||
|
{
|
||||||
|
unsigned int ID = value[L"ID"].as_integer();
|
||||||
|
unitsManager->acquireControl(ID);
|
||||||
|
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||||
|
if (unit != nullptr) {
|
||||||
|
unsigned char shotsIntensity = value[L"shotsIntensity"].as_number().to_uint32();
|
||||||
|
unit->setShotsIntensity(shotsIntensity);
|
||||||
|
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") shots intensity to " + to_string(shotsIntensity), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/************************/
|
||||||
|
else if (key.compare("setCommandModeOptions") == 0)
|
||||||
|
{
|
||||||
setCommandModeOptions(value);
|
setCommandModeOptions(value);
|
||||||
log(username + " updated the Command Mode Options", true);
|
log(username + " updated the Command Mode Options", true);
|
||||||
}
|
}
|
||||||
|
/************************/
|
||||||
|
else if (key.compare("reloadDatabases") == 0) {
|
||||||
|
unitsManager->loadDatabases();
|
||||||
|
}
|
||||||
|
/************************/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log("Unknown command: " + key);
|
log("Unknown command: " + key);
|
||||||
@@ -581,6 +688,7 @@ void Scheduler::handleRequest(string key, json::value value, string username)
|
|||||||
{
|
{
|
||||||
appendCommand(command);
|
appendCommand(command);
|
||||||
log("New command appended correctly to stack. Current server load: " + to_string(getLoad()));
|
log("New command appended correctly to stack. Current server load: " + to_string(getLoad()));
|
||||||
|
answer[L"commandHash"] = json::value(to_wstring(command->getHash()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2,9 +2,12 @@
|
|||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "luatools.h"
|
#include "luatools.h"
|
||||||
#include "dcstools.h"
|
#include "dcstools.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
extern string instancePath;
|
||||||
|
|
||||||
bool executeLuaScript(lua_State* L, string path)
|
bool executeLuaScript(lua_State* L, string path)
|
||||||
{
|
{
|
||||||
replace(path.begin(), path.end(), '\\', '/');
|
replace(path.begin(), path.end(), '\\', '/');
|
||||||
@@ -36,21 +39,9 @@ void registerLuaFunctions(lua_State* L)
|
|||||||
log("protectedCall registered successfully");
|
log("protectedCall registered successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
char* buf = nullptr;
|
executeLuaScript(L, instancePath + MIST_SCRIPT);
|
||||||
size_t sz = 0;
|
executeLuaScript(L, instancePath + OLYMPUS_COMMAND_SCRIPT);
|
||||||
if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr)
|
executeLuaScript(L, instancePath + UNIT_PAYLOADS_SCRIPT);
|
||||||
{
|
executeLuaScript(L, instancePath + TEMPLATES_SCRIPT);
|
||||||
modLocation = buf;
|
executeLuaScript(L, instancePath + MODS_SCRIPT);
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log("DCSOLYMPUS_PATH environment variable is missing");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
executeLuaScript(L, modLocation + "\\Scripts\\mist.lua");
|
|
||||||
executeLuaScript(L, modLocation + "\\Scripts\\OlympusCommand.lua");
|
|
||||||
executeLuaScript(L, modLocation + "\\Scripts\\unitPayloads.lua");
|
|
||||||
executeLuaScript(L, modLocation + "\\Scripts\\templates.lua");
|
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,7 @@ extern Scheduler* scheduler;
|
|||||||
extern json::value missionData;
|
extern json::value missionData;
|
||||||
extern mutex mutexLock;
|
extern mutex mutexLock;
|
||||||
extern string sessionHash;
|
extern string sessionHash;
|
||||||
|
extern string instancePath;
|
||||||
|
|
||||||
void handle_eptr(std::exception_ptr eptr)
|
void handle_eptr(std::exception_ptr eptr)
|
||||||
{
|
{
|
||||||
@@ -88,7 +89,7 @@ void Server::handle_get(http_request request)
|
|||||||
try {
|
try {
|
||||||
time = stoull((*(query.find(L"time"))).second);
|
time = stoull((*(query.find(L"time"))).second);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e) {
|
catch (...) {
|
||||||
time = 0;
|
time = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +143,9 @@ void Server::handle_get(http_request request)
|
|||||||
else
|
else
|
||||||
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Observer");
|
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Observer");
|
||||||
}
|
}
|
||||||
|
else if (URI.compare(COMMANDS_URI) == 0 && query.find(L"commandHash") != query.end()) {
|
||||||
|
answer[L"commandExecuted"] = json::value(scheduler->isCommandExecuted(to_string(query[L"commandHash"])));
|
||||||
|
}
|
||||||
|
|
||||||
/* Common data */
|
/* Common data */
|
||||||
answer[L"time"] = json::value::string(to_wstring(ms.count()));
|
answer[L"time"] = json::value::string(to_wstring(ms.count()));
|
||||||
@@ -222,7 +226,7 @@ void Server::handle_put(http_request request)
|
|||||||
|
|
||||||
std::exception_ptr eptr;
|
std::exception_ptr eptr;
|
||||||
try {
|
try {
|
||||||
scheduler->handleRequest(to_string(key), value, username);
|
scheduler->handleRequest(to_string(key), value, username, answer);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
eptr = std::current_exception(); // capture
|
eptr = std::current_exception(); // capture
|
||||||
@@ -283,39 +287,32 @@ string Server::extractPassword(http_request& request) {
|
|||||||
void Server::task()
|
void Server::task()
|
||||||
{
|
{
|
||||||
string address = REST_ADDRESS;
|
string address = REST_ADDRESS;
|
||||||
string modLocation;
|
string jsonLocation = instancePath + OLYMPUS_JSON_PATH;
|
||||||
char* buf = nullptr;
|
|
||||||
size_t sz = 0;
|
|
||||||
if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr)
|
|
||||||
{
|
|
||||||
std::ifstream ifstream(string(buf) + "\\olympus.json");
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << ifstream.rdbuf();
|
|
||||||
std::error_code errorCode;
|
|
||||||
json::value config = json::value::parse(ss.str(), errorCode);
|
|
||||||
if (config.is_object() && config.has_object_field(L"server") &&
|
|
||||||
config[L"server"].has_string_field(L"address") && config[L"server"].has_number_field(L"port"))
|
|
||||||
{
|
|
||||||
address = "http://" + to_string(config[L"server"][L"address"]) + ":" + to_string(config[L"server"][L"port"].as_number().to_int32());
|
|
||||||
log("Starting server on " + address);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
log("Error reading configuration file. Starting server on " + address);
|
|
||||||
|
|
||||||
if (config.is_object() && config.has_object_field(L"authentication"))
|
log("Reading configuration from " + jsonLocation);
|
||||||
{
|
|
||||||
if (config[L"authentication"].has_string_field(L"gameMasterPassword")) gameMasterPassword = to_string(config[L"authentication"][L"gameMasterPassword"]);
|
std::ifstream ifstream(jsonLocation);
|
||||||
if (config[L"authentication"].has_string_field(L"blueCommanderPassword")) blueCommanderPassword = to_string(config[L"authentication"][L"blueCommanderPassword"]);
|
std::stringstream ss;
|
||||||
if (config[L"authentication"].has_string_field(L"redCommanderPassword")) redCommanderPassword = to_string(config[L"authentication"][L"redCommanderPassword"]);
|
ss << ifstream.rdbuf();
|
||||||
}
|
std::error_code errorCode;
|
||||||
else
|
json::value config = json::value::parse(ss.str(), errorCode);
|
||||||
log("Error reading configuration file. No password set.");
|
if (config.is_object() && config.has_object_field(L"backend") &&
|
||||||
free(buf);
|
config[L"backend"].has_string_field(L"address") && config[L"backend"].has_number_field(L"port"))
|
||||||
|
{
|
||||||
|
address = "http://" + to_string(config[L"backend"][L"address"]) + ":" + to_string(config[L"backend"][L"port"].as_number().to_int32());
|
||||||
|
log("Starting backend on " + address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
log("Error reading configuration file. Starting backend on " + address);
|
||||||
|
|
||||||
|
if (config.is_object() && config.has_object_field(L"authentication"))
|
||||||
{
|
{
|
||||||
log("DCSOLYMPUS_PATH environment variable is missing, starting server on " + address);
|
if (config[L"authentication"].has_string_field(L"gameMasterPassword")) gameMasterPassword = to_string(config[L"authentication"][L"gameMasterPassword"]);
|
||||||
|
if (config[L"authentication"].has_string_field(L"blueCommanderPassword")) blueCommanderPassword = to_string(config[L"authentication"][L"blueCommanderPassword"]);
|
||||||
|
if (config[L"authentication"].has_string_field(L"redCommanderPassword")) redCommanderPassword = to_string(config[L"authentication"][L"redCommanderPassword"]);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
log("Error reading configuration file. No password set.");
|
||||||
|
|
||||||
http_listener listener(to_wstring(address + "/" + REST_URI));
|
http_listener listener(to_wstring(address + "/" + REST_URI));
|
||||||
|
|
||||||
@@ -333,7 +330,7 @@ void Server::task()
|
|||||||
.then([&listener]() {log("RESTServer starting to listen"); })
|
.then([&listener]() {log("RESTServer starting to listen"); })
|
||||||
.wait();
|
.wait();
|
||||||
|
|
||||||
while (runListener);
|
while (runListener) { Sleep(1000); };
|
||||||
|
|
||||||
listener.close()
|
listener.close()
|
||||||
.then([&listener]() {log("RESTServer stopping connections"); })
|
.then([&listener]() {log("RESTServer stopping connections"); })
|
||||||
@@ -66,9 +66,18 @@ void Unit::update(json::value json, double dt)
|
|||||||
if (json.has_number_field(L"heading"))
|
if (json.has_number_field(L"heading"))
|
||||||
setHeading(json[L"heading"].as_number().to_double());
|
setHeading(json[L"heading"].as_number().to_double());
|
||||||
|
|
||||||
|
if (json.has_number_field(L"track"))
|
||||||
|
setTrack(json[L"track"].as_number().to_double());
|
||||||
|
|
||||||
if (json.has_number_field(L"speed"))
|
if (json.has_number_field(L"speed"))
|
||||||
setSpeed(json[L"speed"].as_number().to_double());
|
setSpeed(json[L"speed"].as_number().to_double());
|
||||||
|
|
||||||
|
if (json.has_number_field(L"horizontalVelocity"))
|
||||||
|
setHorizontalVelocity(json[L"horizontalVelocity"].as_number().to_double());
|
||||||
|
|
||||||
|
if (json.has_number_field(L"verticalVelocity"))
|
||||||
|
setVerticalVelocity(json[L"verticalVelocity"].as_number().to_double());
|
||||||
|
|
||||||
if (json.has_boolean_field(L"isAlive"))
|
if (json.has_boolean_field(L"isAlive"))
|
||||||
setAlive(json[L"isAlive"].as_bool());
|
setAlive(json[L"isAlive"].as_bool());
|
||||||
|
|
||||||
@@ -131,6 +140,9 @@ void Unit::update(json::value json, double dt)
|
|||||||
if (json.has_boolean_field(L"hasTask"))
|
if (json.has_boolean_field(L"hasTask"))
|
||||||
setHasTask(json[L"hasTask"].as_bool());
|
setHasTask(json[L"hasTask"].as_bool());
|
||||||
|
|
||||||
|
if (json.has_number_field(L"health"))
|
||||||
|
setHealth(static_cast<unsigned char>(json[L"health"].as_number().to_uint32()));
|
||||||
|
|
||||||
runAILoop();
|
runAILoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +158,10 @@ void Unit::runAILoop() {
|
|||||||
|
|
||||||
/* If the unit is alive, controlled, is the leader of the group and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
|
/* If the unit is alive, controlled, is the leader of the group and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
|
||||||
if (getAlive() && getControlled() && !getHuman() && getIsLeader()) {
|
if (getAlive() && getControlled() && !getHuman() && getIsLeader()) {
|
||||||
if (checkTaskFailed() && state != State::IDLE && state != State::LAND)
|
if (getEnableTaskCheckFailed() && checkTaskFailed()) {
|
||||||
|
log(unitName + " has no task, switching to IDLE state");
|
||||||
setState(State::IDLE);
|
setState(State::IDLE);
|
||||||
|
}
|
||||||
AIloop();
|
AIloop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,8 +184,8 @@ void Unit::refreshLeaderData(unsigned long long time) {
|
|||||||
case DataIndex::state: updateValue(state, leader->state, datumIndex); break;
|
case DataIndex::state: updateValue(state, leader->state, datumIndex); break;
|
||||||
case DataIndex::task: updateValue(task, leader->task, datumIndex); break;
|
case DataIndex::task: updateValue(task, leader->task, datumIndex); break;
|
||||||
case DataIndex::hasTask: updateValue(hasTask, leader->hasTask, datumIndex); break;
|
case DataIndex::hasTask: updateValue(hasTask, leader->hasTask, datumIndex); break;
|
||||||
case DataIndex::isTanker: updateValue(isTanker, leader->isTanker, datumIndex); break;
|
case DataIndex::isActiveTanker: updateValue(isActiveTanker, leader->isActiveTanker, datumIndex); break;
|
||||||
case DataIndex::isAWACS: updateValue(isAWACS, leader->isAWACS, datumIndex); break;
|
case DataIndex::isActiveAWACS: updateValue(isActiveAWACS, leader->isActiveAWACS, datumIndex); break;
|
||||||
case DataIndex::onOff: updateValue(onOff, leader->onOff, datumIndex); break;
|
case DataIndex::onOff: updateValue(onOff, leader->onOff, datumIndex); break;
|
||||||
case DataIndex::followRoads: updateValue(followRoads, leader->followRoads, datumIndex); break;
|
case DataIndex::followRoads: updateValue(followRoads, leader->followRoads, datumIndex); break;
|
||||||
case DataIndex::desiredSpeed: updateValue(desiredSpeed, leader->desiredSpeed, datumIndex); break;
|
case DataIndex::desiredSpeed: updateValue(desiredSpeed, leader->desiredSpeed, datumIndex); break;
|
||||||
@@ -189,6 +203,9 @@ void Unit::refreshLeaderData(unsigned long long time) {
|
|||||||
case DataIndex::radio: updateValue(radio, leader->radio, datumIndex); break;
|
case DataIndex::radio: updateValue(radio, leader->radio, datumIndex); break;
|
||||||
case DataIndex::generalSettings: updateValue(generalSettings, leader->generalSettings, datumIndex); break;
|
case DataIndex::generalSettings: updateValue(generalSettings, leader->generalSettings, datumIndex); break;
|
||||||
case DataIndex::activePath: updateValue(activePath, leader->activePath, datumIndex); break;
|
case DataIndex::activePath: updateValue(activePath, leader->activePath, datumIndex); break;
|
||||||
|
case DataIndex::operateAs: updateValue(operateAs, leader->operateAs, datumIndex); break;
|
||||||
|
case DataIndex::shotsScatter: updateValue(shotsScatter, leader->shotsScatter, datumIndex); break;
|
||||||
|
case DataIndex::shotsIntensity: updateValue(shotsIntensity, leader->shotsIntensity, datumIndex); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,44 +247,51 @@ void Unit::getData(stringstream& ss, unsigned long long time)
|
|||||||
{
|
{
|
||||||
if (checkFreshness(datumIndex, time)) {
|
if (checkFreshness(datumIndex, time)) {
|
||||||
switch (datumIndex) {
|
switch (datumIndex) {
|
||||||
case DataIndex::category: appendString(ss, datumIndex, category); break;
|
case DataIndex::category: appendString(ss, datumIndex, category); break;
|
||||||
case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break;
|
case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break;
|
||||||
case DataIndex::human: appendNumeric(ss, datumIndex, human); break;
|
case DataIndex::human: appendNumeric(ss, datumIndex, human); break;
|
||||||
case DataIndex::controlled: appendNumeric(ss, datumIndex, controlled); break;
|
case DataIndex::controlled: appendNumeric(ss, datumIndex, controlled); break;
|
||||||
case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break;
|
case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break;
|
||||||
case DataIndex::country: appendNumeric(ss, datumIndex, country); break;
|
case DataIndex::country: appendNumeric(ss, datumIndex, country); break;
|
||||||
case DataIndex::name: appendString(ss, datumIndex, name); break;
|
case DataIndex::name: appendString(ss, datumIndex, name); break;
|
||||||
case DataIndex::unitName: appendString(ss, datumIndex, unitName); break;
|
case DataIndex::unitName: appendString(ss, datumIndex, unitName); break;
|
||||||
case DataIndex::groupName: appendString(ss, datumIndex, groupName); break;
|
case DataIndex::groupName: appendString(ss, datumIndex, groupName); break;
|
||||||
case DataIndex::state: appendNumeric(ss, datumIndex, state); break;
|
case DataIndex::state: appendNumeric(ss, datumIndex, state); break;
|
||||||
case DataIndex::task: appendString(ss, datumIndex, task); break;
|
case DataIndex::task: appendString(ss, datumIndex, task); break;
|
||||||
case DataIndex::hasTask: appendNumeric(ss, datumIndex, hasTask); break;
|
case DataIndex::hasTask: appendNumeric(ss, datumIndex, hasTask); break;
|
||||||
case DataIndex::position: appendNumeric(ss, datumIndex, position); break;
|
case DataIndex::position: appendNumeric(ss, datumIndex, position); break;
|
||||||
case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break;
|
case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break;
|
||||||
case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break;
|
case DataIndex::horizontalVelocity: appendNumeric(ss, datumIndex, horizontalVelocity); break;
|
||||||
case DataIndex::isTanker: appendNumeric(ss, datumIndex, isTanker); break;
|
case DataIndex::verticalVelocity: appendNumeric(ss, datumIndex, verticalVelocity); break;
|
||||||
case DataIndex::isAWACS: appendNumeric(ss, datumIndex, isAWACS); break;
|
case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break;
|
||||||
case DataIndex::onOff: appendNumeric(ss, datumIndex, onOff); break;
|
case DataIndex::track: appendNumeric(ss, datumIndex, track); break;
|
||||||
case DataIndex::followRoads: appendNumeric(ss, datumIndex, followRoads); break;
|
case DataIndex::isActiveTanker: appendNumeric(ss, datumIndex, isActiveTanker); break;
|
||||||
case DataIndex::fuel: appendNumeric(ss, datumIndex, fuel); break;
|
case DataIndex::isActiveAWACS: appendNumeric(ss, datumIndex, isActiveAWACS); break;
|
||||||
case DataIndex::desiredSpeed: appendNumeric(ss, datumIndex, desiredSpeed); break;
|
case DataIndex::onOff: appendNumeric(ss, datumIndex, onOff); break;
|
||||||
case DataIndex::desiredSpeedType: appendNumeric(ss, datumIndex, desiredSpeedType); break;
|
case DataIndex::followRoads: appendNumeric(ss, datumIndex, followRoads); break;
|
||||||
case DataIndex::desiredAltitude: appendNumeric(ss, datumIndex, desiredAltitude); break;
|
case DataIndex::fuel: appendNumeric(ss, datumIndex, fuel); break;
|
||||||
case DataIndex::desiredAltitudeType: appendNumeric(ss, datumIndex, desiredAltitudeType); break;
|
case DataIndex::desiredSpeed: appendNumeric(ss, datumIndex, desiredSpeed); break;
|
||||||
case DataIndex::leaderID: appendNumeric(ss, datumIndex, leaderID); break;
|
case DataIndex::desiredSpeedType: appendNumeric(ss, datumIndex, desiredSpeedType); break;
|
||||||
case DataIndex::formationOffset: appendNumeric(ss, datumIndex, formationOffset); break;
|
case DataIndex::desiredAltitude: appendNumeric(ss, datumIndex, desiredAltitude); break;
|
||||||
case DataIndex::targetID: appendNumeric(ss, datumIndex, targetID); break;
|
case DataIndex::desiredAltitudeType: appendNumeric(ss, datumIndex, desiredAltitudeType); break;
|
||||||
case DataIndex::targetPosition: appendNumeric(ss, datumIndex, targetPosition); break;
|
case DataIndex::leaderID: appendNumeric(ss, datumIndex, leaderID); break;
|
||||||
case DataIndex::ROE: appendNumeric(ss, datumIndex, ROE); break;
|
case DataIndex::formationOffset: appendNumeric(ss, datumIndex, formationOffset); break;
|
||||||
case DataIndex::reactionToThreat: appendNumeric(ss, datumIndex, reactionToThreat); break;
|
case DataIndex::targetID: appendNumeric(ss, datumIndex, targetID); break;
|
||||||
case DataIndex::emissionsCountermeasures: appendNumeric(ss, datumIndex, emissionsCountermeasures); break;
|
case DataIndex::targetPosition: appendNumeric(ss, datumIndex, targetPosition); break;
|
||||||
case DataIndex::TACAN: appendNumeric(ss, datumIndex, TACAN); break;
|
case DataIndex::ROE: appendNumeric(ss, datumIndex, ROE); break;
|
||||||
case DataIndex::radio: appendNumeric(ss, datumIndex, radio); break;
|
case DataIndex::reactionToThreat: appendNumeric(ss, datumIndex, reactionToThreat); break;
|
||||||
case DataIndex::generalSettings: appendNumeric(ss, datumIndex, generalSettings); break;
|
case DataIndex::emissionsCountermeasures: appendNumeric(ss, datumIndex, emissionsCountermeasures); break;
|
||||||
case DataIndex::ammo: appendVector(ss, datumIndex, ammo); break;
|
case DataIndex::TACAN: appendNumeric(ss, datumIndex, TACAN); break;
|
||||||
case DataIndex::contacts: appendVector(ss, datumIndex, contacts); break;
|
case DataIndex::radio: appendNumeric(ss, datumIndex, radio); break;
|
||||||
case DataIndex::activePath: appendList(ss, datumIndex, activePath); break;
|
case DataIndex::generalSettings: appendNumeric(ss, datumIndex, generalSettings); break;
|
||||||
case DataIndex::isLeader: appendNumeric(ss, datumIndex, isLeader); break;
|
case DataIndex::ammo: appendVector(ss, datumIndex, ammo); break;
|
||||||
|
case DataIndex::contacts: appendVector(ss, datumIndex, contacts); break;
|
||||||
|
case DataIndex::activePath: appendList(ss, datumIndex, activePath); break;
|
||||||
|
case DataIndex::isLeader: appendNumeric(ss, datumIndex, isLeader); break;
|
||||||
|
case DataIndex::operateAs: appendNumeric(ss, datumIndex, operateAs); break;
|
||||||
|
case DataIndex::shotsScatter: appendNumeric(ss, datumIndex, shotsScatter); break;
|
||||||
|
case DataIndex::shotsIntensity: appendNumeric(ss, datumIndex, shotsIntensity); break;
|
||||||
|
case DataIndex::health: appendNumeric(ss, datumIndex, health); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,7 +421,7 @@ void Unit::resetActiveDestination()
|
|||||||
|
|
||||||
void Unit::resetTask()
|
void Unit::resetTask()
|
||||||
{
|
{
|
||||||
Command* command = dynamic_cast<Command*>(new ResetTask(groupName));
|
Command* command = dynamic_cast<Command*>(new ResetTask(groupName, [this]() { this->setHasTaskAssigned(false); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(false);
|
setHasTask(false);
|
||||||
resetTaskFailedCounter();
|
resetTaskFailedCounter();
|
||||||
@@ -406,7 +430,11 @@ void Unit::resetTask()
|
|||||||
void Unit::setFormationOffset(Offset newFormationOffset)
|
void Unit::setFormationOffset(Offset newFormationOffset)
|
||||||
{
|
{
|
||||||
formationOffset = newFormationOffset;
|
formationOffset = newFormationOffset;
|
||||||
resetTask();
|
|
||||||
|
/* Apply the change */
|
||||||
|
setHasTask(false);
|
||||||
|
resetTaskFailedCounter();
|
||||||
|
AIloop();
|
||||||
|
|
||||||
triggerUpdate(DataIndex::formationOffset);
|
triggerUpdate(DataIndex::formationOffset);
|
||||||
}
|
}
|
||||||
@@ -491,23 +519,31 @@ void Unit::landAt(Coords loc)
|
|||||||
setState(State::LAND);
|
setState(State::LAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::setIsTanker(bool newIsTanker)
|
void Unit::setIsActiveTanker(bool newIsActiveTanker)
|
||||||
{
|
{
|
||||||
if (isTanker != newIsTanker) {
|
if (isActiveTanker != newIsActiveTanker) {
|
||||||
isTanker = newIsTanker;
|
isActiveTanker = newIsActiveTanker;
|
||||||
resetTask();
|
|
||||||
|
/* Apply the change */
|
||||||
|
setHasTask(false);
|
||||||
|
resetTaskFailedCounter();
|
||||||
|
AIloop();
|
||||||
|
|
||||||
triggerUpdate(DataIndex::isTanker);
|
triggerUpdate(DataIndex::isActiveTanker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::setIsAWACS(bool newIsAWACS)
|
void Unit::setIsActiveAWACS(bool newIsActiveAWACS)
|
||||||
{
|
{
|
||||||
if (isAWACS != newIsAWACS) {
|
if (isActiveAWACS != newIsActiveAWACS) {
|
||||||
isAWACS = newIsAWACS;
|
isActiveAWACS = newIsActiveAWACS;
|
||||||
resetTask();
|
|
||||||
|
/* Apply the change */
|
||||||
|
setHasTask(false);
|
||||||
|
resetTaskFailedCounter();
|
||||||
|
AIloop();
|
||||||
|
|
||||||
triggerUpdate(DataIndex::isAWACS);
|
triggerUpdate(DataIndex::isActiveAWACS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,6 +554,12 @@ void Unit::setTACAN(DataTypes::TACAN newTACAN, bool force)
|
|||||||
TACAN = newTACAN;
|
TACAN = newTACAN;
|
||||||
if (TACAN.isOn) {
|
if (TACAN.isOn) {
|
||||||
std::ostringstream commandSS;
|
std::ostringstream commandSS;
|
||||||
|
|
||||||
|
if (TACAN.channel < 0)
|
||||||
|
TACAN.channel = 0;
|
||||||
|
if (TACAN.channel > 126)
|
||||||
|
TACAN.channel = 126;
|
||||||
|
|
||||||
commandSS << "{"
|
commandSS << "{"
|
||||||
<< "id = 'ActivateBeacon',"
|
<< "id = 'ActivateBeacon',"
|
||||||
<< "params = {"
|
<< "params = {"
|
||||||
@@ -555,6 +597,12 @@ void Unit::setRadio(DataTypes::Radio newRadio, bool force)
|
|||||||
std::ostringstream commandSS;
|
std::ostringstream commandSS;
|
||||||
Command* command;
|
Command* command;
|
||||||
|
|
||||||
|
if (radio.frequency < 0)
|
||||||
|
radio.frequency = 0;
|
||||||
|
|
||||||
|
if (radio.frequency > 999000000)
|
||||||
|
radio.frequency = 999000000;
|
||||||
|
|
||||||
commandSS << "{"
|
commandSS << "{"
|
||||||
<< "id = 'SetFrequency',"
|
<< "id = 'SetFrequency',"
|
||||||
<< "params = {"
|
<< "params = {"
|
||||||
@@ -608,10 +656,11 @@ void Unit::setDesiredSpeed(double newDesiredSpeed)
|
|||||||
{
|
{
|
||||||
if (desiredSpeed != newDesiredSpeed) {
|
if (desiredSpeed != newDesiredSpeed) {
|
||||||
desiredSpeed = newDesiredSpeed;
|
desiredSpeed = newDesiredSpeed;
|
||||||
if (state == State::IDLE)
|
|
||||||
resetTask();
|
/* Apply the change */
|
||||||
else
|
setHasTask(false);
|
||||||
goToDestination(); /* Send the command to reach the destination */
|
resetTaskFailedCounter();
|
||||||
|
AIloop();
|
||||||
|
|
||||||
triggerUpdate(DataIndex::desiredSpeed);
|
triggerUpdate(DataIndex::desiredSpeed);
|
||||||
}
|
}
|
||||||
@@ -621,10 +670,11 @@ void Unit::setDesiredAltitude(double newDesiredAltitude)
|
|||||||
{
|
{
|
||||||
if (desiredAltitude != newDesiredAltitude) {
|
if (desiredAltitude != newDesiredAltitude) {
|
||||||
desiredAltitude = newDesiredAltitude;
|
desiredAltitude = newDesiredAltitude;
|
||||||
if (state == State::IDLE)
|
|
||||||
resetTask();
|
/* Apply the change */
|
||||||
else
|
setHasTask(false);
|
||||||
goToDestination(); /* Send the command to reach the destination */
|
resetTaskFailedCounter();
|
||||||
|
AIloop();
|
||||||
|
|
||||||
triggerUpdate(DataIndex::desiredAltitude);
|
triggerUpdate(DataIndex::desiredAltitude);
|
||||||
}
|
}
|
||||||
@@ -634,10 +684,11 @@ void Unit::setDesiredSpeedType(string newDesiredSpeedType)
|
|||||||
{
|
{
|
||||||
if (desiredSpeedType != (newDesiredSpeedType.compare("GS") == 0)) {
|
if (desiredSpeedType != (newDesiredSpeedType.compare("GS") == 0)) {
|
||||||
desiredSpeedType = newDesiredSpeedType.compare("GS") == 0;
|
desiredSpeedType = newDesiredSpeedType.compare("GS") == 0;
|
||||||
if (state == State::IDLE)
|
|
||||||
resetTask();
|
/* Apply the change */
|
||||||
else
|
setHasTask(false);
|
||||||
goToDestination(); /* Send the command to reach the destination */
|
resetTaskFailedCounter();
|
||||||
|
AIloop();
|
||||||
|
|
||||||
triggerUpdate(DataIndex::desiredSpeedType);
|
triggerUpdate(DataIndex::desiredSpeedType);
|
||||||
}
|
}
|
||||||
@@ -647,10 +698,11 @@ void Unit::setDesiredAltitudeType(string newDesiredAltitudeType)
|
|||||||
{
|
{
|
||||||
if (desiredAltitudeType != (newDesiredAltitudeType.compare("AGL") == 0)) {
|
if (desiredAltitudeType != (newDesiredAltitudeType.compare("AGL") == 0)) {
|
||||||
desiredAltitudeType = newDesiredAltitudeType.compare("AGL") == 0;
|
desiredAltitudeType = newDesiredAltitudeType.compare("AGL") == 0;
|
||||||
if (state == State::IDLE)
|
|
||||||
resetTask();
|
/* Apply the change */
|
||||||
else
|
setHasTask(false);
|
||||||
goToDestination(); /* Send the command to reach the destination */
|
resetTaskFailedCounter();
|
||||||
|
AIloop();
|
||||||
|
|
||||||
triggerUpdate(DataIndex::desiredAltitudeType);
|
triggerUpdate(DataIndex::desiredAltitudeType);
|
||||||
}
|
}
|
||||||
@@ -660,7 +712,7 @@ void Unit::goToDestination(string enrouteTask)
|
|||||||
{
|
{
|
||||||
if (activeDestination != NULL)
|
if (activeDestination != NULL)
|
||||||
{
|
{
|
||||||
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType() ? "GS" : "CAS", getDesiredAltitude(), getDesiredAltitudeType() ? "AGL" : "ASL", enrouteTask, getCategory()));
|
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType() ? "GS" : "CAS", getDesiredAltitude(), getDesiredAltitudeType() ? "AGL" : "ASL", enrouteTask, getCategory(), getFollowRoads(), [this]() { this->setHasTaskAssigned(true); }));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
setHasTask(true);
|
setHasTask(true);
|
||||||
}
|
}
|
||||||
@@ -726,13 +778,17 @@ bool Unit::updateActivePath(bool looping)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::setHasTask(bool newValue) {
|
||||||
|
updateValue(hasTask, newValue, DataIndex::hasTask);
|
||||||
|
}
|
||||||
|
|
||||||
bool Unit::checkTaskFailed()
|
bool Unit::checkTaskFailed()
|
||||||
{
|
{
|
||||||
if (getHasTask())
|
if (getHasTask())
|
||||||
return false;
|
return false;
|
||||||
else {
|
else {
|
||||||
if (taskCheckCounter > 0)
|
if (taskCheckCounter > 0)
|
||||||
taskCheckCounter--;
|
taskCheckCounter -= hasTaskAssigned;
|
||||||
return taskCheckCounter == 0;
|
return taskCheckCounter == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -741,6 +797,14 @@ void Unit::resetTaskFailedCounter() {
|
|||||||
taskCheckCounter = TASK_CHECK_INIT_VALUE;
|
taskCheckCounter = TASK_CHECK_INIT_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::setHasTaskAssigned(bool newHasTaskAssigned) {
|
||||||
|
hasTaskAssigned = newHasTaskAssigned;
|
||||||
|
if (hasTaskAssigned)
|
||||||
|
log(unitName + " was assigned a new task");
|
||||||
|
else
|
||||||
|
log(unitName + " no task assigned");
|
||||||
|
}
|
||||||
|
|
||||||
void Unit::triggerUpdate(unsigned char datumIndex) {
|
void Unit::triggerUpdate(unsigned char datumIndex) {
|
||||||
updateTimeMap[datumIndex] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
updateTimeMap[datumIndex] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,10 @@
|
|||||||
#include "weapon.h"
|
#include "weapon.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
#include <GeographicLib/Geodesic.hpp>
|
||||||
|
using namespace GeographicLib;
|
||||||
|
|
||||||
#include "base64.hpp"
|
#include "base64.hpp"
|
||||||
using namespace base64;
|
using namespace base64;
|
||||||
@@ -138,15 +142,87 @@ void UnitsManager::getUnitData(stringstream &ss, unsigned long long time)
|
|||||||
p.second->getData(ss, time);
|
p.second->getData(ss, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitsManager::deleteUnit(unsigned int ID, bool explosion, bool immediate)
|
void UnitsManager::deleteUnit(unsigned int ID, bool explosion, string explosionType, bool immediate)
|
||||||
{
|
{
|
||||||
if (getUnit(ID) != nullptr)
|
if (getUnit(ID) != nullptr)
|
||||||
{
|
{
|
||||||
Command* command = dynamic_cast<Command*>(new Delete(ID, explosion, immediate));
|
Command* command = dynamic_cast<Command*>(new Delete(ID, explosion, explosionType, immediate));
|
||||||
scheduler->appendCommand(command);
|
scheduler->appendCommand(command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Unit* UnitsManager::getClosestUnit(Unit* unit, unsigned char coalition, vector<string> categories, double &distance) {
|
||||||
|
Unit* closestUnit = nullptr;
|
||||||
|
distance = 0;
|
||||||
|
|
||||||
|
for (auto const& p : units) {
|
||||||
|
/* Check if the units category is of the correct type */
|
||||||
|
bool requestedCategory = false;
|
||||||
|
for (auto const& category : categories) {
|
||||||
|
if (p.second->getCategory().compare(category) == 0) {
|
||||||
|
requestedCategory = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the unit belongs to the desired coalition, is alive, and is of the category requested */
|
||||||
|
if (requestedCategory && p.second->getCoalition() == coalition && p.second->getAlive()) {
|
||||||
|
/* Compute the distance from the unit to the tested unit */
|
||||||
|
double dist;
|
||||||
|
double bearing1;
|
||||||
|
double bearing2;
|
||||||
|
Geodesic::WGS84().Inverse(unit->getPosition().lat, unit->getPosition().lng, p.second->getPosition().lat, p.second->getPosition().lng, dist, bearing1, bearing2);
|
||||||
|
double altDelta = unit->getPosition().alt - p.second->getPosition().alt;
|
||||||
|
|
||||||
|
/* If the closest unit has not been assigned yet, assign it to this unit */
|
||||||
|
if (closestUnit == nullptr)
|
||||||
|
{
|
||||||
|
closestUnit = p.second;
|
||||||
|
distance = sqrt(dist * dist + altDelta * altDelta);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Check if the unit is closer than the one already selected */
|
||||||
|
if (dist < distance) {
|
||||||
|
closestUnit = p.second;
|
||||||
|
distance = sqrt(dist * dist + altDelta * altDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closestUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
map<Unit*, double> UnitsManager::getUnitsInRange(Unit* unit, unsigned char coalition, vector<string> categories, double range) {
|
||||||
|
map<Unit*, double> unitsInRange;
|
||||||
|
|
||||||
|
for (auto const& p : units) {
|
||||||
|
/* Check if the units category is of the correct type */
|
||||||
|
bool requestedCategory = false;
|
||||||
|
for (auto const& category : categories) {
|
||||||
|
if (p.second->getCategory().compare(category) == 0) {
|
||||||
|
requestedCategory = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the unit belongs to the desired coalition, is alive, and is of the category requested */
|
||||||
|
if (requestedCategory && p.second->getCoalition() == coalition && p.second->getAlive()) {
|
||||||
|
/* Compute the distance from the unit to the tested unit */
|
||||||
|
double dist;
|
||||||
|
double bearing1;
|
||||||
|
double bearing2;
|
||||||
|
Geodesic::WGS84().Inverse(unit->getPosition().lat, unit->getPosition().lng, p.second->getPosition().lat, p.second->getPosition().lng, dist, bearing1, bearing2);
|
||||||
|
|
||||||
|
if (dist <= range)
|
||||||
|
unitsInRange[p.second] = dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unitsInRange;
|
||||||
|
}
|
||||||
|
|
||||||
void UnitsManager::acquireControl(unsigned int ID) {
|
void UnitsManager::acquireControl(unsigned int ID) {
|
||||||
Unit* leader = getGroupLeader(ID);
|
Unit* leader = getGroupLeader(ID);
|
||||||
if (leader != nullptr) {
|
if (leader != nullptr) {
|
||||||
@@ -157,3 +233,9 @@ void UnitsManager::acquireControl(unsigned int ID) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnitsManager::loadDatabases() {
|
||||||
|
Aircraft::loadDatabase(AIRCRAFT_DATABASE_PATH);
|
||||||
|
Helicopter::loadDatabase(HELICOPTER_DATABASE_PATH);
|
||||||
|
GroundUnit::loadDatabase(GROUNDUNIT_DATABASE_PATH);
|
||||||
|
NavyUnit::loadDatabase(NAVYUNIT_DATABASE_PATH);
|
||||||
|
}
|
||||||
110
backend/dcstools/dcstools.rc
Normal file
110
backend/dcstools/dcstools.rc
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Italian (Italy) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||||
|
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
#endif // Italian (Italy) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (United Kingdom) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,4,0
|
||||||
|
PRODUCTVERSION 1,0,3,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "DCS Olympus"
|
||||||
|
VALUE "FileDescription", "DCS Olympus"
|
||||||
|
VALUE "FileVersion", "1.0.4.0"
|
||||||
|
VALUE "InternalName", "dcstools.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||||
|
VALUE "OriginalFilename", "dcstools.dll"
|
||||||
|
VALUE "ProductName", "DCS Olympus"
|
||||||
|
VALUE "ProductVersion", "1.0.4.0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (United Kingdom) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\dcstools.h" />
|
<ClInclude Include="include\dcstools.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\luatools\luatools.vcxproj">
|
<ProjectReference Include="..\luatools\luatools.vcxproj">
|
||||||
@@ -32,6 +33,9 @@
|
|||||||
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
|
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="dcstools.rc" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
@@ -73,19 +77,23 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>.\..\..\bin\</OutDir>
|
<OutDir>.\..\..\build\backend\bin\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -134,6 +142,7 @@
|
|||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
|
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@@ -23,5 +23,13 @@
|
|||||||
<ClInclude Include="include\dcstools.h">
|
<ClInclude Include="include\dcstools.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="dcstools.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
14
backend/dcstools/resource.h
Normal file
14
backend/dcstools/resource.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by dcstools.rc
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -82,7 +82,7 @@ void getAllUnits(lua_State* L, map<unsigned int, json::value>& unitJSONs)
|
|||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
while (lua_next(L, 2) != 0)
|
while (lua_next(L, 2) != 0)
|
||||||
{
|
{
|
||||||
unsigned int ID = lua_tonumber(L, -2);
|
unsigned int ID = static_cast<unsigned int>(lua_tonumber(L, -2));
|
||||||
if (unitJSONs.find(ID) == unitJSONs.end())
|
if (unitJSONs.find(ID) == unitJSONs.end())
|
||||||
unitJSONs[ID] = json::value::object();
|
unitJSONs[ID] = json::value::object();
|
||||||
luaTableToJSON(L, -1, unitJSONs[ID]);
|
luaTableToJSON(L, -1, unitJSONs[ID]);
|
||||||
2579
backend/docs
Normal file
2579
backend/docs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
|
|
||||||
|
void DllExport setLogDirectory(std::string m_dirPath);
|
||||||
void DllExport log(const std::string& sMessage, bool addToJSON = false);
|
void DllExport log(const std::string& sMessage, bool addToJSON = false);
|
||||||
void DllExport log(const std::wstring& sMessage, bool addToJSON = false);
|
void DllExport log(const std::wstring& sMessage, bool addToJSON = false);
|
||||||
void DllExport getLogsJSON(json::value& json, unsigned long long time);
|
void DllExport getLogsJSON(json::value& json, unsigned long long time);
|
||||||
@@ -8,6 +8,7 @@ public:
|
|||||||
void log(const string& sMessage, bool addToJSON);
|
void log(const string& sMessage, bool addToJSON);
|
||||||
void log(const wstring& sMessage, bool addToJSON);
|
void log(const wstring& sMessage, bool addToJSON);
|
||||||
void toJSON(json::value& json, unsigned long long time);
|
void toJSON(json::value& json, unsigned long long time);
|
||||||
|
void setDirectory(string newDirPath);
|
||||||
|
|
||||||
static Logger* GetLogger();
|
static Logger* GetLogger();
|
||||||
|
|
||||||
@@ -20,9 +21,11 @@ private:
|
|||||||
static Logger* m_pThis;
|
static Logger* m_pThis;
|
||||||
static ofstream m_Logfile;
|
static ofstream m_Logfile;
|
||||||
static std::map<unsigned long long, std::string> m_logs;
|
static std::map<unsigned long long, std::string> m_logs;
|
||||||
|
static string m_dirPath;
|
||||||
|
|
||||||
mutex mutexLock;
|
mutex mutexLock;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
void Open();
|
void Open();
|
||||||
void Close();
|
void Close();
|
||||||
};
|
};
|
||||||
110
backend/logger/logger.rc
Normal file
110
backend/logger/logger.rc
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Italian (Italy) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||||
|
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
#endif // Italian (Italy) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (United Kingdom) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,4,0
|
||||||
|
PRODUCTVERSION 1,0,3,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "DCS Olympus"
|
||||||
|
VALUE "FileDescription", "DCS Olympus"
|
||||||
|
VALUE "FileVersion", "1.0.4.0"
|
||||||
|
VALUE "InternalName", "logger.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||||
|
VALUE "OriginalFilename", "logger.dll"
|
||||||
|
VALUE "ProductName", "DCS Olympus"
|
||||||
|
VALUE "ProductVersion", "1.0.4.0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (United Kingdom) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
@@ -25,12 +25,16 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\interface.h" />
|
<ClInclude Include="include\interface.h" />
|
||||||
<ClInclude Include="include\logger.h" />
|
<ClInclude Include="include\logger.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\utils\utils.vcxproj">
|
<ProjectReference Include="..\utils\utils.vcxproj">
|
||||||
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
|
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="logger.rc" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
@@ -72,19 +76,23 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>.\..\..\bin\</OutDir>
|
<OutDir>.\..\..\build\backend\bin\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -133,6 +141,7 @@
|
|||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
|
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@@ -29,5 +29,13 @@
|
|||||||
<ClInclude Include="include\interface.h">
|
<ClInclude Include="include\interface.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="logger.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
14
backend/logger/resource.h
Normal file
14
backend/logger/resource.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by logger.rc
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -4,6 +4,11 @@
|
|||||||
|
|
||||||
#define LOGGER Logger::GetLogger()
|
#define LOGGER Logger::GetLogger()
|
||||||
|
|
||||||
|
void setLogDirectory(string m_dirPath)
|
||||||
|
{
|
||||||
|
LOGGER->setDirectory(m_dirPath);
|
||||||
|
}
|
||||||
|
|
||||||
void log(const string& message, bool addToJSON)
|
void log(const string& message, bool addToJSON)
|
||||||
{
|
{
|
||||||
LOGGER->log(message, addToJSON);
|
LOGGER->log(message, addToJSON);
|
||||||
@@ -8,25 +8,51 @@ const string Logger::m_sFileName = LOG_NAME;
|
|||||||
Logger* Logger::m_pThis = NULL;
|
Logger* Logger::m_pThis = NULL;
|
||||||
ofstream Logger::m_Logfile;
|
ofstream Logger::m_Logfile;
|
||||||
std::map<unsigned long long, std::string> Logger::m_logs;
|
std::map<unsigned long long, std::string> Logger::m_logs;
|
||||||
|
std::string Logger::m_dirPath;
|
||||||
|
|
||||||
Logger::Logger()
|
Logger::Logger()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger* Logger::GetLogger()
|
Logger* Logger::GetLogger()
|
||||||
{
|
{
|
||||||
if (m_pThis == NULL) {
|
if (m_pThis == NULL) {
|
||||||
m_pThis = new Logger();
|
m_pThis = new Logger();
|
||||||
std::filesystem::path dirPath = std::filesystem::temp_directory_path();
|
m_pThis->Clear();
|
||||||
m_Logfile.open((dirPath.string() + m_sFileName).c_str(), ios::out);
|
|
||||||
}
|
}
|
||||||
return m_pThis;
|
return m_pThis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Logger::setDirectory(string newDirPath)
|
||||||
|
{
|
||||||
|
m_dirPath = newDirPath;
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::Clear()
|
||||||
|
{
|
||||||
|
lock_guard<mutex> guard(mutexLock);
|
||||||
|
try {
|
||||||
|
m_Logfile.open((m_dirPath + m_sFileName).c_str(), ios::out | ios::trunc);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::filesystem::path m_dirPath = std::filesystem::temp_directory_path();
|
||||||
|
m_Logfile.open((m_dirPath.string() + m_sFileName).c_str(), ios::out | ios::trunc);
|
||||||
|
}
|
||||||
|
m_Logfile << "Creating a new log instance\n";
|
||||||
|
m_pThis->Close();
|
||||||
|
}
|
||||||
|
|
||||||
void Logger::Open()
|
void Logger::Open()
|
||||||
{
|
{
|
||||||
std::filesystem::path dirPath = std::filesystem::temp_directory_path();
|
try {
|
||||||
m_Logfile.open((dirPath.string() + m_sFileName).c_str(), ios::out | ios::app);
|
m_Logfile.open((m_dirPath + m_sFileName).c_str(), ios::out | std::ios::app);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::filesystem::path m_dirPath = std::filesystem::temp_directory_path();
|
||||||
|
m_Logfile.open((m_dirPath.string() + m_sFileName).c_str(), ios::out | std::ios::app);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::Close()
|
void Logger::Close()
|
||||||
@@ -5,6 +5,7 @@ void DllExport stackUpdate(lua_State* L, int& stackDepth, int initialStack = 0);
|
|||||||
void DllExport stackPop(lua_State* L, int popDepth = 1);
|
void DllExport stackPop(lua_State* L, int popDepth = 1);
|
||||||
void DllExport stackClean(lua_State* L, int stackDepth);
|
void DllExport stackClean(lua_State* L, int stackDepth);
|
||||||
void DllExport luaTableToJSON(lua_State* L, int index, json::value& json, bool logKeys = false);
|
void DllExport luaTableToJSON(lua_State* L, int index, json::value& json, bool logKeys = false);
|
||||||
|
void DllExport luaLogTableKeys(lua_State* L, int index);
|
||||||
|
|
||||||
#define STACK_UPDATE stackUpdate(L, stackDepth, initialStack);
|
#define STACK_UPDATE stackUpdate(L, stackDepth, initialStack);
|
||||||
#define STACK_INIT int stackDepth = 0; int initialStack = 0; stackUpdate(L, initialStack);
|
#define STACK_INIT int stackDepth = 0; int initialStack = 0; stackUpdate(L, initialStack);
|
||||||
110
backend/luatools/luatools.rc
Normal file
110
backend/luatools/luatools.rc
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Italian (Italy) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||||
|
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
#endif // Italian (Italy) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (United Kingdom) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,4,0
|
||||||
|
PRODUCTVERSION 1,0,3,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "DCS Olympus"
|
||||||
|
VALUE "FileDescription", "DCS Olympus"
|
||||||
|
VALUE "FileVersion", "1.0.4.0"
|
||||||
|
VALUE "InternalName", "luatools.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||||
|
VALUE "OriginalFilename", "luatools.dll"
|
||||||
|
VALUE "ProductName", "DCS Olympus"
|
||||||
|
VALUE "ProductVersion", "1.0.4.0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (United Kingdom) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
@@ -60,19 +60,23 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>.\..\..\bin\</OutDir>
|
<OutDir>.\..\..\build\backend\bin\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -121,6 +125,7 @@
|
|||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
|
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@@ -160,6 +165,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\luatools.h" />
|
<ClInclude Include="include\luatools.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="luatools.rc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
@@ -23,5 +23,13 @@
|
|||||||
<ClInclude Include="include\luatools.h">
|
<ClInclude Include="include\luatools.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="luatools.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
14
backend/luatools/resource.h
Normal file
14
backend/luatools/resource.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by luatools.rc
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -18,6 +18,29 @@ void stackClean(lua_State* L, int stackDepth)
|
|||||||
lua_pop(L, stackDepth);
|
lua_pop(L, stackDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void luaLogTableKeys(lua_State* L, int index)
|
||||||
|
{
|
||||||
|
if (lua_istable(L, index))
|
||||||
|
{
|
||||||
|
STACK_INIT;
|
||||||
|
|
||||||
|
lua_pushvalue(L, index);
|
||||||
|
lua_pushnil(L);
|
||||||
|
while (lua_next(L, -2))
|
||||||
|
{
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
const char* key = lua_tostring(L, -1);
|
||||||
|
log(key);
|
||||||
|
lua_pop(L, 2);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
STACK_CLEAN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void luaTableToJSON(lua_State* L, int index, json::value& json, bool logKeys)
|
void luaTableToJSON(lua_State* L, int index, json::value& json, bool logKeys)
|
||||||
{
|
{
|
||||||
if (lua_istable(L, index))
|
if (lua_istable(L, index))
|
||||||
110
backend/olympus/olympus.rc
Normal file
110
backend/olympus/olympus.rc
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Italian (Italy) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||||
|
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
#endif // Italian (Italy) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (United Kingdom) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,4,0
|
||||||
|
PRODUCTVERSION 1,0,3,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "DCS Olympus"
|
||||||
|
VALUE "FileDescription", "DCS Olympus"
|
||||||
|
VALUE "FileVersion", "1.0.4.0"
|
||||||
|
VALUE "InternalName", "olympus.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||||
|
VALUE "OriginalFilename", "olympus.dll"
|
||||||
|
VALUE "ProductName", "DCS Olympus"
|
||||||
|
VALUE "ProductVersion", "1.0.4.0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (United Kingdom) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
@@ -20,10 +20,19 @@
|
|||||||
<ProjectReference Include="..\logger\logger.vcxproj">
|
<ProjectReference Include="..\logger\logger.vcxproj">
|
||||||
<Project>{873ecabe-fcfe-4217-ac15-91959c3cf1c6}</Project>
|
<Project>{873ecabe-fcfe-4217-ac15-91959c3cf1c6}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\luatools\luatools.vcxproj">
|
||||||
|
<Project>{de139ec1-4f88-47d5-be73-f41915fe14a3}</Project>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\utils\utils.vcxproj">
|
<ProjectReference Include="..\utils\utils.vcxproj">
|
||||||
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
|
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="olympus.rc" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
@@ -53,9 +62,11 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@@ -64,10 +75,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<OutDir>.\..\..\bin\</OutDir>
|
<OutDir>.\..\..\build\backend\bin\</OutDir>
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Label="Vcpkg">
|
|
||||||
<VcpkgAutoLink>true</VcpkgAutoLink>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@@ -87,6 +95,7 @@
|
|||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
<AdditionalDependencies>lua.lib</AdditionalDependencies>
|
<AdditionalDependencies>lua.lib</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
||||||
|
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@@ -112,6 +121,7 @@
|
|||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
<AdditionalDependencies>lua.lib</AdditionalDependencies>
|
<AdditionalDependencies>lua.lib</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
||||||
|
<DelayLoadDLLs>dcstools.dll;logger.dll;utils.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
@@ -13,4 +13,10 @@
|
|||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="olympus.rc" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
14
backend/olympus/resource.h
Normal file
14
backend/olympus/resource.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by olympus.rc
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
/* Run-time linking to core dll allows for "hot swap". This is useful for development but could be removed when stable.*/
|
/* Run-time linking to core dll allows for "hot swap". This is useful for development but could be removed when stable.*/
|
||||||
HINSTANCE hGetProcIDDLL = NULL;
|
HINSTANCE hGetProcIDDLL = NULL;
|
||||||
typedef int(__stdcall* f_coreInit)(lua_State* L);
|
typedef int(__stdcall* f_coreInit)(lua_State* L, const char* path);
|
||||||
typedef int(__stdcall* f_coreDeinit)(lua_State* L);
|
typedef int(__stdcall* f_coreDeinit)(lua_State* L);
|
||||||
typedef int(__stdcall* f_coreFrame)(lua_State* L);
|
typedef int(__stdcall* f_coreFrame)(lua_State* L);
|
||||||
typedef int(__stdcall* f_coreUnitsData)(lua_State* L);
|
typedef int(__stdcall* f_coreUnitsData)(lua_State* L);
|
||||||
@@ -18,25 +18,43 @@ f_coreUnitsData coreUnitsData = nullptr;
|
|||||||
f_coreWeaponsData coreWeaponsData = nullptr;
|
f_coreWeaponsData coreWeaponsData = nullptr;
|
||||||
f_coreMissionData coreMissionData = nullptr;
|
f_coreMissionData coreMissionData = nullptr;
|
||||||
|
|
||||||
|
string modPath;
|
||||||
|
|
||||||
|
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
|
||||||
|
std::string GetLastErrorAsString()
|
||||||
|
{
|
||||||
|
//Get the error message ID, if any.
|
||||||
|
DWORD errorMessageID = ::GetLastError();
|
||||||
|
if (errorMessageID == 0) {
|
||||||
|
return std::string(); //No error message has been recorded
|
||||||
|
}
|
||||||
|
|
||||||
|
LPSTR messageBuffer = nullptr;
|
||||||
|
|
||||||
|
//Ask Win32 to give us the string version of that message ID.
|
||||||
|
//The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
|
||||||
|
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
|
||||||
|
|
||||||
|
//Copy the error message into a std::string.
|
||||||
|
std::string message(messageBuffer, size);
|
||||||
|
|
||||||
|
//Free the Win32's string's buffer.
|
||||||
|
LocalFree(messageBuffer);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
static int onSimulationStart(lua_State* L)
|
static int onSimulationStart(lua_State* L)
|
||||||
{
|
{
|
||||||
|
LogInfo(L, "Trying to load core.dll from " + modPath);
|
||||||
|
SetDllDirectoryA(modPath.c_str());
|
||||||
|
|
||||||
|
setLogDirectory(modPath);
|
||||||
|
|
||||||
log("onSimulationStart callback called successfully");
|
log("onSimulationStart callback called successfully");
|
||||||
|
|
||||||
string modLocation;
|
string dllLocation = modPath + "\\core.dll";
|
||||||
string dllLocation;
|
|
||||||
char* buf = nullptr;
|
|
||||||
size_t sz = 0;
|
|
||||||
if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr)
|
|
||||||
{
|
|
||||||
modLocation = buf;
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log("DCSOLYMPUS_PATH environment variable is missing");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
dllLocation = modLocation + "\\bin\\core.dll";
|
|
||||||
|
|
||||||
log("Loading core.dll");
|
log("Loading core.dll");
|
||||||
hGetProcIDDLL = LoadLibrary(to_wstring(dllLocation).c_str());
|
hGetProcIDDLL = LoadLibrary(to_wstring(dllLocation).c_str());
|
||||||
@@ -90,14 +108,14 @@ static int onSimulationStart(lua_State* L)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
coreInit(L);
|
coreInit(L, modPath.c_str());
|
||||||
|
|
||||||
LogInfo(L, "Module loaded and started successfully.");
|
LogInfo(L, "Module loaded and started successfully.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
LogError(L, "Error while loading module, see Olympus.log in temporary folder for additional details.");
|
LogError(L, "Error while loading module: " + GetLastErrorAsString());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +162,7 @@ static int onSimulationStop(lua_State* L)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
LogError(L, "Error while unloading module, see Olympus.log in temporary folder for additional details.");
|
LogError(L, "Error while unloading module: " + GetLastErrorAsString());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +205,34 @@ static const luaL_Reg Map[] = {
|
|||||||
|
|
||||||
extern "C" DllExport int luaopen_olympus(lua_State * L)
|
extern "C" DllExport int luaopen_olympus(lua_State * L)
|
||||||
{
|
{
|
||||||
|
lua_getglobal(L, "require");
|
||||||
|
lua_pushstring(L, "lfs");
|
||||||
|
lua_pcall(L, 1, 1, 0);
|
||||||
|
lua_getfield(L, -1, "writedir");
|
||||||
|
lua_pcall(L, 0, 1, 0);
|
||||||
|
if (lua_isstring(L, -1)) {
|
||||||
|
modPath = string(lua_tostring(L, -1)) + "Mods\\Services\\Olympus\\bin\\";
|
||||||
|
SetDllDirectoryA(modPath.c_str());
|
||||||
|
LogInfo(L, "Instance location retrieved successfully");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Log without using the helper dlls because we have not loaded them yet here */
|
||||||
|
lua_getglobal(L, "log");
|
||||||
|
lua_getfield(L, -1, "ERROR");
|
||||||
|
int errorLevel = (int)lua_tointeger(L, -1);
|
||||||
|
|
||||||
|
lua_getglobal(L, "log");
|
||||||
|
lua_getfield(L, -1, "write");
|
||||||
|
lua_pushstring(L, "Olympus.dll");
|
||||||
|
lua_pushnumber(L, errorLevel);
|
||||||
|
lua_pushstring(L, "An error has occurred while trying to retrieve Olympus's instance location");
|
||||||
|
lua_pcall(L, 3, 0, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo(L, "Loading .dlls from " + modPath);
|
||||||
|
|
||||||
luaL_register(L, "olympus", Map);
|
luaL_register(L, "olympus", Map);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
28
backend/shared/include/defines.h
Normal file
28
backend/shared/include/defines.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define VERSION "{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}"
|
||||||
|
#define LOG_NAME "..\\..\\..\\..\\Logs\\Olympus_log.txt"
|
||||||
|
|
||||||
|
#define REST_ADDRESS "http://localhost:3001"
|
||||||
|
#define REST_URI "olympus"
|
||||||
|
#define UNITS_URI "units"
|
||||||
|
#define WEAPONS_URI "weapons"
|
||||||
|
#define LOGS_URI "logs"
|
||||||
|
#define AIRBASES_URI "airbases"
|
||||||
|
#define BULLSEYE_URI "bullseyes"
|
||||||
|
#define MISSION_URI "mission"
|
||||||
|
#define COMMANDS_URI "commands"
|
||||||
|
|
||||||
|
#define FRAMERATE_TIME_INTERVAL 0.05
|
||||||
|
|
||||||
|
#define OLYMPUS_JSON_PATH "..\\..\\..\\..\\Config\\olympus.json"
|
||||||
|
#define AIRCRAFT_DATABASE_PATH "..\\databases\\units\\aircraftdatabase.json"
|
||||||
|
#define HELICOPTER_DATABASE_PATH "..\\databases\\units\\helicopterdatabase.json"
|
||||||
|
#define GROUNDUNIT_DATABASE_PATH "..\\databases\\units\\groundunitdatabase.json"
|
||||||
|
#define NAVYUNIT_DATABASE_PATH "..\\databases\\units\\navyunitdatabase.json"
|
||||||
|
|
||||||
|
#define MIST_SCRIPT "..\\Scripts\\mist.lua"
|
||||||
|
#define OLYMPUS_COMMAND_SCRIPT "..\\Scripts\\OlympusCommand.lua"
|
||||||
|
#define UNIT_PAYLOADS_SCRIPT "..\\Scripts\\unitPayloads.lua"
|
||||||
|
#define TEMPLATES_SCRIPT "..\\Scripts\\templates.lua"
|
||||||
|
#define MODS_SCRIPT "..\\Scripts\\mods.lua"
|
||||||
14
backend/utils/resource.h
Normal file
14
backend/utils/resource.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by utils.rc
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -44,6 +44,7 @@ std::string to_string(const std::wstring& wstr)
|
|||||||
|
|
||||||
std::string random_string(size_t length)
|
std::string random_string(size_t length)
|
||||||
{
|
{
|
||||||
|
srand(static_cast<unsigned int>(time(NULL)));
|
||||||
auto randchar = []() -> char
|
auto randchar = []() -> char
|
||||||
{
|
{
|
||||||
const char charset[] =
|
const char charset[] =
|
||||||
110
backend/utils/utils.rc
Normal file
110
backend/utils/utils.rc
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Italian (Italy) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||||
|
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
#endif // Italian (Italy) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (United Kingdom) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
||||||
|
#pragma code_page(1252)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,4,0
|
||||||
|
PRODUCTVERSION 1,0,3,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "DCS Olympus"
|
||||||
|
VALUE "FileDescription", "DCS Olympus"
|
||||||
|
VALUE "FileVersion", "1.0.4.0"
|
||||||
|
VALUE "InternalName", "utils.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2023"
|
||||||
|
VALUE "OriginalFilename", "utils.dll"
|
||||||
|
VALUE "ProductName", "TODO: <Product name>"
|
||||||
|
VALUE "ProductVersion", "1.0.4.0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // English (United Kingdom) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
@@ -20,10 +20,14 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\utils.h" />
|
<ClInclude Include="include\utils.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\utils.cpp" />
|
<ClCompile Include="src\utils.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="utils.rc" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
@@ -65,19 +69,23 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\DCSOlympus.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>.\..\..\bin\</OutDir>
|
<OutDir>.\..\..\build\backend\bin\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
@@ -14,10 +14,16 @@
|
|||||||
<ClInclude Include="include\utils.h">
|
<ClInclude Include="include\utils.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\utils.cpp">
|
<ClCompile Include="src\utils.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="utils.rc" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
14
backend/vcpkg-configuration.json
Normal file
14
backend/vcpkg-configuration.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"default-registry": {
|
||||||
|
"kind": "git",
|
||||||
|
"baseline": "7f9f0e44db287e8e67c0e888141bfa200ab45121",
|
||||||
|
"repository": "https://github.com/microsoft/vcpkg"
|
||||||
|
},
|
||||||
|
"registries": [
|
||||||
|
{
|
||||||
|
"kind": "artifact",
|
||||||
|
"location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
|
||||||
|
"name": "microsoft"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
6
backend/vcpkg.json
Normal file
6
backend/vcpkg.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"dependencies": [
|
||||||
|
"cpprestsdk",
|
||||||
|
"geographiclib"
|
||||||
|
]
|
||||||
|
}
|
||||||
2
build_package.bat
Normal file
2
build_package.bat
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
call .\scripts\batch\build.bat
|
||||||
|
call .\scripts\batch\package.bat
|
||||||
2
client/.vscode/settings.json
vendored
2
client/.vscode/settings.json
vendored
@@ -1,2 +0,0 @@
|
|||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
var express = require('express');
|
|
||||||
var path = require('path');
|
|
||||||
var cookieParser = require('cookie-parser');
|
|
||||||
var logger = require('morgan');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var atcRouter = require('./routes/api/atc');
|
|
||||||
var airbasesRouter = require('./routes/api/airbases');
|
|
||||||
var indexRouter = require('./routes/index');
|
|
||||||
var uikitRouter = require('./routes/uikit');
|
|
||||||
var usersRouter = require('./routes/users');
|
|
||||||
var resourcesRouter = require('./routes/resources');
|
|
||||||
|
|
||||||
var app = express();
|
|
||||||
|
|
||||||
app.use(logger('dev'));
|
|
||||||
app.use(express.json());
|
|
||||||
app.use(express.urlencoded({ extended: false }));
|
|
||||||
app.use(cookieParser());
|
|
||||||
app.use(express.static(path.join(__dirname, 'public')));
|
|
||||||
|
|
||||||
app.use('/', indexRouter);
|
|
||||||
app.use('/api/atc', atcRouter);
|
|
||||||
app.use('/api/airbases', airbasesRouter);
|
|
||||||
app.use('/users', usersRouter);
|
|
||||||
app.use('/uikit', uikitRouter);
|
|
||||||
app.use('/resources', resourcesRouter);
|
|
||||||
|
|
||||||
app.set('view engine', 'ejs');
|
|
||||||
|
|
||||||
let rawdata = fs.readFileSync('../olympus.json');
|
|
||||||
let config = JSON.parse(rawdata);
|
|
||||||
if (config["server"] != undefined)
|
|
||||||
app.get('/config', (req, res) => res.send(config["server"]));
|
|
||||||
|
|
||||||
module.exports = app;
|
|
||||||
|
|
||||||
const DemoDataGenerator = require('./demo.js');
|
|
||||||
var demoDataGenerator = new DemoDataGenerator(app);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var app = require('../app');
|
|
||||||
var debug = require('debug')('client:server');
|
|
||||||
var http = require('http');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get port from environment and store in Express.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var port = normalizePort(process.env.PORT || '3000');
|
|
||||||
app.set('port', port);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create HTTP server.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var server = http.createServer(app);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listen on provided port, on all network interfaces.
|
|
||||||
*/
|
|
||||||
|
|
||||||
server.listen(port);
|
|
||||||
server.on('error', onError);
|
|
||||||
server.on('listening', onListening);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalize a port into a number, string, or false.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function normalizePort(val) {
|
|
||||||
var port = parseInt(val, 10);
|
|
||||||
|
|
||||||
if (isNaN(port)) {
|
|
||||||
// named pipe
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port >= 0) {
|
|
||||||
// port number
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event listener for HTTP server "error" event.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function onError(error) {
|
|
||||||
if (error.syscall !== 'listen') {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
var bind = typeof port === 'string'
|
|
||||||
? 'Pipe ' + port
|
|
||||||
: 'Port ' + port;
|
|
||||||
|
|
||||||
// handle specific listen errors with friendly messages
|
|
||||||
switch (error.code) {
|
|
||||||
case 'EACCES':
|
|
||||||
console.error(bind + ' requires elevated privileges');
|
|
||||||
process.exit(1);
|
|
||||||
break;
|
|
||||||
case 'EADDRINUSE':
|
|
||||||
console.error(bind + ' is already in use');
|
|
||||||
process.exit(1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event listener for HTTP server "listening" event.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function onListening() {
|
|
||||||
var addr = server.address();
|
|
||||||
var bind = typeof addr === 'string'
|
|
||||||
? 'pipe ' + addr
|
|
||||||
: 'port ' + addr.port;
|
|
||||||
debug('Listening on ' + bind);
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet\\leaflet.css
|
|
||||||
copy .\\node_modules\\leaflet.nauticscale\\dist\\leaflet.nauticscale.js .\\public\\javascripts\\leaflet.nauticscale.js
|
|
||||||
copy .\\node_modules\\leaflet-path-drag\\dist\\L.Path.Drag.js .\\public\\javascripts\\L.Path.Drag.js
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
start cmd /k "npm run start"
|
|
||||||
start cmd /k "watchify .\src\index.ts --debug -o .\public\javascripts\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]
|
|
||||||
460
client/demo.js
460
client/demo.js
@@ -1,460 +0,0 @@
|
|||||||
var basicAuth = require('express-basic-auth')
|
|
||||||
var enc = new TextEncoder();
|
|
||||||
|
|
||||||
const DEMO_UNIT_DATA = {
|
|
||||||
["1"]:{ category: "Aircraft", alive: true, human: false, controlled: true, coalition: 2, country: 0, name: "KC-135", unitName: "Cool guy 1-1 who also has a very long name", groupName: "Cool group 1", state: 3, task: "Being cool!",
|
|
||||||
hasTask: true, position: { lat: 37, lng: -116, alt: 1000 }, speed: 200, heading: 45, isTanker: true, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
|
||||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
|
||||||
formationOffset: { x: 0, y: 0, z: 0 },
|
|
||||||
targetID: 2,
|
|
||||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
|
||||||
ROE: 1,
|
|
||||||
reactionToThreat: 1,
|
|
||||||
emissionsCountermeasures: 1,
|
|
||||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
|
||||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
|
||||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
|
||||||
ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
|
||||||
contacts: [{ID: 2, detectionMethod: 1}, {ID: 3, detectionMethod: 4}],
|
|
||||||
activePath: [{lat: 38, lng: -115, alt: 0}, {lat: 38, lng: -114, alt: 0}]
|
|
||||||
},
|
|
||||||
["2"]:{ category: "Aircraft", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "FA-18C_hornet", unitName: "Cool guy 1-2", groupName: "Cool group 2", state: 1, task: "Being cool",
|
|
||||||
hasTask: false, position: { lat: 36.9, lng: -116, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
|
||||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
|
||||||
formationOffset: { x: 0, y: 0, z: 0 },
|
|
||||||
targetID: 0,
|
|
||||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
|
||||||
ROE: 1,
|
|
||||||
reactionToThreat: 1,
|
|
||||||
emissionsCountermeasures: 1,
|
|
||||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
|
||||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
|
||||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
|
||||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
|
||||||
contacts: [{ID: 1, detectionMethod: 16}],
|
|
||||||
activePath: [ ]
|
|
||||||
}, ["3"]:{ category: "Helicopter", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "AH-64D_BLK_II", unitName: "Cool guy 1-4", groupName: "Cool group 3", state: 1, task: "Being cool",
|
|
||||||
hasTask: false, position: { lat: 37.1, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
|
||||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
|
||||||
formationOffset: { x: 0, y: 0, z: 0 },
|
|
||||||
targetID: 0,
|
|
||||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
|
||||||
ROE: 1,
|
|
||||||
reactionToThreat: 1,
|
|
||||||
emissionsCountermeasures: 1,
|
|
||||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
|
||||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
|
||||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
|
||||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
|
||||||
contacts: [{ID: 1, detectionMethod: 16}],
|
|
||||||
activePath: [ ]
|
|
||||||
}, ["4"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "Gepard", unitName: "Cool guy 2-1", groupName: "Cool group 4", state: 1, task: "Being cool",
|
|
||||||
hasTask: false, position: { lat: 37.2, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
|
||||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
|
||||||
formationOffset: { x: 0, y: 0, z: 0 },
|
|
||||||
targetID: 0,
|
|
||||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
|
||||||
ROE: 1,
|
|
||||||
reactionToThreat: 1,
|
|
||||||
emissionsCountermeasures: 1,
|
|
||||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
|
||||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
|
||||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
|
||||||
ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
|
||||||
contacts: [{ID: 1001, detectionMethod: 16}],
|
|
||||||
activePath: [ ],
|
|
||||||
isLeader: true
|
|
||||||
}, ["5"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "S_75M_Volhov", unitName: "Cool guy 2-2", groupName: "Cool group 4", state: 1, task: "Being cool",
|
|
||||||
hasTask: false, position: { lat: 37.21, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
|
||||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
|
||||||
formationOffset: { x: 0, y: 0, z: 0 },
|
|
||||||
targetID: 0,
|
|
||||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
|
||||||
ROE: 1,
|
|
||||||
reactionToThreat: 1,
|
|
||||||
emissionsCountermeasures: 1,
|
|
||||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
|
||||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
|
||||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
|
||||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
|
||||||
contacts: [],
|
|
||||||
activePath: [ ],
|
|
||||||
isLeader: false
|
|
||||||
},
|
|
||||||
["6"]:{ category: "Aircraft", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "FA-18C_hornet", unitName: "Bad boi 1-2", groupName: "Bad group 1", state: 1, task: "Being bad",
|
|
||||||
hasTask: false, position: { lat: 36.8, lng: -116, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
|
||||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
|
||||||
formationOffset: { x: 0, y: 0, z: 0 },
|
|
||||||
targetID: 0,
|
|
||||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
|
||||||
ROE: 1,
|
|
||||||
reactionToThreat: 1,
|
|
||||||
emissionsCountermeasures: 1,
|
|
||||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
|
||||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
|
||||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
|
||||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
|
||||||
contacts: [{ID: 1, detectionMethod: 16}],
|
|
||||||
activePath: [ ]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEMO_WEAPONS_DATA = {
|
|
||||||
["1001"]:{ category: "Missile", alive: true, coalition: 2, name: "", position: { lat: 37.1, lng: -116, alt: 1000 }, speed: 200, heading: 45 * Math.PI / 180 },
|
|
||||||
}
|
|
||||||
|
|
||||||
class DemoDataGenerator {
|
|
||||||
constructor(app)
|
|
||||||
{
|
|
||||||
app.get('/demo/units', (req, res) => this.units(req, res));
|
|
||||||
app.get('/demo/weapons', (req, res) => this.weapons(req, res));
|
|
||||||
app.get('/demo/logs', (req, res) => this.logs(req, res));
|
|
||||||
app.get('/demo/bullseyes', (req, res) => this.bullseyes(req, res));
|
|
||||||
app.get('/demo/airbases', (req, res) => this.airbases(req, res));
|
|
||||||
app.get('/demo/mission', (req, res) => this.mission(req, res));
|
|
||||||
|
|
||||||
app.use('/demo', basicAuth({
|
|
||||||
users: {
|
|
||||||
'admin': 'password',
|
|
||||||
'blue': 'bluepassword',
|
|
||||||
'red': 'redpassword'
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
|
|
||||||
this.startTime = Date.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
units(req, res){
|
|
||||||
var array = new Uint8Array();
|
|
||||||
var time = Date.now();
|
|
||||||
array = this.concat(array, this.uint64ToByteArray(BigInt(time)));
|
|
||||||
for (let idx in DEMO_UNIT_DATA) {
|
|
||||||
const unit = DEMO_UNIT_DATA[idx];
|
|
||||||
array = this.concat(array, this.uint32ToByteArray(idx));
|
|
||||||
array = this.appendString(array, unit.category, 1);
|
|
||||||
array = this.appendUint8(array, unit.alive, 2);
|
|
||||||
array = this.appendUint8(array, unit.human, 3);
|
|
||||||
array = this.appendUint8(array, unit.controlled, 4);
|
|
||||||
array = this.appendUint16(array, unit.coalition, 5);
|
|
||||||
array = this.appendUint8(array, unit.country, 6);
|
|
||||||
array = this.appendString(array, unit.name, 7);
|
|
||||||
array = this.appendString(array, unit.unitName, 8);
|
|
||||||
array = this.appendString(array, unit.groupName, 9);
|
|
||||||
array = this.appendUint8(array, unit.state, 10);
|
|
||||||
array = this.appendString(array, unit.task, 11);
|
|
||||||
array = this.appendUint8(array, unit.hasTask, 12);
|
|
||||||
array = this.appendCoordinates(array, unit.position, 13);
|
|
||||||
array = this.appendDouble(array, unit.speed, 14);
|
|
||||||
array = this.appendDouble(array, unit.heading, 15);
|
|
||||||
array = this.appendUint8(array, unit.isTanker, 16);
|
|
||||||
array = this.appendUint8(array, unit.isAWACS, 17);
|
|
||||||
array = this.appendUint8(array, unit.onOff, 18);
|
|
||||||
array = this.appendUint8(array, unit.followRoads, 19);
|
|
||||||
array = this.appendUint16(array, unit.fuel, 20);
|
|
||||||
array = this.appendDouble(array, unit.desiredSpeed, 21);
|
|
||||||
array = this.appendUint8(array, unit.desiredSpeedType, 22);
|
|
||||||
array = this.appendDouble(array, unit.desiredAltitude, 23);
|
|
||||||
array = this.appendUint8(array, unit.desiredAltitudeType, 24);
|
|
||||||
array = this.appendUint32(array, unit.leaderID, 25);
|
|
||||||
array = this.appendOffset(array, unit.formationOffset, 26);
|
|
||||||
array = this.appendUint32(array, unit.targetID, 27);
|
|
||||||
array = this.appendCoordinates(array, unit.targetPosition, 28);
|
|
||||||
array = this.appendUint8(array, unit.ROE, 29);
|
|
||||||
array = this.appendUint8(array, unit.reactionToThreat, 30);
|
|
||||||
array = this.appendUint8(array, unit.emissionsCountermeasures, 31);
|
|
||||||
array = this.appendTACAN(array, unit.TACAN, 32);
|
|
||||||
array = this.appendRadio(array, unit.radio, 33);
|
|
||||||
array = this.appendRadio(array, unit.generalSettings, 34);
|
|
||||||
array = this.appendAmmo(array, unit.ammo, 35);
|
|
||||||
array = this.appendContacts(array, unit.contacts, 36);
|
|
||||||
array = this.appendActivePath(array, unit.activePath, 37);
|
|
||||||
array = this.appendUint8(array, unit.isLeader, 38);
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(255));
|
|
||||||
}
|
|
||||||
res.end(Buffer.from(array, 'binary'));
|
|
||||||
};
|
|
||||||
|
|
||||||
weapons(req, res){
|
|
||||||
var array = new Uint8Array();
|
|
||||||
var time = Date.now();
|
|
||||||
array = this.concat(array, this.uint64ToByteArray(BigInt(time)));
|
|
||||||
for (let idx in DEMO_WEAPONS_DATA) {
|
|
||||||
const weapon = DEMO_WEAPONS_DATA[idx];
|
|
||||||
array = this.concat(array, this.uint32ToByteArray(idx));
|
|
||||||
array = this.appendString(array, weapon.category, 1);
|
|
||||||
array = this.appendUint8(array, weapon.alive, 2);
|
|
||||||
array = this.appendUint16(array, weapon.coalition, 5);
|
|
||||||
array = this.appendString(array, weapon.name, 7);
|
|
||||||
array = this.appendCoordinates(array, weapon.position, 13);
|
|
||||||
array = this.appendDouble(array, weapon.speed, 14);
|
|
||||||
array = this.appendDouble(array, weapon.heading, 15);
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(255));
|
|
||||||
}
|
|
||||||
res.end(Buffer.from(array, 'binary'));
|
|
||||||
};
|
|
||||||
|
|
||||||
concat(array1, array2) {
|
|
||||||
var mergedArray = new Uint8Array(array1.length + array2.length);
|
|
||||||
mergedArray.set(array1);
|
|
||||||
mergedArray.set(array2, array1.length);
|
|
||||||
return mergedArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8ToByteArray(number) {
|
|
||||||
var buffer = new ArrayBuffer(1);
|
|
||||||
var longNum = new Uint8Array(buffer);
|
|
||||||
longNum[0] = number;
|
|
||||||
return Array.from(new Uint8Array(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16ToByteArray(number) {
|
|
||||||
var buffer = new ArrayBuffer(2);
|
|
||||||
var longNum = new Uint16Array(buffer);
|
|
||||||
longNum[0] = number;
|
|
||||||
return Array.from(new Uint8Array(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32ToByteArray(number) {
|
|
||||||
var buffer = new ArrayBuffer(4);
|
|
||||||
var longNum = new Uint32Array(buffer);
|
|
||||||
longNum[0] = number;
|
|
||||||
return Array.from(new Uint8Array(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64ToByteArray(number) {
|
|
||||||
var buffer = new ArrayBuffer(8);
|
|
||||||
var longNum = new BigUint64Array(buffer);
|
|
||||||
longNum[0] = number;
|
|
||||||
return Array.from(new Uint8Array(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
doubleToByteArray(number) {
|
|
||||||
var buffer = new ArrayBuffer(8);
|
|
||||||
var longNum = new Float64Array(buffer);
|
|
||||||
longNum[0] = number;
|
|
||||||
return Array.from(new Uint8Array(buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
appendUint8(array, number, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(number));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendUint16(array, number, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint16ToByteArray(number));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendUint32(array, number, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint32ToByteArray(number));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendDouble(array, number, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(number));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendCoordinates(array, coordinates, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(coordinates.lat));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(coordinates.lng));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(coordinates.alt));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendOffset(array, offset, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(offset.x));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(offset.y));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(offset.z));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendString(array, string, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint16ToByteArray(string.length));
|
|
||||||
array = this.concat(array, enc.encode(string));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
padString(string, length) {
|
|
||||||
while (string.length < length)
|
|
||||||
string += " ";
|
|
||||||
return string.substring(0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
appendTACAN(array, TACAN, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(TACAN.isOn));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(TACAN.channel));
|
|
||||||
array = this.concat(array, enc.encode(TACAN.XY));
|
|
||||||
array = this.concat(array, enc.encode(this.padString(TACAN.callsign, 4)));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendRadio(array, radio, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint32ToByteArray(radio.frequency));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(radio.callsign));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(radio.callsignNumber));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendGeneralSettings(array, generalSettings, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitAA));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitAfterburner));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitAG));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitAirWpn));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitJettison));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendAmmo(array, ammo, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint16ToByteArray(ammo.length));
|
|
||||||
ammo.forEach((element) => {
|
|
||||||
array = this.concat(array, this.uint16ToByteArray(element.quantity));
|
|
||||||
array = this.concat(array, enc.encode(this.padString(element.name, 33)));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(element.guidance));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(element.category));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(element.missileCategory));
|
|
||||||
})
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendContacts(array, contacts, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint16ToByteArray(contacts.length));
|
|
||||||
contacts.forEach((element) => {
|
|
||||||
array = this.concat(array, this.uint32ToByteArray(element.ID));
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(element.detectionMethod));
|
|
||||||
})
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendActivePath(array, activePath, datumIndex) {
|
|
||||||
array = this.concat(array, this.uint8ToByteArray(datumIndex));
|
|
||||||
array = this.concat(array, this.uint16ToByteArray(activePath.length));
|
|
||||||
activePath.forEach((element) => {
|
|
||||||
array = this.concat(array, this.doubleToByteArray(element.lat));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(element.lng));
|
|
||||||
array = this.concat(array, this.doubleToByteArray(element.alt));
|
|
||||||
})
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
logs(req, res){
|
|
||||||
var ret = {logs: {"1": "I'm a log!", "2": "I'm a different log!"}};
|
|
||||||
ret.time = Date.now();
|
|
||||||
ret.frameRate = 60;
|
|
||||||
ret.load = 0;
|
|
||||||
res.send(JSON.stringify(ret));
|
|
||||||
};
|
|
||||||
|
|
||||||
airbases(req, res){
|
|
||||||
var ret = {airbases: {
|
|
||||||
["0"]: {
|
|
||||||
callsign: "Nellis",
|
|
||||||
latitude: 37.3,
|
|
||||||
longitude: -115.8,
|
|
||||||
coalition: "neutral"
|
|
||||||
},
|
|
||||||
["1"]: {
|
|
||||||
callsign: "Red",
|
|
||||||
latitude: 37.3,
|
|
||||||
longitude: -115.75,
|
|
||||||
coalition: "red"
|
|
||||||
},
|
|
||||||
["2"]: {
|
|
||||||
callsign: "Blue",
|
|
||||||
latitude: 37.3,
|
|
||||||
longitude: -115.7,
|
|
||||||
coalition: "blue"
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
ret.time = Date.now();
|
|
||||||
res.send(JSON.stringify(ret));
|
|
||||||
};
|
|
||||||
|
|
||||||
bullseyes(req, res){
|
|
||||||
var ret = {bullseyes: {
|
|
||||||
"0": {
|
|
||||||
latitude: 37.25,
|
|
||||||
longitude: -115.8,
|
|
||||||
coalition: "neutral"
|
|
||||||
},
|
|
||||||
"1": {
|
|
||||||
latitude: 37.25,
|
|
||||||
longitude: -115.75,
|
|
||||||
coalition: "red"
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
latitude: 37.25,
|
|
||||||
longitude: -115.7,
|
|
||||||
coalition: "blue"
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
ret.time = Date.now();
|
|
||||||
res.send(JSON.stringify(ret));
|
|
||||||
};
|
|
||||||
|
|
||||||
mission(req, res){
|
|
||||||
var ret = {mission: {theatre: "Nevada"}};
|
|
||||||
ret.time = Date.now();
|
|
||||||
|
|
||||||
ret.mission.dateAndTime = {
|
|
||||||
time: Date.now(),
|
|
||||||
date: "",
|
|
||||||
elapsedTime: (Date.now() - this.startTime) / 1000,
|
|
||||||
startTime: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.mission.coalitions = {
|
|
||||||
red: [
|
|
||||||
'Russia',
|
|
||||||
'China'
|
|
||||||
],
|
|
||||||
blue: [
|
|
||||||
'United States',
|
|
||||||
'Great Britain'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.mission.commandModeOptions = {
|
|
||||||
restrictSpawns: false,
|
|
||||||
restrictToCoalition: true,
|
|
||||||
setupTime: 0,
|
|
||||||
spawnPoints: {
|
|
||||||
red: 1000,
|
|
||||||
blue: 400
|
|
||||||
},
|
|
||||||
eras: ["WW2", "Early Cold War", "Late Cold War", "Modern"]
|
|
||||||
}
|
|
||||||
|
|
||||||
var auth = req.get("Authorization");
|
|
||||||
if (auth) {
|
|
||||||
var username = atob(auth.replace("Basic ", "")).split(":")[0];
|
|
||||||
switch (username) {
|
|
||||||
case "admin":
|
|
||||||
ret.mission.commandModeOptions.commandMode = "Game master";
|
|
||||||
break
|
|
||||||
case "blue":
|
|
||||||
ret.mission.commandModeOptions.commandMode = "Blue commander";
|
|
||||||
break;
|
|
||||||
case "red":
|
|
||||||
ret.mission.commandModeOptions.commandMode = "Red commander";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.send(JSON.stringify(ret));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = DemoDataGenerator;
|
|
||||||
13738
client/package-lock.json
generated
13738
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
|||||||
copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet\\leaflet.css
|
|
||||||
copy .\\node_modules\\leaflet.nauticscale\\dist\\leaflet.nauticscale.js .\\public\\javascripts\\leaflet.nauticscale.js
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,565 +0,0 @@
|
|||||||
{
|
|
||||||
"AH-1W": {
|
|
||||||
"name": "AH-1W",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "AH-1W Cobra",
|
|
||||||
"shortLabel": "AH1",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "BGM-71 TOW",
|
|
||||||
"quantity": 8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Hydra-70 WP",
|
|
||||||
"quantity": 38
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "8xBGM-71, 38xHYDRA-70 WP",
|
|
||||||
"name": "TOW / Hydra"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Hydra-70",
|
|
||||||
"quantity": 76
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "76xHYDRA-70",
|
|
||||||
"name": "Hydra"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "ah-1.png"
|
|
||||||
},
|
|
||||||
"AH-64D_BLK_II": {
|
|
||||||
"name": "AH-64D_BLK_II",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "AH-64D Apache",
|
|
||||||
"shortLabel": "AH64",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "AGM-114k Hellfire",
|
|
||||||
"quantity": 8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "M151 Rocket Pod",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "2 * M261: M151 (6PD), 2 * Hellfire station: 4*AGM-114K",
|
|
||||||
"name": "Gun / ATGM / Rocket"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "AGM-114K Hellfire",
|
|
||||||
"quantity": 16
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "4 * Hellfire station: 4*AGM-114K",
|
|
||||||
"name": "Gun / ATGM"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "ah-64.png"
|
|
||||||
},
|
|
||||||
"Ka-50_3": {
|
|
||||||
"name": "Ka-50_3",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Ka-50 Hokum A",
|
|
||||||
"shortLabel": "K50",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Igla",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "4xIgla",
|
|
||||||
"name": "Gun / Fox 2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Igla",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "S-13",
|
|
||||||
"quantity": 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Kh-25ML",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Anti-Ship"
|
|
||||||
],
|
|
||||||
"code": "2xKh-25ML, 10xS-13, 4xIgla",
|
|
||||||
"name": "Gun / ASM / Rockets / Fox 2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Igla",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "S-80FP",
|
|
||||||
"quantity": 40
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Vikhr-M",
|
|
||||||
"quantity": 12
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "12x9A4172, 40xS-8OFP, 4xIgla",
|
|
||||||
"name": "Gun / ATGM / Rockets / Fox 2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Igla",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "S-80FP",
|
|
||||||
"quantity": 40
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Vikhr-M",
|
|
||||||
"quantity": 12
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "12x9A4172, 40xS-8OFP, 4xIgla",
|
|
||||||
"name": "Gun / ATGM"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Igla",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "FAB-500",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "S-13",
|
|
||||||
"quantity": 10
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "10xS-13, 2xFAB-500, 4xIgla",
|
|
||||||
"name": "Gun / Bombs / Rockets / Fox 2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "ka-50.png"
|
|
||||||
},
|
|
||||||
"Mi-24P": {
|
|
||||||
"name": "Mi-24P",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Mi-24P Hind",
|
|
||||||
"shortLabel": "Mi24",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "S-8KOM",
|
|
||||||
"quantity": 40
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "9M114 ATGM",
|
|
||||||
"quantity": 8
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "2xB8V20 (S-8KOM)+8xATGM 9M114",
|
|
||||||
"name": "Gun / ATGM / Rockets"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "S-24B",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "9M114 ATGM",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "4xS-24B+4xATGM 9M114",
|
|
||||||
"name": "Gun / ATGM / Rockets"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "GUV-1 Grenade Launcher",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "9M114 ATGM",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "4xGUV-1 AP30+4xATGM 9M114",
|
|
||||||
"name": "Gun / ATGM / Grenade Launcher"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mi-24.png"
|
|
||||||
},
|
|
||||||
"Mi-26": {
|
|
||||||
"name": "Mi-26",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Mi-26 Halo",
|
|
||||||
"shortLabel": "M26",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mi-26.png"
|
|
||||||
},
|
|
||||||
"Mi-28N": {
|
|
||||||
"name": "Mi-28N",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "Mi-28N Havoc",
|
|
||||||
"shortLabel": "M28",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "9M114 Shturm",
|
|
||||||
"quantity": 16
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "S-8",
|
|
||||||
"quantity": 40
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "16x9M114, 40xS-8",
|
|
||||||
"name": "ATGM / S-8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mi-28.png"
|
|
||||||
},
|
|
||||||
"Mi-8MT": {
|
|
||||||
"name": "Mi-8MT",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Mi-8MT Hip",
|
|
||||||
"shortLabel": "Mi8",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "UPK",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "B8",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "2 x UPK +2 x B8",
|
|
||||||
"name": "Rockets / Gunpods"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mi-8.png"
|
|
||||||
},
|
|
||||||
"SA342L": {
|
|
||||||
"name": "SA342L",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "SA342L Gazelle",
|
|
||||||
"shortLabel": "342",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "20mm Cannon",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SNEB68",
|
|
||||||
"quantity": 8
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Recon"
|
|
||||||
],
|
|
||||||
"code": "M621, 8xSNEB68 EAP",
|
|
||||||
"name": "Gun / ATGM / Rockets"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "sa-342.png"
|
|
||||||
},
|
|
||||||
"SA342M": {
|
|
||||||
"name": "SA342M",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "SA342M Gazelle",
|
|
||||||
"shortLabel": "342",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "HOT3",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "HOT3x4",
|
|
||||||
"name": "ATGM"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "sa-342.png"
|
|
||||||
},
|
|
||||||
"SA342Mistral": {
|
|
||||||
"name": "SA342Mistral",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "SA342Mistral Gazelle",
|
|
||||||
"shortLabel": "342",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Mistral",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "Mistral x 4",
|
|
||||||
"name": "Fox 2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "sa-342.png"
|
|
||||||
},
|
|
||||||
"SH-60B": {
|
|
||||||
"name": "SH-60B",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "SH-60B Seahawk",
|
|
||||||
"shortLabel": "S60",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "AGM-119 ASM",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "AGM-119",
|
|
||||||
"name": "ASM"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "uh-60.png"
|
|
||||||
},
|
|
||||||
"UH-1H": {
|
|
||||||
"name": "UH-1H",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "UH-1H Huey",
|
|
||||||
"shortLabel": "UH1",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "M134 Minigun",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "XM-158",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "M134 Minigun*2, XM158*2",
|
|
||||||
"name": "Miniguns / XM158"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "uh-1.png"
|
|
||||||
},
|
|
||||||
"UH-60A": {
|
|
||||||
"name": "UH-60A",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "UH-60A Blackhawk",
|
|
||||||
"shortLabel": "U60",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "uh-60.png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,767 +0,0 @@
|
|||||||
{
|
|
||||||
"An-26B": {
|
|
||||||
"name": "An-26B",
|
|
||||||
"coalition": "red",
|
|
||||||
"label": "An-26B Curl",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "26",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "an-26.png",
|
|
||||||
"cost": 0
|
|
||||||
},
|
|
||||||
"An-30M": {
|
|
||||||
"name": "An-30M",
|
|
||||||
"coalition": "red",
|
|
||||||
"label": "An-30M Clank",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "30",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "a-50.png",
|
|
||||||
"cost": 0
|
|
||||||
},
|
|
||||||
"C-130": {
|
|
||||||
"name": "C-130",
|
|
||||||
"label": "C-130 Hercules",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"shortLabel": "130",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "c-130.png",
|
|
||||||
"cost": 0
|
|
||||||
},
|
|
||||||
"F-14A-135-GR": {
|
|
||||||
"name": "F-14A-135-GR",
|
|
||||||
"coalition": "blue",
|
|
||||||
"label": "F-14A-135-GR Tomcat",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "14A",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "fuel",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-54A",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-7F",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-9L",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "AIM-54A-MK47*2, AIM-7F*1, AIM-9L*4, XT*2",
|
|
||||||
"name": "Heavy / Fox 3 / Long Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "fuel",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-7F",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-9L",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "AIM-7F*4, AIM-9L*4, XT*2",
|
|
||||||
"name": "Heavy / Fox 1 / Long Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "fuel",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-7M",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-9M",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "GBU-12",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "LANTIRN",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "AIM-7M*1, AIM-9M*2, XT*2, GBU-12*2, LANTIRN",
|
|
||||||
"name": "Heavy / Fox 3, GBU-12 / Long Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "f-14.png",
|
|
||||||
"cost": 300,
|
|
||||||
"liveryID": "IRIAF Asia Minor"
|
|
||||||
},
|
|
||||||
"F-4E": {
|
|
||||||
"name": "F-4E",
|
|
||||||
"coalition": "blue",
|
|
||||||
"label": "F-4E Phantom II",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "4",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "fuel",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-7M",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-9M",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "AIM-9*4,AIM-7*4,Fuel*2",
|
|
||||||
"name": "Heavy / Fox 1 / Long Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "ECM",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-7M",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Mk-82",
|
|
||||||
"quantity": 18
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "Mk-82*18,AIM-7*2,ECM",
|
|
||||||
"name": "Heavy / Fox 1, Mk-82 / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "f-4.png",
|
|
||||||
"cost": 100,
|
|
||||||
"liveryID": "IRIAF Asia Minor"
|
|
||||||
},
|
|
||||||
"F-5E-3": {
|
|
||||||
"name": "F-5E-3",
|
|
||||||
"coalition": "blue",
|
|
||||||
"label": "F-5E Tiger",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "5",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Fuel 275",
|
|
||||||
"quantity": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-9P5",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "AIM-9P5*2, Fuel 275*3",
|
|
||||||
"name": "Heavy / Fox 2 / Long Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Mk-82",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AIM-9P5",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Fuel 275",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "Mk-82LD*4,AIM-9P*2,Fuel 275",
|
|
||||||
"name": "Heavy / Fox 2 / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"liveryID": "ir iriaf 43rd tfs",
|
|
||||||
"filename": "f-5.png",
|
|
||||||
"cost": 80
|
|
||||||
},
|
|
||||||
"F-86F Sabre": {
|
|
||||||
"name": "F-86F Sabre",
|
|
||||||
"coalition": "blue",
|
|
||||||
"label": "F-86F Sabre",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"shortLabel": "86",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "120gal Fuel",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "120gal Fuel*2",
|
|
||||||
"name": "Light / Guns / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "HVAR",
|
|
||||||
"quantity": 16
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "HVAR*16",
|
|
||||||
"name": "Light / HVAR / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "AN-M64",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "AN-M64*2",
|
|
||||||
"name": "Light / AN-M64 / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Light / Guns / Short Range"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "f-86.png",
|
|
||||||
"cost": 40,
|
|
||||||
"liveryID": "iiaf bare metall"
|
|
||||||
},
|
|
||||||
"IL-76MD": {
|
|
||||||
"name": "IL-76MD",
|
|
||||||
"label": "IL-76MD Candid",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "76",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Default Transport"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "il-76.png",
|
|
||||||
"cost": 0
|
|
||||||
},
|
|
||||||
"MiG-15bis": {
|
|
||||||
"name": "MiG-15bis",
|
|
||||||
"coalition": "red",
|
|
||||||
"label": "MiG-15 Fagot",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"shortLabel": "M15",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "300L Fuel Tanks",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "2*300L",
|
|
||||||
"name": "Medium / Guns / Medium Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "FAB-100M",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "2*FAB-100M",
|
|
||||||
"name": "Medium / FAB-100M / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Light / Guns / Short Range"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mig-15.png",
|
|
||||||
"cost": 30,
|
|
||||||
"liveryID": "Iraqi_Camo"
|
|
||||||
},
|
|
||||||
"MiG-21Bis": {
|
|
||||||
"name": "MiG-21Bis",
|
|
||||||
"coalition": "red",
|
|
||||||
"label": "MiG-21 Fishbed",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "21",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "R-3 Atoll",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "R-60 Aphid",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "130 gal tanks",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ASO-2 Countermeasures",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "Patrol, short range",
|
|
||||||
"name": "Light / Fox-2 / Short range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "R-3 Atoll",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "R-60 Aphid",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "210 gal tanks",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ASO-2 Countermeasures",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "Patrol, medium range",
|
|
||||||
"name": "Medium / Fox-2 / Medium range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "R-3R Atoll",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "R-3S Atoll",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "210 gal tanks",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ASO-2 Countermeasures",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "Patrol, long range",
|
|
||||||
"name": "Medium / Fox-1, Fox-2 / Medium range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "GROM",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "FAB-250",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "210 gal tanks",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ASO-2 Countermeasures",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "Few big targets, GROM + BOMBS",
|
|
||||||
"name": "Heavy / GROM, FAB250 / Medium range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mig-21.png",
|
|
||||||
"cost": 100,
|
|
||||||
"liveryID": "iran - standard"
|
|
||||||
},
|
|
||||||
"MiG-23MLD": {
|
|
||||||
"name": "MiG-23MLD",
|
|
||||||
"coalition": "red",
|
|
||||||
"label": "MiG-23 Flogger",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "23",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Fuel-800",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "R-60M",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "R-24R",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "R-24R*2,R-60M*4,Fuel-800",
|
|
||||||
"name": "Heavy / Fox 1 / Long Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Fuel-800",
|
|
||||||
"quantity": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "FAB-500",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "R-60M",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "FAB-500*2,R-60M*2,Fuel-800",
|
|
||||||
"name": "Heavy / FAB-500 / Long Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mig-23.png",
|
|
||||||
"cost": 200
|
|
||||||
},
|
|
||||||
"Mirage-F1EE": {
|
|
||||||
"name": "Mirage-F1EE",
|
|
||||||
"coalition": "red",
|
|
||||||
"label": "Mirage-F1EE",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "F1EE",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "AIM-9JULI",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "R530EM",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "1137L Fuel Tank",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "2*AIM9-JULI, 2*R530EM, 1*Fuel Tank",
|
|
||||||
"name": "Medium / Fox 1 / Medium Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "AIM-9JULI",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SAMP 400 LD",
|
|
||||||
"quantity": 8
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "2*AIM-9JULI, 8*SAMP 400 LD",
|
|
||||||
"name": "Heavy / SAMP400 / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mig-25.png",
|
|
||||||
"cost": 150,
|
|
||||||
"liveryID": "iriaf 3-6215 _ 1990-2010s desert (eq variant)"
|
|
||||||
},
|
|
||||||
"Mirage-F1CE": {
|
|
||||||
"name": "Mirage-F1CE",
|
|
||||||
"coalition": "red",
|
|
||||||
"label": "Mirage-F1CE",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "F1CE",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "AIM-9JULI",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "R530IR",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "1137L Fuel Tank",
|
|
||||||
"quantity": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAP"
|
|
||||||
],
|
|
||||||
"code": "2*AIM9-JULI, 2*R530IR, 1*Fuel Tank",
|
|
||||||
"name": "Medium / Fox 2 / Medium Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "AIM-9JULI",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SAMP 400 LD",
|
|
||||||
"quantity": 8
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "2*AIM-9JULI, 8*SAMP 400 LD",
|
|
||||||
"name": "Heavy / SAMP400 / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mig-25.png",
|
|
||||||
"cost": 150,
|
|
||||||
"liveryID": "iraq air force (fictional eq version)"
|
|
||||||
},
|
|
||||||
"Su-24M": {
|
|
||||||
"name": "Su-24M",
|
|
||||||
"coalition": "red",
|
|
||||||
"label": "Su-24M Fencer",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"shortLabel": "24",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "R-60M",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "FAB-1500",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "FAB-1500*2,R-60M*2",
|
|
||||||
"name": "Heavy / FAB-500 / Short Range"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "su-24.png",
|
|
||||||
"cost": 250,
|
|
||||||
"liveryID": "iran air force"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
{
|
|
||||||
"BMP-1": {
|
|
||||||
"name": "BMP-1",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "BMP-1",
|
|
||||||
"shortLabel": "BMP-1",
|
|
||||||
"filename": "",
|
|
||||||
"type": "IFV",
|
|
||||||
"cost": 10,
|
|
||||||
"liveryID": "desert"
|
|
||||||
},
|
|
||||||
"Hawk SAM Battery": {
|
|
||||||
"name": "Hawk SAM Battery",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "Hawk SAM Battery",
|
|
||||||
"shortLabel": "Hawk SAM Battery",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": "",
|
|
||||||
"type": "SAM Site",
|
|
||||||
"cost": 500
|
|
||||||
},
|
|
||||||
"Infantry AK": {
|
|
||||||
"name": "Infantry AK",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Infantry AK",
|
|
||||||
"shortLabel": "Infantry AK",
|
|
||||||
"filename": "",
|
|
||||||
"type": "Infantry",
|
|
||||||
"cost": 1
|
|
||||||
},
|
|
||||||
"M-113": {
|
|
||||||
"name": "M-113",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "M-113",
|
|
||||||
"shortLabel": "M-113",
|
|
||||||
"filename": "",
|
|
||||||
"type": "APC",
|
|
||||||
"cost": 5
|
|
||||||
},
|
|
||||||
"M-60": {
|
|
||||||
"name": "M-60",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "M-60",
|
|
||||||
"shortLabel": "M-60",
|
|
||||||
"filename": "",
|
|
||||||
"type": "Tank",
|
|
||||||
"cost": 10
|
|
||||||
},
|
|
||||||
"SA-2 SAM Battery": {
|
|
||||||
"name": "SA-2 SAM Battery",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "SA-2 SAM Battery",
|
|
||||||
"shortLabel": "SA-2 SAM Battery",
|
|
||||||
"range": "Long",
|
|
||||||
"filename": "",
|
|
||||||
"type": "SAM Site",
|
|
||||||
"cost": 500
|
|
||||||
},
|
|
||||||
"T-55": {
|
|
||||||
"name": "T-55",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "T-55",
|
|
||||||
"shortLabel": "T-55",
|
|
||||||
"filename": "",
|
|
||||||
"type": "Tank",
|
|
||||||
"cost": 10,
|
|
||||||
"liveryID": "desert"
|
|
||||||
},
|
|
||||||
"T-72B": {
|
|
||||||
"name": "T-72B",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "T-72B",
|
|
||||||
"shortLabel": "T-72B",
|
|
||||||
"filename": "",
|
|
||||||
"type": "Tank",
|
|
||||||
"cost": 20,
|
|
||||||
"liveryID": "desert"
|
|
||||||
},
|
|
||||||
"ZSU-23-4 Shilka": {
|
|
||||||
"name": "ZSU-23-4 Shilka",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "ZSU-23-4 Shilka",
|
|
||||||
"shortLabel": "ZSU-23-4 Shilka",
|
|
||||||
"filename": "",
|
|
||||||
"type": "AAA",
|
|
||||||
"cost": 100
|
|
||||||
},
|
|
||||||
"Ural-375 ZU-23": {
|
|
||||||
"name": "Ural-375 ZU-23",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "Ural-375 ZU-23",
|
|
||||||
"shortLabel": "Ural-375 ZU-23",
|
|
||||||
"filename": "",
|
|
||||||
"type": "AAA",
|
|
||||||
"cost": 50
|
|
||||||
},
|
|
||||||
"SAU Gvozdika": {
|
|
||||||
"name": "SAU Gvozdika",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "SAU Gvozdika",
|
|
||||||
"shortLabel": "SAU Gvozdika",
|
|
||||||
"filename": "",
|
|
||||||
"type": "Gun Artillery",
|
|
||||||
"cost": 10,
|
|
||||||
"liveryID": "desert"
|
|
||||||
},
|
|
||||||
"Grad-URAL": {
|
|
||||||
"name": "Grad-URAL",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "BM-21",
|
|
||||||
"shortLabel": "BM-21",
|
|
||||||
"filename": "",
|
|
||||||
"type": "Rocket Artillery",
|
|
||||||
"cost": 10
|
|
||||||
},
|
|
||||||
"Chieftain_mk3": {
|
|
||||||
"name": "Chieftain_mk3",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "Chieftain Mk3",
|
|
||||||
"shortLabel": "Chieftain Mk3",
|
|
||||||
"filename": "",
|
|
||||||
"type": "Tank",
|
|
||||||
"cost": 20
|
|
||||||
},
|
|
||||||
"Scud_B": {
|
|
||||||
"name": "Scud_B",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "SCUD",
|
|
||||||
"shortLabel": "SCUD",
|
|
||||||
"filename": "",
|
|
||||||
"type": "Rocket Artillery",
|
|
||||||
"cost": 10
|
|
||||||
},
|
|
||||||
"tt_ZU-23": {
|
|
||||||
"name": "tt_ZU-23",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "Technical ZSU-23",
|
|
||||||
"shortLabel": "Technical ZSU-23",
|
|
||||||
"filename": "",
|
|
||||||
"type": "AAA",
|
|
||||||
"cost": 25
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
{
|
|
||||||
"Mi-24P": {
|
|
||||||
"name": "Mi-24P",
|
|
||||||
"coalition": "red",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Mi-24P Hind",
|
|
||||||
"shortLabel": "Mi24",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "S-8KOM",
|
|
||||||
"quantity": 40
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "9M114 ATGM",
|
|
||||||
"quantity": 8
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "2xB8V20 (S-8KOM)+8xATGM 9M114",
|
|
||||||
"name": "Gun / ATGM / Rockets"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "S-24B",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "9M114 ATGM",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"Strike"
|
|
||||||
],
|
|
||||||
"code": "4xS-24B+4xATGM 9M114",
|
|
||||||
"name": "Gun / ATGM / Rockets"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "GUV-1 Grenade Launcher",
|
|
||||||
"quantity": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "9M114 ATGM",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "4xGUV-1 AP30+4xATGM 9M114",
|
|
||||||
"name": "Gun / ATGM / Grenade Launcher"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mi-24.png",
|
|
||||||
"cost": 150,
|
|
||||||
"liveryID": "IQAF"
|
|
||||||
},
|
|
||||||
"Mi-8MT": {
|
|
||||||
"name": "Mi-8MT",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Mi-8MT Hip",
|
|
||||||
"shortLabel": "Mi8",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "UPK",
|
|
||||||
"quantity": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "B8",
|
|
||||||
"quantity": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "2 x UPK +2 x B8",
|
|
||||||
"name": "Rockets / Gunpods"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [],
|
|
||||||
"roles": [
|
|
||||||
"Transport"
|
|
||||||
],
|
|
||||||
"code": "",
|
|
||||||
"name": "Empty Loadout"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "mi-8.png",
|
|
||||||
"cost": 100,
|
|
||||||
"liveryID": "IR Iranian Special Police Forces"
|
|
||||||
},
|
|
||||||
"SA342M": {
|
|
||||||
"name": "SA342M",
|
|
||||||
"coalition": "blue",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "SA342M Gazelle",
|
|
||||||
"shortLabel": "342",
|
|
||||||
"loadouts": [
|
|
||||||
{
|
|
||||||
"fuel": 1,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "HOT3",
|
|
||||||
"quantity": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"roles": [
|
|
||||||
"CAS"
|
|
||||||
],
|
|
||||||
"code": "4x HOT3, IR Deflector, Sand Filter",
|
|
||||||
"name": "ATGM"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename": "sa-342.png",
|
|
||||||
"cost": 80
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,452 +0,0 @@
|
|||||||
{
|
|
||||||
"BDK-775": {
|
|
||||||
"name": "BDK-775",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Landing Craft",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "LS Ropucha",
|
|
||||||
"shortLabel": "LS Ropucha",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Boat Armed Hi-Speed": {
|
|
||||||
"name": "Boat Armed Hi-Speed",
|
|
||||||
"coalition": "",
|
|
||||||
"type": "Fast Attack Craft",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Boat Armed Hi-Speed",
|
|
||||||
"shortLabel": "Boat Armed Hi-Speed",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"CVN_71": {
|
|
||||||
"name": "CVN_71",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Super Aircraft Carrier",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "CVN-71 Theodore Roosevelt",
|
|
||||||
"shortLabel": "CVN-71",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"CVN_72": {
|
|
||||||
"name": "CVN_72",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Super Aircraft Carrier",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "CVN-72 Abraham Lincoln",
|
|
||||||
"shortLabel": "CVN-72",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"CVN_73": {
|
|
||||||
"name": "CVN_73",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Super Aircraft Carrier",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "CVN-73 George Washington",
|
|
||||||
"shortLabel": "CVN-73",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"CVN_75": {
|
|
||||||
"name": "CVN_75",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "CVN-75 Harry S. Truman",
|
|
||||||
"shortLabel": "CVN-75",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"CV_1143_5": {
|
|
||||||
"name": "CV_1143_5",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "CV Admiral Kuznetsov(2017)",
|
|
||||||
"shortLabel": "Admiral Kuznetsov(2017)",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"CV_59": {
|
|
||||||
"name": "CV_59",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "CV-59 Forrestal",
|
|
||||||
"shortLabel": "CV-59",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"CastleClass_01": {
|
|
||||||
"name": "CastleClass_01",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Patrol",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "HMS Leeds Castle (P-258)",
|
|
||||||
"shortLabel": "HMS Leeds Castle (P-258)",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"HandyWind": {
|
|
||||||
"name": "HandyWind",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Cargoship",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Bulker Handy Wind",
|
|
||||||
"shortLabel": "Bulker Handy Wind",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"HarborTug": {
|
|
||||||
"name": "HarborTug",
|
|
||||||
"coalition": "",
|
|
||||||
"type": "Tug",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Harbor Tug",
|
|
||||||
"shortLabel": "Harbor Tug",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"LHA_Tarawa": {
|
|
||||||
"name": "LHA_Tarawa",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "LHA-1 Tarawa",
|
|
||||||
"shortLabel": "LHA-1 Tarawa",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"La_Combattante_II": {
|
|
||||||
"name": "La_Combattante_II",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Fast Attack Craft",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "FAC La Combattante lla",
|
|
||||||
"shortLabel": "FAC La Combattante",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Seawise_Giant": {
|
|
||||||
"name": "Seawise_Giant",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Tanker",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Tanker Seawise Giant",
|
|
||||||
"shortLabel": "Seawise Giant",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Ship_Tilde_Supply": {
|
|
||||||
"name": "Ship_Tilde_Supply",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Transport",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Supply Ship MV Tilde",
|
|
||||||
"shortLabel": "Supply Ship Tilde",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Stennis": {
|
|
||||||
"name": "Stennis",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "CVN-74 John C. Stennis",
|
|
||||||
"shortLabel": "CVN-74",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"TICONDEROG": {
|
|
||||||
"name": "TICONDEROG",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Cruiser",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Ticonderoga",
|
|
||||||
"shortLabel": "Ticonderoga",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Type_052B": {
|
|
||||||
"name": "Type_052B",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Destroyer",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "052B DDG-168 Guangzhou",
|
|
||||||
"shortLabel": "Type 52B",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Type_052C": {
|
|
||||||
"name": "Type_052C",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Destroyer",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "052C DDG-171 Haikou",
|
|
||||||
"shortLabel": "Type 52C",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Type_054A": {
|
|
||||||
"name": "",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "054A FFG-538 Yantai",
|
|
||||||
"shortLabel": "Type 54A",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Type_071": {
|
|
||||||
"name": "Type_071",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Transport",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "Type 071",
|
|
||||||
"shortLabel": "Type 071",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"Type_093": {
|
|
||||||
"name": "Type_093",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Submarine",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "Type 093",
|
|
||||||
"shortLabel": "Type 093",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"USS_Arleigh_Burke_IIa": {
|
|
||||||
"name": "USS_Arleigh_Burke_IIa",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Destroyer",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "DDG Arleigh Burke lla",
|
|
||||||
"shortLabel": "DDG Arleigh Burke",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"albatros": {
|
|
||||||
"name": "albatros",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "Albatros (Grisha-5)",
|
|
||||||
"shortLabel": "Albatros",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"ara_vdm": {
|
|
||||||
"name": "ara_vdm",
|
|
||||||
"coalition": "",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "ARA Vienticinco de Mayo",
|
|
||||||
"shortLabel": "ARA Vienticinco de Mayo",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"barge-1": {
|
|
||||||
"name": "barge-1",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Cargoship",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Dry cargo ship Ivanov",
|
|
||||||
"shortLabel": "Dry cargo ship Ivanov",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"barge-2": {
|
|
||||||
"name": "barge-2",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Cargoship",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Dry cargo ship Yakushev",
|
|
||||||
"shortLabel": "Dry cargo ship Yakushev",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"elnya": {
|
|
||||||
"name": "elnya",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Tanker",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Elnya tanker",
|
|
||||||
"shortLabel": "Elnya tanker",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"hms_invincible": {
|
|
||||||
"name": "hms_invincible",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "HMS Invincible (R05)",
|
|
||||||
"shortLabel": "HMS Invincible",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"kilo": {
|
|
||||||
"name": "kilo",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Submarine",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Project 636 Varshavyanka Basic",
|
|
||||||
"shortLabel": "Varshavyanka Basic",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"kilo_636": {
|
|
||||||
"name": "kilo_636",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Submarine",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Project 636 Varshavyanka Improved",
|
|
||||||
"shortLabel": "Varshavyanka Improved",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"kuznecow": {
|
|
||||||
"name": "kuznecow",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Aircraft Carrier",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Admiral Kuznetsov",
|
|
||||||
"shortLabel": "Admiral Kuznetsov",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"leander-gun-achilles": {
|
|
||||||
"name": "leander-gun-achilles",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "HMS Achilles (F12)",
|
|
||||||
"shortLabel": "HMS Achilles",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"leander-gun-andromeda": {
|
|
||||||
"name": "leander-gun-andromeda",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "HMS Andromeda (F57)",
|
|
||||||
"shortLabel": "HMS Andromeda",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"leander-gun-ariadne": {
|
|
||||||
"name": "leander-gun-ariadne",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "HMS Ariadne (F72)",
|
|
||||||
"shortLabel": "HMS Ariadne",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"leander-gun-condell": {
|
|
||||||
"name": "leander-gun-condell",
|
|
||||||
"coalition": "",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Almirante Condell PFG-06",
|
|
||||||
"shortLabel": "Almirante Condell",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"leander-gun-lynch": {
|
|
||||||
"name": "leander-gun-lynch",
|
|
||||||
"coalition": "",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "CNS Almirante Lynch (PFG-07)",
|
|
||||||
"shortLabel": "CNS Almirante Lynch",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"molniya": {
|
|
||||||
"name": "molniya",
|
|
||||||
"coalition": "",
|
|
||||||
"type": "Fast Attack Craft",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Molniya (Tarantul-3)",
|
|
||||||
"shortLabel": "Molniya",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"moscow": {
|
|
||||||
"name": "moscow",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Cruiser",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Moscow",
|
|
||||||
"shortLabel": "Moscow",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"neustrash": {
|
|
||||||
"name": "neustrash",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Neustrashimy",
|
|
||||||
"shortLabel": "Neustrashimy",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"perry": {
|
|
||||||
"name": "perry",
|
|
||||||
"coalition": "blue",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Mid Cold War",
|
|
||||||
"label": "Oliver H. Perry",
|
|
||||||
"shortLabel": "Oliver H. Perry",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"piotr_velikiy": {
|
|
||||||
"name": "piotr_velikiy",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Cruiser",
|
|
||||||
"era": "Late Cold War",
|
|
||||||
"label": "Pyotr Velikiy",
|
|
||||||
"shortLabel": "Pyotr Velikiy",
|
|
||||||
"range": "Medium",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"rezky": {
|
|
||||||
"name": "Rezky (Krivak-2)",
|
|
||||||
"coalition": "red",
|
|
||||||
"type": "Frigate",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "Rezky (Krivak-2)",
|
|
||||||
"shortLabel": "Rezky",
|
|
||||||
"range": "Short",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"santafe": {
|
|
||||||
"name": "santafe",
|
|
||||||
"coalition": "",
|
|
||||||
"type": "Submarine",
|
|
||||||
"era": "Early Cold War",
|
|
||||||
"label": "ARA Santa Fe S-21",
|
|
||||||
"shortLabel": "ARA Santa",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
},
|
|
||||||
"zwezdny": {
|
|
||||||
"name": "zwezdny",
|
|
||||||
"coalition": "",
|
|
||||||
"type": "Civilian Boat",
|
|
||||||
"era": "Modern",
|
|
||||||
"label": "Zwezdny",
|
|
||||||
"shortLabel": "Zwezdny",
|
|
||||||
"range": "",
|
|
||||||
"filename": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
{
|
|
||||||
"RED": "AGGRESSORS",
|
|
||||||
"INS": "INSURGENTS",
|
|
||||||
"DZ" : "ALGERIA",
|
|
||||||
"AR" : "ARGENTINA",
|
|
||||||
"AU" : "AUSTRALIA",
|
|
||||||
"AT" : "AUSTRIA",
|
|
||||||
"BH" : "BAHRAIN",
|
|
||||||
"BY" : "BELARUS",
|
|
||||||
"BE" : "BELGIUM",
|
|
||||||
"BO" : "BOLIVIA",
|
|
||||||
"BR" : "BRAZIL",
|
|
||||||
"BG" : "BULGARIA",
|
|
||||||
"CA" : "CANADA",
|
|
||||||
"CL" : "CHILE",
|
|
||||||
"CN" : "CHINA",
|
|
||||||
"HR" : "CROATIA",
|
|
||||||
"CU" : "CUBA",
|
|
||||||
"CY" : "CYPRUS",
|
|
||||||
"CZ" : "CHEZH_REPUBLIC",
|
|
||||||
"DK" : "DENMARK",
|
|
||||||
"EG" : "EGYPT",
|
|
||||||
"ET" : "ETHIOPIA",
|
|
||||||
"FI" : "FINLAND",
|
|
||||||
"FR" : "FRANCE",
|
|
||||||
"GE" : "GEORGIA",
|
|
||||||
"DE" : "GERMANY",
|
|
||||||
"GH" : "GHANA",
|
|
||||||
"GI" : "Gibraltar",
|
|
||||||
"GR" : "GREECE",
|
|
||||||
"HN" : "HONDURAS",
|
|
||||||
"HU" : "HUNGARY",
|
|
||||||
"IS" : "Iceland",
|
|
||||||
"IN" : "INDIA",
|
|
||||||
"ID" : "INDONESIA",
|
|
||||||
"IR" : "IRAN",
|
|
||||||
"IQ" : "IRAQ",
|
|
||||||
"IE" : "Ireland",
|
|
||||||
"IM" : "Isle Of Man",
|
|
||||||
"IL" : "ISRAEL",
|
|
||||||
"IT" : "ITALY",
|
|
||||||
"JP" : "JAPAN",
|
|
||||||
"JO" : "JORDAN",
|
|
||||||
"KZ" : "KAZAKHSTAN",
|
|
||||||
"KR" : "SOUTH_KOREA",
|
|
||||||
"KW" : "KUWAIT",
|
|
||||||
"LB" : "LEBANON",
|
|
||||||
"LY" : "LIBYIA",
|
|
||||||
"MY" : "MALAYSIA",
|
|
||||||
"MX" : "MEXICO",
|
|
||||||
"MA" : "MOROCCO",
|
|
||||||
"NL" : "THE_NETHERLANDS",
|
|
||||||
"NG" : "NIGERIA",
|
|
||||||
"NO" : "NORWAY",
|
|
||||||
"OM" : "OMAN",
|
|
||||||
"PK" : "PAKISTAN",
|
|
||||||
"PE" : "PERU",
|
|
||||||
"PH" : "PHILIPPINES",
|
|
||||||
"PL" : "POLAND",
|
|
||||||
"PT" : "PORTUGAL",
|
|
||||||
"QA" : "QATAR",
|
|
||||||
"RO" : "ROMANIA",
|
|
||||||
"RU" : "RUSSIA",
|
|
||||||
"SA" : "SAUDI ARABIA",
|
|
||||||
"RS" : "SERBIA",
|
|
||||||
"SK" : "SLOVAKIA",
|
|
||||||
"SI" : "SLOVENIA",
|
|
||||||
"ZA" : "SOUTH AFRICA",
|
|
||||||
"ES" : "SPAIN",
|
|
||||||
"SD" : "SUDAN",
|
|
||||||
"SE" : "SWEDEN",
|
|
||||||
"CH" : "SWITZERLAND",
|
|
||||||
"SY" : "SYRIA",
|
|
||||||
"TH" : "THAILAND",
|
|
||||||
"TN" : "TUNISIA",
|
|
||||||
"TR" : "TURKEY",
|
|
||||||
"UA" : "UKRAINE",
|
|
||||||
"AE" : "UNITED ARAB EMIRATES",
|
|
||||||
"GB" : "UK",
|
|
||||||
"US" : "USA",
|
|
||||||
"VE" : "VENEZUELA",
|
|
||||||
"VN" : "VIETNAM",
|
|
||||||
"YE" : "YEMEN"
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,38 +0,0 @@
|
|||||||
L.Control.ScaleNautic = L.Control.Scale.extend({
|
|
||||||
options: {
|
|
||||||
nautic: false
|
|
||||||
},
|
|
||||||
|
|
||||||
_addScales: function(options, className, container) {
|
|
||||||
L.Control.Scale.prototype._addScales.call(this, options, className, container);
|
|
||||||
L.setOptions(options);
|
|
||||||
if (this.options.nautic) {
|
|
||||||
this._nScale = L.DomUtil.create('div', className, container);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateScales: function (maxMeters) {
|
|
||||||
L.Control.Scale.prototype._updateScales.call(this, maxMeters);
|
|
||||||
if (this.options.nautic && maxMeters) {
|
|
||||||
this._updateNautic(maxMeters);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateNautic: function (maxMeters) {
|
|
||||||
var scale = this._nScale,
|
|
||||||
maxNauticalMiles = maxMeters / 1852, nauticalMiles;
|
|
||||||
|
|
||||||
if(maxMeters >= 1852) {
|
|
||||||
nauticalMiles = L.Control.Scale.prototype._getRoundNum.call(this, maxNauticalMiles);
|
|
||||||
} else {
|
|
||||||
nauticalMiles = maxNauticalMiles > 0.1 ? Math.round(maxNauticalMiles * 10) / 10 : Math.round(maxNauticalMiles * 100) / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
scale.style.width = Math.round(this.options.maxWidth * (nauticalMiles / maxNauticalMiles)) - 10 + 'px';
|
|
||||||
scale.innerHTML = nauticalMiles + ' nm';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
L.control.scalenautic = function (options) {
|
|
||||||
return new L.Control.ScaleNautic(options);
|
|
||||||
};
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
/**************************************/
|
|
||||||
|
|
||||||
.olympus-dialog {
|
|
||||||
align-self: center;
|
|
||||||
background:white;
|
|
||||||
border-radius: 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-self: center;
|
|
||||||
padding:10px;
|
|
||||||
position:absolute;
|
|
||||||
width:fit-content;
|
|
||||||
z-index: 9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.olympus-dialog-close {
|
|
||||||
cursor:pointer;
|
|
||||||
position:absolute;
|
|
||||||
right:10px;
|
|
||||||
top:5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.olympus-dialog-header {
|
|
||||||
font-weight:bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/***** AIC *****/
|
|
||||||
|
|
||||||
.aic-panel {
|
|
||||||
z-index: 9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-control-panel {
|
|
||||||
bottom:30px;
|
|
||||||
position: absolute;
|
|
||||||
left:30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#aic-control-panel .olympus-button img {
|
|
||||||
max-width: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#aic-toolbox, #aic-callsign-panel {
|
|
||||||
align-items: flex-start;
|
|
||||||
align-self: center;
|
|
||||||
flex-direction: column;
|
|
||||||
row-gap: 10px;
|
|
||||||
display:none;
|
|
||||||
position:absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aic-panel {
|
|
||||||
background:#eaeaea;
|
|
||||||
border-bottom-right-radius: 10px;
|
|
||||||
border-top-right-radius: 10px;
|
|
||||||
justify-self: left;
|
|
||||||
padding:5px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aic-enabled #aic-toolbox, .aic-enabled #aic-callsign-panel {
|
|
||||||
display:flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aic-enabled #aic-callsign-panel {
|
|
||||||
align-self: auto;
|
|
||||||
top: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aic-panel h2 {
|
|
||||||
font-size:90%;
|
|
||||||
margin:0;
|
|
||||||
padding:0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-callsign-display {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-formation-list {
|
|
||||||
display:flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-formation-list > div {
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display:flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top:10px;
|
|
||||||
position:relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-formation-list .aic-formation-image img {
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 10px;
|
|
||||||
max-width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-formation-list .aic-formation-name {
|
|
||||||
font-size:90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-formation-list .aic-formation-descriptor {
|
|
||||||
background:white;
|
|
||||||
border-radius: 10px;
|
|
||||||
left:100px;
|
|
||||||
padding:5px;
|
|
||||||
position:absolute;
|
|
||||||
width: max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-teleprompt {
|
|
||||||
background-color: white;
|
|
||||||
border:2px solid black;
|
|
||||||
border-radius: 10px;
|
|
||||||
bottom: 50px;
|
|
||||||
color: black;
|
|
||||||
display: none;
|
|
||||||
justify-content: center;
|
|
||||||
justify-self: center;
|
|
||||||
padding: 10px;
|
|
||||||
position: absolute;
|
|
||||||
width: fit-content;
|
|
||||||
z-index: 9999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aic-enabled #aic-teleprompt {
|
|
||||||
display:flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor {
|
|
||||||
display:flex;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-section {
|
|
||||||
display:flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin:0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-section-label {
|
|
||||||
background-color:#eaeaea;
|
|
||||||
border-top-left-radius: 10px;
|
|
||||||
border-top-right-radius: 10px;
|
|
||||||
padding:.25em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-phrase {
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
display:flex;
|
|
||||||
flex-direction: row;
|
|
||||||
margin-bottom:5px;
|
|
||||||
padding-bottom:2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-phrase:last-of-type {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-components .aic-descriptor-component {
|
|
||||||
margin:0 5px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-component-label {
|
|
||||||
display:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-component-value:after {
|
|
||||||
content:",";
|
|
||||||
margin-right:5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-component:last-of-type .aic-descriptor-component-value:after {
|
|
||||||
content:"; ";
|
|
||||||
}
|
|
||||||
|
|
||||||
#aic-descriptor .aic-descriptor-section:last-of-type .aic-descriptor-component:last-of-type .aic-descriptor-component-value:after {
|
|
||||||
content:".";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user