mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-07-18 10:34:03 +00:00
Compare commits
1825 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e76c26ff59 | |||
| cb11de6f9c | |||
| cdd78e5163 | |||
| a8da02774a | |||
| 04258a69c4 | |||
| 49882f03d9 | |||
| a7857670d3 | |||
| c41b256775 | |||
| e2929a78c4 | |||
| 15bf379cdc | |||
| 8a8e40e810 | |||
| 2c8adf58cb | |||
| bb579fff5b | |||
| 1ad538ea9f | |||
| 191f7a7377 | |||
| 77d2804fce | |||
| 63ba50a83a | |||
| fb8f804af2 | |||
| ffbab7453c | |||
| 10872918bb | |||
| 8979097fd7 | |||
| 71b2cc1ee5 | |||
| 389d5c7e5b | |||
| 178005346d | |||
| 041c21a883 | |||
| fd946e971a | |||
| 0dab316514 | |||
| 248228720e | |||
| e9c1b6d268 | |||
| 08be2d6e93 | |||
| ac386d5ebe | |||
| 74c1e9d991 | |||
| 0e72717cdb | |||
| 1df525b9c5 | |||
| cdbbad809a | |||
| 970275e96e | |||
| 5456cd04c3 | |||
| 1cdbe55cdd | |||
| 0577e5171b | |||
| 97376320f4 | |||
| 9c1acc731a | |||
| 92f81614ba | |||
| 2a11c4c98a | |||
| e284773492 | |||
| b3d46618c2 | |||
| 4e36e2011f | |||
| a3876c296e | |||
| c80213b4cf | |||
| bfe7bf1af5 | |||
| f28d92e865 | |||
| bffb3e7778 | |||
| d4c2de9dd1 | |||
| ab5425bd83 | |||
| aec3eee3a5 | |||
| eec7e5f8d9 | |||
| a9b51cca93 | |||
| 14ddba69b0 | |||
| a7806deb76 | |||
| 0cf35b664f | |||
| c3ffffbb52 | |||
| d96a55d83c | |||
| 83353d710d | |||
| 9a4c09d249 | |||
| c825191556 | |||
| 27e85e921f | |||
| c120a48879 | |||
| 4a03074571 | |||
| 8855b117a8 | |||
| 2cedb5e996 | |||
| 0af68cd780 | |||
| 6a58748cd1 | |||
| d31db1351a | |||
| 0f33603ecc | |||
| 3bbd55cfc2 | |||
| 163273096c | |||
| 6d1030925c | |||
| dabe8a58d1 | |||
| 16cf6693ab | |||
| fd51ec6932 | |||
| 7a16a5dda8 | |||
| 1b6648996c | |||
| f45a22fe78 | |||
| 4314959cbb | |||
| fad85ef7ed | |||
| 569b3df6af | |||
| 910da86caf | |||
| 73ff2c576d | |||
| d5ffb48548 | |||
| 8ce371f898 | |||
| 6f02f23240 | |||
| 0a1d469c68 | |||
| 823f8fb4fb | |||
| f7e64bc9b5 | |||
| 261f79851c | |||
| 6773ac7841 | |||
| 39f29b066b | |||
| 246879c003 | |||
| 709621967d | |||
| 0c376aec63 | |||
| 725efc3e70 | |||
| 81abe422de | |||
| fb202012da | |||
| 89223ae142 | |||
| 2967de8f6e | |||
| 9c5260f801 | |||
| 4d9ce80c98 | |||
| ee055531b6 | |||
| c9b90e884d | |||
| 21db80afad | |||
| d9d5458450 | |||
| 0575b366dd | |||
| 034b2444ff | |||
| 7901d53d54 | |||
| 88f34e5bb0 | |||
| 49f3e3fc2f | |||
| cae084a352 | |||
| 6d07f7c48c | |||
| 014fea5f10 | |||
| d07709a167 | |||
| ac4db4a392 | |||
| b30cdd073b | |||
| a12e93c7cb | |||
| bd01946f88 | |||
| 8d25bdec7c | |||
| 8da228c9a2 | |||
| 74abcce956 | |||
| 2032c2cfbf | |||
| fb070a0c86 | |||
| 817c69bb11 | |||
| 6cd56e4de4 | |||
| 19a4ec48bb | |||
| c7d990850a | |||
| 885d3b5228 | |||
| 7379b8135a | |||
| 549c9b9ce5 | |||
| f4080d93e8 | |||
| 94b74b7056 | |||
| 6886107934 | |||
| f65783ed6c | |||
| d8e765a9b1 | |||
| 526f241dc3 | |||
| dffb1c0768 | |||
| f30f32732c | |||
| 9cd3027ea6 | |||
| b4c7b63381 | |||
| 0782532763 | |||
| 6fa9e5894e | |||
| c0bc9b393c | |||
| a97e844aca | |||
| d2e91ffcd2 | |||
| d9eee7ea46 | |||
| b1e233421e | |||
| 7157836eb1 | |||
| 53fa850d66 | |||
| 033c52ae54 | |||
| e08b44187e | |||
| 0d29c39724 | |||
| 6946d8d185 | |||
| 6ac1d66aae | |||
| a67bae4f0d | |||
| 4e7c689f7a | |||
| f73ff10edb | |||
| 949e2f9ff3 | |||
| cb9ab26522 | |||
| 7aa4aaf371 | |||
| 901480d99c | |||
| 84dbda6f2b | |||
| 9d00ec0c25 | |||
| 0d08d732a5 | |||
| 8c0f960e39 | |||
| b0978b362e | |||
| ffef3183c7 | |||
| 20a9857fcf | |||
| 828395c398 | |||
| 462e29da6e | |||
| 29ebe94015 | |||
| ce7b30b54e | |||
| feeb0c01f2 | |||
| bef8e53347 | |||
| 46c3ed72c3 | |||
| 1fd8f4d837 | |||
| 6f3fbb25cf | |||
| 05b8df0d88 | |||
| a4dcb643bd | |||
| 9e23cda02a | |||
| c29b67df55 | |||
| bd312b86d2 | |||
| 822b95e8aa | |||
| a7e45338e3 | |||
| 7637f0c6ce | |||
| 6ec43b72ce | |||
| 91e80bf1a6 | |||
| e6464dc5cb | |||
| 34c799b668 | |||
| dbd7634f0e | |||
| baa1dcbf8f | |||
| 660ebeadfe | |||
| ef0ddddb46 | |||
| 77a39364f4 | |||
| dc0a2bccd6 | |||
| ac1b458eb4 | |||
| f5938bc235 | |||
| 7280c17506 | |||
| 4e280f02b6 | |||
| 854f6ae6ae | |||
| 0487487e7c | |||
| 9ec66912c8 | |||
| 960f261ddd | |||
| e55f96f393 | |||
| 713a5b067f | |||
| d6aa7ec17c | |||
| 2da2ddb5bb | |||
| 608033f38f | |||
| 28c25816a6 | |||
| 709fccd96c | |||
| 2c24e56aa5 | |||
| f104ddbe64 | |||
| bbd8ceb8c0 | |||
| b8498fa58f | |||
| 34c26c44bc | |||
| c97f1791b0 | |||
| 63b16e5bd4 | |||
| 184f93168b | |||
| 0400f1a23e | |||
| d3d60757c1 | |||
| 57079e5104 | |||
| 6d967358da | |||
| 095121d83c | |||
| a415b131c4 | |||
| 54a1ea9f56 | |||
| 23091ff851 | |||
| 5571b49b4f | |||
| 4b4708e2a8 | |||
| 789a4c4b7f | |||
| 3775053609 | |||
| 35da50b67a | |||
| 9be30338a5 | |||
| 6510cca837 | |||
| 08b8dfbe0e | |||
| 9af242854a | |||
| bfe9a1888e | |||
| fec496f154 | |||
| 28fd35ad7e | |||
| c5deb09c2c | |||
| ee6d34a9bd | |||
| 6e6bb1e88d | |||
| 0b3aea2bf3 | |||
| f731ec7b2f | |||
| 5b8f840d6e | |||
| 694ad5d33d | |||
| 383ee00e71 | |||
| c279ab6311 | |||
| 4cc1db1365 | |||
| f3d1378692 | |||
| cfb3004142 | |||
| 016643e494 | |||
| 5ec18d45a2 | |||
| f4c9bced45 | |||
| e106ca3da5 | |||
| 262c8ffc59 | |||
| affde2f030 | |||
| a4982bd24e | |||
| 1099e8e876 | |||
| 6a4356fa94 | |||
| 2ec8d94e38 | |||
| 24d47ef353 | |||
| 76ebf8df07 | |||
| a4e52c6c3c | |||
| 285f8d102b | |||
| d0d21a6b5d | |||
| ff58a47244 | |||
| 6e666b0ac8 | |||
| 47684e8717 | |||
| 0d0292385f | |||
| 83e20f8062 | |||
| 5943ae0a46 | |||
| 56c4a11626 | |||
| f0f42df374 | |||
| 5898bc7f07 | |||
| 0d8b94c7fd | |||
| 0fa4be7c4a | |||
| a7bad8e9f4 | |||
| 40276d190a | |||
| 71ccd23953 | |||
| 4e68e33ec7 | |||
| 79c8b31042 | |||
| cee72c1d09 | |||
| a7c8954740 | |||
| a21b9b382e | |||
| ef0b76a632 | |||
| 2806d3a191 | |||
| 9688c7ef01 | |||
| d6181d26f8 | |||
| aa5e8662ed | |||
| ca11e724ab | |||
| ab272da46e | |||
| 584e932769 | |||
| 691a500381 | |||
| 21a2df0830 | |||
| 4773a83a24 | |||
| 09e9377e54 | |||
| 19a90b7d9d | |||
| dbaed1e97b | |||
| 9695789843 | |||
| 75ddd2e1e0 | |||
| 43c81afd12 | |||
| 88a837b769 | |||
| 55656761d2 | |||
| 92710f4625 | |||
| 58dc353bcd | |||
| b194985827 | |||
| bdd283956c | |||
| a9b0017c04 | |||
| 8f185d1291 | |||
| 9564d9d893 | |||
| fe01c6196e | |||
| c8d9377dbb | |||
| d53f01232d | |||
| e3f9a27f87 | |||
| e25b9155b4 | |||
| b769568df1 | |||
| daa60ac501 | |||
| 0340d17ab8 | |||
| c33f637717 | |||
| 334af52ddf | |||
| 9a949c02c5 | |||
| 095c36b3ba | |||
| ff7ebb4f92 | |||
| 3834991e6a | |||
| 67af073b95 | |||
| 5a44948050 | |||
| 3011d625b2 | |||
| d25efe2293 | |||
| 8202791518 | |||
| 9871bf82d3 | |||
| f9c1d62173 | |||
| 89d854f5be | |||
| f1e0bacadb | |||
| 1b0131bd9d | |||
| 2f6cd20cbd | |||
| d66d99a24e | |||
| 9e823f12c2 | |||
| ef5ea01bc1 | |||
| 30e6542887 | |||
| b501eec306 | |||
| 79e99dcb38 | |||
| f6eccba966 | |||
| fa1f67420d | |||
| 6e26e7eac3 | |||
| 0a04ff4f3c | |||
| 99023a3053 | |||
| a3fd583d9d | |||
| a6e7ea6590 | |||
| 178e4ceb7f | |||
| e12455d154 | |||
| 71d5983adf | |||
| 696569f749 | |||
| 4892a58084 | |||
| 75d8d55691 | |||
| 614cfcd7f7 | |||
| 8eef039312 | |||
| f6a88db46b | |||
| 9c5847153a | |||
| cdfb47448f | |||
| 0adca414ce | |||
| 16bfbabf19 | |||
| 539dfd6a38 | |||
| 525666be7c | |||
| 386171bcab | |||
| 55383575e0 | |||
| 9659bfa553 | |||
| 85504fbe62 | |||
| de8dcc4024 | |||
| 620c8eaa27 | |||
| 3f296554ed | |||
| 2a8d166c54 | |||
| 6bc263bd2b | |||
| 907d62c4e7 | |||
| 6965d319ef | |||
| d674f55343 | |||
| 75bc95167f | |||
| 66bf32351a | |||
| fe9a5aea2a | |||
| b99d963cd5 | |||
| b8398af5a3 | |||
| 10d8af2536 | |||
| e79941bb8b | |||
| 4124b6d084 | |||
| ae9c258531 | |||
| df17a3d2a3 | |||
| b47737bda3 | |||
| 96bb475306 | |||
| 7490796637 | |||
| a9f2df83ff | |||
| 50aca57112 | |||
| 5011269586 | |||
| bd42032e3a | |||
| 1256cc3bd1 | |||
| 62122a15bc | |||
| f86db5f134 | |||
| 2acb841539 | |||
| 6724bb8edd | |||
| 7b5b5e0bd2 | |||
| 243ac3027f | |||
| 79a4af44d3 | |||
| 180a0b39d1 | |||
| 2664c36a14 | |||
| 911f4523a1 | |||
| 09b86d6fdf | |||
| 5ec8a4674c | |||
| 2a567c9f74 | |||
| b9a7fc9409 | |||
| 0db13b6cdf | |||
| 08c7409627 | |||
| c38cb046cd | |||
| 037b168825 | |||
| 41a928b775 | |||
| 27598406d1 | |||
| a0ad5292b9 | |||
| a1a258f48e | |||
| 4a0040a12f | |||
| ab13b5f198 | |||
| 788d2d49b9 | |||
| 6c342ef910 | |||
| a4b5362347 | |||
| 0e78be86e4 | |||
| e348bbc344 | |||
| bad17c39d1 | |||
| 8ed30da473 | |||
| af1083d0f1 | |||
| 4fff842c90 | |||
| 7f81039f46 | |||
| b63be6dd28 | |||
| 565a5294e2 | |||
| 254d43fef1 | |||
| 5819884c98 | |||
| cb43f9c392 | |||
| ed677b7682 | |||
| ead8411454 | |||
| 1fc9f13919 | |||
| 6bf077e0aa | |||
| 0de8c0beb2 | |||
| 39f690f2b4 | |||
| 1a575d9364 | |||
| fe58253a44 | |||
| 65cc72e28b | |||
| 00f8fccfae | |||
| 1fea016ac1 | |||
| 35057b9d05 | |||
| b2fdcd5cf0 | |||
| 2b3363de40 | |||
| d031651b58 | |||
| 8fb66ed329 | |||
| e841a38866 | |||
| addb7ba36a | |||
| d4b5e24364 | |||
| dd32d2e53c | |||
| cc1e071e35 | |||
| 3f8efae23f | |||
| 8ee8898a78 | |||
| fc77df4b5d | |||
| 13018ed96a | |||
| 236e7afcfc | |||
| 946a1de931 | |||
| 2840865b83 | |||
| 1411309204 | |||
| 60927e6728 | |||
| 4b11a6a304 | |||
| 37a00f25bc | |||
| 1fc541a9df | |||
| c3cd732254 | |||
| 8f7694111b | |||
| 2854a2d93e | |||
| 78c209a96f | |||
| 9809f08954 | |||
| 4e671ce995 | |||
| b5fd737cea | |||
| 6f82fd7eb6 | |||
| 542fe20782 | |||
| 92591432d3 | |||
| a20cdac9c3 | |||
| 23f45359f8 | |||
| 0bc09548cf | |||
| ee30ab48ae | |||
| 3028a384a4 | |||
| f17db43501 | |||
| 7dd46ec24f | |||
| cefb5d98f0 | |||
| e750a99636 | |||
| 798684e300 | |||
| 7c004ee37c | |||
| 0a4bc23fb8 | |||
| 13a5146010 | |||
| 55fe3630c5 | |||
| 265196398a | |||
| 141d00e160 | |||
| 5c8d90f50e | |||
| 351a2463a2 | |||
| f604f0f913 | |||
| 7afe76212d | |||
| a777b40613 | |||
| 11ef7c6a00 | |||
| b5bc881d52 | |||
| 66d5ba9981 | |||
| eecef9a0aa | |||
| 7e6aa20168 | |||
| 69a80a6c38 | |||
| d63ab1138c | |||
| f790c4fb9e | |||
| 40427c75b9 | |||
| e18a5e4832 | |||
| 4d2a58e428 | |||
| 005d6d2b06 | |||
| 7ada57033a | |||
| 1a332ae6ab | |||
| 064e082a12 | |||
| 10eec8a47b | |||
| db469d1b84 | |||
| 1e04aaa77d | |||
| e97753125d | |||
| 1474ff9b88 | |||
| 39bb95f127 | |||
| 42baf6c8d2 | |||
| 73b9552b5c | |||
| 60cf7506f8 | |||
| 894062c757 | |||
| 165a5d7364 | |||
| 405e66ea72 | |||
| a42ff85406 | |||
| 2eba68b35c | |||
| efe7673c4c | |||
| ca92d7d569 | |||
| 0ee2baadce | |||
| 43856341e6 | |||
| 61aed403d9 | |||
| a8a92c00fe | |||
| 84c41aa554 | |||
| de415384f3 | |||
| 8a9ee747c1 | |||
| 2eeb918c8a | |||
| 72aa596317 | |||
| 6de3a45a51 | |||
| 28a826b35d | |||
| 41813dcc53 | |||
| 6290409e54 | |||
| 25033f4f6b | |||
| b8fae00c1e | |||
| 6d4e4e2f69 | |||
| 1cde688fbb | |||
| e3493fbe3e | |||
| 1b691a3dd7 | |||
| 3022dce26e | |||
| 9780a65f09 | |||
| 34dd864c8b | |||
| 9b16519a7e | |||
| 76321343c2 | |||
| 0159ce5b1d | |||
| 5abec25c58 | |||
| d9de1e866f | |||
| 1ae8e7d55e | |||
| 67dc4521e9 | |||
| 852ebba530 | |||
| 79669d9a69 | |||
| 11d37bcb93 | |||
| c95d5dc320 | |||
| 92044c7797 | |||
| 7084d9e084 | |||
| af96e2f143 | |||
| f7560714e7 | |||
| 785c5e66ec | |||
| f281e5aa95 | |||
| 55f0f5271d | |||
| b60d3a771d | |||
| d2132b2e64 | |||
| 95494c0d03 | |||
| 76a8286c04 | |||
| eca8d6dd8d | |||
| e6ae034f7e | |||
| 236b4efb9b | |||
| 4b4c9ba959 | |||
| 6bf05741a9 | |||
| 5d1998accb | |||
| 3aa9ffc241 | |||
| 8ab5575e0a | |||
| 3980b8a9c8 | |||
| 27550d7ec9 | |||
| 35513e1e21 | |||
| 15496aed44 | |||
| 27408c191d | |||
| 4b6c6717ad | |||
| c0bc3d8061 | |||
| fe5f252bc9 | |||
| e25af085fc | |||
| 400da676fa | |||
| bf9f02e53a | |||
| a437da76ec | |||
| 8cceee49ea | |||
| 34ff03936a | |||
| bf3ee93c23 | |||
| a3260b4ce3 | |||
| ea8cf7b62a | |||
| 7168681918 | |||
| 233291b30c | |||
| e53ff167ee | |||
| df54d09494 | |||
| 4aa3edc508 | |||
| 4ea1b93f8d | |||
| 361ca2cece | |||
| fa0d076a09 | |||
| da5a1e0945 | |||
| 6d187f0d9a | |||
| 85eca4c464 | |||
| 1efbce7661 | |||
| edf69d1ef1 | |||
| 375e7db449 | |||
| ac71e38d96 | |||
| ae5fd91cd4 | |||
| 14e8b2ef17 | |||
| 5bacea8b50 | |||
| 15dff87200 | |||
| ae45c77523 | |||
| 7c834993f6 | |||
| 5f5749ac8f | |||
| c99a7b6666 | |||
| b4e2d3edfe | |||
| 8f9308f349 | |||
| fc48473e40 | |||
| 71317db4cb | |||
| 23815429e2 | |||
| b468134432 | |||
| 3e38db16f6 | |||
| bf591cc01e | |||
| 3178cbc563 | |||
| 1c54f6b2f4 | |||
| 7743456d7d | |||
| 4dc43263a5 | |||
| 5d84f1c523 | |||
| 8289ebbe50 | |||
| 94741f1b4a | |||
| a5b394aa93 | |||
| 9f3d152d8c | |||
| 94c91614d6 | |||
| 02a59b0742 | |||
| 882c2e2378 | |||
| f6b56735b6 | |||
| 8aec463eb4 | |||
| 37cdcf93e6 | |||
| 9547a06f39 | |||
| a8d5d2ace1 | |||
| e8a0464f6c | |||
| 85a39e64c1 | |||
| e18cf759f9 | |||
| 7e1ab1e6b0 | |||
| eed74d72cd | |||
| fa8c96af13 | |||
| 18ec2ff458 | |||
| c38a737421 | |||
| 0166b53e21 | |||
| 724da4e500 | |||
| ce15e8dfe0 | |||
| b968d0d694 | |||
| fa0549f34f | |||
| 999ef36963 | |||
| 7affd05247 | |||
| 2ccf4011ed | |||
| 61f3908d33 | |||
| 08e429210a | |||
| f94944c41a | |||
| 200631e57e | |||
| 9c83d5e752 | |||
| 894bff2e35 | |||
| 6ff0a699c0 | |||
| 5083428a06 | |||
| c74a14fcb0 | |||
| d060c7535a | |||
| 5eb134f7b5 | |||
| c1c5117f01 | |||
| 8ce1f5884f | |||
| 1f8b51fafe | |||
| 80f73f0bb1 | |||
| 88e7b3fb47 | |||
| 3bb36044c1 | |||
| f9ace54fab | |||
| 498d7e2f66 | |||
| 420526df9d | |||
| ab00d9534d | |||
| 4bb9073ce1 | |||
| 58cb0118b4 | |||
| f19740e376 | |||
| ab50d0a514 | |||
| e551212516 | |||
| 888734b7d1 | |||
| 90d1a01998 | |||
| ab1dd2b374 | |||
| 0e4d731068 | |||
| f23416dfb8 | |||
| 469cc3d508 | |||
| 5ad88be997 | |||
| 536341b6de | |||
| 18dcd0a5d2 | |||
| 5f8a0643f4 | |||
| ccbf8b34ef | |||
| 25915c077e | |||
| bcb574e618 | |||
| 6cfa24340f | |||
| 0dc26216c2 | |||
| 8dd850d685 | |||
| 638f261bf4 | |||
| ad5a0a5cd9 | |||
| 7dda54f36d | |||
| a8477940e2 | |||
| 6a26f62ca1 | |||
| 06d0bfadca | |||
| b805d7fe19 | |||
| b784671397 | |||
| 4784a31513 | |||
| 3eb9bfe9ee | |||
| ab31aecdac | |||
| 5cb2bd1332 | |||
| 8bff9efc5c | |||
| d01360ca19 | |||
| f48c71f30c | |||
| a2b3190b1d | |||
| 913d5a532d | |||
| 96c6c372fd | |||
| 8926e06e44 | |||
| 6636e89a0b | |||
| 01e9e83641 | |||
| 30dc338636 | |||
| d4999de214 | |||
| a53595a055 | |||
| 0cb7415a4c | |||
| 9f287d0d7f | |||
| feddda2948 | |||
| 613b7eda8a | |||
| bd3364a3cf | |||
| 3f918bd309 | |||
| 9b3f2ae3c7 | |||
| 6c33c5701f | |||
| e731fe9b98 | |||
| edbfa9117d | |||
| ae54cd8fde | |||
| 91686e252c | |||
| 88d132931e | |||
| 4afedcf126 | |||
| d3d815f26a | |||
| 62725b1930 | |||
| 06d509b5ac | |||
| 77aba38625 | |||
| ce33e1d242 | |||
| 591cf29edf | |||
| dd81823e29 | |||
| 15994e7be8 | |||
| 61f3b87dae | |||
| 6279f1920e | |||
| d169d60d8d | |||
| f49cf43fb1 | |||
| aa94ae8759 | |||
| 8ad20b57fd | |||
| 7c4cb5ea7f | |||
| 23733bb1a6 | |||
| 5be3f333f3 | |||
| b14f3f53aa | |||
| 47c3fc35e3 | |||
| 0fd1497496 | |||
| 6c9c983f72 | |||
| 0422eee9af | |||
| 97a4b79713 | |||
| 0785ee3099 | |||
| d58d04d6a0 | |||
| 9bb2b17c77 | |||
| 64e70d8e92 | |||
| 6fa9eb558a | |||
| ddcc851951 | |||
| dc2e5afe3e | |||
| d8e9997987 | |||
| 3d919cd937 | |||
| b094c2d78f | |||
| 9b699ba374 | |||
| f8e5efc874 | |||
| 2c61c695d5 | |||
| b6e806adbc | |||
| e74aa160af | |||
| 6793228fbe | |||
| e83ea8124e | |||
| 313f99d09d | |||
| 28de292107 | |||
| 10efb98eb3 | |||
| 8ac2241372 | |||
| 092434a103 | |||
| a777997f79 | |||
| 36cf7f718b | |||
| 7989267d51 | |||
| ef4398a5f1 | |||
| 0da8afc108 | |||
| 0e74d36227 | |||
| 290cc151bc | |||
| 21f93aa7e8 | |||
| 04c77e9760 | |||
| c6da6544da | |||
| 94d3e38bc7 | |||
| 5fcf992920 | |||
| 22cc9eabc0 | |||
| b191c0d341 | |||
| d2d431ce2e | |||
| 3a6b58ea8c | |||
| 2d8fc40307 | |||
| 68dce2f247 | |||
| bc03eb2e65 | |||
| f725709e5b | |||
| ba591c9dc5 | |||
| def5d33055 | |||
| 1aaa51c4be | |||
| 37206bcc83 | |||
| c2b86bac4b | |||
| 02dad179cd | |||
| adb94f8773 | |||
| 035110df75 | |||
| 5adb65899c | |||
| 764a373e7d | |||
| 8114327c7e | |||
| 6404417dad | |||
| d89cb8f1e9 | |||
| dee95c2f08 | |||
| 3a907ec7c2 | |||
| 851dff6e8c | |||
| 47e7364976 | |||
| 41f8207b3a | |||
| ed0a3a22ab | |||
| 3a513da942 | |||
| a4f1c60da2 | |||
| de0bf7d814 | |||
| 71fd72e462 | |||
| 619cc3c047 | |||
| 68c75a4e34 | |||
| 37671cefa3 | |||
| d9f409069a | |||
| fd5a190490 | |||
| 2f4d5b32b6 | |||
| 4c7ac68858 | |||
| ad3a3c5266 | |||
| 51d924c1b8 | |||
| 83491f535a | |||
| 380731a244 | |||
| 60c78da0f6 | |||
| 2d02f4f962 | |||
| 982bd89924 | |||
| 04f60747d9 | |||
| 28c107b089 | |||
| e6cc8757ac | |||
| 9169bfc608 | |||
| 610e33e4a4 | |||
| 77dd40fb4a | |||
| 5a63c51316 | |||
| eabc8b5854 | |||
| 1a798886a2 | |||
| 8735dadbca | |||
| 2c53ebc0e4 | |||
| f93033695d | |||
| 2d0f5817d0 | |||
| 2033e22216 | |||
| bada6f64ae | |||
| bc141698c8 | |||
| 75fddd9349 | |||
| b1a417295f | |||
| 0522036b80 | |||
| 061469840b | |||
| 6e218ed908 | |||
| 626b48c3d1 | |||
| dd957237e2 | |||
| fc9e237dbb | |||
| faac265373 | |||
| 998935e2a3 | |||
| 24f8116fce | |||
| 3415330871 | |||
| eadeaae6db | |||
| 32bdaf4f24 | |||
| 7525fe9357 | |||
| b24f31922f | |||
| 4c79349b8d | |||
| 44f7a27387 | |||
| 369425bec1 | |||
| 3dc284335e | |||
| bfc284994a | |||
| 277409a807 | |||
| d1f1f14bc3 | |||
| 5ee1f5d3af | |||
| f4569fb5cc | |||
| 4ba0a2dafb | |||
| c2b1c2b1d8 | |||
| 2e119e2efd | |||
| 4641918486 | |||
| 407f6f2b0f | |||
| f01d7ecd96 | |||
| e3d987bbdf | |||
| 89845883d0 | |||
| 4e7ff94b33 | |||
| 2fb9a1b1d7 | |||
| 5c0ab36662 | |||
| fc6dac326d | |||
| 426dcff085 | |||
| e623f45c04 | |||
| 3b9a9cb0fa | |||
| c018a86bdb | |||
| 559be38baf | |||
| e3e05e5003 | |||
| 95649d7d46 | |||
| 61097de76d | |||
| e49fff5028 | |||
| 20ae7945e0 | |||
| c5a50d23b6 | |||
| ad37e5ca27 | |||
| e8303064b9 | |||
| f8a577749a | |||
| e113817293 | |||
| 0d15cdd370 | |||
| b5db08eec3 | |||
| c3591c1fae | |||
| e1a4d5497a | |||
| 4e83162adc | |||
| 42c6b8a016 | |||
| 48f9d808cf | |||
| 6546c27cf5 | |||
| fc0c0f87dc | |||
| 9d703c0af6 | |||
| 24559c475b | |||
| f92e8a285a | |||
| 0411120551 | |||
| 5f57d4ddcd | |||
| 4164bbeba8 | |||
| 14dea99ccd | |||
| 3ea1881ff5 | |||
| 5192c188f4 | |||
| c1ffa47e9d | |||
| 2808a9dcc5 | |||
| e1ab6b6c93 | |||
| 229868bb20 | |||
| 520eb4cd1d | |||
| 2d0b4d6ae5 | |||
| 5dae9a197a | |||
| ff1ebf9775 | |||
| e6f388518a | |||
| 3557706e3a | |||
| f3d0d55a2f | |||
| b0c2bad1d8 | |||
| 53c9ca3b3a | |||
| e41ba1be45 | |||
| 594febaece | |||
| 890dae8ba7 | |||
| 8a3120be39 | |||
| 6b4975559d | |||
| 3326550705 | |||
| 6be0d82fc6 | |||
| 44ad841d05 | |||
| 53f45ace4c | |||
| 42e9cae876 | |||
| e46922d341 | |||
| 21c242ee05 | |||
| 33b7a0cef2 | |||
| 9cddca1af5 | |||
| 8cdf0d9fce | |||
| a079ac4207 | |||
| 099238a2e5 | |||
| 595bc16d92 | |||
| e9875c8288 | |||
| ec600ab672 | |||
| c3689aee93 | |||
| 60a728d521 | |||
| 7bd7071ec5 | |||
| bb787aa9ca | |||
| d2f629d100 | |||
| 5d949de0ee | |||
| e21bc8a930 | |||
| af79f63870 | |||
| 4ff32342e3 | |||
| 98d55faf4e | |||
| bd532ea808 | |||
| d4bd57ee70 | |||
| 90dbfb31a6 | |||
| 55ca34cad3 | |||
| 36a5e919cd | |||
| 3263ba1440 | |||
| 9721c19e48 | |||
| de71213eed | |||
| 65abbf9563 | |||
| a94098494a | |||
| ec935356aa | |||
| 6ab419dfad | |||
| b1ffcff064 | |||
| 4ce09a3845 | |||
| 9686e74feb | |||
| e97e24762d | |||
| b3fd0805e8 | |||
| 300092d07d | |||
| 56ed3a11d6 | |||
| 6938b20ab6 | |||
| 77f2cf5089 | |||
| 19e3b015c5 | |||
| 2702d0fc2a | |||
| 472a4883f0 | |||
| 485e2e18bf | |||
| 40c0f69eff | |||
| 854a1e5723 | |||
| f4cd28cdb9 | |||
| 5bae790dd8 | |||
| d1d43c38cd | |||
| 7e1552eeb4 | |||
| 7306bf28e0 | |||
| 07e00a8faf | |||
| ab93866366 | |||
| d7801b59e7 | |||
| ea926f173a | |||
| f6b55da0c6 | |||
| ee4e562874 | |||
| abfe5ffc45 | |||
| 9629b0e1a3 | |||
| 80b03dd194 | |||
| 3f92f8d2aa | |||
| 823c94cace | |||
| 421ac6c427 | |||
| 72550d6d84 | |||
| 72999cc7b0 | |||
| 706cf641b3 | |||
| d42bdb2505 | |||
| 9082054ba9 | |||
| abc69bc838 | |||
| 23ea5d9d06 | |||
| 8d009d6366 | |||
| 8213b51bd6 | |||
| a18fc2080d | |||
| 9c0ac0ff57 | |||
| c34dc9f946 | |||
| 1c5c205614 | |||
| 897df1b8fa | |||
| 3fb22b7c55 | |||
| 7819a30c57 | |||
| 37d2c72945 | |||
| 5631e2c09f | |||
| c7ddd6ec35 | |||
| 7280ceac32 | |||
| f8b9128d8e | |||
| c482f1dccd | |||
| 7e306be8aa | |||
| 035e6913b5 | |||
| e12f233afc | |||
| 26c7ff8c18 | |||
| 5647364293 | |||
| 06fa585f69 | |||
| 035eac2f1e | |||
| f01889cbf7 | |||
| 73025bfd4b | |||
| aec6dd1246 | |||
| ab4411e5bb | |||
| 0ac00efda6 | |||
| f32eb8d710 | |||
| ec33dfb76c | |||
| 43dfbac2fa | |||
| 7a483abec2 | |||
| 35e6b6faf4 | |||
| 1066b58fb6 | |||
| b41b8f251f | |||
| a1426c3e81 | |||
| aa3967d88f | |||
| c610c4cba9 | |||
| abb3a2dbd2 | |||
| 1f035301d9 | |||
| ebf7f76d48 | |||
| 397ab77105 | |||
| f37abc69ea | |||
| ee85b0e057 | |||
| eab28abc86 | |||
| 16c5307fc2 | |||
| 8c8cae1e27 | |||
| 925c645821 | |||
| c1c97a86b7 | |||
| 1fc1016148 | |||
| e73545d296 | |||
| f2fb7d43d0 | |||
| 781d421e1c | |||
| a3a7464a29 | |||
| ac936f5650 | |||
| c0f5dc2dc8 | |||
| 31c113180e | |||
| 239df2deb2 | |||
| 31a8c4b0b9 | |||
| f394bd45c7 | |||
| 63999c9ec3 | |||
| 82c24cee7e | |||
| 5e94b0c009 | |||
| 452ff62134 | |||
| 3df494cacd | |||
| d62bb59df7 | |||
| b367f9320b | |||
| 4bc3dbbf6c | |||
| e7b7e3ac96 | |||
| f3c4aea12f | |||
| b9b5938a91 | |||
| e7fdcf0db4 | |||
| c1f22aa556 | |||
| 991b4089d6 | |||
| a8132552de | |||
| a0323aef19 | |||
| a38abc2f7f | |||
| a6beecf510 | |||
| c5dece0e59 | |||
| ce935bafc1 | |||
| fd426a96aa | |||
| fad8800842 | |||
| 273a473db1 | |||
| a7588e517d | |||
| 84eff098eb | |||
| f157f3b5d6 | |||
| 6cd00c60a7 | |||
| 2ea951db61 | |||
| 9d0bd0aabb | |||
| 3d88d16b4b | |||
| 02724dc26d | |||
| 21a93652cd | |||
| fb4caf1a42 | |||
| 7a2508bf17 | |||
| eeeab86952 | |||
| a149ff1705 | |||
| 2c73c9c815 | |||
| f6f29db9f1 | |||
| c823a68616 | |||
| e7e2184760 | |||
| 6fe2422bc9 | |||
| cd62776be6 | |||
| 037357efe9 | |||
| 8d3910ea4c | |||
| 3e5926f706 | |||
| a1d67bf539 | |||
| 3e65457041 | |||
| f70180eb66 | |||
| c0a558e229 | |||
| 801069f5ac | |||
| f9dcac8264 | |||
| 902c001aa4 | |||
| 0cf2a4353d | |||
| 13c8cc90f2 | |||
| db231fafeb | |||
| c3f7deb602 | |||
| 300e3f2f58 | |||
| 513406f0e5 | |||
| 27e21e77f9 | |||
| dadfd803f7 | |||
| 02b0ba2278 | |||
| 3e1005aef1 | |||
| e2eb13739c | |||
| c52e30ceae | |||
| 07754cdf5f | |||
| c74c475a29 | |||
| ad36ab520b | |||
| bc32ff5db9 | |||
| 6009432933 | |||
| 99eaa37c76 | |||
| ed6d5f727a | |||
| c6995d6e58 | |||
| cb0f453a8d | |||
| d9866846ad | |||
| de5d9195f3 | |||
| fd1fe8562c | |||
| b1298223aa | |||
| c48128d92e | |||
| 0f4d466953 | |||
| 1b752fcaf6 | |||
| d06db9909c | |||
| 921024035c | |||
| 3b1c8c3deb | |||
| 69862ab67d | |||
| b05c321306 | |||
| 9b74a58dde | |||
| d112ffaf6a | |||
| 554f063def | |||
| f6dce02203 | |||
| 653dfe82fa | |||
| 5dbf743052 | |||
| f7e7e2e41c | |||
| b28b4db7fd | |||
| c34f30e4a3 | |||
| aa7f11185d | |||
| 1790d19809 | |||
| fa6fbca67b | |||
| cd79c57a27 | |||
| 4c3a97e2b2 | |||
| f126dceeae | |||
| 414521acc5 | |||
| 9147422340 | |||
| 920646ea74 | |||
| c57d839927 | |||
| e7fd5db2c2 | |||
| b76486ef5f | |||
| 5c06584676 | |||
| 2ae2ee64be | |||
| 17ba35e237 | |||
| 53e98e70aa | |||
| 359e18eb58 | |||
| 3377459df5 | |||
| 3e30d15405 | |||
| 2b50cf2243 | |||
| b72e2b6bf9 | |||
| c7a2b34f59 | |||
| b48958995a | |||
| 58c496eacd | |||
| 7bd867c9dd | |||
| be0558849c | |||
| a1c7ec2ac9 | |||
| 8bf073c0c6 | |||
| 994689f05a | |||
| 3e10f9f451 | |||
| 972fa9f674 | |||
| 8e64d8e334 | |||
| eccd81d40a | |||
| 649136f98f | |||
| d7dae1366d | |||
| 19e2ebcd03 | |||
| 021c907d16 | |||
| 8ac3e28fdf | |||
| c5af279730 | |||
| e9377e93f1 | |||
| 6747c69511 | |||
| 9b6cae6c49 | |||
| 7148bd1d42 | |||
| 73940fffc6 | |||
| 09015449cd | |||
| 4dfdb99731 | |||
| bbbca04066 | |||
| e755bba608 | |||
| 9161cec238 | |||
| dc14b60fcc | |||
| da625d51f6 | |||
| ce69055758 | |||
| 589ebd5bca | |||
| 35b50e1a9d | |||
| f038564b1b | |||
| 1d0eb9806d | |||
| c50a9bd318 | |||
| cd9006d29b | |||
| d3b88f9065 | |||
| 6a6cb1961d | |||
| 884c51a69a | |||
| 6f126e6cd4 | |||
| b0c2e5409a | |||
| 9516ec3cd2 | |||
| aecb92ccd3 | |||
| bdf13f29f7 | |||
| 81120abfcb | |||
| 08a8170990 | |||
| 316ea910c2 | |||
| 0b5edfc21f | |||
| 76c08095ab | |||
| 538864519e | |||
| cd6631049b | |||
| 079f8030b7 | |||
| ad0b32c0ee | |||
| 8235b51a14 | |||
| 1bd5e7472f | |||
| 7433a7144c | |||
| 27632ecdd9 | |||
| 0b1e25b073 | |||
| 19a93f0026 | |||
| 3256a6d596 | |||
| 28ddfa5243 | |||
| 05c560be3b | |||
| 8ddd810fe2 | |||
| f20760bae5 | |||
| cea7320a9b | |||
| fe6826016c | |||
| f0167b3e88 | |||
| 0edbf7f517 | |||
| a8a8dcff3f | |||
| 1b0ad13529 | |||
| 418d6c882c | |||
| 1e6899c40b | |||
| 259b201e65 | |||
| 8fb113a04e | |||
| c6ebbc6122 | |||
| 755903a08e | |||
| 34e4825cd0 | |||
| a68eeae9bd | |||
| e4e31b554e | |||
| eba6e3f5f1 | |||
| d73ebaca76 | |||
| 94167152e5 | |||
| 830f76e909 | |||
| 8ae04944fe | |||
| c55b8d29f7 | |||
| 30623f7d38 | |||
| 16964520df | |||
| 3050fdb3c3 | |||
| 77fc2c5cf1 | |||
| b21c3ed4e9 | |||
| 93f4b345c5 | |||
| 88e59a2739 | |||
| 86bb256bf1 | |||
| 9a05f5bc93 | |||
| bce28cf389 | |||
| 629c5e7739 | |||
| ed402e2f5f | |||
| 4a56c7523d | |||
| 218d9f48b0 | |||
| f67cf99477 | |||
| 2201b2adda | |||
| 6b36421bce | |||
| 8c573c65d4 | |||
| 730dabd9cf | |||
| 69175e1b19 | |||
| a5ad58e516 | |||
| 82b4631341 | |||
| a1c9c1538d | |||
| 1a53f58540 | |||
| 1b414b840e | |||
| 642cc0e98f | |||
| 63431bb54b | |||
| d64de26ded | |||
| 8b45067226 | |||
| 061032e3d7 | |||
| 82432686aa | |||
| b66d2039be | |||
| d245a73d7f | |||
| f0037151e6 | |||
| 52d494f573 | |||
| 36a2d71731 | |||
| 615a220acb | |||
| c718584755 | |||
| 4db0ea616d | |||
| 5439e60078 | |||
| a6880d4569 | |||
| 65e852f341 | |||
| 4ffdf9e536 | |||
| 8f698e3e62 | |||
| 61481e6e9a | |||
| 49397df90b | |||
| 7b254a08fb | |||
| 5bebbcf5eb | |||
| 83fd48e2f4 | |||
| f5b25370b0 | |||
| f68d3209ac | |||
| 2ab7f784c9 | |||
| 1e8d99a591 | |||
| d517cba765 | |||
| 552eb5b9d8 | |||
| 684c4ea113 | |||
| 4dfaca610f | |||
| 8a53998251 | |||
| 6690f70b05 | |||
| 96d1d3cb66 | |||
| 09785ef451 | |||
| 25e118f3dc | |||
| 78b3e3c60b | |||
| efe41a5e21 | |||
| 835041e5f6 | |||
| 93a8086ff6 | |||
| 1ac40684de | |||
| 433d1bbf57 | |||
| e33de03522 | |||
| 86fedbfaae | |||
| c0f4eef896 | |||
| a2f3bf3a8c | |||
| 1b717e4683 | |||
| 52e2ac7174 | |||
| 3d6b053eb4 | |||
| 268eb1d60d | |||
| a69865b8c9 | |||
| 4a1df3d5cc | |||
| 6dfd757ea1 | |||
| fc1adf3b94 | |||
| be2d1d7895 | |||
| 9e7c360912 | |||
| 51acd33d19 | |||
| af3dbe2f86 | |||
| 97668e5413 | |||
| 464fde0ed2 | |||
| 65bd7909e1 | |||
| 5d3ea57d4d | |||
| b7bc3cfbcf | |||
| 04ef32420b | |||
| a3d8a48b92 | |||
| ef86d1d7cb | |||
| 00b3e9b371 | |||
| 0d02f56855 | |||
| 48aa841add | |||
| 4ba52212a9 | |||
| a14bca1059 | |||
| a7e07af24f | |||
| e14d655447 | |||
| 74bdeaf4f7 | |||
| 9591c62175 | |||
| 39c46dcab0 | |||
| 299e08f53d | |||
| 12555a6ff1 | |||
| 1cc012c7d1 | |||
| 28c6810878 | |||
| 1ed36fdff4 | |||
| 26801cf206 | |||
| c80cebb824 | |||
| 3c6e8d6d01 | |||
| 76a53ab154 | |||
| fa3e387dd1 | |||
| dca626bbcb | |||
| 3289ad2817 | |||
| 5a022a2246 | |||
| b012c5b2aa | |||
| a861f8d9d4 | |||
| 36669c80da | |||
| 2ff128f184 | |||
| 3b44aba341 | |||
| 978be4e383 | |||
| d4cdfcc48c | |||
| 5123ab0720 | |||
| 5021a1e1f3 | |||
| 576281a612 | |||
| b84c0aba59 | |||
| ee503a378e | |||
| f235037cb9 | |||
| 0cd1cd97a6 | |||
| 74513f1b5c | |||
| 231c5bfea7 | |||
| cfd0e4ba85 | |||
| bf33e4ed4f | |||
| 6290db035d | |||
| cd1935be1d | |||
| 64262d6ecc | |||
| 270c69344f | |||
| 10a0793af7 | |||
| 1b37af321f | |||
| 7cde279be1 | |||
| 0396741f3d | |||
| 117cf8888a | |||
| 83db7b32e8 | |||
| d496d3d16e | |||
| 6b801247ab | |||
| 4c6cd31bfc | |||
| a8ef096f24 | |||
| c8d2a7e833 | |||
| 783391838b | |||
| 7c37d8b204 | |||
| 65ed8825b0 | |||
| af9324dd5f | |||
| 064f727676 | |||
| 8025862fb9 | |||
| 2544ec5587 | |||
| 6c823b0137 | |||
| 88d44fa654 | |||
| 8b6f9f9de7 | |||
| cb14961dcd | |||
| dab486ec99 | |||
| 75849fbfb5 | |||
| f984ff044b | |||
| aaf5f295da | |||
| 8f612f2017 | |||
| a2808163a7 | |||
| e4aa23ce3d | |||
| 1b3cac9424 | |||
| e49020b905 | |||
| d68dcaf69a | |||
| 856c3578f6 | |||
| 18c6ea39ce | |||
| 1ce46c016c | |||
| 296944c23c | |||
| 4f772fecdc | |||
| cdd22444b9 | |||
| 15848bc8c4 | |||
| 9eba6d607c | |||
| e9d3c7c2e7 | |||
| ad16c6d44f | |||
| 2046958bd6 | |||
| 0046533d53 | |||
| ce7e152e13 | |||
| edcdc057e6 | |||
| cfa851beea | |||
| f5d8efe86e | |||
| 7c8e5033ec | |||
| 22ec94b374 | |||
| 5cd3a172f1 | |||
| a89a3b38ce | |||
| 3202702612 | |||
| 725e32f439 | |||
| 7da1905ad3 | |||
| 421005a3b6 | |||
| d5bf28f799 | |||
| 990f748e42 | |||
| a466365949 | |||
| b12f71c430 | |||
| 236a69e5dc | |||
| 9458243926 | |||
| 41274e7801 | |||
| 0259e41ce8 | |||
| e78f9cbd46 | |||
| 9d6851adec | |||
| 4668f072af | |||
| a1a414925f | |||
| 19eb9dca30 | |||
| 8464a2ba43 | |||
| a8549e2b7d | |||
| 2531a25c9e | |||
| 2f7b7eeddd | |||
| ab1ec54c03 | |||
| a1ca605206 | |||
| a7b444dfea | |||
| 64b35b9cb3 | |||
| 4a8d52b328 | |||
| 3cbf6fff90 | |||
| 2693e76483 | |||
| b232a5da37 | |||
| e50fc00583 | |||
| 4b8802af37 | |||
| ebd69fd10d | |||
| c1a8c08880 | |||
| 647fb6acbf | |||
| ede692ea2a | |||
| ca44e2762b | |||
| eda70742eb | |||
| b81e3e9e6d | |||
| e766eaeccc | |||
| bab61271f2 | |||
| b1465d89a6 | |||
| 05b1ddf013 | |||
| 903e8711f7 | |||
| 31b93fb42c | |||
| e16bbfc2b9 | |||
| 220e004d73 | |||
| 3136861b24 | |||
| dc2693bead | |||
| d7da8c4253 | |||
| c1ff5831ad | |||
| ac5646075b | |||
| 5a1faba796 | |||
| 4ab16cb276 | |||
| eb1e885c0a | |||
| 00ff9a11b8 | |||
| 8eabc024bf | |||
| a848af0753 | |||
| f4e7a3a314 | |||
| d83283c709 | |||
| a35112a6f3 | |||
| 66c012a30d | |||
| 7b92b7853d | |||
| 6c9f10e6a8 | |||
| 6db2c4465d | |||
| c0cc960df5 | |||
| 968240ad44 | |||
| 50f3016711 | |||
| 56e2b06e9d | |||
| c02f69720a | |||
| 96df7d1e42 | |||
| 1d4caf7588 | |||
| b0e3201d3c | |||
| bab097958f | |||
| f4a3f6d433 | |||
| e73ab89a18 | |||
| 187643f6ae | |||
| 3c9bdb2915 | |||
| 5241642447 | |||
| 3b2cbea1c4 | |||
| 80e3da49cb | |||
| 1df7a12587 | |||
| 663a59bd71 | |||
| ced859424b | |||
| 4a6377c204 | |||
| fd22558207 | |||
| a6faadea48 | |||
| 42a26100b7 | |||
| e8f4770abe | |||
| 7751d4ee88 | |||
| cdd829e7be | |||
| 16bf3a89b5 | |||
| 11cdae098b | |||
| a63ee3fa8b | |||
| 5cc023d1fe | |||
| c4084156ac | |||
| 302018feff | |||
| c50f6b72e7 | |||
| c0401447dd | |||
| 43680c2fc3 | |||
| 2c92bb9d61 | |||
| dcf1a56756 | |||
| 5990ab1cc9 | |||
| 084499fa0e | |||
| 74e84a73dd | |||
| 96b0393f91 | |||
| 0656c33e05 | |||
| ec1ab49b54 | |||
| 1daa2857b2 | |||
| 8c55541d0e | |||
| c5a4776b3a | |||
| 8bb9f0d7c0 | |||
| 7d83c251a8 | |||
| ee3ead9aac | |||
| 54896e0e31 | |||
| 016198e7f2 | |||
| 0933eef4c3 | |||
| fe55555c67 | |||
| bcf8973eed | |||
| 50d2e42cc3 | |||
| 261d1cbeba | |||
| 242462b9ba | |||
| fd4e478dbf | |||
| 6b91e68668 | |||
| 7516d2af56 | |||
| c247a98402 | |||
| 83bcd55a7a | |||
| 5a43936e35 | |||
| 35b776179e | |||
| f4cb6df8d4 | |||
| a259b88f1d | |||
| 5b4f3d1c98 | |||
| c62c21c386 | |||
| 17c56a11bd | |||
| 796561b8b6 | |||
| 209b7a64ed | |||
| 8f56299380 | |||
| 73b1394ca7 | |||
| f3a2cf7284 | |||
| df79c765f8 | |||
| d09737c218 | |||
| 6b0c42ae50 | |||
| 7363da1b54 | |||
| 684f19c060 | |||
| d08e4db0eb | |||
| f1e7d8bd06 | |||
| 1328ac061e | |||
| 391f0fc9af | |||
| 38cf5be738 | |||
| 1bb70b8697 | |||
| 6e35b80daf | |||
| a171c22ce4 | |||
| f56457bc28 | |||
| 9708de70c7 | |||
| d68589bb70 | |||
| 16eb38782a | |||
| 2175e9c0d6 | |||
| 9abd71f681 | |||
| d1dc829136 | |||
| eda672bdc6 | |||
| 0e5dbbea79 | |||
| f5809ef302 | |||
| 457ce1ece1 | |||
| 9c9841332f | |||
| 9470d3a2ef | |||
| 8356271f8d | |||
| 42a6f3272d | |||
| 362b242c41 | |||
| 7ace7b49ca | |||
| 7cd902e924 | |||
| e3c14678e2 | |||
| bfaca75a7d | |||
| 5aecd8c255 | |||
| cfc0f1a1f7 | |||
| edf657c65c | |||
| 801d00fa26 | |||
| eeffa31282 | |||
| 206528a530 | |||
| 41690fdf7b | |||
| 5b83f8e45b | |||
| 94863ed8ae | |||
| e63b99c890 | |||
| e8542743b4 | |||
| 309e1208c2 | |||
| 3e0db05664 | |||
| 9573d92cc0 | |||
| 1abc0dcb6a | |||
| 770fb3228f | |||
| d6aa251c5e | |||
| 9305b870d2 | |||
| 824a98d7a8 | |||
| 7a55ba105c | |||
| 122425338e | |||
| 1d7f874a78 | |||
| afb63a7331 | |||
| 0c07a660ee | |||
| 8ffda53e3d | |||
| 5a30c08ff6 | |||
| 9cac2674c4 | |||
| ec3f43c69f | |||
| 270dfab6a2 | |||
| 624b1f5647 | |||
| 84332a3ebf | |||
| 63ff79ef0b | |||
| 09452444d7 | |||
| 75be2fc0ba | |||
| 1e0a0f8dc5 | |||
| f3d9b9c5be | |||
| cef0e444c9 | |||
| bad8dc2220 | |||
| e05d57d908 | |||
| 45c153f7a0 | |||
| 0948f418cd | |||
| d027113b0b | |||
| ff00c2fb15 | |||
| cd5b4ee1be | |||
| ac337b8459 | |||
| 567f7cbc29 | |||
| d81ffcf119 | |||
| 6ed66a70a2 | |||
| 9ed3b045f7 | |||
| 2d6653c14a | |||
| ab0e7e735a | |||
| 3243555d3f | |||
| 8696ce0cc1 | |||
| 459ff26868 | |||
| 277eb2d09f | |||
| 187093fa5a | |||
| 6c9ce55759 | |||
| f9721e501a | |||
| 23c22651be | |||
| 2ad81ca499 | |||
| 7792381c36 | |||
| 591dd128ce | |||
| ce10390406 | |||
| bf299e5f8d | |||
| 7f98e703f1 | |||
| 421d27f640 | |||
| fb1e95ab87 | |||
| 3737592734 | |||
| 6445cf01a2 | |||
| 8e07b93eac | |||
| 23f6752362 | |||
| 19b870c038 | |||
| ca7f15e622 | |||
| d497bb25f3 | |||
| 29d694722b | |||
| 40ffef035b | |||
| a00c198bcc | |||
| 717842b276 | |||
| d5c4c34759 | |||
| edb0032118 | |||
| 123144d06e | |||
| 38f5d45d5b | |||
| bcaf808b88 | |||
| 7b8db597ef | |||
| 18e192b235 | |||
| 5ad30277ba | |||
| 2e998dc315 | |||
| cda1658541 | |||
| 8b640912c3 | |||
| 81a773b861 | |||
| 444cc43971 | |||
| eb86d59203 | |||
| 5ee35f3fbb | |||
| 9a91145f89 | |||
| 637081ebdd | |||
| 7d2746e7be | |||
| c84a92c787 | |||
| b775aaa274 | |||
| a97d7abc24 | |||
| 7e73db505b | |||
| a126906776 | |||
| 2d6092c114 | |||
| caef309547 | |||
| f9ec21a2b5 | |||
| 06600b2a94 | |||
| 3f39ec0ae0 | |||
| cfc45cf068 | |||
| 45d809a641 | |||
| fcfbc5e17c | |||
| f30c66424c | |||
| f823fc6ee0 | |||
| aac291c0c6 | |||
| 61adeeeda3 | |||
| f94a5eed61 | |||
| 0695c48e7a | |||
| f4bfcf58fd | |||
| dee7307adc | |||
| 114032a743 | |||
| e9e6a63e6a | |||
| 2a4f6020c2 | |||
| 3ea8b3737f | |||
| ed47b4b3db | |||
| adc89feda9 | |||
| 32c9a59ff0 | |||
| 200c1dac85 | |||
| cf65c2af15 | |||
| fb6ebc42a5 | |||
| c7696c375e | |||
| 337e1a837f | |||
| 495a9fd3a0 | |||
| e6f7493ddd | |||
| 76e75505e5 | |||
| dafbd3f368 | |||
| 11ec70441a | |||
| d1a18913f3 | |||
| 775b9e9fde | |||
| 286e34e057 | |||
| da2aa00442 | |||
| ba90176bb1 | |||
| cf9248ecc8 | |||
| 0d42b12658 | |||
| 2f6d9b640f | |||
| 04923b65b2 | |||
| 2328f9a36b | |||
| 98971736f8 | |||
| ec809085b4 | |||
| af023c1994 | |||
| d9b7cc18f3 | |||
| ce1121a4c2 | |||
| 5fa75bf6b9 | |||
| 5cb1036618 | |||
| 9473dc2069 | |||
| 81f5184b43 | |||
| b6bc22f991 | |||
| 56fad29df9 | |||
| dfeea53cf6 | |||
| 71e6369960 | |||
| 0611db78b3 | |||
| 8c768cc517 | |||
| b67750d808 | |||
| 96f2ad06e2 | |||
| 5cf4833455 | |||
| f578fcfdc7 | |||
| 9838e1af19 | |||
| cee443e28d | |||
| 1fe57cab67 | |||
| 80b22a8444 | |||
| 71733babf8 | |||
| 9f793d6cf7 | |||
| 46e73a108f | |||
| b13ddc958b | |||
| ba3954ad3f | |||
| f2e417b21f | |||
| d93d0afdf3 | |||
| 207c9ed62e | |||
| e3f4aa3d64 | |||
| 2392c9dc8e | |||
| 682c1f5ef2 |
@@ -28,6 +28,13 @@ local.properties
|
||||
.buildpath
|
||||
|
||||
|
||||
#####################
|
||||
## Visual Studio Code
|
||||
#####################
|
||||
*.code-workspace
|
||||
.vscode/
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
@@ -147,8 +147,8 @@
|
||||
-- @image Escorting.JPG
|
||||
|
||||
|
||||
---
|
||||
-- @type AI_ESCORT
|
||||
|
||||
--- @type AI_ESCORT
|
||||
-- @extends AI.AI_Formation#AI_FORMATION
|
||||
|
||||
|
||||
@@ -168,14 +168,11 @@
|
||||
--
|
||||
-- -- First find the GROUP object and the CLIENT object.
|
||||
-- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor.
|
||||
-- local EscortGroup = SET_GROUP:New():FilterPrefixes("Escort"):FilterOnce() -- The the group name of the escorts contains "Escort".
|
||||
-- local EscortGroup = GROUP:FindByName( "Group Name" ) -- The Group Name is the name of the group that will escort the Escort Client.
|
||||
--
|
||||
-- -- Now use these 2 objects to construct the new EscortPlanes object.
|
||||
-- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
|
||||
-- EscortPlanes:MenusAirplanes() -- create menus for airplanes
|
||||
-- EscortPlanes:__Start(2)
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #AI_ESCORT
|
||||
AI_ESCORT = {
|
||||
ClassName = "AI_ESCORT",
|
||||
@@ -192,7 +189,7 @@ AI_ESCORT = {
|
||||
TaskPoints = {}
|
||||
}
|
||||
|
||||
-- @field Functional.Detection#DETECTION_AREAS
|
||||
--- @field Functional.Detection#DETECTION_AREAS
|
||||
AI_ESCORT.Detection = nil
|
||||
|
||||
--- MENUPARAM type
|
||||
@@ -214,14 +211,10 @@ AI_ESCORT.Detection = nil
|
||||
--
|
||||
-- -- First find the GROUP object and the CLIENT object.
|
||||
-- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor.
|
||||
-- local EscortGroup = SET_GROUP:New():FilterPrefixes("Escort"):FilterOnce() -- The the group name of the escorts contains "Escort".
|
||||
-- local EscortGroup = GROUP:FindByName( "Group Name" ) -- The Group Name is the name of the group that will escort the Escort Client.
|
||||
--
|
||||
-- -- Now use these 2 objects to construct the new EscortPlanes object.
|
||||
-- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
|
||||
-- EscortPlanes:MenusAirplanes() -- create menus for airplanes
|
||||
-- EscortPlanes:__Start(2)
|
||||
--
|
||||
--
|
||||
function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
|
||||
|
||||
local self = BASE:Inherit( self, AI_FORMATION:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) ) -- #AI_ESCORT
|
||||
@@ -234,17 +227,10 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
|
||||
self.EscortGroupSet = EscortGroupSet
|
||||
|
||||
self.EscortGroupSet:SetSomeIteratorLimit( 8 )
|
||||
|
||||
|
||||
self.EscortBriefing = EscortBriefing
|
||||
|
||||
self.Menu = {}
|
||||
self.Menu.HoldAtEscortPosition = self.Menu.HoldAtEscortPosition or {}
|
||||
self.Menu.HoldAtLeaderPosition = self.Menu.HoldAtLeaderPosition or {}
|
||||
self.Menu.Flare = self.Menu.Flare or {}
|
||||
self.Menu.Smoke = self.Menu.Smoke or {}
|
||||
self.Menu.Targets = self.Menu.Targets or {}
|
||||
self.Menu.ROE = self.Menu.ROE or {}
|
||||
self.Menu.ROT = self.Menu.ROT or {}
|
||||
|
||||
-- if not EscortBriefing then
|
||||
-- EscortGroup:MessageToClient( EscortGroup:GetCategoryName() .. " '" .. EscortName .. "' (" .. EscortGroup:GetCallsign() .. ") reporting! " ..
|
||||
@@ -264,7 +250,7 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
|
||||
|
||||
|
||||
EscortGroupSet:ForEachGroup(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
-- Set EscortGroup known at EscortUnit.
|
||||
if not self.PlayerUnit._EscortGroups then
|
||||
@@ -339,14 +325,14 @@ function AI_ESCORT:_InitEscortRoute( EscortGroup )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||
function AI_ESCORT:onafterStart( EscortGroupSet )
|
||||
|
||||
self:F()
|
||||
|
||||
EscortGroupSet:ForEachGroup(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
EscortGroup:WayPointInitialize()
|
||||
|
||||
@@ -384,7 +370,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
|
||||
self:_InitFlightMenus()
|
||||
|
||||
self.EscortGroupSet:ForSomeGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
|
||||
self:_InitEscortMenus( EscortGroup )
|
||||
@@ -392,7 +378,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
|
||||
|
||||
self:SetFlightModeFormation( EscortGroup )
|
||||
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function EscortGroup:OnEventDeadOrCrash( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
@@ -408,14 +394,14 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
|
||||
|
||||
end
|
||||
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||
function AI_ESCORT:onafterStop( EscortGroupSet )
|
||||
|
||||
self:F()
|
||||
|
||||
EscortGroupSet:ForEachGroup(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
EscortGroup:WayPointInitialize()
|
||||
|
||||
@@ -564,7 +550,7 @@ function AI_ESCORT:SetFlightMenuFormation( Formation )
|
||||
local MenuFlightFormationID = MENU_GROUP_COMMAND:New( self.PlayerGroup, Formation, FlightMenuFormation,
|
||||
function ( self, Formation, ... )
|
||||
self.EscortGroupSet:ForSomeGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup, self, Formation, Arguments )
|
||||
if EscortGroup:IsAir() then
|
||||
self:E({FormationID=FormationID})
|
||||
@@ -778,7 +764,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuHoldAtEscortPosition()
|
||||
|
||||
for _, MenuHoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition or {} ) do
|
||||
for _, MenuHoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition ) do
|
||||
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
|
||||
|
||||
local FlightMenuHoldPosition = MENU_GROUP_COMMAND
|
||||
@@ -799,7 +785,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuHoldAtEscortPosition( EscortGroup )
|
||||
|
||||
for _, HoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition or {}) do
|
||||
for _, HoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition ) do
|
||||
if EscortGroup:IsAir() then
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
local EscortMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", EscortGroup.EscortMenu )
|
||||
@@ -867,7 +853,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuHoldAtLeaderPosition()
|
||||
|
||||
for _, MenuHoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition or {}) do
|
||||
for _, MenuHoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition ) do
|
||||
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
|
||||
|
||||
local FlightMenuHoldAtLeaderPosition = MENU_GROUP_COMMAND
|
||||
@@ -888,7 +874,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuHoldAtLeaderPosition( EscortGroup )
|
||||
|
||||
for _, HoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition or {}) do
|
||||
for _, HoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition ) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1013,7 +999,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuFlare()
|
||||
|
||||
for _, MenuFlare in pairs( self.Menu.Flare or {}) do
|
||||
for _, MenuFlare in pairs( self.Menu.Flare) do
|
||||
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
|
||||
local FlightMenuFlare = MENU_GROUP:New( self.PlayerGroup, MenuFlare.MenuText, FlightMenuReportNavigation )
|
||||
|
||||
@@ -1028,7 +1014,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuFlare( EscortGroup )
|
||||
|
||||
for _, MenuFlare in pairs( self.Menu.Flare or {}) do
|
||||
for _, MenuFlare in pairs( self.Menu.Flare) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1073,7 +1059,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuSmoke()
|
||||
|
||||
for _, MenuSmoke in pairs( self.Menu.Smoke or {}) do
|
||||
for _, MenuSmoke in pairs( self.Menu.Smoke) do
|
||||
local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu )
|
||||
local FlightMenuSmoke = MENU_GROUP:New( self.PlayerGroup, MenuSmoke.MenuText, FlightMenuReportNavigation )
|
||||
|
||||
@@ -1090,7 +1076,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuSmoke( EscortGroup )
|
||||
|
||||
for _, MenuSmoke in pairs( self.Menu.Smoke or {}) do
|
||||
for _, MenuSmoke in pairs( self.Menu.Smoke) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1183,7 +1169,7 @@ function AI_ESCORT:SetFlightMenuTargets()
|
||||
local FlightMenuAttackNearbyAir = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest airborne targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Air ):SetTag( "Attack" )
|
||||
local FlightMenuAttackNearbyGround = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest ground targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Ground ):SetTag( "Attack" )
|
||||
|
||||
for _, MenuTargets in pairs( self.Menu.Targets or {}) do
|
||||
for _, MenuTargets in pairs( self.Menu.Targets) do
|
||||
MenuTargets.FlightReportTargetsScheduler = SCHEDULER:New( self, self._FlightReportTargetsScheduler, {}, MenuTargets.Interval, MenuTargets.Interval )
|
||||
end
|
||||
|
||||
@@ -1193,7 +1179,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuTargets( EscortGroup )
|
||||
|
||||
for _, MenuTargets in pairs( self.Menu.Targets or {} or {}) do
|
||||
for _, MenuTargets in pairs( self.Menu.Targets) do
|
||||
if EscortGroup:IsAir() then
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
--local EscortMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", EscortGroup.EscortMenu )
|
||||
@@ -1245,7 +1231,7 @@ function AI_ESCORT:MenuAssistedAttack()
|
||||
self:F()
|
||||
|
||||
self.EscortGroupSet:ForSomeGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if not EscortGroup:IsAir() then
|
||||
-- Request assistance from other escorts.
|
||||
@@ -1260,7 +1246,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuROE()
|
||||
|
||||
for _, MenuROE in pairs( self.Menu.ROE or {}) do
|
||||
for _, MenuROE in pairs( self.Menu.ROE) do
|
||||
local FlightMenuROE = MENU_GROUP:New( self.PlayerGroup, "Rule Of Engagement", self.FlightMenu )
|
||||
|
||||
local FlightMenuROEHoldFire = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Hold fire", FlightMenuROE, AI_ESCORT._FlightROEHoldFire, self, "Holding weapons!" )
|
||||
@@ -1275,7 +1261,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuROE( EscortGroup )
|
||||
|
||||
for _, MenuROE in pairs( self.Menu.ROE or {}) do
|
||||
for _, MenuROE in pairs( self.Menu.ROE) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1316,7 +1302,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetFlightMenuROT()
|
||||
|
||||
for _, MenuROT in pairs( self.Menu.ROT or {}) do
|
||||
for _, MenuROT in pairs( self.Menu.ROT) do
|
||||
local FlightMenuROT = MENU_GROUP:New( self.PlayerGroup, "Reaction On Threat", self.FlightMenu )
|
||||
|
||||
local FlightMenuROTNoReaction = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Fight until death", FlightMenuROT, AI_ESCORT._FlightROTNoReaction, self, "Fighting until death!" )
|
||||
@@ -1331,7 +1317,7 @@ end
|
||||
|
||||
function AI_ESCORT:SetEscortMenuROT( EscortGroup )
|
||||
|
||||
for _, MenuROT in pairs( self.Menu.ROT or {}) do
|
||||
for _, MenuROT in pairs( self.Menu.ROT) do
|
||||
if EscortGroup:IsAir() then
|
||||
|
||||
local EscortGroupName = EscortGroup:GetName()
|
||||
@@ -1389,7 +1375,7 @@ function AI_ESCORT:SetEscortMenuResumeMission( EscortGroup )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP OrbitGroup
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param #number OrbitHeight
|
||||
@@ -1433,7 +1419,7 @@ function AI_ESCORT:_HoldPosition( OrbitGroup, EscortGroup, OrbitHeight, OrbitSec
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP OrbitGroup
|
||||
-- @param #number OrbitHeight
|
||||
-- @param #number OrbitSeconds
|
||||
@@ -1442,7 +1428,7 @@ function AI_ESCORT:_FlightHoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds )
|
||||
local EscortUnit = self.PlayerUnit
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup, OrbitGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
if OrbitGroup == nil then
|
||||
@@ -1470,7 +1456,7 @@ end
|
||||
function AI_ESCORT:_FlightJoinUp()
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_JoinUp( EscortGroup )
|
||||
@@ -1497,7 +1483,7 @@ end
|
||||
function AI_ESCORT:_FlightFormationTrail( XStart, XSpace, YStart )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_EscortFormationTrail( EscortGroup, XStart, XSpace, YStart )
|
||||
@@ -1524,7 +1510,7 @@ end
|
||||
function AI_ESCORT:_FlightFormationStack( XStart, XSpace, YStart, YSpace )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_EscortFormationStack( EscortGroup, XStart, XSpace, YStart, YSpace )
|
||||
@@ -1547,7 +1533,7 @@ end
|
||||
function AI_ESCORT:_FlightFlare( Color, Message )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_Flare( EscortGroup, Color, Message )
|
||||
@@ -1570,7 +1556,7 @@ end
|
||||
function AI_ESCORT:_FlightSmoke( Color, Message )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_Smoke( EscortGroup, Color, Message )
|
||||
@@ -1601,7 +1587,7 @@ end
|
||||
function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets )
|
||||
@@ -1693,7 +1679,7 @@ function AI_ESCORT:_ScanTargets( ScanDuration )
|
||||
|
||||
end
|
||||
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param #AI_ESCORT self
|
||||
function AI_ESCORT.___Resume( EscortGroup, self )
|
||||
|
||||
@@ -1715,7 +1701,7 @@ function AI_ESCORT.___Resume( EscortGroup, self )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param #number WayPoint
|
||||
function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint )
|
||||
@@ -1737,7 +1723,7 @@ function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item.
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
|
||||
@@ -1757,7 +1743,7 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = EscortGroup:TaskAttackUnit( DetectedUnit )
|
||||
@@ -1781,7 +1767,7 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem )
|
||||
local Tasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
|
||||
@@ -1809,7 +1795,7 @@ end
|
||||
function AI_ESCORT:_FlightAttackTarget( DetectedItem )
|
||||
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Core.Group#GROUP EscortGroup
|
||||
function( EscortGroup, DetectedItem )
|
||||
if EscortGroup:IsAir() then
|
||||
self:_AttackTarget( EscortGroup, DetectedItem )
|
||||
@@ -1856,7 +1842,7 @@ end
|
||||
|
||||
|
||||
---
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item.
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem )
|
||||
@@ -1868,7 +1854,7 @@ function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem )
|
||||
local Tasks = {}
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit, Tasks )
|
||||
if DetectedUnit:IsAlive() then
|
||||
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
|
||||
@@ -1895,7 +1881,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROEHoldFire( EscortROEMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROE( EscortGroup, EscortGroup.OptionROEHoldFire, EscortROEMessage )
|
||||
end
|
||||
@@ -1904,7 +1890,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROEOpenFire( EscortROEMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROE( EscortGroup, EscortGroup.OptionROEOpenFire, EscortROEMessage )
|
||||
end
|
||||
@@ -1913,7 +1899,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROEReturnFire( EscortROEMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROE( EscortGroup, EscortGroup.OptionROEReturnFire, EscortROEMessage )
|
||||
end
|
||||
@@ -1922,7 +1908,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROEWeaponFree( EscortROEMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROE( EscortGroup, EscortGroup.OptionROEWeaponFree, EscortROEMessage )
|
||||
end
|
||||
@@ -1938,7 +1924,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROTNoReaction( EscortROTMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROT( EscortGroup, EscortGroup.OptionROTNoReaction, EscortROTMessage )
|
||||
end
|
||||
@@ -1947,7 +1933,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROTPassiveDefense( EscortROTMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROT( EscortGroup, EscortGroup.OptionROTPassiveDefense, EscortROTMessage )
|
||||
end
|
||||
@@ -1956,7 +1942,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROTEvadeFire( EscortROTMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROT( EscortGroup, EscortGroup.OptionROTEvadeFire, EscortROTMessage )
|
||||
end
|
||||
@@ -1965,7 +1951,7 @@ end
|
||||
|
||||
function AI_ESCORT:_FlightROTVertical( EscortROTMessage )
|
||||
self.EscortGroupSet:ForEachGroupAlive(
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
self:_ROT( EscortGroup, EscortGroup.OptionROTVertical, EscortROTMessage )
|
||||
end
|
||||
@@ -2192,3 +2178,5 @@ function AI_ESCORT:_FlightReportTargetsScheduler()
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,785 @@
|
||||
--- **Core** - Client Menu Management.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * For complex, non-static menu structures
|
||||
-- * Lightweigt implementation as alternative to MENU
|
||||
-- * Separation of menu tree creation from menu on the clients's side
|
||||
-- * Works with a SET_CLIENT set of clients
|
||||
-- * Allow manipulation of the shadow tree in various ways
|
||||
-- * Push to all or only one client
|
||||
-- * Change entries' menu text
|
||||
-- * Option to make an entry usable once only across all clients
|
||||
-- * Auto appends GROUP and CLIENT objects to menu calls
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **applevangelist**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Core.ClientMenu
|
||||
-- @image Core_Menu.JPG
|
||||
-- last change: July 2023
|
||||
|
||||
-- TODO
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- CLIENTMENU
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
---
|
||||
-- @type CLIENTMENU
|
||||
-- @field #string ClassName Class Name
|
||||
-- @field #string lid Lid for log entries
|
||||
-- @field #string version Version string
|
||||
-- @field #string name Name
|
||||
-- @field #table path
|
||||
-- @field #table parentpath
|
||||
-- @field #CLIENTMENU Parent
|
||||
-- @field Wrapper.Client#CLIENT client
|
||||
-- @field #number GroupID Group ID
|
||||
-- @field #number ID Entry ID
|
||||
-- @field Wrapper.Group#GROUP group
|
||||
-- @field #string UUID Unique ID based on path+name
|
||||
-- @field #string Function
|
||||
-- @field #table Functionargs
|
||||
-- @field #table Children
|
||||
-- @field #boolean Once
|
||||
-- @field #boolean Generic
|
||||
-- @field #boolean debug
|
||||
-- @field #CLIENTMENUMANAGER Controller
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
-- @field #CLIENTMENU
|
||||
CLIENTMENU = {
|
||||
ClassName = "CLIENTMENUE",
|
||||
lid = "",
|
||||
version = "0.1.0",
|
||||
name = nil,
|
||||
path = nil,
|
||||
group = nil,
|
||||
client = nil,
|
||||
GroupID = nil,
|
||||
Children = {},
|
||||
Once = false,
|
||||
Generic = false,
|
||||
debug = false,
|
||||
Controller = nil,
|
||||
}
|
||||
|
||||
---
|
||||
-- @field #CLIENTMENU_ID
|
||||
CLIENTMENU_ID = 0
|
||||
|
||||
--- Create an new CLIENTMENU object.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param Wrapper.Client#CLIENT Client The client for whom this entry is.
|
||||
-- @param #string Text Text of the F10 menu entry.
|
||||
-- @param #CLIENTMENU Parent The parent menu entry.
|
||||
-- @param #string Function (optional) Function to call when the entry is used.
|
||||
-- @param ... (optional) Arguments for the Function, comma separated
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:NewEntry(Client,Text,Parent,Function,...)
|
||||
-- Inherit everything from BASE class.
|
||||
local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENU
|
||||
CLIENTMENU_ID = CLIENTMENU_ID + 1
|
||||
self.ID = CLIENTMENU_ID
|
||||
if Client then
|
||||
self.group = Client:GetGroup()
|
||||
self.client = Client
|
||||
self.GroupID = self.group:GetID()
|
||||
else
|
||||
self.Generic = true
|
||||
end
|
||||
self.name = Text or "unknown entry"
|
||||
if Parent then
|
||||
if Parent:IsInstanceOf("MENU_BASE") then
|
||||
self.parentpath = Parent.MenuPath
|
||||
else
|
||||
self.parentpath = Parent:GetPath()
|
||||
Parent:AddChild(self)
|
||||
end
|
||||
end
|
||||
self.Parent = Parent
|
||||
self.Function = Function
|
||||
self.Functionargs = arg or {}
|
||||
table.insert(self.Functionargs,self.group)
|
||||
table.insert(self.Functionargs,self.client)
|
||||
if self.Functionargs and self.debug then
|
||||
self:T({"Functionargs",self.Functionargs})
|
||||
end
|
||||
if not self.Generic then
|
||||
if Function ~= nil then
|
||||
local ErrorHandler = function( errmsg )
|
||||
env.info( "MOOSE Error in CLIENTMENU COMMAND function: " .. errmsg )
|
||||
if BASE.Debug ~= nil then
|
||||
env.info( BASE.Debug.traceback() )
|
||||
end
|
||||
return errmsg
|
||||
end
|
||||
self.CallHandler = function()
|
||||
local function MenuFunction()
|
||||
return self.Function( unpack( self.Functionargs ) )
|
||||
end
|
||||
local Status, Result = xpcall( MenuFunction, ErrorHandler)
|
||||
if self.Once == true then
|
||||
self:Clear()
|
||||
end
|
||||
end
|
||||
self.path = missionCommands.addCommandForGroup(self.GroupID,Text,self.parentpath, self.CallHandler)
|
||||
else
|
||||
self.path = missionCommands.addSubMenuForGroup(self.GroupID,Text,self.parentpath)
|
||||
end
|
||||
else
|
||||
if self.parentpath then
|
||||
self.path = UTILS.DeepCopy(self.parentpath)
|
||||
else
|
||||
self.path = {}
|
||||
end
|
||||
self.path[#self.path+1] = Text
|
||||
end
|
||||
self.UUID = table.concat(self.path,";")
|
||||
self:T({self.UUID})
|
||||
self.Once = false
|
||||
-- Log id.
|
||||
self.lid=string.format("CLIENTMENU %s | %s | ", self.ID, self.name)
|
||||
self:T(self.lid.."Created")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a UUID
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param #CLIENTMENU Parent The parent object if any
|
||||
-- @param #string Text The menu entry text
|
||||
-- @return #string UUID
|
||||
function CLIENTMENU:CreateUUID(Parent,Text)
|
||||
local path = {}
|
||||
if Parent and Parent.path then
|
||||
path = Parent.path
|
||||
end
|
||||
path[#path+1] = Text
|
||||
local UUID = table.concat(path,";")
|
||||
return UUID
|
||||
end
|
||||
|
||||
--- Set the CLIENTMENUMANAGER for this entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param #CLIENTMENUMANAGER Controller The controlling object.
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:SetController(Controller)
|
||||
self.Controller = Controller
|
||||
return self
|
||||
end
|
||||
|
||||
--- The entry will be deleted after being used used - for menu entries with functions only.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:SetOnce()
|
||||
self:T(self.lid.."SetOnce")
|
||||
self.Once = true
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove the entry from the F10 menu.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:RemoveF10()
|
||||
self:T(self.lid.."RemoveF10")
|
||||
if self.GroupID then
|
||||
--self:I(self.lid.."Removing "..table.concat(self.path,";"))
|
||||
missionCommands.removeItemForGroup(self.GroupID , self.path )
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get the menu path table.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #table Path
|
||||
function CLIENTMENU:GetPath()
|
||||
self:T(self.lid.."GetPath")
|
||||
return self.path
|
||||
end
|
||||
|
||||
--- Get the UUID.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #string UUID
|
||||
function CLIENTMENU:GetUUID()
|
||||
self:T(self.lid.."GetUUID")
|
||||
return self.UUID
|
||||
end
|
||||
|
||||
--- Link a child entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param #CLIENTMENU Child The entry to link as a child.
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:AddChild(Child)
|
||||
self:T(self.lid.."AddChild "..Child.ID)
|
||||
table.insert(self.Children,Child.ID,Child)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove a child entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param #CLIENTMENU Child The entry to remove from the children.
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:RemoveChild(Child)
|
||||
self:T(self.lid.."RemoveChild "..Child.ID)
|
||||
table.remove(self.Children,Child.ID)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove all subentries (children) from this entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:RemoveSubEntries()
|
||||
self:T(self.lid.."RemoveSubEntries")
|
||||
self:T({self.Children})
|
||||
for _id,_entry in pairs(self.Children) do
|
||||
self:T("Removing ".._id)
|
||||
if _entry then
|
||||
_entry:RemoveSubEntries()
|
||||
_entry:RemoveF10()
|
||||
if _entry.Parent then
|
||||
_entry.Parent:RemoveChild(self)
|
||||
end
|
||||
--if self.Controller then
|
||||
--self.Controller:_RemoveByID(_entry.ID)
|
||||
--end
|
||||
--_entry = nil
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove this entry and all subentries (children) from this entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:Clear()
|
||||
self:T(self.lid.."Clear")
|
||||
for _id,_entry in pairs(self.Children) do
|
||||
if _entry then
|
||||
_entry:RemoveSubEntries()
|
||||
_entry = nil
|
||||
end
|
||||
end
|
||||
self:RemoveF10()
|
||||
if self.Parent then
|
||||
self.Parent:RemoveChild(self)
|
||||
end
|
||||
--if self.Controller then
|
||||
--self.Controller:_RemoveByID(self.ID)
|
||||
--end
|
||||
return self
|
||||
end
|
||||
|
||||
-- TODO
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- CLIENTMENUMANAGER
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
--- Class CLIENTMENUMANAGER
|
||||
-- @type CLIENTMENUMANAGER
|
||||
-- @field #string ClassName Class Name
|
||||
-- @field #string lid Lid for log entries
|
||||
-- @field #string version Version string
|
||||
-- @field #string name Name
|
||||
-- @field Core.Set#SET_CLIENT clientset The set of clients this menu manager is for
|
||||
-- @field #table flattree
|
||||
-- @field #table rootentries
|
||||
-- @field #table menutree
|
||||
-- @field #number entrycount
|
||||
-- @field #boolean debug
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *As a child my family's menu consisted of two choices: take it, or leave it.*
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## CLIENTMENU and CLIENTMENUMANAGER
|
||||
--
|
||||
-- Manage menu structures for a SET_CLIENT of clients.
|
||||
--
|
||||
-- ## Concept
|
||||
--
|
||||
-- Separate creation of a menu tree structure from pushing it to each client. Create a shadow "reference" menu structure tree for your client pilot's in a mission.
|
||||
-- This can then be propagated to all clients. Manipulate the entries in the structure with removing, clearing or changing single entries, create replacement sub-structures
|
||||
-- for entries etc, push to one or all clients.
|
||||
--
|
||||
-- Many functions can either change the tree for one client or for all clients.
|
||||
--
|
||||
-- ## Create a base reference tree and send to all clients
|
||||
--
|
||||
-- local clientset = SET_CLIENT:New():FilterStart()
|
||||
--
|
||||
-- local menumgr = CLIENTMENUMANAGER:New(clientset,"Dayshift")
|
||||
-- local mymenu = menumgr:NewEntry("Top")
|
||||
-- local mymenu_lv1a = menumgr:NewEntry("Level 1 a",mymenu)
|
||||
-- local mymenu_lv1b = menumgr:NewEntry("Level 1 b",mymenu)
|
||||
-- -- next one is a command menu entry, which can only be used once
|
||||
-- local mymenu_lv1c = menumgr:NewEntry("Action Level 1 c",mymenu, testfunction, "testtext"):SetOnce()
|
||||
--
|
||||
-- local mymenu_lv2a = menumgr:NewEntry("Go here",mymenu_lv1a)
|
||||
-- local mymenu_lv2b = menumgr:NewEntry("Level 2 ab",mymenu_lv1a)
|
||||
-- local mymenu_lv2c = menumgr:NewEntry("Level 2 ac",mymenu_lv1a)
|
||||
--
|
||||
-- local mymenu_lv2ba = menumgr:NewEntry("Level 2 ba",mymenu_lv1b)
|
||||
-- local mymenu_lv2bb = menumgr:NewEntry("Level 2 bb",mymenu_lv1b)
|
||||
-- local mymenu_lv2bc = menumgr:NewEntry("Level 2 bc",mymenu_lv1b)
|
||||
--
|
||||
-- local mymenu_lv3a = menumgr:NewEntry("Level 3 aaa",mymenu_lv2a)
|
||||
-- local mymenu_lv3b = menumgr:NewEntry("Level 3 aab",mymenu_lv2a)
|
||||
-- local mymenu_lv3c = menumgr:NewEntry("Level 3 aac",mymenu_lv2a)
|
||||
--
|
||||
-- menumgr:Propagate()
|
||||
--
|
||||
-- ## Remove a single entry's subtree
|
||||
--
|
||||
-- menumgr:RemoveSubEntries(mymenu_lv3a)
|
||||
--
|
||||
-- ## Remove a single entry and also it's subtree
|
||||
--
|
||||
-- menumgr:DeleteEntry(mymenu_lv3a)
|
||||
--
|
||||
-- ## Add a single entry
|
||||
--
|
||||
-- local baimenu = menumgr:NewEntry("BAI",mymenu_lv1b)
|
||||
--
|
||||
-- menumgr:AddEntry(baimenu)
|
||||
--
|
||||
-- ## Add an entry with a function
|
||||
--
|
||||
-- local baimenu = menumgr:NewEntry("Task Action", mymenu_lv1b, TestFunction, Argument1, Argument1)
|
||||
--
|
||||
-- Now, the class will **automatically append the call with GROUP and CLIENT objects**, as this is can only be done when pushing the entry to the clients. So, the actual function implementation needs to look like this:
|
||||
--
|
||||
-- function TestFunction( Argument1, Argument2, Group, Client)
|
||||
--
|
||||
-- **Caveat is**, that you need to ensure your arguments are not **nil** or **false**, as LUA will optimize those away. You would end up having Group and Client in wrong places in the function call. Hence,
|
||||
-- if you need/ want to send **nil** or **false**, send a place holder instead and ensure your function can handle this, e.g.
|
||||
--
|
||||
-- local baimenu = menumgr:NewEntry("Task Action", mymenu_lv1b, TestFunction, "nil", Argument1)
|
||||
--
|
||||
-- ## Change the text of a leaf entry in the menu tree
|
||||
--
|
||||
-- menumgr:ChangeEntryTextForAll(mymenu_lv1b,"Attack")
|
||||
--
|
||||
-- ## Reset a single clients menu tree
|
||||
--
|
||||
-- menumgr:ResetMenu(client)
|
||||
--
|
||||
-- ## Reset all and clear the reference tree
|
||||
--
|
||||
-- menumgr:ResetMenuComplete()
|
||||
--
|
||||
-- @field #CLIENTMENUMANAGER
|
||||
CLIENTMENUMANAGER = {
|
||||
ClassName = "CLIENTMENUMANAGER",
|
||||
lid = "",
|
||||
version = "0.1.0",
|
||||
name = nil,
|
||||
clientset = nil,
|
||||
menutree = {},
|
||||
flattree = {},
|
||||
playertree = {},
|
||||
entrycount = 0,
|
||||
rootentries = {},
|
||||
debug = true,
|
||||
}
|
||||
|
||||
--- Create a new ClientManager instance.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param Core.Set#SET_CLIENT ClientSet The set of clients to manage.
|
||||
-- @param #string Alias The name of this manager.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:New(ClientSet, Alias)
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENUMANAGER
|
||||
self.clientset = ClientSet
|
||||
self.name = Alias or "Nightshift"
|
||||
-- Log id.
|
||||
self.lid=string.format("CLIENTMENUMANAGER %s | %s | ", self.version, self.name)
|
||||
if self.debug then
|
||||
self:T(self.lid.."Created")
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a new entry in the generic structure.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string Text Text of the F10 menu entry.
|
||||
-- @param #CLIENTMENU Parent The parent menu entry.
|
||||
-- @param #string Function (optional) Function to call when the entry is used.
|
||||
-- @param ... (optional) Arguments for the Function, comma separated.
|
||||
-- @return #CLIENTMENU Entry
|
||||
function CLIENTMENUMANAGER:NewEntry(Text,Parent,Function,...)
|
||||
self:T(self.lid.."NewEntry "..Text or "None")
|
||||
self.entrycount = self.entrycount + 1
|
||||
local entry = CLIENTMENU:NewEntry(nil,Text,Parent,Function,unpack(arg))
|
||||
if not Parent then
|
||||
self.rootentries[self.entrycount] = entry
|
||||
end
|
||||
local depth = #entry.path
|
||||
if not self.menutree[depth] then self.menutree[depth] = {} end
|
||||
table.insert(self.menutree[depth],entry.UUID)
|
||||
self.flattree[entry.UUID] = entry
|
||||
return entry
|
||||
end
|
||||
|
||||
--- Check matching entry in the generic structure by UUID.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string UUID UUID of the menu entry.
|
||||
-- @return #boolean Exists
|
||||
function CLIENTMENUMANAGER:EntryUUIDExists(UUID)
|
||||
local exists = self.flattree[UUID] and true or false
|
||||
return exists
|
||||
end
|
||||
|
||||
--- Find matching entry in the generic structure by UUID.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string UUID UUID of the menu entry.
|
||||
-- @return #CLIENTMENU Entry The #CLIENTMENU object found or nil.
|
||||
function CLIENTMENUMANAGER:FindEntryByUUID(UUID)
|
||||
self:T(self.lid.."FindEntryByUUID "..UUID or "None")
|
||||
local entry = nil
|
||||
for _gid,_entry in pairs(self.flattree) do
|
||||
local Entry = _entry -- #CLIENTMENU
|
||||
if Entry and Entry.UUID == UUID then
|
||||
entry = Entry
|
||||
end
|
||||
end
|
||||
return entry
|
||||
end
|
||||
|
||||
--- Find matching entries by text in the generic structure by UUID.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string Text Text or partial text of the menu entry to find.
|
||||
-- @param #CLIENTMENU Parent (Optional) Only find entries under this parent entry.
|
||||
-- @return #table Table of matching UUIDs of #CLIENTMENU objects
|
||||
-- @return #table Table of matching #CLIENTMENU objects
|
||||
-- @return #number Number of matches
|
||||
function CLIENTMENUMANAGER:FindUUIDsByText(Text,Parent)
|
||||
self:T(self.lid.."FindUUIDsByText "..Text or "None")
|
||||
local matches = {}
|
||||
local entries = {}
|
||||
local n = 0
|
||||
for _uuid,_entry in pairs(self.flattree) do
|
||||
local Entry = _entry -- #CLIENTMENU
|
||||
if Parent then
|
||||
if Entry and string.find(Entry.name,Text) and string.find(Entry.UUID,Parent.UUID) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
end
|
||||
else
|
||||
if Entry and string.find(Entry.name,Text) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
end
|
||||
end
|
||||
end
|
||||
return matches, entries, n
|
||||
end
|
||||
|
||||
--- Find matching entries in the generic structure by the menu text.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string Text Text or partial text of the F10 menu entry.
|
||||
-- @param #CLIENTMENU Parent (Optional) Only find entries under this parent entry.
|
||||
-- @return #table Table of matching #CLIENTMENU objects.
|
||||
-- @return #number Number of matches
|
||||
function CLIENTMENUMANAGER:FindEntriesByText(Text,Parent)
|
||||
self:T(self.lid.."FindEntriesByText "..Text or "None")
|
||||
local matches, objects, number = self:FindUUIDsByText(Text, Parent)
|
||||
return objects, number
|
||||
end
|
||||
|
||||
--- Find matching entries under a parent in the generic structure by UUID.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Parent Find entries under this parent entry.
|
||||
-- @return #table Table of matching UUIDs of #CLIENTMENU objects
|
||||
-- @return #table Table of matching #CLIENTMENU objects
|
||||
-- @return #number Number of matches
|
||||
function CLIENTMENUMANAGER:FindUUIDsByParent(Parent)
|
||||
self:T(self.lid.."FindUUIDsByParent")
|
||||
local matches = {}
|
||||
local entries = {}
|
||||
local n = 0
|
||||
for _uuid,_entry in pairs(self.flattree) do
|
||||
local Entry = _entry -- #CLIENTMENU
|
||||
if Parent then
|
||||
if Entry and string.find(Entry.UUID,Parent.UUID) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
end
|
||||
end
|
||||
end
|
||||
return matches, entries, n
|
||||
end
|
||||
|
||||
--- Find matching entries in the generic structure under a parent.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Parent Find entries under this parent entry.
|
||||
-- @return #table Table of matching #CLIENTMENU objects.
|
||||
-- @return #number Number of matches
|
||||
function CLIENTMENUMANAGER:FindEntriesByParent(Parent)
|
||||
self:T(self.lid.."FindEntriesByParent")
|
||||
local matches, objects, number = self:FindUUIDsByParent(Parent)
|
||||
return objects, number
|
||||
end
|
||||
|
||||
--- Alter the text of a leaf entry in the generic structure and push to one specific client's F10 menu.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The menu entry.
|
||||
-- @param #string Text New Text of the F10 menu entry.
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) The client for whom to alter the entry, if nil done for all clients.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:ChangeEntryText(Entry, Text, Client)
|
||||
self:T(self.lid.."ChangeEntryText "..Text or "None")
|
||||
local newentry = CLIENTMENU:NewEntry(nil,Text,Entry.Parent,Entry.Function,unpack(Entry.Functionargs))
|
||||
self:DeleteF10Entry(Entry,Client)
|
||||
self:DeleteGenericEntry(Entry)
|
||||
if not Entry.Parent then
|
||||
self.rootentries[self.entrycount] = newentry
|
||||
end
|
||||
local depth = #newentry.path
|
||||
if not self.menutree[depth] then self.menutree[depth] = {} end
|
||||
table.insert(self.menutree[depth],newentry.UUID)
|
||||
self.flattree[newentry.UUID] = newentry
|
||||
self:AddEntry(newentry,Client)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Push the complete menu structure to each of the clients in the set - refresh the menu tree of the clients.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, propagate only for this client.
|
||||
-- @return #CLIENTMENU Entry
|
||||
function CLIENTMENUMANAGER:Propagate(Client)
|
||||
self:T(self.lid.."Propagate")
|
||||
self:T(Client)
|
||||
local Set = self.clientset.Set
|
||||
if Client then
|
||||
Set = {Client}
|
||||
end
|
||||
self:ResetMenu(Client)
|
||||
for _,_client in pairs(Set) do
|
||||
local client = _client -- Wrapper.Client#CLIENT
|
||||
if client and client:IsAlive() then
|
||||
local playername = client:GetPlayerName()
|
||||
if not self.playertree[playername] then
|
||||
self.playertree[playername] = {}
|
||||
end
|
||||
for level,branch in pairs (self.menutree) do
|
||||
self:T("Building branch:" .. level)
|
||||
for _,leaf in pairs(branch) do
|
||||
self:T("Building leaf:" .. leaf)
|
||||
local entry = self:FindEntryByUUID(leaf)
|
||||
if entry then
|
||||
self:T("Found generic entry:" .. entry.UUID)
|
||||
local parent = nil
|
||||
if entry.Parent and entry.Parent.UUID then
|
||||
parent = self.playertree[playername][entry.Parent.UUID] or self:FindEntryByUUID(entry.Parent.UUID)
|
||||
end
|
||||
self.playertree[playername][entry.UUID] = CLIENTMENU:NewEntry(client,entry.name,parent,entry.Function,unpack(entry.Functionargs))
|
||||
self.playertree[playername][entry.UUID].Once = entry.Once
|
||||
else
|
||||
self:T("NO generic entry for:" .. leaf)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Push a single previously created entry into the menu structure of all clients.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry to add.
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:AddEntry(Entry,Client)
|
||||
self:T(self.lid.."AddEntry")
|
||||
local Set = self.clientset.Set
|
||||
if Client then
|
||||
Set = {Client}
|
||||
end
|
||||
for _,_client in pairs(Set) do
|
||||
local client = _client -- Wrapper.Client#CLIENT
|
||||
if client and client:IsAlive() then
|
||||
local playername = client:GetPlayerName()
|
||||
if Entry then
|
||||
self:T("Adding generic entry:" .. Entry.UUID)
|
||||
local parent = nil
|
||||
if not self.playertree[playername] then
|
||||
self.playertree[playername] = {}
|
||||
end
|
||||
if Entry.Parent and Entry.Parent.UUID then
|
||||
parent = self.playertree[playername][Entry.Parent.UUID] or self:FindEntryByUUID(Entry.Parent.UUID)
|
||||
end
|
||||
self.playertree[playername][Entry.UUID] = CLIENTMENU:NewEntry(client,Entry.name,parent,Entry.Function,unpack(Entry.Functionargs))
|
||||
self.playertree[playername][Entry.UUID].Once = Entry.Once
|
||||
else
|
||||
self:T("NO generic entry given")
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Blank out the menu - remove **all root entries** and all entries below from the client's F10 menus, leaving the generic structure untouched.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, remove only for this client.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:ResetMenu(Client)
|
||||
self:T(self.lid.."ResetMenu")
|
||||
for _,_entry in pairs(self.rootentries) do
|
||||
--local RootEntry = self.structure.generic[_entry]
|
||||
if _entry then
|
||||
self:DeleteF10Entry(_entry,Client)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Blank out the menu - remove **all root entries** and all entries below from all clients' F10 menus, and **delete** the generic structure.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:ResetMenuComplete()
|
||||
self:T(self.lid.."ResetMenuComplete")
|
||||
for _,_entry in pairs(self.rootentries) do
|
||||
--local RootEntry = self.structure.generic[_entry]
|
||||
if _entry then
|
||||
self:DeleteF10Entry(_entry)
|
||||
end
|
||||
end
|
||||
self.playertree = nil
|
||||
self.playertree = {}
|
||||
self.rootentries = nil
|
||||
self.rootentries = {}
|
||||
self.menutree = nil
|
||||
self.menutree = {}
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove the entry and all entries below the given entry from the client's F10 menus.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry to remove
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client. In this case the generic structure will not be touched.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:DeleteF10Entry(Entry,Client)
|
||||
self:T(self.lid.."DeleteF10Entry")
|
||||
local Set = self.clientset.Set
|
||||
if Client then
|
||||
Set = {Client}
|
||||
end
|
||||
for _,_client in pairs(Set) do
|
||||
if _client and _client:IsAlive() then
|
||||
local playername = _client:GetPlayerName()
|
||||
if self.playertree[playername] then
|
||||
local centry = self.playertree[playername][Entry.UUID] -- #CLIENTMENU
|
||||
if centry then
|
||||
--self:I("Match for "..Entry.UUID)
|
||||
centry:Clear()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove the entry and all entries below the given entry from the generic tree.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry to remove
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:DeleteGenericEntry(Entry)
|
||||
self:T(self.lid.."DeleteGenericEntry")
|
||||
|
||||
if Entry.Children and #Entry.Children > 0 then
|
||||
self:RemoveGenericSubEntries(Entry)
|
||||
end
|
||||
|
||||
local depth = #Entry.path
|
||||
local uuid = Entry.UUID
|
||||
|
||||
local tbl = UTILS.DeepCopy(self.menutree)
|
||||
|
||||
if tbl[depth] then
|
||||
for i=depth,#tbl do
|
||||
--self:I("Level = "..i)
|
||||
for _id,_uuid in pairs(tbl[i]) do
|
||||
self:T(_uuid)
|
||||
if string.find(_uuid,uuid) or _uuid == uuid then
|
||||
--self:I("Match for ".._uuid)
|
||||
self.menutree[i][_id] = nil
|
||||
self.flattree[_uuid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove all entries below the given entry from the generic tree.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry where to start. This entry stays.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:RemoveGenericSubEntries(Entry)
|
||||
self:T(self.lid.."RemoveGenericSubEntries")
|
||||
|
||||
local depth = #Entry.path + 1
|
||||
local uuid = Entry.UUID
|
||||
|
||||
local tbl = UTILS.DeepCopy(self.menutree)
|
||||
|
||||
if tbl[depth] then
|
||||
for i=depth,#tbl do
|
||||
self:T("Level = "..i)
|
||||
for _id,_uuid in pairs(tbl[i]) do
|
||||
self:T(_uuid)
|
||||
if string.find(_uuid,uuid) then
|
||||
self:T("Match for ".._uuid)
|
||||
self.menutree[i][_id] = nil
|
||||
self.flattree[_uuid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Remove all entries below the given entry from the client's F10 menus.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry where to start. This entry stays.
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client. In this case the generic structure will not be touched.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:RemoveF10SubEntries(Entry,Client)
|
||||
self:T(self.lid.."RemoveSubEntries")
|
||||
local Set = self.clientset.Set
|
||||
if Client then
|
||||
Set = {Client}
|
||||
end
|
||||
for _,_client in pairs(Set) do
|
||||
if _client and _client:IsAlive() then
|
||||
local playername = _client:GetPlayerName()
|
||||
if self.playertree[playername] then
|
||||
local centry = self.playertree[playername][Entry.UUID] -- #CLIENTMENU
|
||||
centry:RemoveSubEntries()
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- End ClientMenu
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
@@ -32,12 +32,10 @@
|
||||
-- @image Core_Database.JPG
|
||||
|
||||
|
||||
--- DATABASE class.
|
||||
-- @type DATABASE
|
||||
--- @type DATABASE
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #table Templates Templates: Units, Groups, Statics, ClientsByName, ClientsByID.
|
||||
-- @field #table CLIENTS Clients.
|
||||
-- @field #table STORAGES DCS warehouse storages.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator.
|
||||
@@ -52,7 +50,6 @@
|
||||
-- * PLAYERSJOINED
|
||||
-- * PLAYERS
|
||||
-- * CARGOS
|
||||
-- * STORAGES (DCS warehouses)
|
||||
--
|
||||
-- On top, for internal MOOSE administration purposes, the DATABASE administers the Unit and Group TEMPLATES as defined within the Mission Editor.
|
||||
--
|
||||
@@ -93,7 +90,6 @@ DATABASE = {
|
||||
FLIGHTCONTROLS = {},
|
||||
OPSZONES = {},
|
||||
PATHLINES = {},
|
||||
STORAGES = {},
|
||||
}
|
||||
|
||||
local _DATABASECoalition =
|
||||
@@ -250,38 +246,6 @@ function DATABASE:FindAirbase( AirbaseName )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Adds a STORAGE (DCS warehouse wrapper) based on the Airbase Name to the DATABASE.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string AirbaseName The name of the airbase.
|
||||
-- @return Wrapper.Storage#STORAGE Storage object.
|
||||
function DATABASE:AddStorage( AirbaseName )
|
||||
|
||||
if not self.STORAGES[AirbaseName] then
|
||||
self.STORAGES[AirbaseName] = STORAGE:New( AirbaseName )
|
||||
end
|
||||
|
||||
return self.STORAGES[AirbaseName]
|
||||
end
|
||||
|
||||
|
||||
--- Deletes a STORAGE from the DATABASE based on the name of the associated airbase.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string AirbaseName The name of the airbase.
|
||||
function DATABASE:DeleteStorage( AirbaseName )
|
||||
self.STORAGES[AirbaseName] = nil
|
||||
end
|
||||
|
||||
|
||||
--- Finds an STORAGE based on the name of the associated airbase.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string AirbaseName Name of the airbase.
|
||||
-- @return Wrapper.Storage#STORAGE The found STORAGE.
|
||||
function DATABASE:FindStorage( AirbaseName )
|
||||
local storage = self.STORAGES[AirbaseName]
|
||||
return storage
|
||||
end
|
||||
|
||||
do -- Zones and Pathlines
|
||||
|
||||
--- Finds a @{Core.Zone} based on the zone name.
|
||||
|
||||
@@ -676,7 +676,7 @@ do -- COORDINATE
|
||||
local _,_,_,_,_,scenerys=self:ScanObjects(radius, false, false, true)
|
||||
|
||||
local set={}
|
||||
|
||||
|
||||
for _,_scenery in pairs(scenerys) do
|
||||
local scenery=_scenery --DCS#Object
|
||||
|
||||
@@ -2389,6 +2389,7 @@ do -- COORDINATE
|
||||
end
|
||||
|
||||
--- Creates a free form shape on the F10 map. The first point is the current COORDINATE. The remaining points need to be specified.
|
||||
-- **NOTE**: A free form polygon must have **at least three points** in total and currently only **up to 15 points** in total are supported.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #table Coordinates Table of coordinates of the remaining points of the shape.
|
||||
-- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All.
|
||||
@@ -2462,30 +2463,9 @@ do -- COORDINATE
|
||||
vecs[11], vecs[12], vecs[13], vecs[14], vecs[15],
|
||||
Color, FillColor, LineType, ReadOnly, Text or "")
|
||||
else
|
||||
|
||||
self:E("ERROR: Currently a free form polygon can only have 15 points in total!")
|
||||
-- Unfortunately, unpack(vecs) does not work! So no idea how to generalize this :(
|
||||
--trigger.action.markupToAll(7, Coalition, MarkID, unpack(vecs), Color, FillColor, LineType, ReadOnly, Text or "")
|
||||
|
||||
-- Write command as string and execute that. Idea by Grimes https://forum.dcs.world/topic/324201-mark-to-all-function/#comment-5273793
|
||||
local s=string.format("trigger.action.markupToAll(7, %d, %d,", Coalition, MarkID)
|
||||
for _,vec in pairs(vecs) do
|
||||
s=s..string.format("%s,", UTILS._OneLineSerialize(vec))
|
||||
end
|
||||
s=s..string.format("%s, %s, %s, %s", UTILS._OneLineSerialize(Color), UTILS._OneLineSerialize(FillColor), tostring(LineType), tostring(ReadOnly))
|
||||
if Text and Text~="" then
|
||||
s=s..string.format(", \"%s\"", Text)
|
||||
end
|
||||
s=s..")"
|
||||
|
||||
|
||||
-- Execute string command
|
||||
local success=UTILS.DoString(s)
|
||||
|
||||
if not success then
|
||||
self:E("ERROR: Could not draw polygon")
|
||||
env.info(s)
|
||||
end
|
||||
|
||||
trigger.action.markupToAll(7, Coalition, MarkID, unpack(vecs), Color, FillColor, LineType, ReadOnly, Text or "")
|
||||
end
|
||||
|
||||
return MarkID
|
||||
|
||||
@@ -46,9 +46,8 @@
|
||||
-- @image Core_Sets.JPG
|
||||
|
||||
do -- SET_BASE
|
||||
|
||||
---
|
||||
-- @type SET_BASE
|
||||
|
||||
--- @type SET_BASE
|
||||
-- @field #table Filter Table of filters.
|
||||
-- @field #table Set Table of objects.
|
||||
-- @field #table Index Table of indices.
|
||||
@@ -243,7 +242,7 @@ do -- SET_BASE
|
||||
function SET_BASE:Add( ObjectName, Object )
|
||||
|
||||
-- Debug info.
|
||||
self:T2( { ObjectName = ObjectName, Object = Object } )
|
||||
self:T( { ObjectName = ObjectName, Object = Object } )
|
||||
|
||||
-- Ensure that the existing element is removed from the Set before a new one is inserted to the Set
|
||||
if self.Set[ObjectName] then
|
||||
@@ -258,8 +257,6 @@ do -- SET_BASE
|
||||
|
||||
-- Trigger Added event.
|
||||
self:Added( ObjectName, Object )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using the Object Name as the index.
|
||||
@@ -581,8 +578,8 @@ do -- SET_BASE
|
||||
end
|
||||
|
||||
----- Private method that registers all alive players in the mission.
|
||||
-- @param #SET_BASE self
|
||||
-- @return #SET_BASE self
|
||||
---- @param #SET_BASE self
|
||||
---- @return #SET_BASE self
|
||||
-- function SET_BASE:_RegisterPlayers()
|
||||
--
|
||||
-- local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) }
|
||||
@@ -799,8 +796,8 @@ do -- SET_BASE
|
||||
|
||||
|
||||
----- Iterate the SET_BASE and call an iterator function for each **alive** unit, providing the Unit and optional parameters.
|
||||
-- @param #SET_BASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive unit in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive unit in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_BASE self
|
||||
-- function SET_BASE:ForEachDCSUnitAlive( IteratorFunction, ... )
|
||||
-- self:F3( arg )
|
||||
@@ -811,8 +808,8 @@ do -- SET_BASE
|
||||
-- end
|
||||
--
|
||||
----- Iterate the SET_BASE and call an iterator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
-- @param #SET_BASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_BASE self
|
||||
-- function SET_BASE:ForEachPlayer( IteratorFunction, ... )
|
||||
-- self:F3( arg )
|
||||
@@ -824,8 +821,8 @@ do -- SET_BASE
|
||||
--
|
||||
--
|
||||
----- Iterate the SET_BASE and call an iterator function for each client, providing the Client to the function and optional parameters.
|
||||
-- @param #SET_BASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a CLIENT parameter.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_BASE self
|
||||
-- function SET_BASE:ForEachClient( IteratorFunction, ... )
|
||||
-- self:F3( arg )
|
||||
@@ -904,12 +901,9 @@ do -- SET_BASE
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
do -- SET_GROUP
|
||||
|
||||
-- SET_GROUP
|
||||
|
||||
---
|
||||
-- @type SET_GROUP #SET_GROUP
|
||||
--- @type SET_GROUP #SET_GROUP
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
@@ -1574,7 +1568,7 @@ do
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Group#GROUP GroupObject
|
||||
function( ZoneObject, GroupObject )
|
||||
if GroupObject:IsCompletelyInZone( ZoneObject ) then
|
||||
@@ -1596,7 +1590,7 @@ do
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Group#GROUP GroupObject
|
||||
function( ZoneObject, GroupObject )
|
||||
if GroupObject:IsPartlyInZone( ZoneObject ) then
|
||||
@@ -1618,7 +1612,7 @@ do
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Group#GROUP GroupObject
|
||||
function( ZoneObject, GroupObject )
|
||||
if GroupObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -1665,7 +1659,7 @@ do
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Group#GROUP GroupObject
|
||||
function( ZoneObject, GroupObject )
|
||||
if GroupObject:IsAnyInZone( ZoneObject ) then
|
||||
@@ -1863,8 +1857,8 @@ do
|
||||
end
|
||||
|
||||
----- Iterate the SET_GROUP and call an iterator function for each **alive** player, providing the Group of the player and optional parameters.
|
||||
-- @param #SET_GROUP self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a GROUP parameter.
|
||||
---- @param #SET_GROUP self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a GROUP parameter.
|
||||
---- @return #SET_GROUP self
|
||||
-- function SET_GROUP:ForEachPlayer( IteratorFunction, ... )
|
||||
-- self:F2( arg )
|
||||
@@ -1876,8 +1870,8 @@ do
|
||||
--
|
||||
--
|
||||
----- Iterate the SET_GROUP and call an iterator function for each client, providing the Client to the function and optional parameters.
|
||||
-- @param #SET_GROUP self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a CLIENT parameter.
|
||||
---- @param #SET_GROUP self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_GROUP self
|
||||
-- function SET_GROUP:ForEachClient( IteratorFunction, ... )
|
||||
-- self:F2( arg )
|
||||
@@ -1951,7 +1945,7 @@ do
|
||||
if self.Filter.Zones then
|
||||
local MGroupZone = false
|
||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||
--self:T( "Zone:", ZoneName )
|
||||
--self:I( "Zone:", ZoneName )
|
||||
if MGroup:IsInZone(Zone) then
|
||||
MGroupZone = true
|
||||
end
|
||||
@@ -2017,9 +2011,8 @@ do
|
||||
end
|
||||
|
||||
do -- SET_UNIT
|
||||
|
||||
---
|
||||
-- @type SET_UNIT
|
||||
|
||||
--- @type SET_UNIT
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
@@ -2679,7 +2672,7 @@ do -- SET_UNIT
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Unit#UNIT UnitObject
|
||||
function( ZoneObject, UnitObject )
|
||||
if UnitObject:IsInZone( ZoneObject ) then
|
||||
@@ -2701,7 +2694,7 @@ do -- SET_UNIT
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Unit#UNIT UnitObject
|
||||
function( ZoneObject, UnitObject )
|
||||
if UnitObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -3018,8 +3011,8 @@ do -- SET_UNIT
|
||||
|
||||
|
||||
----- Iterate the SET_UNIT and call an iterator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
-- @param #SET_UNIT self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a UNIT parameter.
|
||||
---- @param #SET_UNIT self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_UNIT self
|
||||
-- function SET_UNIT:ForEachPlayer( IteratorFunction, ... )
|
||||
-- self:F2( arg )
|
||||
@@ -3031,8 +3024,8 @@ do -- SET_UNIT
|
||||
--
|
||||
--
|
||||
----- Iterate the SET_UNIT and call an iterator function for each client, providing the Client to the function and optional parameters.
|
||||
-- @param #SET_UNIT self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a CLIENT parameter.
|
||||
---- @param #SET_UNIT self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_UNIT self
|
||||
-- function SET_UNIT:ForEachClient( IteratorFunction, ... )
|
||||
-- self:F2( arg )
|
||||
@@ -3047,7 +3040,7 @@ do -- SET_UNIT
|
||||
-- @param Wrapper.Unit#UNIT MUnit
|
||||
-- @return #SET_UNIT self
|
||||
function SET_UNIT:IsIncludeObject( MUnit )
|
||||
self:F2( {MUnit} )
|
||||
self:F2( MUnit )
|
||||
|
||||
local MUnitInclude = false
|
||||
|
||||
@@ -3198,9 +3191,8 @@ do -- SET_UNIT
|
||||
end
|
||||
|
||||
do -- SET_STATIC
|
||||
|
||||
---
|
||||
-- @type SET_STATIC
|
||||
|
||||
--- @type SET_STATIC
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the SET_STATIC class to build sets of Statics belonging to certain:
|
||||
@@ -3620,7 +3612,7 @@ do -- SET_STATIC
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Static#STATIC StaticObject
|
||||
function( ZoneObject, StaticObject )
|
||||
if StaticObject:IsInZone( ZoneObject ) then
|
||||
@@ -3642,7 +3634,7 @@ do -- SET_STATIC
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Static#STATIC StaticObject
|
||||
function( ZoneObject, StaticObject )
|
||||
if StaticObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -3953,9 +3945,8 @@ do -- SET_STATIC
|
||||
end
|
||||
|
||||
do -- SET_CLIENT
|
||||
|
||||
---
|
||||
-- @type SET_CLIENT
|
||||
|
||||
--- @type SET_CLIENT
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
@@ -4017,8 +4008,8 @@ do -- SET_CLIENT
|
||||
Countries = nil,
|
||||
ClientPrefixes = nil,
|
||||
Zones = nil,
|
||||
Playernames = nil,
|
||||
Callsigns = nil,
|
||||
Playernames = nil,
|
||||
Callsigns = nil,
|
||||
},
|
||||
FilterMeta = {
|
||||
Coalitions = {
|
||||
@@ -4068,7 +4059,7 @@ do -- SET_CLIENT
|
||||
|
||||
--- Remove CLIENT(s) from SET_CLIENT.
|
||||
-- @param Core.Set#SET_CLIENT self
|
||||
-- @param Wrapper.Client#CLIENT RemoveClientNames A single object or an array of CLIENT objects.
|
||||
-- @param Wrapper.Client#CLIENT RemoveClientNames A single name or an array of CLIENT names.
|
||||
-- @return self
|
||||
function SET_CLIENT:RemoveClientsByName( RemoveClientNames )
|
||||
|
||||
@@ -4378,7 +4369,7 @@ do -- SET_CLIENT
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Client#CLIENT ClientObject
|
||||
function( ZoneObject, ClientObject )
|
||||
if ClientObject:IsInZone( ZoneObject ) then
|
||||
@@ -4400,7 +4391,7 @@ do -- SET_CLIENT
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Client#CLIENT ClientObject
|
||||
function( ZoneObject, ClientObject )
|
||||
if ClientObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -4468,7 +4459,7 @@ do -- SET_CLIENT
|
||||
if self.Filter.Active == false or (self.Filter.Active == true and MClient:IsActive() == true and MClient:IsAlive() == true) then
|
||||
MClientActive = true
|
||||
end
|
||||
--self:T( { "Evaluated Active", MClientActive } )
|
||||
--self:I( { "Evaluated Active", MClientActive } )
|
||||
MClientInclude = MClientInclude and MClientActive
|
||||
end
|
||||
|
||||
@@ -4535,45 +4526,45 @@ do -- SET_CLIENT
|
||||
MClientInclude = MClientInclude and MClientPrefix
|
||||
end
|
||||
|
||||
if self.Filter.Zones then
|
||||
local MClientZone = false
|
||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||
self:T3( "Zone:", ZoneName )
|
||||
local unit = MClient:GetClientGroupUnit()
|
||||
if unit and unit:IsInZone(Zone) then
|
||||
MClientZone = true
|
||||
end
|
||||
end
|
||||
MClientInclude = MClientInclude and MClientZone
|
||||
end
|
||||
|
||||
if self.Filter.Playernames then
|
||||
local MClientPlayername = false
|
||||
local playername = MClient:GetPlayerName() or "Unknown"
|
||||
--self:T(playername)
|
||||
for _,_Playername in pairs(self.Filter.Playernames) do
|
||||
if playername and string.find(playername,_Playername) then
|
||||
MClientPlayername = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Playername", MClientPlayername } )
|
||||
MClientInclude = MClientInclude and MClientPlayername
|
||||
end
|
||||
|
||||
if self.Filter.Callsigns then
|
||||
local MClientCallsigns = false
|
||||
local callsign = MClient:GetCallsign()
|
||||
--self:T(callsign)
|
||||
for _,_Callsign in pairs(self.Filter.Callsigns) do
|
||||
if callsign and string.find(callsign,_Callsign) then
|
||||
MClientCallsigns = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Callsign", MClientCallsigns } )
|
||||
MClientInclude = MClientInclude and MClientCallsigns
|
||||
end
|
||||
|
||||
end
|
||||
if self.Filter.Zones then
|
||||
local MClientZone = false
|
||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||
self:T3( "Zone:", ZoneName )
|
||||
local unit = MClient:GetClientGroupUnit()
|
||||
if unit and unit:IsInZone(Zone) then
|
||||
MClientZone = true
|
||||
end
|
||||
end
|
||||
MClientInclude = MClientInclude and MClientZone
|
||||
end
|
||||
|
||||
if self.Filter.Playernames then
|
||||
local MClientPlayername = false
|
||||
local playername = MClient:GetPlayerName() or "Unknown"
|
||||
--self:I(playername)
|
||||
for _,_Playername in pairs(self.Filter.Playernames) do
|
||||
if playername and string.find(playername,_Playername) then
|
||||
MClientPlayername = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Playername", MClientPlayername } )
|
||||
MClientInclude = MClientInclude and MClientPlayername
|
||||
end
|
||||
|
||||
if self.Filter.Callsigns then
|
||||
local MClientCallsigns = false
|
||||
local callsign = MClient:GetCallsign()
|
||||
--self:I(callsign)
|
||||
for _,_Callsign in pairs(self.Filter.Callsigns) do
|
||||
if callsign and string.find(callsign,_Callsign) then
|
||||
MClientCallsigns = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Callsign", MClientCallsigns } )
|
||||
MClientInclude = MClientInclude and MClientCallsigns
|
||||
end
|
||||
|
||||
end
|
||||
self:T2( MClientInclude )
|
||||
return MClientInclude
|
||||
end
|
||||
@@ -4582,8 +4573,7 @@ end
|
||||
|
||||
do -- SET_PLAYER
|
||||
|
||||
---
|
||||
-- @type SET_PLAYER
|
||||
--- @type SET_PLAYER
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_PLAYER} class to build sets of units belonging to alive players:
|
||||
@@ -4878,7 +4868,7 @@ do -- SET_PLAYER
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Client#CLIENT ClientObject
|
||||
function( ZoneObject, ClientObject )
|
||||
if ClientObject:IsInZone( ZoneObject ) then
|
||||
@@ -4900,7 +4890,7 @@ do -- SET_PLAYER
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self:GetSet(),
|
||||
-- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
--- @param Core.Zone#ZONE_BASE ZoneObject
|
||||
-- @param Wrapper.Client#CLIENT ClientObject
|
||||
function( ZoneObject, ClientObject )
|
||||
if ClientObject:IsNotInZone( ZoneObject ) then
|
||||
@@ -5008,9 +4998,8 @@ do -- SET_PLAYER
|
||||
end
|
||||
|
||||
do -- SET_AIRBASE
|
||||
|
||||
---
|
||||
-- @type SET_AIRBASE
|
||||
|
||||
--- @type SET_AIRBASE
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_AIRBASE} class to build sets of airbases optionally belonging to certain:
|
||||
@@ -5352,9 +5341,8 @@ do -- SET_AIRBASE
|
||||
end
|
||||
|
||||
do -- SET_CARGO
|
||||
|
||||
---
|
||||
-- @type SET_CARGO
|
||||
|
||||
--- @type SET_CARGO
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_CARGO} class to build sets of cargos optionally belonging to certain:
|
||||
@@ -5779,9 +5767,8 @@ do -- SET_CARGO
|
||||
end
|
||||
|
||||
do -- SET_ZONE
|
||||
|
||||
---
|
||||
-- @type SET_ZONE
|
||||
|
||||
--- @type SET_ZONE
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_ZONE} class to build sets of zones of various types.
|
||||
@@ -6148,9 +6135,8 @@ do -- SET_ZONE
|
||||
end
|
||||
|
||||
do -- SET_ZONE_GOAL
|
||||
|
||||
---
|
||||
-- @type SET_ZONE_GOAL
|
||||
|
||||
--- @type SET_ZONE_GOAL
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_ZONE_GOAL} class to build sets of zones of various types.
|
||||
@@ -6460,9 +6446,8 @@ do -- SET_ZONE_GOAL
|
||||
end
|
||||
|
||||
do -- SET_OPSZONE
|
||||
|
||||
---
|
||||
-- @type SET_OPSZONE
|
||||
|
||||
--- @type SET_OPSZONE
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_OPSZONE} class to build sets of zones of various types.
|
||||
@@ -6918,9 +6903,8 @@ end
|
||||
|
||||
|
||||
do -- SET_OPSGROUP
|
||||
|
||||
---
|
||||
-- @type SET_OPSGROUP
|
||||
|
||||
--- @type SET_OPSGROUP
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_OPSGROUP} class to build sets of OPS groups belonging to certain:
|
||||
@@ -7587,7 +7571,6 @@ do -- SET_SCENERY
|
||||
Scenerys = {},
|
||||
Filter = {
|
||||
SceneryPrefixes = nil,
|
||||
SceneryRoles = nil,
|
||||
Zones = nil,
|
||||
},
|
||||
}
|
||||
@@ -7610,7 +7593,7 @@ do -- SET_SCENERY
|
||||
|
||||
if ZoneSet then
|
||||
for _,_zone in pairs(ZoneSet.Set) do
|
||||
self:T("Zone type handed: "..tostring(_zone.ClassName))
|
||||
self:T("Zone type handed: "..tostring(_zone.ClassName))
|
||||
table.insert(zonenames,_zone:GetName())
|
||||
end
|
||||
self:AddSceneryByName(zonenames)
|
||||
@@ -7634,7 +7617,7 @@ do -- SET_SCENERY
|
||||
|
||||
--- Add SCENERY(s) to SET_SCENERY.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @param Wrapper.Scenery#SCENERY AddScenery A single SCENERY object.
|
||||
-- @param #string AddScenery A single SCENERY.
|
||||
-- @return #SET_SCENERY self
|
||||
function SET_SCENERY:AddScenery( AddScenery )
|
||||
self:F2( AddScenery:GetName() )
|
||||
@@ -7704,7 +7687,6 @@ do -- SET_SCENERY
|
||||
end
|
||||
for _,Zone in pairs( zones ) do
|
||||
local zonename = Zone:GetName()
|
||||
self:T(zonename)
|
||||
self.Filter.Zones[zonename] = Zone
|
||||
end
|
||||
return self
|
||||
@@ -7723,30 +7705,11 @@ do -- SET_SCENERY
|
||||
Prefixes = { Prefixes }
|
||||
end
|
||||
for PrefixID, Prefix in pairs( Prefixes ) do
|
||||
--self:T(Prefix)
|
||||
self.Filter.SceneryPrefixes[Prefix] = Prefix
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Builds a set of SCENERYs that **contain** an exact match of the "ROLE" property.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @param #string Role The string pattern(s) that needs to exactly match the scenery "ROLE" property from the ME quad-zone properties. Can also be passed as a `#table` of strings.
|
||||
-- @return #SET_SCENERY self
|
||||
function SET_SCENERY:FilterRoles( Role )
|
||||
if not self.Filter.SceneryRoles then
|
||||
self.Filter.SceneryRoles = {}
|
||||
end
|
||||
if type( Role ) ~= "table" then
|
||||
Role = { Role }
|
||||
end
|
||||
for PrefixID, Prefix in pairs( Role ) do
|
||||
--self:T(Prefix)
|
||||
self.Filter.SceneryRoles[Prefix] = Prefix
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Iterate the SET_SCENERY and count how many SCENERYSs are alive.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #number The number of SCENERYSs alive.
|
||||
@@ -7839,76 +7802,10 @@ do -- SET_SCENERY
|
||||
-- @param Wrapper.Scenery#SCENERY MScenery
|
||||
-- @return #SET_SCENERY self
|
||||
function SET_SCENERY:IsIncludeObject( MScenery )
|
||||
self:T( MScenery.SceneryName )
|
||||
|
||||
local MSceneryInclude = true
|
||||
|
||||
if MScenery then
|
||||
local MSceneryName = MScenery:GetName()
|
||||
|
||||
-- Filter Prefixes
|
||||
if self.Filter.Prefixes then
|
||||
local MSceneryPrefix = false
|
||||
for ZonePrefixId, ZonePrefix in pairs( self.Filter.Prefixes ) do
|
||||
self:T( { "Prefix:", string.find( MSceneryName, ZonePrefix, 1 ), ZonePrefix } )
|
||||
if string.find( MSceneryName, ZonePrefix, 1 ) then
|
||||
MSceneryPrefix = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Prefix", MSceneryPrefix } )
|
||||
MSceneryInclude = MSceneryInclude and MSceneryPrefix
|
||||
end
|
||||
|
||||
if self.Filter.Zones then
|
||||
local MSceneryZone = false
|
||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||
--self:T( "Zone:", ZoneName )
|
||||
local coord = MScenery:GetCoordinate()
|
||||
if coord and Zone:IsCoordinateInZone(coord) then
|
||||
MSceneryZone = true
|
||||
end
|
||||
self:T( { "Evaluated Zone", MSceneryZone } )
|
||||
end
|
||||
MSceneryInclude = MSceneryInclude and MSceneryZone
|
||||
end
|
||||
|
||||
-- Filter Roles
|
||||
if self.Filter.SceneryRoles then
|
||||
local MSceneryRole = false
|
||||
local Role = MScenery:GetProperty("ROLE") or "none"
|
||||
for ZoneRoleId, ZoneRole in pairs( self.Filter.SceneryRoles ) do
|
||||
self:T( { "Role:", ZoneRole, Role } )
|
||||
if ZoneRole == Role then
|
||||
MSceneryRole = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Role ", MSceneryRole } )
|
||||
MSceneryInclude = MSceneryInclude and MSceneryRole
|
||||
end
|
||||
end
|
||||
|
||||
self:T2( MSceneryInclude )
|
||||
return MSceneryInclude
|
||||
self:F2( MScenery )
|
||||
return true
|
||||
end
|
||||
|
||||
--- Filters for the defined collection.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #SET_SCENERY self
|
||||
function SET_SCENERY:FilterOnce()
|
||||
|
||||
for ObjectName, Object in pairs( self:GetSet() ) do
|
||||
self:T(ObjectName)
|
||||
if self:IsIncludeObject( Object ) then
|
||||
self:Add( ObjectName, Object )
|
||||
else
|
||||
self:Remove(ObjectName, true)
|
||||
end
|
||||
end
|
||||
|
||||
return self --FilteredSet
|
||||
end
|
||||
|
||||
|
||||
--- Count overall initial (Life0) lifepoints of the SET objects.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #number LIfe0Points
|
||||
@@ -7946,7 +7843,7 @@ do -- SET_SCENERY
|
||||
function SET_SCENERY:GetRelativeLife()
|
||||
local life = self:GetLife()
|
||||
local life0 = self:GetLife0()
|
||||
self:T2(string.format("Set Lifepoints: %d life0 | %d life",life0,life))
|
||||
self:T3(string.format("Set Lifepoints: %d life0 | %d life",life0,life))
|
||||
local rlife = math.floor((life / life0) * 100)
|
||||
return rlife
|
||||
end
|
||||
|
||||
@@ -1616,7 +1616,11 @@ function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset)
|
||||
if (Offset.dx or Offset.dy) and (Offset.rho or Offset.theta) then
|
||||
error("Cannot use (dx, dy) with (rho, theta)")
|
||||
end
|
||||
end
|
||||
|
||||
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetVec2(), Radius, true ) )
|
||||
|
||||
if Offset then
|
||||
self.dy = Offset.dy or 0.0
|
||||
self.dx = Offset.dx or 0.0
|
||||
self.rho = Offset.rho or 0.0
|
||||
@@ -1624,8 +1628,6 @@ function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset)
|
||||
self.relative_to_unit = Offset.relative_to_unit or false
|
||||
end
|
||||
|
||||
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetVec2(), Radius, true ) )
|
||||
|
||||
self:F( { ZoneName, ZoneUNIT:GetVec2(), Radius } )
|
||||
|
||||
self.ZoneUNIT = ZoneUNIT
|
||||
|
||||
@@ -793,112 +793,11 @@ do -- Airbase
|
||||
-- @function [parent=#Airbase] getDesc
|
||||
-- @param self
|
||||
-- @return #Airbase.Desc
|
||||
|
||||
--- Returns the warehouse object associated with the airbase object. Can then be used to call the warehouse class functions to modify the contents of the warehouse.
|
||||
-- @function [parent=#Airbase] getWarehouse
|
||||
-- @param self
|
||||
-- @return #Warehouse The DCS warehouse object of this airbase.
|
||||
|
||||
--- Enables or disables the airbase and FARP auto capture game mechanic where ownership of a base can change based on the presence of ground forces or the
|
||||
-- default setting assigned in the editor.
|
||||
-- @function [parent=#Airbase] autoCapture
|
||||
-- @param self
|
||||
-- @param #boolean setting `true` : enables autoCapture behavior, `false` : disables autoCapture behavior
|
||||
|
||||
--- Returns the current autoCapture setting for the passed base.
|
||||
-- @function [parent=#Airbase] autoCaptureIsOn
|
||||
-- @param self
|
||||
-- @return #boolean `true` if autoCapture behavior is enabled and `false` otherwise.
|
||||
|
||||
--- Changes the passed airbase object's coalition to the set value. Must be used with Airbase.autoCapture to disable auto capturing of the base,
|
||||
-- otherwise the base can revert back to a different coalition depending on the situation and built in game capture rules.
|
||||
-- @function [parent=#Airbase] setCoalition
|
||||
-- @param self
|
||||
-- @param #number coa The new owner coalition: 0=neutra, 1=red, 2=blue.
|
||||
|
||||
--- Returns the wsType of every object that exists in DCS. A wsType is a table consisting of 4 entries indexed numerically.
|
||||
-- It can be used to broadly categorize object types. The table can be broken down as: {mainCategory, subCat1, subCat2, index}
|
||||
-- @function [parent=#Airbase] getResourceMap
|
||||
-- @param self
|
||||
-- @return #table wsType of every object that exists in DCS.
|
||||
|
||||
|
||||
Airbase = {} --#Airbase
|
||||
|
||||
end -- Airbase
|
||||
|
||||
|
||||
do -- Warehouse
|
||||
|
||||
--- [DCS Class Warehouse](https://wiki.hoggitworld.com/view/DCS_Class_Warehouse)
|
||||
-- The warehouse class gives control over warehouses that exist in airbase objects. These warehouses can limit the aircraft, munitions, and fuel available to coalition aircraft.
|
||||
-- @type Warehouse
|
||||
|
||||
--- Adds the passed amount of a given item to the warehouse.
|
||||
-- itemName is the typeName associated with the item: "weapons.missiles.AIM_54C_Mk47"
|
||||
-- A wsType table can also be used, however the last digit with wsTypes has been known to change. {4, 4, 7, 322}
|
||||
-- @function [parent=#Warehouse] addItem
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
-- @param #number count Number of items to add.
|
||||
|
||||
--- Returns the number of the passed type of item currently in a warehouse object.
|
||||
-- @function [parent=#Warehouse] getItemCount
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
|
||||
--- Sets the passed amount of a given item to the warehouse.
|
||||
-- @function [parent=#Warehouse] setItem
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
-- @param #number count Number of items to add.
|
||||
|
||||
--- Removes the amount of the passed item from the warehouse.
|
||||
-- @function [parent=#Warehouse] removeItem
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
-- @param #number count Number of items to be removed.
|
||||
|
||||
--- Adds the passed amount of a liquid fuel into the warehouse inventory.
|
||||
-- @function [parent=#Warehouse] addLiquid
|
||||
-- @param self
|
||||
-- @param #number liquidType Type of liquid to add: 0=jetfuel, 1=aviation gasoline, 2=MW50, 3=Diesel.
|
||||
-- @param #number count Amount of liquid to add.
|
||||
|
||||
--- Returns the amount of the passed liquid type within a given warehouse.
|
||||
-- @function [parent=#Warehouse] getLiquidAmount
|
||||
-- @param self
|
||||
-- @param #number liquidType Type of liquid to add: 0=jetfuel, 1=aviation gasoline, 2=MW50, 3=Diesel.
|
||||
-- @return #number Amount of liquid.
|
||||
|
||||
--- Sets the passed amount of a liquid fuel into the warehouse inventory.
|
||||
-- @function [parent=#Warehouse] setLiquidAmount
|
||||
-- @param self
|
||||
-- @param #number liquidType Type of liquid to add: 0=jetfuel, 1=aviation gasoline, 2=MW50, 3=Diesel.
|
||||
-- @param #number count Amount of liquid.
|
||||
|
||||
--- Removes the set amount of liquid from the inventory in a warehouse.
|
||||
-- @function [parent=#Warehouse] setLiquidAmount
|
||||
-- @param self
|
||||
-- @param #number liquidType Type of liquid to add: 0=jetfuel, 1=aviation gasoline, 2=MW50, 3=Diesel.
|
||||
-- @param #number count Amount of liquid.
|
||||
|
||||
--- Returns the airbase object associated with the warehouse object.
|
||||
-- @function [parent=#Warehouse] getOwner
|
||||
-- @param self
|
||||
-- @return #Airbase The airbase object owning this warehouse.
|
||||
|
||||
--- Returns a full itemized list of everything currently in a warehouse. If a category is set to unlimited then the table will be returned empty.
|
||||
-- Aircraft and weapons are indexed by strings. Liquids are indexed by number.
|
||||
-- @function [parent=#Warehouse] getInventory
|
||||
-- @param self
|
||||
-- @param #string itemName Name of the item.
|
||||
-- @return #table Itemized list of everything currently in a warehouse
|
||||
|
||||
|
||||
Warehouse = {} --#Warehouse
|
||||
|
||||
end
|
||||
|
||||
do -- Spot
|
||||
|
||||
--- [DCS Class Spot](https://wiki.hoggitworld.com/view/DCS_Class_Spot)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,806 @@
|
||||
--- **Functional** -- Send a truck to supply artillery groups.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- **AMMOTRUCK** - Send a truck to supply artillery groups.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- ### [AmmoTruck](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/AMT%20-%20AmmoTruck/AmmoTruck%20100%20-%20NTTR%20-%20Basic)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author : **applevangelist**
|
||||
--
|
||||
-- @module Functional.AmmoTruck
|
||||
-- @image Artillery.JPG
|
||||
--
|
||||
-- Last update: July 2023
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **AMMOTRUCK** class, extends Core.FSM#FSM
|
||||
-- @type AMMOTRUCK
|
||||
-- @field #string ClassName Class Name
|
||||
-- @field #string lid Lid for log entries
|
||||
-- @field #string version Version string
|
||||
-- @field #string alias Alias name
|
||||
-- @field #boolean debug Debug flag
|
||||
-- @field #table trucklist List of (alive) #AMMOTRUCK.data trucks
|
||||
-- @field #table targetlist List of (alive) #AMMOTRUCK.data artillery
|
||||
-- @field #number coalition Coalition this is for
|
||||
-- @field Core.Set#SET_GROUP truckset SET of trucks
|
||||
-- @field Core.Set#SET_GROUP targetset SET of artillery
|
||||
-- @field #table remunitionqueue List of (alive) #AMMOTRUCK.data artillery to be reloaded
|
||||
-- @field #table waitingtargets List of (alive) #AMMOTRUCK.data artillery waiting
|
||||
-- @field #number ammothreshold Threshold (min) ammo before sending a truck
|
||||
-- @field #number remunidist Max distance trucks will go
|
||||
-- @field #number monitor Monitor interval in seconds
|
||||
-- @field #number unloadtime Unload time in seconds
|
||||
-- @field #number waitingtime Max waiting time in seconds
|
||||
-- @field #boolean routeonroad Route truck on road if true (default)
|
||||
-- @field #number reloads Number of reloads a single truck can do before he must return home
|
||||
-- @extends Core.FSM#FSM
|
||||
|
||||
--- *Amateurs talk about tactics, but professionals study logistics.* - General Robert H Barrow, USMC
|
||||
--
|
||||
-- Simple Class to re-arm your artillery with trucks.
|
||||
--
|
||||
-- #AMMOTRUCK
|
||||
--
|
||||
-- * Controls a SET\_GROUP of trucks which will re-arm a SET\_GROUP of artillery groups when they run out of ammunition.
|
||||
--
|
||||
-- ## 1 The AMMOTRUCK concept
|
||||
--
|
||||
-- A SET\_GROUP of trucks which will re-arm a SET\_GROUP of artillery groups when they run out of ammunition. They will be based on a
|
||||
-- homebase and drive from there to the artillery groups and then back home.
|
||||
-- Trucks are the **only known in-game mechanic** to re-arm artillery and other units in DCS. Working units are e.g.: M-939 (blue), Ural-375 and ZIL-135 (both red).
|
||||
--
|
||||
-- ## 2 Set-up
|
||||
--
|
||||
-- Define a set of trucks and a set of artillery:
|
||||
--
|
||||
-- local truckset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Ammo Truck"):FilterStart()
|
||||
-- local ariset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Artillery"):FilterStart()
|
||||
--
|
||||
-- Create an AMMOTRUCK object to take care of the artillery using the trucks, with a homezone:
|
||||
--
|
||||
-- local ammotruck = AMMOTRUCK:New(truckset,ariset,coalition.side.BLUE,"Logistics",ZONE:FindByName("HomeZone")
|
||||
--
|
||||
-- ## 2 Options and their default values
|
||||
--
|
||||
-- ammotruck.ammothreshold = 5 -- send a truck when down to this many rounds
|
||||
-- ammotruck.remunidist = 20000 -- 20km - send trucks max this far from home
|
||||
-- ammotruck.unloadtime = 600 -- 10 minutes - min time to unload ammunition
|
||||
-- ammotruck.waitingtime = 1800 -- 30 mintes - wait max this long until remunition is done
|
||||
-- ammotruck.monitor = -60 -- 1 minute - AMMOTRUCK checks run every one minute
|
||||
-- ammotruck.routeonroad = true -- Trucks will **try** to drive on roads
|
||||
-- ammotruck.usearmygroup = false -- If true, will make use of ARMYGROUP in the background (if used in DEV branch)
|
||||
-- ammotruck.reloads = 5 -- Maxn re-arms a truck can do before he needs to go home and restock. Set to -1 for unlimited
|
||||
--
|
||||
-- ## 3 FSM Events to shape mission
|
||||
--
|
||||
-- Truck has been sent off:
|
||||
--
|
||||
-- function ammotruck:OnAfterRouteTruck(From, Event, To, Truckdata, Aridata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Truck has arrived:
|
||||
--
|
||||
-- function ammotruck:OnAfterTruckArrived(From, Event, To, Truckdata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Truck is unloading:
|
||||
--
|
||||
-- function ammotruck:OnAfterTruckUnloading(From, Event, To, Truckdata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Truck is returning home:
|
||||
--
|
||||
-- function ammotruck:OnAfterTruckReturning(From, Event, To, Truckdata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Truck is arrived at home:
|
||||
--
|
||||
-- function ammotruck:OnAfterTruckHome(From, Event, To, Truckdata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- @field #AMMOTRUCK
|
||||
AMMOTRUCK = {
|
||||
ClassName = "AMMOTRUCK",
|
||||
lid = "",
|
||||
version = "0.0.12",
|
||||
alias = "",
|
||||
debug = false,
|
||||
trucklist = {},
|
||||
targetlist = {},
|
||||
coalition = nil,
|
||||
truckset = nil,
|
||||
targetset = nil,
|
||||
remunitionqueue = {},
|
||||
waitingtargets = {},
|
||||
ammothreshold = 5,
|
||||
remunidist = 20000,
|
||||
monitor = -60,
|
||||
unloadtime = 600,
|
||||
waitingtime = 1800,
|
||||
routeonroad = true,
|
||||
reloads = 5,
|
||||
}
|
||||
|
||||
---
|
||||
-- @type AMMOTRUCK.State
|
||||
AMMOTRUCK.State = {
|
||||
IDLE = "idle",
|
||||
DRIVING = "driving",
|
||||
ARRIVED = "arrived",
|
||||
UNLOADING = "unloading",
|
||||
RETURNING = "returning",
|
||||
WAITING = "waiting",
|
||||
RELOADING = "reloading",
|
||||
OUTOFAMMO = "outofammo",
|
||||
REQUESTED = "requested",
|
||||
}
|
||||
|
||||
---
|
||||
--@type AMMOTRUCK.data
|
||||
--@field Wrapper.Group#GROUP group
|
||||
--@field #string name
|
||||
--@field #AMMOTRUCK.State statusquo
|
||||
--@field #number timestamp
|
||||
--@field #number ammo
|
||||
--@field Core.Point#COORDINATE coordinate
|
||||
--@field #string targetname
|
||||
--@field Wrapper.Group#GROUP targetgroup
|
||||
--@field Core.Point#COORDINATE targetcoordinate
|
||||
--@field #number reloads
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param Core.Set#SET_GROUP Truckset Set of truck groups
|
||||
-- @param Core.Set#SET_GROUP Targetset Set of artillery groups
|
||||
-- @param #number Coalition Coalition
|
||||
-- @param #string Alias Alias Name
|
||||
-- @param Core.Zone#ZONE Homezone Home, return zone for trucks
|
||||
-- @return #AMMOTRUCK self
|
||||
-- @usage
|
||||
-- Define a set of trucks and a set of artillery:
|
||||
-- local truckset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Ammo Truck"):FilterStart()
|
||||
-- local ariset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Artillery"):FilterStart()
|
||||
--
|
||||
-- Create an AMMOTRUCK object to take care of the artillery using the trucks, with a homezone:
|
||||
-- local ammotruck = AMMOTRUCK:New(truckset,ariset,coalition.side.BLUE,"Logistics",ZONE:FindByName("HomeZone")
|
||||
function AMMOTRUCK:New(Truckset,Targetset,Coalition,Alias,Homezone)
|
||||
|
||||
-- Inherit everything from BASE class.
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #AMMOTRUCK
|
||||
|
||||
self.truckset = Truckset -- Core.Set#SET_GROUP
|
||||
self.targetset = Targetset -- Core.Set#SET_GROUP
|
||||
self.coalition = Coalition -- #number
|
||||
self.alias = Alias -- #string
|
||||
self.debug = false
|
||||
self.remunitionqueue = {}
|
||||
self.trucklist = {}
|
||||
self.targetlist = {}
|
||||
self.ammothreshold = 5
|
||||
self.remunidist = 20000
|
||||
self.homezone = Homezone -- Core.Zone#ZONE
|
||||
self.waitingtime = 1800
|
||||
self.usearmygroup = false
|
||||
self.hasarmygroup = false
|
||||
|
||||
-- Log id.
|
||||
self.lid=string.format("AMMOTRUCK %s | %s | ", self.version, self.alias)
|
||||
|
||||
self:SetStartState("Stopped")
|
||||
self:AddTransition("Stopped", "Start", "Running")
|
||||
self:AddTransition("*", "Monitor", "*")
|
||||
self:AddTransition("*", "RouteTruck", "*")
|
||||
self:AddTransition("*", "TruckArrived", "*")
|
||||
self:AddTransition("*", "TruckUnloading", "*")
|
||||
self:AddTransition("*", "TruckReturning", "*")
|
||||
self:AddTransition("*", "TruckHome", "*")
|
||||
self:AddTransition("*", "Stop", "Stopped")
|
||||
|
||||
self:__Start(math.random(5,10))
|
||||
|
||||
self:I(self.lid .. "Started")
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the AMMOTRUCK and all its event handlers.
|
||||
-- @function [parent=#AMMOTRUCK] Stop
|
||||
-- @param #AMMOTRUCK self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the AMMOTRUCK and all its event handlers.
|
||||
-- @function [parent=#AMMOTRUCK] __Stop
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- On after "RouteTruck" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterRouteTruck
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
-- @param #AMMOTRUCK.data Artillery
|
||||
|
||||
--- On after "TruckUnloading" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckUnloading
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
|
||||
--- On after "TruckReturning" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckReturning
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
|
||||
--- On after "RouteTruck" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterRouteTruck
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
|
||||
--- On after "TruckHome" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckHome
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckDrivingTrucks(dataset)
|
||||
self:T(self.lid .. " CheckDrivingTrucks")
|
||||
local data = dataset
|
||||
for _,_data in pairs (data) do
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
-- see if we arrived at destination
|
||||
local coord = truck.group:GetCoordinate()
|
||||
local tgtcoord = truck.targetcoordinate
|
||||
local dist = coord:Get2DDistance(tgtcoord)
|
||||
if dist <= 150 then
|
||||
-- arrived
|
||||
truck.statusquo = AMMOTRUCK.State.ARRIVED
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
truck.coordinate = coord
|
||||
self:__TruckArrived(1,truck)
|
||||
end
|
||||
-- still driving?
|
||||
local Tnow = timer.getAbsTime()
|
||||
if Tnow - truck.timestamp > 30 then
|
||||
local group = truck.group
|
||||
if self.usearmygroup then
|
||||
group = truck.group:GetGroup()
|
||||
end
|
||||
local currspeed = group:GetVelocityKMH()
|
||||
if truck.lastspeed then
|
||||
if truck.lastspeed == 0 and currspeed == 0 then
|
||||
self:T(truck.group:GetName().." Is not moving!")
|
||||
-- try and move it
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
if self.routeonroad then
|
||||
group:RouteGroundOnRoad(truck.targetcoordinate,30,2,"Vee")
|
||||
else
|
||||
group:RouteGroundTo(truck.targetcoordinate,30,"Vee",2)
|
||||
end
|
||||
end
|
||||
truck.lastspeed = currspeed
|
||||
else
|
||||
truck.lastspeed = currspeed
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
end
|
||||
self:I({truck=truck.group:GetName(),currspeed=currspeed,lastspeed=truck.lastspeed})
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:GetAmmoStatus(Group)
|
||||
local ammotot, shells, rockets, bombs, missiles, narti = Group:GetAmmunition()
|
||||
return rockets+missiles+narti
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckWaitingTargets(dataset)
|
||||
self:T(self.lid .. " CheckWaitingTargets")
|
||||
local data = dataset
|
||||
for _,_data in pairs (data) do
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
-- see how long we're waiting - maybe ammo truck is dead?
|
||||
local Tnow = timer.getAbsTime()
|
||||
local Tdiff = Tnow - truck.timestamp
|
||||
if Tdiff > self.waitingtime then
|
||||
local hasammo = self:GetAmmoStatus(truck.group)
|
||||
if hasammo <= self.ammothreshold then
|
||||
truck.statusquo = AMMOTRUCK.State.OUTOFAMMO
|
||||
else
|
||||
truck.statusquo = AMMOTRUCK.State.IDLE
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckReturningTrucks(dataset)
|
||||
self:T(self.lid .. " CheckReturningTrucks")
|
||||
local data = dataset
|
||||
local tgtcoord = self.homezone:GetCoordinate()
|
||||
local radius = self.homezone:GetRadius()
|
||||
for _,_data in pairs (data) do
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
-- see if we arrived at destination
|
||||
local coord = truck.group:GetCoordinate()
|
||||
local dist = coord:Get2DDistance(tgtcoord)
|
||||
self:T({name=truck.name,radius=radius,distance=dist})
|
||||
if dist <= radius then
|
||||
-- arrived
|
||||
truck.statusquo = AMMOTRUCK.State.IDLE
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
truck.coordinate = coord
|
||||
truck.reloads = self.reloads or 5
|
||||
self:__TruckHome(1,truck)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string name Artillery group name to find
|
||||
-- @return #AMMOTRUCK.data Data
|
||||
function AMMOTRUCK:FindTarget(name)
|
||||
self:T(self.lid .. " FindTarget")
|
||||
local data = nil
|
||||
local dataset = self.targetlist
|
||||
for _,_entry in pairs(dataset) do
|
||||
local entry = _entry -- #AMMOTRUCK.data
|
||||
if entry.name == name then
|
||||
data = entry
|
||||
break
|
||||
end
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string name Truck group name to find
|
||||
-- @return #AMMOTRUCK.data Data
|
||||
function AMMOTRUCK:FindTruck(name)
|
||||
self:T(self.lid .. " FindTruck")
|
||||
local data = nil
|
||||
local dataset = self.trucklist
|
||||
for _,_entry in pairs(dataset) do
|
||||
local entry = _entry -- #AMMOTRUCK.data
|
||||
if entry.name == name then
|
||||
data = entry
|
||||
break
|
||||
end
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckArrivedTrucks(dataset)
|
||||
self:T(self.lid .. " CheckArrivedTrucks")
|
||||
local data = dataset
|
||||
for _,_data in pairs (data) do
|
||||
-- set to unloading
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
truck.statusquo = AMMOTRUCK.State.UNLOADING
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
self:__TruckUnloading(2,truck)
|
||||
-- set target to reloading
|
||||
local aridata = self:FindTarget(truck.targetname) -- #AMMOTRUCK.data
|
||||
if aridata then
|
||||
aridata.statusquo = AMMOTRUCK.State.RELOADING
|
||||
aridata.timestamp = timer.getAbsTime()
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckUnloadingTrucks(dataset)
|
||||
self:T(self.lid .. " CheckUnloadingTrucks")
|
||||
local data = dataset
|
||||
for _,_data in pairs (data) do
|
||||
-- check timestamp
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
local Tnow = timer.getAbsTime()
|
||||
local Tpassed = Tnow - truck.timestamp
|
||||
local hasammo = self:GetAmmoStatus(truck.targetgroup)
|
||||
if Tpassed > self.unloadtime and hasammo > self.ammothreshold then
|
||||
truck.statusquo = AMMOTRUCK.State.RETURNING
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
self:__TruckReturning(2,truck)
|
||||
-- set target to reloaded
|
||||
local aridata = self:FindTarget(truck.targetname) -- #AMMOTRUCK.data
|
||||
if aridata then
|
||||
aridata.statusquo = AMMOTRUCK.State.IDLE
|
||||
aridata.timestamp = timer.getAbsTime()
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckTargetsAlive()
|
||||
self:T(self.lid .. " CheckTargetsAlive")
|
||||
local arilist = self.targetlist
|
||||
for _,_ari in pairs(arilist) do
|
||||
local ari = _ari -- #AMMOTRUCK.data
|
||||
if ari.group and ari.group:IsAlive() then
|
||||
-- everything fine
|
||||
else
|
||||
-- ari dead
|
||||
self.targetlist[ari.name] = nil
|
||||
end
|
||||
end
|
||||
-- new arrivals?
|
||||
local aritable = self.targetset:GetSetObjects() --#table
|
||||
for _,_ari in pairs(aritable) do
|
||||
local ari = _ari -- Wrapper.Group#GROUP
|
||||
if ari and ari:IsAlive() and not self.targetlist[ari:GetName()] then
|
||||
local name = ari:GetName()
|
||||
local newari = {} -- #AMMOTRUCK.data
|
||||
newari.name = name
|
||||
newari.group = ari
|
||||
newari.statusquo = AMMOTRUCK.State.IDLE
|
||||
newari.timestamp = timer.getAbsTime()
|
||||
newari.coordinate = ari:GetCoordinate()
|
||||
local hasammo = self:GetAmmoStatus(ari)
|
||||
--newari.ammo = ari:GetAmmunition()
|
||||
newari.ammo = hasammo
|
||||
self.targetlist[name] = newari
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckTrucksAlive()
|
||||
self:T(self.lid .. " CheckTrucksAlive")
|
||||
local trucklist = self.trucklist
|
||||
for _,_truck in pairs(trucklist) do
|
||||
local truck = _truck -- #AMMOTRUCK.data
|
||||
if truck.group and truck.group:IsAlive() then
|
||||
-- everything fine
|
||||
else
|
||||
-- truck dead
|
||||
local tgtname = truck.targetname
|
||||
local targetdata = self:FindTarget(tgtname) -- #AMMOTRUCK.data
|
||||
if targetdata then
|
||||
if targetdata.statusquo ~= AMMOTRUCK.State.IDLE then
|
||||
targetdata.statusquo = AMMOTRUCK.State.IDLE
|
||||
end
|
||||
end
|
||||
self.trucklist[truck.name] = nil
|
||||
end
|
||||
end
|
||||
-- new arrivals?
|
||||
local trucktable = self.truckset:GetSetObjects() --#table
|
||||
for _,_truck in pairs(trucktable) do
|
||||
local truck = _truck -- Wrapper.Group#GROUP
|
||||
if truck and truck:IsAlive() and not self.trucklist[truck:GetName()] then
|
||||
local name = truck:GetName()
|
||||
local newtruck = {} -- #AMMOTRUCK.data
|
||||
newtruck.name = name
|
||||
newtruck.group = truck
|
||||
if self.hasarmygroup then
|
||||
-- is (not) already ARMYGROUP?
|
||||
if truck.ClassName and truck.ClassName == "GROUP" then
|
||||
local trucker = ARMYGROUP:New(truck)
|
||||
trucker:Activate()
|
||||
newtruck.group = trucker
|
||||
end
|
||||
end
|
||||
newtruck.statusquo = AMMOTRUCK.State.IDLE
|
||||
newtruck.timestamp = timer.getAbsTime()
|
||||
newtruck.coordinate = truck:GetCoordinate()
|
||||
newtruck.reloads = self.reloads or 5
|
||||
self.trucklist[name] = newtruck
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterStart(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
if ARMYGROUP and self.usearmygroup then
|
||||
self.hasarmygroup = true
|
||||
else
|
||||
self.hasarmygroup = false
|
||||
end
|
||||
if self.debug then
|
||||
BASE:TraceOn()
|
||||
BASE:TraceClass("AMMOTRUCK")
|
||||
end
|
||||
self:CheckTargetsAlive()
|
||||
self:CheckTrucksAlive()
|
||||
self:__Monitor(-30)
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterMonitor(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
self:CheckTargetsAlive()
|
||||
self:CheckTrucksAlive()
|
||||
-- update ammo state
|
||||
local remunition = false
|
||||
local remunitionqueue = {}
|
||||
local waitingtargets = {}
|
||||
for _,_ari in pairs(self.targetlist) do
|
||||
local data = _ari -- #AMMOTRUCK.data
|
||||
if data.group and data.group:IsAlive() then
|
||||
data.ammo = self:GetAmmoStatus(data.group)
|
||||
data.timestamp = timer.getAbsTime()
|
||||
local text = string.format("Ari %s | Ammo %d | State %s",data.name,data.ammo,data.statusquo)
|
||||
self:T(text)
|
||||
if data.ammo <= self.ammothreshold and (data.statusquo == AMMOTRUCK.State.IDLE or data.statusquo == AMMOTRUCK.State.OUTOFAMMO) then
|
||||
-- add to remu queue
|
||||
data.statusquo = AMMOTRUCK.State.OUTOFAMMO
|
||||
remunitionqueue[#remunitionqueue+1] = data
|
||||
remunition = true
|
||||
elseif data.statusquo == AMMOTRUCK.State.WAITING then
|
||||
waitingtargets[#waitingtargets+1] = data
|
||||
end
|
||||
else
|
||||
self.targetlist[data.name] = nil
|
||||
end
|
||||
end
|
||||
-- sort trucks in buckets
|
||||
local idletrucks = {}
|
||||
local drivingtrucks = {}
|
||||
local unloadingtrucks = {}
|
||||
local arrivedtrucks = {}
|
||||
local returningtrucks = {}
|
||||
local found = false
|
||||
for _,_truckdata in pairs(self.trucklist) do
|
||||
local data = _truckdata -- #AMMOTRUCK.data
|
||||
if data.group and data.group:IsAlive() then
|
||||
-- check state
|
||||
local text = string.format("Truck %s | State %s",data.name,data.statusquo)
|
||||
self:T(text)
|
||||
if data.statusquo == AMMOTRUCK.State.IDLE then
|
||||
idletrucks[#idletrucks+1] = data
|
||||
found = true
|
||||
elseif data.statusquo == AMMOTRUCK.State.DRIVING then
|
||||
drivingtrucks[#drivingtrucks+1] = data
|
||||
elseif data.statusquo == AMMOTRUCK.State.ARRIVED then
|
||||
arrivedtrucks[#arrivedtrucks+1] = data
|
||||
elseif data.statusquo == AMMOTRUCK.State.UNLOADING then
|
||||
unloadingtrucks[#unloadingtrucks+1] = data
|
||||
elseif data.statusquo == AMMOTRUCK.State.RETURNING then
|
||||
returningtrucks[#returningtrucks+1] = data
|
||||
if data.reloads > 0 or data.reloads == -1 then
|
||||
idletrucks[#idletrucks+1] = data
|
||||
found = true
|
||||
end
|
||||
end
|
||||
else
|
||||
self.truckset[data.name] = nil
|
||||
end
|
||||
end
|
||||
-- see if we can/need route one
|
||||
local n=0
|
||||
if found and remunition then
|
||||
-- match
|
||||
--local match = false
|
||||
for _,_truckdata in pairs(idletrucks) do
|
||||
local truckdata = _truckdata -- #AMMOTRUCK.data
|
||||
local truckcoord = truckdata.group:GetCoordinate() -- Core.Point#COORDINATE
|
||||
for _,_aridata in pairs(remunitionqueue) do
|
||||
local aridata = _aridata -- #AMMOTRUCK.data
|
||||
local aricoord = aridata.coordinate
|
||||
local distance = truckcoord:Get2DDistance(aricoord)
|
||||
if distance <= self.remunidist and aridata.statusquo == AMMOTRUCK.State.OUTOFAMMO and n <= #idletrucks then
|
||||
n = n + 1
|
||||
aridata.statusquo = AMMOTRUCK.State.REQUESTED
|
||||
self:__RouteTruck(n*5,truckdata,aridata)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- check driving trucks
|
||||
if #drivingtrucks > 0 then
|
||||
self:CheckDrivingTrucks(drivingtrucks)
|
||||
end
|
||||
|
||||
-- check arrived trucks
|
||||
if #arrivedtrucks > 0 then
|
||||
self:CheckArrivedTrucks(arrivedtrucks)
|
||||
end
|
||||
|
||||
-- check unloading trucks
|
||||
if #unloadingtrucks > 0 then
|
||||
self:CheckUnloadingTrucks(unloadingtrucks)
|
||||
end
|
||||
|
||||
-- check returningtrucks trucks
|
||||
if #returningtrucks > 0 then
|
||||
self:CheckReturningTrucks(returningtrucks)
|
||||
end
|
||||
|
||||
-- check waiting targets
|
||||
if #waitingtargets > 0 then
|
||||
self:CheckWaitingTargets(waitingtargets)
|
||||
end
|
||||
|
||||
self:__Monitor(self.monitor)
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #AMMOTRUCK.data Truckdata
|
||||
-- @param #AMMOTRUCK.data Aridata
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterRouteTruck(From, Event, To, Truckdata, Aridata)
|
||||
self:T({From, Event, To, Truckdata.name, Aridata.name})
|
||||
local truckdata = Truckdata -- #AMMOTRUCK.data
|
||||
local aridata = Aridata -- #AMMOTRUCK.data
|
||||
local tgtgrp = aridata.group
|
||||
local tgtzone = ZONE_GROUP:New(aridata.name,tgtgrp,30)
|
||||
local tgtcoord = tgtzone:GetRandomCoordinate(15)
|
||||
if self.hasarmygroup then
|
||||
local mission = AUFTRAG:NewONGUARD(tgtcoord)
|
||||
local oldmission = truckdata.group:GetMissionCurrent()
|
||||
if oldmission then oldmission:Cancel() end
|
||||
mission:SetTime(5)
|
||||
mission:SetTeleport(false)
|
||||
truckdata.group:AddMission(mission)
|
||||
elseif self.routeonroad then
|
||||
truckdata.group:RouteGroundOnRoad(tgtcoord,30)
|
||||
else
|
||||
truckdata.group:RouteGroundTo(tgtcoord,30)
|
||||
end
|
||||
truckdata.statusquo = AMMOTRUCK.State.DRIVING
|
||||
truckdata.targetgroup = tgtgrp
|
||||
truckdata.targetname = aridata.name
|
||||
truckdata.targetcoordinate = tgtcoord
|
||||
aridata.statusquo = AMMOTRUCK.State.WAITING
|
||||
aridata.timestamp = timer.getAbsTime()
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #AMMOTRUCK.data Truckdata
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterTruckUnloading(From, Event, To, Truckdata)
|
||||
local m = MESSAGE:New("Truck "..Truckdata.name.." unloading!",15,"AmmoTruck"):ToCoalitionIf(self.coalition,self.debug)
|
||||
local truck = Truckdata -- Functional.AmmoTruck#AMMOTRUCK.data
|
||||
local coord = truck.group:GetCoordinate()
|
||||
local heading = truck.group:GetHeading()
|
||||
heading = heading < 180 and (360-heading) or (heading - 180)
|
||||
local cid = self.coalition == coalition.side.BLUE and country.id.USA or country.id.RUSSIA
|
||||
cid = self.coalition == coalition.side.NEUTRAL and country.id.UN_PEACEKEEPERS or cid
|
||||
|
||||
local ammo = {}
|
||||
for i=1,5 do
|
||||
ammo[i] = SPAWNSTATIC:NewFromType("ammo_cargo","Cargos",cid)
|
||||
:InitCoordinate(coord:Translate((15+((i-1)*4)),heading))
|
||||
:Spawn(0,"AmmoCrate-"..math.random(1,10000))
|
||||
end
|
||||
|
||||
local function destroyammo(ammo)
|
||||
for _,_crate in pairs(ammo) do
|
||||
_crate:Destroy(false)
|
||||
end
|
||||
end
|
||||
|
||||
local scheduler = SCHEDULER:New(nil,destroyammo,{ammo},self.waitingtime)
|
||||
|
||||
-- one reload less
|
||||
if truck.reloads ~= -1 then
|
||||
truck.reloads = truck.reloads - 1
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterTruckReturning(From, Event, To, Truck)
|
||||
self:T({From, Event, To, Truck.name})
|
||||
-- route home
|
||||
local truckdata = Truck -- #AMMOTRUCK.data
|
||||
local tgtzone = self.homezone
|
||||
local tgtcoord = tgtzone:GetRandomCoordinate()
|
||||
if self.hasarmygroup then
|
||||
local mission = AUFTRAG:NewONGUARD(tgtcoord)
|
||||
local oldmission = truckdata.group:GetMissionCurrent()
|
||||
if oldmission then oldmission:Cancel() end
|
||||
mission:SetTime(5)
|
||||
mission:SetTeleport(false)
|
||||
truckdata.group:AddMission(mission)
|
||||
elseif self.routeonroad then
|
||||
truckdata.group:RouteGroundOnRoad(tgtcoord,30,1,"Cone")
|
||||
else
|
||||
truckdata.group:RouteGroundTo(tgtcoord,30,"Cone",1)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterStop(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
return self
|
||||
end
|
||||
@@ -3547,8 +3547,6 @@ end
|
||||
function ARTY:onafterRespawn(Controllable, From, Event, To)
|
||||
self:_EventFromTo("onafterRespawn", Event, From, To)
|
||||
|
||||
env.info("FF Respawning arty group")
|
||||
|
||||
local group=self.Controllable --Wrapper.Group#GROUP
|
||||
|
||||
-- Respawn group.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -591,7 +591,7 @@ RANGE.MenuF10Root = nil
|
||||
|
||||
--- Range script version.
|
||||
-- @field #string version
|
||||
RANGE.version = "2.7.1"
|
||||
RANGE.version = "2.7.0"
|
||||
|
||||
-- TODO list:
|
||||
-- TODO: Verbosity level for messages.
|
||||
@@ -2044,7 +2044,6 @@ function RANGE:OnEventShot( EventData )
|
||||
-- Attack parameters.
|
||||
local attackHdg=_unit:GetHeading()
|
||||
local attackAlt=_unit:GetHeight()
|
||||
attackAlt = UTILS.MetersToFeet(attackAlt)
|
||||
local attackVel=_unit:GetVelocityKNOTS()
|
||||
|
||||
-- Tracking info and init of last bomb position.
|
||||
|
||||
@@ -1420,7 +1420,7 @@ function SCORING:ReportDetailedPlayerHits( PlayerName )
|
||||
Penalty = Penalty + UnitData.Penalty
|
||||
PenaltyHit = UnitData.PenaltyHit
|
||||
end
|
||||
local ScoreMessageHit = string.format( "%s: %d ", CategoryName, Score - Penalty )
|
||||
local ScoreMessageHit = string.format( "%s:%d ", CategoryName, Score - Penalty )
|
||||
self:T( ScoreMessageHit )
|
||||
ScoreMessageHits = ScoreMessageHits .. ScoreMessageHit
|
||||
PlayerScore = PlayerScore + Score
|
||||
@@ -1476,7 +1476,7 @@ function SCORING:ReportDetailedPlayerDestroys( PlayerName )
|
||||
end
|
||||
end
|
||||
|
||||
local ScoreMessageDestroy = string.format( " %s: %d ", CategoryName, Score - Penalty )
|
||||
local ScoreMessageDestroy = string.format( " %s:%d ", CategoryName, Score - Penalty )
|
||||
self:T( ScoreMessageDestroy )
|
||||
ScoreMessageDestroys = ScoreMessageDestroys .. ScoreMessageDestroy
|
||||
|
||||
|
||||
@@ -6671,7 +6671,13 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
|
||||
self:Destroyed()
|
||||
end
|
||||
if self.airbase and self.airbasename and self.airbasename==EventData.IniUnitName then
|
||||
self:RunwayDestroyed()
|
||||
if self:IsRunwayOperational() then
|
||||
-- Trigger RunwayDestroyed event (only if it is not destroyed already)
|
||||
self:RunwayDestroyed()
|
||||
else
|
||||
-- Reset the time stamp.
|
||||
self.runwaydestroyed=timer.getAbsTime()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--- **Functional** - Base class that models processes to achieve goals involving a Zone for a Coalition.
|
||||
--- **Functional (WIP)** - Base class modeling processes to achieve goals involving coalition zones.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
|
||||
@@ -1,54 +1,55 @@
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Enums.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Routines.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Utils.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Profiler.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Templates.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/STTS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/FiFo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Profiler.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Routines.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Socket.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/STTS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Templates.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Utilities/Utils.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Core/Base.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Core/Astar.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Beacon.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Condition.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/UserFlag.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Report.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Scheduler.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/ScheduleDispatcher.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Event.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Settings.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Menu.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Zone.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Zone_Detection.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/ClientMenu.lua')
|
||||
__Moose.Include( 'Scripts/Moose/Core/Database.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Set.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Point.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Velocity.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Message.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Event.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Fsm.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Goal.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/MarkerOps_Base.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Menu.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Message.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Point.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Report.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/ScheduleDispatcher.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Scheduler.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Set.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Settings.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Spawn.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Timer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Goal.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Spot.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/MarkerOps_Base.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/TextAndSound.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Timer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/UserFlag.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Velocity.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Zone_Detection.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Zone.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Core/Pathline.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Object.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Identifiable.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Positionable.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Client.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Controllable.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Group.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Unit.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Client.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Identifiable.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Marker.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Object.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Positionable.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Unit.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Weapon.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Net.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Wrapper/Storage.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Cargo/Cargo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' )
|
||||
@@ -56,35 +57,67 @@ __Moose.Include( 'Scripts/Moose/Cargo/CargoSlingload.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoCrate.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoGroup.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Scoring.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/CleanUp.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Movement.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Sead.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Escort.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/MissileTrainer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/AICSAR.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/AmmoTruck.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Artillery.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/ATC_Ground.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Autolase.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/CleanUp.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Designate.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Detection.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/DetectionZones.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Designate.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/RAT.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Range.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoal.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCoalition.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneCaptureCoalition.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Artillery.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Suppression.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/PseudoATC.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Warehouse.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Escort.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Fox.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Mantis.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/MissileTrainer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Movement.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/PseudoATC.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Range.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/RAT.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Scoring.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Sead.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Shorad.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Suppression.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/Warehouse.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneCaptureCoalition.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoal.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCargo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCoalition.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/AirWing.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/ArmyGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/ATIS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Auftrag.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Awacs.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Brigade.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Chief.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Cohort.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Commander.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/CSAR.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/CTLD.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Fleet.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/FlightControl.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/FlightGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Flotilla.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Intelligence.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Legion.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/NavyGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Operation.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/OpsGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/OpsTransport.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/OpsZone.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Platoon.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/PlayerTask.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/PlayerRecce.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/RescueHelo.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/ATIS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/CTLD.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/CSAR.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Squadron.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Target.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Navigation/Navaid.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Navigation/NavFix.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Navigation/FlightPlan.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' )
|
||||
@@ -123,12 +156,12 @@ __Moose.Include( 'Scripts/Moose/Actions/Act_Route.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Actions/Act_Account.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Actions/Act_Assist.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Sound/UserSound.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Sound/SoundOutput.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Sound/Radio.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Sound/RadioQueue.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Sound/RadioSpeech.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Sound/SoundOutput.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Sound/SRS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Sound/UserSound.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/CommandCenter.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Tasking/Mission.lua' )
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
--- **NAVIGATION** - Flight Plan.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Manage navigation aids
|
||||
-- * VOR, NDB
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops%20-%20FlightPlan).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Navigation.FlightPlan
|
||||
-- @image NAVIGATION_FlightPlan.png
|
||||
|
||||
|
||||
--- FLIGHTPLAN class.
|
||||
-- @type FLIGHTPLAN
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field #table fixes Navigation fixes.
|
||||
-- @field Wrapper.Airbase#AIRBASE departureAirbase Departure airbase.
|
||||
-- @field Wrapper.Airbase#AIRBASE destinationAirbase Destination airbase.
|
||||
-- @field #number altitudeCruiseMin Minimum cruise altitude in feet MSL.
|
||||
-- @field #number altitudeCruiseMax Maximum cruise altitude in feet MSL.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The FLIGHTPLAN Concept
|
||||
--
|
||||
-- A FLIGHTPLAN consists of one or multiple FLOTILLAs. These flotillas "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
-- A new `FLIGHTPLAN` object can be created with the @{#FLIGHTPLAN.New}(`WarehouseName`, `FleetName`) function, where `WarehouseName` is the name of the static or unit object hosting the fleet
|
||||
-- and `FleetName` is the name you want to give the fleet. This must be *unique*!
|
||||
--
|
||||
-- myFlightplan=FLIGHTPLAN:New("Plan A")
|
||||
-- myFleet:SetPortZone(ZonePort1stFleet)
|
||||
-- myFleet:Start()
|
||||
--
|
||||
-- A fleet needs a *port zone*, which is set via the @{#FLIGHTPLAN.SetPortZone}(`PortZone`) function. This is the zone where the naval assets are spawned and return to.
|
||||
--
|
||||
-- Finally, the fleet needs to be started using the @{#FLIGHTPLAN.Start}() function. If the fleet is not started, it will not process any requests.
|
||||
--
|
||||
-- @field #FLIGHTPLAN
|
||||
FLIGHTPLAN = {
|
||||
ClassName = "FLIGHTPLAN",
|
||||
verbose = 0,
|
||||
fixes = {}
|
||||
}
|
||||
|
||||
--- Type of navaid
|
||||
-- @type FLIGHTPLAN.Type
|
||||
-- @field #string VOR VOR
|
||||
-- @field #string NDB NDB
|
||||
FLIGHTPLAN.TYPE={
|
||||
VOR="VOR",
|
||||
NDB="NDB",
|
||||
}
|
||||
|
||||
--- FLIGHTPLAN class version.
|
||||
-- @field #string version
|
||||
FLIGHTPLAN.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot...
|
||||
-- TODO: How to handle the FLIGHTGROUP:_LandAtAirBase
|
||||
-- TODO: Do we always need a holding pattern? https://www.faa.gov/air_traffic/publications/atpubs/aip_html/part2_enr_section_1.5.html#:~:text=If%20no%20holding%20pattern%20is,than%20that%20desired%20by%20ATC.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new FLIGHTPLAN instance.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param #string Name Name of this flight plan.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:New(Name)
|
||||
|
||||
-- Inherit everything from SCENERY class.
|
||||
self=BASE:Inherit(self, BASE:New()) -- #FLIGHTPLAN
|
||||
|
||||
-- Set alias.
|
||||
self.alias=tostring(Name)
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("FLIGHTPLAN %s | ", self.alias)
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.lid..string.format("Created FLIGHTPLAN!"))
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a new FLIGHTPLAN instance from another FLIGHTPLAN acting as blue print.
|
||||
-- The newly created flight plan is deep copied from the given one.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param #FLIGHTPLAN FlightPlan Blue print of the flight plan to copy.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:NewFromFlightPlan(FlightPlan)
|
||||
self=UTILS.DeepCopy(FlightPlan)
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add navigation fix to the flight plan.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param Navigation.NavFix#NAVFIX NavFix The nav fix.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:AddNavFix(NavFix)
|
||||
|
||||
table.insert(self.fixes, NavFix)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set depature airbase.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param #string AirbaseName Name of the airbase or AIRBASE object.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:SetDepartureAirbase(AirbaseName)
|
||||
|
||||
self.departureAirbase=AIRBASE:FindByName(AirbaseName)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set destination airbase.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param #string AirbaseName Name of the airbase or AIRBASE object.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:SetDestinationAirbase(AirbaseName)
|
||||
|
||||
self.destinationAirbase=AIRBASE:FindByName(AirbaseName)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set cruise altitude.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param #number AltMin Minimum altitude in feet MSL.
|
||||
-- @param #number AltMax Maximum altitude in feet MSL. Default is `AltMin`.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:SetCruiseAltitude(AltMin, AltMax)
|
||||
|
||||
self.altitudeCruiseMin=AltMin
|
||||
self.altitudeCruiseMax=AltMax or self.altitudeCruiseMin
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Get the name of this flight plan.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @return #string The name.
|
||||
function FLIGHTPLAN:GetName()
|
||||
return self.alias
|
||||
end
|
||||
|
||||
|
||||
--- Get cruise altitude. This returns a random altitude between the set min/max cruise altitudes.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @return #number Cruise altitude in feet MSL.
|
||||
function FLIGHTPLAN:GetCruiseAltitude()
|
||||
|
||||
local alt=10000
|
||||
if self.altitudeCruiseMin and self.altitudeCruiseMax then
|
||||
alt=math.random(self.altitudeCruiseMin, self.altitudeCruiseMax)
|
||||
elseif self.altitudeCruiseMin then
|
||||
alt=self.altitudeCruiseMin
|
||||
elseif self.altitudeCruiseMax then
|
||||
alt=self.altitudeCruiseMax
|
||||
end
|
||||
|
||||
return alt
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Private Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,212 @@
|
||||
--- **NAVIGATION** - Navigation Airspace Fix.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Stuff
|
||||
-- * More Stuff
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20NavFix).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Navigation.NavFix
|
||||
-- @image NAVIGATION_NavFix.png
|
||||
|
||||
|
||||
--- NAVFIX class.
|
||||
-- @type NAVFIX
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field #string name Name of the fix.
|
||||
-- @field Core.Point#COORDINATE coordinate Coordinate of the fix.
|
||||
-- @field Wrapper.Marker#MARKER marker Marker of fix on F10 map.
|
||||
-- @field #boolean isCompulsory Is this a compulsory fix.
|
||||
-- @field #boolean isFlyover Is this a fly over fix.
|
||||
-- @field #boolean isIAF Is initial approach fix (IAF).
|
||||
-- @field #boolean isIF Is intermediate fix (IF).
|
||||
--
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The NAVFIX Concept
|
||||
--
|
||||
-- The NAVFIX class has a great concept!
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
-- A new `NAVFIX` object can be created with the @{#NAVFIX.New}() function.
|
||||
--
|
||||
-- myTemplate=NAVFIX:New()
|
||||
-- myTemplate:SetXYZ(X, Y, Z)
|
||||
--
|
||||
-- This is how it works.
|
||||
--
|
||||
-- @field #NAVFIX
|
||||
NAVFIX = {
|
||||
ClassName = "NAVFIX",
|
||||
verbose = 0,
|
||||
}
|
||||
|
||||
--- Type of navaid
|
||||
-- @type NAVFIX.Type
|
||||
-- @field #string VOR VOR
|
||||
-- @field #string NDB NDB
|
||||
NAVFIX.Type={
|
||||
VOR="VOR",
|
||||
NDB="NDB",
|
||||
}
|
||||
|
||||
--- NAVFIX class version.
|
||||
-- @field #string version
|
||||
NAVFIX.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot...
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new NAVFIX class instance.
|
||||
-- @param #NAVFIX self
|
||||
-- @return #NAVFIX self
|
||||
function NAVFIX:New(Coordinate, Name)
|
||||
|
||||
-- Inherit everything from SCENERY class.
|
||||
self=BASE:Inherit(self, BASE:New()) -- #NAVFIX
|
||||
|
||||
self.coordinate=Coordinate
|
||||
|
||||
self.name=Name
|
||||
|
||||
self.marker=MARKER:New(Coordinate, self:_GetMarkerText())
|
||||
self.marker:ToAll()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set minimum altitude.
|
||||
-- @param #NAVFIX self
|
||||
-- @param #number Altitude Min altitude in feet.
|
||||
-- @return #NAVFIX self
|
||||
function NAVFIX:SetAltMin(Altitude)
|
||||
|
||||
self.altMin=Altitude
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set maximum altitude.
|
||||
-- @param #NAVFIX self
|
||||
-- @param #number Altitude Max altitude in feet.
|
||||
-- @return #NAVFIX self
|
||||
function NAVFIX:SetAltMax(Altitude)
|
||||
|
||||
self.altMax=Altitude
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set whether this fix is compulsory.
|
||||
-- @param #NAVFIX self
|
||||
-- @param #boolean Compulsory If `true`, this is a compusory fix. If `false` or nil, it is non-compulsory.
|
||||
-- @return #NAVFIX self
|
||||
function NAVFIX:SetCompulsory(Compulsory)
|
||||
self.isCompulsory=Compulsory
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set whether this fix is compulsory.
|
||||
-- @param #NAVFIX self
|
||||
-- @param #boolean FlyOver If `true`, this is a fly over fix. If `false` or nil, it is not.
|
||||
-- @return #NAVFIX self
|
||||
function NAVFIX:SetFlyOver(FlyOver)
|
||||
self.isFlyover=FlyOver
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set whether this is the intermediate fix.
|
||||
-- @param #NAVFIX self
|
||||
-- @param #boolean IntermediateFix If `true`, this is an intermediate fix.
|
||||
-- @return #NAVFIX self
|
||||
function NAVFIX:SetIntermediateFix(IntermediateFix)
|
||||
self.isIF=IntermediateFix
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set whether this is an initial approach fix (IAF).
|
||||
-- @param #NAVFIX self
|
||||
-- @param #boolean IntermediateFix If `true`, this is an intermediate fix.
|
||||
-- @return #NAVFIX self
|
||||
function NAVFIX:SetInitialApproachFix(IntermediateFix)
|
||||
self.isIAF=IntermediateFix
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get the altitude in feet MSL.
|
||||
-- @param #NAVFIX self
|
||||
-- @return #number Altitude in feet MSL. Can be `#nil`
|
||||
function NAVFIX:GetAltitude()
|
||||
|
||||
local alt=nil
|
||||
if self.altMin and self.altMax then
|
||||
alt=math.random(self.altMin, self.altMax)
|
||||
elseif self.altMin then
|
||||
alt=self.altMin
|
||||
elseif self.altMax then
|
||||
alt=self.altMax
|
||||
end
|
||||
|
||||
return alt
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Private Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Get text displayed in the F10 marker.
|
||||
-- @param #NAVFIX self
|
||||
-- @return #string Marker text.
|
||||
function NAVFIX:_GetMarkerText()
|
||||
|
||||
local altmin=self.altMin and tostring(self.altMin) or ""
|
||||
local altmax=self.altMax and tostring(self.altMax) or ""
|
||||
local speedmin=self.speedMin and tostring(self.speedMin) or ""
|
||||
local speedmax=self.speedMax and tostring(self.speedMax) or ""
|
||||
|
||||
|
||||
local text=string.format("NAVFIX %s", self.name)
|
||||
if self.isIAF then
|
||||
text=text..string.format(" (IAF)")
|
||||
end
|
||||
if self.isIF then
|
||||
text=text..string.format(" (IF)")
|
||||
end
|
||||
text=text..string.format("\nAltitude: %s - %s", altmin, altmax)
|
||||
text=text..string.format("\nSpeed: %s - %s", speedmin, speedmax)
|
||||
text=text..string.format("\nCompulsory: %s", tostring(self.isCompulsory))
|
||||
text=text..string.format("\nFly Over: %s", tostring(self.isFlyover))
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,172 @@
|
||||
--- **Navigation** - Navigation aid.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Manage navigation aids
|
||||
-- * VOR, NDB
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20Navaid).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Navigation.Navaid
|
||||
-- @image Navigation_Navaid.png
|
||||
|
||||
|
||||
--- NAVAID class.
|
||||
-- @type NAVAID
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The NAVAID Concept
|
||||
--
|
||||
-- A NAVAID consists of one or multiple FLOTILLAs. These flotillas "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
-- A new `NAVAID` object can be created with the @{#NAVAID.New}(`WarehouseName`, `FleetName`) function, where `WarehouseName` is the name of the static or unit object hosting the fleet
|
||||
-- and `FleetName` is the name you want to give the fleet. This must be *unique*!
|
||||
--
|
||||
-- myFleet=NAVAID:New("myWarehouseName", "1st Fleet")
|
||||
-- myFleet:SetPortZone(ZonePort1stFleet)
|
||||
-- myFleet:Start()
|
||||
--
|
||||
-- A fleet needs a *port zone*, which is set via the @{#NAVAID.SetPortZone}(`PortZone`) function. This is the zone where the naval assets are spawned and return to.
|
||||
--
|
||||
-- Finally, the fleet needs to be started using the @{#NAVAID.Start}() function. If the fleet is not started, it will not process any requests.
|
||||
--
|
||||
-- @field #NAVAID
|
||||
NAVAID = {
|
||||
ClassName = "NAVAID",
|
||||
verbose = 0,
|
||||
}
|
||||
|
||||
--- Type of navaid
|
||||
-- @type NAVAID.Type
|
||||
-- @field #string VOR VOR
|
||||
-- @field #string NDB NDB
|
||||
NAVAID.TYPE={
|
||||
VOR="VOR",
|
||||
NDB="NDB",
|
||||
}
|
||||
|
||||
--- NAVAID class version.
|
||||
-- @field #string version
|
||||
NAVAID.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot...
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new NAVAID class instance.
|
||||
-- @param #NAVAID self
|
||||
-- @param #string ZoneName Name of the zone to scan the scenery.
|
||||
-- @param #string SceneryName Name of the scenery object.
|
||||
-- @param #string Type Type of Navaid.
|
||||
-- @return #NAVAID self
|
||||
function NAVAID:New(ZoneName, SceneryName, Type)
|
||||
|
||||
-- Inherit everything from SCENERY class.
|
||||
self=BASE:Inherit(self, BASE:New()) -- #NAVAID
|
||||
|
||||
|
||||
self.zone=ZONE:FindByName(ZoneName)
|
||||
|
||||
self.coordinate=self.zone:GetCoordinate()
|
||||
|
||||
if SceneryName then
|
||||
self.scenery=SCENERY:FindByNameInZone(SceneryName, ZoneName)
|
||||
if not self.scenery then
|
||||
self:E("ERROR: Could not find scenery object %s in zone %s", SceneryName, ZoneName)
|
||||
end
|
||||
end
|
||||
|
||||
self.alias=string.format("%s %s %s", tostring(ZoneName), tostring(SceneryName), tostring(Type))
|
||||
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("NAVAID %s | ", self.alias)
|
||||
|
||||
self:I(self.lid..string.format("Created NAVAID!"))
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set frequency.
|
||||
-- @param #NAVAID self
|
||||
-- @param #number Frequency Frequency in Hz.
|
||||
-- @return #NAVAID self
|
||||
function NAVAID:SetFrequency(Frequency)
|
||||
|
||||
self.frequency=Frequency
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set channel.
|
||||
-- @param #NAVAID self
|
||||
-- @param #number Channel
|
||||
-- @param #string Band
|
||||
-- @return #NAVAID self
|
||||
function NAVAID:SetChannel(Channel, Band)
|
||||
|
||||
self.channel=Channel
|
||||
self.band=Band
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add marker the NAVAID on the F10 map.
|
||||
-- @param #NAVAID self
|
||||
-- @return #NAVAID self
|
||||
function NAVAID:AddMarker()
|
||||
|
||||
local text=string.format("I am a NAVAID!")
|
||||
|
||||
self.markID=self.coordinate:MarkToAll(text, true)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove marker of the NAVAID from the F10 map.
|
||||
-- @param #NAVAID self
|
||||
-- @return #NAVAID self
|
||||
function NAVAID:DelMarker()
|
||||
|
||||
if self.markID then
|
||||
UTILS.RemoveMark(self.markID)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Private Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,108 @@
|
||||
--- **NAVIGATION** - Template.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Stuff
|
||||
-- * More Stuff
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20Template).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Navigation.Template
|
||||
-- @image NAVIGATION_Template.png
|
||||
|
||||
|
||||
--- TEMPLATE class.
|
||||
-- @type TEMPLATE
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The TEMPLATE Concept
|
||||
--
|
||||
-- The TEMPLATE class has a great concept!
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
-- A new `TEMPLATE` object can be created with the @{#TEMPLATE.New}() function.
|
||||
--
|
||||
-- myTemplate=TEMPLATE:New()
|
||||
-- myTemplate:SetXYZ(X, Y, Z)
|
||||
--
|
||||
-- This is how it works.
|
||||
--
|
||||
-- @field #TEMPLATE
|
||||
TEMPLATE = {
|
||||
ClassName = "TEMPLATE",
|
||||
verbose = 0,
|
||||
}
|
||||
|
||||
--- Type of navaid
|
||||
-- @type TEMPLATE.Type
|
||||
-- @field #string VOR VOR
|
||||
-- @field #string NDB NDB
|
||||
TEMPLATE.TYPE={
|
||||
VOR="VOR",
|
||||
NDB="NDB",
|
||||
}
|
||||
|
||||
--- TEMPLATE class version.
|
||||
-- @field #string version
|
||||
TEMPLATE.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot...
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new TEMPLATE class instance.
|
||||
-- @param #TEMPLATE self
|
||||
-- @return #TEMPLATE self
|
||||
function TEMPLATE:New()
|
||||
|
||||
-- Inherit everything from SCENERY class.
|
||||
self=BASE:Inherit(self, BASE:New()) -- #TEMPLATE
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set frequency.
|
||||
-- @param #TEMPLATE self
|
||||
-- @param #number Frequency Frequency in Hz.
|
||||
-- @return #TEMPLATE self
|
||||
function TEMPLATE:SetFrequency(Frequency)
|
||||
|
||||
self.frequency=Frequency
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Private Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -46,7 +46,6 @@
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- ### Additions for SRS and FARP: **applevangelist**
|
||||
--
|
||||
-- @module Ops.ATIS
|
||||
-- @image OPS_ATIS.png
|
||||
@@ -420,8 +419,6 @@ ATIS.RunwayM2T = {
|
||||
TheChannel = -10,
|
||||
Syria = 5,
|
||||
MarianaIslands = 2,
|
||||
Falklands = 12,
|
||||
Sinai = 5,
|
||||
}
|
||||
|
||||
--- Whether ICAO phraseology is used for ATIS broadcasts.
|
||||
@@ -433,8 +430,6 @@ ATIS.RunwayM2T = {
|
||||
-- @field #boolean TheChannel true.
|
||||
-- @field #boolean Syria true.
|
||||
-- @field #boolean MarianaIslands true.
|
||||
-- @field #boolean Falklands true.
|
||||
-- @field #boolean Sinai true.
|
||||
ATIS.ICAOPhraseology = {
|
||||
Caucasus = true,
|
||||
Nevada = false,
|
||||
@@ -442,9 +437,7 @@ ATIS.ICAOPhraseology = {
|
||||
PersianGulf = true,
|
||||
TheChannel = true,
|
||||
Syria = true,
|
||||
MarianaIslands = true,
|
||||
Falklands = true,
|
||||
Sinai = true,
|
||||
MarianaIslands = true
|
||||
}
|
||||
|
||||
--- Nav point data.
|
||||
@@ -616,7 +609,7 @@ _ATIS = {}
|
||||
|
||||
--- ATIS class version.
|
||||
-- @field #string version
|
||||
ATIS.version = "0.9.16"
|
||||
ATIS.version = "0.9.15"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -1279,9 +1272,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function ATIS:onafterStart( From, Event, To )
|
||||
self:T({From, Event, To})
|
||||
self:T("Airbase category is "..self.airbase:GetAirbaseCategory())
|
||||
|
||||
|
||||
-- Check that this is an airdrome.
|
||||
if self.airbase:GetAirbaseCategory() == Airbase.Category.SHIP then
|
||||
self:E( self.lid .. string.format( "ERROR: Cannot start ATIS for airbase %s! Only AIRDROMES are supported but NOT SHIPS.", self.airbasename ) )
|
||||
@@ -1342,7 +1333,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function ATIS:onafterStatus( From, Event, To )
|
||||
self:T({From, Event, To})
|
||||
|
||||
-- Get FSM state.
|
||||
local fsmstate = self:GetState()
|
||||
|
||||
@@ -1364,7 +1355,7 @@ function ATIS:onafterStatus( From, Event, To )
|
||||
self:T( self.lid .. text )
|
||||
|
||||
if not self:Is("Stopped") then
|
||||
self:__Status( 60 )
|
||||
self:__Status( -60 )
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1378,26 +1369,25 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function ATIS:onafterCheckQueue( From, Event, To )
|
||||
self:T({From, Event, To})
|
||||
if not self:Is("Stopped") then
|
||||
if self.useSRS then
|
||||
|
||||
if self.useSRS then
|
||||
|
||||
self:Broadcast()
|
||||
|
||||
else
|
||||
|
||||
if #self.radioqueue.queue == 0 then
|
||||
self:T( self.lid .. string.format( "Radio queue empty. Repeating message." ) )
|
||||
self:Broadcast()
|
||||
|
||||
else
|
||||
|
||||
if #self.radioqueue.queue == 0 then
|
||||
self:T( self.lid .. string.format( "Radio queue empty. Repeating message." ) )
|
||||
self:Broadcast()
|
||||
else
|
||||
self:T2( self.lid .. string.format( "Radio queue %d transmissions queued.", #self.radioqueue.queue ) )
|
||||
end
|
||||
|
||||
self:T2( self.lid .. string.format( "Radio queue %d transmissions queued.", #self.radioqueue.queue ) )
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
if not self:Is("Stopped") then
|
||||
-- Check back in 5 seconds.
|
||||
self:__CheckQueue( math.abs( self.dTQueueCheck ) )
|
||||
self:__CheckQueue( -math.abs( self.dTQueueCheck ) )
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1407,7 +1397,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function ATIS:onafterBroadcast( From, Event, To )
|
||||
self:T({From, Event, To})
|
||||
|
||||
-- Get current coordinate.
|
||||
local coord = self.airbase:GetCoordinate()
|
||||
|
||||
@@ -1833,10 +1823,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
|
||||
-- Airbase name
|
||||
subtitle = string.format( "%s", self.airbasename )
|
||||
if (not self.ATISforFARPs) and self.airbasename:find( "AFB" ) == nil and self.airbasename:find( "Airport" ) == nil
|
||||
and self.airbasename:find( "Airstrip" ) == nil and self.airbasename:find( "airfield" ) == nil and self.airbasename:find( "AB" ) == nil
|
||||
and self.airbasename:find( "Field" ) == nil
|
||||
then
|
||||
if (not self.ATISforFARPs) and self.airbasename:find( "AFB" ) == nil and self.airbasename:find( "Airport" ) == nil and self.airbasename:find( "Airstrip" ) == nil and self.airbasename:find( "airfield" ) == nil and self.airbasename:find( "AB" ) == nil then
|
||||
subtitle = subtitle .. " Airport"
|
||||
end
|
||||
if not self.useSRS then
|
||||
@@ -2159,9 +2146,8 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
|
||||
if not self.ATISforFARPs then
|
||||
-- Active runway.
|
||||
local subtitle
|
||||
if runwayLanding then
|
||||
subtitle=string.format("Active runway %s", runwayLanding)
|
||||
local subtitle=string.format("Active runway %s", runwayLanding)
|
||||
if rwyLandingLeft==true then
|
||||
subtitle=subtitle.." Left"
|
||||
elseif rwyLandingLeft==false then
|
||||
@@ -2421,7 +2407,6 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #string Text Report text.
|
||||
function ATIS:onafterReport( From, Event, To, Text )
|
||||
self:T({From, Event, To})
|
||||
self:T( self.lid .. string.format( "Report:\n%s", Text ) )
|
||||
|
||||
if self.useSRS and self.msrs then
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -152,12 +152,16 @@
|
||||
-- @field #boolean ICLSon Automatic ICLS is activated.
|
||||
-- @field #number ICLSchannel ICLS channel.
|
||||
-- @field #string ICLSmorse ICLS morse code, e.g. "STN".
|
||||
-- @field #AIRBOSS.Radio PilotRadio Radio for Pilot calls.
|
||||
-- @field #AIRBOSS.Radio LSORadio Radio for LSO calls.
|
||||
-- @field #number LSOFreq LSO radio frequency in MHz.
|
||||
-- @field #string LSOModu LSO radio modulation "AM" or "FM".
|
||||
-- @field #AIRBOSS.Radio MarshalRadio Radio for carrier calls.
|
||||
-- @field #number MarshalFreq Marshal radio frequency in MHz.
|
||||
-- @field #string MarshalModu Marshal radio modulation "AM" or "FM".
|
||||
-- @field #AIRBOSS.Radio AirbossRadio Radio for carrier calls.
|
||||
-- @field #number AirbossFreq Airboss radio frequency in MHz.
|
||||
-- @field #string AirbossModu Airboss radio modulation "AM" or "FM".
|
||||
-- @field #number TowerFreq Tower radio frequency in MHz.
|
||||
-- @field Core.Scheduler#SCHEDULER radiotimer Radio queue scheduler.
|
||||
-- @field Core.Zone#ZONE_UNIT zoneCCA Carrier controlled area (CCA), i.e. a zone of 50 NM radius around the carrier.
|
||||
@@ -1731,6 +1735,10 @@ AIRBOSS.Difficulty = {
|
||||
-- @field #table trapsheet Groove data table recorded every 0.5 seconds.
|
||||
-- @field #boolean trapon If true, save trap sheets.
|
||||
-- @field #string debriefschedulerID Debrief scheduler ID.
|
||||
--
|
||||
-- @field Sound.SRS#MSRS SRS
|
||||
-- @field Sound.SRS#MSRSQUEUE SRSQ
|
||||
--
|
||||
-- @extends #AIRBOSS.FlightGroup
|
||||
|
||||
--- Main group level radio menu: F10 Other/Airboss.
|
||||
@@ -1743,7 +1751,7 @@ AIRBOSS.MenuF10Root = nil
|
||||
|
||||
--- Airboss class version.
|
||||
-- @field #string version
|
||||
AIRBOSS.version = "1.3.0"
|
||||
AIRBOSS.version = "1.3.2"
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1876,6 +1884,7 @@ function AIRBOSS:New( carriername, alias )
|
||||
|
||||
-- Set up Airboss radio.
|
||||
self:SetMarshalRadio()
|
||||
self:SetAirbossRadio()
|
||||
|
||||
-- Set up LSO radio.
|
||||
self:SetLSORadio()
|
||||
@@ -2847,7 +2856,7 @@ function AIRBOSS:SetGlideslopeErrorThresholds(_max,_min, High, HIGH, Low, LOW)
|
||||
|
||||
--Check if V/STOL Carrier
|
||||
if self.carriertype == AIRBOSS.CarrierType.INVINCIBLE or self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
|
||||
|
||||
|
||||
-- allow a larger GSE for V/STOL operations --Pene Testing
|
||||
self.gle._max=_max or 0.7
|
||||
self.gle.High=High or 1.4
|
||||
@@ -2864,7 +2873,7 @@ function AIRBOSS:SetGlideslopeErrorThresholds(_max,_min, High, HIGH, Low, LOW)
|
||||
self.gle.Low=Low or -0.6
|
||||
self.gle.LOW=LOW or -0.9
|
||||
end
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -2884,7 +2893,7 @@ function AIRBOSS:SetLineupErrorThresholds(_max,_min, Left, LeftMed, LEFT, Right,
|
||||
|
||||
--Check if V/STOL Carrier -- Pene testing
|
||||
if self.carriertype == AIRBOSS.CarrierType.INVINCIBLE or self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
|
||||
|
||||
|
||||
-- V/STOL Values -- allow a larger LUE for V/STOL operations
|
||||
self.lue._max=_max or 1.8
|
||||
self.lue._min=_min or -1.8
|
||||
@@ -2905,7 +2914,7 @@ function AIRBOSS:SetLineupErrorThresholds(_max,_min, Left, LeftMed, LEFT, Right,
|
||||
self.lue.RightMed=RightMed or 2.0
|
||||
self.lue.RIGHT=RIGHT or 3.0
|
||||
end
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -3043,12 +3052,56 @@ function AIRBOSS:SetBeaconRefresh( TimeInterval )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set up SRS for usage without sound files
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #string PathToSRS Path to SRS folder, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone".
|
||||
-- @param #number Port Port of the SRS server, defaults to 5002.
|
||||
-- @param #string Culture (Optional, Airboss Culture) Culture, defaults to "en-US".
|
||||
-- @param #string Gender (Optional, Airboss Gender) Gender, e.g. "male" or "female". Defaults to "male".
|
||||
-- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings.
|
||||
-- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json".
|
||||
-- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest).
|
||||
-- @param #table AltBackend (Optional) See MSRS for details.
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volume,AltBackend)
|
||||
-- SRS
|
||||
local Frequency = self.AirbossRadio.frequency
|
||||
local Modulation = self.AirbossRadio.modulation
|
||||
self.SRS = MSRS:New(PathToSRS,Frequency,Modulation,Volume,AltBackend)
|
||||
self.SRS:SetCoalition(self:GetCoalition())
|
||||
self.SRS:SetCoordinate(self:GetCoordinate())
|
||||
self.SRS:SetCulture(Culture or "en-US")
|
||||
--self.SRS:SetFrequencies(Frequencies)
|
||||
self.SRS:SetGender(Gender or "male")
|
||||
self.SRS:SetPath(PathToSRS)
|
||||
self.SRS:SetPort(Port or 5002)
|
||||
self.SRS:SetLabel(self.AirbossRadio.alias or "AIRBOSS")
|
||||
--self.SRS:SetModulations(Modulations)
|
||||
if GoogleCreds then
|
||||
self.SRS:SetGoogle(GoogleCreds)
|
||||
end
|
||||
if Voice then
|
||||
self.SRS:SetVoice(Voice)
|
||||
end
|
||||
self.SRS:SetVolume(Volume or 1.0)
|
||||
-- SRSQUEUE
|
||||
self.SRSQ = MSRSQUEUE:New("AIRBOSS")
|
||||
self.SRSQ:SetTransmitOnlyWithPlayers(true)
|
||||
if not self.PilotRadio then
|
||||
self:SetSRSPilotVoice()
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number Frequency (Optional) Frequency in MHz. Default 264 MHz.
|
||||
-- @param #string Modulation (Optional) Modulation, "AM" or "FM". Default "AM".
|
||||
-- @param #string Voice (Optional) SRS specific voice
|
||||
-- @param #string Gender (Optional) SRS specific gender
|
||||
-- @param #string Culture (Optional) SRS specific culture
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetLSORadio( Frequency, Modulation )
|
||||
function AIRBOSS:SetLSORadio( Frequency, Modulation, Voice, Gender, Culture )
|
||||
|
||||
self.LSOFreq = (Frequency or 264)
|
||||
Modulation = Modulation or "AM"
|
||||
@@ -3063,16 +3116,62 @@ function AIRBOSS:SetLSORadio( Frequency, Modulation )
|
||||
self.LSORadio.frequency = self.LSOFreq
|
||||
self.LSORadio.modulation = self.LSOModu
|
||||
self.LSORadio.alias = "LSO"
|
||||
self.LSORadio.voice = Voice
|
||||
self.LSORadio.gender = Gender or "male"
|
||||
self.LSORadio.culture = Culture or "en-US"
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set carrier radio frequency and modulation. Default frequency is 305 MHz AM.
|
||||
--- Set Airboss radio frequency and modulation. Default frequency is Tower frequency.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number Frequency (Optional) Frequency in MHz. Default frequency is Tower frequency.
|
||||
-- @param #string Modulation (Optional) Modulation, "AM" or "FM". Default "AM".
|
||||
-- @param #string Voice (Optional) SRS specific voice
|
||||
-- @param #string Gender (Optional) SRS specific gender
|
||||
-- @param #string Culture (Optional) SRS specific culture
|
||||
-- @return #AIRBOSS self
|
||||
-- @usage
|
||||
-- -- Set single frequency
|
||||
-- myairboss:SetAirbossRadio(127.5,"AM",MSRS.Voices.Google.Standard.en_GB_Standard_F)
|
||||
--
|
||||
-- -- Set multiple frequencies, note you **need** to pass one modulation per frequency given!
|
||||
-- myairboss:SetAirbossRadio({127.5,243},{radio.modulation.AM,radio.modulation.AM},MSRS.Voices.Google.Standard.en_GB_Standard_F)
|
||||
function AIRBOSS:SetAirbossRadio( Frequency, Modulation, Voice, Gender, Culture )
|
||||
|
||||
self.AirbossFreq = Frequency or self:_GetTowerFrequency() or 127.5
|
||||
Modulation = Modulation or "AM"
|
||||
|
||||
if type(Modulation) == "table" then
|
||||
self.AirbossModu = Modulation
|
||||
else
|
||||
if Modulation == "FM" then
|
||||
self.AirbossModu = radio.modulation.FM
|
||||
else
|
||||
self.AirbossModu = radio.modulation.AM
|
||||
end
|
||||
end
|
||||
|
||||
self.AirbossRadio = {} -- #AIRBOSS.Radio
|
||||
self.AirbossRadio.frequency = self.AirbossFreq
|
||||
self.AirbossRadio.modulation = self.AirbossModu
|
||||
self.AirbossRadio.alias = "AIRBOSS"
|
||||
self.AirbossRadio.voice = Voice
|
||||
self.AirbossRadio.gender = Gender or "male"
|
||||
self.AirbossRadio.culture = Culture or "en-US"
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set Marshal radio frequency and modulation. Default frequency is 305 MHz AM.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number Frequency (Optional) Frequency in MHz. Default 305 MHz.
|
||||
-- @param #string Modulation (Optional) Modulation, "AM" or "FM". Default "AM".
|
||||
-- @param #string Voice (Optional) SRS specific voice
|
||||
-- @param #string Gender (Optional) SRS specific gender
|
||||
-- @param #string Culture (Optional) SRS specific culture
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetMarshalRadio( Frequency, Modulation )
|
||||
function AIRBOSS:SetMarshalRadio( Frequency, Modulation, Voice, Gender, Culture )
|
||||
|
||||
self.MarshalFreq = Frequency or 305
|
||||
Modulation = Modulation or "AM"
|
||||
@@ -3087,6 +3186,9 @@ function AIRBOSS:SetMarshalRadio( Frequency, Modulation )
|
||||
self.MarshalRadio.frequency = self.MarshalFreq
|
||||
self.MarshalRadio.modulation = self.MarshalModu
|
||||
self.MarshalRadio.alias = "MARSHAL"
|
||||
self.MarshalRadio.voice = Voice
|
||||
self.MarshalRadio.gender = Gender or "male"
|
||||
self.MarshalRadio.culture = Culture or "en-US"
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -3268,7 +3370,7 @@ function AIRBOSS:SetExtraVoiceOversAI(status)
|
||||
self.xtVoiceOversAI=status
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Do not handle AI aircraft.
|
||||
-- @param #AIRBOSS self
|
||||
-- @return #AIRBOSS self
|
||||
@@ -3383,9 +3485,9 @@ end
|
||||
-- @param #string Host Host. Default `"127.0.0.1"`.
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetFunkManOn(Port, Host)
|
||||
|
||||
|
||||
self.funkmanSocket=SOCKET:New(Port, Host)
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -5822,64 +5924,27 @@ function AIRBOSS:_ScanCarrierZone()
|
||||
-- Get aircraft type name.
|
||||
local actype = group:GetTypeName()
|
||||
|
||||
-- Create a new flight group
|
||||
if knownflight then
|
||||
|
||||
-- Debug output.
|
||||
self:T2(self.lid..string.format("Known flight group %s of type %s in CCA.", groupname, actype))
|
||||
|
||||
-- Check if flight is AI and if we want to handle it at all.
|
||||
if knownflight.ai and self.handleai then
|
||||
if knownflight.ai and knownflight.flag == -100 and self.handleai then
|
||||
|
||||
-- Defines if AI group should be handled by the airboss.
|
||||
local iscarriersquad=true
|
||||
local putintomarshal = false
|
||||
|
||||
-- Check if AI group is part of the group set if a set was defined.
|
||||
if self.squadsetAI then
|
||||
local group=self.squadsetAI:FindGroup(groupname)
|
||||
if group then
|
||||
iscarriersquad=true
|
||||
-- Get flight group.
|
||||
local flight = _DATABASE:GetOpsGroup( groupname )
|
||||
|
||||
if flight and flight:IsInbound() and flight.destbase:GetName() == self.carrier:GetName() then
|
||||
if flight.ishelo then
|
||||
else
|
||||
iscarriersquad=false
|
||||
putintomarshal = true
|
||||
end
|
||||
flight.airboss = self
|
||||
end
|
||||
|
||||
-- Check if group was explicitly excluded.
|
||||
if self.excludesetAI then
|
||||
local group=self.excludesetAI:FindGroup(groupname)
|
||||
if group then
|
||||
iscarriersquad=false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Get distance to carrier.
|
||||
local dist=knownflight.group:GetCoordinate():Get2DDistance(self:GetCoordinate())
|
||||
|
||||
-- Close in distance. Is >0 if AC comes closer wrt to first detected distance d0.
|
||||
local closein=knownflight.dist0-dist
|
||||
|
||||
-- Debug info.
|
||||
self:T3(self.lid..string.format("Known AI flight group %s closed in by %.1f NM", knownflight.groupname, UTILS.MetersToNM(closein)))
|
||||
|
||||
-- Is this group the tanker?
|
||||
local istanker=self.tanker and self.tanker.tanker:GetName()==groupname
|
||||
|
||||
-- Is this group the AWACS?
|
||||
local isawacs=self.awacs and self.awacs.tanker:GetName()==groupname
|
||||
|
||||
-- Send tanker to marshal stack?
|
||||
local tanker2marshal = istanker and self.tanker:IsReturning() and self.tanker.airbase:GetName()==self.airbase:GetName() and knownflight.flag==-100 and self.tanker.recovery==true
|
||||
|
||||
-- Send AWACS to marhsal stack?
|
||||
local awacs2marshal = isawacs and self.awacs:IsReturning() and self.awacs.airbase:GetName()==self.airbase:GetName() and knownflight.flag==-100 and self.awacs.recovery==true
|
||||
|
||||
-- Put flight into Marshal.
|
||||
local putintomarshal=closein>UTILS.NMToMeters(5) and knownflight.flag==-100 and iscarriersquad and istanker==false and isawacs==false
|
||||
|
||||
-- Send AI flight to marshal stack if group closes in more than 5 and has initial flag value.
|
||||
if putintomarshal or tanker2marshal or awacs2marshal then
|
||||
|
||||
-- Send AI flight to marshal stack.
|
||||
if putintomarshal then
|
||||
|
||||
-- Get the next free stack for current recovery case.
|
||||
local stack = self:_GetFreeStack( knownflight.ai )
|
||||
@@ -6401,7 +6466,7 @@ function AIRBOSS:_LandAI( flight )
|
||||
-- Aircraft speed when flying the pattern.
|
||||
local Speed = UTILS.KnotsToKmph( 200 )
|
||||
|
||||
if flight.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||
if flight.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||
or flight.actype == AIRBOSS.AircraftCarrier.FA18C
|
||||
or flight.actype == AIRBOSS.AircraftCarrier.RHINOE
|
||||
or flight.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||
@@ -8139,7 +8204,7 @@ end
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AIRBOSS:OnEventBirth( EventData )
|
||||
self:F3( { eventbirth = EventData } )
|
||||
|
||||
|
||||
-- Nil checks.
|
||||
if EventData == nil then
|
||||
self:E( self.lid .. "ERROR: EventData=nil in event BIRTH!" )
|
||||
@@ -8151,9 +8216,9 @@ function AIRBOSS:OnEventBirth( EventData )
|
||||
self:E( EventData )
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if EventData.IniObjectCategory ~= Object.Category.UNIT then return end
|
||||
|
||||
|
||||
local _unitName = EventData.IniUnitName
|
||||
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
||||
|
||||
@@ -9231,9 +9296,9 @@ function AIRBOSS:_DirtyUp( playerData )
|
||||
self:_PlayerHint( playerData )
|
||||
|
||||
-- Radio call "Say/Fly needles". Delayed by 10/15 seconds.
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.F14A
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.F14A
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER
|
||||
@@ -9830,24 +9895,24 @@ function AIRBOSS:_Groove( playerData )
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Long V/STOL groove time Wave Off over 75 seconds to IC - TOPGUN level Only. --pene testing (WIP)--- Need to think more about this.
|
||||
|
||||
|
||||
--if rho>=RAR and rho<=RIC and not playerData.waveoff and playerData.difficulty==AIRBOSS.Difficulty.HARD and playerData.actype== AIRBOSS.AircraftCarrier.AV8B then
|
||||
-- Get groove time
|
||||
--local vSlow=groovedata.time
|
||||
-- If too slow wave off.
|
||||
-- If too slow wave off.
|
||||
--if vSlow >75 then
|
||||
|
||||
|
||||
-- LSO Wave off!
|
||||
--self:RadioTransmission(self.LSORadio, self.LSOCall.WAVEOFF, nil, nil, nil, true)
|
||||
--playerData.Tlso=timer.getTime()
|
||||
|
||||
|
||||
-- Player was waved Off
|
||||
--playerData.waveoff=true
|
||||
--return
|
||||
--end
|
||||
--end
|
||||
--end
|
||||
|
||||
-- Groovedata step.
|
||||
@@ -10045,7 +10110,7 @@ function AIRBOSS:_CheckWaveOff( glideslopeError, lineupError, AoA, playerData )
|
||||
waveoff = true
|
||||
end
|
||||
|
||||
-- Too slow or too fast? Only for pros.
|
||||
-- Too slow or too fast? Only for pros.
|
||||
|
||||
if playerData.difficulty == AIRBOSS.Difficulty.HARD and playerData.actype ~= AIRBOSS.AircraftCarrier.AV8B then
|
||||
-- Get aircraft specific AoA values. Not for AV-8B due to transition to Stable Hover.
|
||||
@@ -10201,7 +10266,7 @@ function AIRBOSS:_GetSternCoord()
|
||||
elseif case==2 or case==1 then
|
||||
-- V/Stol: Translate 8 meters port.
|
||||
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true)
|
||||
end
|
||||
end
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
||||
-- Stennis: translate 7 meters starboard wrt Final bearing.
|
||||
self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( 7, FB + 90, true, true )
|
||||
@@ -10350,7 +10415,7 @@ function AIRBOSS:_Trapped( playerData )
|
||||
|
||||
-- Get current wire (estimate). This now based on the position where the player comes to a standstill which should reflect the trapped wire better.
|
||||
local dcorr = 100
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.HORNET
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOE
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.RHINOF
|
||||
or playerData.actype == AIRBOSS.AircraftCarrier.GROWLER then
|
||||
@@ -10875,7 +10940,7 @@ function AIRBOSS:_GetZoneAbeamLandingSpot()
|
||||
|
||||
-- Coordinate array. Pene Testing extended Abeam landing spot V/STOL.
|
||||
local p={}
|
||||
|
||||
|
||||
-- Points.
|
||||
p[1] = S:Translate( 15, FB ):Translate( 15, FB + 90 ) -- Top-Right
|
||||
p[2] = S:Translate( -45, FB ):Translate( 15, FB + 90 ) -- Bottom-Right
|
||||
@@ -11323,7 +11388,7 @@ function AIRBOSS:_GetOptLandingCoordinate()
|
||||
|
||||
-- set Case III V/STOL abeam landing spot over deck -- Pene Testing
|
||||
if self.carriertype==AIRBOSS.CarrierType.INVINCIBLE or self.carriertype==AIRBOSS.CarrierType.HERMES or self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
|
||||
|
||||
|
||||
if case==3 then
|
||||
|
||||
-- Landing coordinate.
|
||||
@@ -11331,7 +11396,7 @@ function AIRBOSS:_GetOptLandingCoordinate()
|
||||
|
||||
-- Altitude 120ft -- is this corect for Case III?
|
||||
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
|
||||
|
||||
|
||||
elseif case==2 or case==1 then
|
||||
|
||||
-- Landing 100 ft abeam, 120 ft alt.
|
||||
@@ -11341,7 +11406,7 @@ function AIRBOSS:_GetOptLandingCoordinate()
|
||||
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
|
||||
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
|
||||
-- Ideally we want to land between 2nd and 3rd wire.
|
||||
@@ -11485,8 +11550,48 @@ end
|
||||
-- @return #number Carrier heading in degrees.
|
||||
function AIRBOSS:GetHeadingIntoWind( magnetic, coord )
|
||||
|
||||
local function adjustDegreesForWindSpeed(windSpeed)
|
||||
local degreesAdjustment = 0
|
||||
-- the windspeeds are in m/s
|
||||
|
||||
-- +0 degrees at 15m/s = 37kts
|
||||
-- +0 degrees at 14m/s = 35kts
|
||||
-- +0 degrees at 13m/s = 33kts
|
||||
-- +4 degrees at 12m/s = 31kts
|
||||
-- +4 degrees at 11m/s = 29kts
|
||||
-- +4 degrees at 10m/s = 27kts
|
||||
-- +4 degrees at 9m/s = 27kts
|
||||
-- +4 degrees at 8m/s = 27kts
|
||||
-- +8 degrees at 7m/s = 27kts
|
||||
-- +8 degrees at 6m/s = 27kts
|
||||
-- +8 degrees at 5m/s = 26kts
|
||||
-- +20 degrees at 4m/s = 26kts
|
||||
-- +20 degrees at 3m/s = 26kts
|
||||
-- +30 degrees at 2m/s = 26kts 1s
|
||||
|
||||
if windSpeed > 0 and windSpeed < 3 then
|
||||
degreesAdjustment = 30
|
||||
elseif windSpeed >= 3 and windSpeed < 5 then
|
||||
degreesAdjustment = 20
|
||||
elseif windSpeed >= 5 and windSpeed < 8 then
|
||||
degreesAdjustment = 8
|
||||
elseif windSpeed >= 8 and windSpeed < 13 then
|
||||
degreesAdjustment = 4
|
||||
elseif windSpeed >= 13 then
|
||||
degreesAdjustment = 0
|
||||
end
|
||||
|
||||
return degreesAdjustment
|
||||
end
|
||||
|
||||
-- Get direction the wind is blowing from. This is where we want to go.
|
||||
local windfrom, vwind = self:GetWind( nil, nil, coord )
|
||||
|
||||
--self:I("windfrom="..windfrom.." vwind="..vwind)
|
||||
|
||||
vwind = vwind + adjustDegreesForWindSpeed(vwind)
|
||||
|
||||
--self:I("windfrom="..windfrom.." (c)vwind="..vwind)
|
||||
|
||||
-- Actually, we want the runway in the wind.
|
||||
local intowind = windfrom - self.carrierparam.rwyangle
|
||||
@@ -11936,7 +12041,7 @@ function AIRBOSS:_LSOgrade( playerData )
|
||||
local nS=count(G, '%(')
|
||||
local nN=N-nS-nL
|
||||
local nNv=Nv-nS-nL
|
||||
|
||||
|
||||
-- Groove time 15-18.99 sec for a unicorn. Or 60-65 for V/STOL unicorn.
|
||||
local Tgroove=playerData.Tgroove
|
||||
local TgrooveUnicorn=Tgroove and (Tgroove>=15.0 and Tgroove<=18.99) or false
|
||||
@@ -12053,7 +12158,7 @@ function AIRBOSS:_LSOgrade( playerData )
|
||||
|
||||
elseif not playerData.hover and playerData.actype == AIRBOSS.AircraftCarrier.AV8B then
|
||||
-------------------------------
|
||||
-- AV-8B not cleared to land -- -- Landing clearence is carrier from LC to Landing
|
||||
-- AV-8B not cleared to land -- -- Landing clearence is carrier from LC to Landing
|
||||
-------------------------------
|
||||
if playerData.landed then
|
||||
-- AIRBOSS wants your balls!
|
||||
@@ -13421,8 +13526,8 @@ function AIRBOSS:CarrierTurnIntoWind( time, vdeck, uturn )
|
||||
-- Wind speed.
|
||||
local _, vwind = self:GetWind()
|
||||
|
||||
-- Speed of carrier in m/s but at least 2 knots.
|
||||
local vtot = math.max( vdeck - vwind, UTILS.KnotsToMps( 2 ) )
|
||||
-- Speed of carrier in m/s but at least 4 knots.
|
||||
local vtot = math.max( vdeck - vwind, UTILS.KnotsToMps( 4 ) )
|
||||
|
||||
-- Distance to travel
|
||||
local dist = vtot * time
|
||||
@@ -14625,59 +14730,140 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
if radio == nil or call == nil then
|
||||
return
|
||||
end
|
||||
|
||||
-- Create a new radio transmission item.
|
||||
local transmission = {} -- #AIRBOSS.Radioitem
|
||||
|
||||
transmission.radio = radio
|
||||
transmission.call = call
|
||||
transmission.Tplay = timer.getAbsTime() + (delay or 0)
|
||||
transmission.interval = interval
|
||||
transmission.isplaying = false
|
||||
transmission.Tstarted = nil
|
||||
transmission.loud = loud and call.loud
|
||||
|
||||
-- Player onboard number if sender has one.
|
||||
if self:_IsOnboard( call.modexsender ) then
|
||||
self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall )
|
||||
end
|
||||
|
||||
-- Play onboard number if receiver has one.
|
||||
if self:_IsOnboard( call.modexreceiver ) then
|
||||
self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall )
|
||||
end
|
||||
|
||||
-- Add transmission to the right queue.
|
||||
local caller = ""
|
||||
if radio.alias == "LSO" then
|
||||
|
||||
table.insert( self.RQLSO, transmission )
|
||||
|
||||
caller = "LSOCall"
|
||||
|
||||
-- Schedule radio queue checks.
|
||||
if not self.RQLid then
|
||||
self:T( self.lid .. string.format( "Starting LSO radio queue." ) )
|
||||
self.RQLid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQLSO, "LSO" }, 0.02, 0.05 )
|
||||
|
||||
if not self.SRS then
|
||||
|
||||
-- Create a new radio transmission item.
|
||||
local transmission = {} -- #AIRBOSS.Radioitem
|
||||
|
||||
transmission.radio = radio
|
||||
transmission.call = call
|
||||
transmission.Tplay = timer.getAbsTime() + (delay or 0)
|
||||
transmission.interval = interval
|
||||
transmission.isplaying = false
|
||||
transmission.Tstarted = nil
|
||||
transmission.loud = loud and call.loud
|
||||
|
||||
-- Player onboard number if sender has one.
|
||||
if self:_IsOnboard( call.modexsender ) then
|
||||
self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall )
|
||||
end
|
||||
|
||||
-- Play onboard number if receiver has one.
|
||||
if self:_IsOnboard( call.modexreceiver ) then
|
||||
self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall )
|
||||
end
|
||||
|
||||
-- Add transmission to the right queue.
|
||||
local caller = ""
|
||||
if radio.alias == "LSO" then
|
||||
|
||||
table.insert( self.RQLSO, transmission )
|
||||
|
||||
caller = "LSOCall"
|
||||
|
||||
-- Schedule radio queue checks.
|
||||
if not self.RQLid then
|
||||
self:T( self.lid .. string.format( "Starting LSO radio queue." ) )
|
||||
self.RQLid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQLSO, "LSO" }, 0.02, 0.05 )
|
||||
end
|
||||
|
||||
elseif radio.alias == "MARSHAL" then
|
||||
|
||||
table.insert( self.RQMarshal, transmission )
|
||||
|
||||
caller = "MarshalCall"
|
||||
|
||||
if not self.RQMid then
|
||||
self:T( self.lid .. string.format( "Starting Marhal radio queue." ) )
|
||||
self.RQMid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQMarshal, "MARSHAL" }, 0.02, 0.05 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Append radio click sound at the end of the transmission.
|
||||
if click then
|
||||
self:RadioTransmission( radio, self[caller].CLICK, false, delay )
|
||||
end
|
||||
|
||||
else
|
||||
-- SRS transmission
|
||||
|
||||
local frequency = self.MarshalRadio.frequency
|
||||
local modulation = self.MarshalRadio.modulation
|
||||
local voice = nil
|
||||
local gender = nil
|
||||
local culture = nil
|
||||
|
||||
if radio.alias == "AIRBOSS" then
|
||||
frequency = self.AirbossRadio.frequency
|
||||
modulation = self.AirbossRadio.modulation
|
||||
voice = self.AirbossRadio.voice
|
||||
gender = self.AirbossRadio.gender
|
||||
culture = self.AirbossRadio.culture
|
||||
end
|
||||
|
||||
if radio.alias == "MARSHAL" then
|
||||
voice = self.MarshalRadio.voice
|
||||
gender = self.MarshalRadio.gender
|
||||
culture = self.MarshalRadio.culture
|
||||
end
|
||||
|
||||
if radio.alias == "LSO" then
|
||||
frequency = self.LSORadio.frequency
|
||||
modulation = self.LSORadio.modulation
|
||||
voice = self.LSORadio.voice
|
||||
gender = self.LSORadio.gender
|
||||
culture = self.LSORadio.culture
|
||||
end
|
||||
|
||||
if pilotcall then
|
||||
voice = self.PilotRadio.voice
|
||||
gender = self.PilotRadio.gender
|
||||
culture = self.PilotRadio.culture
|
||||
radio.alias = "PILOT"
|
||||
end
|
||||
|
||||
elseif radio.alias == "MARSHAL" then
|
||||
|
||||
table.insert( self.RQMarshal, transmission )
|
||||
|
||||
caller = "MarshalCall"
|
||||
|
||||
if not self.RQMid then
|
||||
self:T( self.lid .. string.format( "Starting Marhal radio queue." ) )
|
||||
self.RQMid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQMarshal, "MARSHAL" }, 0.02, 0.05 )
|
||||
if not radio.alias then
|
||||
-- TODO - what freq to use here?
|
||||
frequency = self.AirbossRadio.frequency
|
||||
modulation = self.AirbossRadio.modulation
|
||||
radio.alias = "AIRBOSS"
|
||||
end
|
||||
|
||||
|
||||
local volume = nil
|
||||
|
||||
if loud then
|
||||
volume = 1.0
|
||||
end
|
||||
|
||||
--local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle
|
||||
local text = call.subtitle
|
||||
self:I(self.lid..text)
|
||||
local srstext = self:_GetNiceSRSText(text)
|
||||
self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, tstart, 0.1, subgroups, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias)
|
||||
end
|
||||
end
|
||||
|
||||
-- Append radio click sound at the end of the transmission.
|
||||
if click then
|
||||
self:RadioTransmission( radio, self[caller].CLICK, false, delay )
|
||||
--- Set SRS voice for the pilot calls.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #string Voice (Optional) SRS specific voice
|
||||
-- @param #string Gender (Optional) SRS specific gender
|
||||
-- @param #string Culture (Optional) SRS specific culture
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetSRSPilotVoice( Voice, Gender, Culture )
|
||||
|
||||
self.PilotRadio = {} -- #AIRBOSS.Radio
|
||||
self.PilotRadio.alias = "PILOT"
|
||||
self.PilotRadio.voice = Voice or MSRS.Voices.Microsoft.David
|
||||
self.PilotRadio.gender = Gender or "male"
|
||||
self.PilotRadio.culture = Culture or "en-US"
|
||||
|
||||
if (not Voice) and self.SRS and self.SRS.google then
|
||||
self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Check if a call needs a subtitle because the complete voice overs are not available.
|
||||
@@ -14923,6 +15109,39 @@ function AIRBOSS:_RadioFilename( call, loud, channel )
|
||||
return filename
|
||||
end
|
||||
|
||||
--- Format text into SRS friendly string
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #string text
|
||||
-- @return #string text
|
||||
function AIRBOSS:_GetNiceSRSText(text)
|
||||
text = string.gsub(text,"================================\n","")
|
||||
text = string.gsub(text,"||","parallel")
|
||||
text = string.gsub(text,"==","perpendicular")
|
||||
text = string.gsub(text,"BRC","Base recovery")
|
||||
--text = string.gsub(text,"#","Number")
|
||||
text = string.gsub(text,"%((%a+)%)","Morse %1")
|
||||
text = string.gsub(text,"°C","° Celsius")
|
||||
text = string.gsub(text,"°"," degrees")
|
||||
text = string.gsub(text," FB "," Final bearing ")
|
||||
text = string.gsub(text," ops"," operations ")
|
||||
text = string.gsub(text," kts"," knots")
|
||||
text = string.gsub(text,"TACAN","Tackan")
|
||||
text = string.gsub(text,"ICLS","I.C.L.S.")
|
||||
text = string.gsub(text,"LSO","L.S.O.")
|
||||
text = string.gsub(text,"inHg","inches of Mercury")
|
||||
text = string.gsub(text,"QFE","Q.F.E.")
|
||||
text = string.gsub(text,"hPa","hecto pascal")
|
||||
text = string.gsub(text," NM"," nautical miles")
|
||||
text = string.gsub(text," ft"," feet")
|
||||
text = string.gsub(text,"A/C","aircraft")
|
||||
text = string.gsub(text,"(#[%a%d%p%s]+)\n","")
|
||||
text = string.gsub(text,"%.000"," dot zero")
|
||||
text = string.gsub(text,"00"," double zero")
|
||||
text = string.gsub(text," 0 "," zero " )
|
||||
text = string.gsub(text,"\n","; ")
|
||||
return text
|
||||
end
|
||||
|
||||
--- Send text message to player client.
|
||||
-- Message format will be "SENDER: RECCEIVER, MESSAGE".
|
||||
-- @param #AIRBOSS self
|
||||
@@ -14934,7 +15153,7 @@ end
|
||||
-- @param #boolean clear If true, clear screen from previous messages.
|
||||
-- @param #number delay Delay in seconds, before the message is displayed.
|
||||
function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duration, clear, delay )
|
||||
|
||||
self:I({sender,receiver,message})
|
||||
if playerData and message and message ~= "" then
|
||||
|
||||
-- Default duration.
|
||||
@@ -14957,49 +15176,91 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
|
||||
-- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay)
|
||||
self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear )
|
||||
else
|
||||
|
||||
-- Wait until previous sound finished.
|
||||
local wait = 0
|
||||
|
||||
-- Onboard number to get the attention.
|
||||
if receiver == playerData.onboard then
|
||||
|
||||
-- Which voice over number to use.
|
||||
if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then
|
||||
|
||||
-- User sound of board number.
|
||||
wait = wait + self:_Number2Sound( playerData, sender, receiver )
|
||||
|
||||
|
||||
if not self.SRS then
|
||||
-- Wait until previous sound finished.
|
||||
local wait = 0
|
||||
|
||||
-- Onboard number to get the attention.
|
||||
if receiver == playerData.onboard then
|
||||
|
||||
-- Which voice over number to use.
|
||||
if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then
|
||||
|
||||
-- User sound of board number.
|
||||
wait = wait + self:_Number2Sound( playerData, sender, receiver )
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Negative.
|
||||
if string.find( text:lower(), "negative" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.NEGATIVE.duration
|
||||
end
|
||||
|
||||
-- Affirm.
|
||||
if string.find( text:lower(), "affirm" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.AFFIRMATIVE.duration
|
||||
end
|
||||
|
||||
-- Roger.
|
||||
if string.find( text:lower(), "roger" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.ROGER.duration
|
||||
end
|
||||
|
||||
-- Play click sound to end message.
|
||||
if wait > 0 then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.CLICK )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
end
|
||||
else
|
||||
-- SRS transmission
|
||||
local frequency = self.MarshalRadio.frequency
|
||||
local modulation = self.MarshalRadio.modulation
|
||||
local voice = self.MarshalRadio.voice
|
||||
local gender = self.MarshalRadio.gender
|
||||
local culture = self.MarshalRadio.culture
|
||||
|
||||
if not sender then sender = "AIRBOSS" end
|
||||
|
||||
-- Negative.
|
||||
if string.find( text:lower(), "negative" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.NEGATIVE.duration
|
||||
end
|
||||
if string.find(sender,"AIRBOSS" ) then
|
||||
frequency = self.AirbossRadio.frequency
|
||||
modulation = self.AirbossRadio.modulation
|
||||
voice = self.AirbossRadio.voice
|
||||
gender = self.AirbossRadio.gender
|
||||
culture = self.AirbossRadio.culture
|
||||
end
|
||||
|
||||
-- Affirm.
|
||||
if string.find( text:lower(), "affirm" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.AFFIRMATIVE.duration
|
||||
end
|
||||
--if sender == "MARSHAL" then
|
||||
--voice = self.MarshalRadio.voice
|
||||
--gender = self.MarshalRadio.gender
|
||||
--culture = self.MarshalRadio.culture
|
||||
--end
|
||||
|
||||
-- Roger.
|
||||
if string.find( text:lower(), "roger" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.ROGER.duration
|
||||
end
|
||||
if sender == "LSO" then
|
||||
frequency = self.LSORadio.frequency
|
||||
modulation = self.LSORadio.modulation
|
||||
voice = self.LSORadio.voice
|
||||
gender = self.LSORadio.gender
|
||||
culture = self.LSORadio.culture
|
||||
--elseif not sender then
|
||||
-- TODO - what freq to use here?
|
||||
--frequency = self.AirbossRadio.frequency
|
||||
--modulation = self.AirbossRadio.modulation
|
||||
--sender = "AIRBOSS"
|
||||
end
|
||||
|
||||
-- Play click sound to end message.
|
||||
if wait > 0 then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.CLICK )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
self:I(self.lid..text)
|
||||
self:I({sender,frequency,modulation,voice})
|
||||
local srstext = self:_GetNiceSRSText(text)
|
||||
self.SRSQ:NewTransmission(srstext,duration,self.SRS,tstart,0.1,subgroups,subtitle,subduration,frequency,modulation,gender,culture,voice,volume,sender)
|
||||
end
|
||||
|
||||
-- Text message to player client.
|
||||
if playerData.client then
|
||||
MESSAGE:New( text, duration, sender, clear ):ToClient( playerData.client )
|
||||
@@ -15283,13 +15544,13 @@ end
|
||||
-- @param #string modex Tail number.
|
||||
function AIRBOSS:_MarshallInboundCall(unit, modex)
|
||||
|
||||
-- Calculate
|
||||
-- Calculate
|
||||
local vectorCarrier = self:GetCoordinate():GetDirectionVec3(unit:GetCoordinate())
|
||||
local bearing = UTILS.Round(unit:GetCoordinate():GetAngleDegrees( vectorCarrier ), 0)
|
||||
local distance = UTILS.Round(UTILS.MetersToNM(unit:GetCoordinate():Get2DDistance(self:GetCoordinate())),0)
|
||||
local angels = UTILS.Round(UTILS.MetersToFeet(unit:GetHeight()/1000),0)
|
||||
local state = UTILS.Round(self:_GetFuelState(unit)/1000,1)
|
||||
|
||||
|
||||
-- Pilot: "Marshall, [modex], marking mom's [bearing] for [distance], angels [XX], state [X.X]"
|
||||
local text=string.format("Marshal, %s, marking mom's %d for %d, angels %d, state %.1f", modex, bearing, distance, angels, state)
|
||||
-- Debug message.
|
||||
@@ -16116,8 +16377,8 @@ function AIRBOSS:_RequestMarshal( _unitName )
|
||||
-- Voice over of inbound call (regardless of airboss rejecting it or not)
|
||||
if self.xtVoiceOvers then
|
||||
self:_MarshallInboundCall(_unit, playerData.onboard)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Check if player is in CCA
|
||||
local inCCA = playerData.unit:IsInZone( self.zoneCCA )
|
||||
|
||||
@@ -16338,7 +16599,7 @@ function AIRBOSS:_RequestSpinning( _unitName )
|
||||
-- Some advice.
|
||||
if playerData.difficulty == AIRBOSS.Difficulty.EASY then
|
||||
local text = "Climb to 1200 feet and proceed to the initial again."
|
||||
self:MessageToPlayer( playerData, text, "INSTRUCTOR", "" )
|
||||
self:MessageToPlayer( playerData, text, "AIRBOSS", "" )
|
||||
end
|
||||
|
||||
return
|
||||
@@ -16365,12 +16626,12 @@ function AIRBOSS:_RequestCommence( _unitName )
|
||||
local playerData = self.players[_playername] -- #AIRBOSS.PlayerData
|
||||
|
||||
if playerData then
|
||||
|
||||
|
||||
-- Voice over of Commencing call (regardless of Airboss will rejected or not)
|
||||
if self.xtVoiceOvers then
|
||||
self:_CommencingCall(_unit, playerData.onboard)
|
||||
end
|
||||
|
||||
|
||||
-- Check if unit is in CCA.
|
||||
local text = ""
|
||||
local cleared = false
|
||||
@@ -17093,7 +17354,7 @@ function AIRBOSS:_DisplayCarrierInfo( _unitname )
|
||||
state = "Deck closed"
|
||||
end
|
||||
if self.turning then
|
||||
state = state .. " (turning currently)"
|
||||
state = state .. " (currently turning)"
|
||||
end
|
||||
|
||||
-- Message text.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,621 @@
|
||||
--- **Ops** - Brigade Warehouse.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Manage platoons
|
||||
-- * Carry out ARTY and PATROLZONE missions (AUFTRAG)
|
||||
-- * Define rearming zones
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Brigade).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.Brigade
|
||||
-- @image OPS_Brigade_.png
|
||||
|
||||
|
||||
--- BRIGADE class.
|
||||
-- @type BRIGADE
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||
-- @field #table refuellingZones Refuelling zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||
-- @field Core.Set#SET_ZONE retreatZones Retreat zone set.
|
||||
-- @extends Ops.Legion#LEGION
|
||||
|
||||
--- *I am not afraid of an Army of lions lead by a sheep; I am afraid of sheep lead by a lion* -- Alexander the Great
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The BRIGADE Concept
|
||||
--
|
||||
-- A BRIGADE consists of one or multiple PLATOONs. These platoons "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
||||
--
|
||||
--
|
||||
-- @field #BRIGADE
|
||||
BRIGADE = {
|
||||
ClassName = "BRIGADE",
|
||||
verbose = 0,
|
||||
rearmingZones = {},
|
||||
refuellingZones = {},
|
||||
}
|
||||
|
||||
--- Supply Zone.
|
||||
-- @type BRIGADE.SupplyZone
|
||||
-- @field Core.Zone#ZONE zone The zone.
|
||||
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo or fuel.
|
||||
-- @field #boolean markerOn If `true`, marker is on.
|
||||
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
||||
|
||||
--- BRIGADE class version.
|
||||
-- @field #string version
|
||||
BRIGADE.version="0.1.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Spawn when hosting warehouse is a ship or oil rig or gas platform.
|
||||
-- TODO: Rearming zones.
|
||||
-- TODO: Retreat zones.
|
||||
-- DONE: Add weapon range.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new BRIGADE class object.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string WarehouseName Name of the warehouse STATIC or UNIT object representing the warehouse.
|
||||
-- @param #string BrigadeName Name of the brigade.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:New(WarehouseName, BrigadeName)
|
||||
|
||||
-- Inherit everything from LEGION class.
|
||||
local self=BASE:Inherit(self, LEGION:New(WarehouseName, BrigadeName)) -- #BRIGADE
|
||||
|
||||
-- Nil check.
|
||||
if not self then
|
||||
BASE:E(string.format("ERROR: Could not find warehouse %s!", WarehouseName))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("BRIGADE %s | ", self.alias)
|
||||
|
||||
-- Defaults
|
||||
self:SetRetreatZones()
|
||||
|
||||
-- Turn ship into NAVYGROUP.
|
||||
if self:IsShip() then
|
||||
local wh=self.warehouse --Wrapper.Unit#UNIT
|
||||
local group=wh:GetGroup()
|
||||
self.warehouseOpsGroup=NAVYGROUP:New(group) --Ops.NavyGroup#NAVYGROUP
|
||||
self.warehouseOpsElement=self.warehouseOpsGroup:GetElementByName(wh:GetName())
|
||||
end
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "ArmyOnMission", "*") -- An ARMYGROUP was send on a Mission (AUFTRAG).
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Start". Starts the BRIGADE. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#BRIGADE] Start
|
||||
-- @param #BRIGADE self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the BRIGADE. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#BRIGADE] __Start
|
||||
-- @param #BRIGADE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the BRIGADE and all its event handlers.
|
||||
-- @param #BRIGADE self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the BRIGADE and all its event handlers.
|
||||
-- @function [parent=#BRIGADE] __Stop
|
||||
-- @param #BRIGADE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "ArmyOnMission".
|
||||
-- @function [parent=#BRIGADE] ArmyOnMission
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
--- Triggers the FSM event "ArmyOnMission" after a delay.
|
||||
-- @function [parent=#BRIGADE] __ArmyOnMission
|
||||
-- @param #BRIGADE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
--- On after "ArmyOnMission" event.
|
||||
-- @function [parent=#BRIGADE] OnAfterArmyOnMission
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add a platoon to the brigade.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.Platoon#PLATOON Platoon The platoon object.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:AddPlatoon(Platoon)
|
||||
|
||||
-- Add platoon to brigade.
|
||||
table.insert(self.cohorts, Platoon)
|
||||
|
||||
-- Add assets to platoon.
|
||||
self:AddAssetToPlatoon(Platoon, Platoon.Ngroups)
|
||||
|
||||
-- Set brigade of platoon.
|
||||
Platoon:SetBrigade(self)
|
||||
|
||||
-- Start platoon.
|
||||
if Platoon:IsStopped() then
|
||||
Platoon:Start()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add asset group(s) to platoon.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.Platoon#PLATOON Platoon The platoon object.
|
||||
-- @param #number Nassets Number of asset groups to add.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:AddAssetToPlatoon(Platoon, Nassets)
|
||||
|
||||
if Platoon then
|
||||
|
||||
-- Get the template group of the platoon.
|
||||
local Group=GROUP:FindByName(Platoon.templatename)
|
||||
|
||||
if Group then
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Adding asset %s to platoon %s", Group:GetName(), Platoon.name)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Add assets to airwing warehouse.
|
||||
self:AddAsset(Group, Nassets, nil, nil, nil, nil, Platoon.skill, Platoon.livery, Platoon.name)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Group does not exist!")
|
||||
end
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Platoon does not exit!")
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Define a set of retreat zones.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Core.Set#SET_ZONE RetreatZoneSet Set of retreat zones.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:SetRetreatZones(RetreatZoneSet)
|
||||
self.retreatZones=RetreatZoneSet or SET_ZONE:New()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a retreat zone.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Core.Zone#ZONE RetreatZone Retreat zone.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:AddRetreatZone(RetreatZone)
|
||||
self.retreatZones:AddZone(RetreatZone)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get retreat zones.
|
||||
-- @param #BRIGADE self
|
||||
-- @return Core.Set#SET_ZONE Set of retreat zones.
|
||||
function BRIGADE:GetRetreatZones()
|
||||
return self.retreatZones
|
||||
end
|
||||
|
||||
--- Add a rearming zone.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
||||
-- @return #BRIGADE.SupplyZone The rearming zone data.
|
||||
function BRIGADE:AddRearmingZone(RearmingZone)
|
||||
|
||||
local rearmingzone={} --#BRIGADE.SupplyZone
|
||||
|
||||
rearmingzone.zone=RearmingZone
|
||||
rearmingzone.mission=nil
|
||||
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
||||
|
||||
table.insert(self.rearmingZones, rearmingzone)
|
||||
|
||||
return rearmingzone
|
||||
end
|
||||
|
||||
|
||||
--- Add a refuelling zone.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Core.Zone#ZONE RefuellingZone Refuelling zone.
|
||||
-- @return #BRIGADE.SupplyZone The refuelling zone data.
|
||||
function BRIGADE:AddRefuellingZone(RefuellingZone)
|
||||
|
||||
local supplyzone={} --#BRIGADE.SupplyZone
|
||||
|
||||
supplyzone.zone=RefuellingZone
|
||||
supplyzone.mission=nil
|
||||
supplyzone.marker=MARKER:New(supplyzone.zone:GetCoordinate(), "Refuelling Zone"):ToCoalition(self:GetCoalition())
|
||||
|
||||
table.insert(self.refuellingZones, supplyzone)
|
||||
|
||||
return supplyzone
|
||||
end
|
||||
|
||||
|
||||
--- Get platoon by name.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string PlatoonName Name of the platoon.
|
||||
-- @return Ops.Platoon#PLATOON The Platoon object.
|
||||
function BRIGADE:GetPlatoon(PlatoonName)
|
||||
local platoon=self:_GetCohort(PlatoonName)
|
||||
return platoon
|
||||
end
|
||||
|
||||
--- Get platoon of an asset.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
||||
-- @return Ops.Platoon#PLATOON The platoon object.
|
||||
function BRIGADE:GetPlatoonOfAsset(Asset)
|
||||
local platoon=self:GetPlatoon(Asset.squadname)
|
||||
return platoon
|
||||
end
|
||||
|
||||
--- Remove asset from platoon.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
||||
function BRIGADE:RemoveAssetFromPlatoon(Asset)
|
||||
local platoon=self:GetPlatoonOfAsset(Asset)
|
||||
if platoon then
|
||||
platoon:DelAsset(Asset)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- [ GROUND ] Function to load back an asset in the field that has been filed before.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string Templatename e.g."1 PzDv LogRg I\_AID-976" - that's the alias (name) of an platoon spawned as `"platoon - alias"_AID-"asset-ID"`
|
||||
-- @param Core.Point#COORDINATE Position where to spawn the platoon
|
||||
-- @return #BRIGADE self
|
||||
-- @usage
|
||||
-- Prerequisites:
|
||||
-- Save the assets spawned by BRIGADE/CHIEF regularly (~every 5 mins) into a file, e.g. like this:
|
||||
--
|
||||
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
|
||||
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
|
||||
-- local BlueSaveOps = SET_GROUP:New():FilterCoalitions("blue"):FilterPrefixes("AID"):FilterCategoryGround():FilterOnce()
|
||||
-- UTILS.SaveSetOfGroups(BlueSaveOps,Path,BlueOpsFilename)
|
||||
--
|
||||
-- where Path and Filename are strings, as chosen by you.
|
||||
-- You can then load back the assets at the start of your next mission run. Be aware that it takes a couple of seconds for the
|
||||
-- platoon data to arrive in brigade, so make this an action after ~20 seconds, e.g. like so:
|
||||
--
|
||||
-- function LoadBackAssets()
|
||||
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
|
||||
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
|
||||
-- if UTILS.CheckFileExists(Path,BlueOpsFilename) then
|
||||
-- local loadback = UTILS.LoadSetOfGroups(Path,BlueOpsFilename,false)
|
||||
-- for _,_platoondata in pairs (loadback) do
|
||||
-- local groupname = _platoondata.groupname -- #string
|
||||
-- local coordinate = _platoondata.coordinate -- Core.Point#COORDINATE
|
||||
-- Your_Brigade:LoadBackAssetInPosition(groupname,coordinate)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- local AssetLoader = TIMER:New(LoadBackAssets)
|
||||
-- AssetLoader:Start(20)
|
||||
--
|
||||
-- The assets loaded back into the mission will be considered for AUFTRAG type missions from CHIEF and BRIGADE.
|
||||
function BRIGADE:LoadBackAssetInPosition(Templatename,Position)
|
||||
self:T(self.lid .. "LoadBackAssetInPosition: " .. tostring(Templatename))
|
||||
|
||||
-- get Platoon alias from Templatename
|
||||
local nametbl = UTILS.Split(Templatename,"_")
|
||||
|
||||
local name = nametbl[1]
|
||||
|
||||
self:T(string.format("*** Target Platoon = %s ***",name))
|
||||
|
||||
-- find a matching asset table from BRIGADE
|
||||
local cohorts = self.cohorts or {}
|
||||
local thisasset = nil --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
local found = false
|
||||
|
||||
for _,_cohort in pairs(cohorts) do
|
||||
local asset = _cohort:GetName()
|
||||
self:T(string.format("*** Looking at Platoon = %s ***",asset))
|
||||
if asset == name then
|
||||
self:T("**** Found Platoon ****")
|
||||
local cohassets = _cohort.assets or {}
|
||||
for _,_zug in pairs (cohassets) do
|
||||
local zug = _zug -- Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
if zug.assignment == name and zug.requested == false then
|
||||
self:T("**** Found Asset ****")
|
||||
found = true
|
||||
thisasset = zug --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if found then
|
||||
|
||||
-- prep asset
|
||||
thisasset.rid = thisasset.uid
|
||||
thisasset.requested = false
|
||||
thisasset.score=100
|
||||
thisasset.missionTask="CAS"
|
||||
thisasset.spawned = true
|
||||
local template = thisasset.templatename
|
||||
local alias = thisasset.spawngroupname
|
||||
|
||||
-- Spawn group
|
||||
local spawnasset = SPAWN:NewWithAlias(template,alias)
|
||||
:InitDelayOff()
|
||||
:SpawnFromCoordinate(Position)
|
||||
|
||||
-- build a new self request
|
||||
local request = {} --Functional.Warehouse#WAREHOUSE.Pendingitem
|
||||
request.assignment = name
|
||||
request.warehouse = self
|
||||
request.assets = {thisasset}
|
||||
request.ntransporthome = 0
|
||||
request.ndelivered = 0
|
||||
request.ntransport = 0
|
||||
request.cargoattribute = thisasset.attribute
|
||||
request.category = thisasset.category
|
||||
request.cargoassets = {thisasset}
|
||||
request.assetdesc = WAREHOUSE.Descriptor.ASSETLIST
|
||||
request.cargocategory = thisasset.category
|
||||
request.toself = true
|
||||
request.transporttype = WAREHOUSE.TransportType.SELFPROPELLED
|
||||
request.assetproblem = {}
|
||||
request.born = true
|
||||
request.prio = 50
|
||||
request.uid = thisasset.uid
|
||||
request.airbase = nil
|
||||
request.timestamp = timer.getAbsTime()
|
||||
request.assetdescval = {thisasset}
|
||||
request.nasset = 1
|
||||
request.cargogroupset = SET_GROUP:New()
|
||||
request.cargogroupset:AddGroup(spawnasset)
|
||||
request.iscargo = true
|
||||
|
||||
-- Call Brigade self
|
||||
self:__AssetSpawned(2, spawnasset, thisasset, request)
|
||||
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Start BRIGADE FSM.
|
||||
-- @param #BRIGADE self
|
||||
function BRIGADE:onafterStart(From, Event, To)
|
||||
|
||||
-- Start parent Warehouse.
|
||||
self:GetParent(self, BRIGADE).onafterStart(self, From, Event, To)
|
||||
|
||||
-- Info.
|
||||
self:I(self.lid..string.format("Starting BRIGADE v%s", BRIGADE.version))
|
||||
|
||||
end
|
||||
|
||||
--- Update status.
|
||||
-- @param #BRIGADE self
|
||||
function BRIGADE:onafterStatus(From, Event, To)
|
||||
|
||||
-- Status of parent Warehouse.
|
||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
----------------
|
||||
-- Transport ---
|
||||
----------------
|
||||
|
||||
self:CheckTransportQueue()
|
||||
|
||||
--------------
|
||||
-- Mission ---
|
||||
--------------
|
||||
|
||||
-- Check if any missions should be cancelled.
|
||||
self:CheckMissionQueue()
|
||||
|
||||
---------------------
|
||||
-- Rearming Zones ---
|
||||
---------------------
|
||||
|
||||
for _,_rearmingzone in pairs(self.rearmingZones) do
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
||||
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
||||
self:AddMission(rearmingzone.mission)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------
|
||||
-- Refuelling Zones ---
|
||||
-----------------------
|
||||
|
||||
-- Check refuelling zones.
|
||||
for _,_supplyzone in pairs(self.refuellingZones) do
|
||||
local supplyzone=_supplyzone --#BRIGADE.SupplyZone
|
||||
-- Check if mission is nil or over.
|
||||
if (not supplyzone.mission) or supplyzone.mission:IsOver() then
|
||||
supplyzone.mission=AUFTRAG:NewFUELSUPPLY(supplyzone.zone)
|
||||
self:AddMission(supplyzone.mission)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----------
|
||||
-- Info ---
|
||||
-----------
|
||||
|
||||
-- General info:
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- Count missions not over yet.
|
||||
local Nmissions=self:CountMissionsInQueue()
|
||||
|
||||
-- Asset count.
|
||||
local Npq, Np, Nq=self:CountAssetsOnMission()
|
||||
|
||||
-- Asset string.
|
||||
local assets=string.format("%d [OnMission: Total=%d, Active=%d, Queued=%d]", self:CountAssets(), Npq, Np, Nq)
|
||||
|
||||
-- Output.
|
||||
local text=string.format("%s: Missions=%d, Platoons=%d, Assets=%s", fsmstate, Nmissions, #self.cohorts, assets)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
------------------
|
||||
-- Mission Info --
|
||||
------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Missions Total=%d:", #self.missionqueue)
|
||||
for i,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
local prio=string.format("%d/%s", mission.prio, tostring(mission.importance)) ; if mission.urgent then prio=prio.." (!)" end
|
||||
local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.Nassets or 0)
|
||||
local target=string.format("%d/%d Damage=%.1f", mission:CountMissionTargets(), mission:GetTargetInitialNumber(), mission:GetTargetDamage())
|
||||
|
||||
text=text..string.format("\n[%d] %s %s: Status=%s, Prio=%s, Assets=%s, Targets=%s", i, mission.name, mission.type, mission.status, prio, assets, target)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
--------------------
|
||||
-- Transport Info --
|
||||
--------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Transports Total=%d:", #self.transportqueue)
|
||||
for i,_transport in pairs(self.transportqueue) do
|
||||
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
|
||||
|
||||
local prio=string.format("%d/%s", transport.prio, tostring(transport.importance)) ; if transport.urgent then prio=prio.." (!)" end
|
||||
local carriers=string.format("Ncargo=%d/%d, Ncarriers=%d", transport.Ncargo, transport.Ndelivered, transport.Ncarrier)
|
||||
|
||||
text=text..string.format("\n[%d] UID=%d: Status=%s, Prio=%s, Cargo: %s", i, transport.uid, transport:GetState(), prio, carriers)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Platoon Info --
|
||||
-------------------
|
||||
if self.verbose>=3 then
|
||||
local text="Platoons:"
|
||||
for i,_platoon in pairs(self.cohorts) do
|
||||
local platoon=_platoon --Ops.Platoon#PLATOON
|
||||
|
||||
local callsign=platoon.callsignName and UTILS.GetCallsignName(platoon.callsignName) or "N/A"
|
||||
local modex=platoon.modex and platoon.modex or -1
|
||||
local skill=platoon.skill and tostring(platoon.skill) or "N/A"
|
||||
|
||||
-- Platoon text.
|
||||
text=text..string.format("\n* %s %s: %s*%d/%d, Callsign=%s, Modex=%d, Skill=%s", platoon.name, platoon:GetState(), platoon.aircrafttype, platoon:CountAssets(true), #platoon.assets, callsign, modex, skill)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Rearming Info --
|
||||
-------------------
|
||||
if self.verbose>=4 then
|
||||
local text="Rearming Zones:"
|
||||
for i,_rearmingzone in pairs(self.rearmingZones) do
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||
-- Info text.
|
||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", rearmingzone.zone:GetName(), rearmingzone.mission:GetState(), rearmingzone.mission:CountOpsGroups())
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
---------------------
|
||||
-- Refuelling Info --
|
||||
---------------------
|
||||
if self.verbose>=4 then
|
||||
local text="Refuelling Zones:"
|
||||
for i,_refuellingzone in pairs(self.refuellingZones) do
|
||||
local refuellingzone=_refuellingzone --#BRIGADE.SupplyZone
|
||||
-- Info text.
|
||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", refuellingzone.zone:GetName(), refuellingzone.mission:GetState(), refuellingzone.mission:CountOpsGroups())
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
----------------
|
||||
-- Asset Info --
|
||||
----------------
|
||||
if self.verbose>=5 then
|
||||
local text="Assets in stock:"
|
||||
for i,_asset in pairs(self.stock) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
-- Info text.
|
||||
text=text..string.format("\n* %s: spawned=%s", asset.spawngroupname, tostring(asset.spawned))
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after "ArmyOnMission".
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup Ops army group on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The requested mission.
|
||||
function BRIGADE:onafterArmyOnMission(From, Event, To, ArmyGroup, Mission)
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Group %s on %s mission %s", ArmyGroup:GetName(), Mission:GetType(), Mission:GetName()))
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,425 @@
|
||||
--- **Ops** - Fleet Warehouse.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Manage flotillas
|
||||
-- * Carry out ARTY and PATROLZONE missions (AUFTRAG)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Fleet).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.Fleet
|
||||
-- @image OPS_Fleet.png
|
||||
|
||||
|
||||
--- FLEET class.
|
||||
-- @type FLEET
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field Core.Set#SET_ZONE retreatZones Retreat zone set.
|
||||
-- @field #boolean pathfinding Set pathfinding on for all spawned navy groups.
|
||||
-- @extends Ops.Legion#LEGION
|
||||
|
||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The FLEET Concept
|
||||
--
|
||||
-- A FLEET consists of one or multiple FLOTILLAs. These flotillas "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
-- A new `FLEET` object can be created with the @{#FLEET.New}(`WarehouseName`, `FleetName`) function, where `WarehouseName` is the name of the static or unit object hosting the fleet
|
||||
-- and `FleetName` is the name you want to give the fleet. This must be *unique*!
|
||||
--
|
||||
-- myFleet=FLEET:New("myWarehouseName", "1st Fleet")
|
||||
-- myFleet:SetPortZone(ZonePort1stFleet)
|
||||
-- myFleet:Start()
|
||||
--
|
||||
-- A fleet needs a *port zone*, which is set via the @{#FLEET.SetPortZone}(`PortZone`) function. This is the zone where the naval assets are spawned and return to.
|
||||
--
|
||||
-- Finally, the fleet needs to be started using the @{#FLEET.Start}() function. If the fleet is not started, it will not process any requests.
|
||||
--
|
||||
-- ## Adding Flotillas
|
||||
--
|
||||
-- Flotillas can be added via the @{#FLEET.AddFlotilla}(`Flotilla`) function. See @{Ops.Flotilla#FLOTILLA} for how to create a flotilla.
|
||||
--
|
||||
-- myFleet:AddFlotilla(FlotillaTiconderoga)
|
||||
-- myFleet:AddFlotilla(FlotillaPerry)
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #FLEET
|
||||
FLEET = {
|
||||
ClassName = "FLEET",
|
||||
verbose = 0,
|
||||
pathfinding = false,
|
||||
}
|
||||
|
||||
--- Supply Zone.
|
||||
-- @type FLEET.SupplyZone
|
||||
-- @field Core.Zone#ZONE zone The zone.
|
||||
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo or fuel.
|
||||
-- @field #boolean markerOn If `true`, marker is on.
|
||||
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
||||
|
||||
--- FLEET class version.
|
||||
-- @field #string version
|
||||
FLEET.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Add routes?
|
||||
-- DONE: Add weapon range.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new FLEET class object.
|
||||
-- @param #FLEET self
|
||||
-- @param #string WarehouseName Name of the warehouse STATIC or UNIT object representing the warehouse.
|
||||
-- @param #string FleetName Name of the fleet.
|
||||
-- @return #FLEET self
|
||||
function FLEET:New(WarehouseName, FleetName)
|
||||
|
||||
-- Inherit everything from LEGION class.
|
||||
local self=BASE:Inherit(self, LEGION:New(WarehouseName, FleetName)) -- #FLEET
|
||||
|
||||
-- Nil check.
|
||||
if not self then
|
||||
BASE:E(string.format("ERROR: Could not find warehouse %s!", WarehouseName))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("FLEET %s | ", self.alias)
|
||||
|
||||
-- Defaults
|
||||
self:SetRetreatZones()
|
||||
|
||||
-- Turn ship into NAVYGROUP.
|
||||
if self:IsShip() then
|
||||
local wh=self.warehouse --Wrapper.Unit#UNIT
|
||||
local group=wh:GetGroup()
|
||||
self.warehouseOpsGroup=NAVYGROUP:New(group) --Ops.NavyGroup#NAVYGROUP
|
||||
self.warehouseOpsElement=self.warehouseOpsGroup:GetElementByName(wh:GetName())
|
||||
end
|
||||
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "NavyOnMission", "*") -- An NAVYGROUP was send on a Mission (AUFTRAG).
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Start". Starts the FLEET. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#FLEET] Start
|
||||
-- @param #FLEET self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the FLEET. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#FLEET] __Start
|
||||
-- @param #FLEET self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the FLEET and all its event handlers.
|
||||
-- @param #FLEET self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the FLEET and all its event handlers.
|
||||
-- @function [parent=#FLEET] __Stop
|
||||
-- @param #FLEET self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "NavyOnMission".
|
||||
-- @function [parent=#FLEET] NavyOnMission
|
||||
-- @param #FLEET self
|
||||
-- @param Ops.NavyGroup#NAVYGROUP ArmyGroup The NAVYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
--- Triggers the FSM event "NavyOnMission" after a delay.
|
||||
-- @function [parent=#FLEET] __NavyOnMission
|
||||
-- @param #FLEET self
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param Ops.NavyGroup#NAVYGROUP ArmyGroup The NAVYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
--- On after "NavyOnMission" event.
|
||||
-- @function [parent=#FLEET] OnAfterNavyOnMission
|
||||
-- @param #FLEET self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.NavyGroup#NAVYGROUP NavyGroup The NAVYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add a flotilla to the fleet.
|
||||
-- @param #FLEET self
|
||||
-- @param Ops.Flotilla#FLOTILLA Flotilla The flotilla object.
|
||||
-- @return #FLEET self
|
||||
function FLEET:AddFlotilla(Flotilla)
|
||||
|
||||
-- Add flotilla to fleet.
|
||||
table.insert(self.cohorts, Flotilla)
|
||||
|
||||
-- Add assets to flotilla.
|
||||
self:AddAssetToFlotilla(Flotilla, Flotilla.Ngroups)
|
||||
|
||||
-- Set fleet of flotilla.
|
||||
Flotilla:SetFleet(self)
|
||||
|
||||
-- Start flotilla.
|
||||
if Flotilla:IsStopped() then
|
||||
Flotilla:Start()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add asset group(s) to flotilla.
|
||||
-- @param #FLEET self
|
||||
-- @param Ops.Flotilla#FLOTILLA Flotilla The flotilla object.
|
||||
-- @param #number Nassets Number of asset groups to add.
|
||||
-- @return #FLEET self
|
||||
function FLEET:AddAssetToFlotilla(Flotilla, Nassets)
|
||||
|
||||
if Flotilla then
|
||||
|
||||
-- Get the template group of the flotilla.
|
||||
local Group=GROUP:FindByName(Flotilla.templatename)
|
||||
|
||||
if Group then
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Adding asset %s to flotilla %s", Group:GetName(), Flotilla.name)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Add assets to airwing warehouse.
|
||||
self:AddAsset(Group, Nassets, nil, nil, nil, nil, Flotilla.skill, Flotilla.livery, Flotilla.name)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Group does not exist!")
|
||||
end
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Flotilla does not exit!")
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set pathfinding for all spawned naval groups.
|
||||
-- @param #FLEET self
|
||||
-- @param #boolean Switch If `true`, pathfinding is used.
|
||||
-- @return #FLEET self
|
||||
function FLEET:SetPathfinding(Switch)
|
||||
self.pathfinding=Switch
|
||||
return self
|
||||
end
|
||||
|
||||
--- Define a set of retreat zones.
|
||||
-- @param #FLEET self
|
||||
-- @param Core.Set#SET_ZONE RetreatZoneSet Set of retreat zones.
|
||||
-- @return #FLEET self
|
||||
function FLEET:SetRetreatZones(RetreatZoneSet)
|
||||
self.retreatZones=RetreatZoneSet or SET_ZONE:New()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a retreat zone.
|
||||
-- @param #FLEET self
|
||||
-- @param Core.Zone#ZONE RetreatZone Retreat zone.
|
||||
-- @return #FLEET self
|
||||
function FLEET:AddRetreatZone(RetreatZone)
|
||||
self.retreatZones:AddZone(RetreatZone)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get retreat zones.
|
||||
-- @param #FLEET self
|
||||
-- @return Core.Set#SET_ZONE Set of retreat zones.
|
||||
function FLEET:GetRetreatZones()
|
||||
return self.retreatZones
|
||||
end
|
||||
|
||||
--- Get flotilla by name.
|
||||
-- @param #FLEET self
|
||||
-- @param #string FlotillaName Name of the flotilla.
|
||||
-- @return Ops.Flotilla#FLOTILLA The Flotilla object.
|
||||
function FLEET:GetFlotilla(FlotillaName)
|
||||
local flotilla=self:_GetCohort(FlotillaName)
|
||||
return flotilla
|
||||
end
|
||||
|
||||
--- Get flotilla of an asset.
|
||||
-- @param #FLEET self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The flotilla asset.
|
||||
-- @return Ops.Flotilla#FLOTILLA The flotilla object.
|
||||
function FLEET:GetFlotillaOfAsset(Asset)
|
||||
local flotilla=self:GetFlotilla(Asset.squadname)
|
||||
return flotilla
|
||||
end
|
||||
|
||||
--- Remove asset from flotilla.
|
||||
-- @param #FLEET self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The flotilla asset.
|
||||
function FLEET:RemoveAssetFromFlotilla(Asset)
|
||||
local flotilla=self:GetFlotillaOfAsset(Asset)
|
||||
if flotilla then
|
||||
flotilla:DelAsset(Asset)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Start FLEET FSM.
|
||||
-- @param #FLEET self
|
||||
function FLEET:onafterStart(From, Event, To)
|
||||
|
||||
-- Start parent Warehouse.
|
||||
self:GetParent(self, FLEET).onafterStart(self, From, Event, To)
|
||||
|
||||
-- Info.
|
||||
self:I(self.lid..string.format("Starting FLEET v%s", FLEET.version))
|
||||
|
||||
end
|
||||
|
||||
--- Update status.
|
||||
-- @param #FLEET self
|
||||
function FLEET:onafterStatus(From, Event, To)
|
||||
|
||||
-- Status of parent Warehouse.
|
||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
----------------
|
||||
-- Transport ---
|
||||
----------------
|
||||
|
||||
self:CheckTransportQueue()
|
||||
|
||||
--------------
|
||||
-- Mission ---
|
||||
--------------
|
||||
|
||||
-- Check if any missions should be cancelled.
|
||||
self:CheckMissionQueue()
|
||||
|
||||
-----------
|
||||
-- Info ---
|
||||
-----------
|
||||
|
||||
-- General info:
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- Count missions not over yet.
|
||||
local Nmissions=self:CountMissionsInQueue()
|
||||
|
||||
-- Asset count.
|
||||
local Npq, Np, Nq=self:CountAssetsOnMission()
|
||||
|
||||
-- Asset string.
|
||||
local assets=string.format("%d [OnMission: Total=%d, Active=%d, Queued=%d]", self:CountAssets(), Npq, Np, Nq)
|
||||
|
||||
-- Output.
|
||||
local text=string.format("%s: Missions=%d, Flotillas=%d, Assets=%s", fsmstate, Nmissions, #self.cohorts, assets)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
------------------
|
||||
-- Mission Info --
|
||||
------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Missions Total=%d:", #self.missionqueue)
|
||||
for i,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
local prio=string.format("%d/%s", mission.prio, tostring(mission.importance)) ; if mission.urgent then prio=prio.." (!)" end
|
||||
local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.Nassets or 0)
|
||||
local target=string.format("%d/%d Damage=%.1f", mission:CountMissionTargets(), mission:GetTargetInitialNumber(), mission:GetTargetDamage())
|
||||
|
||||
text=text..string.format("\n[%d] %s %s: Status=%s, Prio=%s, Assets=%s, Targets=%s", i, mission.name, mission.type, mission.status, prio, assets, target)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
--------------------
|
||||
-- Transport Info --
|
||||
--------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Transports Total=%d:", #self.transportqueue)
|
||||
for i,_transport in pairs(self.transportqueue) do
|
||||
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
|
||||
|
||||
local prio=string.format("%d/%s", transport.prio, tostring(transport.importance)) ; if transport.urgent then prio=prio.." (!)" end
|
||||
local carriers=string.format("Ncargo=%d/%d, Ncarriers=%d", transport.Ncargo, transport.Ndelivered, transport.Ncarrier)
|
||||
|
||||
text=text..string.format("\n[%d] UID=%d: Status=%s, Prio=%s, Cargo: %s", i, transport.uid, transport:GetState(), prio, carriers)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Flotilla Info --
|
||||
-------------------
|
||||
if self.verbose>=3 then
|
||||
local text="Flotillas:"
|
||||
for i,_flotilla in pairs(self.cohorts) do
|
||||
local flotilla=_flotilla --Ops.Flotilla#FLOTILLA
|
||||
|
||||
local callsign=flotilla.callsignName and UTILS.GetCallsignName(flotilla.callsignName) or "N/A"
|
||||
local modex=flotilla.modex and flotilla.modex or -1
|
||||
local skill=flotilla.skill and tostring(flotilla.skill) or "N/A"
|
||||
|
||||
-- Flotilla text.
|
||||
text=text..string.format("\n* %s %s: %s*%d/%d, Callsign=%s, Modex=%d, Skill=%s", flotilla.name, flotilla:GetState(), flotilla.aircrafttype, flotilla:CountAssets(true), #flotilla.assets, callsign, modex, skill)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after "NavyOnMission".
|
||||
-- @param #FLEET self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup Ops army group on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The requested mission.
|
||||
function FLEET:onafterNavyOnMission(From, Event, To, NavyGroup, Mission)
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Group %s on %s mission %s", NavyGroup:GetName(), Mission:GetType(), Mission:GetName()))
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,175 @@
|
||||
--- **Ops** - Flotilla is a small naval group belonging to a fleet.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Set parameters like livery, skill valid for all flotilla members.
|
||||
-- * Define mission types, this flotilla can perform (see Ops.Auftrag#AUFTRAG).
|
||||
-- * Pause/unpause flotilla operations.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.Flotilla
|
||||
-- @image OPS_Flotilla.png
|
||||
|
||||
|
||||
--- FLOTILLA class.
|
||||
-- @type FLOTILLA
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity level.
|
||||
-- @field Ops.OpsGroup#OPSGROUP.WeaponData weaponData Weapon data table with key=BitType.
|
||||
-- @extends Ops.Cohort#COHORT
|
||||
|
||||
--- *No captain can do very wrong if he places his ship alongside that of an enemy.* -- Horation Nelson
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The FLOTILLA Concept
|
||||
--
|
||||
-- A FLOTILLA is an essential part of a FLEET.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #FLOTILLA
|
||||
FLOTILLA = {
|
||||
ClassName = "FLOTILLA",
|
||||
verbose = 0,
|
||||
weaponData = {},
|
||||
}
|
||||
|
||||
--- FLOTILLA class version.
|
||||
-- @field #string version
|
||||
FLOTILLA.version="0.1.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new FLOTILLA object and start the FSM.
|
||||
-- @param #FLOTILLA self
|
||||
-- @param #string TemplateGroupName Name of the template group.
|
||||
-- @param #number Ngroups Number of asset groups of this flotilla. Default 3.
|
||||
-- @param #string FlotillaName Name of the flotilla. Must be **unique**!
|
||||
-- @return #FLOTILLA self
|
||||
function FLOTILLA:New(TemplateGroupName, Ngroups, FlotillaName)
|
||||
|
||||
-- Inherit everything from COHORT class.
|
||||
local self=BASE:Inherit(self, COHORT:New(TemplateGroupName, Ngroups, FlotillaName)) -- #FLOTILLA
|
||||
|
||||
-- All flotillas get mission type Nothing.
|
||||
self:AddMissionCapability(AUFTRAG.Type.NOTHING, 50)
|
||||
|
||||
-- Is naval.
|
||||
self.isNaval=true
|
||||
|
||||
-- Get initial ammo.
|
||||
self.ammo=self:_CheckAmmo()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Flotilla specific user functions.
|
||||
|
||||
--- Set fleet of this flotilla.
|
||||
-- @param #FLOTILLA self
|
||||
-- @param Ops.Fleet#FLEET Fleet The fleet.
|
||||
-- @return #FLOTILLA self
|
||||
function FLOTILLA:SetFleet(Fleet)
|
||||
self.legion=Fleet
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get fleet of this flotilla.
|
||||
-- @param #FLOTILLA self
|
||||
-- @return Ops.Fleet#FLEET The fleet.
|
||||
function FLOTILLA:GetFleet()
|
||||
return self.legion
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Start & Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
||||
-- @param #FLOTILLA self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLOTILLA:onafterStart(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Starting %s v%s %s", self.ClassName, self.version, self.name)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__Status(-1)
|
||||
end
|
||||
|
||||
--- On after "Status" event.
|
||||
-- @param #FLOTILLA self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLOTILLA:onafterStatus(From, Event, To)
|
||||
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
local callsign=self.callsignName and UTILS.GetCallsignName(self.callsignName) or "N/A"
|
||||
local skill=self.skill and tostring(self.skill) or "N/A"
|
||||
|
||||
local NassetsTot=#self.assets
|
||||
local NassetsInS=self:CountAssets(true)
|
||||
local NassetsQP=0 ; local NassetsP=0 ; local NassetsQ=0
|
||||
if self.legion then
|
||||
NassetsQP, NassetsP, NassetsQ=self.legion:CountAssetsOnMission(nil, self)
|
||||
end
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("%s [Type=%s, Call=%s, Skill=%s]: Assets Total=%d, Stock=%d, Mission=%d [Active=%d, Queue=%d]",
|
||||
fsmstate, self.aircrafttype, callsign, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Weapon data info.
|
||||
if self.verbose>=3 and self.weaponData then
|
||||
local text="Weapon Data:"
|
||||
for bit,_weapondata in pairs(self.weaponData) do
|
||||
local weapondata=_weapondata --Ops.OpsGroup#OPSGROUP.WeaponData
|
||||
text=text..string.format("\n- Bit=%s: Rmin=%.1f km, Rmax=%.1f km", bit, weapondata.RangeMin/1000, weapondata.RangeMax/1000)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Check if group has detected any units.
|
||||
self:_CheckAssetStatus()
|
||||
|
||||
end
|
||||
|
||||
if not self:IsStopped() then
|
||||
self:__Status(-60)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,175 @@
|
||||
--- **Ops** - Brigade Platoon.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Set parameters like livery, skill valid for all platoon members.
|
||||
-- * Define modex and callsigns.
|
||||
-- * Define mission types, this platoon can perform (see Ops.Auftrag#AUFTRAG).
|
||||
-- * Pause/unpause platoon operations.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Ops.Platoon
|
||||
-- @image OPS_Platoon.png
|
||||
|
||||
|
||||
--- PLATOON class.
|
||||
-- @type PLATOON
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity level.
|
||||
-- @field Ops.OpsGroup#OPSGROUP.WeaponData weaponData Weapon data table with key=BitType.
|
||||
-- @extends Ops.Cohort#COHORT
|
||||
|
||||
--- *Some cool cohort quote* -- Known Author
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The PLATOON Concept
|
||||
--
|
||||
-- A PLATOON is essential part of an BRIGADE.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #PLATOON
|
||||
PLATOON = {
|
||||
ClassName = "PLATOON",
|
||||
verbose = 0,
|
||||
weaponData = {},
|
||||
}
|
||||
|
||||
--- PLATOON class version.
|
||||
-- @field #string version
|
||||
PLATOON.version="0.1.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new PLATOON object and start the FSM.
|
||||
-- @param #PLATOON self
|
||||
-- @param #string TemplateGroupName Name of the template group.
|
||||
-- @param #number Ngroups Number of asset groups of this platoon. Default 3.
|
||||
-- @param #string PlatoonName Name of the platoon. Must be **unique**!
|
||||
-- @return #PLATOON self
|
||||
function PLATOON:New(TemplateGroupName, Ngroups, PlatoonName)
|
||||
|
||||
-- Inherit everything from COHORT class.
|
||||
local self=BASE:Inherit(self, COHORT:New(TemplateGroupName, Ngroups, PlatoonName)) -- #PLATOON
|
||||
|
||||
-- All platoons get mission type Nothing.
|
||||
self:AddMissionCapability(AUFTRAG.Type.NOTHING, 50)
|
||||
|
||||
-- Is ground.
|
||||
self.isGround=true
|
||||
|
||||
-- Get ammo.
|
||||
self.ammo=self:_CheckAmmo()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Platoon specific user functions.
|
||||
|
||||
--- Set brigade of this platoon.
|
||||
-- @param #PLATOON self
|
||||
-- @param Ops.Brigade#BRIGADE Brigade The brigade.
|
||||
-- @return #PLATOON self
|
||||
function PLATOON:SetBrigade(Brigade)
|
||||
self.legion=Brigade
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get brigade of this platoon.
|
||||
-- @param #PLATOON self
|
||||
-- @return Ops.Brigade#BRIGADE The brigade.
|
||||
function PLATOON:GetBrigade()
|
||||
return self.legion
|
||||
end
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Start & Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--[[
|
||||
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
||||
-- @param #PLATOON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function PLATOON:onafterStart(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Starting %s v%s %s", self.ClassName, self.version, self.name)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__Status(-1)
|
||||
end
|
||||
]]
|
||||
|
||||
--- On after "Status" event.
|
||||
-- @param #PLATOON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function PLATOON:onafterStatus(From, Event, To)
|
||||
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
local callsign=self.callsignName and UTILS.GetCallsignName(self.callsignName) or "N/A"
|
||||
local skill=self.skill and tostring(self.skill) or "N/A"
|
||||
|
||||
local NassetsTot=#self.assets
|
||||
local NassetsInS=self:CountAssets(true)
|
||||
local NassetsQP=0 ; local NassetsP=0 ; local NassetsQ=0
|
||||
if self.legion then
|
||||
NassetsQP, NassetsP, NassetsQ=self.legion:CountAssetsOnMission(nil, self)
|
||||
end
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("%s [Type=%s, Call=%s, Skill=%s]: Assets Total=%d, Stock=%d, Mission=%d [Active=%d, Queue=%d]",
|
||||
fsmstate, self.aircrafttype, callsign, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Weapon data info.
|
||||
if self.verbose>=3 and self.weaponData then
|
||||
local text="Weapon Data:"
|
||||
for bit,_weapondata in pairs(self.weaponData) do
|
||||
local weapondata=_weapondata --Ops.OpsGroup#OPSGROUP.WeaponData
|
||||
text=text..string.format("\n- Bit=%s: Rmin=%.1f km, Rmax=%.1f km", bit, weapondata.RangeMin/1000, weapondata.RangeMax/1000)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Check if group has detected any units.
|
||||
self:_CheckAssetStatus()
|
||||
|
||||
end
|
||||
|
||||
if not self:IsStopped() then
|
||||
self:__Status(-60)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Misc functions.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,324 @@
|
||||
--- **Ops** - Airwing Squadron.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Set parameters like livery, skill valid for all squadron members.
|
||||
-- * Define modex and callsigns.
|
||||
-- * Define mission types, this squadron can perform (see Ops.Auftrag#AUFTRAG).
|
||||
-- * Pause/unpause squadron operations.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Ops.Squadron
|
||||
-- @image OPS_Squadron.png
|
||||
|
||||
|
||||
--- SQUADRON class.
|
||||
-- @type SQUADRON
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity level.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field #string name Name of the squadron.
|
||||
-- @field #string templatename Name of the template group.
|
||||
-- @field #string aircrafttype Type of the airframe the squadron is using.
|
||||
-- @field Wrapper.Group#GROUP templategroup Template group.
|
||||
-- @field #number ngrouping User defined number of units in the asset group.
|
||||
-- @field #table assets Squadron assets.
|
||||
-- @field #table missiontypes Capabilities (mission types and performances) of the squadron.
|
||||
-- @field #number fuellow Low fuel threshold.
|
||||
-- @field #boolean fuellowRefuel If `true`, flight tries to refuel at the nearest tanker.
|
||||
-- @field #number maintenancetime Time in seconds needed for maintenance of a returned flight.
|
||||
-- @field #number repairtime Time in seconds for each
|
||||
-- @field #string livery Livery of the squadron.
|
||||
-- @field #number skill Skill of squadron members.
|
||||
-- @field #number modex Modex.
|
||||
-- @field #number modexcounter Counter to incease modex number for assets.
|
||||
-- @field #string callsignName Callsign name.
|
||||
-- @field #number callsigncounter Counter to increase callsign names for new assets.
|
||||
-- @field #number Ngroups Number of asset flight groups this squadron has.
|
||||
-- @field #number engageRange Mission range in meters.
|
||||
-- @field #string attribute Generalized attribute of the squadron template group.
|
||||
-- @field #number tankerSystem For tanker squads, the refuel system used (boom=0 or probpe=1). Default nil.
|
||||
-- @field #number refuelSystem For refuelable squads, the refuel system used (boom=0 or probe=1). Default nil.
|
||||
-- @field #table tacanChannel List of TACAN channels available to the squadron.
|
||||
-- @field #number radioFreq Radio frequency in MHz the squad uses.
|
||||
-- @field #number radioModu Radio modulation the squad uses.
|
||||
-- @field #string takeoffType Take of type.
|
||||
-- @field #table parkingIDs Parking IDs for this squadron.
|
||||
-- @field #boolean despawnAfterLanding Aircraft are despawned after landing.
|
||||
-- @field #boolean despawnAfterHolding Aircraft are despawned after holding.
|
||||
-- @extends Ops.Cohort#COHORT
|
||||
|
||||
--- *It is unbelievable what a squadron of twelve aircraft did to tip the balance* -- Adolf Galland
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The SQUADRON Concept
|
||||
--
|
||||
-- A SQUADRON is essential part of an @{Ops.Airwing#AIRWING} and consists of **one** type of aircraft.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #SQUADRON
|
||||
SQUADRON = {
|
||||
ClassName = "SQUADRON",
|
||||
verbose = 0,
|
||||
modex = nil,
|
||||
modexcounter = 0,
|
||||
callsignName = nil,
|
||||
callsigncounter= 11,
|
||||
tankerSystem = nil,
|
||||
refuelSystem = nil,
|
||||
}
|
||||
|
||||
--- SQUADRON class version.
|
||||
-- @field #string version
|
||||
SQUADRON.version="0.8.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- DONE: Parking spots for squadrons?
|
||||
-- DONE: Engage radius.
|
||||
-- DONE: Modex.
|
||||
-- DONE: Call signs.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new SQUADRON object and start the FSM.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string TemplateGroupName Name of the template group.
|
||||
-- @param #number Ngroups Number of asset groups of this squadron. Default 3.
|
||||
-- @param #string SquadronName Name of the squadron, e.g. "VFA-37". Must be **unique**!
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:New(TemplateGroupName, Ngroups, SquadronName)
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, COHORT:New(TemplateGroupName, Ngroups, SquadronName)) -- #SQUADRON
|
||||
|
||||
-- Everyone can ORBIT.
|
||||
self:AddMissionCapability(AUFTRAG.Type.ORBIT)
|
||||
|
||||
-- Is air.
|
||||
self.isAir=true
|
||||
|
||||
-- Refueling system.
|
||||
self.refuelSystem=select(2, self.templategroup:GetUnit(1):IsRefuelable())
|
||||
self.tankerSystem=select(2, self.templategroup:GetUnit(1):IsTanker())
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
-- See COHORT class
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set number of units in groups.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number nunits Number of units. Must be >=1 and <=4. Default 2.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetGrouping(nunits)
|
||||
self.ngrouping=nunits or 2
|
||||
if self.ngrouping<1 then self.ngrouping=1 end
|
||||
if self.ngrouping>4 then self.ngrouping=4 end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set valid parking spot IDs. Assets of this squad are only allowed to be spawned at these parking spots. **Note** that the IDs are different from the ones displayed in the mission editor!
|
||||
-- @param #SQUADRON self
|
||||
-- @param #table ParkingIDs Table of parking ID numbers or a single `#number`.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetParkingIDs(ParkingIDs)
|
||||
if type(ParkingIDs)~="table" then
|
||||
ParkingIDs={ParkingIDs}
|
||||
end
|
||||
self.parkingIDs=ParkingIDs
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set takeoff type. All assets of this squadron will be spawned with cold (default) or hot engines.
|
||||
-- Spawning on runways is not supported.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string TakeoffType Take off type: "Cold" (default) or "Hot" with engines on or "Air" for spawning in air.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetTakeoffType(TakeoffType)
|
||||
TakeoffType=TakeoffType or "Cold"
|
||||
if TakeoffType:lower()=="hot" then
|
||||
self.takeoffType=COORDINATE.WaypointType.TakeOffParkingHot
|
||||
elseif TakeoffType:lower()=="cold" then
|
||||
self.takeoffType=COORDINATE.WaypointType.TakeOffParking
|
||||
elseif TakeoffType:lower()=="air" then
|
||||
self.takeoffType=COORDINATE.WaypointType.TurningPoint
|
||||
else
|
||||
self.takeoffType=COORDINATE.WaypointType.TakeOffParking
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set takeoff type cold (default). All assets of this squadron will be spawned with engines off (cold).
|
||||
-- @param #SQUADRON self
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetTakeoffCold()
|
||||
self:SetTakeoffType("Cold")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set takeoff type hot. All assets of this squadron will be spawned with engines on (hot).
|
||||
-- @param #SQUADRON self
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetTakeoffHot()
|
||||
self:SetTakeoffType("Hot")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set takeoff type air. All assets of this squadron will be spawned in air above the airbase.
|
||||
-- @param #SQUADRON self
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetTakeoffAir()
|
||||
self:SetTakeoffType("Air")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set despawn after landing. Aircraft will be despawned after the landing event.
|
||||
-- Can help to avoid DCS AI taxiing issues.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #boolean Switch If `true` (default), activate despawn after landing.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetDespawnAfterLanding(Switch)
|
||||
if Switch then
|
||||
self.despawnAfterLanding=Switch
|
||||
else
|
||||
self.despawnAfterLanding=true
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set despawn after holding. Aircraft will be despawned when they arrive at their holding position at the airbase.
|
||||
-- Can help to avoid DCS AI taxiing issues.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #boolean Switch If `true` (default), activate despawn after holding.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetDespawnAfterHolding(Switch)
|
||||
if Switch then
|
||||
self.despawnAfterHolding=Switch
|
||||
else
|
||||
self.despawnAfterHolding=true
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set low fuel threshold.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #number LowFuel Low fuel threshold in percent. Default 25.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetFuelLowThreshold(LowFuel)
|
||||
self.fuellow=LowFuel or 25
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set if low fuel threshold is reached, flight tries to refuel at the neares tanker.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #boolean switch If true or nil, flight goes for refuelling. If false, turn this off.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetFuelLowRefuel(switch)
|
||||
if switch==false then
|
||||
self.fuellowRefuel=false
|
||||
else
|
||||
self.fuellowRefuel=true
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set airwing.
|
||||
-- @param #SQUADRON self
|
||||
-- @param Ops.AirWing#AIRWING Airwing The airwing.
|
||||
-- @return #SQUADRON self
|
||||
function SQUADRON:SetAirwing(Airwing)
|
||||
self.legion=Airwing
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get airwing.
|
||||
-- @param #SQUADRON self
|
||||
-- @return Ops.AirWing#AIRWING The airwing.
|
||||
function SQUADRON:GetAirwing(Airwing)
|
||||
return self.legion
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Start & Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function SQUADRON:onafterStart(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Starting SQUADRON", self.name)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__Status(-1)
|
||||
end
|
||||
|
||||
--- On after "Status" event.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function SQUADRON:onafterStatus(From, Event, To)
|
||||
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
local callsign=self.callsignName and UTILS.GetCallsignName(self.callsignName) or "N/A"
|
||||
local modex=self.modex and self.modex or -1
|
||||
local skill=self.skill and tostring(self.skill) or "N/A"
|
||||
|
||||
local NassetsTot=#self.assets
|
||||
local NassetsInS=self:CountAssets(true)
|
||||
local NassetsQP=0 ; local NassetsP=0 ; local NassetsQ=0
|
||||
if self.legion then
|
||||
NassetsQP, NassetsP, NassetsQ=self.legion:CountAssetsOnMission(nil, self)
|
||||
end
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("%s [Type=%s, Call=%s, Modex=%d, Skill=%s]: Assets Total=%d, Stock=%d, Mission=%d [Active=%d, Queue=%d]",
|
||||
fsmstate, self.aircrafttype, callsign, modex, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Check if group has detected any units.
|
||||
self:_CheckAssetStatus()
|
||||
|
||||
end
|
||||
|
||||
if not self:IsStopped() then
|
||||
self:__Status(-60)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,6 +46,7 @@
|
||||
-- @field #string path Path to the SRS exe. This includes the final slash "/".
|
||||
-- @field #string google Full path google credentials JSON file, e.g. "C:\Users\username\Downloads\service-account-file.json".
|
||||
-- @field #string Label Label showing up on the SRS radio overlay. Default is "ROBOT". No spaces allowed.
|
||||
-- @field #table AltBackend Table containing functions and variables to enable an alternate backend to transmit to SRS.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *It is a very sad thing that nowadays there is so little useless information.* - Oscar Wilde
|
||||
@@ -123,6 +124,50 @@
|
||||
--
|
||||
-- Use @{#MSRS.SetVolume} to define the SRS volume. Defaults to 1.0. Allowed values are between 0.0 and 1.0, from silent to loudest.
|
||||
--
|
||||
-- ## Set DCS-gRPC as an alternative to 'DCS-SR-ExternalAudio.exe' for TTS
|
||||
--
|
||||
-- Use @{#MSRS.SetDefaultBackendGRPC} to enable [DCS-gRPC](https://github.com/DCS-gRPC/rust-server) as an alternate backend for transmitting text-to-speech over SRS.
|
||||
-- This can be useful if 'DCS-SR-ExternalAudio.exe' cannot be used in the environment, or to use Azure or AWS clouds for TTS. Note that DCS-gRPC does not (yet?) support
|
||||
-- all of the features and options available with 'DCS-SR-ExternalAudio.exe'. Of note, only text-to-speech is supported and it it cannot be used to transmit audio files.
|
||||
--
|
||||
-- DCS-gRPC must be installed and configured per the [DCS-gRPC documentation](https://github.com/DCS-gRPC/rust-server) and already running via either the 'autostart' mechanism
|
||||
-- or a Lua call to 'GRPC.load()' prior to use of the alternate DCS-gRPC backend. If a cloud TTS provider is being used, the API key must be set via the 'Config\dcs-grpc.lua'
|
||||
-- configuration file prior DCS-gRPC being started. DCS-gRPC can be used both with DCS dedicated server and regular DCS installations.
|
||||
--
|
||||
-- To use the default local Windows TTS with DCS-gRPC, Windows 2019 Server (or newer) or Windows 10/11 are required. Voices for non-local languages and dialects may need to
|
||||
-- be explicitly installed.
|
||||
--
|
||||
-- To set the MSRS class to use the DCS-gRPC backend for all future instances, call the function `MSRS.SetDefaultBackendGRPC()`.
|
||||
--
|
||||
-- **Note** - When using other classes that use MSRS with the alternate DCS-gRPC backend, pass them strings instead of nil values for non-applicable fields with filesystem paths,
|
||||
-- such as the SRS path or Google credential path. This will help maximize compatibility with other classes that were written for the default backend.
|
||||
--
|
||||
-- Basic Play Text-To-Speech example using alternate DCS-gRPC backend (DCS-gRPC not previously started):
|
||||
--
|
||||
-- -- Start DCS-gRPC
|
||||
-- GRPC.load()
|
||||
-- -- Select the alternate DCS-gRPC backend for new MSRS instances
|
||||
-- MSRS.SetDefaultBackendGRPC()
|
||||
-- -- Create a SOUNDTEXT object.
|
||||
-- local text=SOUNDTEXT:New("All Enemies destroyed")
|
||||
-- -- MOOSE SRS
|
||||
-- local msrs=MSRS:New('', 305.0)
|
||||
-- -- Text-to speech with default voice after 30 seconds.
|
||||
-- msrs:PlaySoundText(text, 30)
|
||||
--
|
||||
-- Basic example of using another class (ATIS) with SRS and the DCS-gRPC backend (DCS-gRPC not previously started):
|
||||
--
|
||||
-- -- Start DCS-gRPC
|
||||
-- GRPC.load()
|
||||
-- -- Select the alternate DCS-gRPC backend for new MSRS instances
|
||||
-- MSRS.SetDefaultBackendGRPC()
|
||||
-- -- Create new ATIS as usual
|
||||
-- atis=ATIS:New("Nellis", 251, radio.modulation.AM)
|
||||
-- -- ATIS:SetSRS() expects a string for the SRS path even though it is not needed with DCS-gRPC
|
||||
-- atis:SetSRS('')
|
||||
-- -- Start ATIS
|
||||
-- atis:Start()
|
||||
--
|
||||
-- @field #MSRS
|
||||
MSRS = {
|
||||
ClassName = "MSRS",
|
||||
@@ -139,11 +184,12 @@ MSRS = {
|
||||
speed = 1,
|
||||
coordinate = nil,
|
||||
Label = "ROBOT",
|
||||
AltBackend = nil,
|
||||
}
|
||||
|
||||
--- MSRS class version.
|
||||
-- @field #string version
|
||||
MSRS.version="0.1.1"
|
||||
MSRS.version="0.1.2"
|
||||
|
||||
--- Voices
|
||||
-- @type Voices
|
||||
@@ -264,16 +310,35 @@ MSRS.Voices = {
|
||||
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. Can also be given as a #table of multiple frequencies.
|
||||
-- @param #number Modulation Radio modulation: 0=AM (default), 1=FM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. Can also be given as a #table of multiple modulations.
|
||||
-- @param #number Volume Volume - 1.0 is max, 0.0 is silence
|
||||
-- @param #table AltBackend Optional table containing tables 'Functions' and 'Vars' which add/replace functions and variables for the MSRS instance to allow alternate backends for transmitting to SRS.
|
||||
-- @return #MSRS self
|
||||
function MSRS:New(PathToSRS, Frequency, Modulation, Volume)
|
||||
function MSRS:New(PathToSRS, Frequency, Modulation, Volume, AltBackend)
|
||||
|
||||
-- Defaults.
|
||||
Frequency =Frequency or 143
|
||||
Modulation= Modulation or radio.modulation.AM
|
||||
Frequency = Frequency or 143
|
||||
Modulation = Modulation or radio.modulation.AM
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, BASE:New()) -- #MSRS
|
||||
|
||||
-- If AltBackend is supplied, initialize it, which will add/replace functions and variables in this MSRS instance.
|
||||
if type( AltBackend ) == "table" or type( self.AltBackend ) == "table" then
|
||||
|
||||
local Backend = UTILS.DeepCopy(AltBackend) or UTILS.DeepCopy(self.AltBackend)
|
||||
|
||||
-- Add parameters to vars so alternate backends can use them if applicable
|
||||
Backend.Vars = Backend.Vars or {}
|
||||
Backend.Vars.PathToSRS = UTILS.DeepCopy(PathToSRS) -- DeepCopy probably unecessary
|
||||
Backend.Vars.Frequency = UTILS.DeepCopy(Frequency)
|
||||
Backend.Vars.Modulation = UTILS.DeepCopy(Modulation)
|
||||
Backend.Vars.Volume = UTILS.DeepCopy(Volume) -- DeepCopy probably unecessary
|
||||
|
||||
Backend.Functions = Backend.Functions or {}
|
||||
|
||||
return self:_NewAltBackend(Backend)
|
||||
end
|
||||
|
||||
-- If no AltBackend table, the proceed with default initialization
|
||||
self:SetPath(PathToSRS)
|
||||
self:SetPort()
|
||||
self:SetFrequencies(Frequency)
|
||||
@@ -568,6 +633,32 @@ function MSRS:Help()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets an alternate SRS backend to be used by MSRS to transmit over SRS for all new MSRS class instances.
|
||||
-- @param #table A table containing a table `Functions` with new/replacement class functions and `Vars` with new/replacement variables.
|
||||
-- @return #boolean Returns 'true' on success.
|
||||
function MSRS.SetDefaultBackend(Backend)
|
||||
if type(Backend) == "table" then
|
||||
MSRS.AltBackend = UTILS.DeepCopy(Backend)
|
||||
else
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- Restores default SRS backend (DCS-SR-ExternalAudio.exe) to be used by all new MSRS class instances to transmit over SRS.
|
||||
-- @return #boolean Returns 'true' on success.
|
||||
function MSRS.ResetDefaultBackend()
|
||||
MSRS.AltBackend = nil
|
||||
return true
|
||||
end
|
||||
|
||||
--- Sets DCS-gRPC as the default SRS backend for all new MSRS class instances.
|
||||
-- @return #boolean Returns 'true' on success.
|
||||
function MSRS.SetDefaultBackendGRPC()
|
||||
return MSRS.SetDefaultBackend(MSRS_BACKEND_DCSGRPC)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Transmission Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -736,6 +827,35 @@ end
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Adds or replaces functions and variables in the current MSRS class instance to enable an alternate backends for transmitting to SRS.
|
||||
-- @param #MSRS self
|
||||
-- @param #table A table containing a table `Functions` with new/replacement class functions and `Vars` with new/replacement variables.
|
||||
-- @return #MSRS self
|
||||
function MSRS:_NewAltBackend(Backend)
|
||||
BASE:T('Entering MSRS:_NewAltBackend()')
|
||||
|
||||
-- Add/replace class instance functions with those defined in the alternate backend in Functions table
|
||||
for funcName,funcDef in pairs(Backend.Functions) do
|
||||
if type(funcDef) == 'function' then
|
||||
BASE:T('MSRS (re-)defining function MSRS:' .. funcName )
|
||||
self[funcName] = funcDef
|
||||
end
|
||||
end
|
||||
|
||||
-- Add/replace class instance variables with those defined in the alternate backend in Vars table
|
||||
for varName,varVal in pairs(Backend.Vars) do
|
||||
BASE:T('MSRS setting self.' .. varName)
|
||||
self[varName] = UTILS.DeepCopy(varVal)
|
||||
end
|
||||
|
||||
-- If _MSRSbackendInit() is defined in the backend, then run it (it should return self)
|
||||
if self._MSRSbackendInit and type(self._MSRSbackendInit) == 'function' then
|
||||
return self:_MSRSbackendInit()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Execute SRS command to play sound using the `DCS-SR-ExternalAudio.exe`.
|
||||
-- @param #MSRS self
|
||||
-- @param #string command Command to executer
|
||||
@@ -779,8 +899,25 @@ function MSRS:_ExecCommand(command)
|
||||
-- Remove file in 1 second.
|
||||
timer.scheduleFunction(os.remove, filename, timer.getTime()+1)
|
||||
timer.scheduleFunction(os.remove, filenvbs, timer.getTime()+1)
|
||||
|
||||
|
||||
|
||||
elseif false then
|
||||
|
||||
-- Create a tmp file.
|
||||
local filenvbs = os.getenv('TMP') .. "\\MSRS-"..STTS.uuid()..".vbs"
|
||||
|
||||
-- VBS script
|
||||
local script = io.open(filenvbs, "w+")
|
||||
script:write(string.format('Set oShell = CreateObject ("Wscript.Shell")\n'))
|
||||
script:write(string.format('Dim strArgs\n'))
|
||||
script:write(string.format('strArgs = "cmd /c %s"\n', filename))
|
||||
script:write(string.format('oShell.Run strArgs, 0, false'))
|
||||
script:close()
|
||||
|
||||
local runvbs=string.format('cscript.exe //Nologo //B "%s"', filenvbs)
|
||||
|
||||
-- Play file in 0.01 seconds
|
||||
res=os.execute(runvbs)
|
||||
|
||||
else
|
||||
|
||||
-- Debug output.
|
||||
@@ -879,6 +1016,311 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
|
||||
return command
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- MSRS DCS-gRPC alternate backend
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Alternate backend for MSRS to enable text-to-speech via DCS-gRPC.
|
||||
-- ### Author: **dogjutsu**
|
||||
-- A table containing functions and variables for MSRS to use DCS-gRPC [DCS-gRPC](https://github.com/DCS-gRPC/rust-server) 0.7.0 or newer as a backend to transmit over SRS.
|
||||
-- This is not a standalone class. Instead, variables and functions under the `Vars` and `Functions` tables get added to or replace MSRS variables/functions when activated.
|
||||
--
|
||||
-- @type MSRS_BACKEND_DCSGRPC
|
||||
-- @field #number version Version number of this alternate backend.
|
||||
-- @field #table Functions A table of functions that will add or replace the default MSRS class functions.
|
||||
-- @field #table Vars A table of variables that will add or replace the default MSRS class variables.
|
||||
MSRS_BACKEND_DCSGRPC = {}
|
||||
MSRS_BACKEND_DCSGRPC.version = 0.1
|
||||
|
||||
MSRS_BACKEND_DCSGRPC.Functions = {}
|
||||
MSRS_BACKEND_DCSGRPC.Vars = { provider = 'win' }
|
||||
|
||||
--- Called by @{#MSRS._NewAltBackend} (if present) immediately after an alternate backend functions and variables for MSRS are added/replaced.
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions._MSRSbackendInit = function (self)
|
||||
BASE:I('Loaded MSRS DCS-gRPC alternate backend version ' .. self.AltBackend.version or 'unspecified')
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- MSRS DCS-gRPC alternate backend User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- No-op replacement function for @{#MSRS.SetPath} (Not Applicable)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.SetPath = function (self)
|
||||
return self
|
||||
end
|
||||
|
||||
--- No-op replacement function for @{#MSRS.GetPath} (Not Applicable)
|
||||
-- @param #MSRS self
|
||||
-- @return #string Empty string
|
||||
MSRS_BACKEND_DCSGRPC.Functions.GetPath = function (self)
|
||||
return ''
|
||||
end
|
||||
|
||||
--- No-op replacement function for @{#MSRS.SetVolume} (Not Applicable)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.SetVolume = function (self)
|
||||
BASE:I('NOTE: MSRS:SetVolume() not used with DCS-gRPC backend.')
|
||||
return self
|
||||
end
|
||||
|
||||
--- No-op replacement function for @{#MSRS.GetVolume} (Not Applicable)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.GetVolume = function (self)
|
||||
BASE:I('NOTE: MSRS:GetVolume() not used with DCS-gRPC backend.')
|
||||
return 1
|
||||
end
|
||||
|
||||
--- No-op replacement function for @{#MSRS.SetGender} (Not Applicable)
|
||||
-- @param #MSRS self
|
||||
-- #string Gender Gender: "male" or "female"
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.SetGender = function (self, Gender)
|
||||
-- Use DCS-gRPC default if not specified
|
||||
|
||||
if Gender then
|
||||
self.gender=Gender:lower()
|
||||
end
|
||||
|
||||
-- Debug output.
|
||||
self:T("Setting gender to "..tostring(self.gender))
|
||||
return self
|
||||
end
|
||||
|
||||
--- Replacement function for @{#MSRS.SetGoogle} to use google text-to-speech. (API key set as part of DCS-gRPC configuration)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.SetGoogle = function (self)
|
||||
self.provider = 'gcloud'
|
||||
return self
|
||||
end
|
||||
|
||||
--- MSRS:SetAWS() Use AWS text-to-speech. (API key set as part of DCS-gRPC configuration)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.SetAWS = function (self)
|
||||
self.provider = 'aws'
|
||||
return self
|
||||
end
|
||||
|
||||
--- MSRS:SetAzure() Use Azure text-to-speech. (API key set as part of DCS-gRPC configuration)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.SetAzure = function (self)
|
||||
self.provider = 'azure'
|
||||
return self
|
||||
end
|
||||
|
||||
--- MSRS:SetWin() Use local Windows OS text-to-speech (Windows Server 2019 / Windows 11 / Windows 10? or newer). (Default)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.SetWin = function (self)
|
||||
self.provider = 'win'
|
||||
return self
|
||||
end
|
||||
|
||||
--- Replacement function for @{#MSRS.Help} to display help.
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.Help = function (self)
|
||||
env.info('For DCS-gRPC help, please see: https://github.com/DCS-gRPC/rust-server')
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- MSRS DCS-gRPC alternate backend Transmission Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- No-op replacement function for @{#MSRS.PlaySoundFile} (Not Applicable)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.PlaySoundFile = function (self)
|
||||
BASE:E("ERROR: MSRS:PlaySoundFile() is not supported by the DCS-gRPC backend.")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Replacement function for @{#MSRS.PlaySoundText}
|
||||
-- @param #MSRS self
|
||||
-- @param Sound.SoundFile#SOUNDTEXT SoundText Sound text.
|
||||
-- @param #number Delay Delay in seconds, before the sound file is played.
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.PlaySoundText = function (self, SoundText, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, self.PlaySoundText, self, SoundText, 0)
|
||||
else
|
||||
self:_DCSgRPCtts(tostring(SoundText.text))
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Replacement function for @{#MSRS.PlayText}
|
||||
-- @param #MSRS self
|
||||
-- @param #string Text Text message.
|
||||
-- @param #number Delay Delay in seconds, before the message is played.
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.PlayText = function (self, Text, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, self.PlayText, self, Text, 0)
|
||||
else
|
||||
self:_DCSgRPCtts(tostring(Text))
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Replacement function for @{#MSRS.PlayText}
|
||||
-- @param #MSRS self
|
||||
-- @param #string Text Text message.
|
||||
-- @param #number Delay Delay in seconds, before the message is played.
|
||||
-- @param #table Frequencies Radio frequencies.
|
||||
-- @param #table Modulations Radio modulations. (Non-functional, DCS-gRPC sets automatically)
|
||||
-- @param #string Gender Gender. (Non-functional, only 'Voice' supported)
|
||||
-- @param #string Culture Culture. (Non-functional, only 'Voice' supported)
|
||||
-- @param #string Voice Voice.
|
||||
-- @param #number Volume Volume. (Non-functional, all transmissions full volume with DCS-gRPC)
|
||||
-- @param #string Label Label.
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.PlayTextExt = function (self, Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label)
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, self.PlayTextExt, self, Text, 0, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label)
|
||||
else
|
||||
self:_DCSgRPCtts(tostring(Text, nil, Frequencies, Voice, Label))
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- No-op replacement function for @{#MSRS.PlayTextFile} (Not Applicable)
|
||||
-- @param #MSRS self
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions.PlayTextFile = function (self, TextFile, Delay)
|
||||
BASE:E("ERROR: MSRS:PlayTextFile() is not supported by the DCS-gRPC backend.")
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- MSRS DCS-gRPC alternate backend Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- DCS-gRPC v0.70 TTS API call:
|
||||
-- GRPC.tts(ssml, frequency[, options]) - Synthesize text (ssml; SSML tags supported) to speech and transmit it over SRS on the frequency with the following optional options (and their defaults):
|
||||
|
||||
-- {
|
||||
-- -- The plain text without any transformations made to it for the purpose of getting it spoken out
|
||||
-- -- as desired (no SSML tags, no FOUR NINER instead of 49, ...). Even though this field is
|
||||
-- -- optional, please consider providing it as it can be used to display the spoken text to players
|
||||
-- -- with hearing impairments.
|
||||
-- plaintext = null, -- e.g. `= "Hello Pilot"`
|
||||
|
||||
-- -- Name of the SRS client.
|
||||
-- srsClientName = "DCS-gRPC",
|
||||
|
||||
-- -- The origin of the transmission. Relevant if the SRS server has "Line of
|
||||
-- -- Sight" and/or "Distance Limit" enabled.
|
||||
-- position = {
|
||||
-- lat = 0.0,
|
||||
-- lon = 0.0,
|
||||
-- alt = 0.0, -- in meters
|
||||
-- },
|
||||
|
||||
-- -- The coalition of the transmission. Relevant if the SRS server has "Secure
|
||||
-- -- Coalition Radios" enabled. Supported values are: `blue` and `red`. Defaults
|
||||
-- -- to being spectator if not specified.
|
||||
-- coalition = null,
|
||||
|
||||
-- -- TTS provider to be use. Defaults to the one configured in your config or to Windows'
|
||||
-- -- built-in TTS. Examples:
|
||||
-- -- `= { aws = {} }` / `= { aws = { voice = "..." } }` enable AWS TTS
|
||||
-- -- `= { azure = {} }` / `= { azure = { voice = "..." } }` enable Azure TTS
|
||||
-- -- `= { gcloud = {} }` / `= { gcloud = { voice = "..." } }` enable Google Cloud TTS
|
||||
-- -- `= { win = {} }` / `= { win = { voice = "..." } }` enable Windows TTS
|
||||
-- provider = null,
|
||||
-- }
|
||||
|
||||
--- Make DCS-gRPC API call to transmit text-to-speech over SRS.
|
||||
-- @param #MSRS self
|
||||
-- @param #string Text Text of message to transmit (can also be SSML).
|
||||
-- @param #string Optional plaintext version of message (for accessiblity)
|
||||
-- @param #table Frequencies Radio frequencies to transmit on. Can also accept a number in MHz.
|
||||
-- @param #string Voice Voice for the TTS provider to user.
|
||||
-- @param #string Label Label (SRS diplays as name of the transmitter).
|
||||
-- @return #MSRS self
|
||||
MSRS_BACKEND_DCSGRPC.Functions._DCSgRPCtts = function (self, Text, Plaintext, Frequencies, Voice, Label)
|
||||
|
||||
BASE:T("MSRS_BACKEND_DCSGRPC:_DCSgRPCtts()")
|
||||
BASE:T({Text, Plaintext, Frequencies, Voice, Label})
|
||||
|
||||
local options = {}
|
||||
local ssml = Text or ''
|
||||
|
||||
local XmitFrequencies = Frequencies or self.Frequency
|
||||
if type(XmitFrequencies)~="table" then
|
||||
XmitFrequencies={XmitFrequencies}
|
||||
end
|
||||
|
||||
options.plaintext = Plaintext
|
||||
options.srsClientName = Label or self.Label
|
||||
options.position = {}
|
||||
if self.coordinate then
|
||||
options.position.lat, options.position.lat, options.position.alt = self:_GetLatLongAlt(self.coordinate)
|
||||
end
|
||||
|
||||
options.position.lat = options.position.lat or 0.0
|
||||
options.position.lon = options.position.lon or 0.0
|
||||
options.position.alt = options.position.alt or 0.0
|
||||
|
||||
if UTILS.GetCoalitionName(self.coalition) == 'Blue' then
|
||||
options.coalition = 'blue'
|
||||
elseif UTILS.GetCoalitionName(self.coalition) == 'Red' then
|
||||
options.coalition = 'red'
|
||||
end
|
||||
|
||||
options.provider = {}
|
||||
options.provider[self.provider] = {}
|
||||
|
||||
if self.voice then
|
||||
options.provider[self.provider].voice = Voice or self.voice
|
||||
elseif ssml then
|
||||
-- DCS-gRPC doesn't directly support language/gender, but can use SSML
|
||||
-- Only use if a voice isn't explicitly set
|
||||
local preTag, genderProp, langProp, postTag = '', '', '', ''
|
||||
|
||||
if self.gender then
|
||||
genderProp = ' gender=\"' .. self.gender .. '\"'
|
||||
end
|
||||
if self.culture then
|
||||
langProp = ' language=\"' .. self.culture .. '\"'
|
||||
end
|
||||
|
||||
if self.culture or self.gender then
|
||||
preTag = '<voice' .. langProp .. genderProp .. '>'
|
||||
postTag = '</voice>'
|
||||
ssml = preTag .. Text .. postTag
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
for _,_freq in ipairs(XmitFrequencies) do
|
||||
local freq = _freq*1000000
|
||||
BASE:T("GRPC.tts")
|
||||
BASE:T(ssml)
|
||||
BASE:T(freq)
|
||||
BASE:T(options)
|
||||
GRPC.tts(ssml, freq, options)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Manages radio transmissions.
|
||||
@@ -922,6 +1364,11 @@ MSRSQUEUE = {
|
||||
-- @field #number interval Interval in seconds before next transmission.
|
||||
-- @field #boolean TransmitOnlyWithPlayers If true, only transmit if there are alive Players.
|
||||
-- @field Core.Set#SET_CLIENT PlayerSet PlayerSet created when TransmitOnlyWithPlayers == true
|
||||
-- @field #string gender Voice gender
|
||||
-- @field #string culture Voice culture
|
||||
-- @field #string voice Voice if any
|
||||
-- @field #number volume Volume
|
||||
-- @field #string label Label to be used
|
||||
|
||||
--- Create a new MSRSQUEUE object for a given radio frequency/modulation.
|
||||
-- @param #MSRSQUEUE self
|
||||
@@ -1001,8 +1448,13 @@ end
|
||||
-- @param #number subduration Duration [sec] of the subtitle being displayed. Default 5 sec.
|
||||
-- @param #number frequency Radio frequency if other than MSRS default.
|
||||
-- @param #number modulation Radio modulation if other then MSRS default.
|
||||
-- @param #string gender Gender of the voice
|
||||
-- @param #string culture Culture of the voice
|
||||
-- @param #string voice Specific voice
|
||||
-- @param #number volume Volume setting
|
||||
-- @param #string label Label to be used
|
||||
-- @return #MSRSQUEUE.Transmission Radio transmission table.
|
||||
function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation)
|
||||
function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation, gender, culture, voice, volume, label)
|
||||
|
||||
if self.TransmitOnlyWithPlayers then
|
||||
if self.PlayerSet and self.PlayerSet:CountAlive() == 0 then
|
||||
@@ -1037,6 +1489,11 @@ function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgr
|
||||
else
|
||||
transmission.subduration=0 --nil
|
||||
end
|
||||
transmission.gender = gender
|
||||
transmission.culture = culture
|
||||
transmission.voice = voice
|
||||
transmission.gender = volume
|
||||
transmission.label = label
|
||||
|
||||
-- Add transmission to queue.
|
||||
self:AddTransmission(transmission)
|
||||
@@ -1050,7 +1507,7 @@ end
|
||||
function MSRSQUEUE:Broadcast(transmission)
|
||||
|
||||
if transmission.frequency then
|
||||
transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, Gender, Culture, Voice, Volume, Label)
|
||||
transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, transmission.gender, transmission.culture, transmission.voice, transmission.volume, transmission.label)
|
||||
else
|
||||
transmission.msrs:PlayText(transmission.text)
|
||||
end
|
||||
|
||||
@@ -562,578 +562,3 @@ ENUMS.ReportingName =
|
||||
Predator = "MQ-1A",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- Enums for the STORAGE class for stores - which need to be in ""
|
||||
-- @type ENUMS.Storage
|
||||
-- @type ENUMS.Storage.weapons
|
||||
ENUMS.Storage = {
|
||||
weapons = {
|
||||
missiles = {}, -- Missiles
|
||||
bombs = {}, -- Bombs
|
||||
nurs = {}, -- Rockets and unguided
|
||||
containers = {}, -- Containers
|
||||
droptanks = {}, -- Droptanks
|
||||
adapters = {}, -- Adapter
|
||||
torpedoes = {}, -- Torpedoes
|
||||
}
|
||||
}
|
||||
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE253_F1B = "weapons.nurs.SNEB_TYPE253_F1B"
|
||||
ENUMS.Storage.weapons.missiles.P_24T = "weapons.missiles.P_24T"
|
||||
ENUMS.Storage.weapons.bombs.BLU_3B_OLD = "weapons.bombs.BLU-3B_OLD"
|
||||
ENUMS.Storage.weapons.missiles.AGM_154 = "weapons.missiles.AGM_154"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_M151_M433 = "weapons.nurs.HYDRA_70_M151_M433"
|
||||
ENUMS.Storage.weapons.bombs.SAM_Avenger_M1097_Skid_7090lb = "weapons.bombs.SAM Avenger M1097 Skid [7090lb]"
|
||||
ENUMS.Storage.weapons.bombs.British_GP_250LB_Bomb_Mk5 = "weapons.bombs.British_GP_250LB_Bomb_Mk5"
|
||||
ENUMS.Storage.weapons.containers.OV10_SMOKE = "weapons.containers.{OV10_SMOKE}"
|
||||
ENUMS.Storage.weapons.bombs.BLU_4B_OLD = "weapons.bombs.BLU-4B_OLD"
|
||||
ENUMS.Storage.weapons.bombs.FAB_500M54 = "weapons.bombs.FAB-500M54"
|
||||
ENUMS.Storage.weapons.bombs.GBU_38 = "weapons.bombs.GBU_38"
|
||||
ENUMS.Storage.weapons.containers.F_15E_AXQ_14_DATALINK = "weapons.containers.F-15E_AXQ-14_DATALINK"
|
||||
ENUMS.Storage.weapons.bombs.BEER_BOMB = "weapons.bombs.BEER_BOMB"
|
||||
ENUMS.Storage.weapons.bombs.P_50T = "weapons.bombs.P-50T"
|
||||
ENUMS.Storage.weapons.nurs.C_8CM_GN = "weapons.nurs.C_8CM_GN"
|
||||
ENUMS.Storage.weapons.bombs.FAB_500SL = "weapons.bombs.FAB-500SL"
|
||||
ENUMS.Storage.weapons.bombs.KAB_1500Kr = "weapons.bombs.KAB_1500Kr"
|
||||
ENUMS.Storage.weapons.bombs.two50_2 = "weapons.bombs.250-2"
|
||||
ENUMS.Storage.weapons.droptanks.Spitfire_tank_1 = "weapons.droptanks.Spitfire_tank_1"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65G = "weapons.missiles.AGM_65G"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65A = "weapons.missiles.AGM_65A"
|
||||
ENUMS.Storage.weapons.containers.Hercules_JATO = "weapons.containers.Hercules_JATO"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_M259 = "weapons.nurs.HYDRA_70_M259"
|
||||
ENUMS.Storage.weapons.missiles.AGM_84E = "weapons.missiles.AGM_84E"
|
||||
ENUMS.Storage.weapons.bombs.AN_M30A1 = "weapons.bombs.AN_M30A1"
|
||||
ENUMS.Storage.weapons.nurs.C_25 = "weapons.nurs.C_25"
|
||||
ENUMS.Storage.weapons.containers.AV8BNA_ALQ164 = "weapons.containers.AV8BNA_ALQ164"
|
||||
ENUMS.Storage.weapons.containers.lav_25 = "weapons.containers.lav-25"
|
||||
ENUMS.Storage.weapons.missiles.P_60 = "weapons.missiles.P_60"
|
||||
ENUMS.Storage.weapons.bombs.FAB_1500 = "weapons.bombs.FAB_1500"
|
||||
ENUMS.Storage.weapons.droptanks.FuelTank_350L = "weapons.droptanks.FuelTank_350L"
|
||||
ENUMS.Storage.weapons.bombs.AAA_Vulcan_M163_Skid_21577lb = "weapons.bombs.AAA Vulcan M163 Skid [21577lb]"
|
||||
ENUMS.Storage.weapons.missiles.Kormoran = "weapons.missiles.Kormoran"
|
||||
ENUMS.Storage.weapons.droptanks.HB_F14_EXT_DROPTANK_EMPTY = "weapons.droptanks.HB_F14_EXT_DROPTANK_EMPTY"
|
||||
ENUMS.Storage.weapons.droptanks.FuelTank_150L = "weapons.droptanks.FuelTank_150L"
|
||||
ENUMS.Storage.weapons.missiles.Rb_15F_for_A_I = "weapons.missiles.Rb 15F (for A.I.)"
|
||||
ENUMS.Storage.weapons.missiles.RB75T = "weapons.missiles.RB75T"
|
||||
ENUMS.Storage.weapons.missiles.Vikhr_M = "weapons.missiles.Vikhr_M"
|
||||
ENUMS.Storage.weapons.nurs.FFAR_M156_WP = "weapons.nurs.FFAR M156 WP"
|
||||
ENUMS.Storage.weapons.nurs.British_HE_60LBSAPNo2_3INCHNo1 = "weapons.nurs.British_HE_60LBSAPNo2_3INCHNo1"
|
||||
ENUMS.Storage.weapons.missiles.DWS39_MJ2 = "weapons.missiles.DWS39_MJ2"
|
||||
ENUMS.Storage.weapons.bombs.HEBOMBD = "weapons.bombs.HEBOMBD"
|
||||
ENUMS.Storage.weapons.missiles.CATM_9M = "weapons.missiles.CATM_9M"
|
||||
ENUMS.Storage.weapons.bombs.Mk_81 = "weapons.bombs.Mk_81"
|
||||
ENUMS.Storage.weapons.droptanks.Drop_Tank_300_Liter = "weapons.droptanks.Drop_Tank_300_Liter"
|
||||
ENUMS.Storage.weapons.containers.HMMWV_M1025 = "weapons.containers.HMMWV_M1025"
|
||||
ENUMS.Storage.weapons.bombs.SAM_CHAPARRAL_Air_21624lb = "weapons.bombs.SAM CHAPARRAL Air [21624lb]"
|
||||
ENUMS.Storage.weapons.missiles.AGM_154A = "weapons.missiles.AGM_154A"
|
||||
ENUMS.Storage.weapons.bombs.Mk_84AIR_TP = "weapons.bombs.Mk_84AIR_TP"
|
||||
ENUMS.Storage.weapons.bombs.GBU_31_V_3B = "weapons.bombs.GBU_31_V_3B"
|
||||
ENUMS.Storage.weapons.nurs.C_8CM_WH = "weapons.nurs.C_8CM_WH"
|
||||
ENUMS.Storage.weapons.missiles.Matra_Super_530D = "weapons.missiles.Matra Super 530D"
|
||||
ENUMS.Storage.weapons.nurs.ARF8M3TPSM = "weapons.nurs.ARF8M3TPSM"
|
||||
ENUMS.Storage.weapons.missiles.TGM_65H = "weapons.missiles.TGM_65H"
|
||||
ENUMS.Storage.weapons.nurs.M8rocket = "weapons.nurs.M8rocket"
|
||||
ENUMS.Storage.weapons.bombs.GBU_27 = "weapons.bombs.GBU_27"
|
||||
ENUMS.Storage.weapons.missiles.AGR_20A = "weapons.missiles.AGR_20A"
|
||||
ENUMS.Storage.weapons.missiles.LS_6_250 = "weapons.missiles.LS-6-250"
|
||||
ENUMS.Storage.weapons.droptanks.M2KC_RPL_522_EMPTY = "weapons.droptanks.M2KC_RPL_522_EMPTY"
|
||||
ENUMS.Storage.weapons.droptanks.M2KC_02_RPL541 = "weapons.droptanks.M2KC_02_RPL541"
|
||||
ENUMS.Storage.weapons.missiles.AGM_45 = "weapons.missiles.AGM_45"
|
||||
ENUMS.Storage.weapons.missiles.AGM_84A = "weapons.missiles.AGM_84A"
|
||||
ENUMS.Storage.weapons.bombs.APC_BTR_80_Air_23936lb = "weapons.bombs.APC BTR-80 Air [23936lb]"
|
||||
ENUMS.Storage.weapons.missiles.P_33E = "weapons.missiles.P_33E"
|
||||
ENUMS.Storage.weapons.missiles.Ataka_9M120 = "weapons.missiles.Ataka_9M120"
|
||||
ENUMS.Storage.weapons.bombs.MK76 = "weapons.bombs.MK76"
|
||||
ENUMS.Storage.weapons.bombs.AB_250_2_SD_2 = "weapons.bombs.AB_250_2_SD_2"
|
||||
ENUMS.Storage.weapons.missiles.Rb_05A = "weapons.missiles.Rb 05A"
|
||||
ENUMS.Storage.weapons.bombs.ART_GVOZDIKA_34720lb = "weapons.bombs.ART GVOZDIKA [34720lb]"
|
||||
ENUMS.Storage.weapons.bombs.Generic_Crate_20000lb = "weapons.bombs.Generic Crate [20000lb]"
|
||||
ENUMS.Storage.weapons.bombs.FAB_100SV = "weapons.bombs.FAB_100SV"
|
||||
ENUMS.Storage.weapons.bombs.BetAB_500 = "weapons.bombs.BetAB_500"
|
||||
ENUMS.Storage.weapons.droptanks.M2KC_02_RPL541_EMPTY = "weapons.droptanks.M2KC_02_RPL541_EMPTY"
|
||||
ENUMS.Storage.weapons.droptanks.PTB600_MIG15 = "weapons.droptanks.PTB600_MIG15"
|
||||
ENUMS.Storage.weapons.missiles.Rb_24J = "weapons.missiles.Rb 24J"
|
||||
ENUMS.Storage.weapons.nurs.C_8CM_BU = "weapons.nurs.C_8CM_BU"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE259E_F1B = "weapons.nurs.SNEB_TYPE259E_F1B"
|
||||
ENUMS.Storage.weapons.nurs.WGr21 = "weapons.nurs.WGr21"
|
||||
ENUMS.Storage.weapons.bombs.SAMP250HD = "weapons.bombs.SAMP250HD"
|
||||
ENUMS.Storage.weapons.containers.alq_184long = "weapons.containers.alq-184long"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE259E_H1 = "weapons.nurs.SNEB_TYPE259E_H1"
|
||||
ENUMS.Storage.weapons.bombs.British_SAP_250LB_Bomb_Mk5 = "weapons.bombs.British_SAP_250LB_Bomb_Mk5"
|
||||
ENUMS.Storage.weapons.bombs.Transport_UAZ_469_Air_3747lb = "weapons.bombs.Transport UAZ-469 Air [3747lb]"
|
||||
ENUMS.Storage.weapons.bombs.Mk_83CT = "weapons.bombs.Mk_83CT"
|
||||
ENUMS.Storage.weapons.missiles.AIM_7P = "weapons.missiles.AIM-7P"
|
||||
ENUMS.Storage.weapons.missiles.AT_6 = "weapons.missiles.AT_6"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE254_H1_GREEN = "weapons.nurs.SNEB_TYPE254_H1_GREEN"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE250_F1B = "weapons.nurs.SNEB_TYPE250_F1B"
|
||||
ENUMS.Storage.weapons.containers.U22A = "weapons.containers.U22A"
|
||||
ENUMS.Storage.weapons.bombs.British_GP_250LB_Bomb_Mk1 = "weapons.bombs.British_GP_250LB_Bomb_Mk1"
|
||||
ENUMS.Storage.weapons.bombs.CBU_105 = "weapons.bombs.CBU_105"
|
||||
ENUMS.Storage.weapons.droptanks.FW_190_Fuel_Tank = "weapons.droptanks.FW-190_Fuel-Tank"
|
||||
ENUMS.Storage.weapons.missiles.X_58 = "weapons.missiles.X_58"
|
||||
ENUMS.Storage.weapons.missiles.BK90_MJ1_MJ2 = "weapons.missiles.BK90_MJ1_MJ2"
|
||||
ENUMS.Storage.weapons.missiles.TGM_65D = "weapons.missiles.TGM_65D"
|
||||
ENUMS.Storage.weapons.containers.BRD_4_250 = "weapons.containers.BRD-4-250"
|
||||
ENUMS.Storage.weapons.missiles.P_73 = "weapons.missiles.P_73"
|
||||
ENUMS.Storage.weapons.bombs.AN_M66 = "weapons.bombs.AN_M66"
|
||||
ENUMS.Storage.weapons.bombs.APC_LAV_25_Air_22520lb = "weapons.bombs.APC LAV-25 Air [22520lb]"
|
||||
ENUMS.Storage.weapons.missiles.AIM_7MH = "weapons.missiles.AIM-7MH"
|
||||
ENUMS.Storage.weapons.containers.MB339_TravelPod = "weapons.containers.MB339_TravelPod"
|
||||
ENUMS.Storage.weapons.bombs.GBU_12 = "weapons.bombs.GBU_12"
|
||||
ENUMS.Storage.weapons.bombs.SC_250_T3_J = "weapons.bombs.SC_250_T3_J"
|
||||
ENUMS.Storage.weapons.missiles.KD_20 = "weapons.missiles.KD-20"
|
||||
ENUMS.Storage.weapons.missiles.AGM_86C = "weapons.missiles.AGM_86C"
|
||||
ENUMS.Storage.weapons.missiles.X_35 = "weapons.missiles.X_35"
|
||||
ENUMS.Storage.weapons.bombs.MK106 = "weapons.bombs.MK106"
|
||||
ENUMS.Storage.weapons.bombs.BETAB_500S = "weapons.bombs.BETAB-500S"
|
||||
ENUMS.Storage.weapons.nurs.C_5 = "weapons.nurs.C_5"
|
||||
ENUMS.Storage.weapons.nurs.S_24B = "weapons.nurs.S-24B"
|
||||
ENUMS.Storage.weapons.bombs.British_MC_500LB_Bomb_Mk2 = "weapons.bombs.British_MC_500LB_Bomb_Mk2"
|
||||
ENUMS.Storage.weapons.containers.ANAWW_13 = "weapons.containers.ANAWW_13"
|
||||
ENUMS.Storage.weapons.droptanks.droptank_108_gal = "weapons.droptanks.droptank_108_gal"
|
||||
ENUMS.Storage.weapons.droptanks.DFT_300_GAL_A4E_LR = "weapons.droptanks.DFT_300_GAL_A4E_LR"
|
||||
ENUMS.Storage.weapons.bombs.CBU_87 = "weapons.bombs.CBU_87"
|
||||
ENUMS.Storage.weapons.missiles.GAR_8 = "weapons.missiles.GAR-8"
|
||||
ENUMS.Storage.weapons.bombs.BELOUGA = "weapons.bombs.BELOUGA"
|
||||
ENUMS.Storage.weapons.containers.EclairM_33 = "weapons.containers.{EclairM_33}"
|
||||
ENUMS.Storage.weapons.bombs.ART_2S9_NONA_Air_19140lb = "weapons.bombs.ART 2S9 NONA Air [19140lb]"
|
||||
ENUMS.Storage.weapons.bombs.BR_250 = "weapons.bombs.BR_250"
|
||||
ENUMS.Storage.weapons.bombs.IAB_500 = "weapons.bombs.IAB-500"
|
||||
ENUMS.Storage.weapons.containers.AN_ASQ_228 = "weapons.containers.AN_ASQ_228"
|
||||
ENUMS.Storage.weapons.missiles.P_27P = "weapons.missiles.P_27P"
|
||||
ENUMS.Storage.weapons.bombs.SD_250_Stg = "weapons.bombs.SD_250_Stg"
|
||||
ENUMS.Storage.weapons.missiles.R_530F_IR = "weapons.missiles.R_530F_IR"
|
||||
ENUMS.Storage.weapons.bombs.British_SAP_500LB_Bomb_Mk5 = "weapons.bombs.British_SAP_500LB_Bomb_Mk5"
|
||||
ENUMS.Storage.weapons.bombs.FAB_250M54 = "weapons.bombs.FAB-250M54"
|
||||
ENUMS.Storage.weapons.containers.M2KC_AAF = "weapons.containers.{M2KC_AAF}"
|
||||
ENUMS.Storage.weapons.missiles.CM_802AKG_AI = "weapons.missiles.CM-802AKG_AI"
|
||||
ENUMS.Storage.weapons.bombs.CBU_103 = "weapons.bombs.CBU_103"
|
||||
ENUMS.Storage.weapons.containers.US_M10_SMOKE_TANK_RED = "weapons.containers.{US_M10_SMOKE_TANK_RED}"
|
||||
ENUMS.Storage.weapons.missiles.X_29T = "weapons.missiles.X_29T"
|
||||
ENUMS.Storage.weapons.bombs.HEMTT_TFFT_34400lb = "weapons.bombs.HEMTT TFFT [34400lb]"
|
||||
ENUMS.Storage.weapons.missiles.C_701IR = "weapons.missiles.C-701IR"
|
||||
ENUMS.Storage.weapons.containers.fullCargoSeats = "weapons.containers.fullCargoSeats"
|
||||
ENUMS.Storage.weapons.bombs.GBU_15_V_31_B = "weapons.bombs.GBU_15_V_31_B"
|
||||
ENUMS.Storage.weapons.bombs.APC_M1043_HMMWV_Armament_Air_7023lb = "weapons.bombs.APC M1043 HMMWV Armament Air [7023lb]"
|
||||
ENUMS.Storage.weapons.missiles.PL_5EII = "weapons.missiles.PL-5EII"
|
||||
ENUMS.Storage.weapons.bombs.SC_250_T1_L2 = "weapons.bombs.SC_250_T1_L2"
|
||||
ENUMS.Storage.weapons.torpedoes.mk46torp_name = "weapons.torpedoes.mk46torp_name"
|
||||
ENUMS.Storage.weapons.containers.F_15E_AAQ_33_XR_ATP_SE = "weapons.containers.F-15E_AAQ-33_XR_ATP-SE"
|
||||
ENUMS.Storage.weapons.missiles.AIM_7 = "weapons.missiles.AIM_7"
|
||||
ENUMS.Storage.weapons.missiles.AGM_122 = "weapons.missiles.AGM_122"
|
||||
ENUMS.Storage.weapons.bombs.HEBOMB = "weapons.bombs.HEBOMB"
|
||||
ENUMS.Storage.weapons.bombs.CBU_97 = "weapons.bombs.CBU_97"
|
||||
ENUMS.Storage.weapons.bombs.MK_81SE = "weapons.bombs.MK-81SE"
|
||||
ENUMS.Storage.weapons.nurs.Zuni_127 = "weapons.nurs.Zuni_127"
|
||||
ENUMS.Storage.weapons.containers.M2KC_AGF = "weapons.containers.{M2KC_AGF}"
|
||||
ENUMS.Storage.weapons.droptanks.Hercules_ExtFuelTank = "weapons.droptanks.Hercules_ExtFuelTank"
|
||||
ENUMS.Storage.weapons.containers.SMOKE_WHITE = "weapons.containers.{SMOKE_WHITE}"
|
||||
ENUMS.Storage.weapons.droptanks.droptank_150_gal = "weapons.droptanks.droptank_150_gal"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_WTU1B = "weapons.nurs.HYDRA_70_WTU1B"
|
||||
ENUMS.Storage.weapons.missiles.GB_6_SFW = "weapons.missiles.GB-6-SFW"
|
||||
ENUMS.Storage.weapons.missiles.KD_63 = "weapons.missiles.KD-63"
|
||||
ENUMS.Storage.weapons.bombs.GBU_28 = "weapons.bombs.GBU_28"
|
||||
ENUMS.Storage.weapons.nurs.C_8CM_YE = "weapons.nurs.C_8CM_YE"
|
||||
ENUMS.Storage.weapons.droptanks.HB_F14_EXT_DROPTANK = "weapons.droptanks.HB_F14_EXT_DROPTANK"
|
||||
ENUMS.Storage.weapons.missiles.Super_530F = "weapons.missiles.Super_530F"
|
||||
ENUMS.Storage.weapons.missiles.Ataka_9M220 = "weapons.missiles.Ataka_9M220"
|
||||
ENUMS.Storage.weapons.bombs.BDU_33 = "weapons.bombs.BDU_33"
|
||||
ENUMS.Storage.weapons.bombs.British_GP_250LB_Bomb_Mk4 = "weapons.bombs.British_GP_250LB_Bomb_Mk4"
|
||||
ENUMS.Storage.weapons.missiles.TOW = "weapons.missiles.TOW"
|
||||
ENUMS.Storage.weapons.bombs.ATGM_M1045_HMMWV_TOW_Air_7183lb = "weapons.bombs.ATGM M1045 HMMWV TOW Air [7183lb]"
|
||||
ENUMS.Storage.weapons.missiles.X_25MR = "weapons.missiles.X_25MR"
|
||||
ENUMS.Storage.weapons.droptanks.fueltank230 = "weapons.droptanks.fueltank230"
|
||||
ENUMS.Storage.weapons.droptanks.PTB_490C_MIG21 = "weapons.droptanks.PTB-490C-MIG21"
|
||||
ENUMS.Storage.weapons.bombs.M1025_HMMWV_Air_6160lb = "weapons.bombs.M1025 HMMWV Air [6160lb]"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE254_F1B_GREEN = "weapons.nurs.SNEB_TYPE254_F1B_GREEN"
|
||||
ENUMS.Storage.weapons.missiles.R_550 = "weapons.missiles.R_550"
|
||||
ENUMS.Storage.weapons.bombs.KAB_1500LG = "weapons.bombs.KAB_1500LG"
|
||||
ENUMS.Storage.weapons.missiles.AGM_84D = "weapons.missiles.AGM_84D"
|
||||
ENUMS.Storage.weapons.missiles.YJ_83K = "weapons.missiles.YJ-83K"
|
||||
ENUMS.Storage.weapons.missiles.AIM_54C_Mk47 = "weapons.missiles.AIM_54C_Mk47"
|
||||
ENUMS.Storage.weapons.missiles.BRM_1_90MM = "weapons.missiles.BRM-1_90MM"
|
||||
ENUMS.Storage.weapons.missiles.Ataka_9M120F = "weapons.missiles.Ataka_9M120F"
|
||||
ENUMS.Storage.weapons.droptanks.Eleven00L_Tank = "weapons.droptanks.1100L Tank"
|
||||
ENUMS.Storage.weapons.bombs.BAP_100 = "weapons.bombs.BAP_100"
|
||||
ENUMS.Storage.weapons.adapters.lau_88 = "weapons.adapters.lau-88"
|
||||
ENUMS.Storage.weapons.missiles.P_40T = "weapons.missiles.P_40T"
|
||||
ENUMS.Storage.weapons.missiles.GB_6 = "weapons.missiles.GB-6"
|
||||
ENUMS.Storage.weapons.bombs.FAB_250M54TU = "weapons.bombs.FAB-250M54TU"
|
||||
ENUMS.Storage.weapons.missiles.DWS39_MJ1 = "weapons.missiles.DWS39_MJ1"
|
||||
ENUMS.Storage.weapons.missiles.CM_802AKG = "weapons.missiles.CM-802AKG"
|
||||
ENUMS.Storage.weapons.bombs.FAB_250 = "weapons.bombs.FAB_250"
|
||||
ENUMS.Storage.weapons.missiles.C_802AK = "weapons.missiles.C_802AK"
|
||||
ENUMS.Storage.weapons.bombs.SD_500_A = "weapons.bombs.SD_500_A"
|
||||
ENUMS.Storage.weapons.bombs.GBU_32_V_2B = "weapons.bombs.GBU_32_V_2B"
|
||||
ENUMS.Storage.weapons.containers.marder = "weapons.containers.marder"
|
||||
ENUMS.Storage.weapons.missiles.ADM_141B = "weapons.missiles.ADM_141B"
|
||||
ENUMS.Storage.weapons.bombs.ROCKEYE = "weapons.bombs.ROCKEYE"
|
||||
ENUMS.Storage.weapons.missiles.BK90_MJ1 = "weapons.missiles.BK90_MJ1"
|
||||
ENUMS.Storage.weapons.containers.BTR_80 = "weapons.containers.BTR-80"
|
||||
ENUMS.Storage.weapons.bombs.SAM_ROLAND_ADS_34720lb = "weapons.bombs.SAM ROLAND ADS [34720lb]"
|
||||
ENUMS.Storage.weapons.containers.wmd7 = "weapons.containers.wmd7"
|
||||
ENUMS.Storage.weapons.missiles.C_701T = "weapons.missiles.C-701T"
|
||||
ENUMS.Storage.weapons.missiles.AIM_7E_2 = "weapons.missiles.AIM-7E-2"
|
||||
ENUMS.Storage.weapons.nurs.HVAR = "weapons.nurs.HVAR"
|
||||
ENUMS.Storage.weapons.containers.HMMWV_M1043 = "weapons.containers.HMMWV_M1043"
|
||||
ENUMS.Storage.weapons.droptanks.PTB_800_MIG21 = "weapons.droptanks.PTB-800-MIG21"
|
||||
ENUMS.Storage.weapons.missiles.AGM_114 = "weapons.missiles.AGM_114"
|
||||
ENUMS.Storage.weapons.bombs.APC_M1126_Stryker_ICV_29542lb = "weapons.bombs.APC M1126 Stryker ICV [29542lb]"
|
||||
ENUMS.Storage.weapons.bombs.APC_M113_Air_21624lb = "weapons.bombs.APC M113 Air [21624lb]"
|
||||
ENUMS.Storage.weapons.bombs.M_117 = "weapons.bombs.M_117"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65D = "weapons.missiles.AGM_65D"
|
||||
ENUMS.Storage.weapons.droptanks.MB339_TT320_L = "weapons.droptanks.MB339_TT320_L"
|
||||
ENUMS.Storage.weapons.missiles.AGM_86 = "weapons.missiles.AGM_86"
|
||||
ENUMS.Storage.weapons.bombs.BDU_45LGB = "weapons.bombs.BDU_45LGB"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65H = "weapons.missiles.AGM_65H"
|
||||
ENUMS.Storage.weapons.nurs.RS_82 = "weapons.nurs.RS-82"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE252_F1B = "weapons.nurs.SNEB_TYPE252_F1B"
|
||||
ENUMS.Storage.weapons.bombs.BL_755 = "weapons.bombs.BL_755"
|
||||
ENUMS.Storage.weapons.containers.F_15E_AAQ_28_LITENING = "weapons.containers.F-15E_AAQ-28_LITENING"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE256_F1B = "weapons.nurs.SNEB_TYPE256_F1B"
|
||||
ENUMS.Storage.weapons.missiles.AGM_84H = "weapons.missiles.AGM_84H"
|
||||
ENUMS.Storage.weapons.missiles.AIM_54 = "weapons.missiles.AIM_54"
|
||||
ENUMS.Storage.weapons.missiles.X_31A = "weapons.missiles.X_31A"
|
||||
ENUMS.Storage.weapons.bombs.KAB_500Kr = "weapons.bombs.KAB_500Kr"
|
||||
ENUMS.Storage.weapons.containers.SPS_141_100 = "weapons.containers.SPS-141-100"
|
||||
ENUMS.Storage.weapons.missiles.BK90_MJ2 = "weapons.missiles.BK90_MJ2"
|
||||
ENUMS.Storage.weapons.missiles.Super_530D = "weapons.missiles.Super_530D"
|
||||
ENUMS.Storage.weapons.bombs.CBU_52B = "weapons.bombs.CBU_52B"
|
||||
ENUMS.Storage.weapons.droptanks.PTB_450 = "weapons.droptanks.PTB-450"
|
||||
ENUMS.Storage.weapons.bombs.IFV_MCV_80_34720lb = "weapons.bombs.IFV MCV-80 [34720lb]"
|
||||
ENUMS.Storage.weapons.containers.Two_c9 = "weapons.containers.2-c9"
|
||||
ENUMS.Storage.weapons.missiles.AIM_9JULI = "weapons.missiles.AIM-9JULI"
|
||||
ENUMS.Storage.weapons.droptanks.MB339_TT500_R = "weapons.droptanks.MB339_TT500_R"
|
||||
ENUMS.Storage.weapons.nurs.C_8CM = "weapons.nurs.C_8CM"
|
||||
ENUMS.Storage.weapons.containers.BARAX = "weapons.containers.BARAX"
|
||||
ENUMS.Storage.weapons.missiles.P_40R = "weapons.missiles.P_40R"
|
||||
ENUMS.Storage.weapons.missiles.YJ_12 = "weapons.missiles.YJ-12"
|
||||
ENUMS.Storage.weapons.missiles.CM_802AKG = "weapons.missiles.CM_802AKG"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE254_H1_YELLOW = "weapons.nurs.SNEB_TYPE254_H1_YELLOW"
|
||||
ENUMS.Storage.weapons.bombs.Durandal = "weapons.bombs.Durandal"
|
||||
ENUMS.Storage.weapons.droptanks.i16_eft = "weapons.droptanks.i16_eft"
|
||||
ENUMS.Storage.weapons.droptanks.AV8BNA_AERO1D_EMPTY = "weapons.droptanks.AV8BNA_AERO1D_EMPTY"
|
||||
ENUMS.Storage.weapons.containers.Hercules_Battle_Station_TGP = "weapons.containers.Hercules_Battle_Station_TGP"
|
||||
ENUMS.Storage.weapons.nurs.C_8CM_VT = "weapons.nurs.C_8CM_VT"
|
||||
ENUMS.Storage.weapons.missiles.PL_12 = "weapons.missiles.PL-12"
|
||||
ENUMS.Storage.weapons.missiles.R_3R = "weapons.missiles.R-3R"
|
||||
ENUMS.Storage.weapons.bombs.GBU_54_V_1B = "weapons.bombs.GBU_54_V_1B"
|
||||
ENUMS.Storage.weapons.droptanks.MB339_TT320_R = "weapons.droptanks.MB339_TT320_R"
|
||||
ENUMS.Storage.weapons.bombs.RN_24 = "weapons.bombs.RN-24"
|
||||
ENUMS.Storage.weapons.containers.Twoc6m = "weapons.containers.2c6m"
|
||||
ENUMS.Storage.weapons.bombs.ARV_BRDM_2_Air_12320lb = "weapons.bombs.ARV BRDM-2 Air [12320lb]"
|
||||
ENUMS.Storage.weapons.bombs.ARV_BRDM_2_Skid_12210lb = "weapons.bombs.ARV BRDM-2 Skid [12210lb]"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE251_F1B = "weapons.nurs.SNEB_TYPE251_F1B"
|
||||
ENUMS.Storage.weapons.missiles.X_41 = "weapons.missiles.X_41"
|
||||
ENUMS.Storage.weapons.containers.MIG21_SMOKE_WHITE = "weapons.containers.{MIG21_SMOKE_WHITE}"
|
||||
ENUMS.Storage.weapons.bombs.MK_82AIR = "weapons.bombs.MK_82AIR"
|
||||
ENUMS.Storage.weapons.missiles.R_530F_EM = "weapons.missiles.R_530F_EM"
|
||||
ENUMS.Storage.weapons.bombs.SAMP400LD = "weapons.bombs.SAMP400LD"
|
||||
ENUMS.Storage.weapons.bombs.FAB_50 = "weapons.bombs.FAB_50"
|
||||
ENUMS.Storage.weapons.bombs.AB_250_2_SD_10A = "weapons.bombs.AB_250_2_SD_10A"
|
||||
ENUMS.Storage.weapons.missiles.ADM_141A = "weapons.missiles.ADM_141A"
|
||||
ENUMS.Storage.weapons.containers.KBpod = "weapons.containers.KBpod"
|
||||
ENUMS.Storage.weapons.bombs.British_GP_500LB_Bomb_Mk4 = "weapons.bombs.British_GP_500LB_Bomb_Mk4"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65E = "weapons.missiles.AGM_65E"
|
||||
ENUMS.Storage.weapons.containers.sa342_dipole_antenna = "weapons.containers.sa342_dipole_antenna"
|
||||
ENUMS.Storage.weapons.bombs.OFAB_100_Jupiter = "weapons.bombs.OFAB-100 Jupiter"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE257_F1B = "weapons.nurs.SNEB_TYPE257_F1B"
|
||||
ENUMS.Storage.weapons.missiles.Rb_04E_for_A_I = "weapons.missiles.Rb 04E (for A.I.)"
|
||||
ENUMS.Storage.weapons.bombs.AN_M66A2 = "weapons.bombs.AN-M66A2"
|
||||
ENUMS.Storage.weapons.missiles.P_27T = "weapons.missiles.P_27T"
|
||||
ENUMS.Storage.weapons.droptanks.LNS_VIG_XTANK = "weapons.droptanks.LNS_VIG_XTANK"
|
||||
ENUMS.Storage.weapons.missiles.R_55 = "weapons.missiles.R-55"
|
||||
ENUMS.Storage.weapons.torpedoes.YU_6 = "weapons.torpedoes.YU-6"
|
||||
ENUMS.Storage.weapons.bombs.British_MC_250LB_Bomb_Mk2 = "weapons.bombs.British_MC_250LB_Bomb_Mk2"
|
||||
ENUMS.Storage.weapons.droptanks.PTB_120_F86F35 = "weapons.droptanks.PTB_120_F86F35"
|
||||
ENUMS.Storage.weapons.missiles.PL_8B = "weapons.missiles.PL-8B"
|
||||
ENUMS.Storage.weapons.droptanks.F_15E_Drop_Tank_Empty = "weapons.droptanks.F-15E_Drop_Tank_Empty"
|
||||
ENUMS.Storage.weapons.nurs.British_HE_60LBFNo1_3INCHNo1 = "weapons.nurs.British_HE_60LBFNo1_3INCHNo1"
|
||||
ENUMS.Storage.weapons.missiles.P_77 = "weapons.missiles.P_77"
|
||||
ENUMS.Storage.weapons.torpedoes.LTF_5B = "weapons.torpedoes.LTF_5B"
|
||||
ENUMS.Storage.weapons.missiles.R_3S = "weapons.missiles.R-3S"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE253_H1 = "weapons.nurs.SNEB_TYPE253_H1"
|
||||
ENUMS.Storage.weapons.missiles.PL_8A = "weapons.missiles.PL-8A"
|
||||
ENUMS.Storage.weapons.bombs.APC_BTR_82A_Skid_24888lb = "weapons.bombs.APC BTR-82A Skid [24888lb]"
|
||||
ENUMS.Storage.weapons.containers.Sborka = "weapons.containers.Sborka"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65L = "weapons.missiles.AGM_65L"
|
||||
ENUMS.Storage.weapons.missiles.X_28 = "weapons.missiles.X_28"
|
||||
ENUMS.Storage.weapons.missiles.TGM_65G = "weapons.missiles.TGM_65G"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE257_H1 = "weapons.nurs.SNEB_TYPE257_H1"
|
||||
ENUMS.Storage.weapons.missiles.RB75B = "weapons.missiles.RB75B"
|
||||
ENUMS.Storage.weapons.missiles.X_25ML = "weapons.missiles.X_25ML"
|
||||
ENUMS.Storage.weapons.droptanks.FPU_8A = "weapons.droptanks.FPU_8A"
|
||||
ENUMS.Storage.weapons.bombs.BLG66 = "weapons.bombs.BLG66"
|
||||
ENUMS.Storage.weapons.nurs.C_8CM_RD = "weapons.nurs.C_8CM_RD"
|
||||
ENUMS.Storage.weapons.containers.EclairM_06 = "weapons.containers.{EclairM_06}"
|
||||
ENUMS.Storage.weapons.bombs.RBK_500AO = "weapons.bombs.RBK_500AO"
|
||||
ENUMS.Storage.weapons.missiles.AIM_9P = "weapons.missiles.AIM-9P"
|
||||
ENUMS.Storage.weapons.bombs.British_GP_500LB_Bomb_Mk4_Short = "weapons.bombs.British_GP_500LB_Bomb_Mk4_Short"
|
||||
ENUMS.Storage.weapons.containers.MB339_Vinten = "weapons.containers.MB339_Vinten"
|
||||
ENUMS.Storage.weapons.missiles.Rb_15F = "weapons.missiles.Rb 15F"
|
||||
ENUMS.Storage.weapons.nurs.ARAKM70BHE = "weapons.nurs.ARAKM70BHE"
|
||||
ENUMS.Storage.weapons.bombs.AAA_Vulcan_M163_Air_21666lb = "weapons.bombs.AAA Vulcan M163 Air [21666lb]"
|
||||
ENUMS.Storage.weapons.missiles.X_29L = "weapons.missiles.X_29L"
|
||||
ENUMS.Storage.weapons.containers.F14_LANTIRN_TP = "weapons.containers.{F14-LANTIRN-TP}"
|
||||
ENUMS.Storage.weapons.bombs.FAB_250_M62 = "weapons.bombs.FAB-250-M62"
|
||||
ENUMS.Storage.weapons.missiles.AIM_120C = "weapons.missiles.AIM_120C"
|
||||
ENUMS.Storage.weapons.bombs.EWR_SBORKA_Air_21624lb = "weapons.bombs.EWR SBORKA Air [21624lb]"
|
||||
ENUMS.Storage.weapons.bombs.SAMP250LD = "weapons.bombs.SAMP250LD"
|
||||
ENUMS.Storage.weapons.droptanks.Spitfire_slipper_tank = "weapons.droptanks.Spitfire_slipper_tank"
|
||||
ENUMS.Storage.weapons.missiles.LS_6_500 = "weapons.missiles.LS-6-500"
|
||||
ENUMS.Storage.weapons.bombs.GBU_31_V_4B = "weapons.bombs.GBU_31_V_4B"
|
||||
ENUMS.Storage.weapons.droptanks.PTB400_MIG15 = "weapons.droptanks.PTB400_MIG15"
|
||||
ENUMS.Storage.weapons.containers.m_113 = "weapons.containers.m-113"
|
||||
ENUMS.Storage.weapons.bombs.SPG_M1128_Stryker_MGS_33036lb = "weapons.bombs.SPG M1128 Stryker MGS [33036lb]"
|
||||
ENUMS.Storage.weapons.missiles.AIM_9L = "weapons.missiles.AIM-9L"
|
||||
ENUMS.Storage.weapons.missiles.AIM_9X = "weapons.missiles.AIM_9X"
|
||||
ENUMS.Storage.weapons.nurs.C_8 = "weapons.nurs.C_8"
|
||||
ENUMS.Storage.weapons.bombs.SAM_CHAPARRAL_Skid_21516lb = "weapons.bombs.SAM CHAPARRAL Skid [21516lb]"
|
||||
ENUMS.Storage.weapons.missiles.P_27TE = "weapons.missiles.P_27TE"
|
||||
ENUMS.Storage.weapons.bombs.ODAB_500PM = "weapons.bombs.ODAB-500PM"
|
||||
ENUMS.Storage.weapons.bombs.MK77mod1_WPN = "weapons.bombs.MK77mod1-WPN"
|
||||
ENUMS.Storage.weapons.droptanks.PTB400_MIG19 = "weapons.droptanks.PTB400_MIG19"
|
||||
ENUMS.Storage.weapons.torpedoes.Mark_46 = "weapons.torpedoes.Mark_46"
|
||||
ENUMS.Storage.weapons.containers.rightSeat = "weapons.containers.rightSeat"
|
||||
ENUMS.Storage.weapons.containers.US_M10_SMOKE_TANK_ORANGE = "weapons.containers.{US_M10_SMOKE_TANK_ORANGE}"
|
||||
ENUMS.Storage.weapons.bombs.SAB_100MN = "weapons.bombs.SAB_100MN"
|
||||
ENUMS.Storage.weapons.nurs.FFAR_Mk5_HEAT = "weapons.nurs.FFAR Mk5 HEAT"
|
||||
ENUMS.Storage.weapons.bombs.IFV_TPZ_FUCH_33440lb = "weapons.bombs.IFV TPZ FUCH [33440lb]"
|
||||
ENUMS.Storage.weapons.bombs.IFV_M2A2_Bradley_34720lb = "weapons.bombs.IFV M2A2 Bradley [34720lb]"
|
||||
ENUMS.Storage.weapons.bombs.MK77mod0_WPN = "weapons.bombs.MK77mod0-WPN"
|
||||
ENUMS.Storage.weapons.containers.ASO_2 = "weapons.containers.ASO-2"
|
||||
ENUMS.Storage.weapons.bombs.Mk_84AIR_GP = "weapons.bombs.Mk_84AIR_GP"
|
||||
ENUMS.Storage.weapons.nurs.S_24A = "weapons.nurs.S-24A"
|
||||
ENUMS.Storage.weapons.bombs.RBK_250_275_AO_1SCH = "weapons.bombs.RBK_250_275_AO_1SCH"
|
||||
ENUMS.Storage.weapons.bombs.Transport_Tigr_Skid_15730lb = "weapons.bombs.Transport Tigr Skid [15730lb]"
|
||||
ENUMS.Storage.weapons.missiles.AIM_7F = "weapons.missiles.AIM-7F"
|
||||
ENUMS.Storage.weapons.bombs.CBU_99 = "weapons.bombs.CBU_99"
|
||||
ENUMS.Storage.weapons.bombs.LUU_2B = "weapons.bombs.LUU_2B"
|
||||
ENUMS.Storage.weapons.bombs.FAB_500TA = "weapons.bombs.FAB-500TA"
|
||||
ENUMS.Storage.weapons.missiles.AGR_20_M282 = "weapons.missiles.AGR_20_M282"
|
||||
ENUMS.Storage.weapons.droptanks.MB339_FT330 = "weapons.droptanks.MB339_FT330"
|
||||
ENUMS.Storage.weapons.bombs.SAMP125LD = "weapons.bombs.SAMP125LD"
|
||||
ENUMS.Storage.weapons.missiles.X_25MP = "weapons.missiles.X_25MP"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE252_H1 = "weapons.nurs.SNEB_TYPE252_H1"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65F = "weapons.missiles.AGM_65F"
|
||||
ENUMS.Storage.weapons.missiles.AIM_9P5 = "weapons.missiles.AIM-9P5"
|
||||
ENUMS.Storage.weapons.bombs.Transport_Tigr_Air_15900lb = "weapons.bombs.Transport Tigr Air [15900lb]"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE254_H1_RED = "weapons.nurs.SNEB_TYPE254_H1_RED"
|
||||
ENUMS.Storage.weapons.nurs.FFAR_Mk1_HE = "weapons.nurs.FFAR Mk1 HE"
|
||||
ENUMS.Storage.weapons.nurs.SPRD_99 = "weapons.nurs.SPRD-99"
|
||||
ENUMS.Storage.weapons.bombs.BIN_200 = "weapons.bombs.BIN_200"
|
||||
ENUMS.Storage.weapons.bombs.BLU_4B_GROUP = "weapons.bombs.BLU_4B_GROUP"
|
||||
ENUMS.Storage.weapons.bombs.GBU_24 = "weapons.bombs.GBU_24"
|
||||
ENUMS.Storage.weapons.missiles.Rb_04E = "weapons.missiles.Rb 04E"
|
||||
ENUMS.Storage.weapons.missiles.Rb_74 = "weapons.missiles.Rb 74"
|
||||
ENUMS.Storage.weapons.containers.leftSeat = "weapons.containers.leftSeat"
|
||||
ENUMS.Storage.weapons.bombs.LS_6_100 = "weapons.bombs.LS-6-100"
|
||||
ENUMS.Storage.weapons.bombs.Transport_URAL_375_14815lb = "weapons.bombs.Transport URAL-375 [14815lb]"
|
||||
ENUMS.Storage.weapons.containers.US_M10_SMOKE_TANK_GREEN = "weapons.containers.{US_M10_SMOKE_TANK_GREEN}"
|
||||
ENUMS.Storage.weapons.missiles.X_22 = "weapons.missiles.X_22"
|
||||
ENUMS.Storage.weapons.containers.FAS = "weapons.containers.FAS"
|
||||
ENUMS.Storage.weapons.nurs.S_25_O = "weapons.nurs.S-25-O"
|
||||
ENUMS.Storage.weapons.droptanks.para = "weapons.droptanks.para"
|
||||
ENUMS.Storage.weapons.droptanks.F_15E_Drop_Tank = "weapons.droptanks.F-15E_Drop_Tank"
|
||||
ENUMS.Storage.weapons.droptanks.M2KC_08_RPL541_EMPTY = "weapons.droptanks.M2KC_08_RPL541_EMPTY"
|
||||
ENUMS.Storage.weapons.missiles.X_31P = "weapons.missiles.X_31P"
|
||||
ENUMS.Storage.weapons.bombs.RBK_500U = "weapons.bombs.RBK_500U"
|
||||
ENUMS.Storage.weapons.missiles.AIM_54A_Mk47 = "weapons.missiles.AIM_54A_Mk47"
|
||||
ENUMS.Storage.weapons.droptanks.oiltank = "weapons.droptanks.oiltank"
|
||||
ENUMS.Storage.weapons.missiles.AGM_154B = "weapons.missiles.AGM_154B"
|
||||
ENUMS.Storage.weapons.containers.MB339_SMOKE_POD = "weapons.containers.MB339_SMOKE-POD"
|
||||
ENUMS.Storage.weapons.containers.ECM_POD_L_175V = "weapons.containers.{ECM_POD_L_175V}"
|
||||
ENUMS.Storage.weapons.droptanks.PTB_580G_F1 = "weapons.droptanks.PTB_580G_F1"
|
||||
ENUMS.Storage.weapons.containers.EclairM_15 = "weapons.containers.{EclairM_15}"
|
||||
ENUMS.Storage.weapons.containers.F_15E_AAQ_13_LANTIRN = "weapons.containers.F-15E_AAQ-13_LANTIRN"
|
||||
ENUMS.Storage.weapons.droptanks.Eight00L_Tank_Empty = "weapons.droptanks.800L Tank Empty"
|
||||
ENUMS.Storage.weapons.containers.One6c_hts_pod = "weapons.containers.16c_hts_pod"
|
||||
ENUMS.Storage.weapons.bombs.AN_M81 = "weapons.bombs.AN-M81"
|
||||
ENUMS.Storage.weapons.droptanks.Mosquito_Drop_Tank_100gal = "weapons.droptanks.Mosquito_Drop_Tank_100gal"
|
||||
ENUMS.Storage.weapons.droptanks.Mosquito_Drop_Tank_50gal = "weapons.droptanks.Mosquito_Drop_Tank_50gal"
|
||||
ENUMS.Storage.weapons.droptanks.DFT_150_GAL_A4E = "weapons.droptanks.DFT_150_GAL_A4E"
|
||||
ENUMS.Storage.weapons.missiles.AIM_9 = "weapons.missiles.AIM_9"
|
||||
ENUMS.Storage.weapons.bombs.IFV_BTR_D_Air_18040lb = "weapons.bombs.IFV BTR-D Air [18040lb]"
|
||||
ENUMS.Storage.weapons.containers.EclairM_42 = "weapons.containers.{EclairM_42}"
|
||||
ENUMS.Storage.weapons.bombs.KAB_1500T = "weapons.bombs.KAB_1500T"
|
||||
ENUMS.Storage.weapons.droptanks.PTB_490_MIG21 = "weapons.droptanks.PTB-490-MIG21"
|
||||
ENUMS.Storage.weapons.droptanks.PTB_200_F86F35 = "weapons.droptanks.PTB_200_F86F35"
|
||||
ENUMS.Storage.weapons.droptanks.PTB760_MIG19 = "weapons.droptanks.PTB760_MIG19"
|
||||
ENUMS.Storage.weapons.bombs.GBU_43_B_MOAB = "weapons.bombs.GBU-43/B(MOAB)"
|
||||
ENUMS.Storage.weapons.torpedoes.G7A_T1 = "weapons.torpedoes.G7A_T1"
|
||||
ENUMS.Storage.weapons.bombs.IFV_BMD_1_Air_18040lb = "weapons.bombs.IFV BMD-1 Air [18040lb]"
|
||||
ENUMS.Storage.weapons.bombs.SAM_LINEBACKER_34720lb = "weapons.bombs.SAM LINEBACKER [34720lb]"
|
||||
ENUMS.Storage.weapons.containers.ais_pod_t50_r = "weapons.containers.ais-pod-t50_r"
|
||||
ENUMS.Storage.weapons.containers.CE2_SMOKE_WHITE = "weapons.containers.{CE2_SMOKE_WHITE}"
|
||||
ENUMS.Storage.weapons.droptanks.fuel_tank_230 = "weapons.droptanks.fuel_tank_230"
|
||||
ENUMS.Storage.weapons.droptanks.M2KC_RPL_522 = "weapons.droptanks.M2KC_RPL_522"
|
||||
ENUMS.Storage.weapons.missiles.AGM_130 = "weapons.missiles.AGM_130"
|
||||
ENUMS.Storage.weapons.droptanks.Eight00L_Tank = "weapons.droptanks.800L Tank"
|
||||
ENUMS.Storage.weapons.bombs.IFV_BTR_D_Skid_17930lb = "weapons.bombs.IFV BTR-D Skid [17930lb]"
|
||||
ENUMS.Storage.weapons.containers.bmp_1 = "weapons.containers.bmp-1"
|
||||
ENUMS.Storage.weapons.bombs.GBU_31 = "weapons.bombs.GBU_31"
|
||||
ENUMS.Storage.weapons.containers.aaq_28LEFT_litening = "weapons.containers.aaq-28LEFT litening"
|
||||
ENUMS.Storage.weapons.missiles.Kh_66_Grom = "weapons.missiles.Kh-66_Grom"
|
||||
ENUMS.Storage.weapons.containers.MIG21_SMOKE_RED = "weapons.containers.{MIG21_SMOKE_RED}"
|
||||
ENUMS.Storage.weapons.containers.U22 = "weapons.containers.U22"
|
||||
ENUMS.Storage.weapons.bombs.IFV_BMD_1_Skid_17930lb = "weapons.bombs.IFV BMD-1 Skid [17930lb]"
|
||||
ENUMS.Storage.weapons.droptanks.Bidon = "weapons.droptanks.Bidon"
|
||||
ENUMS.Storage.weapons.bombs.GBU_31_V_2B = "weapons.bombs.GBU_31_V_2B"
|
||||
ENUMS.Storage.weapons.bombs.Mk_82Y = "weapons.bombs.Mk_82Y"
|
||||
ENUMS.Storage.weapons.containers.pl5eii = "weapons.containers.pl5eii"
|
||||
ENUMS.Storage.weapons.bombs.RBK_500U_OAB_2_5RT = "weapons.bombs.RBK_500U_OAB_2_5RT"
|
||||
ENUMS.Storage.weapons.bombs.British_GP_500LB_Bomb_Mk5 = "weapons.bombs.British_GP_500LB_Bomb_Mk5"
|
||||
ENUMS.Storage.weapons.containers.Eclair = "weapons.containers.{Eclair}"
|
||||
ENUMS.Storage.weapons.nurs.S5MO_HEFRAG_FFAR = "weapons.nurs.S5MO_HEFRAG_FFAR"
|
||||
ENUMS.Storage.weapons.bombs.BETAB_500M = "weapons.bombs.BETAB-500M"
|
||||
ENUMS.Storage.weapons.bombs.Transport_M818_16000lb = "weapons.bombs.Transport M818 [16000lb]"
|
||||
ENUMS.Storage.weapons.bombs.British_MC_250LB_Bomb_Mk1 = "weapons.bombs.British_MC_250LB_Bomb_Mk1"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE251_H1 = "weapons.nurs.SNEB_TYPE251_H1"
|
||||
ENUMS.Storage.weapons.bombs.TYPE_200A = "weapons.bombs.TYPE-200A"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_M151 = "weapons.nurs.HYDRA_70_M151"
|
||||
ENUMS.Storage.weapons.bombs.IFV_BMP_3_32912lb = "weapons.bombs.IFV BMP-3 [32912lb]"
|
||||
ENUMS.Storage.weapons.bombs.APC_MTLB_Air_26400lb = "weapons.bombs.APC MTLB Air [26400lb]"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_M229 = "weapons.nurs.HYDRA_70_M229"
|
||||
ENUMS.Storage.weapons.bombs.BDU_45 = "weapons.bombs.BDU_45"
|
||||
ENUMS.Storage.weapons.bombs.OFAB_100_120TU = "weapons.bombs.OFAB-100-120TU"
|
||||
ENUMS.Storage.weapons.missiles.AIM_9J = "weapons.missiles.AIM-9J"
|
||||
ENUMS.Storage.weapons.nurs.ARF8M3API = "weapons.nurs.ARF8M3API"
|
||||
ENUMS.Storage.weapons.bombs.BetAB_500ShP = "weapons.bombs.BetAB_500ShP"
|
||||
ENUMS.Storage.weapons.nurs.C_8OFP2 = "weapons.nurs.C_8OFP2"
|
||||
ENUMS.Storage.weapons.bombs.GBU_10 = "weapons.bombs.GBU_10"
|
||||
ENUMS.Storage.weapons.bombs.APC_MTLB_Skid_26290lb = "weapons.bombs.APC MTLB Skid [26290lb]"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE254_F1B_RED = "weapons.nurs.SNEB_TYPE254_F1B_RED"
|
||||
ENUMS.Storage.weapons.missiles.X_65 = "weapons.missiles.X_65"
|
||||
ENUMS.Storage.weapons.missiles.R_550_M1 = "weapons.missiles.R_550_M1"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65K = "weapons.missiles.AGM_65K"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE254_F1B_YELLOW = "weapons.nurs.SNEB_TYPE254_F1B_YELLOW"
|
||||
ENUMS.Storage.weapons.missiles.AGM_88 = "weapons.missiles.AGM_88"
|
||||
ENUMS.Storage.weapons.nurs.C_8OM = "weapons.nurs.C_8OM"
|
||||
ENUMS.Storage.weapons.bombs.SAM_ROLAND_LN_34720b = "weapons.bombs.SAM ROLAND LN [34720b]"
|
||||
ENUMS.Storage.weapons.missiles.AIM_120 = "weapons.missiles.AIM_120"
|
||||
ENUMS.Storage.weapons.missiles.HOT3_MBDA = "weapons.missiles.HOT3_MBDA"
|
||||
ENUMS.Storage.weapons.missiles.R_13M = "weapons.missiles.R-13M"
|
||||
ENUMS.Storage.weapons.missiles.AIM_54C_Mk60 = "weapons.missiles.AIM_54C_Mk60"
|
||||
ENUMS.Storage.weapons.bombs.AAA_GEPARD_34720lb = "weapons.bombs.AAA GEPARD [34720lb]"
|
||||
ENUMS.Storage.weapons.missiles.R_13M1 = "weapons.missiles.R-13M1"
|
||||
ENUMS.Storage.weapons.bombs.APC_Cobra_Air_10912lb = "weapons.bombs.APC Cobra Air [10912lb]"
|
||||
ENUMS.Storage.weapons.bombs.RBK_250 = "weapons.bombs.RBK_250"
|
||||
ENUMS.Storage.weapons.bombs.SC_500_J = "weapons.bombs.SC_500_J"
|
||||
ENUMS.Storage.weapons.missiles.AGM_114K = "weapons.missiles.AGM_114K"
|
||||
ENUMS.Storage.weapons.missiles.ALARM = "weapons.missiles.ALARM"
|
||||
ENUMS.Storage.weapons.bombs.Mk_83 = "weapons.bombs.Mk_83"
|
||||
ENUMS.Storage.weapons.missiles.AGM_65B = "weapons.missiles.AGM_65B"
|
||||
ENUMS.Storage.weapons.bombs.MK_82SNAKEYE = "weapons.bombs.MK_82SNAKEYE"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_MK1 = "weapons.nurs.HYDRA_70_MK1"
|
||||
ENUMS.Storage.weapons.bombs.BLG66_BELOUGA = "weapons.bombs.BLG66_BELOUGA"
|
||||
ENUMS.Storage.weapons.containers.EclairM_51 = "weapons.containers.{EclairM_51}"
|
||||
ENUMS.Storage.weapons.missiles.AIM_54A_Mk60 = "weapons.missiles.AIM_54A_Mk60"
|
||||
ENUMS.Storage.weapons.droptanks.DFT_300_GAL_A4E = "weapons.droptanks.DFT_300_GAL_A4E"
|
||||
ENUMS.Storage.weapons.bombs.ATGM_M1134_Stryker_30337lb = "weapons.bombs.ATGM M1134 Stryker [30337lb]"
|
||||
ENUMS.Storage.weapons.bombs.BAT_120 = "weapons.bombs.BAT-120"
|
||||
ENUMS.Storage.weapons.missiles.DWS39_MJ1_MJ2 = "weapons.missiles.DWS39_MJ1_MJ2"
|
||||
ENUMS.Storage.weapons.containers.SPRD = "weapons.containers.SPRD"
|
||||
ENUMS.Storage.weapons.bombs.BR_500 = "weapons.bombs.BR_500"
|
||||
ENUMS.Storage.weapons.bombs.British_GP_500LB_Bomb_Mk1 = "weapons.bombs.British_GP_500LB_Bomb_Mk1"
|
||||
ENUMS.Storage.weapons.bombs.BDU_50HD = "weapons.bombs.BDU_50HD"
|
||||
ENUMS.Storage.weapons.missiles.RS2US = "weapons.missiles.RS2US"
|
||||
ENUMS.Storage.weapons.bombs.IFV_BMP_2_25168lb = "weapons.bombs.IFV BMP-2 [25168lb]"
|
||||
ENUMS.Storage.weapons.bombs.SAMP400HD = "weapons.bombs.SAMP400HD"
|
||||
ENUMS.Storage.weapons.containers.Hercules_Battle_Station = "weapons.containers.Hercules_Battle_Station"
|
||||
ENUMS.Storage.weapons.bombs.AN_M64 = "weapons.bombs.AN_M64"
|
||||
ENUMS.Storage.weapons.containers.rearCargoSeats = "weapons.containers.rearCargoSeats"
|
||||
ENUMS.Storage.weapons.bombs.Mk_82 = "weapons.bombs.Mk_82"
|
||||
ENUMS.Storage.weapons.missiles.AKD_10 = "weapons.missiles.AKD-10"
|
||||
ENUMS.Storage.weapons.bombs.BDU_50LGB = "weapons.bombs.BDU_50LGB"
|
||||
ENUMS.Storage.weapons.missiles.SD_10 = "weapons.missiles.SD-10"
|
||||
ENUMS.Storage.weapons.containers.IRDeflector = "weapons.containers.IRDeflector"
|
||||
ENUMS.Storage.weapons.bombs.FAB_500 = "weapons.bombs.FAB_500"
|
||||
ENUMS.Storage.weapons.bombs.KAB_500 = "weapons.bombs.KAB_500"
|
||||
ENUMS.Storage.weapons.nurs.S_5M = "weapons.nurs.S-5M"
|
||||
ENUMS.Storage.weapons.missiles.MICA_R = "weapons.missiles.MICA_R"
|
||||
ENUMS.Storage.weapons.missiles.X_59M = "weapons.missiles.X_59M"
|
||||
ENUMS.Storage.weapons.nurs.UG_90MM = "weapons.nurs.UG_90MM"
|
||||
ENUMS.Storage.weapons.bombs.LYSBOMB = "weapons.bombs.LYSBOMB"
|
||||
ENUMS.Storage.weapons.nurs.R4M = "weapons.nurs.R4M"
|
||||
ENUMS.Storage.weapons.containers.dlpod_akg = "weapons.containers.dlpod_akg"
|
||||
ENUMS.Storage.weapons.missiles.LD_10 = "weapons.missiles.LD-10"
|
||||
ENUMS.Storage.weapons.bombs.SC_50 = "weapons.bombs.SC_50"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_MK5 = "weapons.nurs.HYDRA_70_MK5"
|
||||
ENUMS.Storage.weapons.bombs.FAB_100M = "weapons.bombs.FAB_100M"
|
||||
ENUMS.Storage.weapons.missiles.Rb_24 = "weapons.missiles.Rb 24"
|
||||
ENUMS.Storage.weapons.bombs.BDU_45B = "weapons.bombs.BDU_45B"
|
||||
ENUMS.Storage.weapons.missiles.GB_6_HE = "weapons.missiles.GB-6-HE"
|
||||
ENUMS.Storage.weapons.missiles.KD_63B = "weapons.missiles.KD-63B"
|
||||
ENUMS.Storage.weapons.missiles.P_27PE = "weapons.missiles.P_27PE"
|
||||
ENUMS.Storage.weapons.droptanks.PTB300_MIG15 = "weapons.droptanks.PTB300_MIG15"
|
||||
ENUMS.Storage.weapons.bombs.Two50_3 = "weapons.bombs.250-3"
|
||||
ENUMS.Storage.weapons.bombs.SC_500_L2 = "weapons.bombs.SC_500_L2"
|
||||
ENUMS.Storage.weapons.containers.HMMWV_M1045 = "weapons.containers.HMMWV_M1045"
|
||||
ENUMS.Storage.weapons.bombs.FAB_500M54TU = "weapons.bombs.FAB-500M54TU"
|
||||
ENUMS.Storage.weapons.containers.US_M10_SMOKE_TANK_YELLOW = "weapons.containers.{US_M10_SMOKE_TANK_YELLOW}"
|
||||
ENUMS.Storage.weapons.containers.EclairM_60 = "weapons.containers.{EclairM_60}"
|
||||
ENUMS.Storage.weapons.bombs.SAB_250_200 = "weapons.bombs.SAB_250_200"
|
||||
ENUMS.Storage.weapons.bombs.FAB_100 = "weapons.bombs.FAB_100"
|
||||
ENUMS.Storage.weapons.bombs.KAB_500S = "weapons.bombs.KAB_500S"
|
||||
ENUMS.Storage.weapons.missiles.AGM_45A = "weapons.missiles.AGM_45A"
|
||||
ENUMS.Storage.weapons.missiles.Kh25MP_PRGS1VP = "weapons.missiles.Kh25MP_PRGS1VP"
|
||||
ENUMS.Storage.weapons.nurs.S5M1_HEFRAG_FFAR = "weapons.nurs.S5M1_HEFRAG_FFAR"
|
||||
ENUMS.Storage.weapons.containers.kg600 = "weapons.containers.kg600"
|
||||
ENUMS.Storage.weapons.bombs.AN_M65 = "weapons.bombs.AN_M65"
|
||||
ENUMS.Storage.weapons.bombs.AN_M57 = "weapons.bombs.AN_M57"
|
||||
ENUMS.Storage.weapons.bombs.BLU_3B_GROUP = "weapons.bombs.BLU_3B_GROUP"
|
||||
ENUMS.Storage.weapons.bombs.BAP_100 = "weapons.bombs.BAP-100"
|
||||
ENUMS.Storage.weapons.containers.HEMTT = "weapons.containers.HEMTT"
|
||||
ENUMS.Storage.weapons.bombs.British_MC_500LB_Bomb_Mk1_Short = "weapons.bombs.British_MC_500LB_Bomb_Mk1_Short"
|
||||
ENUMS.Storage.weapons.nurs.ARAKM70BAP = "weapons.nurs.ARAKM70BAP"
|
||||
ENUMS.Storage.weapons.missiles.AGM_119 = "weapons.missiles.AGM_119"
|
||||
ENUMS.Storage.weapons.missiles.MMagicII = "weapons.missiles.MMagicII"
|
||||
ENUMS.Storage.weapons.bombs.AB_500_1_SD_10A = "weapons.bombs.AB_500_1_SD_10A"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_M282 = "weapons.nurs.HYDRA_70_M282"
|
||||
ENUMS.Storage.weapons.droptanks.DFT_400_GAL_A4E = "weapons.droptanks.DFT_400_GAL_A4E"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_M257 = "weapons.nurs.HYDRA_70_M257"
|
||||
ENUMS.Storage.weapons.droptanks.AV8BNA_AERO1D = "weapons.droptanks.AV8BNA_AERO1D"
|
||||
ENUMS.Storage.weapons.containers.US_M10_SMOKE_TANK_BLUE = "weapons.containers.{US_M10_SMOKE_TANK_BLUE}"
|
||||
ENUMS.Storage.weapons.nurs.ARF8M3HEI = "weapons.nurs.ARF8M3HEI"
|
||||
ENUMS.Storage.weapons.bombs.RN_28 = "weapons.bombs.RN-28"
|
||||
ENUMS.Storage.weapons.bombs.Squad_30_x_Soldier_7950lb = "weapons.bombs.Squad 30 x Soldier [7950lb]"
|
||||
ENUMS.Storage.weapons.containers.uaz_469 = "weapons.containers.uaz-469"
|
||||
ENUMS.Storage.weapons.containers.Otokar_Cobra = "weapons.containers.Otokar_Cobra"
|
||||
ENUMS.Storage.weapons.bombs.APC_BTR_82A_Air_24998lb = "weapons.bombs.APC BTR-82A Air [24998lb]"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_M274 = "weapons.nurs.HYDRA_70_M274"
|
||||
ENUMS.Storage.weapons.missiles.P_24R = "weapons.missiles.P_24R"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_MK61 = "weapons.nurs.HYDRA_70_MK61"
|
||||
ENUMS.Storage.weapons.missiles.Igla_1E = "weapons.missiles.Igla_1E"
|
||||
ENUMS.Storage.weapons.missiles.C_802AK = "weapons.missiles.C-802AK"
|
||||
ENUMS.Storage.weapons.nurs.C_24 = "weapons.nurs.C_24"
|
||||
ENUMS.Storage.weapons.droptanks.M2KC_08_RPL541 = "weapons.droptanks.M2KC_08_RPL541"
|
||||
ENUMS.Storage.weapons.nurs.C_13 = "weapons.nurs.C_13"
|
||||
ENUMS.Storage.weapons.droptanks.droptank_110_gal = "weapons.droptanks.droptank_110_gal"
|
||||
ENUMS.Storage.weapons.bombs.Mk_84 = "weapons.bombs.Mk_84"
|
||||
ENUMS.Storage.weapons.missiles.Sea_Eagle = "weapons.missiles.Sea_Eagle"
|
||||
ENUMS.Storage.weapons.droptanks.PTB_1200_F1 = "weapons.droptanks.PTB_1200_F1"
|
||||
ENUMS.Storage.weapons.nurs.SNEB_TYPE256_H1 = "weapons.nurs.SNEB_TYPE256_H1"
|
||||
ENUMS.Storage.weapons.containers.MATRA_PHIMAT = "weapons.containers.MATRA-PHIMAT"
|
||||
ENUMS.Storage.weapons.containers.smoke_pod = "weapons.containers.smoke_pod"
|
||||
ENUMS.Storage.weapons.containers.F_15E_AAQ_14_LANTIRN = "weapons.containers.F-15E_AAQ-14_LANTIRN"
|
||||
ENUMS.Storage.weapons.containers.EclairM_24 = "weapons.containers.{EclairM_24}"
|
||||
ENUMS.Storage.weapons.bombs.GBU_16 = "weapons.bombs.GBU_16"
|
||||
ENUMS.Storage.weapons.nurs.HYDRA_70_M156 = "weapons.nurs.HYDRA_70_M156"
|
||||
ENUMS.Storage.weapons.missiles.R_60 = "weapons.missiles.R-60"
|
||||
ENUMS.Storage.weapons.containers.zsu_23_4 = "weapons.containers.zsu-23-4"
|
||||
ENUMS.Storage.weapons.missiles.RB75 = "weapons.missiles.RB75"
|
||||
ENUMS.Storage.weapons.missiles.Mistral = "weapons.missiles.Mistral"
|
||||
ENUMS.Storage.weapons.droptanks.MB339_TT500_L = "weapons.droptanks.MB339_TT500_L"
|
||||
ENUMS.Storage.weapons.bombs.SAM_SA_13_STRELA_21624lb = "weapons.bombs.SAM SA-13 STRELA [21624lb]"
|
||||
ENUMS.Storage.weapons.bombs.SAM_Avenger_M1097_Air_7200lb = "weapons.bombs.SAM Avenger M1097 Air [7200lb]"
|
||||
ENUMS.Storage.weapons.droptanks.Eleven00L_Tank_Empty = "weapons.droptanks.1100L Tank Empty"
|
||||
ENUMS.Storage.weapons.bombs.AN_M88 = "weapons.bombs.AN-M88"
|
||||
ENUMS.Storage.weapons.missiles.S_25L = "weapons.missiles.S_25L"
|
||||
ENUMS.Storage.weapons.nurs.British_AP_25LBNo1_3INCHNo1 = "weapons.nurs.British_AP_25LBNo1_3INCHNo1"
|
||||
ENUMS.Storage.weapons.bombs.BDU_50LD = "weapons.bombs.BDU_50LD"
|
||||
ENUMS.Storage.weapons.bombs.AGM_62 = "weapons.bombs.AGM_62"
|
||||
ENUMS.Storage.weapons.containers.US_M10_SMOKE_TANK_WHITE = "weapons.containers.{US_M10_SMOKE_TANK_WHITE}"
|
||||
ENUMS.Storage.weapons.missiles.MICA_T = "weapons.missiles.MICA_T"
|
||||
ENUMS.Storage.weapons.containers.HVAR_rocket = "weapons.containers.HVAR_rocket"
|
||||
|
||||
@@ -295,9 +295,8 @@ UTILS.DeepCopy = function(object)
|
||||
end
|
||||
|
||||
|
||||
--- Serialize a given table.
|
||||
--- Porting in Slmod's serialize_slmod2.
|
||||
-- @param #table tbl Input table.
|
||||
-- @return #string Table as a string.
|
||||
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
|
||||
|
||||
local lookup_table = {}
|
||||
@@ -374,54 +373,7 @@ local lookup_table = {}
|
||||
return objectreturn
|
||||
end
|
||||
|
||||
--- Serialize a table to a single line string.
|
||||
-- @param #table tbl table to serialize.
|
||||
-- @return #string string containing serialized table.
|
||||
function UTILS._OneLineSerialize(tbl)
|
||||
|
||||
if type(tbl) == 'table' then --function only works for tables!
|
||||
|
||||
local tbl_str = {}
|
||||
|
||||
tbl_str[#tbl_str + 1] = '{ '
|
||||
|
||||
for ind,val in pairs(tbl) do -- serialize its fields
|
||||
if type(ind) == "number" then
|
||||
tbl_str[#tbl_str + 1] = '['
|
||||
tbl_str[#tbl_str + 1] = tostring(ind)
|
||||
tbl_str[#tbl_str + 1] = '] = '
|
||||
else --must be a string
|
||||
tbl_str[#tbl_str + 1] = '['
|
||||
tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(ind)
|
||||
tbl_str[#tbl_str + 1] = '] = '
|
||||
end
|
||||
|
||||
if ((type(val) == 'number') or (type(val) == 'boolean')) then
|
||||
tbl_str[#tbl_str + 1] = tostring(val)
|
||||
tbl_str[#tbl_str + 1] = ', '
|
||||
elseif type(val) == 'string' then
|
||||
tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(val)
|
||||
tbl_str[#tbl_str + 1] = ', '
|
||||
elseif type(val) == 'nil' then -- won't ever happen, right?
|
||||
tbl_str[#tbl_str + 1] = 'nil, '
|
||||
elseif type(val) == 'table' then
|
||||
tbl_str[#tbl_str + 1] = UTILS._OneLineSerialize(val)
|
||||
tbl_str[#tbl_str + 1] = ', ' --I think this is right, I just added it
|
||||
else
|
||||
--log:warn('Unable to serialize value type $1 at index $2', mist.utils.basicSerialize(type(val)), tostring(ind))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
tbl_str[#tbl_str + 1] = '}'
|
||||
return table.concat(tbl_str)
|
||||
else
|
||||
return UTILS.BasicSerialize(tbl)
|
||||
end
|
||||
end
|
||||
|
||||
--- Basic serialize (porting in Slmod's "safestring" basic serialize).
|
||||
-- @param #string s Table to serialize.
|
||||
--porting in Slmod's "safestring" basic serialize
|
||||
UTILS.BasicSerialize = function(s)
|
||||
if s == nil then
|
||||
return "\"\""
|
||||
@@ -452,114 +404,6 @@ function UTILS.PrintTableToLog(table, indent)
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns table in a easy readable string representation.
|
||||
-- @param tbl table to show
|
||||
-- @param loc
|
||||
-- @param indent
|
||||
-- @param tableshow_tbls
|
||||
-- @return Human readable string representation of given table.
|
||||
function UTILS.TableShow(tbl, loc, indent, tableshow_tbls)
|
||||
tableshow_tbls = tableshow_tbls or {} --create table of tables
|
||||
loc = loc or ""
|
||||
indent = indent or ""
|
||||
if type(tbl) == 'table' then --function only works for tables!
|
||||
tableshow_tbls[tbl] = loc
|
||||
|
||||
local tbl_str = {}
|
||||
|
||||
tbl_str[#tbl_str + 1] = indent .. '{\n'
|
||||
|
||||
for ind,val in pairs(tbl) do -- serialize its fields
|
||||
if type(ind) == "number" then
|
||||
tbl_str[#tbl_str + 1] = indent
|
||||
tbl_str[#tbl_str + 1] = loc .. '['
|
||||
tbl_str[#tbl_str + 1] = tostring(ind)
|
||||
tbl_str[#tbl_str + 1] = '] = '
|
||||
else
|
||||
tbl_str[#tbl_str + 1] = indent
|
||||
tbl_str[#tbl_str + 1] = loc .. '['
|
||||
tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(ind)
|
||||
tbl_str[#tbl_str + 1] = '] = '
|
||||
end
|
||||
|
||||
if ((type(val) == 'number') or (type(val) == 'boolean')) then
|
||||
tbl_str[#tbl_str + 1] = tostring(val)
|
||||
tbl_str[#tbl_str + 1] = ',\n'
|
||||
elseif type(val) == 'string' then
|
||||
tbl_str[#tbl_str + 1] = UTILS.BasicSerialize(val)
|
||||
tbl_str[#tbl_str + 1] = ',\n'
|
||||
elseif type(val) == 'nil' then -- won't ever happen, right?
|
||||
tbl_str[#tbl_str + 1] = 'nil,\n'
|
||||
elseif type(val) == 'table' then
|
||||
if tableshow_tbls[val] then
|
||||
tbl_str[#tbl_str + 1] = tostring(val) .. ' already defined: ' .. tableshow_tbls[val] .. ',\n'
|
||||
else
|
||||
tableshow_tbls[val] = loc .. '[' .. UTILS.BasicSerialize(ind) .. ']'
|
||||
tbl_str[#tbl_str + 1] = tostring(val) .. ' '
|
||||
tbl_str[#tbl_str + 1] = UTILS.TableShow(val, loc .. '[' .. UTILS.BasicSerialize(ind).. ']', indent .. ' ', tableshow_tbls)
|
||||
tbl_str[#tbl_str + 1] = ',\n'
|
||||
end
|
||||
elseif type(val) == 'function' then
|
||||
if debug and debug.getinfo then
|
||||
local fcnname = tostring(val)
|
||||
local info = debug.getinfo(val, "S")
|
||||
if info.what == "C" then
|
||||
tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', C function') .. ',\n'
|
||||
else
|
||||
if (string.sub(info.source, 1, 2) == [[./]]) then
|
||||
tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')' .. info.source) ..',\n'
|
||||
else
|
||||
tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')') ..',\n'
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
tbl_str[#tbl_str + 1] = 'a function,\n'
|
||||
end
|
||||
else
|
||||
tbl_str[#tbl_str + 1] = 'unable to serialize value type ' .. UTILS.BasicSerialize(type(val)) .. ' at index ' .. tostring(ind)
|
||||
end
|
||||
end
|
||||
|
||||
tbl_str[#tbl_str + 1] = indent .. '}'
|
||||
return table.concat(tbl_str)
|
||||
end
|
||||
end
|
||||
|
||||
--- Dumps the global table _G.
|
||||
-- This dumps the global table _G to a file in the DCS\Logs directory.
|
||||
-- This function requires you to disable script sanitization in $DCS_ROOT\Scripts\MissionScripting.lua to access lfs and io libraries.
|
||||
-- @param #string fname File name.
|
||||
function UTILS.Gdump(fname)
|
||||
if lfs and io then
|
||||
|
||||
local fdir = lfs.writedir() .. [[Logs\]] .. fname
|
||||
|
||||
local f = io.open(fdir, 'w')
|
||||
|
||||
f:write(UTILS.TableShow(_G))
|
||||
|
||||
f:close()
|
||||
|
||||
env.info(string.format('Wrote debug data to $1', fdir))
|
||||
else
|
||||
env.error("WARNING: lfs and/or io not de-sanitized - cannot dump _G!")
|
||||
end
|
||||
end
|
||||
|
||||
--- Executes the given string.
|
||||
-- borrowed from Slmod
|
||||
-- @param #string s string containing LUA code.
|
||||
-- @return #boolean `true` if successfully executed, `false` otherwise.
|
||||
function UTILS.DoString(s)
|
||||
local f, err = loadstring(s)
|
||||
if f then
|
||||
return true, f()
|
||||
else
|
||||
return false, err
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
UTILS.ToDegree = function(angle)
|
||||
return angle*180/math.pi
|
||||
@@ -711,6 +555,18 @@ UTILS.kg2lbs = function( kg )
|
||||
return kg * 2.20462
|
||||
end
|
||||
|
||||
--- Convert latitude or longitude from degrees, minutes, seconds (DMS) to decimal degrees (DD).
|
||||
-- @param #number Degrees Degrees in grad.
|
||||
-- @param #number Minutes Minutes.
|
||||
-- @param #number Seconds Seconds.
|
||||
-- @return #number Latitude or Longitude in decimal degrees.
|
||||
UTILS.LLDMSToDD = function(Degrees, Minutes, Seconds)
|
||||
|
||||
local dd=(Degrees or 0) + (Minutes or 0)/60 + (Seconds or 0)/3600
|
||||
|
||||
return dd
|
||||
end
|
||||
|
||||
--[[acc:
|
||||
in DM: decimal point of minutes.
|
||||
In DMS: decimal point of seconds.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
-- @module Wrapper.Airbase
|
||||
-- @image Wrapper_Airbase.JPG
|
||||
|
||||
---
|
||||
|
||||
-- @type AIRBASE
|
||||
-- @field #string ClassName Name of the class, i.e. "AIRBASE".
|
||||
-- @field #table CategoryName Names of airbase categories.
|
||||
@@ -30,7 +30,6 @@
|
||||
-- @field #table runways Runways of airdromes.
|
||||
-- @field #AIRBASE.Runway runwayLanding Runway used for landing.
|
||||
-- @field #AIRBASE.Runway runwayTakeoff Runway used for takeoff.
|
||||
-- @field Wrapper.Storage#STORAGE storage The DCS warehouse storage.
|
||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||
|
||||
--- Wrapper class to handle the DCS Airbase objects:
|
||||
@@ -549,8 +548,6 @@ AIRBASE.Syria={
|
||||
-- * AIRBASE.MarianaIslands.Saipan_Intl
|
||||
-- * AIRBASE.MarianaIslands.Tinian_Intl
|
||||
-- * AIRBASE.MarianaIslands.Olf_Orote
|
||||
-- * AIRBASE.MarianaIslands.Pagan_Airstrip
|
||||
-- * AIRBASE.MarianaIslands.North_West_Field
|
||||
--
|
||||
-- @field MarianaIslands
|
||||
AIRBASE.MarianaIslands = {
|
||||
@@ -560,8 +557,6 @@ AIRBASE.MarianaIslands = {
|
||||
["Saipan_Intl"] = "Saipan Intl",
|
||||
["Tinian_Intl"] = "Tinian Intl",
|
||||
["Olf_Orote"] = "Olf Orote",
|
||||
["Pagan_Airstrip"] = "Pagan Airstrip",
|
||||
["North_West_Field"] = "North West Field",
|
||||
}
|
||||
|
||||
--- Airbases of the South Atlantic map:
|
||||
@@ -792,13 +787,7 @@ function AIRBASE:Register(AirbaseName)
|
||||
|
||||
-- Category.
|
||||
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
|
||||
|
||||
-- H2 is bugged
|
||||
--if self.AirbaseName == "H4" and self.descriptors == nil then
|
||||
--self:E("***** H4 on Syria map is currently bugged!")
|
||||
--return nil
|
||||
--end
|
||||
|
||||
|
||||
-- Set category.
|
||||
if self.category==Airbase.Category.AIRDROME then
|
||||
self.isAirdrome=true
|
||||
@@ -833,9 +822,6 @@ function AIRBASE:Register(AirbaseName)
|
||||
|
||||
-- Init coordinate.
|
||||
self:GetCoordinate()
|
||||
|
||||
-- Storage.
|
||||
self.storage=_DATABASE:AddStorage(AirbaseName)
|
||||
|
||||
if vec2 then
|
||||
if self.isShip then
|
||||
@@ -923,87 +909,6 @@ function AIRBASE:GetZone()
|
||||
return self.AirbaseZone
|
||||
end
|
||||
|
||||
--- Get the DCS warehouse.
|
||||
-- @param #AIRBASE self
|
||||
-- @return DCS#Warehouse The DCS warehouse object.
|
||||
function AIRBASE:GetWarehouse()
|
||||
local warehouse=nil --DCS#Warehouse
|
||||
local airbase=self:GetDCSObject()
|
||||
if airbase then
|
||||
warehouse=airbase:getWarehouse()
|
||||
end
|
||||
return warehouse
|
||||
end
|
||||
|
||||
--- Get the warehouse storage of this airbase. The returned `STORAGE` object is the wrapper of the DCS warehouse.
|
||||
-- This allows you to add and remove items such as aircraft, liquids, weapons and other equipment.
|
||||
-- @param #AIRBASE self
|
||||
-- @return Wrapper.Storage#STORAGE The storage.
|
||||
function AIRBASE:GetStorage()
|
||||
return self.storage
|
||||
end
|
||||
|
||||
--- Enables or disables automatic capturing of the airbase.
|
||||
-- @param #AIRBASE self
|
||||
-- @param #boolean Switch If `true`, enable auto capturing. If `false`, disable it.
|
||||
-- @return #AIRBASE self
|
||||
function AIRBASE:SetAutoCapture(Switch)
|
||||
|
||||
local airbase=self:GetDCSObject()
|
||||
|
||||
if airbase then
|
||||
airbase:autoCapture(Switch)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Enables automatic capturing of the airbase.
|
||||
-- @param #AIRBASE self
|
||||
-- @return #AIRBASE self
|
||||
function AIRBASE:SetAutoCaptureON()
|
||||
self:SetAutoCapture(true)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Disables automatic capturing of the airbase.
|
||||
-- @param #AIRBASE self
|
||||
-- @return #AIRBASE self
|
||||
function AIRBASE:SetAutoCaptureOFF()
|
||||
self:SetAutoCapture(false)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns whether auto capturing of the airbase is on or off.
|
||||
-- @param #AIRBASE self
|
||||
-- @return #boolean Returns `true` if auto capturing is on, `false` if off and `nil` if the airbase object cannot be retrieved.
|
||||
function AIRBASE:IsAutoCapture()
|
||||
|
||||
local airbase=self:GetDCSObject()
|
||||
|
||||
local auto=nil
|
||||
if airbase then
|
||||
auto=airbase:autoCaptureIsOn()
|
||||
end
|
||||
|
||||
return auto
|
||||
end
|
||||
|
||||
--- Sets the coalition of the airbase.
|
||||
-- @param #AIRBASE self
|
||||
-- @param #number Coal Coalition that the airbase should have (0=Neutral, 1=Red, 2=Blue).
|
||||
-- @return #AIRBASE self
|
||||
function AIRBASE:SetCoalition(Coal)
|
||||
|
||||
local airbase=self:GetDCSObject()
|
||||
|
||||
if airbase then
|
||||
airbase:setCoalition(Coal)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get all airbases of the current map. This includes ships and FARPS.
|
||||
-- @param DCS#Coalition coalition (Optional) Return only airbases belonging to the specified coalition. By default, all airbases of the map are returned.
|
||||
-- @param #number category (Optional) Return only airbases of a certain category, e.g. Airbase.Category.FARP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@ do
|
||||
-- @field #number id
|
||||
-- @field #number side
|
||||
-- @field #number slot
|
||||
-- @field #numner timestamp
|
||||
|
||||
--- Encapsules multiplayer environment scripting functions from [net](https://wiki.hoggitworld.com/view/DCS_singleton_net)
|
||||
-- with some added FSM functions and options to block/unblock players in MP environments.
|
||||
@@ -205,7 +206,7 @@ function NET:_EventHandler(EventData)
|
||||
|
||||
-- Joining
|
||||
if data.id == EVENTS.PlayerEnterUnit or data.id == EVENTS.PlayerEnterAircraft then
|
||||
self:T(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid)
|
||||
self:T(self.lid.."Pilot Joining: "..name.." | UCID: "..ucid.." | Event ID: "..data.id)
|
||||
-- Check for blockages
|
||||
local blocked = self:IsAnyBlocked(ucid,name,PlayerID,PlayerSide,PlayerSlot)
|
||||
|
||||
@@ -213,15 +214,18 @@ function NET:_EventHandler(EventData)
|
||||
-- block pilot
|
||||
local outcome = net.force_player_slot(tonumber(PlayerID), 0, '' )
|
||||
else
|
||||
self.KnownPilots[name] = {
|
||||
name = name,
|
||||
ucid = ucid,
|
||||
id = PlayerID,
|
||||
side = PlayerSide,
|
||||
slot = PlayerSlot,
|
||||
}
|
||||
local client = CLIENT:FindByPlayerName(name) or data.IniUnit
|
||||
self:__PlayerJoined(1,client,name)
|
||||
if not self.KnownPilots[name] or (self.KnownPilots[name] and TNow-self.KnownPilots[name].timestamp > 3) then
|
||||
self:__PlayerJoined(1,client,name)
|
||||
self.KnownPilots[name] = {
|
||||
name = name,
|
||||
ucid = ucid,
|
||||
id = PlayerID,
|
||||
side = PlayerSide,
|
||||
slot = PlayerSlot,
|
||||
timestamp = TNow,
|
||||
}
|
||||
end
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
@@ -591,10 +591,10 @@ function POSITIONABLE:GetRandomVec3( Radius )
|
||||
|
||||
if Radius then
|
||||
local PositionableRandomVec3 = {}
|
||||
local angle = math.random() * math.pi * 2
|
||||
PositionableRandomVec3.x = PositionablePointVec3.x + math.cos( angle ) * math.random() * Radius
|
||||
local angle = math.random() * math.pi * 2;
|
||||
PositionableRandomVec3.x = PositionablePointVec3.x + math.cos( angle ) * math.random() * Radius;
|
||||
PositionableRandomVec3.y = PositionablePointVec3.y
|
||||
PositionableRandomVec3.z = PositionablePointVec3.z + math.sin( angle ) * math.random() * Radius
|
||||
PositionableRandomVec3.z = PositionablePointVec3.z + math.sin( angle ) * math.random() * Radius;
|
||||
|
||||
self:T3( PositionableRandomVec3 )
|
||||
return PositionableRandomVec3
|
||||
@@ -1768,93 +1768,6 @@ do -- Cargo
|
||||
end
|
||||
return self.__.CargoBayWeightLimit - CargoWeight
|
||||
end
|
||||
|
||||
---
|
||||
-- @field DefaultInfantryWeight
|
||||
-- Abstract out the "XYZ*95" calculation in the Ground POSITIONABLE case, where the table
|
||||
-- holds number of infantry that the vehicle could carry, instead of actual cargo weights.
|
||||
POSITIONABLE.DefaultInfantryWeight = 95
|
||||
|
||||
---
|
||||
-- @field CargoBayCapacityValues
|
||||
-- @field CargoBayCapacityValues.Air
|
||||
-- @field CargoBayCapacityValues.Naval
|
||||
-- @field CargoBayCapacityValues.Ground
|
||||
POSITIONABLE.CargoBayCapacityValues = {
|
||||
["Air"] = {
|
||||
-- C-17A
|
||||
-- Wiki says: max=265,352, empty=128,140, payload=77,516 (134 troops, 1 M1 Abrams tank, 2 M2 Bradley or 3 Stryker)
|
||||
-- DCS says: max=265,350, empty=125,645, fuel=132,405 ==> Cargo Bay=7300 kg with a full fuel load (lot of fuel!) and 73300 with half a fuel load.
|
||||
--["C-17A"] = 35000, --77519 cannot be used, because it loads way too much apcs and infantry.
|
||||
-- C-130:
|
||||
-- DCS says: max=79,380, empty=36,400, fuel=10,415 kg ==> Cargo Bay=32,565 kg with fuel load.
|
||||
-- Wiki says: max=70,307, empty=34,382, payload=19,000 kg (92 passengers, 2-3 Humvees or 2 M113s), max takeoff weight 70,037 kg.
|
||||
-- Here we say two M113s should be transported. Each one weights 11,253 kg according to DCS. So the cargo weight should be 23,000 kg with a full load of fuel.
|
||||
-- This results in a max takeoff weight of 69,815 kg (23,000+10,415+36,400), which is very close to the Wiki value of 70,037 kg.
|
||||
["C_130"] = 70000,
|
||||
},
|
||||
["Naval"] = {
|
||||
["Type_071"] = 245000,
|
||||
["LHA_Tarawa"] = 500000,
|
||||
["Ropucha_class"] = 150000,
|
||||
["Dry_cargo_ship_1"] = 70000,
|
||||
["Dry_cargo_ship_2"] = 70000,
|
||||
["Higgins_boat"] = 3700, -- Higgins Boat can load 3700 kg of general cargo or 36 men (source wikipedia).
|
||||
["USS_Samuel_Chase"] = 25000, -- Let's say 25 tons for now. Wiki says 33 Higgins boats, which would be 264 tons (can't be right!) and/or 578 troops.
|
||||
["LST_Mk2"] = 2100000, -- Can carry 2100 tons according to wiki source!
|
||||
["speedboat"] = 500, -- 500 kg ~ 5 persons
|
||||
["Seawise_Giant"] =261000000, -- Gross tonnage is 261,000 tonns.
|
||||
},
|
||||
["Ground"] = {
|
||||
["AAV7"] = 25*POSITIONABLE.DefaultInfantryWeight,
|
||||
["Bedford_MWD"] = 8*POSITIONABLE.DefaultInfantryWeight, -- new by kappa
|
||||
["Blitz_36_6700A"] = 10*POSITIONABLE.DefaultInfantryWeight, -- new by kappa
|
||||
["BMD_1"] = 9*POSITIONABLE.DefaultInfantryWeight, -- IRL should be 4 passengers
|
||||
["BMP_1"] = 8*POSITIONABLE.DefaultInfantryWeight,
|
||||
["BMP_2"] = 7*POSITIONABLE.DefaultInfantryWeight,
|
||||
["BMP_3"] = 8*POSITIONABLE.DefaultInfantryWeight, -- IRL should be 7+2 passengers
|
||||
["Boman"] = 25*POSITIONABLE.DefaultInfantryWeight,
|
||||
["BTR_80"] = 9*POSITIONABLE.DefaultInfantryWeight, -- IRL should be 7 passengers
|
||||
["BTR_82A"] = 9*POSITIONABLE.DefaultInfantryWeight, -- new by kappa -- IRL should be 7 passengers
|
||||
["BTR_D"] = 12*POSITIONABLE.DefaultInfantryWeight, -- IRL should be 10 passengers
|
||||
["Cobra"] = 8*POSITIONABLE.DefaultInfantryWeight,
|
||||
["Land_Rover_101_FC"] = 11*POSITIONABLE.DefaultInfantryWeight, -- new by kappa
|
||||
["Land_Rover_109_S3"] = 7*POSITIONABLE.DefaultInfantryWeight, -- new by kappa
|
||||
["LAV_25"] = 6*POSITIONABLE.DefaultInfantryWeight,
|
||||
["M_2_Bradley"] = 6*POSITIONABLE.DefaultInfantryWeight,
|
||||
["M1043_HMMWV_Armament"] = 4*POSITIONABLE.DefaultInfantryWeight,
|
||||
["M1045_HMMWV_TOW"] = 4*POSITIONABLE.DefaultInfantryWeight,
|
||||
["M1126_Stryker_ICV"] = 9*POSITIONABLE.DefaultInfantryWeight,
|
||||
["M1134_Stryker_ATGM"] = 9*POSITIONABLE.DefaultInfantryWeight,
|
||||
["M2A1_halftrack"] = 9*POSITIONABLE.DefaultInfantryWeight,
|
||||
["M_113"] = 9*POSITIONABLE.DefaultInfantryWeight, -- IRL should be 11 passengers
|
||||
["Marder"] = 6*POSITIONABLE.DefaultInfantryWeight,
|
||||
["MCV_80"] = 9*POSITIONABLE.DefaultInfantryWeight, -- IRL should be 7 passengers
|
||||
["MLRS_FDDM"] = 4*POSITIONABLE.DefaultInfantryWeight,
|
||||
["MTLB"] = 25*POSITIONABLE.DefaultInfantryWeight, -- IRL should be 11 passengers
|
||||
["GAZ_66"] = 8*POSITIONABLE.DefaultInfantryWeight,
|
||||
["GAZ_3307"] = 12*POSITIONABLE.DefaultInfantryWeight,
|
||||
["GAZ_3308"] = 14*POSITIONABLE.DefaultInfantryWeight,
|
||||
["Grad_FDDM"] = 6*POSITIONABLE.DefaultInfantryWeight, -- new by kappa
|
||||
["KAMAZ_Truck"] = 12*POSITIONABLE.DefaultInfantryWeight,
|
||||
["KrAZ6322"] = 12*POSITIONABLE.DefaultInfantryWeight,
|
||||
["M_818"] = 12*POSITIONABLE.DefaultInfantryWeight,
|
||||
["Tigr_233036"] = 6*POSITIONABLE.DefaultInfantryWeight,
|
||||
["TPZ"] = 10*POSITIONABLE.DefaultInfantryWeight, -- Fuchs
|
||||
["UAZ_469"] = 4*POSITIONABLE.DefaultInfantryWeight, -- new by kappa
|
||||
["Ural_375"] = 12*POSITIONABLE.DefaultInfantryWeight,
|
||||
["Ural_4320_31"] = 14*POSITIONABLE.DefaultInfantryWeight,
|
||||
["Ural_4320_APA_5D"] = 10*POSITIONABLE.DefaultInfantryWeight,
|
||||
["Ural_4320T"] = 14*POSITIONABLE.DefaultInfantryWeight,
|
||||
["ZBD04A"] = 7*POSITIONABLE.DefaultInfantryWeight, -- new by kappa
|
||||
["VAB_Mephisto"] = 8*POSITIONABLE.DefaultInfantryWeight, -- new by Apple
|
||||
["tt_KORD"] = 6*POSITIONABLE.DefaultInfantryWeight, -- 2.7.1 HL/TT
|
||||
["tt_DSHK"] = 6*POSITIONABLE.DefaultInfantryWeight,
|
||||
["HL_KORD"] = 6*POSITIONABLE.DefaultInfantryWeight,
|
||||
["HL_DSHK"] = 6*POSITIONABLE.DefaultInfantryWeight,
|
||||
["CCKW_353"] = 16*POSITIONABLE.DefaultInfantryWeight, --GMC CCKW 2½-ton 6×6 truck, estimating 16 soldiers,
|
||||
}
|
||||
}
|
||||
|
||||
--- Set Cargo Bay Weight Limit in kg.
|
||||
-- @param #POSITIONABLE self
|
||||
@@ -1879,13 +1792,23 @@ do -- Cargo
|
||||
|
||||
-- Unit type name.
|
||||
local TypeName=Desc.typeName or "Unknown Type"
|
||||
TypeName = string.gsub(TypeName,"[%p%s]","_")
|
||||
|
||||
|
||||
-- When an airplane or helicopter, we calculate the WeightLimit based on the descriptor.
|
||||
if self:IsAir() then
|
||||
|
||||
-- Max takeoff weight if DCS descriptors have unrealstic values.
|
||||
local Weights = POSITIONABLE.CargoBayCapacityValues.Air
|
||||
local Weights = {
|
||||
-- C-17A
|
||||
-- Wiki says: max=265,352, empty=128,140, payload=77,516 (134 troops, 1 M1 Abrams tank, 2 M2 Bradley or 3 Stryker)
|
||||
-- DCS says: max=265,350, empty=125,645, fuel=132,405 ==> Cargo Bay=7300 kg with a full fuel load (lot of fuel!) and 73300 with half a fuel load.
|
||||
--["C-17A"] = 35000, --77519 cannot be used, because it loads way too much apcs and infantry.
|
||||
-- C-130:
|
||||
-- DCS says: max=79,380, empty=36,400, fuel=10,415 kg ==> Cargo Bay=32,565 kg with fuel load.
|
||||
-- Wiki says: max=70,307, empty=34,382, payload=19,000 kg (92 passengers, 2-3 Humvees or 2 M113s), max takeoff weight 70,037 kg.
|
||||
-- Here we say two M113s should be transported. Each one weights 11,253 kg according to DCS. So the cargo weight should be 23,000 kg with a full load of fuel.
|
||||
-- This results in a max takeoff weight of 69,815 kg (23,000+10,415+36,400), which is very close to the Wiki value of 70,037 kg.
|
||||
["C-130"] = 70000,
|
||||
}
|
||||
|
||||
-- Max (takeoff) weight (empty+fuel+cargo weight).
|
||||
local massMax= Desc.massMax or 0
|
||||
@@ -1920,16 +1843,75 @@ do -- Cargo
|
||||
elseif self:IsShip() then
|
||||
|
||||
-- Hard coded cargo weights in kg.
|
||||
local Weights = POSITIONABLE.CargoBayCapacityValues.Naval
|
||||
local Weights = {
|
||||
["Type_071"] = 245000,
|
||||
["LHA_Tarawa"] = 500000,
|
||||
["Ropucha-class"] = 150000,
|
||||
["Dry-cargo ship-1"] = 70000,
|
||||
["Dry-cargo ship-2"] = 70000,
|
||||
["Higgins_boat"] = 3700, -- Higgins Boat can load 3700 kg of general cargo or 36 men (source wikipedia).
|
||||
["USS_Samuel_Chase"] = 25000, -- Let's say 25 tons for now. Wiki says 33 Higgins boats, which would be 264 tons (can't be right!) and/or 578 troops.
|
||||
["LST_Mk2"] = 2100000, -- Can carry 2100 tons according to wiki source!
|
||||
["speedboat"] = 500, -- 500 kg ~ 5 persons
|
||||
["Seawise_Giant"] =261000000, -- Gross tonnage is 261,000 tonns.
|
||||
}
|
||||
self.__.CargoBayWeightLimit = ( Weights[TypeName] or 50000 )
|
||||
|
||||
else
|
||||
|
||||
-- Hard coded number of soldiers.
|
||||
local Weights = POSITIONABLE.CargoBayCapacityValues.Ground
|
||||
local Weights = {
|
||||
["AAV7"] = 25,
|
||||
["Bedford_MWD"] = 8, -- new by kappa
|
||||
["Blitz_36-6700A"] = 10, -- new by kappa
|
||||
["BMD-1"] = 9, -- IRL should be 4 passengers
|
||||
["BMP-1"] = 8,
|
||||
["BMP-2"] = 7,
|
||||
["BMP-3"] = 8, -- IRL should be 7+2 passengers
|
||||
["Boman"] = 25,
|
||||
["BTR-80"] = 9, -- IRL should be 7 passengers
|
||||
["BTR-82A"] = 9, -- new by kappa -- IRL should be 7 passengers
|
||||
["BTR_D"] = 12, -- IRL should be 10 passengers
|
||||
["Cobra"] = 8,
|
||||
["Land_Rover_101_FC"] = 11, -- new by kappa
|
||||
["Land_Rover_109_S3"] = 7, -- new by kappa
|
||||
["LAV-25"] = 6,
|
||||
["M-2 Bradley"] = 6,
|
||||
["M1043 HMMWV Armament"] = 4,
|
||||
["M1045 HMMWV TOW"] = 4,
|
||||
["M1126 Stryker ICV"] = 9,
|
||||
["M1134 Stryker ATGM"] = 9,
|
||||
["M2A1_halftrack"] = 9,
|
||||
["M-113"] = 9, -- IRL should be 11 passengers
|
||||
["Marder"] = 6,
|
||||
["MCV-80"] = 9, -- IRL should be 7 passengers
|
||||
["MLRS FDDM"] = 4,
|
||||
["MTLB"] = 25, -- IRL should be 11 passengers
|
||||
["GAZ-66"] = 8,
|
||||
["GAZ-3307"] = 12,
|
||||
["GAZ-3308"] = 14,
|
||||
["Grad_FDDM"] = 6, -- new by kappa
|
||||
["KAMAZ Truck"] = 12,
|
||||
["KrAZ6322"] = 12,
|
||||
["M 818"] = 12,
|
||||
["Tigr_233036"] = 6,
|
||||
["TPZ"] = 10, -- Fuchs
|
||||
["UAZ-469"] = 4, -- new by kappa
|
||||
["Ural-375"] = 12,
|
||||
["Ural-4320-31"] = 14,
|
||||
["Ural-4320 APA-5D"] = 10,
|
||||
["Ural-4320T"] = 14,
|
||||
["ZBD04A"] = 7, -- new by kappa
|
||||
["VAB_Mephisto"] = 8, -- new by Apple
|
||||
["tt_KORD"] = 6, -- 2.7.1 HL/TT
|
||||
["tt_DSHK"] = 6,
|
||||
["HL_KORD"] = 6,
|
||||
["HL_DSHK"] = 6,
|
||||
["CCKW_353"] = 16, --GMC CCKW 2½-ton 6×6 truck, estimating 16 soldiers
|
||||
}
|
||||
|
||||
-- Assuming that each passenger weighs 95 kg on average.
|
||||
local CargoBayWeightLimit = ( Weights[TypeName] or 0 )
|
||||
local CargoBayWeightLimit = ( Weights[TypeName] or 0 ) * 95
|
||||
|
||||
self.__.CargoBayWeightLimit = CargoBayWeightLimit
|
||||
end
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
-- @field #string SceneryName Name of the scenery object.
|
||||
-- @field DCS#Object SceneryObject DCS scenery object.
|
||||
-- @field #number Life0 Initial life points.
|
||||
-- @field #table Properties
|
||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||
|
||||
|
||||
@@ -44,7 +43,7 @@ function SCENERY:Register( SceneryName, SceneryObject )
|
||||
|
||||
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )
|
||||
|
||||
self.SceneryName = tostring(SceneryName)
|
||||
self.SceneryName = SceneryName
|
||||
|
||||
self.SceneryObject = SceneryObject
|
||||
|
||||
@@ -53,43 +52,9 @@ function SCENERY:Register( SceneryName, SceneryObject )
|
||||
else
|
||||
self.Life0 = 0
|
||||
end
|
||||
|
||||
self.Properties = {}
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns the Value of the zone with the given PropertyName, or nil if no matching property exists.
|
||||
-- @param #SCENERY self
|
||||
-- @param #string PropertyName The name of a the QuadZone Property from the scenery assignment to be retrieved.
|
||||
-- @return #string The Value of the QuadZone Property from the scenery assignment with the given PropertyName, or nil if absent.
|
||||
function SCENERY:GetProperty(PropertyName)
|
||||
return self.Properties[PropertyName]
|
||||
end
|
||||
|
||||
--- Returns the scenery Properties table.
|
||||
-- @param #SCENERY self
|
||||
-- @return #table The Key:Value table of QuadZone properties of the zone from the scenery assignment .
|
||||
function SCENERY:GetAllProperties()
|
||||
return self.Properties
|
||||
end
|
||||
|
||||
--- Set a scenery property
|
||||
-- @param #SCENERY self
|
||||
-- @param #string PropertyName
|
||||
-- @param #string PropertyValue
|
||||
-- @return #SCENERY self
|
||||
function SCENERY:SetProperty(PropertyName, PropertyValue)
|
||||
self.Properties[PropertyName] = PropertyValue
|
||||
return self
|
||||
end
|
||||
--- Obtain object name.
|
||||
--@param #SCENERY self
|
||||
--@return #string Name
|
||||
function SCENERY:GetName()
|
||||
return self.SceneryName
|
||||
end
|
||||
|
||||
--- Obtain DCS Object from the SCENERY Object.
|
||||
--@param #SCENERY self
|
||||
--@return DCS#Object DCS scenery object.
|
||||
@@ -150,28 +115,26 @@ end
|
||||
--@param Core.Point#COORDINATE Coordinate Where to find the scenery object
|
||||
--@param #number Radius (optional) Search radius around coordinate, defaults to 100
|
||||
--@return #SCENERY Scenery Object or `nil` if it cannot be found
|
||||
function SCENERY:FindByName(Name, Coordinate, Radius, Role)
|
||||
|
||||
function SCENERY:FindByName(Name, Coordinate, Radius)
|
||||
|
||||
local radius = Radius or 100
|
||||
local name = Name or "unknown"
|
||||
local scenery = nil
|
||||
|
||||
BASE:T({name, radius, Coordinate:GetVec2()})
|
||||
|
||||
---
|
||||
-- @param Core.Point#COORDINATE coordinate
|
||||
-- @param #number radius
|
||||
-- @param #string name
|
||||
local function SceneryScan(scoordinate, sradius, sname)
|
||||
if scoordinate ~= nil then
|
||||
local Vec2 = scoordinate:GetVec2()
|
||||
local scanzone = ZONE_RADIUS:New("Zone-"..sname,Vec2,sradius,true)
|
||||
scanzone:Scan({Object.Category.SCENERY})
|
||||
local scanned = scanzone:GetScannedSceneryObjects()
|
||||
local rscenery = nil -- Wrapper.Scenery#SCENERY
|
||||
for _,_scenery in pairs(scanned) do
|
||||
local function SceneryScan(coordinate, radius, name)
|
||||
if coordinate ~= nil then
|
||||
local scenerylist = coordinate:ScanScenery(radius)
|
||||
local rscenery = nil
|
||||
for _,_scenery in pairs(scenerylist) do
|
||||
local scenery = _scenery -- Wrapper.Scenery#SCENERY
|
||||
if tostring(scenery.SceneryName) == tostring(sname) then
|
||||
if tostring(scenery.SceneryName) == tostring(name) then
|
||||
rscenery = scenery
|
||||
if Role then rscenery:SetProperty("ROLE",Role) end
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -181,7 +144,6 @@ function SCENERY:FindByName(Name, Coordinate, Radius, Role)
|
||||
end
|
||||
|
||||
if Coordinate then
|
||||
--BASE:I("Coordinate Scenery Scan")
|
||||
scenery = SceneryScan(Coordinate, radius, name)
|
||||
end
|
||||
|
||||
@@ -192,17 +154,17 @@ end
|
||||
-- to find the correct object.
|
||||
--@param #SCENERY self
|
||||
--@param #string Name The name or id of the scenery object as taken from the ME. Ex. '595785449'
|
||||
--@param Core.Zone#ZONE_BASE Zone Where to find the scenery object. Can be handed as zone name.
|
||||
--@param Core.Zone#ZONE Zone Where to find the scenery object. Can be handed as zone name.
|
||||
--@param #number Radius (optional) Search radius around coordinate, defaults to 100
|
||||
--@return #SCENERY Scenery Object or `nil` if it cannot be found
|
||||
function SCENERY:FindByNameInZone(Name, Zone, Radius)
|
||||
function SCENERY:FindByNameInZone(Name, Zone, Radius)
|
||||
local radius = Radius or 100
|
||||
local name = Name or "unknown"
|
||||
if type(Zone) == "string" then
|
||||
Zone = ZONE:FindByName(Zone)
|
||||
end
|
||||
local coordinate = Zone:GetCoordinate()
|
||||
return self:FindByName(Name,coordinate,Radius,Zone:GetProperty("ROLE"))
|
||||
return self:FindByName(Name,coordinate,Radius)
|
||||
end
|
||||
|
||||
--- Find a SCENERY object from its zone name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
@@ -211,34 +173,38 @@ end
|
||||
--@param #string ZoneName The name of the scenery zone as created with a right-click on the map in the mission editor and select "assigned to...". Can be handed over as ZONE object.
|
||||
--@return #SCENERY First found Scenery Object or `nil` if it cannot be found
|
||||
function SCENERY:FindByZoneName( ZoneName )
|
||||
local zone = ZoneName -- Core.Zone#ZONE_BASE
|
||||
local zone = ZoneName -- Core.Zone#ZONE
|
||||
if type(ZoneName) == "string" then
|
||||
zone = ZONE:FindByName(ZoneName) -- Core.Zone#ZONE_POLYGON
|
||||
zone = ZONE:FindByName(ZoneName)
|
||||
end
|
||||
local _id = zone:GetProperty('OBJECT ID')
|
||||
--local properties = zone:GetAllProperties() or {}
|
||||
--BASE:I(string.format("Object ID is: %s",_id or "none"))
|
||||
--BASE:T("Object ID ".._id)
|
||||
BASE:T("Object ID ".._id)
|
||||
if not _id then
|
||||
-- this zone has no object ID
|
||||
BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
|
||||
if string.find(zone.ClassName,"POLYGON") then
|
||||
zone:Scan({Object.Category.SCENERY})
|
||||
local scanned = zone:GetScannedSceneryObjects()
|
||||
local scanned = zone:GetScannedScenery()
|
||||
for _,_scenery in (scanned) do
|
||||
local scenery = _scenery -- Wrapper.Scenery#SCENERY
|
||||
if scenery:IsAlive() then
|
||||
local role = zone:GetProperty("ROLE")
|
||||
if role then scenery:SetProperty("ROLE",role) end
|
||||
return scenery
|
||||
end
|
||||
end
|
||||
return nil
|
||||
else
|
||||
return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
local coordinate = zone:GetCoordinate()
|
||||
local scanned = coordinate:ScanScenery()
|
||||
for _,_scenery in (scanned) do
|
||||
local scenery = _scenery -- Wrapper.Scenery#SCENERY
|
||||
if scenery:IsAlive() then
|
||||
return scenery
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
return self:FindByName(_id, zone:GetCoordinate())
|
||||
end
|
||||
end
|
||||
|
||||
@@ -253,7 +219,6 @@ function SCENERY:FindAllByZoneName( ZoneName )
|
||||
zone = ZONE:FindByName(ZoneName)
|
||||
end
|
||||
local _id = zone:GetProperty('OBJECT ID')
|
||||
--local properties = zone:GetAllProperties() or {}
|
||||
if not _id then
|
||||
-- this zone has no object ID
|
||||
--BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
|
||||
@@ -265,7 +230,7 @@ function SCENERY:FindAllByZoneName( ZoneName )
|
||||
return nil
|
||||
end
|
||||
else
|
||||
local obj = self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
local obj = self:FindByName(_id, zone:GetCoordinate())
|
||||
if obj then
|
||||
return {obj}
|
||||
else
|
||||
|
||||
@@ -1,359 +0,0 @@
|
||||
--- **Wrapper** - Warehouse storage of DCS airbases.
|
||||
--
|
||||
-- ## Main Features:
|
||||
--
|
||||
-- * Convenient access to DCS API functions
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Wrapper%20-%20Storage).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Wrapper.Storage
|
||||
-- @image Wrapper_Storage.png
|
||||
|
||||
|
||||
--- STORAGE class.
|
||||
-- @type STORAGE
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity level.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field DCS#Warehouse warehouse The DCS warehouse object.
|
||||
-- @field DCS#Airbase airbase The DCS airbase object.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *The capitalist cannot store labour-power in warehouses after he has bought it, as he may do with the raw material.* -- Karl Marx
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The STORAGE Concept
|
||||
--
|
||||
-- The STORAGE class offers an easy-to-use wrapper interface to all DCS API functions of DCS warehouses.
|
||||
-- We named the class STORAGE, because the name WAREHOUSE is already taken by another MOOSE class.
|
||||
--
|
||||
-- This class allows you to add and remove items to a DCS warehouse, such as aircraft, liquids, weapons and other equipment.
|
||||
--
|
||||
-- # Constructor
|
||||
--
|
||||
-- A DCS warehouse is associated with an airbase. Therefore, a `STORAGE` instance is automatically created, once an airbase is registered and added to the MOOSE database.
|
||||
--
|
||||
-- You can get the `STORAGE` object from the
|
||||
--
|
||||
-- -- Create a STORAGE instance of the Batumi warehouse
|
||||
-- local storage=STORAGE:FindByName("Batumi")
|
||||
--
|
||||
-- An other way to get the `STORAGE` object is to retrieve it from the AIRBASE function `AIRBASE:GetStorage()`
|
||||
--
|
||||
-- -- Get storage instance of Batumi airbase
|
||||
-- local Batumi=AIRBASE:FindByName("Batumi")
|
||||
-- local storage=Batumi:GetStorage()
|
||||
--
|
||||
-- # Aircraft, Weapons and Equipment
|
||||
--
|
||||
-- ## Adding Items
|
||||
--
|
||||
-- To add aircraft, weapons and/or othe equipment, you can use the @{#STORAGE.AddItem}() function
|
||||
--
|
||||
-- storage:AddItem("A-10C", 3)
|
||||
-- storage:AddItem("weapons.missiles.AIM_120C", 10)
|
||||
--
|
||||
-- This will add three A-10Cs and ten AIM-120C missiles to the warehouse inventory.
|
||||
--
|
||||
-- ## Setting Items
|
||||
--
|
||||
-- You can also explicitly set, how many items are in the inventory with the @{#STORAGE.SetItem}() function.
|
||||
--
|
||||
-- ## Removing Items
|
||||
--
|
||||
-- Items can be removed from the inventory with the @{#STORAGE.RemoveItem}() function.
|
||||
--
|
||||
-- ## Getting Amount
|
||||
--
|
||||
-- The number of items currently in the inventory can be obtained with the @{#STORAGE.GetItemAmount}() function
|
||||
--
|
||||
-- local N=storage:GetItemAmount("A-10C")
|
||||
-- env.info(string.format("We currently have %d A-10Cs available", N))
|
||||
--
|
||||
-- # Liquids
|
||||
--
|
||||
-- Liquids can be added and removed by slightly different functions as described below. Currently there are four types of liquids
|
||||
--
|
||||
-- * Jet fuel `STORAGE.Liquid.JETFUEL`
|
||||
-- * Aircraft gasoline `STORAGE.Liquid.GASOLINE`
|
||||
-- * MW 50 `STORAGE.Liquid.MW50`
|
||||
-- * Diesel `STORAGE.Liquid.DIESEL`
|
||||
--
|
||||
-- ## Adding Liquids
|
||||
--
|
||||
-- To add a certain type of liquid, you can use the @{#STORAGE.AddItem}(Type, Amount) function
|
||||
--
|
||||
-- storage:AddLiquid(STORAGE.Liquid.JETFUEL, 10000)
|
||||
-- storage:AddLiquid(STORAGE.Liquid.DIESEL, 20000)
|
||||
--
|
||||
-- This will add 10,000 kg of jet fuel and 20,000 kg of diesel to the inventory.
|
||||
--
|
||||
-- ## Setting Liquids
|
||||
--
|
||||
-- You can also explicitly set the amount of liquid with the @{#STORAGE.SetLiquid}(Type, Amount) function.
|
||||
--
|
||||
-- ## Removing Liquids
|
||||
--
|
||||
-- Liquids can be removed with @{#STORAGE.RemoveLiquid}(Type, Amount) function.
|
||||
--
|
||||
-- ## Getting Amount
|
||||
--
|
||||
-- The current amount of a certain liquid can be obtained with the @{#STORAGE.GetLiquidAmount}(Type) function
|
||||
--
|
||||
-- local N=storage:GetLiquidAmount(STORAGE.Liquid.DIESEL)
|
||||
-- env.info(string.format("We currently have %d kg of Diesel available", N))
|
||||
--
|
||||
--
|
||||
-- # Inventory
|
||||
--
|
||||
-- The current inventory of the warehouse can be obtained with the @{#STORAGE.GetInventory}() function. This returns three tables with the aircraft, liquids and weapons:
|
||||
--
|
||||
-- local aircraft, liquids, weapons=storage:GetInventory()
|
||||
--
|
||||
-- UTILS.PrintTableToLog(aircraft)
|
||||
-- UTILS.PrintTableToLog(liquids)
|
||||
-- UTILS.PrintTableToLog(weapons)
|
||||
--
|
||||
-- @field #STORAGE
|
||||
STORAGE = {
|
||||
ClassName = "STORAGE",
|
||||
verbose = 0,
|
||||
}
|
||||
|
||||
--- Liquid types.
|
||||
-- @type STORAGE.Liquid
|
||||
-- @field #number JETFUEL Jet fuel (0).
|
||||
-- @field #number GASOLINE Aviation gasoline (1).
|
||||
-- @field #number MW50 MW50 (2).
|
||||
-- @field #number DIESEL Diesel (3).
|
||||
STORAGE.Liquid = {
|
||||
JETFUEL = 0,
|
||||
GASOLINE = 1,
|
||||
MW50 = 2,
|
||||
DIESEL = 3,
|
||||
}
|
||||
|
||||
--- STORAGE class version.
|
||||
-- @field #string version
|
||||
STORAGE.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot...
|
||||
-- TODO: Persistence
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new STORAGE object from the DCS weapon object.
|
||||
-- @param #STORAGE self
|
||||
-- @param #string AirbaseName Name of the airbase.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:New(AirbaseName)
|
||||
|
||||
-- Inherit everything from BASE class.
|
||||
local self=BASE:Inherit(self, BASE:New()) -- #STORAGE
|
||||
|
||||
self.airbase=Airbase.getByName(AirbaseName)
|
||||
|
||||
self.warehouse=self.airbase:getWarehouse()
|
||||
|
||||
self.lid = string.format("STORAGE %s", AirbaseName)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Find a STORAGE in the **_DATABASE** using the name associated airbase.
|
||||
-- @param #STORAGE self
|
||||
-- @param #string AirbaseName The Airbase Name.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:FindByName( AirbaseName )
|
||||
local storage = _DATABASE:FindStorage( AirbaseName )
|
||||
return storage
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User API Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set verbosity level.
|
||||
-- @param #STORAGE self
|
||||
-- @param #number VerbosityLevel Level of output (higher=more). Default 0.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:SetVerbosity(VerbosityLevel)
|
||||
self.verbose=VerbosityLevel or 0
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Adds the passed amount of a given item to the warehouse.
|
||||
-- @param #STORAGE self
|
||||
-- @param #string Name Name of the item to add.
|
||||
-- @param #number Amount Amount of items to add.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:AddItem(Name, Amount)
|
||||
|
||||
self:T(self.lid..string.format("Adding %d items of %s", Amount, UTILS.OneLineSerialize(Name)))
|
||||
|
||||
self.warehouse:addItem(Name, Amount)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Sets the specified amount of a given item to the warehouse.
|
||||
-- @param #STORAGE self
|
||||
-- @param #string Name Name of the item.
|
||||
-- @param #number Amount Amount of items.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:SetItem(Name, Amount)
|
||||
|
||||
self:T(self.lid..string.format("Setting item %s to N=%d", UTILS.OneLineSerialize(Name), Amount))
|
||||
|
||||
self.warehouse:setItem(Name, Amount)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Gets the amount of a given item currently present the warehouse.
|
||||
-- @param #STORAGE self
|
||||
-- @param #string Name Name of the item.
|
||||
-- @return #number Amount of items.
|
||||
function STORAGE:GetItemAmount(Name)
|
||||
|
||||
local N=self.warehouse:getItemCount(Name)
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Removes the amount of the passed item from the warehouse.
|
||||
-- @param #STORAGE self
|
||||
-- @param #string Name Name of the item.
|
||||
-- @param #number Amount Amount of items.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:RemoveItem(Name, Amount)
|
||||
|
||||
self:T(self.lid..string.format("Removing N=%d of item %s", Amount, Name))
|
||||
|
||||
self.warehouse:removeItem(Name, Amount)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--- Adds the passed amount of a given liquid to the warehouse.
|
||||
-- @param #STORAGE self
|
||||
-- @param #number Type Type of liquid.
|
||||
-- @param #number Amount Amount of liquid to add.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:AddLiquid(Type, Amount)
|
||||
|
||||
self:T(self.lid..string.format("Adding %d liquids of %s", Amount, self:GetLiquidName(Type)))
|
||||
|
||||
self.warehouse:addLiquid(Type, Amount)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Sets the specified amount of a given liquid to the warehouse.
|
||||
-- @param #STORAGE self
|
||||
-- @param #number Type Type of liquid.
|
||||
-- @param #number Amount Amount of liquid.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:SetLiquid(Type, Amount)
|
||||
|
||||
self:T(self.lid..string.format("Setting liquid %s to N=%d", self:GetLiquidName(Type), Amount))
|
||||
|
||||
self.warehouse:setLiquid(Type, Amount)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes the amount of the given liquid type from the warehouse.
|
||||
-- @param #STORAGE self
|
||||
-- @param #number Type Type of liquid.
|
||||
-- @param #number Amount Amount of liquid in kg to be removed.
|
||||
-- @return #STORAGE self
|
||||
function STORAGE:RemoveLiquid(Type, Amount)
|
||||
|
||||
self:T(self.lid..string.format("Removing N=%d of liquid %s", Amount, self:GetLiquidName(Type)))
|
||||
|
||||
self.warehouse:removeLiquid(Type, Amount)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Gets the amount of a given liquid currently present the warehouse.
|
||||
-- @param #STORAGE self
|
||||
-- @param #number Type Type of liquid.
|
||||
-- @return #number Amount of liquid in kg.
|
||||
function STORAGE:GetLiquidAmount(Type)
|
||||
|
||||
local N=self.warehouse:getLiquidAmount(Type)
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
--- Returns the name of the liquid from its numeric type.
|
||||
-- @param #STORAGE self
|
||||
-- @param #number Type Type of liquid.
|
||||
-- @return #string Name of the liquid.
|
||||
function STORAGE:GetLiquidName(Type)
|
||||
|
||||
local name="Unknown"
|
||||
|
||||
if Type==STORAGE.Liquid.JETFUEL then
|
||||
name = "Jet fuel"
|
||||
elseif Type==STORAGE.Liquid.GASOLINE then
|
||||
name = "Aircraft gasoline"
|
||||
elseif Type==STORAGE.Liquid.MW50 then
|
||||
name = "MW 50"
|
||||
elseif Type==STORAGE.Liquid.DIESEL then
|
||||
name = "Diesel"
|
||||
else
|
||||
self:E(self.lid..string.format("ERROR: Unknown liquid type %s", tostring(Type)))
|
||||
end
|
||||
|
||||
return name
|
||||
end
|
||||
|
||||
|
||||
--- Returns a full itemized list of everything currently in a warehouse. If a category is set to unlimited then the table will be returned empty.
|
||||
-- @param #STORAGE self
|
||||
-- @param #string Item Name of item as #string or type of liquid as #number.
|
||||
-- @return #table Table of aircraft. Table is emtpy `{}` if number of aircraft is set to be unlimited.
|
||||
-- @return #table Table of liquids. Table is emtpy `{}` if number of liquids is set to be unlimited.
|
||||
-- @return #table Table of weapons and other equipment. Table is emtpy `{}` if number of liquids is set to be unlimited.
|
||||
function STORAGE:GetInventory(Item)
|
||||
|
||||
local inventory=self.warehouse:getInventory(Item)
|
||||
|
||||
return inventory.aircraft, inventory.liquids, inventory.weapon
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Private Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -179,9 +179,9 @@ function UNIT:GetDCSObject()
|
||||
return DCSUnit
|
||||
end
|
||||
|
||||
if self.DCSUnit then
|
||||
return self.DCSUnit
|
||||
end
|
||||
--if self.DCSUnit then
|
||||
--return self.DCSUnit
|
||||
--end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\ProgramData\chocolatey\lib\lua51\tools\lua5.1.exe"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose Setup\Moose_Create.lua" "D" "LOCAL" "${resource_loc:/MOOSE/Moose Development/Moose}" "${resource_loc:/MOOSE/Moose Setup}" ${resource_loc:/MOOSE_INCLUDE/Moose_Include_Dynamic}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/MOOSE}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/lua54/lua54.exe}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose Setup/Moose_Create.lua" "D" "LOCAL" "${workspace_loc:/Moose_Framework/Moose Development/Moose}" "${workspace_loc:/Moose_Framework/Moose Setup}" "${workspace_loc:/Moose_Framework/MOOSE_INCLUDE\Moose_Include_Dynamic}" 1"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework}"/>
|
||||
</launchConfiguration>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\ProgramData\chocolatey\lib\lua51\tools\lua5.1.exe"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose Setup\Moose_Create.lua" "S" "LOCAL" "${resource_loc:/MOOSE/Moose Development/Moose}" "${resource_loc:/MOOSE/Moose Setup}" ${resource_loc:/MOOSE_INCLUDE/Moose_Include_Static}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/MOOSE}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/lua54/lua54.exe}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose Setup\Moose_Create.lua" "S" "LOCAL" "${workspace_loc:/Moose_Framework/Moose Development/Moose}" "${workspace_loc:/Moose_Framework/Moose Setup}" "${workspace_loc:/Moose_Framework/MOOSE_INCLUDE\Moose_Include_Static}" 1"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework}"/>
|
||||
</launchConfiguration>
|
||||
|
||||
+29
-6
@@ -6,7 +6,6 @@ Utilities/Profiler.lua
|
||||
Utilities/Templates.lua
|
||||
Utilities/STTS.lua
|
||||
Utilities/FiFo.lua
|
||||
Utilities/Socket.lua
|
||||
|
||||
Core/Base.lua
|
||||
Core/Beacon.lua
|
||||
@@ -30,11 +29,10 @@ Core/SpawnStatic.lua
|
||||
Core/Timer.lua
|
||||
Core/Goal.lua
|
||||
Core/Spot.lua
|
||||
Core/MarkerOps_Base.lua
|
||||
Core/Astar.lua
|
||||
Core/Condition.lua
|
||||
Core/TextAndSound.lua
|
||||
Core/Condition.lua
|
||||
Core/Pathline.lua
|
||||
Core/ClientMenu.lua
|
||||
|
||||
Wrapper/Object.lua
|
||||
Wrapper/Identifiable.lua
|
||||
@@ -49,7 +47,6 @@ Wrapper/Scenery.lua
|
||||
Wrapper/Marker.lua
|
||||
Wrapper/Weapon.lua
|
||||
Wrapper/Net.lua
|
||||
Wrapper/Storage.lua
|
||||
|
||||
Cargo/Cargo.lua
|
||||
Cargo/CargoUnit.lua
|
||||
@@ -79,13 +76,39 @@ Functional/Warehouse.lua
|
||||
Functional/Fox.lua
|
||||
Functional/Mantis.lua
|
||||
Functional/Shorad.lua
|
||||
Functional/Autolase.lua
|
||||
Functional/AICSAR.lua
|
||||
Functional/AmmoTruck.lua
|
||||
|
||||
Ops/Airboss.lua
|
||||
Ops/RecoveryTanker.lua
|
||||
Ops/RescueHelo.lua
|
||||
Ops/ATIS.lua
|
||||
Ops/CTLD.lua
|
||||
Ops/Auftrag.lua
|
||||
Ops/OpsGroup.lua
|
||||
Ops/FlightGroup.lua
|
||||
Ops/NavyGroup.lua
|
||||
Ops/Cohort.lua
|
||||
Ops/Squadron.lua
|
||||
Ops/Platoon.lua
|
||||
Ops/Flotilla.lua
|
||||
Ops/Legion.lua
|
||||
Ops/AirWing.lua
|
||||
Ops/Brigade.lua
|
||||
Ops/Fleet.lua
|
||||
Ops/Intelligence.lua
|
||||
Ops/Commander.lua
|
||||
Ops/Chief.lua
|
||||
Ops/CSAR.lua
|
||||
Ops/CTLD.lua
|
||||
Ops/Awacs.lua
|
||||
Ops/Operation.lua
|
||||
Ops/FlightControl.lua
|
||||
Ops/PlayerTask.lua
|
||||
Ops/PlayerRecce.lua
|
||||
|
||||
Navigation/Navaid.lua
|
||||
Navigation/FlightPlan.lua
|
||||
|
||||
AI/AI_Balancer.lua
|
||||
AI/AI_Air.lua
|
||||
|
||||
@@ -5,19 +5,32 @@ local MooseCommitHash = arg[2]
|
||||
local MooseDevelopmentPath = arg[3]
|
||||
local MooseSetupPath = arg[4]
|
||||
local MooseTargetPath = arg[5]
|
||||
local isWindows = arg[6]
|
||||
|
||||
if not isWindows then
|
||||
isWindows = 0
|
||||
end
|
||||
print( "Moose (D)ynamic (S)tatic : " .. MooseDynamicStatic )
|
||||
print( "Commit Hash ID : " .. MooseCommitHash )
|
||||
print( "Moose development path : " .. MooseDevelopmentPath )
|
||||
print( "Moose setup path : " .. MooseSetupPath )
|
||||
print( "Moose target path : " .. MooseTargetPath )
|
||||
print( "isWindows : " .. isWindows)
|
||||
|
||||
|
||||
function PathConvert(splatnixPath)
|
||||
if isWindows == 0 then
|
||||
return splatnixPath
|
||||
end
|
||||
return splatnixPath:gsub("/", "\\")
|
||||
end
|
||||
|
||||
local MooseModulesFilePath = MooseDevelopmentPath .. "/Modules.lua"
|
||||
local LoaderFilePath = MooseTargetPath .. "/Moose.lua"
|
||||
|
||||
print( "Reading Moose source list : " .. MooseModulesFilePath )
|
||||
|
||||
local LoaderFile = io.open( LoaderFilePath, "w" )
|
||||
print("Opening Loaderfile " .. PathConvert(LoaderFilePath))
|
||||
local LoaderFile = assert(io.open( PathConvert(LoaderFilePath), "w+" ))
|
||||
|
||||
if MooseDynamicStatic == "S" then
|
||||
LoaderFile:write( "env.info( '*** MOOSE GITHUB Commit Hash ID: " .. MooseCommitHash .. " ***' )\n" )
|
||||
@@ -31,13 +44,14 @@ if MooseDynamicStatic == "S" then
|
||||
MooseLoaderPath = MooseSetupPath .. "/Moose Templates/Moose_Static_Loader.lua"
|
||||
end
|
||||
|
||||
local MooseLoader = io.open( MooseLoaderPath, "r" )
|
||||
|
||||
local MooseLoader = assert(io.open( PathConvert(MooseLoaderPath), "r" ))
|
||||
local MooseLoaderText = MooseLoader:read( "*a" )
|
||||
MooseLoader:close()
|
||||
|
||||
LoaderFile:write( MooseLoaderText )
|
||||
|
||||
local MooseSourcesFile = io.open( MooseModulesFilePath, "r" )
|
||||
local MooseSourcesFile = assert(io.open( PathConvert(MooseModulesFilePath), "r" ))
|
||||
local MooseSource = MooseSourcesFile:read("*l")
|
||||
|
||||
while( MooseSource ) do
|
||||
@@ -50,7 +64,7 @@ while( MooseSource ) do
|
||||
end
|
||||
if MooseDynamicStatic == "S" then
|
||||
print( "Load static: " .. MooseFilePath )
|
||||
local MooseSourceFile = io.open( MooseFilePath, "r" )
|
||||
local MooseSourceFile = assert(io.open( PathConvert(MooseFilePath), "r" ))
|
||||
local MooseSourceFileText = MooseSourceFile:read( "*a" )
|
||||
MooseSourceFile:close()
|
||||
|
||||
@@ -72,3 +86,8 @@ LoaderFile:write( "env.info( '*** MOOSE INCLUDE END *** ' )\n" )
|
||||
|
||||
MooseSourcesFile:close()
|
||||
LoaderFile:close()
|
||||
|
||||
print("Moose include generation complete.")
|
||||
if MooseDynamicStatic == "D" then
|
||||
print("To enable dynamic moose loading, add a soft or hard link from \"<YOUR_DCS_INSTALL_DIRECTORY>\\Scripts\\Moose\" to the \"Moose Development\\Moose\" subdirectory of the Moose_Framework repository.")
|
||||
end
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user