Compare commits

...

361 Commits

Author SHA1 Message Date
Applevangelist
8efcad123c Merge remote-tracking branch 'origin/master' into develop 2025-08-14 17:18:03 +02:00
Applevangelist
b9cf1e46af xx 2025-08-14 17:17:34 +02:00
Applevangelist
47409b11cb Merge remote-tracking branch 'origin/master' into develop 2025-08-14 17:16:30 +02:00
Applevangelist
4a04d7cce7 xx 2025-08-14 17:15:43 +02:00
Applevangelist
5ef6383c63 Merge remote-tracking branch 'origin/master' into develop 2025-08-14 09:13:32 +02:00
Applevangelist
35f15435a3 #MANTIS - Added Pantsir S1, TOR M2, IRIS-T SLM to main man SAM data (from CH mod) 2025-08-14 09:12:58 +02:00
Thomas
38dcd04334 Merge pull request #2363 from FlightControl-Master/Applevangelist-patch-1
#EasyGCICAP Adjustments for CAP ZONE using
2025-08-11 12:58:30 +02:00
Thomas
b32a8a2899 #EasyGCICAP Adjustments for CAP ZONE using
Added missing computations for coordinate when the zone is moving
2025-08-11 12:57:37 +02:00
Applevangelist
8cac4dbf9e #TIRESIAS - allow documents to build 2025-08-10 13:35:24 +02:00
Applevangelist
ef2bec72a1 Merge remote-tracking branch 'origin/master' into develop 2025-08-10 13:33:44 +02:00
Applevangelist
03c3a20b1b #AIRWING, #EASYGCICAP - allow moving zones as patrol points for CAP/TANKER/AWACS/RECON 2025-08-10 13:33:16 +02:00
Applevangelist
4c97d966a2 #MSRS - align google voices catalog with new voice types. 2025-08-10 13:20:22 +02:00
Applevangelist
f075c02db5 #EASYGCICAP - small tweak to allow the airbase to be a carrier ship 2025-08-07 18:47:49 +02:00
Applevangelist
32e61a7a09 Merge remote-tracking branch 'origin/master' into develop 2025-08-07 11:31:54 +02:00
Applevangelist
674c6eec81 More randomness in functions using random coordinates 2025-08-07 11:30:44 +02:00
Thomas
da535eaddc Merge pull request #2362 from FlightControl-Master/master
Merge from Master - SCORING
2025-08-07 11:17:24 +02:00
Thomas
c75c3d8777 Merge pull request #2361 from FlightControl-Master/Applevangelist-score-1
Update Scoring.lua
2025-08-07 11:16:29 +02:00
Thomas
4fa63986dc Update Scoring.lua
Further changes
2025-08-07 11:16:07 +02:00
Thomas
029f7a3f5c Update Scoring.lua
Better check for Scenery hits where target category is usually nil
2025-08-06 12:27:28 +02:00
Thomas
eb6eba25f3 Merge pull request #2359 from FlightControl-Master/master
Airbase new Sinai Bases
2025-08-04 16:12:01 +02:00
Thomas
e9194c59f4 Merge pull request #2358 from FlightControl-Master/Applevangelist-patch-1
Update Airbase.lua
2025-08-04 16:11:00 +02:00
Thomas
c8d693c8e7 Update Airbase.lua
Sinai add'l bases
2025-08-04 16:10:10 +02:00
Thomas
72d8b29699 Merge pull request #2357 from FlightControl-Master/master
Merge from master
2025-08-02 18:35:43 +02:00
Thomas
2341014882 Merge pull request #2356 from leka1986/master
Master
2025-08-02 18:34:25 +02:00
leka1986
eb15fadcfe Added SetPartlyInside. if used, it the :Trigger will trigger as soon as any of the group units enteres the zone even if they are far apart. 2025-08-02 17:40:55 +02:00
Applevangelist
1e7203320f Merge remote-tracking branch 'origin/master' into develop 2025-08-01 14:03:29 +02:00
Applevangelist
e3b587aa95 xx 2025-08-01 14:03:12 +02:00
Applevangelist
13fa8f373e #MANTIS - added radar entry for Dog Ear and Nike 2025-08-01 14:02:57 +02:00
Applevangelist
c3dc055fb2 #FLIGHTGROUP - avoid nil error on dynamic spawn clients when looking for theri original prarking space 2025-08-01 09:23:40 +02:00
Applevangelist
4e024f7173 #EASYGCICAP - added FuelLow/Critical settings and stopping of Airwings if you call Stop(). 2025-07-31 12:35:40 +02:00
Applevangelist
1248006f3d Merge remote-tracking branch 'origin/master' into develop 2025-07-31 09:48:23 +02:00
Applevangelist
b318e8ae13 #AIRBOSS - Added :SetCarrierIllumination(Mode) 2025-07-31 09:47:54 +02:00
Thomas
1af4d44ca5 Merge pull request #2355 from FlightControl-Master/master
Merge from master
2025-07-31 09:27:03 +02:00
Thomas
7e963bef41 Merge pull request #2354 from shaji-Dev/master
[ADDED] `UTILS.ShowPicture` For all, coalition, country, group and unit
2025-07-31 09:26:09 +02:00
smiki
933000ffc7 [ADDED] UNIT:SetCarrierIlluminationMode 2025-07-31 09:06:19 +02:00
smiki
9b217e1c97 [ADDED] UTILS.ShowPicture For all, coalition, country, group and unit
[ADDED] `UTILS.ShowHelperGateForUnit`
2025-07-31 08:57:20 +02:00
smiki
324f4944b4 [ADDED] UTILS.ShowPicture For all, coalition, country, group and unit
[ADDED] `UTILS.ShowHelperGateForUnit`
2025-07-31 08:54:16 +02:00
Applevangelist
b9d738c1ad Merge remote-tracking branch 'origin/master' into develop 2025-07-29 17:39:08 +02:00
Applevangelist
f735f1eb53 CTLD - correct ground speed for routing 2025-07-29 17:38:35 +02:00
Thomas
7149226283 Merge pull request #2353 from shaji-Dev/master
[CHANGED] Use file path instead of resource key
2025-07-29 13:04:46 +02:00
shaji-Dev
4164a5288a Merge branch 'FlightControl-Master:master' into master 2025-07-29 12:50:45 +02:00
smiki
1992276b07 Merge remote-tracking branch 'origin/master' 2025-07-29 12:50:27 +02:00
smiki
21a7023b7b Removed getValueResourceByKey UTILS.ShowPicture and UTILS.SetMissionBriefing to use full file paths 2025-07-29 12:50:19 +02:00
Applevangelist
bd054b26c0 Merge remote-tracking branch 'origin/master' into develop 2025-07-29 12:05:29 +02:00
Applevangelist
f094716b73 CTLD - Added option for Vehicle Formation when going to a MOVE zone. 2025-07-29 12:04:41 +02:00
Applevangelist
b3100d2f5e Merge remote-tracking branch 'origin/master' into develop 2025-07-29 10:03:34 +02:00
Applevangelist
4b1888a34d CSAR - Allow also the initial down message to be suppressed 2025-07-29 10:02:22 +02:00
Applevangelist
f4cd214823 #TIRESIAS - Avoid creating SET_GROUPs all the time for player objects, cached now 2025-07-27 19:24:43 +02:00
Applevangelist
b9be3aa7f8 xx 2025-07-27 14:50:45 +02:00
Thomas
bb6db2b7f8 Merge pull request #2352 from FlightControl-Master/master
Merge from Master
2025-07-27 14:16:07 +02:00
Thomas
fd2dacaefb Merge pull request #2351 from shaji-Dev/master
[ADDED] `UTILS.LoadMission` and `UTILS.SetMissionBriefing`
2025-07-27 14:15:16 +02:00
smiki
cc60e85901 [ADDED] UTILS.LoadMission and UTILS.SetMissionBriefing 2025-07-27 13:18:56 +02:00
Thomas
9520782a04 Merge pull request #2350 from FlightControl-Master/master
Merge from master
2025-07-26 09:02:12 +02:00
Thomas
f172f6efeb Merge pull request #2349 from shaji-Dev/master
[ADDED] `UTILS.ShowPicture`. Overlay pictures for players
2025-07-26 09:01:02 +02:00
smiki
b6b6686873 [ADDED] COORDINATE:GetLandProfile 2025-07-25 23:43:00 +02:00
smiki
5e724e7a3f [ADDED] COORDINATE:GetLandProfile 2025-07-25 23:39:53 +02:00
smiki
90f1d1df2a Merge remote-tracking branch 'origin/master' 2025-07-25 23:27:11 +02:00
smiki
a5726c0ed8 [ADDED] UTILS.ShowPicture. Overlay pictures for players.
Refactoring
2025-07-25 23:27:01 +02:00
Applevangelist
1860366986 Merge remote-tracking branch 'origin/master' into develop 2025-07-25 19:06:34 +02:00
Applevangelist
9db1d38a15 #TIRESIAS - some optimization 2025-07-25 19:06:12 +02:00
Applevangelist
04ceda693b #AUTOLASE - switch off increased ground awareness as default 2025-07-25 19:05:40 +02:00
Applevangelist
23ff128ac8 #ZONE added ZONE_BASE:FindNearestCoordinateOnRadius() 2025-07-25 19:05:01 +02:00
Applevangelist
3749142670 Merge remote-tracking branch 'origin/master' into develop 2025-07-25 14:58:41 +02:00
Applevangelist
7d3fc1740a xx 2025-07-25 14:57:58 +02:00
Applevangelist
b2a084d669 xx 2025-07-25 14:57:06 +02:00
Applevangelist
30203668e4 Revert "#UTILS - Added FindNearestPointOnCircle()"
This reverts commit 2cc1ddd4679b0e3fb7a5f72ea5e4822112e2f2d1.
2025-07-25 14:57:06 +02:00
Thomas
ebecc70693 Merge pull request #2348 from shaji-Dev/master
[ADDED] `Disposition.getSimpleZones`  support for ZONE_POLYGON_BASE
2025-07-25 14:47:08 +02:00
smiki
74712b6e27 [ADDED] Disposition.getSimpleZones to ZONE_POLYGON_BASE to support all zone types 2025-07-25 14:17:03 +02:00
Applevangelist
40253ea8bb xx 2025-07-24 18:27:44 +02:00
Applevangelist
7279da7f09 xx 2025-07-24 18:26:28 +02:00
Applevangelist
31c40c96f2 Merge remote-tracking branch 'origin/develop' into develop 2025-07-24 16:21:24 +02:00
Applevangelist
7a833365ce #CONTROLLABLE - added options for landing approaches
* Prefer vertical for helos
and for aircraft
* Straight in
* Overhead break
* Force pair
* Restrict pair

You can also set these on AirWing and FlightGroup levels

#AUFTRAG - added dive bomb option to NewBombing
2025-07-24 16:21:04 +02:00
Applevangelist
4e56078d2a #CONTROLLABLE - added options for landing approaches
* Prefer vertical for helos
and for aircraft
* Straight in
* Overhead break
* Force pair
* Restrict pair
2025-07-24 16:17:09 +02:00
Thomas
0ac156f2b5 Merge pull request #2346 from FlightControl-Master/master
Merge from master
2025-07-24 09:40:00 +02:00
Thomas
4bbf20ca4e Merge pull request #2345 from shaji-Dev/master
[Fixed] `Disposition.getSimpleZones`
2025-07-24 09:39:09 +02:00
smiki
a462c5a493 [Fixed] Disposition.getSimpleZones 2025-07-24 01:51:10 +02:00
Applevangelist
179cb5f589 Merge remote-tracking branch 'origin/master' into develop 2025-07-23 15:48:26 +02:00
Applevangelist
367014ebf3 xxx 2025-07-23 15:47:56 +02:00
Applevangelist
9d8d0c2155 Merge remote-tracking branch 'origin/develop' into develop 2025-07-23 12:36:05 +02:00
Applevangelist
edfe91274d Merge remote-tracking branch 'origin/master' into develop 2025-07-23 12:36:01 +02:00
Thomas
326b20b08d Merge pull request #2344 from shaji-Dev/master
[ADDED] `Disposition.getSimpleZones`
2025-07-23 12:35:16 +02:00
Applevangelist
11b0ce6275 #AIRBASE - remove some differences between data produced by _InitRunways and GetRunwayData 2025-07-23 12:34:52 +02:00
smiki
03763e16d6 [ADDED] Disposition.getSimpleZones 2025-07-23 12:19:00 +02:00
smiki
c1e8ee12e0 [ADDED] Disposition.getSimpleZones 2025-07-23 11:48:33 +02:00
smiki
ac8cc408c1 [FIXED] Disposition.getSimpleZones 2025-07-23 11:48:07 +02:00
Thomas
dad91cca8c Merge pull request #2343 from shaji-Dev/develop
[FIXED] COMMANDER.maxMissionsAssignPerCycle typo
2025-07-22 18:55:50 +02:00
smiki
2f9c384ac0 [FIXED] COMMANDER.maxMissionsAssignPerCycle typo 2025-07-22 18:45:02 +02:00
Applevangelist
f23a2267cf Merge remote-tracking branch 'origin/master' into develop 2025-07-22 13:09:48 +02:00
Applevangelist
ada38fa3ea #AIRBOSS - SRS 2.2.x path in documentation 2025-07-22 13:08:46 +02:00
Applevangelist
2ee0597d48 #CTLD - added FSM event "CratesPacked"
#UTILS - more options for MASH building
2025-07-22 13:08:18 +02:00
Applevangelist
b39a83ad6e Merge remote-tracking branch 'origin/master' into develop 2025-07-21 15:03:22 +02:00
Applevangelist
7ae4cdc8f1 #Documentation 2025-07-21 15:02:45 +02:00
Applevangelist
7d47227fab Merge remote-tracking branch 'origin/develop' into develop 2025-07-21 14:50:42 +02:00
Applevangelist
1f09b8fe0b Merge remote-tracking branch 'origin/master' into develop 2025-07-21 14:50:38 +02:00
Applevangelist
8c92a578ed #UTILS - added UTILS.SpawnMASHStatics() 2025-07-21 14:50:08 +02:00
Thomas
992f09d9ba Merge pull request #2342 from FlightControl-Master/master
Vnao Airboss exits
2025-07-21 09:11:12 +02:00
Thomas
096f2caf9c Merge pull request #2341 from nasgroup94/master
Added VNAO Edits
2025-07-21 09:09:54 +02:00
frankiep95
0b37c909b3 Added VNAO Edits 2025-07-20 16:58:33 -04:00
Applevangelist
bdad38e707 Merge remote-tracking branch 'origin/master' into develop 2025-07-20 14:04:24 +02:00
Applevangelist
1b18ae1597 #MANTIS - Added SAMP/T, SA-17 data correction, HDS explanations expanded 2025-07-20 14:03:33 +02:00
Thomas
8dcc3cbe8f Merge pull request #2340 from shaji-Dev/develop
[ADDED] COMMANDER:SetMaxMissionsAssignPerCycle
2025-07-20 12:28:36 +02:00
smiki
aa8f3a824c [ADDED] COMMANDER:SetMaxMissionsStartPerCycle 2025-07-20 12:12:31 +02:00
smiki
b5a19528a1 [ADDED] COMMANDER:SetMaxMissionsStartPerCycle 2025-07-20 12:11:57 +02:00
Thomas
bd20e8fc81 Merge pull request #2339 from shaji-Dev/develop
Develop
2025-07-20 11:51:57 +02:00
smiki
2f806801bc [ADDED] AUFTRAG:SetRepeatDelay 2025-07-20 11:48:35 +02:00
shaji-Dev
be006bd2bf Merge branch 'FlightControl-Master:develop' into develop 2025-07-20 11:44:34 +02:00
Applevangelist
18a08288ec Merge remote-tracking branch 'origin/master' into develop 2025-07-19 18:36:40 +02:00
Applevangelist
c9ac6d73e6 #MANTIS - Better documented use of SA-10B/C/12/23 naming usage with launcher differences. 2025-07-19 18:36:03 +02:00
Applevangelist
f602455d1f Merge remote-tracking branch 'origin/master' into develop 2025-07-19 16:05:55 +02:00
Applevangelist
d5c34a37b0 #AICSAR - Added functionality to use rescue zones instead of pure distance. Fixed helo not despawning after landing back at base. 2025-07-19 16:05:28 +02:00
Applevangelist
8a0e9a3400 #Fix SRS TTS folder path in documentation and defaults 2025-07-19 16:05:06 +02:00
Applevangelist
0e836973fd #Fix SRS TTS folder path in documentation and defaults 2025-07-19 16:04:49 +02:00
Applevangelist
1b57af88a0 Merge remote-tracking branch 'origin/master' into develop 2025-07-18 18:10:43 +02:00
Applevangelist
be40d7be9a #SPAWNSTATIC - NewFromStatic now creates a new template in the database under the new name - if not already there. This allows #WAREHOUSE static warehouses spawned that way to be respawned eg on coalition change. 2025-07-18 18:09:57 +02:00
Applevangelist
00de8d911c Merge remote-tracking branch 'origin/develop' into develop 2025-07-18 09:24:58 +02:00
smiki
9df3fcfdf7 [FIXED] attempt to index local 'airbase' (a nil value) 2025-07-17 23:36:23 +02:00
Thomas
d675e34f37 Merge pull request #2338 from shaji-Dev/develop
[FIXED] AIRWING operational regardless of airbase coalition
2025-07-17 07:38:43 +02:00
smiki
2d96ba0f56 [FIXED] AIRWING operational regardless of airbase coalition 2025-07-16 23:39:04 +02:00
smiki
21c2bd1103 [FIXED] AIRWING operational regardless of airbase coalition 2025-07-16 23:17:47 +02:00
Thomas
f3b7740041 Merge pull request #2335 from shaji-Dev/master
[ADDED] GROUP.Attribute.GROUND_SHORAD
2025-07-15 11:19:41 +02:00
smiki
7d7488db6f [ADDED] GROUP.Attribute.GROUND_SHORAD 2025-07-15 11:05:03 +02:00
Thomas
b9197d65d5 Merge pull request #2334 from shaji-Dev/develop
[ADDED] GROUP.Attribute.GROUND_SHORAD
2025-07-15 10:35:36 +02:00
smiki
ec6f190b68 [ADDED] GROUP.Attribute.GROUND_SHORAD 2025-07-15 10:16:49 +02:00
Thomas
5e4f9f035b Merge pull request #2333 from shaji-Dev/develop
[FIXED] AUFTRAG and FSM state mismatch workaround `AUFTRAG:CheckGroupsDone`
2025-07-14 19:18:05 +02:00
smiki
7b6bf7f39b [FIXED] AUFTRAG and FSM state mismatch workaround for AUFTRAG:CheckGroupsDone 2025-07-14 19:04:26 +02:00
Thomas
2e8875dd2f Update Auftrag.lua
Fix catch all check groups 
2025-07-14 10:13:38 +02:00
Thomas
4964cc2f2d Merge pull request #2332 from FlightControl-Master/Applevangelist-Vertical
Controllable - add option prefer vertical landing
2025-07-09 12:18:10 +02:00
Thomas
f0a4c5b008 Merge pull request #2331 from FlightControl-Master/Applevangelist-patch-2
Update Controllable.lua
2025-07-09 12:16:29 +02:00
Thomas
1b6412821b Update Controllable.lua 2025-07-09 12:15:34 +02:00
Thomas
926a0733e4 Controllable - add option prefer vertical landing
Addrd
2025-07-09 12:14:41 +02:00
Applevangelist
124ebd3240 xxx 2025-07-05 18:57:39 +02:00
Applevangelist
7728609165 Merge remote-tracking branch 'origin/master' into develop 2025-07-05 18:57:27 +02:00
Applevangelist
da70f4ce6c #DynamicSlots for dynamic FARPs 2025-07-05 18:56:59 +02:00
Applevangelist
69b3e9abad Small fix 2025-07-04 18:47:08 +02:00
Applevangelist
f9f77bfa7b xxx 2025-07-04 18:46:56 +02:00
Applevangelist
429db73854 #AUFTRAG - fix condition for assets done test 2025-07-04 16:22:55 +02:00
Applevangelist
1e9c45c115 Merge remote-tracking branch 'origin/master' into develop 2025-07-03 16:39:55 +02:00
Applevangelist
727cb3276c #SET fix for table insert of GetAliveSet 2025-07-03 16:39:24 +02:00
Applevangelist
a68175448d Merge remote-tracking branch 'origin/master' into develop 2025-07-03 15:15:54 +02:00
Thomas
33e63a4819 Merge pull request #2330 from shaji-Dev/master
[FIXED] index `nil` at  `MARKEROPS_BASE:OnEventMark`
2025-07-03 15:14:11 +02:00
Applevangelist
d7431478d1 Merge remote-tracking branch 'origin/master' into develop 2025-07-03 14:59:14 +02:00
smiki
3543b2c79a [FIXED] index nil at MARKEROPS_BASE:OnEventMark 2025-07-03 14:59:07 +02:00
Applevangelist
4489efff94 #POSITIONABLE - make GetVec3/GetCoordinate a bit more robust 2025-07-03 14:57:48 +02:00
Applevangelist
dcdea379ef Merge remote-tracking branch 'origin/master' into develop 2025-07-03 11:59:23 +02:00
Applevangelist
6a4bddde99 #SET - do not create a new SET on GetAliveSet is we only send back the object table 2025-07-03 11:58:44 +02:00
Applevangelist
2088359756 Merge remote-tracking branch 'origin/master' into develop 2025-07-03 10:55:02 +02:00
Thomas
dc2511942c Merge pull request #2329 from shaji-Dev/master
[FIXED] Memory leaks
2025-07-03 10:52:40 +02:00
Thomas
f0c257c4a5 Merge branch 'master' into master 2025-07-03 10:52:29 +02:00
Applevangelist
068d21612f #MARKEROPS - do not crate a COORDINATE b4 you need it
#UTILS - added
* UTILS.ShowHelperGate(pos, heading)
* UTILS.ShellZone
* UTILS.RemoveObjects
* UTILS.DestroyScenery
2025-07-03 10:48:54 +02:00
smiki
773461aad9 [FIXED] Memory leaks 2025-07-03 09:54:07 +02:00
smiki
f9257b2b0d [FIXED] Memory leaks 2025-07-03 09:45:21 +02:00
smiki
9e0f03a3cd [FIXED] Memory leaks 2025-07-03 08:44:41 +02:00
Applevangelist
0ab6a10ec4 #AWACS - added FSM transitions for VID Success and Failure 2025-06-29 15:50:24 +02:00
Thomas
73f393c542 Merge pull request #2328 from FlightControl-Master/master
Merge
2025-06-24 19:28:33 +02:00
Thomas
a467fabdc8 Merge pull request #2327 from leka1986/patch-1
Update CTLD.lua
2025-06-24 19:26:36 +02:00
leka1986
a2ab84c45a Update CTLD.lua
Added Herc fix when dropping from air.

Added CratesName in the OnAfterCratesBuildStarted parm
2025-06-24 19:24:00 +02:00
Thomas
7ec7228cb8 Merge pull request #2326 from FlightControl-Master/master
Merge from master
2025-06-24 18:23:19 +02:00
Thomas
9fd6729967 Merge pull request #2325 from FlightControl-Master/Applevangelist-patch-1-1
Update Airbase.lua
2025-06-24 18:22:18 +02:00
Thomas
f1d4f1753a Update Airbase.lua 2025-06-24 16:28:46 +02:00
Frank
1f268b3b5d Merge branch 'master' into develop 2025-06-23 22:43:13 +02:00
Frank
6d9c3fd0aa Merge pull request #2324 from FlightControl-Master/FF/MasterDevel
AIRBOSS Essex+Corsair
2025-06-23 22:41:16 +02:00
Frank
28ae63bd8d Update Airboss.lua 2025-06-23 22:39:52 +02:00
Frank
42e7e3f94f Update Airboss.lua 2025-06-23 22:28:48 +02:00
Thomas
4a5204aecb Merge pull request #2323 from FlightControl-Master/master
Merge
2025-06-23 19:09:47 +02:00
Thomas
6466c5e95e Merge pull request #2322 from leka1986/master
Merge branch 'master' of https://github.com/FlightControl-Master/MOOSE
2025-06-23 19:02:56 +02:00
leka1986
829f5af25f Merge branch 'master' of https://github.com/FlightControl-Master/MOOSE 2025-06-23 18:28:08 +02:00
leka1986
0d1147bac4 Added the missing lines to check if the droped troop is engineer, then start the engineer instance. Added missing messages when dropping single crate type, ie truck for example. Added a call to refreshdropcratesmenu in the takeoff / land event. Drop and build is only created if fixedwing is on the ground. 2025-06-23 18:28:02 +02:00
Frank
24b47b02e0 AIRBOSS
- Essex
- Corsair
2025-06-22 22:29:52 +02:00
Thomas
10262fd30b Merge pull request #2321 from FlightControl-Master/master
Merge from master
2025-06-20 14:03:40 +02:00
Thomas
3cabc07d58 Merge pull request #2320 from shaji-Dev/master
[ADDED] New Kola Airbases
2025-06-20 14:01:24 +02:00
shaji
b0546b1e60 [ADDED] New Kola Airbases 2025-06-20 12:58:50 +02:00
shaji
a988e67490 [ADDED] New Kola Airbases 2025-06-20 12:20:58 +02:00
Thomas
fa951838d2 Merge pull request #2319 from FlightControl-Master/master
Merge from master
2025-06-19 09:16:30 +02:00
Thomas
2594c5bbf0 Merge pull request #2318 from shaji-Dev/master
[FIXED] Error: attempt to index local 'Schedule' (a nil value)
2025-06-19 09:15:42 +02:00
shaji
db70fa341c Merge remote-tracking branch 'origin/master' 2025-06-19 07:42:52 +02:00
shaji
763e3852ac [FIXED] Error: attempt to index local 'Schedule' (a nil value) 2025-06-19 07:42:29 +02:00
Thomas
66157d0596 Merge pull request #2316 from FlightControl-Master/master
Fixes from Master
2025-06-18 14:34:04 +02:00
Thomas
8ec86973c6 Update SpawnStatic.lua
Fix SpawnFromZone()
2025-06-18 14:29:34 +02:00
Thomas
eb2c6ac6f2 Update SRS.lua
#MSRS Voice mapping correction
2025-06-18 14:19:50 +02:00
Applevangelist
93a8d8bc2d Merge remote-tracking branch 'origin/master' into develop 2025-06-15 17:02:35 +02:00
Applevangelist
cbcc893ce5 #CTLD - avoid smoking runways on airbase zones 2025-06-15 17:01:58 +02:00
Applevangelist
c19713949d Merge remote-tracking branch 'origin/master' into develop 2025-06-15 15:42:57 +02:00
Applevangelist
54450935a1 Merge remote-tracking branch 'origin/develop' into develop 2025-06-15 15:42:37 +02:00
Applevangelist
d0f5712ca8 #AUFTRAG - Allow CAP Auftrag w/o Zone 2025-06-15 15:42:33 +02:00
Applevangelist
382b049c5f #AIRBASE - Syria and Sinai few names corrected 2025-06-15 15:38:12 +02:00
Thomas
6c2cc37abe Merge pull request #2315 from FlightControl-Master/master
Update Airbase.lua
2025-06-15 13:15:30 +02:00
Thomas
a53763221c Update Airbase.lua
Correct afb name gor Borg al arab on Sinai
2025-06-15 13:14:05 +02:00
Thomas
83447a3fb4 Merge pull request #2314 from FlightControl-Master/master
Csar
2025-06-15 10:19:19 +02:00
Thomas
b7bac28113 Merge pull request #2313 from FlightControl-Master/Applevangelist-patch-1
Update CSAR.lua
2025-06-15 10:18:01 +02:00
Thomas
a9edb16554 Update CSAR.lua
Make static and zone mash SETs dynamic
2025-06-15 10:17:32 +02:00
Applevangelist
52cbb7202c #EASYGCICAP - more noob catches 2025-06-12 09:09:38 +02:00
Frank
f6a8317c42 Merge branch 'develop' of https://github.com/FlightControl-Master/MOOSE into develop 2025-06-10 21:58:21 +02:00
Frank
2a9a7db9b8 OPSGROUP
- Improved behaviour when mission is unpaused and groups are teleported
2025-06-10 21:58:19 +02:00
Applevangelist
3aeec78f79 Merge remote-tracking branch 'origin/master' into develop 2025-06-10 18:05:58 +02:00
Applevangelist
0aeb1fc6af #UTILS - Small fix for GetReportingName to distinguish Shark from Mainstay 2025-06-10 18:05:02 +02:00
Applevangelist
26565d7549 #EASYGCICAP - Added noob/fatfinger checks for airbase static warehouses and CAP point airwing names 2025-06-10 09:25:00 +02:00
Applevangelist
62816f217b Merge remote-tracking branch 'origin/master' into develop 2025-06-08 18:43:35 +02:00
Applevangelist
eeeeda4e5e #POINT - Offset options for smoke 2025-06-08 18:43:01 +02:00
Applevangelist
95767c5ef4 AIRBOSS - Remove useless E Messages for non-debug 2025-06-01 12:20:08 +02:00
Applevangelist
f5881eda53 AIRBOSS - Remove useless E Messages for non-debug 2025-06-01 12:19:42 +02:00
Applevangelist
fca6faa3a8 xx 2025-05-30 20:51:04 +02:00
Thomas
c1997d9f70 Merge pull request #2311 from FlightControl-Master/Applevangelist-patch-1
Update CSAR.lua
2025-05-30 18:37:50 +02:00
Thomas
bb1caa6642 Update CSAR.lua 2025-05-30 18:37:38 +02:00
Thomas
638f083729 Merge pull request #2310 from shaji-Dev/develop
CSAR Downed Pilot Queue
2025-05-30 18:36:33 +02:00
shaji
59d41cf98b - [ADDED] Removes previous downed pilot with the same player name in Ejection event
- [ADDED] `useFIFOLimitReplacement` If true, it will remove the oldest downed pilot when a new one is added, if the limit is reached (FIFO queue), otherwise does not add downed pilots when the limit is reached.
2025-05-30 16:03:01 +02:00
Applevangelist
793adafda7 Merge remote-tracking branch 'origin/master' into develop 2025-05-30 11:14:33 +02:00
Applevangelist
dd5ca93f26 CSAR Small addition 2025-05-30 11:13:50 +02:00
Thomas
0d1a7c770b Merge pull request #2309 from FlightControl-Master/master
Merge from master
2025-05-25 09:12:50 +02:00
Thomas
1889df4952 Merge pull request #2308 from shaji-Dev/master
[FIXED] Velocity is taking into account dead units for GROUP
2025-05-25 09:12:04 +02:00
shaji
7ca219748d [FIXED] Velocity is taking into account dead units for GROUP 2025-05-24 19:46:20 +02:00
Applevangelist
b3f944e82e Merge remote-tracking branch 'origin/master' into develop 2025-05-24 15:54:14 +02:00
Applevangelist
2fc16ba694 Runway text duplication 2025-05-24 15:53:43 +02:00
Thomas
432fc0ef4b Merge pull request #2307 from shaji-Dev/develop
[ADDED] `TARGET:GetObjects()` and `TARGET:GetCoordinates()` in case of SET
2025-05-24 12:50:44 +02:00
shaji
20c50c751f [ADDED] Sets target support for Auftrag STRIKE and BOMBING 2025-05-24 11:29:01 +02:00
shaji
d3b62d0260 [ADDED] TARGET:GetObjects() and TARGET:GetCoordinates() in case of SET 2025-05-24 11:18:41 +02:00
Applevangelist
d0449265c1 Merge remote-tracking branch 'origin/master' into develop 2025-05-21 10:22:16 +02:00
Applevangelist
a4feafab8e #POINT - improved IsDay() for Kola 2025-05-21 10:21:48 +02:00
Applevangelist
309eedd165 Merge remote-tracking branch 'origin/master' into develop 2025-05-21 10:05:30 +02:00
Applevangelist
997baf21a0 #CSAR fix for ADF beacons 2025-05-21 10:04:58 +02:00
Applevangelist
fa676cc750 Merge remote-tracking branch 'origin/master' into develop 2025-05-16 13:43:27 +02:00
Applevangelist
b126cc00d0 xx 2025-05-16 13:43:03 +02:00
Applevangelist
1e0c27f599 Merge remote-tracking branch 'origin/master' into develop 2025-05-16 12:00:32 +02:00
Applevangelist
09b7922b84 Small fixes 2025-05-16 11:58:40 +02:00
Applevangelist
66032d6894 #EASYGCICAP - added SetDefaultTakeOffType() 2025-05-15 18:24:26 +02:00
Applevangelist
7c98a793c7 Merge remote-tracking branch 'origin/master' into develop 2025-05-15 17:08:28 +02:00
Applevangelist
7a5b9a75f3 #AIRBASE - added Syria Marka AFB 2025-05-15 17:07:55 +02:00
Applevangelist
0ea5631955 Merge remote-tracking branch 'origin/master' into develop 2025-05-15 13:20:07 +02:00
Applevangelist
4bab2ee1de Add deprecated banner 2025-05-15 13:19:42 +02:00
Applevangelist
f5b9713639 Merge remote-tracking branch 'origin/master' into develop 2025-05-15 11:42:54 +02:00
Applevangelist
1bfb4fc4e1 Small fix 2025-05-15 11:42:27 +02:00
Applevangelist
d7defe6f7f xx 2025-05-15 11:42:05 +02:00
Applevangelist
ebb94c07b3 Small fix 2025-05-15 10:05:11 +02:00
Applevangelist
f4cdbec376 Merge remote-tracking branch 'origin/develop' into develop 2025-05-15 08:52:18 +02:00
Applevangelist
21d5a5dfac Merge remote-tracking branch 'origin/master' into develop 2025-05-15 08:52:14 +02:00
Applevangelist
f8947aab9c #MANTIS - Make DLINK caching (DEV version) configureable 2025-05-15 08:51:44 +02:00
Applevangelist
db869bcb6d #MANTIS - Make DLINK caching (DEV version) configureable 2025-05-15 08:51:30 +02:00
Thomas
36a0cfd635 Merge pull request #2306 from FlightControl-Master/master
Merge
2025-05-15 06:52:23 +02:00
Thomas
ea4a1f9ff9 Merge pull request #2305 from shaji-Dev/master
[FIXED] Kola Airbase name "Alakourtti" to "Alakurtti"
2025-05-15 06:42:07 +02:00
shaji
20406e40ca [FIXED] Kola Airbase name "Alakourtti" to "Alakurtti" 2025-05-15 01:17:55 +02:00
Applevangelist
acbcb14cba Merge remote-tracking branch 'origin/master' into develop 2025-05-12 17:51:12 +02:00
Applevangelist
3b50fee5a0 #CTLD - extract troops, check for groupname in task properties of PLAYERTASKs, so the right people rescue the correct group 2025-05-12 17:50:37 +02:00
Applevangelist
804004198b #MANTIS - Update docu 2025-05-12 17:49:25 +02:00
Thomas
67ef6c6e7b Merge pull request #2304 from FlightControl-Master/master
Nil check
2025-05-12 07:01:15 +02:00
Thomas
5b8b8a5566 Merge pull request #2303 from leka1986/master
Fix Line 77390: attempt to index local 'zonecoord' (a nil value)
2025-05-12 07:00:19 +02:00
leka1986
0468bacc0b Fix Line 77390: attempt to index local 'zonecoord' (a nil value) 2025-05-11 21:15:31 +02:00
Applevangelist
eacc43cb5a Merge remote-tracking branch 'origin/develop' into develop 2025-05-04 12:54:33 +02:00
Applevangelist
f3dcde075c Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	Moose Development/Moose/AI/AI_Formation.lua
#	Moose Development/Moose/Functional/Fox.lua
2025-05-04 12:54:27 +02:00
Thomas
7eba1349ae Merge pull request #2301 from leka1986/master
VS Code pointed out some errors, like duplicated values in tables. This is first time I do changes through VS Code, Hope for the best
2025-05-04 10:47:28 +02:00
leka1986
b6074a4795 VS Code pointed out some errors, like duplicated values in tables. This is first time I do changes through VS Code, Hope for the best 2025-05-04 10:38:44 +02:00
Thomas
615afb7cc4 Merge pull request #2300 from FlightControl-Master/master
Merge from master
2025-05-03 20:33:49 +02:00
Thomas
36c9f551d9 Merge pull request #2299 from leka1986/patch-3
Update CTLD.lua
2025-05-03 20:32:40 +02:00
leka1986
89c3f7310b Update CTLD.lua
Changed the naming from Get only to Get

and the order is Get, Get and load
Instead of Get and load, and Get only.

Changed the order on Pack and load, Pack and remove, pack only to 
Pack, Pack and load, Pack and remove.

Same goes for Drop and build, Drop only to Drop, Drop and build.

It purely subjective what one would like, so I leave it up to you. If you like it this way or the first version, you decide, then disregard this change.
2025-05-03 19:22:59 +02:00
Applevangelist
6791a0e704 Merge remote-tracking branch 'origin/master' into develop 2025-05-03 17:02:29 +02:00
Applevangelist
a6b622ed31 #CTLD - Additional features by Lekaa to drop and build one/many in one go and pack/load or get/load in one go 2025-05-03 17:01:02 +02:00
Frank
f1af3a50b8 Update Unit.lua
- GetAmmo HE shells can also be named "HESH"
2025-05-02 21:36:03 +02:00
Applevangelist
f999e45323 Merge remote-tracking branch 'origin/master' into develop 2025-05-02 10:53:29 +02:00
Applevangelist
0c90e90c18 #CSAR - fixed design issue that prevented usage of ZONE objects as MASHes 2025-05-02 10:53:02 +02:00
Frank
4747f3f48f Merge branch 'master' into develop 2025-05-01 22:11:54 +02:00
Frank
f97ef25104 Update Unit.lua 2025-05-01 22:11:43 +02:00
Thomas
e1a670185e Merge pull request #2298 from FlightControl-Master/master
CTLD - Fix issue when a ship zone is destroyed
2025-04-28 09:22:32 +02:00
Thomas
069c0aa03f Merge pull request #2297 from FlightControl-Master/Applevangelist-patch-1
Update CTLD.lua
2025-04-28 09:20:58 +02:00
Thomas
b145588ed5 Update CTLD.lua
Fix an issue when a ship is used as loading zone and the ship is destroyed
2025-04-28 09:20:04 +02:00
Applevangelist
b678e2cde1 Merge remote-tracking branch 'origin/master' into develop 2025-04-27 11:26:51 +02:00
Applevangelist
db23a0bf2b #FlightGroup - added nil check for name 2025-04-27 11:26:22 +02:00
Applevangelist
3ad60a95ce #MANTIS - Adde Gepard data, made Roland Short 2025-04-27 11:25:46 +02:00
Frank
5c3b7312c0 Update Range.lua
- Reduced smoke duration at impact coordinate to 30 seconds
2025-04-26 23:55:13 +02:00
Frank
f177d0a257 Merge branch 'master' into develop 2025-04-26 23:39:34 +02:00
Frank
ac4b620f16 COORDINATE
- Improved Smoke and Fire and Smoke functions by adding delay and duration parameters
2025-04-26 23:39:22 +02:00
Thomas
c49b56eefc Merge pull request #2296 from FlightControl-Master/master
Merge from master
2025-04-26 07:53:01 +02:00
Thomas
ccada18a6a Merge pull request #2295 from leka1986/patch-2
Update CTLD.lua
2025-04-26 07:52:01 +02:00
leka1986
1547d66327 Update CTLD.lua
Getting rid of this error,
bad argument #1 to 'find' (string expected, got nil)
2025-04-26 03:28:16 +02:00
Applevangelist
e21236655a Merge remote-tracking branch 'origin/develop' into develop 2025-04-24 14:48:17 +02:00
Applevangelist
cdad3bd058 #PLAYERTASK - make an existing marker move with the group if the group is moving around 2025-04-24 14:48:12 +02:00
Thomas
0db9c27f7e Merge pull request #2294 from FlightControl-Master/master
Merge from master
2025-04-23 14:23:04 +02:00
Thomas
8042e8bfaf Merge pull request #2293 from shaji-Dev/master
[ADDED] AIRBOSS:SetMaxSectionDistance
2025-04-23 14:21:31 +02:00
shaji
dd7b87e9cd [ADDED] AIRBOSS:SetMaxSectionDistance 2025-04-23 13:39:55 +02:00
Thomas
68a539923f Merge pull request #2292 from FlightControl-Master/master
Range os.date fix
2025-04-23 09:24:02 +02:00
Thomas
460d2768ff Merge pull request #2291 from FlightControl-Master/Applevangelist-patch-1
Update Range.lua
2025-04-23 09:03:54 +02:00
Thomas
3c74272749 Update Range.lua
#RANGE log an error if os/os.date() are not available
2025-04-23 09:00:05 +02:00
Thomas
3442725525 Merge pull request #2290 from FlightControl-Master/master
Merge from master
2025-04-23 06:29:32 +02:00
Thomas
82c409d77a Merge pull request #2289 from shaji-Dev/master
[ADDED] IsAlive condition for Unit and Group out message
2025-04-23 06:28:13 +02:00
shaji
195aac4504 [ADDED] IsAlive condition for Unit and Group out message 2025-04-22 20:57:06 +02:00
Thomas
326e27327d Merge pull request #2286 from FlightControl-Master/master
Kola airbase additions
2025-04-21 19:38:24 +02:00
Thomas
08d8f3e25f Merge pull request #2285 from shaji-Dev/master
[ADDED] New Kola airbases
2025-04-21 19:37:22 +02:00
shaji
6f72697e26 [ADDED] New Kola airbases
-- * AIRBASE.Kola.Alta
-- * AIRBASE.Kola.Sodankyla
-- * AIRBASE.Kola.Enontekio
-- * AIRBASE.Kola.Evenes
-- * AIRBASE.Kola.Hosio
2025-04-21 19:11:22 +02:00
Applevangelist
296d4b1e93 Merge remote-tracking branch 'origin/master' into develop 2025-04-20 17:49:54 +02:00
Applevangelist
0f6439cf9f #MANTIS - added C-RAM Point Defense 2025-04-20 17:49:25 +02:00
Applevangelist
9705b49dbe #PLAYERTASKMANAGER - Surfaced some functions for conflict zones 2025-04-20 15:52:30 +02:00
Applevangelist
9364579a18 #EASYGCICAP - fixed some wrongly used self.values
#OPSZONE - make check time schedule configureable
2025-04-19 17:53:07 +02:00
Frank
02a6d8f2c0 Merge branch 'master' into develop 2025-04-18 17:50:11 +02:00
Frank
2c10943cb1 Update Airbase.lua
Germany map Umlaute
2025-04-18 17:50:01 +02:00
Frank
a293c59d6d Merge branch 'master' into develop 2025-04-18 17:46:00 +02:00
Frank
544db963ea Update Airbase.lua 2025-04-18 17:45:43 +02:00
Frank
d3fd21e6da Merge branch 'master' into develop 2025-04-18 17:41:07 +02:00
Frank
207698a2dd Update Airbase.lua
- Germany map readded Umlaute in keys
2025-04-18 17:40:55 +02:00
Applevangelist
27cd90a0ce Merge remote-tracking branch 'origin/master' into develop 2025-04-18 16:02:56 +02:00
Applevangelist
d1ae2c0f5e xx 2025-04-18 16:01:55 +02:00
Applevangelist
66e6a603f1 Merge remote-tracking branch 'origin/master' into develop 2025-04-18 14:46:45 +02:00
Applevangelist
0392417189 Germany CW Bases 2025-04-18 14:46:13 +02:00
Frank
0678ad17f8 Merge branch 'master' into develop 2025-04-17 21:34:17 +02:00
Frank
be4beea9d0 Update Airbase.lua
- Removed umlauts and ß in airbase names
2025-04-17 21:34:01 +02:00
Frank
5da899138b Merge pull request #2284 from FlightControl-Master/FF/MasterDevel
Germany CW map
2025-04-17 21:19:48 +02:00
Frank
1ec1e00bde Germany CW map
- ATIS Germany map
- UTILS magnetic declination
2025-04-17 21:19:01 +02:00
Thomas
d7d46d4f1b Merge pull request #2283 from FlightControl-Master/master
Merge from master
2025-04-17 08:45:51 +02:00
Thomas
5d93b33d42 Merge pull request #2282 from shaji-Dev/master
[FIXED] Returns nil for late activated templates we use to mark paths to use in our scripts
2025-04-17 08:44:38 +02:00
shaji
b2077bfc74 [FIXED] Returns nil for late activated templates we use to mark waypoint paths to use in the scripts. 2025-04-16 19:59:13 +02:00
Applevangelist
e958ca103a #EASYGCICAP - make conflict zones setup a bit more explic 2025-04-15 11:45:49 +02:00
Applevangelist
1d9ef869a7 Merge remote-tracking branch 'origin/master' into develop 2025-04-14 12:23:37 +02:00
Applevangelist
6fdf9a649f #AIRBASE rescribe umlauts 2025-04-14 12:23:12 +02:00
Applevangelist
90c6c57449 Merge remote-tracking branch 'origin/master' into develop 2025-04-14 12:11:56 +02:00
Applevangelist
d013bbc751 #STORAGE Enum, some additions 2025-04-14 12:11:27 +02:00
Applevangelist
e0092fdba0 #AIRBASE GermanCW Map airbases 2025-04-14 11:37:45 +02:00
Thomas
ecce2eff9b Merge pull request #2281 from FlightControl-Master/master
Merge
2025-04-12 10:52:39 +02:00
Thomas
fbeada439f Merge pull request #2278 from leka1986/patch-5
Update Group.lua
2025-04-12 10:51:42 +02:00
Thomas
6c8858d2f5 Merge pull request #2280 from leka1986/patch-7
Update Set.lua
2025-04-12 10:51:00 +02:00
Thomas
e2b77878df Merge pull request #2279 from leka1986/patch-6
Update Event.lua
2025-04-12 10:50:39 +02:00
leka1986
53d7972858 Update Set.lua
Removed the Filter={},
2025-04-12 10:48:22 +02:00
leka1986
04a55e4104 Update Event.lua
Added nil checks which was causing nil. had this for a few weeks with no errors.
2025-04-12 10:44:29 +02:00
leka1986
d11acecdac Update Group.lua
Fix for the error attempt to index a nil value called from suppression
2025-04-12 10:26:34 +02:00
Applevangelist
4b23c86daa Merge remote-tracking branch 'origin/master' into develop 2025-04-09 08:16:20 +02:00
Applevangelist
49c11073e6 #MANTIS Mod data updates 2025-04-09 08:15:50 +02:00
Applevangelist
daa5caa125 Merge remote-tracking branch 'origin/master' into develop 2025-04-07 11:57:39 +02:00
Applevangelist
1a156e7e12 #CTLD - make menu build for CA a bit faster 2025-04-07 11:57:15 +02:00
Applevangelist
6fe88a6319 Merge remote-tracking branch 'origin/master' into develop 2025-04-07 10:40:58 +02:00
Applevangelist
1856754614 #Smaller Changes 2025-04-07 10:40:30 +02:00
Thomas
b9f6c1b9c7 Merge pull request #2277 from FlightControl-Master/master
Update docs-header.py
2025-04-06 16:33:05 +02:00
Thomas
6ac452ff15 Update docs-header.py 2025-04-06 16:28:19 +02:00
Applevangelist
b52176a0ff Merge remote-tracking branch 'origin/master' into develop 2025-04-06 16:19:43 +02:00
Applevangelist
d707a4775c xx 2025-04-06 16:19:12 +02:00
Thomas
ffccc31e38 Update CargoGroup.lua 2025-04-06 16:12:13 +02:00
Thomas
0405af2bde Update docs-header.py 2025-04-06 16:04:07 +02:00
Thomas
d09f0b1f6f Update classes-core.md 2025-04-06 15:47:52 +02:00
Thomas
e50e572c78 Update classes-core.md 2025-04-06 15:43:09 +02:00
Applevangelist
2e688e7da1 Merge remote-tracking branch 'origin/master' into develop 2025-04-06 15:38:55 +02:00
Applevangelist
3083599158 #CTLD - Allow CA Ground Transport 2025-04-06 15:38:26 +02:00
Applevangelist
2921f7a76b Merge remote-tracking branch 'origin/master' into develop 2025-04-03 14:22:25 +02:00
Applevangelist
b7b6c1ea19 #RADIOQUEUE - small tweak for a group when a unit dies. 2025-04-03 14:21:58 +02:00
Applevangelist
8a185c352e Merge remote-tracking branch 'origin/master' into develop 2025-04-03 11:49:30 +02:00
Applevangelist
5b107ce2da #CONTROLLABLE:CommandSmokeOnOff(OnOff, Delay) added 2025-04-03 11:48:53 +02:00
Thomas
5c1e342a79 Update classes-core.md 2025-04-03 09:33:49 +02:00
Applevangelist
3fc8f52796 Merge remote-tracking branch 'origin/master' into develop 2025-04-03 09:29:57 +02:00
Applevangelist
ddf33da787 #DYNAMICCARGO - Hover / Sling checks 2025-04-03 09:29:19 +02:00
Thomas
e7cee4d97b Merge pull request #2276 from FlightControl-Master/master
Small fixes
2025-04-02 16:13:50 +02:00
Thomas
b0a192a767 Update DynamicCargo.lua
small fix
2025-04-02 16:12:06 +02:00
Thomas
986c340211 Merge pull request #2275 from FlightControl-Master/Applevangelist-patch-1
Update classes-core.md
2025-04-02 09:54:54 +02:00
Thomas
2109537f86 Update classes-core.md
fix
2025-04-02 09:54:20 +02:00
Thomas
bad9d1ea92 Merge pull request #2274 from FlightControl-Master/master
Fix SpawnStatic
2025-04-02 09:45:44 +02:00
Thomas
690db7f12f Merge pull request #2273 from FlightControl-Master/Applevangelist-SpawnStatic-1
Update SpawnStatic.lua
2025-04-02 09:43:04 +02:00
Thomas
4f3fd06cc9 Update SpawnStatic.lua
Restored previous version as overwritten
2025-04-02 09:42:02 +02:00
Applevangelist
f5b1050086 Merge remote-tracking branch 'origin/master' into develop 2025-04-01 15:27:55 +02:00
Applevangelist
4074023ed3 #DYNAMICCARGO - enhance checks for unloading cargo from hovering Hooks 2025-04-01 15:27:23 +02:00
Applevangelist
f729b1d358 Merge remote-tracking branch 'origin/master' into develop 2025-04-01 14:13:42 +02:00
Applevangelist
6c00b0c7eb #POINT - some catches for POINT_VEC2 behaviour 2025-04-01 14:13:14 +02:00
Applevangelist
5adefe6f7b Merge remote-tracking branch 'origin/master' into develop 2025-04-01 13:18:55 +02:00
Applevangelist
76dc0d690a #POINT - Removal of References to legacy POINT_VEC2/3 classes 2025-04-01 13:17:48 +02:00
Thomas
13c16b8674 Merge pull request #2272 from shaji-Dev/develop
[Fixed] Parameter #1 (unit name) is incorrect
2025-03-31 14:05:41 +02:00
Thomas
222722225e Update OpsGroup.lua
Better make this a unit and alive check
2025-03-31 14:04:07 +02:00
shaji
82e1dcfc04 [Fixed] Parameter #1 (unit name) is incorrect 2025-03-31 13:11:56 +02:00
Thomas
c26220d1fd Merge pull request #2271 from FlightControl-Master/master
DynamicCargo small fixes
2025-03-31 12:32:55 +02:00
Thomas
d783f7be99 Merge pull request #2270 from FlightControl-Master/Applevangelist-patch-1
Update DynamicCargo.lua
2025-03-31 12:31:52 +02:00
Thomas
b66e91b11f Update DynamicCargo.lua
#DYNAMICCARGO small fixes
2025-03-31 12:31:23 +02:00
115 changed files with 6656 additions and 3041 deletions

View File

@@ -1953,7 +1953,7 @@ local function refct_from_id(id) -- refct = refct_from_id(CTypeID)
unsigned = refct.unsigned, unsigned = refct.unsigned,
size = bit.band(bit.rshift(ctype.info, 16), 127), size = bit.band(bit.rshift(ctype.info, 16), 127),
} }
refct.bool, refct.const, refct.volatile, refct.unsigned = nil refct.bool, refct.const, refct.volatile, refct.unsigned = nil, nil, nil, nil
end end
if CT[4] then -- Merge sibling attributes onto this type. if CT[4] then -- Merge sibling attributes onto this type.

View File

@@ -18,6 +18,8 @@
--- The AI_A2A_CAP class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group} --- The AI_A2A_CAP class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone. -- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ![Process](..\Presentations\AI_CAP\Dia3.JPG) -- ![Process](..\Presentations\AI_CAP\Dia3.JPG)
-- --
-- The AI_A2A_CAP is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_CAP process can be started using the **Start** event. -- The AI_A2A_CAP is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_CAP process can be started using the **Start** event.

View File

@@ -33,6 +33,8 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- # QUICK START GUIDE -- # QUICK START GUIDE
-- --
-- There are basically two classes available to model an A2A defense system. -- There are basically two classes available to model an A2A defense system.

View File

@@ -19,6 +19,8 @@
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- The AI_A2A_GCI is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_GCI process can be started using the **Start** event. -- The AI_A2A_GCI is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_GCI process can be started using the **Start** event.
-- --
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. -- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.

View File

@@ -15,6 +15,8 @@
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}. --- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ![Process](..\Presentations\AI_PATROL\Dia3.JPG) -- ![Process](..\Presentations\AI_PATROL\Dia3.JPG)
-- --
-- The AI_A2A_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_PATROL process can be started using the **Start** event. -- The AI_A2A_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_PATROL process can be started using the **Start** event.

View File

@@ -16,6 +16,8 @@
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- # Developer Note -- # Developer Note
-- --
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE

View File

@@ -18,6 +18,8 @@
-- --
-- # Developer Note -- # Developer Note
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --

View File

@@ -36,6 +36,8 @@
-- --
-- # QUICK START GUIDE -- # QUICK START GUIDE
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- The following class is available to model an A2G defense system. -- The following class is available to model an A2G defense system.
-- --
-- AI_A2G_DISPATCHER is the main A2G defense class that models the A2G defense system. -- AI_A2G_DISPATCHER is the main A2G defense class that models the A2G defense system.

View File

@@ -19,6 +19,8 @@
--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders. --- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- The AI_A2G_SEAD is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_SEAD process can be started using the **Start** event. -- The AI_A2G_SEAD is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_SEAD process can be started using the **Start** event.
-- --
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. -- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.

View File

@@ -15,6 +15,7 @@
--- The AI_AIR class implements the core functions to operate an AI @{Wrapper.Group}. --- The AI_AIR class implements the core functions to operate an AI @{Wrapper.Group}.
-- --
-- ![Banner Image](..\Images\deprecated.png)
-- --
-- # 1) AI_AIR constructor -- # 1) AI_AIR constructor
-- --
@@ -657,8 +658,8 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
--- Create a route point of type air. --- Create a route point of type air.
local FromRTBRoutePoint = FromCoord:WaypointAir( local FromRTBRoutePoint = FromCoord:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
RTBSpeed, RTBSpeed,
true true
) )
@@ -666,8 +667,8 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
--- Create a route point of type air. --- Create a route point of type air.
local ToRTBRoutePoint = ToAirbaseCoord:WaypointAir( local ToRTBRoutePoint = ToAirbaseCoord:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
RTBSpeed, RTBSpeed,
true true
) )
@@ -761,10 +762,10 @@ function AI_AIR:onafterRefuel( AIGroup, From, Event, To )
local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
--- Create a route point of type air. --- Create a route point of type air.
local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true) local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToRefuelSpeed, true)
--- Create a route point of type air. NOT used! --- Create a route point of type air. NOT used!
local ToRefuelRoutePoint = Tanker:GetCoordinate():WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true) local ToRefuelRoutePoint = Tanker:GetCoordinate():WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToRefuelSpeed, true)
self:F( { ToRefuelSpeed = ToRefuelSpeed } ) self:F( { ToRefuelSpeed = ToRefuelSpeed } )

View File

@@ -36,6 +36,8 @@
-- --
-- # QUICK START GUIDE -- # QUICK START GUIDE
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- The following class is available to model an AIR defense system. -- The following class is available to model an AIR defense system.
-- --
-- AI_AIR_DISPATCHER is the main AIR defense class that models the AIR defense system. -- AI_AIR_DISPATCHER is the main AIR defense class that models the AIR defense system.

View File

@@ -13,12 +13,14 @@
-- @type AI_AIR_ENGAGE --- @type AI_AIR_ENGAGE
-- @extends AI.AI_AIR#AI_AIR -- @extends AI.AI_AIR#AI_AIR
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- The AI_AIR_ENGAGE is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_ENGAGE process can be started using the **Start** event. -- The AI_AIR_ENGAGE is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_ENGAGE process can be started using the **Start** event.
-- --
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. -- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
@@ -453,7 +455,7 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
--- Calculate the target route point. --- Calculate the target route point.
local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true) local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
EngageRoute[#EngageRoute+1] = FromWP EngageRoute[#EngageRoute+1] = FromWP
@@ -462,7 +464,7 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) ) local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ) local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true) local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
EngageRoute[#EngageRoute+1] = ToWP EngageRoute[#EngageRoute+1] = ToWP
@@ -536,7 +538,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
local EngageRoute = {} local EngageRoute = {}
local AttackTasks = {} local AttackTasks = {}
local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true) local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
EngageRoute[#EngageRoute+1] = FromWP EngageRoute[#EngageRoute+1] = FromWP
self:SetTargetDistance( TargetCoord ) -- For RTB status check self:SetTargetDistance( TargetCoord ) -- For RTB status check
@@ -544,7 +546,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) ) local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ) local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true) local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
EngageRoute[#EngageRoute+1] = ToWP EngageRoute[#EngageRoute+1] = ToWP
-- TODO: A factor of * 3 this way too low. This causes the AI NOT to engage until very close or even merged sometimes. Some A2A missiles have a much longer range! Needs more frequent updates of the task! -- TODO: A factor of * 3 this way too low. This causes the AI NOT to engage until very close or even merged sometimes. Some A2A missiles have a much longer range! Needs more frequent updates of the task!

View File

@@ -15,6 +15,8 @@
--- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} --- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group}
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone. -- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ![Process](..\Presentations\AI_CAP\Dia3.JPG) -- ![Process](..\Presentations\AI_CAP\Dia3.JPG)
-- --
-- The AI_AIR_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_PATROL process can be started using the **Start** event. -- The AI_AIR_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_PATROL process can be started using the **Start** event.
@@ -309,7 +311,7 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
local speedkmh=ToTargetSpeed local speedkmh=ToTargetSpeed
local FromWP = CurrentCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true) local FromWP = CurrentCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToTargetSpeed, true)
PatrolRoute[#PatrolRoute+1] = FromWP PatrolRoute[#PatrolRoute+1] = FromWP
if self.racetrack then if self.racetrack then
@@ -359,7 +361,7 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
else else
--- Create a route point of type air. --- Create a route point of type air.
local ToWP = ToTargetCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true) local ToWP = ToTargetCoord:WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToTargetSpeed, true)
PatrolRoute[#PatrolRoute+1] = ToWP PatrolRoute[#PatrolRoute+1] = ToWP
local Tasks = {} local Tasks = {}

View File

@@ -13,7 +13,7 @@
-- @type AI_AIR_SQUADRON --- @type AI_AIR_SQUADRON
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@@ -21,6 +21,8 @@
-- --
-- # Developer Note -- # Developer Note
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --

View File

@@ -38,6 +38,8 @@
--- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}. --- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. -- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
-- --
-- ![HoldAndEngage](..\Presentations\AI_BAI\Dia3.JPG) -- ![HoldAndEngage](..\Presentations\AI_BAI\Dia3.JPG)
@@ -521,12 +523,12 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1). --DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude() local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir( local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
self.EngageSpeed, self.EngageSpeed,
true true
) )
@@ -577,13 +579,13 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
self:T2( ToTargetVec2 ) self:T2( ToTargetVec2 )
--- Obtain a 3D @{Point} from the 2D point + altitude. --- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y ) local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
--- Create a route point of type air. --- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir( local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
self.EngageSpeed, self.EngageSpeed,
true true
) )

View File

@@ -33,8 +33,9 @@
-- @field Wrapper.Group#GROUP Test -- @field Wrapper.Group#GROUP Test
-- @extends Core.Fsm#FSM_SET -- @extends Core.Fsm#FSM_SET
--- ![Banner Image](..\Images\deprecated.png)
--- Monitors and manages as many replacement AI groups as there are --
-- Monitors and manages as many replacement AI groups as there are
-- CLIENTS in a SET\_CLIENT collection, which are not occupied by human players. -- CLIENTS in a SET\_CLIENT collection, which are not occupied by human players.
-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions. -- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.
-- --
@@ -220,16 +221,9 @@ function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
AIGroup:MessageToRed( "Returning to home base ...", 30 ) AIGroup:MessageToRed( "Returning to home base ...", 30 )
else else
-- Okay, we need to send this Group back to the nearest base of the Coalition of the AI. -- Okay, we need to send this Group back to the nearest base of the Coalition of the AI.
--TODO: i need to rework the POINT_VEC2 thing. local PointVec2 = COORDINATE:New(AIGroup:GetVec2().x, 0, AIGroup:GetVec2().y)
local PointVec2 = POINT_VEC2:New( AIGroup:GetVec2().x, AIGroup:GetVec2().y )
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 ) local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
self:T( ClosestAirbase.AirbaseName ) self:T( ClosestAirbase.AirbaseName )
--[[
AIGroup:MessageToRed( "Returning to " .. ClosestAirbase:GetName().. " ...", 30 )
local RTBRoute = AIGroup:RouteReturnToAirbase( ClosestAirbase )
AIGroupTemplate.route = RTBRoute
AIGroup:Respawn( AIGroupTemplate )
]]
AIGroup:RouteRTB(ClosestAirbase) AIGroup:RouteRTB(ClosestAirbase)
end end

View File

@@ -39,6 +39,8 @@
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group} --- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone. -- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ![Process](..\Presentations\AI_CAP\Dia3.JPG) -- ![Process](..\Presentations\AI_CAP\Dia3.JPG)
-- --
-- The AI_CAP_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event. -- The AI_CAP_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
@@ -423,12 +425,12 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1). --DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude() local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir( local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
ToEngageZoneSpeed, ToEngageZoneSpeed,
true true
) )
@@ -445,13 +447,13 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
--- Obtain a 3D @{Point} from the 2D point + altitude. --- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
--- Create a route point of type air. --- Create a route point of type air.
local ToPatrolRoutePoint = ToTargetPointVec3:WaypointAir( local ToPatrolRoutePoint = ToTargetPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
ToTargetSpeed, ToTargetSpeed,
true true
) )

View File

@@ -38,6 +38,9 @@
-- @extends AI.AI_Patrol#AI_PATROL_ZONE -- @extends AI.AI_Patrol#AI_PATROL_ZONE
--- Implements the core functions to provide Close Air Support in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}. --- Implements the core functions to provide Close Air Support in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
--
-- ![Banner Image](..\Images\deprecated.png)
--
-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. -- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
-- --
-- ![HoldAndEngage](..\Presentations\AI_CAS\Dia3.JPG) -- ![HoldAndEngage](..\Presentations\AI_CAS\Dia3.JPG)
@@ -465,12 +468,12 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1). --DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude() local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir( local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
self.EngageSpeed, self.EngageSpeed,
true true
) )
@@ -507,13 +510,13 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
self:T2( ToTargetVec2 ) self:T2( ToTargetVec2 )
--- Obtain a 3D @{Point} from the 2D point + altitude. --- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y ) local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
--- Create a route point of type air. --- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir( local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
self.EngageSpeed, self.EngageSpeed,
true true
) )

View File

@@ -9,12 +9,14 @@
-- @module AI.AI_Cargo -- @module AI.AI_Cargo
-- @image Cargo.JPG -- @image Cargo.JPG
-- @type AI_CARGO --- @type AI_CARGO
-- @extends Core.Fsm#FSM_CONTROLLABLE -- @extends Core.Fsm#FSM_CONTROLLABLE
--- Base class for the dynamic cargo handling capability for AI groups. --- Base class for the dynamic cargo handling capability for AI groups.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Carriers can be mobilized to intelligently transport infantry and other cargo within the simulation. -- Carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI_CARGO module uses the @{Cargo.Cargo} capabilities within the MOOSE framework. -- The AI_CARGO module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI_CARGO object recognize the cargo. -- CARGO derived objects must be declared within the mission to make the AI_CARGO object recognize the cargo.

View File

@@ -15,6 +15,8 @@
--- Brings a dynamic cargo handling capability for an AI vehicle group. --- Brings a dynamic cargo handling capability for an AI vehicle group.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Armoured Personnel Carriers (APC), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation. -- Armoured Personnel Carriers (APC), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- --
-- The AI_CARGO_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework. -- The AI_CARGO_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.

View File

@@ -15,6 +15,8 @@
--- Brings a dynamic cargo handling capability for an AI airplane group. --- Brings a dynamic cargo handling capability for an AI airplane group.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Airplane carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation between airbases. -- Airplane carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation between airbases.
-- --
-- The AI_CARGO_AIRPLANE module uses the @{Cargo.Cargo} capabilities within the MOOSE framework. -- The AI_CARGO_AIRPLANE module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
@@ -440,7 +442,7 @@ function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed, Height, Uncontrolled
-- To point. -- To point.
local AirbasePointVec2 = Airbase:GetPointVec2() local AirbasePointVec2 = Airbase:GetPointVec2()
local ToWaypoint = AirbasePointVec2:WaypointAir(POINT_VEC3.RoutePointAltType.BARO, "Land", "Landing", Speed or Airplane:GetSpeedMax()*0.8, true, Airbase) local ToWaypoint = AirbasePointVec2:WaypointAir(COORDINATE.WaypointAltType.BARO, "Land", "Landing", Speed or Airplane:GetSpeedMax()*0.8, true, Airbase)
--ToWaypoint["airdromeId"] = Airbase:GetID() --ToWaypoint["airdromeId"] = Airbase:GetID()
--ToWaypoint["speed_locked"] = true --ToWaypoint["speed_locked"] = true

View File

@@ -22,6 +22,8 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- # The dispatcher concept. -- # The dispatcher concept.
-- --
-- Carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation. -- Carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.

View File

@@ -36,6 +36,8 @@
--- A dynamic cargo transportation capability for AI groups. --- A dynamic cargo transportation capability for AI groups.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Armoured Personnel APCs (APC), Trucks, Jeeps and other carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation. -- Armoured Personnel APCs (APC), Trucks, Jeeps and other carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- --
-- The AI_CARGO_DISPATCHER_APC module is derived from the AI_CARGO_DISPATCHER module. -- The AI_CARGO_DISPATCHER_APC module is derived from the AI_CARGO_DISPATCHER module.

View File

@@ -30,6 +30,8 @@
--- Brings a dynamic cargo handling capability for AI groups. --- Brings a dynamic cargo handling capability for AI groups.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Airplanes can be mobilized to intelligently transport infantry and other cargo within the simulation. -- Airplanes can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- --
-- The AI_CARGO_DISPATCHER_AIRPLANE module is derived from the AI_CARGO_DISPATCHER module. -- The AI_CARGO_DISPATCHER_AIRPLANE module is derived from the AI_CARGO_DISPATCHER module.

View File

@@ -31,6 +31,8 @@
--- A dynamic cargo handling capability for AI helicopter groups. --- A dynamic cargo handling capability for AI helicopter groups.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation. -- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- --
-- --

View File

@@ -29,6 +29,8 @@
--- A dynamic cargo transportation capability for AI groups. --- A dynamic cargo transportation capability for AI groups.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Naval vessels can be mobilized to semi-intelligently transport cargo within the simulation. -- Naval vessels can be mobilized to semi-intelligently transport cargo within the simulation.
-- --
-- The AI_CARGO_DISPATCHER_SHIP module is derived from the AI_CARGO_DISPATCHER module. -- The AI_CARGO_DISPATCHER_SHIP module is derived from the AI_CARGO_DISPATCHER module.

View File

@@ -15,6 +15,8 @@
--- Brings a dynamic cargo handling capability for an AI helicopter group. --- Brings a dynamic cargo handling capability for an AI helicopter group.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Helicopter carriers can be mobilized to intelligently transport infantry and other cargo within the simulation. -- Helicopter carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- --
-- The AI_CARGO_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework. -- The AI_CARGO_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
@@ -367,8 +369,8 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
-- local CoordinateFrom = Helicopter:GetCoordinate() -- local CoordinateFrom = Helicopter:GetCoordinate()
-- local WaypointFrom = CoordinateFrom:WaypointAir( -- local WaypointFrom = CoordinateFrom:WaypointAir(
-- "RADIO", -- "RADIO",
-- POINT_VEC3.RoutePointType.TurningPoint, -- COORDINATE.WaypointType.TurningPoint,
-- POINT_VEC3.RoutePointAction.TurningPoint, -- COORDINATE.WaypointAction.TurningPoint,
-- Speed, -- Speed,
-- true -- true
-- ) -- )
@@ -380,8 +382,8 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
local WaypointTo = CoordinateTo:WaypointAir( local WaypointTo = CoordinateTo:WaypointAir(
"RADIO", "RADIO",
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
50, 50,
true true
) )
@@ -427,7 +429,7 @@ function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordina
local landheight = CoordinateTo:GetLandHeight() -- get target height local landheight = CoordinateTo:GetLandHeight() -- get target height
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, 50, true) local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, 50, true)
Route[#Route+1] = WaypointTo Route[#Route+1] = WaypointTo
local Tasks = {} local Tasks = {}
@@ -496,14 +498,14 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin
local CoordinateFrom = Helicopter:GetCoordinate() local CoordinateFrom = Helicopter:GetCoordinate()
--- Create a route point of type air. --- Create a route point of type air.
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true) local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
--- Create a route point of type air. --- Create a route point of type air.
local CoordinateTo = Coordinate local CoordinateTo = Coordinate
local landheight = CoordinateTo:GetLandHeight() -- get target height local landheight = CoordinateTo:GetLandHeight() -- get target height
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint,_speed, true) local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint,_speed, true)
Route[#Route+1] = WaypointFrom Route[#Route+1] = WaypointFrom
Route[#Route+1] = WaypointTo Route[#Route+1] = WaypointTo
@@ -563,7 +565,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
--- Create a route point of type air. --- Create a route point of type air.
local CoordinateFrom = Helicopter:GetCoordinate() local CoordinateFrom = Helicopter:GetCoordinate()
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true) local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
Route[#Route+1] = WaypointFrom Route[#Route+1] = WaypointFrom
Route[#Route+1] = WaypointFrom Route[#Route+1] = WaypointFrom
@@ -573,7 +575,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
local landheight = CoordinateTo:GetLandHeight() -- get target height local landheight = CoordinateTo:GetLandHeight() -- get target height
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true) local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
Route[#Route+1] = WaypointTo Route[#Route+1] = WaypointTo
Route[#Route+1] = WaypointTo Route[#Route+1] = WaypointTo
@@ -631,7 +633,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
--- Create a route point of type air. --- Create a route point of type air.
local CoordinateFrom = Helicopter:GetCoordinate() local CoordinateFrom = Helicopter:GetCoordinate()
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, Speed, true) local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true)
Route[#Route+1] = WaypointFrom Route[#Route+1] = WaypointFrom
--- Create a route point of type air. --- Create a route point of type air.
@@ -639,7 +641,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
local landheight = CoordinateTo:GetLandHeight() -- get target height local landheight = CoordinateTo:GetLandHeight() -- get target height
CoordinateTo.y = landheight + Height -- flight height should be 50m above ground CoordinateTo.y = landheight + Height -- flight height should be 50m above ground
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, Speed, true) local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true)
Route[#Route+1] = WaypointTo Route[#Route+1] = WaypointTo

View File

@@ -14,6 +14,8 @@
--- Brings a dynamic cargo handling capability for an AI naval group. --- Brings a dynamic cargo handling capability for an AI naval group.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Naval ships can be utilized to transport cargo around the map following naval shipping lanes. -- Naval ships can be utilized to transport cargo around the map following naval shipping lanes.
-- The AI_CARGO_SHIP class uses the @{Cargo.Cargo} capabilities within the MOOSE framework. -- The AI_CARGO_SHIP class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
-- @{Cargo.Cargo} must be declared within the mission or warehouse to make the AI_CARGO_SHIP recognize the cargo. -- @{Cargo.Cargo} must be declared within the mission or warehouse to make the AI_CARGO_SHIP recognize the cargo.

View File

@@ -25,6 +25,8 @@
-- --
-- Allows you to interact with escorting AI on your flight and take the lead. -- Allows you to interact with escorting AI on your flight and take the lead.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10). -- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
-- --
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes. -- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.

View File

@@ -23,6 +23,8 @@
-- --
-- # Developer Note -- # Developer Note
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --

View File

@@ -21,6 +21,8 @@
--- Models the assignment of AI escorts to player flights upon request using the radio menu. --- Models the assignment of AI escorts to player flights upon request using the radio menu.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- # Developer Note -- # Developer Note
-- --
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE

View File

@@ -25,6 +25,8 @@
-- --
-- Allows you to interact with escorting AI on your flight and take the lead. -- Allows you to interact with escorting AI on your flight and take the lead.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10). -- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
-- --
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes. -- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.

View File

@@ -41,6 +41,8 @@
--- Build large formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader. --- Build large formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- AI_FORMATION makes AI @{Wrapper.Group#GROUP}s fly in formation of various compositions. -- AI_FORMATION makes AI @{Wrapper.Group#GROUP}s fly in formation of various compositions.
-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!! -- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
-- The purpose of the class is to: -- The purpose of the class is to:
@@ -725,7 +727,7 @@ function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, X
for FollowID, FollowGroup in pairs( FollowSet ) do for FollowID, FollowGroup in pairs( FollowSet ) do
local PointVec3 = POINT_VEC3:New() local PointVec3 = COORDINATE:New()
PointVec3:SetX( XStart + i * XSpace ) PointVec3:SetX( XStart + i * XSpace )
PointVec3:SetY( YStart + i * YSpace ) PointVec3:SetY( YStart + i * YSpace )
PointVec3:SetZ( ZStart + i * ZSpace ) PointVec3:SetZ( ZStart + i * ZSpace )
@@ -877,7 +879,7 @@ function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event ,
for FollowID, FollowGroup in pairs( FollowSet ) do for FollowID, FollowGroup in pairs( FollowSet ) do
local PointVec3 = POINT_VEC3:New() local PointVec3 = COORDINATE:New()
local Side = ( i % 2 == 0 ) and 1 or -1 local Side = ( i % 2 == 0 ) and 1 or -1
local Row = i / 2 + 1 local Row = i / 2 + 1
@@ -936,7 +938,7 @@ function AI_FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XS
for FollowID, FollowGroup in pairs( FollowSet ) do for FollowID, FollowGroup in pairs( FollowSet ) do
local PointVec3 = POINT_VEC3:New() local PointVec3 = COORDINATE:New()
local ZIndex = i % ZLevels local ZIndex = i % ZLevels
local XIndex = math.floor( i / ZLevels ) local XIndex = math.floor( i / ZLevels )

View File

@@ -48,6 +48,8 @@
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}. --- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ![Process](..\Presentations\AI_PATROL\Dia3.JPG) -- ![Process](..\Presentations\AI_PATROL\Dia3.JPG)
-- --
-- The AI_PATROL_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event. -- The AI_PATROL_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
@@ -751,12 +753,12 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
if not CurrentVec2 then return end if not CurrentVec2 then return end
--Done: Create GetAltitude function for GROUP, and delete GetUnit(1). --Done: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude() local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir( local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TakeOffParking, COORDINATE.WaypointType.TakeOffParking,
POINT_VEC3.RoutePointAction.FromParkingArea, COORDINATE.WaypointAction.FromParkingArea,
ToPatrolZoneSpeed, ToPatrolZoneSpeed,
true true
) )
@@ -767,12 +769,12 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
if not CurrentVec2 then return end if not CurrentVec2 then return end
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1). --DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude() local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir( local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
ToPatrolZoneSpeed, ToPatrolZoneSpeed,
true true
) )
@@ -792,13 +794,13 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
--- Obtain a 3D @{Point} from the 2D point + altitude. --- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
--- Create a route point of type air. --- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir( local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
ToTargetSpeed, ToTargetSpeed,
true true
) )
@@ -890,12 +892,12 @@ function AI_PATROL_ZONE:onafterRTB()
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1). --DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
--local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() --local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
local CurrentAltitude = self.Controllable:GetAltitude() local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir( local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType, self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, COORDINATE.WaypointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, COORDINATE.WaypointAction.TurningPoint,
ToPatrolZoneSpeed, ToPatrolZoneSpeed,
true true
) )

View File

@@ -1,6 +1,6 @@
--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occurring on UNITs. --- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occurring on UNITs.
-- --
-- ![Banner Image](..\Presentations\ACT_ACCOUNT\Dia1.JPG) -- ![Banner Image](..\Images\deprecated.png)
-- --
-- === -- ===
-- --
@@ -11,6 +11,8 @@ do -- ACT_ACCOUNT
--- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS} --- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS}
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ## ACT_ACCOUNT state machine: -- ## ACT_ACCOUNT state machine:
-- --
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur. -- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
@@ -133,7 +135,7 @@ do -- ACT_ACCOUNT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
function ACT_ACCOUNT:onafterEvent( ProcessUnit, From, Event, To, Event ) function ACT_ACCOUNT:onafterEvent( ProcessUnit, From, Event, To )
self:__NoMore( 1 ) self:__NoMore( 1 )
end end

View File

@@ -2,6 +2,8 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS} -- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
-- --
-- ## ACT_ASSIGN state machine: -- ## ACT_ASSIGN state machine:

View File

@@ -1,5 +1,6 @@
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones. --- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
-- --
-- ![Banner Image](..\Images\deprecated.png)
-- ## ACT_ASSIST state machine: -- ## ACT_ASSIST state machine:
-- --
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur. -- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.

View File

@@ -2,6 +2,8 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS} -- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS}
-- --
-- ## ACT_ROUTE state machine: -- ## ACT_ROUTE state machine:

View File

@@ -2,6 +2,8 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- # 1) MOOSE Cargo System. -- # 1) MOOSE Cargo System.
-- --
-- #### Those who have used the mission editor, know that the DCS mission editor provides cargo facilities. -- #### Those who have used the mission editor, know that the DCS mission editor provides cargo facilities.
@@ -275,14 +277,14 @@
-- The cargo must be in the **Loaded** state. -- The cargo must be in the **Loaded** state.
-- @function [parent=#CARGO] UnBoard -- @function [parent=#CARGO] UnBoard
-- @param #CARGO self -- @param #CARGO self
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location. -- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
--- UnBoards the cargo to a Carrier. The event will create a movement (= running or driving) of the cargo from the Carrier. --- UnBoards the cargo to a Carrier. The event will create a movement (= running or driving) of the cargo from the Carrier.
-- The cargo must be in the **Loaded** state. -- The cargo must be in the **Loaded** state.
-- @function [parent=#CARGO] __UnBoard -- @function [parent=#CARGO] __UnBoard
-- @param #CARGO self -- @param #CARGO self
-- @param #number DelaySeconds The amount of seconds to delay the action. -- @param #number DelaySeconds The amount of seconds to delay the action.
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location. -- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
-- Load -- Load
@@ -307,14 +309,14 @@
-- The cargo must be in the **Loaded** state. -- The cargo must be in the **Loaded** state.
-- @function [parent=#CARGO] UnLoad -- @function [parent=#CARGO] UnLoad
-- @param #CARGO self -- @param #CARGO self
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location. -- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
--- UnLoads the cargo to a Carrier. The event will unload the cargo from the Carrier. There will be no movement simulated of the cargo loading. --- UnLoads the cargo to a Carrier. The event will unload the cargo from the Carrier. There will be no movement simulated of the cargo loading.
-- The cargo must be in the **Loaded** state. -- The cargo must be in the **Loaded** state.
-- @function [parent=#CARGO] __UnLoad -- @function [parent=#CARGO] __UnLoad
-- @param #CARGO self -- @param #CARGO self
-- @param #number DelaySeconds The amount of seconds to delay the action. -- @param #number DelaySeconds The amount of seconds to delay the action.
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location. -- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
-- State Transition Functions -- State Transition Functions
@@ -467,7 +469,7 @@ do -- CARGO
self.Type = Type self.Type = Type
self.Name = Name self.Name = Name
self.Weight = Weight or 0 self.Weight = Weight or 0
self.CargoObject = nil self.CargoObject = nil -- Wrapper.Group#GROUP
self.CargoCarrier = nil -- Wrapper.Client#CLIENT self.CargoCarrier = nil -- Wrapper.Client#CLIENT
self.Representable = false self.Representable = false
self.Slingloadable = false self.Slingloadable = false
@@ -897,7 +899,7 @@ do -- CARGO
--- Get the current PointVec2 of the cargo. --- Get the current PointVec2 of the cargo.
-- @param #CARGO self -- @param #CARGO self
-- @return Core.Point#POINT_VEC2 -- @return Core.Point#COORDINATE
function CARGO:GetPointVec2() function CARGO:GetPointVec2()
return self.CargoObject:GetPointVec2() return self.CargoObject:GetPointVec2()
end end
@@ -1094,7 +1096,7 @@ do -- CARGO_REPRESENTABLE
--- Route a cargo unit to a PointVec2. --- Route a cargo unit to a PointVec2.
-- @param #CARGO_REPRESENTABLE self -- @param #CARGO_REPRESENTABLE self
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#COORDINATE ToPointVec2
-- @param #number Speed -- @param #number Speed
-- @return #CARGO_REPRESENTABLE -- @return #CARGO_REPRESENTABLE
function CARGO_REPRESENTABLE:RouteTo( ToPointVec2, Speed ) function CARGO_REPRESENTABLE:RouteTo( ToPointVec2, Speed )

View File

@@ -22,6 +22,9 @@ do -- CARGO_CRATE
-- @type CARGO_CRATE -- @type CARGO_CRATE
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE -- @extends Cargo.Cargo#CARGO_REPRESENTABLE
---
-- ![Banner Image](..\Images\deprecated.png)
--
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier. --- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers. -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers.
-- --
@@ -114,7 +117,7 @@ do -- CARGO_CRATE
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 -- @param Core.Point#COORDINATE
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 ) function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
--self:T( { ToPointVec2, From, Event, To } ) --self:T( { ToPointVec2, From, Event, To } )

View File

@@ -22,9 +22,12 @@ do -- CARGO_GROUP
--- @type CARGO_GROUP --- @type CARGO_GROUP
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects. -- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
-- @field #string GroupName The name of the CargoGroup. -- @field #string GroupName The name of the CargoGroup.
-- @field Wrapper.Group#GROUÜ CargoCarrier The carrier group.
-- @extends Cargo.Cargo#CARGO_REPORTABLE -- @extends Cargo.Cargo#CARGO_REPORTABLE
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator. --- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
--
-- ![Banner Image](..\Images\deprecated.png)
-- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers. -- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers.
-- --
-- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo: -- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo:
@@ -410,7 +413,7 @@ do -- CARGO_GROUP
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... ) function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
self:T( {From, Event, To, ToPointVec2, NearRadius } ) self:T( {From, Event, To, ToPointVec2, NearRadius } )
@@ -453,7 +456,7 @@ do -- CARGO_GROUP
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
--self:T( { From, Event, To, ToPointVec2, NearRadius } ) --self:T( { From, Event, To, ToPointVec2, NearRadius } )
@@ -491,7 +494,7 @@ do -- CARGO_GROUP
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#COORDINATE ToPointVec2
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... ) function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
--self:T( { From, Event, To, ToPointVec2 } ) --self:T( { From, Event, To, ToPointVec2 } )
@@ -771,3 +774,4 @@ do -- CARGO_GROUP
end -- CARGO_GROUP end -- CARGO_GROUP

View File

@@ -32,6 +32,8 @@ do -- CARGO_SLINGLOAD
-- --
-- # Developer Note -- # Developer Note
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --

View File

@@ -30,6 +30,8 @@ do -- CARGO_UNIT
-- --
-- # Developer Note -- # Developer Note
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
@@ -72,7 +74,7 @@ do -- CARGO_UNIT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius (optional) Defaut 25 m. -- @param #number NearRadius (optional) Defaut 25 m.
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius ) function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:T( { From, Event, To, ToPointVec2, NearRadius } ) self:T( { From, Event, To, ToPointVec2, NearRadius } )
@@ -145,7 +147,7 @@ do -- CARGO_UNIT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius (optional) Defaut 100 m. -- @param #number NearRadius (optional) Defaut 100 m.
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius ) function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:T( { From, Event, To, ToPointVec2, NearRadius } ) self:T( { From, Event, To, ToPointVec2, NearRadius } )
@@ -171,7 +173,7 @@ do -- CARGO_UNIT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius (optional) Defaut 100 m. -- @param #number NearRadius (optional) Defaut 100 m.
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius ) function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:T( { From, Event, To, ToPointVec2, NearRadius } ) self:T( { From, Event, To, ToPointVec2, NearRadius } )
@@ -197,7 +199,7 @@ do -- CARGO_UNIT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 -- @param Core.Point#COORDINATE
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 ) function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
self:T( { ToPointVec2, From, Event, To } ) self:T( { ToPointVec2, From, Event, To } )

View File

@@ -974,7 +974,7 @@ do -- Scheduling
-- @param #BASE self -- @param #BASE self
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called. -- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments. -- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
-- @param #table ... Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }. -- @param ... Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
-- @return #string The Schedule ID of the planned schedule. -- @return #string The Schedule ID of the planned schedule.
function BASE:ScheduleOnce( Start, SchedulerFunction, ... ) function BASE:ScheduleOnce( Start, SchedulerFunction, ... )

View File

@@ -872,6 +872,8 @@ end
-- @return Wrapper.Group#GROUP The found GROUP. -- @return Wrapper.Group#GROUP The found GROUP.
function DATABASE:FindGroup( GroupName ) function DATABASE:FindGroup( GroupName )
if type(GroupName) ~= "string" or GroupName == "" then return end
local GroupFound = self.GROUPS[GroupName] local GroupFound = self.GROUPS[GroupName]
if GroupFound == nil and GroupName ~= nil and self.Templates.Groups[GroupName] == nil then if GroupFound == nil and GroupName ~= nil and self.Templates.Groups[GroupName] == nil then
@@ -1110,7 +1112,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
self:E("WARNING: Invalid STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name) self:E("WARNING: Invalid STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
else else
self.STNS[stn] = UnitTemplate.name self.STNS[stn] = UnitTemplate.name
self:I("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name) self:T("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
end end
end end
if UnitTemplate.AddPropAircraft.SADL_TN then if UnitTemplate.AddPropAircraft.SADL_TN then
@@ -1119,7 +1121,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name) self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
else else
self.SADL[sadl] = UnitTemplate.name self.SADL[sadl] = UnitTemplate.name
self:I("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name) self:T("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
end end
end end
end end
@@ -1380,7 +1382,7 @@ function DATABASE:GetCoalitionFromClientTemplate( ClientName )
if self.Templates.ClientsByName[ClientName] then if self.Templates.ClientsByName[ClientName] then
return self.Templates.ClientsByName[ClientName].CoalitionID return self.Templates.ClientsByName[ClientName].CoalitionID
end end
self:E("WARNING: Template does not exist for client "..tostring(ClientName)) self:T("WARNING: Template does not exist for client "..tostring(ClientName))
return nil return nil
end end
@@ -1392,7 +1394,7 @@ function DATABASE:GetCategoryFromClientTemplate( ClientName )
if self.Templates.ClientsByName[ClientName] then if self.Templates.ClientsByName[ClientName] then
return self.Templates.ClientsByName[ClientName].CategoryID return self.Templates.ClientsByName[ClientName].CategoryID
end end
self:E("WARNING: Template does not exist for client "..tostring(ClientName)) self:T("WARNING: Template does not exist for client "..tostring(ClientName))
return nil return nil
end end
@@ -1404,7 +1406,7 @@ function DATABASE:GetCountryFromClientTemplate( ClientName )
if self.Templates.ClientsByName[ClientName] then if self.Templates.ClientsByName[ClientName] then
return self.Templates.ClientsByName[ClientName].CountryID return self.Templates.ClientsByName[ClientName].CountryID
end end
self:E("WARNING: Template does not exist for client "..tostring(ClientName)) self:T("WARNING: Template does not exist for client "..tostring(ClientName))
return nil return nil
end end
@@ -1697,7 +1699,7 @@ function DATABASE:_EventOnBirth( Event )
if PlayerName then if PlayerName then
-- Debug info. -- Debug info.
self:I(string.format("Player '%s' joined unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName))) self:I(string.format("Player '%s' joined unit '%s' (%s) of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniTypeName), tostring(Event.IniDCSGroupName)))
-- Add client in case it does not exist already. -- Add client in case it does not exist already.
if client == nil or (client and client:CountPlayers() == 0) then if client == nil or (client and client:CountPlayers() == 0) then

View File

@@ -1372,11 +1372,12 @@ function EVENT:onEvent( Event )
-- Scenery -- Scenery
--- ---
Event.IniDCSUnit = Event.initiator Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit.getName and Event.IniDCSUnit:getName() or "Scenery no name "..math.random(1,20000) Event.IniDCSUnitName = ( Event.IniDCSUnit and Event.IniDCSUnit.getName ) and Event.IniDCSUnit:getName() or "Scenery no name "..math.random(1,20000)
Event.IniUnitName = Event.IniDCSUnitName Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator ) Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
Event.IniCategory = Event.IniDCSUnit.getDesc and Event.IniDCSUnit:getDesc().category Event.IniCategory = (Event.IniDCSUnit and Event.IniDCSUnit.getDesc ) and Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY" Event.IniTypeName = (Event.initiator and Event.initiator.isExist
and Event.initiator:isExist() and Event.IniDCSUnit and Event.IniDCSUnit.getTypeName) and Event.IniDCSUnit:getTypeName() or "SCENERY"
elseif Event.IniObjectCategory == Object.Category.BASE then elseif Event.IniObjectCategory == Object.Category.BASE then
--- ---

View File

@@ -50,7 +50,7 @@ MARKEROPS_BASE = {
ClassName = "MARKEROPS", ClassName = "MARKEROPS",
Tag = "mytag", Tag = "mytag",
Keywords = {}, Keywords = {},
version = "0.1.3", version = "0.1.4",
debug = false, debug = false,
Casesensitive = true, Casesensitive = true,
} }
@@ -154,14 +154,7 @@ function MARKEROPS_BASE:OnEventMark(Event)
self:E("Skipping onEvent. Event or Event.idx unknown.") self:E("Skipping onEvent. Event or Event.idx unknown.")
return true return true
end end
--position
local vec3={y=Event.pos.y, x=Event.pos.x, z=Event.pos.z}
local coord=COORDINATE:NewFromVec3(vec3)
if self.debug then
local coordtext = coord:ToStringLLDDM()
local text = tostring(Event.text)
local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
end
local coalition = Event.MarkCoalition local coalition = Event.MarkCoalition
-- decision -- decision
if Event.id==world.event.S_EVENT_MARK_ADDED then if Event.id==world.event.S_EVENT_MARK_ADDED then
@@ -170,6 +163,12 @@ function MARKEROPS_BASE:OnEventMark(Event)
local Eventtext = tostring(Event.text) local Eventtext = tostring(Event.text)
if Eventtext~=nil then if Eventtext~=nil then
if self:_MatchTag(Eventtext) then if self:_MatchTag(Eventtext) then
local coord=COORDINATE:NewFromVec3({y=Event.pos.y, x=Event.pos.x, z=Event.pos.z})
if self.debug then
local coordtext = coord:ToStringLLDDM()
local text = tostring(Event.text)
local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
end
local matchtable = self:_MatchKeywords(Eventtext) local matchtable = self:_MatchKeywords(Eventtext)
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event) self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
end end
@@ -180,6 +179,12 @@ function MARKEROPS_BASE:OnEventMark(Event)
local Eventtext = tostring(Event.text) local Eventtext = tostring(Event.text)
if Eventtext~=nil then if Eventtext~=nil then
if self:_MatchTag(Eventtext) then if self:_MatchTag(Eventtext) then
local coord=COORDINATE:NewFromVec3({y=Event.pos.y, x=Event.pos.x, z=Event.pos.z})
if self.debug then
local coordtext = coord:ToStringLLDDM()
local text = tostring(Event.text)
local m = MESSAGE:New(string.format("Mark changed at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
end
local matchtable = self:_MatchKeywords(Eventtext) local matchtable = self:_MatchKeywords(Eventtext)
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event) self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
end end

View File

@@ -206,7 +206,7 @@ end
function MESSAGE:ToGroup( Group, Settings ) function MESSAGE:ToGroup( Group, Settings )
self:F( Group.GroupName ) self:F( Group.GroupName )
if Group then if Group and Group:IsAlive() then
if self.MessageType then if self.MessageType then
local Settings = Settings or (Group and _DATABASE:GetPlayerSettings( Group:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS local Settings = Settings or (Group and _DATABASE:GetPlayerSettings( Group:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS
@@ -231,7 +231,7 @@ end
function MESSAGE:ToUnit( Unit, Settings ) function MESSAGE:ToUnit( Unit, Settings )
self:F( Unit.IdentifiableName ) self:F( Unit.IdentifiableName )
if Unit then if Unit and Unit:IsAlive() then
if self.MessageType then if self.MessageType then
local Settings = Settings or ( Unit and _DATABASE:GetPlayerSettings( Unit:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS local Settings = Settings or ( Unit and _DATABASE:GetPlayerSettings( Unit:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
@@ -452,7 +452,7 @@ end
_MESSAGESRS = {} _MESSAGESRS = {}
--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions. `SetMSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible. --- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions. `SetMSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
-- @param #string PathToSRS (optional) Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone" or your configuration file setting. -- @param #string PathToSRS (optional) Path to SRS TTS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone\\ExternalAudio" or your configuration file setting.
-- @param #number Port Port (optional) number of SRS, defaults to 5002 or your configuration file setting. -- @param #number Port Port (optional) number of SRS, defaults to 5002 or your configuration file setting.
-- @param #string PathToCredentials (optional) Path to credentials file for Google. -- @param #string PathToCredentials (optional) Path to credentials file for Google.
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies. -- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
@@ -468,13 +468,13 @@ _MESSAGESRS = {}
-- @usage -- @usage
-- -- Mind the dot here, not using the colon this time around! -- -- Mind the dot here, not using the colon this time around!
-- -- Needed once only -- -- Needed once only
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE) -- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
-- -- later on in your code -- -- later on in your code
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
-- --
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate,Backend) function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate,Backend)
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" _MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
_MESSAGESRS.frequency = Frequency or MSRS.frequencies or 243 _MESSAGESRS.frequency = Frequency or MSRS.frequencies or 243
_MESSAGESRS.modulation = Modulation or MSRS.modulations or radio.modulation.AM _MESSAGESRS.modulation = Modulation or MSRS.modulations or radio.modulation.AM
@@ -535,7 +535,7 @@ end
-- @usage -- @usage
-- -- Mind the dot here, not using the colon this time around! -- -- Mind the dot here, not using the colon this time around!
-- -- Needed once only -- -- Needed once only
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE) -- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
-- -- later on in your code -- -- later on in your code
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
-- --
@@ -567,7 +567,7 @@ end
-- @usage -- @usage
-- -- Mind the dot here, not using the colon this time around! -- -- Mind the dot here, not using the colon this time around!
-- -- Needed once only -- -- Needed once only
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE) -- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
-- -- later on in your code -- -- later on in your code
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSBlue() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSBlue()
-- --
@@ -589,7 +589,7 @@ end
-- @usage -- @usage
-- -- Mind the dot here, not using the colon this time around! -- -- Mind the dot here, not using the colon this time around!
-- -- Needed once only -- -- Needed once only
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.RED) -- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.RED)
-- -- later on in your code -- -- later on in your code
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSRed() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSRed()
-- --
@@ -611,7 +611,7 @@ end
-- @usage -- @usage
-- -- Mind the dot here, not using the colon this time around! -- -- Mind the dot here, not using the colon this time around!
-- -- Needed once only -- -- Needed once only
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.NEUTRAL) -- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.NEUTRAL)
-- -- later on in your code -- -- later on in your code
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSAll() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSAll()
-- --

View File

@@ -25,7 +25,7 @@
do -- COORDINATE do -- COORDINATE
--- --- Coordinate class
-- @type COORDINATE -- @type COORDINATE
-- @field #string ClassName Name of the class -- @field #string ClassName Name of the class
-- @field #number x Component of the 3D vector. -- @field #number x Component of the 3D vector.
@@ -59,6 +59,10 @@ do -- COORDINATE
-- * @{#COORDINATE.SmokeOrange}(): To smoke the point in orange. -- * @{#COORDINATE.SmokeOrange}(): To smoke the point in orange.
-- * @{#COORDINATE.SmokeWhite}(): To smoke the point in white. -- * @{#COORDINATE.SmokeWhite}(): To smoke the point in white.
-- * @{#COORDINATE.SmokeGreen}(): To smoke the point in green. -- * @{#COORDINATE.SmokeGreen}(): To smoke the point in green.
-- * @{#COORDINATE.SetSmokeOffsetDirection}(): To set an offset point direction for smoke.
-- * @{#COORDINATE.SetSmokeOffsetDistance}(): To set an offset point distance for smoke.
-- * @{#COORDINATE.SwitchSmokeOffsetOn}(): To set an offset point for smoke to on.
-- * @{#COORDINATE.SwitchSmokeOffsetOff}(): To set an offset point for smoke to off.
-- --
-- ## 2.2) Flare -- ## 2.2) Flare
-- --
@@ -773,7 +777,9 @@ do -- COORDINATE
-- @return DCS#Vec2 Vec2 -- @return DCS#Vec2 Vec2
function COORDINATE:GetRandomVec2InRadius( OuterRadius, InnerRadius ) function COORDINATE:GetRandomVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } ) self:F2( { OuterRadius, InnerRadius } )
math.random()
math.random()
math.random()
local Theta = 2 * math.pi * math.random() local Theta = 2 * math.pi * math.random()
local Radials = math.random() + math.random() local Radials = math.random() + math.random()
if Radials > 1 then if Radials > 1 then
@@ -833,6 +839,26 @@ do -- COORDINATE
return land.getHeight( Vec2 ) return land.getHeight( Vec2 )
end end
--- Returns a table of DCS#Vec3 points representing the terrain profile between two points.
-- @param #COORDINATE self
-- @param Destination DCS#Vec3 Ending point of the profile.
-- @return #table DCS#Vec3 table of the profile
function COORDINATE:GetLandProfileVec3(Destination)
return land.profile(self:GetVec3(), Destination)
end
--- Returns a table of #COORDINATE representing the terrain profile between two points.
-- @param #COORDINATE self
-- @param Destination #COORDINATE Ending coordinate of the profile.
-- @return #table #COORDINATE table of the profile
function COORDINATE:GetLandProfileCoordinates(Destination)
local points = self:GetLandProfileVec3(Destination:GetVec3())
local coords = {}
for _, point in ipairs(points) do
table.insert(coords, COORDINATE:NewFromVec3(point))
end
return coords
end
--- Set the heading of the coordinate, if applicable. --- Set the heading of the coordinate, if applicable.
-- @param #COORDINATE self -- @param #COORDINATE self
@@ -1157,6 +1183,162 @@ do -- COORDINATE
return vec3 return vec3
end end
--- Return the x coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @return #number The x coordinate.
function COORDINATE:GetX()
return self.x
end
--- Return the y coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @return #number The y coordinate.
function COORDINATE:GetY()
if self:IsInstanceOf("POINT_VEC2") then
return self.z
end
return self.y
end
--- Return the z coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @return #number The z coordinate.
function COORDINATE:GetZ()
return self.z
end
--- Set the x coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number x The x coordinate.
-- @return #COORDINATE
function COORDINATE:SetX( x )
self.x = x
return self
end
--- Set the y coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number y The y coordinate.
-- @return #COORDINATE
function COORDINATE:SetY( y )
if self:IsInstanceOf("POINT_VEC2") then
self.z = y
else
self.y = y
end
return self
end
--- Set the z coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number z The z coordinate.
-- @return #COORDINATE
function COORDINATE:SetZ( z )
self.z = z
return self
end
--- Add to the x coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number x The x coordinate value to add to the current x coordinate.
-- @return #COORDINATE
function COORDINATE:AddX( x )
self.x = self.x + x
return self
end
--- Return Return the Lat(itude) coordinate of the COORDINATE (ie: (parent)COORDINATE.x).
-- @param #COORDINATE self
-- @return #number The x coordinate.
function COORDINATE:GetLat()
return self.x
end
--- Set the Lat(itude) coordinate of the COORDINATE (ie: COORDINATE.x).
-- @param #COORDINATE self
-- @param #number x The x coordinate.
-- @return #COORDINATE
function COORDINATE:SetLat( x )
self.x = x
return self
end
--- Return the Lon(gitude) coordinate of the COORDINATE (ie: (parent)COORDINATE.z).
-- @param #COORDINATE self
-- @return #number The y coordinate.
function COORDINATE:GetLon()
return self.z
end
--- Set the Lon(gitude) coordinate of the COORDINATE (ie: COORDINATE.z).
-- @param #COORDINATE self
-- @param #number y The y coordinate.
-- @return #COORDINATE
function COORDINATE:SetLon( z )
self.z = z
return self
end
--- Return the altitude (height) of the land at the COORDINATE.
-- @param #COORDINATE self
-- @return #number The land altitude.
function COORDINATE:GetAlt()
return self.y ~= 0 or land.getHeight( { x = self.x, y = self.z } )
end
--- Set the altitude of the COORDINATE.
-- @param #COORDINATE self
-- @param #number Altitude The land altitude. If nothing (nil) is given, then the current land altitude is set.
-- @return #COORDINATE
function COORDINATE:SetAlt( Altitude )
self.y = Altitude or land.getHeight( { x = self.x, y = self.z } )
return self
end
--- Add to the current land height an altitude.
-- @param #COORDINATE self
-- @param #number Altitude The Altitude to add. If nothing (nil) is given, then the current land altitude is set.
-- @return #COORDINATE
function COORDINATE:AddAlt( Altitude )
self.y = land.getHeight( { x = self.x, y = self.z } ) + Altitude or 0
return self
end
--- Return a random COORDINATE within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE.
-- @param #COORDINATE self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #COORDINATE
function COORDINATE:GetRandomPointVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } )
return COORDINATE:NewFromVec2( self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) )
end
--- Add to the y coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number y The y coordinate value to add to the current y coordinate.
-- @return #COORDINATE
function COORDINATE:AddY( y )
if self:IsInstanceOf("POINT_VEC2") then
return self:AddZ(y)
else
self.y = self.y + y
end
return self
end
--- Add to the z coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number z The z coordinate value to add to the current z coordinate.
-- @return #COORDINATE
function COORDINATE:AddZ( z )
self.z = self.z +z
return self
end
--- Returns a text documenting the wind direction (from) and strength according the measurement system @{Core.Settings}. --- Returns a text documenting the wind direction (from) and strength according the measurement system @{Core.Settings}.
-- The text will reflect the wind like this: -- The text will reflect the wind like this:
@@ -1962,16 +2144,114 @@ do -- COORDINATE
end end
--- Smokes the point in a color. --- Create colored smoke the point. The smoke we last up to 5 min (DCS limitation) but you can optionally specify a shorter duration or stop it manually.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Utilities.Utils#SMOKECOLOR SmokeColor -- @param #number SmokeColor Color of smoke, e.g. `SMOKECOLOR.Green` for green smoke.
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins) -- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
function COORDINATE:Smoke( SmokeColor, name ) -- @param #number Delay (Optional) Delay before the smoke is started in seconds.
self:F2( { SmokeColor } ) -- @param #string Name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
self.firename = name or "Smoke-"..math.random(1,100000) -- @param #boolean Offset (Optional) If true, offset the smokle a bit.
-- @param #number Direction (Optional) If Offset is true this is the direction of the offset, 1-359 (degrees). Default random.
-- @param #number Distance (Optional) If Offset is true this is the distance of the offset in meters. Default random 10-20.
-- @return #COORDINATE self
function COORDINATE:Smoke( SmokeColor, Duration, Delay, Name, Offset,Direction,Distance)
self:F2( { SmokeColor, Name, Duration, Delay, Offset } )
SmokeColor=SmokeColor or SMOKECOLOR.Green
if Delay and Delay>0 then
self:ScheduleOnce(Delay, COORDINATE.Smoke, self, SmokeColor, Duration, 0, Name, Direction,Distance)
else
-- Create a name which is used to stop the smoke manually
self.firename = Name or "Smoke-"..math.random(1,100000)
-- Create smoke
if Offset or self.SmokeOffset then
local Angle = Direction or self:GetSmokeOffsetDirection()
local Distance = Distance or self:GetSmokeOffsetDistance()
local newpos = self:Translate(Distance,Angle,true,false)
local newvec3 = newpos:GetVec3()
trigger.action.smoke( newvec3, SmokeColor, self.firename )
else
trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename ) trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename )
end end
-- Stop smoke
if Duration and Duration>0 then
self:ScheduleOnce(Duration, COORDINATE.StopSmoke, self, self.firename )
end
end
return self
end
--- Get the offset direction when using `COORDINATE:Smoke()`.
-- @param #COORDINATE self
-- @return #number Direction in degrees.
function COORDINATE:GetSmokeOffsetDirection()
local direction = self.SmokeOffsetDirection or math.random(1,359)
return direction
end
--- Set the offset direction when using `COORDINATE:Smoke()`.
-- @param #COORDINATE self
-- @param #number Direction (Optional) This is the direction of the offset, 1-359 (degrees). Default random.
-- @return #COORDINATE self
function COORDINATE:SetSmokeOffsetDirection(Direction)
if self then
self.SmokeOffsetDirection = Direction or math.random(1,359)
return self
else
COORDINATE.SmokeOffsetDirection = Direction or math.random(1,359)
end
end
--- Get the offset distance when using `COORDINATE:Smoke()`.
-- @param #COORDINATE self
-- @return #number Distance Distance in meters.
function COORDINATE:GetSmokeOffsetDistance()
local distance = self.SmokeOffsetDistance or math.random(10,20)
return distance
end
--- Set the offset distance when using `COORDINATE:Smoke()`.
-- @param #COORDINATE self
-- @param #number Distance (Optional) This is the distance of the offset in meters. Default random 10-20.
-- @return #COORDINATE self
function COORDINATE:SetSmokeOffsetDistance(Distance)
if self then
self.SmokeOffsetDistance = Distance or math.random(10,20)
return self
else
COORDINATE.SmokeOffsetDistance = Distance or math.random(10,20)
end
end
--- Set the offset on when using `COORDINATE:Smoke()`.
-- @param #COORDINATE self
-- @return #COORDINATE self
function COORDINATE:SwitchSmokeOffsetOn()
if self then
self.SmokeOffset = true
return self
else
COORDINATE.SmokeOffset = true
end
end
--- Set the offset off when using `COORDINATE:Smoke()`.
-- @param #COORDINATE self
-- @return #COORDINATE self
function COORDINATE:SwitchSmokeOffsetOff()
if self then
self.SmokeOffset = false
return self
else
COORDINATE.SmokeOffset = false
end
end
--- Stops smoking the point in a color. --- Stops smoking the point in a color.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins) -- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
@@ -1981,49 +2261,83 @@ do -- COORDINATE
--- Smoke the COORDINATE Green. --- Smoke the COORDINATE Green.
-- @param #COORDINATE self -- @param #COORDINATE self
function COORDINATE:SmokeGreen() -- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
self:F2() -- @param #number Delay (Optional) Delay before the smoke is started in seconds.
self:Smoke( SMOKECOLOR.Green ) -- @return #COORDINATE self
function COORDINATE:SmokeGreen(Duration, Delay)
self:Smoke( SMOKECOLOR.Green, Duration, Delay )
return self
end end
--- Smoke the COORDINATE Red. --- Smoke the COORDINATE Red.
-- @param #COORDINATE self -- @param #COORDINATE self
function COORDINATE:SmokeRed() -- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
self:F2() -- @param #number Delay (Optional) Delay before the smoke is started in seconds.
self:Smoke( SMOKECOLOR.Red ) -- @return #COORDINATE self
function COORDINATE:SmokeRed(Duration, Delay)
self:Smoke( SMOKECOLOR.Red, Duration, Delay )
return self
end end
--- Smoke the COORDINATE White. --- Smoke the COORDINATE White.
-- @param #COORDINATE self -- @param #COORDINATE self
function COORDINATE:SmokeWhite() -- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
self:F2() -- @param #number Delay (Optional) Delay before the smoke is started in seconds.
self:Smoke( SMOKECOLOR.White ) -- @return #COORDINATE self
function COORDINATE:SmokeWhite(Duration, Delay)
self:Smoke( SMOKECOLOR.White, Duration, Delay )
return self
end end
--- Smoke the COORDINATE Orange. --- Smoke the COORDINATE Orange.
-- @param #COORDINATE self -- @param #COORDINATE self
function COORDINATE:SmokeOrange() -- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
self:F2() -- @param #number Delay (Optional) Delay before the smoke is started in seconds.
self:Smoke( SMOKECOLOR.Orange ) -- @return #COORDINATE self
function COORDINATE:SmokeOrange(Duration, Delay)
self:Smoke( SMOKECOLOR.Orange, Duration, Delay )
return self
end end
--- Smoke the COORDINATE Blue. --- Smoke the COORDINATE Blue.
-- @param #COORDINATE self -- @param #COORDINATE self
function COORDINATE:SmokeBlue() -- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
self:F2() -- @param #number Delay (Optional) Delay before the smoke is started in seconds.
self:Smoke( SMOKECOLOR.Blue ) -- @return #COORDINATE self
function COORDINATE:SmokeBlue(Duration, Delay)
self:Smoke( SMOKECOLOR.Blue, Duration, Delay )
return self
end end
--- Big smoke and fire at the coordinate. --- Big smoke and fire at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Utilities.Utils#BIGSMOKEPRESET preset Smoke preset (1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke). -- @param #number Preset Smoke preset (1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke).
-- @param #number density (Optional) Smoke density. Number in [0,...,1]. Default 0.5. -- @param #number Density (Optional) Smoke density. Number in [0,...,1]. Default 0.5.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
function COORDINATE:BigSmokeAndFire( preset, density, name ) -- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
self:F2( { preset=preset, density=density } ) -- @param #string Name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
density=density or 0.5 -- @return #COORDINATE self
self.firename = name or "Fire-"..math.random(1,10000) function COORDINATE:BigSmokeAndFire( Preset, Density, Duration, Delay, Name )
trigger.action.effectSmokeBig( self:GetVec3(), preset, density, self.firename ) self:F2( { preset=Preset, density=Density } )
Preset=Preset or BIGSMOKEPRESET.SmallSmokeAndFire
Density=Density or 0.5
if Delay and Delay>0 then
self:ScheduleOnce(Delay, COORDINATE.BigSmokeAndFire, self, Preset, Density, Duration, 0, Name)
else
self.firename = Name or "Fire-"..math.random(1,10000)
trigger.action.effectSmokeBig( self:GetVec3(), Preset, Density, self.firename )
-- Stop smoke
if Duration and Duration>0 then
self:ScheduleOnce(Duration, COORDINATE.StopBigSmokeAndFire, self, self.firename )
end
end
return self
end end
--- Stop big smoke and fire at the coordinate. --- Stop big smoke and fire at the coordinate.
@@ -2036,82 +2350,98 @@ do -- COORDINATE
--- Small smoke and fire at the coordinate. --- Small smoke and fire at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5. -- @param #number Density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
function COORDINATE:BigSmokeAndFireSmall( density, name ) -- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
self:F2( { density=density } ) -- @param #string Name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
density=density or 0.5 -- @return #COORDINATE self
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmokeAndFire, density, name) function COORDINATE:BigSmokeAndFireSmall( Density, Duration, Delay, Name )
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmokeAndFire, Density, Duration, Delay, Name)
return self
end end
--- Medium smoke and fire at the coordinate. --- Medium smoke and fire at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5. -- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
function COORDINATE:BigSmokeAndFireMedium( density, name ) -- @return #COORDINATE self
self:F2( { density=density } ) function COORDINATE:BigSmokeAndFireMedium( Density, Duration, Delay, Name )
density=density or 0.5 self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmokeAndFire, Density, Duration, Delay, Name)
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmokeAndFire, density, name) return self
end end
--- Large smoke and fire at the coordinate. --- Large smoke and fire at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5. -- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
function COORDINATE:BigSmokeAndFireLarge( density, name ) -- @return #COORDINATE self
self:F2( { density=density } ) function COORDINATE:BigSmokeAndFireLarge( Density, Duration, Delay, Name )
density=density or 0.5 self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmokeAndFire, Density, Duration, Delay, Name)
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmokeAndFire, density, name) return self
end end
--- Huge smoke and fire at the coordinate. --- Huge smoke and fire at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5. -- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
function COORDINATE:BigSmokeAndFireHuge( density, name ) -- @return #COORDINATE self
self:F2( { density=density } ) function COORDINATE:BigSmokeAndFireHuge( Density, Duration, Delay, Name )
density=density or 0.5 self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmokeAndFire, Density, Duration, Delay, Name)
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmokeAndFire, density, name) return self
end end
--- Small smoke at the coordinate. --- Small smoke at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5. -- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
function COORDINATE:BigSmokeSmall( density, name ) -- @return #COORDINATE self
self:F2( { density=density } ) function COORDINATE:BigSmokeSmall( Density, Duration, Delay, Name )
density=density or 0.5 self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmoke, Density, Duration, Delay, Name)
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmoke, density, name) return self
end end
--- Medium smoke at the coordinate. --- Medium smoke at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param number density (Optional) Smoke density. Number between 0 and 1. Default 0.5. -- @param number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
function COORDINATE:BigSmokeMedium( density, name ) -- @return #COORDINATE self
self:F2( { density=density } ) function COORDINATE:BigSmokeMedium( Density, Duration, Delay, Name )
density=density or 0.5 self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmoke, Density, Duration, Delay, Name)
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmoke, density, name) return self
end end
--- Large smoke at the coordinate. --- Large smoke at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5. -- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
function COORDINATE:BigSmokeLarge( density, name ) -- @return #COORDINATE self
self:F2( { density=density } ) function COORDINATE:BigSmokeLarge( Density, Duration, Delay, Name )
density=density or 0.5 self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmoke, Density, Duration, Delay, Name)
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmoke, density,name) return self
end end
--- Huge smoke at the coordinate. --- Huge smoke at the coordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5. -- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number. -- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
function COORDINATE:BigSmokeHuge( density, name ) -- @return #COORDINATE self
self:F2( { density=density } ) function COORDINATE:BigSmokeHuge( Density, Duration, Delay, Name )
density=density or 0.5 self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmoke, Density, Duration, Delay, Name)
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmoke, density,name) return self
end end
--- Flares the point in a color. --- Flares the point in a color.
@@ -2765,8 +3095,10 @@ do -- COORDINATE
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff) local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
local sunset=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff) local sunset=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff)
if type(sunrise) == "string" or type(sunset) == "string" then
if sunrise == "N/R" then return false end if sunrise == "N/R" then return false end
if sunrise == "N/S" then return true end if sunset == "N/S" then return true end
end
local time=UTILS.ClockToSeconds(clock) local time=UTILS.ClockToSeconds(clock)
@@ -2785,6 +3117,11 @@ do -- COORDINATE
-- Todays sun set in sec. -- Todays sun set in sec.
local sunset=self:GetSunset(true) local sunset=self:GetSunset(true)
if type(sunrise) == "string" or type(sunset) == "string" then
if sunrise == "N/R" then return false end
if sunset == "N/S" then return true end
end
-- Seconds passed since midnight. -- Seconds passed since midnight.
local time=UTILS.SecondsOfToday() local time=UTILS.SecondsOfToday()
@@ -3474,9 +3811,37 @@ do -- COORDINATE
return flat, elev return flat, elev
end end
--- Return a random COORDINATE within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE.
-- @param #COORDINATE self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #COORDINATE
function COORDINATE:GetRandomPointVec3InRadius( OuterRadius, InnerRadius )
return COORDINATE:NewFromVec3( self:GetRandomVec3InRadius( OuterRadius, InnerRadius ) )
end end
do -- POINT_VEC3
--- Search for clear zones in a given area. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
-- @param #number SearchRadius Radius of the search area.
-- @param #number PosRadius Required clear radius around each position.
-- @param #number NumPositions Number of positions to find.
-- @return #table A table of Core.Point#COORDINATE that are clear of map objects within the given PosRadius. nil if no positions are found.
function COORDINATE:GetSimpleZones(SearchRadius, PosRadius, NumPositions)
local clearPositions = UTILS.GetSimpleZones(self:GetVec3(), SearchRadius, PosRadius, NumPositions)
if clearPositions and #clearPositions > 0 then
local coords = {}
for _, pos in pairs(clearPositions) do
local coord = COORDINATE:NewFromVec2(pos)
table.insert(coords, coord)
end
return coords
end
return nil
end
end
do
--- The POINT_VEC3 class --- The POINT_VEC3 class
-- @type POINT_VEC3 -- @type POINT_VEC3
@@ -3493,6 +3858,8 @@ do -- POINT_VEC3
--- Defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space. --- Defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
-- --
-- **DEPRECATED - PLEASE USE COORDINATE!**
--
-- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts. -- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts.
-- In order to keep the credibility of the the author, -- In order to keep the credibility of the the author,
-- I want to emphasize that the formulas embedded in the MIST framework were created by Grimes or previous authors, -- I want to emphasize that the formulas embedded in the MIST framework were created by Grimes or previous authors,
@@ -3580,130 +3947,19 @@ do -- POINT_VEC3
return self return self
end end
--- Create a new POINT_VEC3 object from Vec2 coordinates.
-- @param #POINT_VEC3 self
-- @param DCS#Vec2 Vec2 The Vec2 point.
-- @param DCS#Distance LandHeightAdd (optional) Add a landheight.
-- @return Core.Point#POINT_VEC3 self
function POINT_VEC3:NewFromVec2( Vec2, LandHeightAdd )
local self = BASE:Inherit( self, COORDINATE:NewFromVec2( Vec2, LandHeightAdd ) ) -- Core.Point#POINT_VEC3
self:F2( self )
return self
end end
do
--- Create a new POINT_VEC3 object from Vec3 coordinates. --- @type POINT_VEC2
-- @param #POINT_VEC3 self
-- @param DCS#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#POINT_VEC3 self
function POINT_VEC3:NewFromVec3( Vec3 )
local self = BASE:Inherit( self, COORDINATE:NewFromVec3( Vec3 ) ) -- Core.Point#POINT_VEC3
self:F2( self )
return self
end
--- Return the x coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @return #number The x coordinate.
function POINT_VEC3:GetX()
return self.x
end
--- Return the y coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @return #number The y coordinate.
function POINT_VEC3:GetY()
return self.y
end
--- Return the z coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @return #number The z coordinate.
function POINT_VEC3:GetZ()
return self.z
end
--- Set the x coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:SetX( x )
self.x = x
return self
end
--- Set the y coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:SetY( y )
self.y = y
return self
end
--- Set the z coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number z The z coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:SetZ( z )
self.z = z
return self
end
--- Add to the x coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number x The x coordinate value to add to the current x coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:AddX( x )
self.x = self.x + x
return self
end
--- Add to the y coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number y The y coordinate value to add to the current y coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:AddY( y )
self.y = self.y + y
return self
end
--- Add to the z coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number z The z coordinate value to add to the current z coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:AddZ( z )
self.z = self.z +z
return self
end
--- Return a random POINT_VEC3 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #POINT_VEC3
function POINT_VEC3:GetRandomPointVec3InRadius( OuterRadius, InnerRadius )
return POINT_VEC3:NewFromVec3( self:GetRandomVec3InRadius( OuterRadius, InnerRadius ) )
end
end
do -- POINT_VEC2
-- @type POINT_VEC2
-- @field DCS#Distance x The x coordinate in meters. -- @field DCS#Distance x The x coordinate in meters.
-- @field DCS#Distance y the y coordinate in meters. -- @field DCS#Distance y the y coordinate in meters.
-- @extends Core.Point#COORDINATE -- @extends Core.Point#COORDINATE
--- Defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified. --- Defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
-- --
-- **DEPRECATED - PLEASE USE COORDINATE!**
--
-- ## POINT_VEC2 constructor -- ## POINT_VEC2 constructor
-- --
-- A new POINT_VEC2 instance can be created with: -- A new POINT_VEC2 instance can be created with:
@@ -3751,166 +4007,4 @@ do -- POINT_VEC2
return self return self
end end
--- Create a new POINT_VEC2 object from Vec2 coordinates.
-- @param #POINT_VEC2 self
-- @param DCS#Vec2 Vec2 The Vec2 point.
-- @return Core.Point#POINT_VEC2 self
function POINT_VEC2:NewFromVec2( Vec2, LandHeightAdd )
local LandHeight = land.getHeight( Vec2 )
LandHeightAdd = LandHeightAdd or 0
LandHeight = LandHeight + LandHeightAdd
local self = BASE:Inherit( self, COORDINATE:NewFromVec2( Vec2, LandHeightAdd ) ) -- #POINT_VEC2
self:F2( self )
return self
end
--- Create a new POINT_VEC2 object from Vec3 coordinates.
-- @param #POINT_VEC2 self
-- @param DCS#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#POINT_VEC2 self
function POINT_VEC2:NewFromVec3( Vec3 )
local self = BASE:Inherit( self, COORDINATE:NewFromVec3( Vec3 ) ) -- #POINT_VEC2
self:F2( self )
return self
end
--- Return the x coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @return #number The x coordinate.
function POINT_VEC2:GetX()
return self.x
end
--- Return the y coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @return #number The y coordinate.
function POINT_VEC2:GetY()
return self.z
end
--- Set the x coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetX( x )
self.x = x
return self
end
--- Set the y coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetY( y )
self.z = y
return self
end
--- Return Return the Lat(itude) coordinate of the POINT_VEC2 (ie: (parent)POINT_VEC3.x).
-- @param #POINT_VEC2 self
-- @return #number The x coordinate.
function POINT_VEC2:GetLat()
return self.x
end
--- Set the Lat(itude) coordinate of the POINT_VEC2 (ie: POINT_VEC3.x).
-- @param #POINT_VEC2 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetLat( x )
self.x = x
return self
end
--- Return the Lon(gitude) coordinate of the POINT_VEC2 (ie: (parent)POINT_VEC3.z).
-- @param #POINT_VEC2 self
-- @return #number The y coordinate.
function POINT_VEC2:GetLon()
return self.z
end
--- Set the Lon(gitude) coordinate of the POINT_VEC2 (ie: POINT_VEC3.z).
-- @param #POINT_VEC2 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetLon( z )
self.z = z
return self
end
--- Return the altitude (height) of the land at the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @return #number The land altitude.
function POINT_VEC2:GetAlt()
return self.y ~= 0 or land.getHeight( { x = self.x, y = self.z } )
end
--- Set the altitude of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number Altitude The land altitude. If nothing (nil) is given, then the current land altitude is set.
-- @return #POINT_VEC2
function POINT_VEC2:SetAlt( Altitude )
self.y = Altitude or land.getHeight( { x = self.x, y = self.z } )
return self
end
--- Add to the x coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:AddX( x )
self.x = self.x + x
return self
end
--- Add to the y coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:AddY( y )
self.z = self.z + y
return self
end
--- Add to the current land height an altitude.
-- @param #POINT_VEC2 self
-- @param #number Altitude The Altitude to add. If nothing (nil) is given, then the current land altitude is set.
-- @return #POINT_VEC2
function POINT_VEC2:AddAlt( Altitude )
self.y = land.getHeight( { x = self.x, y = self.z } ) + Altitude or 0
return self
end
--- Return a random POINT_VEC2 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #POINT_VEC2
function POINT_VEC2:GetRandomPointVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } )
return POINT_VEC2:NewFromVec2( self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) )
end
-- TODO: Check this to replace
--- Calculate the distance from a reference @{#POINT_VEC2}.
-- @param #POINT_VEC2 self
-- @param #POINT_VEC2 PointVec2Reference The reference @{#POINT_VEC2}.
-- @return DCS#Distance The distance from the reference @{#POINT_VEC2} in meters.
function POINT_VEC2:DistanceFromPointVec2( PointVec2Reference )
self:F2( PointVec2Reference )
local Distance = ( ( PointVec2Reference.x - self.x ) ^ 2 + ( PointVec2Reference.z - self.z ) ^2 ) ^ 0.5
self:T2( Distance )
return Distance
end
end end

View File

@@ -175,7 +175,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
local Name = Info.name or "?" local Name = Info.name or "?"
local ErrorHandler = function( errmsg ) local ErrorHandler = function( errmsg )
env.info( "Error in timer function: " .. errmsg ) env.info( "Error in timer function: " .. errmsg or "" )
if BASE.Debug ~= nil then if BASE.Debug ~= nil then
env.info( BASE.Debug.traceback() ) env.info( BASE.Debug.traceback() )
end end
@@ -326,7 +326,7 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
local Schedule = self.Schedule[Scheduler][CallID] -- #SCHEDULEDISPATCHER.ScheduleData local Schedule = self.Schedule[Scheduler][CallID] -- #SCHEDULEDISPATCHER.ScheduleData
-- Only stop when there is a ScheduleID defined for the CallID. So, when the scheduler was stopped before, do nothing. -- Only stop when there is a ScheduleID defined for the CallID. So, when the scheduler was stopped before, do nothing.
if Schedule.ScheduleID then if Schedule and Schedule.ScheduleID then
self:T( string.format( "SCHEDULEDISPATCHER stopping scheduler CallID=%s, ScheduleID=%s", tostring( CallID ), tostring( Schedule.ScheduleID ) ) ) self:T( string.format( "SCHEDULEDISPATCHER stopping scheduler CallID=%s, ScheduleID=%s", tostring( CallID ), tostring( Schedule.ScheduleID ) ) )

View File

@@ -629,14 +629,14 @@ do -- SET_BASE
return self return self
end end
--- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#POINT_VEC2}. --- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#COORDINATE}.
-- @param #SET_BASE self -- @param #SET_BASE self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#COORDINATE} or @{Core.Point#POINT_VEC2} object (but **not** a simple DCS#Vec2!) from where to evaluate the closest object in the set. -- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object (but **not** a simple DCS#Vec2!) from where to evaluate the closest object in the set.
-- @return Core.Base#BASE The closest object. -- @return Core.Base#BASE The closest object.
-- @usage -- @usage
-- myset:FindNearestObjectFromPointVec2( ZONE:New("Test Zone"):GetCoordinate() ) -- myset:FindNearestObjectFromPointVec2( ZONE:New("Test Zone"):GetCoordinate() )
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 ) function SET_BASE:FindNearestObjectFromPointVec2( Coordinate )
--self:F2( PointVec2 ) --self:F2( Coordinate )
local NearestObject = nil local NearestObject = nil
local ClosestDistance = nil local ClosestDistance = nil
@@ -644,9 +644,9 @@ do -- SET_BASE
for ObjectID, ObjectData in pairs( self.Set ) do for ObjectID, ObjectData in pairs( self.Set ) do
if NearestObject == nil then if NearestObject == nil then
NearestObject = ObjectData NearestObject = ObjectData
ClosestDistance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() ) ClosestDistance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
else else
local Distance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() ) local Distance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
if Distance < ClosestDistance then if Distance < ClosestDistance then
NearestObject = ObjectData NearestObject = ObjectData
ClosestDistance = Distance ClosestDistance = Distance
@@ -959,6 +959,25 @@ do -- SET_BASE
return ObjectNames return ObjectNames
end end
--- Get a *new* set table that only contains alive objects.
-- @param #SET_BASE self
-- @return #table Set table of alive objects.
function SET_BASE:GetAliveSet()
--self:F2()
local AliveSet = {}
-- Clean the Set before returning with only the alive Objects.
for ObjectName, Object in pairs( self.Set ) do
if Object then
if Object:IsAlive() then
AliveSet[#AliveSet+1] = Object
end
end
end
return AliveSet or {}
end
end end
do do
@@ -1125,25 +1144,25 @@ do
end end
--- Get a *new* set that only contains alive groups. --- Get a *new* set table that only contains alive groups.
-- @param #SET_GROUP self -- @param #SET_GROUP self
-- @return #SET_GROUP Set of alive groups. -- @return #table Set of alive groups.
function SET_GROUP:GetAliveSet() function SET_GROUP:GetAliveSet()
--self:F2() --self:F2()
local AliveSet = SET_GROUP:New() --local AliveSet = SET_GROUP:New()
local AliveSet = {}
-- Clean the Set before returning with only the alive Groups. -- Clean the Set before returning with only the alive Groups.
for GroupName, GroupObject in pairs( self.Set ) do for GroupName, GroupObject in pairs( self.Set ) do
local GroupObject = GroupObject -- Wrapper.Group#GROUP local GroupObject = GroupObject -- Wrapper.Group#GROUP
if GroupObject then if GroupObject then
if GroupObject:IsAlive() then if GroupObject:IsAlive() then
AliveSet:Add( GroupName, GroupObject ) AliveSet[GroupName] = GroupObject
end end
end end
end end
return AliveSet.Set or {} return AliveSet or {}
end end
--- Returns a report of of unit types. --- Returns a report of of unit types.
@@ -1242,12 +1261,12 @@ do
return GroupFound return GroupFound
end end
--- Iterate the SET_GROUP while identifying the nearest object from a @{Core.Point#POINT_VEC2}. --- Iterate the SET_GROUP while identifying the nearest object from a @{Core.Point#COORDINATE}.
-- @param #SET_GROUP self -- @param #SET_GROUP self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest object in the set. -- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest object in the set.
-- @return Wrapper.Group#GROUP The closest group. -- @return Wrapper.Group#GROUP The closest group.
function SET_GROUP:FindNearestGroupFromPointVec2( PointVec2 ) function SET_GROUP:FindNearestGroupFromPointVec2( Coordinate )
--self:F2( PointVec2 ) --self:F2( Coordinate )
local NearestGroup = nil -- Wrapper.Group#GROUP local NearestGroup = nil -- Wrapper.Group#GROUP
local ClosestDistance = nil local ClosestDistance = nil
@@ -1257,9 +1276,9 @@ do
for ObjectID, ObjectData in pairs( Set ) do for ObjectID, ObjectData in pairs( Set ) do
if NearestGroup == nil then if NearestGroup == nil then
NearestGroup = ObjectData NearestGroup = ObjectData
ClosestDistance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() ) ClosestDistance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
else else
local Distance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() ) local Distance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
if Distance < ClosestDistance then if Distance < ClosestDistance then
NearestGroup = ObjectData NearestGroup = ObjectData
ClosestDistance = Distance ClosestDistance = Distance
@@ -2520,6 +2539,35 @@ do -- SET_UNIT
return self return self
end end
--- Builds a set of units which belong to groups with certain **group names**.
-- @param #SET_UNIT self
-- @param #string Prefixes The (partial) group names to look for. Can be a single string or a table of strings.
-- @return #SET_UNIT self
function SET_UNIT:FilterGroupPrefixes(Prefixes)
if type(Prefixes) == "string" then
Prefixes = {Prefixes}
end
self:FilterFunction(
function(unit,prefixes)
local outcome = false
if unit then
local grp = unit:GetGroup()
local gname = grp ~= nil and grp:GetName() or "none"
for _,_fix in pairs(prefixes or {}) do
if string.find(gname,_fix) then
outcome = true
break
end
end
else
return false
end
return outcome
end, Prefixes
)
return self
end
--- Builds a set of units having a radar of give types. --- Builds a set of units having a radar of give types.
-- All the units having a radar of a given type will be included within the set. -- All the units having a radar of a given type will be included within the set.
-- @param #SET_UNIT self -- @param #SET_UNIT self
@@ -2566,7 +2614,7 @@ do -- SET_UNIT
--- Gets the alive set. --- Gets the alive set.
-- @param #SET_UNIT self -- @param #SET_UNIT self
-- @return #table Table of SET objects -- @return #table Table of alive UNIT objects
-- @return #SET_UNIT AliveSet -- @return #SET_UNIT AliveSet
function SET_UNIT:GetAliveSet() function SET_UNIT:GetAliveSet()
@@ -2574,10 +2622,8 @@ do -- SET_UNIT
-- Clean the Set before returning with only the alive Groups. -- Clean the Set before returning with only the alive Groups.
for GroupName, GroupObject in pairs(self.Set) do for GroupName, GroupObject in pairs(self.Set) do
local GroupObject=GroupObject --Wrapper.Client#CLIENT
if GroupObject and GroupObject:IsAlive() then if GroupObject and GroupObject:IsAlive() then
AliveSet:Add(GroupName, GroupObject) AliveSet[GroupName] = GroupObject
end end
end end
@@ -4435,6 +4481,35 @@ do -- SET_CLIENT
return self return self
end end
--- Builds a set of clients which belong to groups with certain **group names**.
-- @param #SET_CLIENT self
-- @param #string Prefixes The (partial) group names to look for. Can be anywhere in the group name. Can be a single string or a table of strings.
-- @return #SET_CLIENT self
function SET_CLIENT:FilterGroupPrefixes(Prefixes)
if type(Prefixes) == "string" then
Prefixes = {Prefixes}
end
self:FilterFunction(
function(unit,prefixes)
local outcome = false
if unit then
local grp = unit:GetGroup()
local gname = grp ~= nil and grp:GetName() or "none"
for _,_fix in pairs(prefixes or {}) do
if string.find(gname,_fix) then
outcome = true
break
end
end
else
return false
end
return outcome
end, Prefixes
)
return self
end
--- Builds a set of clients that are only active. --- Builds a set of clients that are only active.
-- Only the clients that are active will be included within the set. -- Only the clients that are active will be included within the set.
-- @param #SET_CLIENT self -- @param #SET_CLIENT self
@@ -4726,18 +4801,16 @@ do -- SET_CLIENT
-- @return #table Table of SET objects -- @return #table Table of SET objects
function SET_CLIENT:GetAliveSet() function SET_CLIENT:GetAliveSet()
local AliveSet = SET_CLIENT:New() local AliveSet = {}
-- Clean the Set before returning with only the alive Groups. -- Clean the Set before returning with only the alive Groups.
for GroupName, GroupObject in pairs(self.Set) do for GroupName, GroupObject in pairs(self.Set) do
local GroupObject=GroupObject --Wrapper.Client#CLIENT
if GroupObject and GroupObject:IsAlive() then if GroupObject and GroupObject:IsAlive() then
AliveSet:Add(GroupName, GroupObject) AliveSet[GroupName] = GroupObject
end end
end end
return AliveSet.Set or {} return AliveSet or {}
end end
--- [User] Add a custom condition function. --- [User] Add a custom condition function.
@@ -5670,14 +5743,14 @@ do -- SET_AIRBASE
return self return self
end end
--- Iterate the SET_AIRBASE while identifying the nearest @{Wrapper.Airbase#AIRBASE} from a @{Core.Point#POINT_VEC2}. --- Iterate the SET_AIRBASE while identifying the nearest @{Wrapper.Airbase#AIRBASE} from a @{Core.Point#COORDINATE}.
-- @param #SET_AIRBASE self -- @param #SET_AIRBASE self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest @{Wrapper.Airbase#AIRBASE}. -- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest @{Wrapper.Airbase#AIRBASE}.
-- @return Wrapper.Airbase#AIRBASE The closest @{Wrapper.Airbase#AIRBASE}. -- @return Wrapper.Airbase#AIRBASE The closest @{Wrapper.Airbase#AIRBASE}.
function SET_AIRBASE:FindNearestAirbaseFromPointVec2( PointVec2 ) function SET_AIRBASE:FindNearestAirbaseFromPointVec2( Coordinate )
--self:F2( PointVec2 ) --self:F2( Coordinate )
local NearestAirbase = self:FindNearestObjectFromPointVec2( PointVec2 ) local NearestAirbase = self:FindNearestObjectFromPointVec2( Coordinate )
return NearestAirbase return NearestAirbase
end end
@@ -6007,17 +6080,19 @@ do -- SET_CARGO
return self return self
end end
--- (R2.1) Iterate the SET_CARGO while identifying the nearest @{Cargo.Cargo#CARGO} from a @{Core.Point#POINT_VEC2}. --- (R2.1) Iterate the SET_CARGO while identifying the nearest @{Cargo.Cargo#CARGO} from a @{Core.Point#COORDINATE}.
-- @param #SET_CARGO self -- @param #SET_CARGO self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest @{Cargo.Cargo#CARGO}. -- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest @{Cargo.Cargo#CARGO}.
-- @return Cargo.Cargo#CARGO The closest @{Cargo.Cargo#CARGO}. -- @return Cargo.Cargo#CARGO The closest @{Cargo.Cargo#CARGO}.
function SET_CARGO:FindNearestCargoFromPointVec2( PointVec2 ) -- R2.1 function SET_CARGO:FindNearestCargoFromPointVec2( Coordinate ) -- R2.1
--self:F2( PointVec2 ) --self:F2( Coordinate )
local NearestCargo = self:FindNearestObjectFromPointVec2( PointVec2 ) local NearestCargo = self:FindNearestObjectFromPointVec2( Coordinate )
return NearestCargo return NearestCargo
end end
---
-- @param #SET_CARGO self
function SET_CARGO:FirstCargoWithState( State ) function SET_CARGO:FirstCargoWithState( State )
local FirstCargo = nil local FirstCargo = nil
@@ -6032,6 +6107,8 @@ do -- SET_CARGO
return FirstCargo return FirstCargo
end end
---
-- @param #SET_CARGO self
function SET_CARGO:FirstCargoWithStateAndNotDeployed( State ) function SET_CARGO:FirstCargoWithStateAndNotDeployed( State )
local FirstCargo = nil local FirstCargo = nil
@@ -6614,6 +6691,8 @@ do -- SET_ZONE
-- --
-- -- Stop watching after 1 hour -- -- Stop watching after 1 hour
-- zoneset:__TriggerStop(3600) -- zoneset:__TriggerStop(3600)
-- -- Call :SetPartlyInside() on any zone (or SET_ZONE) if you want GROUPs to count as inside when any of their units enters even if they are far apart.
-- -- Make sure to call :SetPartlyInside() before :Trigger()!.
function SET_ZONE:Trigger(Objects) function SET_ZONE:Trigger(Objects)
--self:I("Added Set_Zone Trigger") --self:I("Added Set_Zone Trigger")
self:AddTransition("*","TriggerStart","TriggerRunning") self:AddTransition("*","TriggerStart","TriggerRunning")
@@ -6664,6 +6743,20 @@ do -- SET_ZONE
-- @param Core.Zone#ZONE_BASE Zone The zone left. -- @param Core.Zone#ZONE_BASE Zone The zone left.
end end
--- Toggle “partly-inside” handling for every zone in the set when those zones are used with :Trigger().
-- * Call with no argument or **true** → enable for all.
-- * Call with **false** → disable again (handy if it was enabled before).
-- @param #SET_ZONE self
-- @return #SET_ZONE self
function SET_ZONE:SetPartlyInside(state)
for _,Zone in pairs(self.Set) do
if Zone.SetPartlyInside then
Zone:SetPartlyInside(state)
end
end
return self
end
--- (Internal) Check the assigned objects for being in/out of the zone --- (Internal) Check the assigned objects for being in/out of the zone
-- @param #SET_ZONE self -- @param #SET_ZONE self
-- @param #boolean fromstart If true, do the init of the objects -- @param #boolean fromstart If true, do the init of the objects
@@ -6699,8 +6792,13 @@ do -- SET_ZONE
-- has not been tagged previously - wasn't in set! -- has not been tagged previously - wasn't in set!
obj.TriggerInZone[_zone.ZoneName] = false obj.TriggerInZone[_zone.ZoneName] = false
end end
-- is obj in zone? -- is obj in this zone?
local inzone = _zone:IsCoordinateInZone(obj:GetCoordinate()) local inzone
if _zone.PartlyInside and obj.ClassName == "GROUP" then
inzone = obj:IsAnyInZone(_zone) -- TRUE as soon as any unit is inside
else
inzone = _zone:IsCoordinateInZone(obj:GetCoordinate()) -- original centroid test
end
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone)) --self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
if inzone and not obj.TriggerInZone[_zone.ZoneName] then if inzone and not obj.TriggerInZone[_zone.ZoneName] then
-- wasn't in zone before -- wasn't in zone before
@@ -8693,7 +8791,6 @@ do -- SET_DYNAMICCARGO
-- @field #SET_DYNAMICCARGO SET_DYNAMICCARGO -- @field #SET_DYNAMICCARGO SET_DYNAMICCARGO
SET_DYNAMICCARGO = { SET_DYNAMICCARGO = {
ClassName = "SET_DYNAMICCARGO", ClassName = "SET_DYNAMICCARGO",
Filter = {},
Set = {}, Set = {},
List = {}, List = {},
Index = {}, Index = {},

View File

@@ -1631,7 +1631,7 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
if SpawnTemplate then if SpawnTemplate then
local PointVec3 = POINT_VEC3:New( SpawnTemplate.route.points[1].x, SpawnTemplate.route.points[1].alt, SpawnTemplate.route.points[1].y ) local PointVec3 = COORDINATE:New( SpawnTemplate.route.points[1].x, SpawnTemplate.route.points[1].alt, SpawnTemplate.route.points[1].y )
--self:T2( { "Current point of ", self.SpawnTemplatePrefix, PointVec3 } ) --self:T2( { "Current point of ", self.SpawnTemplatePrefix, PointVec3 } )
-- If RandomizePosition, then Randomize the formation in the zone band, keeping the template. -- If RandomizePosition, then Randomize the formation in the zone band, keeping the template.
@@ -2830,7 +2830,7 @@ end
function SPAWN:SpawnFromVec3( Vec3, SpawnIndex ) function SPAWN:SpawnFromVec3( Vec3, SpawnIndex )
--self:F( { self.SpawnTemplatePrefix, Vec3, SpawnIndex } ) --self:F( { self.SpawnTemplatePrefix, Vec3, SpawnIndex } )
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 ) local PointVec3 = COORDINATE:NewFromVec3( Vec3 )
--self:T2( PointVec3 ) --self:T2( PointVec3 )
if SpawnIndex then if SpawnIndex then
@@ -2906,7 +2906,7 @@ end
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn. -- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed. -- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self -- @param #SPAWN self
-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 coordinates where to spawn the group. -- @param Core.Point#COORDINATE PointVec3 The COORDINATE coordinates where to spawn the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone. -- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned or #nil if nothing was spawned. -- @return Wrapper.Group#GROUP that was spawned or #nil if nothing was spawned.
-- @usage -- @usage
@@ -2954,12 +2954,12 @@ function SPAWN:SpawnFromVec2( Vec2, MinHeight, MaxHeight, SpawnIndex )
return self:SpawnFromVec3( { x = Vec2.x, y = Height, z = Vec2.y }, SpawnIndex ) -- y can be nil. In this case, spawn on the ground for vehicles, and in the template altitude for air. return self:SpawnFromVec3( { x = Vec2.x, y = Height, z = Vec2.y }, SpawnIndex ) -- y can be nil. In this case, spawn on the ground for vehicles, and in the template altitude for air.
end end
--- Will spawn a group from a POINT_VEC2 in 3D space. --- Will spawn a group from a COORDINATE in 3D space.
-- This method is mostly advisable to be used if you want to simulate spawning groups on the ground from air units, like vehicles. -- This method is mostly advisable to be used if you want to simulate spawning groups on the ground from air units, like vehicles.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn. -- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed. -- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self -- @param #SPAWN self
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 coordinates where to spawn the group. -- @param Core.Point#COORDINATE PointVec2 The coordinates where to spawn the group.
-- @param #number MinHeight (optional) The minimum height to spawn an airborne group into the zone. -- @param #number MinHeight (optional) The minimum height to spawn an airborne group into the zone.
-- @param #number MaxHeight (optional) The maximum height to spawn an airborne group into the zone. -- @param #number MaxHeight (optional) The maximum height to spawn an airborne group into the zone.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone. -- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.

View File

@@ -105,7 +105,7 @@
-- --
-- * @{#SPAWNSTATIC.Spawn}(Heading, NewName) spawns the static with the set parameters. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.Spawn}(Heading, NewName) spawns the static with the set parameters. Optionally, heading and name can be given. The name **must be unique**!
-- * @{#SPAWNSTATIC.SpawnFromCoordinate}(Coordinate, Heading, NewName) spawn the static at the given coordinate. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.SpawnFromCoordinate}(Coordinate, Heading, NewName) spawn the static at the given coordinate. Optionally, heading and name can be given. The name **must be unique**!
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a POINT_VEC2 coordinate. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a COORDINATE coordinate. Optionally, heading and name can be given. The name **must be unique**!
-- * @{#SPAWNSTATIC.SpawnFromZone}(Zone, Heading, NewName) spawns the static at the center of a @{Core.Zone}. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.SpawnFromZone}(Zone, Heading, NewName) spawns the static at the center of a @{Core.Zone}. Optionally, heading and name can be given. The name **must be unique**!
-- --
-- @field #SPAWNSTATIC SPAWNSTATIC -- @field #SPAWNSTATIC SPAWNSTATIC
@@ -149,6 +149,7 @@ function SPAWNSTATIC:NewFromStatic(SpawnTemplateName, SpawnCountryID)
self.CategoryID = CategoryID self.CategoryID = CategoryID
self.CoalitionID = CoalitionID self.CoalitionID = CoalitionID
self.SpawnIndex = 0 self.SpawnIndex = 0
self.StaticCopyFrom = SpawnTemplateName
else else
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. tostring(SpawnTemplateName) .. "'" ) error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. tostring(SpawnTemplateName) .. "'" )
end end
@@ -302,12 +303,16 @@ end
-- @param #number CallsignID Callsign ID. Default 1 (="London"). -- @param #number CallsignID Callsign ID. Default 1 (="London").
-- @param #number Frequency Frequency in MHz. Default 127.5 MHz. -- @param #number Frequency Frequency in MHz. Default 127.5 MHz.
-- @param #number Modulation Modulation 0=AM, 1=FM. -- @param #number Modulation Modulation 0=AM, 1=FM.
-- @param #boolean DynamicSpawns If true, allow Dynamic Spawns
-- @param #boolean DynamicHotStarts If true, and DynamicSpawns is true, then allow Dynamic Spawns with hot starts.
-- @return #SPAWNSTATIC self -- @return #SPAWNSTATIC self
function SPAWNSTATIC:InitFARP(CallsignID, Frequency, Modulation) function SPAWNSTATIC:InitFARP(CallsignID, Frequency, Modulation, DynamicSpawns,DynamicHotStarts)
self.InitFarp=true self.InitFarp=true
self.InitFarpCallsignID=CallsignID or 1 self.InitFarpCallsignID=CallsignID or 1
self.InitFarpFreq=Frequency or 127.5 self.InitFarpFreq=Frequency or 127.5
self.InitFarpModu=Modulation or 0 self.InitFarpModu=Modulation or 0
self.InitFarpDynamicSpawns = DynamicSpawns
self.InitFarpDynamicHotStarts = (DynamicSpawns == true and DynamicHotStarts == true) and true or nil
return self return self
end end
@@ -411,9 +416,9 @@ function SPAWNSTATIC:Spawn(Heading, NewName)
end end
--- Creates a new @{Wrapper.Static} from a POINT_VEC2. --- Creates a new @{Wrapper.Static} from a COORDINATE.
-- @param #SPAWNSTATIC self -- @param #SPAWNSTATIC self
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static. -- @param Core.Point#COORDINATE PointVec2 The 2D coordinate where to spawn the static.
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360. -- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
-- @param #string NewName (Optional) The name of the new static. -- @param #string NewName (Optional) The name of the new static.
-- @return Wrapper.Static#STATIC The static spawned. -- @return Wrapper.Static#STATIC The static spawned.
@@ -459,7 +464,8 @@ end
function SPAWNSTATIC:SpawnFromZone(Zone, Heading, NewName) function SPAWNSTATIC:SpawnFromZone(Zone, Heading, NewName)
-- Spawn the new static at the center of the zone. -- Spawn the new static at the center of the zone.
local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName ) --local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
local Static = self:SpawnFromCoordinate(Zone:GetCoordinate(), Heading, NewName)
return Static return Static
end end
@@ -550,12 +556,20 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
TemplateGroup.y=Template.y TemplateGroup.y=Template.y
TemplateGroup.name=Template.name TemplateGroup.name=Template.name
if self.InitFarpDynamicSpawns == true then
TemplateGroup.units[1].dynamicSpawn = true
if self.InitFarpDynamicHotStarts == true then
TemplateGroup.units[1].allowHotStart = true
end
end
self:T("Spawning FARP") self:T("Spawning FARP")
self:T({Template=Template}) self:T({Template=Template})
self:T({TemplateGroup=TemplateGroup}) self:T({TemplateGroup=TemplateGroup})
-- ED's dirty way to spawn FARPS. -- ED's dirty way to spawn FARPS.
Static=coalition.addGroup(CountryID, -1, TemplateGroup) Static=coalition.addGroup(CountryID, -1, TemplateGroup)
--Static=coalition.addStaticObject(CountryID, Template)
-- Currently DCS 2.8 does not trigger birth events if FARPS are spawned! -- Currently DCS 2.8 does not trigger birth events if FARPS are spawned!
-- We create such an event. The airbase is registered in Core.Event -- We create such an event. The airbase is registered in Core.Event
@@ -595,5 +609,18 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
self:ScheduleOnce(0.3, self.SpawnFunctionHook, mystatic, unpack(self.SpawnFunctionArguments)) self:ScheduleOnce(0.3, self.SpawnFunctionHook, mystatic, unpack(self.SpawnFunctionArguments))
end end
if self.StaticCopyFrom ~= nil then
mystatic.StaticCopyFrom = self.StaticCopyFrom
if not _DATABASE.Templates.Statics[Template.name] then
local TemplateGroup={}
TemplateGroup.units={}
TemplateGroup.units[1]=Template
TemplateGroup.x=Template.x
TemplateGroup.y=Template.y
TemplateGroup.name=Template.name
_DATABASE:_RegisterStaticTemplate( TemplateGroup, self.CoalitionID, self.CategoryID, CountryID )
end
end
return mystatic return mystatic
end end

View File

@@ -70,6 +70,7 @@
-- @field #table Table of any trigger zone properties from the ME. The key is the Name of the property, and the value is the property's Value. -- @field #table Table of any trigger zone properties from the ME. The key is the Name of the property, and the value is the property's Value.
-- @field #number Surface Type of surface. Only determined at the center of the zone! -- @field #number Surface Type of surface. Only determined at the center of the zone!
-- @field #number Checktime Check every Checktime seconds, used for ZONE:Trigger() -- @field #number Checktime Check every Checktime seconds, used for ZONE:Trigger()
-- @field #boolean PartlyInside When called, a GROUP is considered inside as soon as any of its units enters the zone even if they are far apart.
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
@@ -213,7 +214,7 @@ end
--- Returns if a PointVec3 is within the zone. --- Returns if a PointVec3 is within the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 to test. -- @param Core.Point#COORDINATE PointVec3 The PointVec3 to test.
-- @return #boolean true if the PointVec3 is within the zone. -- @return #boolean true if the PointVec3 is within the zone.
function ZONE_BASE:IsPointVec3InZone( PointVec3 ) function ZONE_BASE:IsPointVec3InZone( PointVec3 )
local InZone = self:IsPointVec2InZone( PointVec3 ) local InZone = self:IsPointVec2InZone( PointVec3 )
@@ -227,16 +228,16 @@ function ZONE_BASE:GetVec2()
return nil return nil
end end
--- Returns a @{Core.Point#POINT_VEC2} of the zone. --- Returns a @{Core.Point#COORDINATE} of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC2 The PointVec2 of the zone. -- @return Core.Point#COORDINATE The COORDINATE of the zone.
function ZONE_BASE:GetPointVec2() function ZONE_BASE:GetPointVec2()
--self:F2( self.ZoneName ) --self:F2( self.ZoneName )
local Vec2 = self:GetVec2() local Vec2 = self:GetVec2()
local PointVec2 = POINT_VEC2:NewFromVec2( Vec2 ) local PointVec2 = COORDINATE:NewFromVec2( Vec2 )
--self:T2( { PointVec2 } ) --self:T2( { PointVec2 } )
@@ -261,16 +262,16 @@ function ZONE_BASE:GetVec3( Height )
return Vec3 return Vec3
end end
--- Returns a @{Core.Point#POINT_VEC3} of the zone. --- Returns a @{Core.Point#COORDINATE} of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC3 The PointVec3 of the zone. -- @return Core.Point#COORDINATE The PointVec3 of the zone.
function ZONE_BASE:GetPointVec3( Height ) function ZONE_BASE:GetPointVec3( Height )
--self:F2( self.ZoneName ) --self:F2( self.ZoneName )
local Vec3 = self:GetVec3( Height ) local Vec3 = self:GetVec3( Height )
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 ) local PointVec3 = COORDINATE:NewFromVec3( Vec3 )
--self:T2( { PointVec3 } ) --self:T2( { PointVec3 } )
@@ -330,16 +331,16 @@ function ZONE_BASE:GetRandomVec2()
return nil return nil
end end
--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. --- Define a random @{Core.Point#COORDINATE} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates. -- @return Core.Point#COORDINATE The COORDINATE coordinates.
function ZONE_BASE:GetRandomPointVec2() function ZONE_BASE:GetRandomPointVec2()
return nil return nil
end end
--- Define a random @{Core.Point#POINT_VEC3} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table. --- Define a random @{Core.Point#COORDINATE} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return Core.Point#POINT_VEC3 The PointVec3 coordinates. -- @return Core.Point#COORDINATE The COORDINATE coordinates.
function ZONE_BASE:GetRandomPointVec3() function ZONE_BASE:GetRandomPointVec3()
return nil return nil
end end
@@ -534,6 +535,19 @@ function ZONE_BASE:GetZoneProbability()
return self.ZoneProbability return self.ZoneProbability
end end
--- Get the coordinate on the radius of the zone nearest to Outsidecoordinate. Useto e.g. find an ingress point.
-- @param #ZONE_BASE self
-- @param Core.Point#COORDINATE Outsidecoordinate The coordinate outside of the zone from where to look.
-- @return Core.Point#COORDINATE CoordinateOnRadius
function ZONE_BASE:FindNearestCoordinateOnRadius(Outsidecoordinate)
local Vec1 = self:GetVec2()
local Radius = self:GetRadius()
local Vec2 = Outsidecoordinate:GetVec2()
local Point = UTILS.FindNearestPointOnCircle(Vec1,Radius,Vec2)
local rc = COORDINATE:NewFromVec2(Point)
return rc
end
--- Get the zone taking into account the randomization probability of a zone to be selected. --- Get the zone taking into account the randomization probability of a zone to be selected.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor. -- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor.
@@ -599,6 +613,8 @@ end
-- --
-- -- Stop watching the zone after 1 hour -- -- Stop watching the zone after 1 hour
-- triggerzone:__TriggerStop(3600) -- triggerzone:__TriggerStop(3600)
-- -- Call :SetPartlyInside() if you use SET_GROUP to count as inside when any of their units enters even when they are far apart.
-- -- Make sure to call :SetPartlyInside() before :Trigger()!
function ZONE_BASE:Trigger(Objects) function ZONE_BASE:Trigger(Objects)
--self:I("Added Zone Trigger") --self:I("Added Zone Trigger")
self:SetStartState("TriggerStopped") self:SetStartState("TriggerStopped")
@@ -667,6 +683,16 @@ function ZONE_BASE:Trigger(Objects)
end end
--- Toggle “partly-inside” handling for this zone. To be used before :Trigger().
-- * Default:* flag is **false** until you call the method.
-- * Call with no argument or with **true** → enable.
-- * Call with **false** → disable again (handy if it was enabled before).
-- @param #ZONE_BASE self
-- @return #ZONE_BASE self
function ZONE_BASE:SetPartlyInside(state)
self.PartlyInside = state or not ( state == false )
return self
end
--- (Internal) Check the assigned objects for being in/out of the zone --- (Internal) Check the assigned objects for being in/out of the zone
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param #boolean fromstart If true, do the init of the objects -- @param #boolean fromstart If true, do the init of the objects
@@ -705,7 +731,12 @@ function ZONE_BASE:_TriggerCheck(fromstart)
obj.TriggerInZone[self.ZoneName] = false obj.TriggerInZone[self.ZoneName] = false
end end
-- is obj in zone? -- is obj in zone?
local inzone = self:IsCoordinateInZone(obj:GetCoordinate()) local inzone
if self.PartlyInside and obj.ClassName == "GROUP" then
inzone = obj:IsAnyInZone(self) -- TRUE if any unit is inside
else
inzone = self:IsCoordinateInZone(obj:GetCoordinate()) -- original barycentre test
end
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone)) --self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
if inzone and obj.TriggerInZone[self.ZoneName] then if inzone and obj.TriggerInZone[self.ZoneName] then
-- just count -- just count
@@ -814,8 +845,8 @@ end
-- Various functions exist to find random points within the zone. -- Various functions exist to find random points within the zone.
-- --
-- * @{#ZONE_RADIUS.GetRandomVec2}(): Gets a random 2D point in the zone. -- * @{#ZONE_RADIUS.GetRandomVec2}(): Gets a random 2D point in the zone.
-- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Core.Point#POINT_VEC2} object representing a random 2D point in the zone. -- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Core.Point#COORDINATE} object representing a random 2D point in the zone.
-- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Core.Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight. -- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Core.Point#COORDINATE} object representing a random 3D point in the zone. Note that the height of the point is at landheight.
-- --
-- ## Draw zone -- ## Draw zone
-- --
@@ -1010,7 +1041,7 @@ function ZONE_RADIUS:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset )
local Radial = ( Angle + AngleOffset ) * RadialBase / 360 local Radial = ( Angle + AngleOffset ) * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius() Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius() Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Smoke( SmokeColor ) COORDINATE:New( Point.x, AddHeight, Point.y ):Smoke( SmokeColor )
end end
return self return self
@@ -1040,7 +1071,7 @@ function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth, AddHeight )
local Radial = Angle * RadialBase / 360 local Radial = Angle * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius() Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius() Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Flare( FlareColor, Azimuth ) COORDINATE:New( Point.x, AddHeight, Point.y ):Flare( FlareColor, Azimuth )
end end
return self return self
@@ -1509,6 +1540,26 @@ function ZONE_RADIUS:IsVec3InZone( Vec3 )
return InZone return InZone
end end
--- Search for clear ground spawn zones within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
-- @param #ZONE_RADIUS self
-- @param #number PosRadius Required clear radius around each position.
-- @param #number NumPositions Number of positions to find.
-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius. nil if no clear positions are found.
function ZONE_RADIUS:GetClearZonePositions(PosRadius, NumPositions)
return UTILS.GetClearZonePositions(self, PosRadius, NumPositions)
end
--- Search for a random clear ground spawn coordinate within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
-- @param #ZONE_RADIUS self
-- @param #number PosRadius (Optional) Required clear radius around each position. (Default is math.min(Radius/10, 200))
-- @param #number NumPositions (Optional) Number of positions to find. (Default 50)
-- @return Core.Point#COORDINATE A random coordinate for a clear zone. nil if no clear positions are found.
-- @return #number Assigned radius for the found zones. nil if no clear positions are found.
function ZONE_RADIUS:GetRandomClearZoneCoordinate(PosRadius, NumPositions)
return UTILS.GetRandomClearZoneCoordinate(self, PosRadius, NumPositions)
end
--- Returns a random Vec2 location within the zone. --- Returns a random Vec2 location within the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number inner (Optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (Optional) Minimal distance from the center of the zone. Default is 0.
@@ -1521,6 +1572,10 @@ function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes)
local _inner = inner or 0 local _inner = inner or 0
local _outer = outer or self:GetRadius() local _outer = outer or self:GetRadius()
math.random()
math.random()
math.random()
if surfacetypes and type(surfacetypes)~="table" then if surfacetypes and type(surfacetypes)~="table" then
surfacetypes={surfacetypes} surfacetypes={surfacetypes}
end end
@@ -1561,15 +1616,15 @@ function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes)
return point return point
end end
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. --- Returns a @{Core.Point#COORDINATE} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone. -- @return Core.Point#COORDINATE The @{Core.Point#COORDINATE} object reflecting the random 3D location within the zone.
function ZONE_RADIUS:GetRandomPointVec2( inner, outer ) function ZONE_RADIUS:GetRandomPointVec2( inner, outer )
--self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2( inner, outer ) ) local PointVec2 = COORDINATE:NewFromVec2( self:GetRandomVec2( inner, outer ) )
--self:T3( { PointVec2 } ) --self:T3( { PointVec2 } )
@@ -1592,15 +1647,15 @@ function ZONE_RADIUS:GetRandomVec3( inner, outer )
end end
--- Returns a @{Core.Point#POINT_VEC3} object reflecting a random 3D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table. --- Returns a @{Core.Point#COORDINATE} object reflecting a random 3D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC3 The @{Core.Point#POINT_VEC3} object reflecting the random 3D location within the zone. -- @return Core.Point#COORDINATE The @{Core.Point#COORDINATE} object reflecting the random 3D location within the zone.
function ZONE_RADIUS:GetRandomPointVec3( inner, outer ) function ZONE_RADIUS:GetRandomPointVec3( inner, outer )
--self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2( inner, outer ) ) local PointVec3 = COORDINATE:NewFromVec2( self:GetRandomVec2( inner, outer ) )
--self:T3( { PointVec3 } ) --self:T3( { PointVec3 } )
@@ -2036,15 +2091,15 @@ function ZONE_GROUP:GetRandomVec2()
return Point return Point
end end
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. --- Returns a @{Core.Point#COORDINATE} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_GROUP self -- @param #ZONE_GROUP self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone. -- @return Core.Point#COORDINATE The @{Core.Point#COORDINATE} object reflecting the random 3D location within the zone.
function ZONE_GROUP:GetRandomPointVec2( inner, outer ) function ZONE_GROUP:GetRandomPointVec2( inner, outer )
--self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() ) local PointVec2 = COORDINATE:NewFromVec2( self:GetRandomVec2() )
--self:T3( { PointVec2 } ) --self:T3( { PointVec2 } )
@@ -2192,8 +2247,8 @@ end
-- Various functions exist to find random points within the zone. -- Various functions exist to find random points within the zone.
-- --
-- * @{#ZONE_POLYGON_BASE.GetRandomVec2}(): Gets a random 2D point in the zone. -- * @{#ZONE_POLYGON_BASE.GetRandomVec2}(): Gets a random 2D point in the zone.
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Core.Point#POINT_VEC2} object representing a random 2D point within the zone. -- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Core.Point#COORDINATE} object representing a random 2D point within the zone.
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone. -- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Core.Point#COORDINATE} object representing a random 3D point at landheight within the zone.
-- --
-- ## Draw zone -- ## Draw zone
-- --
@@ -2487,6 +2542,26 @@ function ZONE_POLYGON_BASE:Flush()
return self return self
end end
--- Search for clear ground spawn zones within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
-- @param #ZONE_POLYGON_BASE self
-- @param #number PosRadius Required clear radius around each position.
-- @param #number NumPositions Number of positions to find.
-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius. nil if no clear positions are found.
function ZONE_POLYGON_BASE:GetClearZonePositions(PosRadius, NumPositions)
return UTILS.GetClearZonePositions(self, PosRadius, NumPositions)
end
--- Search for a random clear ground spawn coordinate within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
-- @param #ZONE_POLYGON_BASE self
-- @param #number PosRadius (Optional) Required clear radius around each position. (Default is math.min(Radius/10, 200))
-- @param #number NumPositions (Optional) Number of positions to find. (Default 50)
-- @return Core.Point#COORDINATE A random coordinate for a clear zone. nil if no clear positions are found.
-- @return #number Assigned radius for the found zones. nil if no clear positions are found.
function ZONE_POLYGON_BASE:GetRandomClearZoneCoordinate(PosRadius, NumPositions)
return UTILS.GetRandomClearZoneCoordinate(self, PosRadius, NumPositions)
end
--- Smokes the zone boundaries in a color. --- Smokes the zone boundaries in a color.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @param #boolean UnBound If true, the tyres will be destroyed. -- @param #boolean UnBound If true, the tyres will be destroyed.
@@ -2769,7 +2844,7 @@ function ZONE_POLYGON_BASE:SmokeZone( SmokeColor, Segments )
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line. for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments ) local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments ) local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments )
POINT_VEC2:New( PointX, PointY ):Smoke( SmokeColor ) COORDINATE:New( PointX, 0, PointY ):Smoke( SmokeColor )
end end
j = i j = i
i = i + 1 i = i + 1
@@ -2804,7 +2879,7 @@ function ZONE_POLYGON_BASE:FlareZone( FlareColor, Segments, Azimuth, AddHeight )
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line. for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments ) local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments ) local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments )
POINT_VEC2:New( PointX, PointY, AddHeight ):Flare(FlareColor, Azimuth) COORDINATE:New( PointX, AddHeight, PointY ):Flare(FlareColor, Azimuth)
end end
j = i j = i
i = i + 1 i = i + 1
@@ -2865,6 +2940,11 @@ end
function ZONE_POLYGON_BASE:GetRandomVec2() function ZONE_POLYGON_BASE:GetRandomVec2()
-- make sure we assign weights to the triangles based on their surface area, otherwise -- make sure we assign weights to the triangles based on their surface area, otherwise
-- we'll be more likely to generate random points in smaller triangles -- we'll be more likely to generate random points in smaller triangles
math.random()
math.random()
math.random()
local weights = {} local weights = {}
for _, triangle in pairs(self._Triangles) do for _, triangle in pairs(self._Triangles) do
weights[triangle] = triangle.SurfaceArea / self.SurfaceArea weights[triangle] = triangle.SurfaceArea / self.SurfaceArea
@@ -2880,26 +2960,26 @@ function ZONE_POLYGON_BASE:GetRandomVec2()
end end
end end
--- Return a @{Core.Point#POINT_VEC2} object representing a random 2D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. --- Return a @{Core.Point#COORDINATE} object representing a random 2D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return @{Core.Point#POINT_VEC2} -- @return @{Core.Point#COORDINATE}
function ZONE_POLYGON_BASE:GetRandomPointVec2() function ZONE_POLYGON_BASE:GetRandomPointVec2()
--self:F2() --self:F2()
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() ) local PointVec2 = COORDINATE:NewFromVec2( self:GetRandomVec2() )
--self:T2( PointVec2 ) --self:T2( PointVec2 )
return PointVec2 return PointVec2
end end
--- Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table. --- Return a @{Core.Point#COORDINATE} object representing a random 3D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return @{Core.Point#POINT_VEC3} -- @return @{Core.Point#COORDINATE}
function ZONE_POLYGON_BASE:GetRandomPointVec3() function ZONE_POLYGON_BASE:GetRandomPointVec3()
--self:F2() --self:F2()
local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2() ) local PointVec3 = COORDINATE:NewFromVec2( self:GetRandomVec2() )
--self:T2( PointVec3 ) --self:T2( PointVec3 )
@@ -3204,12 +3284,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
local vectors = self:GetBoundingSquare() local vectors = self:GetBoundingSquare()
local minVec3 = {x=vectors.x1, y=0, z=vectors.y1} local ZoneRadius = UTILS.VecDist2D({x=vectors.x1, y=vectors.y1}, {x=vectors.x2, y=vectors.y2})/2
local maxVec3 = {x=vectors.x2, y=0, z=vectors.y2}
local minmarkcoord = COORDINATE:NewFromVec3(minVec3)
local maxmarkcoord = COORDINATE:NewFromVec3(maxVec3)
local ZoneRadius = minmarkcoord:Get2DDistance(maxmarkcoord)/2
-- self:I("Scan Radius:" ..ZoneRadius) -- self:I("Scan Radius:" ..ZoneRadius)
local CenterVec3 = self:GetCoordinate():GetVec3() local CenterVec3 = self:GetCoordinate():GetVec3()
@@ -3931,18 +4006,18 @@ function ZONE_OVAL:GetRandomVec2()
return {x=rx, y=ry} return {x=rx, y=ry}
end end
--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. --- Define a random @{Core.Point#COORDINATE} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_OVAL self -- @param #ZONE_OVAL self
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates. -- @return Core.Point#COORDINATE The COORDINATE coordinates.
function ZONE_OVAL:GetRandomPointVec2() function ZONE_OVAL:GetRandomPointVec2()
return POINT_VEC2:NewFromVec2(self:GetRandomVec2()) return COORDINATE:NewFromVec2(self:GetRandomVec2())
end end
--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table. --- Define a random @{Core.Point#COORDINATE} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
-- @param #ZONE_OVAL self -- @param #ZONE_OVAL self
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates. -- @return Core.Point#COORDINATE The COORDINATE coordinates.
function ZONE_OVAL:GetRandomPointVec3() function ZONE_OVAL:GetRandomPointVec3()
return POINT_VEC3:NewFromVec3(self:GetRandomVec2()) return COORDINATE:NewFromVec3(self:GetRandomVec2())
end end
--- Draw the zone on the F10 map. --- Draw the zone on the F10 map.
@@ -4082,15 +4157,15 @@ do -- ZONE_AIRBASE
return ZoneVec2 return ZoneVec2
end end
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. --- Returns a @{Core.Point#COORDINATE} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_AIRBASE self -- @param #ZONE_AIRBASE self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone. -- @return Core.Point#COORDINATE The @{Core.Point#COORDINATE} object reflecting the random 3D location within the zone.
function ZONE_AIRBASE:GetRandomPointVec2( inner, outer ) function ZONE_AIRBASE:GetRandomPointVec2( inner, outer )
--self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() ) local PointVec2 = COORDINATE:NewFromVec2( self:GetRandomVec2() )
--self:T3( { PointVec2 } ) --self:T3( { PointVec2 } )

View File

@@ -107,7 +107,7 @@ function ZONE_DETECTION:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset )
local Radial = ( Angle + AngleOffset ) * RadialBase / 360 local Radial = ( Angle + AngleOffset ) * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius() Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius() Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Smoke( SmokeColor ) COORDINATE:New( Point.x, AddHeight, Point.y):Smoke( SmokeColor )
end end
return self return self
@@ -138,7 +138,7 @@ function ZONE_DETECTION:FlareZone( FlareColor, Points, Azimuth, AddHeight )
local Radial = Angle * RadialBase / 360 local Radial = Angle * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius() Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius() Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Flare( FlareColor, Azimuth ) COORDINATE:New( Point.x, AddHeight, Point.y ):Flare( FlareColor, Azimuth )
end end
return self return self
@@ -202,4 +202,3 @@ function ZONE_DETECTION:IsVec3InZone( Vec3 )
return InZone return InZone
end end

View File

@@ -198,7 +198,7 @@ end -- env
do -- radio do -- radio
---@type radio --@type radio
-- @field #radio.modulation modulation -- @field #radio.modulation modulation
--- ---

View File

@@ -22,7 +22,7 @@
-- === -- ===
-- --
-- ### Author: **Applevangelist** -- ### Author: **Applevangelist**
-- Last Update Sept 2023 -- Last Update July 2025
-- --
-- === -- ===
-- @module Functional.AICSAR -- @module Functional.AICSAR
@@ -57,6 +57,8 @@
-- @field #number Speed Default speed setting for the helicopter FLIGHTGROUP is 100kn. -- @field #number Speed Default speed setting for the helicopter FLIGHTGROUP is 100kn.
-- @field #boolean UseEventEject In case Event LandingAfterEjection isn't working, use set this to true. -- @field #boolean UseEventEject In case Event LandingAfterEjection isn't working, use set this to true.
-- @field #number Delay In case of UseEventEject wait this long until we spawn a landed pilot. -- @field #number Delay In case of UseEventEject wait this long until we spawn a landed pilot.
-- @field #boolean UseRescueZone If true, use a rescue zone and not the max distance to FARP/MASH
-- @field Core.Zone#ZONE_RADIUS RescueZone Use this zone as operational area for the AICSAR instance.
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
@@ -153,10 +155,10 @@
-- To set up AICSAR for SRS TTS output, add e.g. the following to your script: -- To set up AICSAR for SRS TTS output, add e.g. the following to your script:
-- --
-- -- setup for google TTS, radio 243 AM, SRS server port 5002 with a google standard-quality voice (google cloud account required) -- -- setup for google TTS, radio 243 AM, SRS server port 5002 with a google standard-quality voice (google cloud account required)
-- my_aicsar:SetSRSTTSRadio(true,"C:\\Program Files\\DCS-SimpleRadio-Standalone",243,radio.modulation.AM,5002,MSRS.Voices.Google.Standard.en_US_Standard_D,"en-US","female","C:\\Program Files\\DCS-SimpleRadio-Standalone\\google.json") -- my_aicsar:SetSRSTTSRadio(true,"C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",243,radio.modulation.AM,5002,MSRS.Voices.Google.Standard.en_US_Standard_D,"en-US","female","C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio\\google.json")
-- --
-- -- alternatively for MS Desktop TTS (voices need to be installed locally first!) -- -- alternatively for MS Desktop TTS (voices need to be installed locally first!)
-- my_aicsar:SetSRSTTSRadio(true,"C:\\Program Files\\DCS-SimpleRadio-Standalone",243,radio.modulation.AM,5002,MSRS.Voices.Microsoft.Hazel,"en-GB","female") -- my_aicsar:SetSRSTTSRadio(true,"C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",243,radio.modulation.AM,5002,MSRS.Voices.Microsoft.Hazel,"en-GB","female")
-- --
-- -- define a different voice for the downed pilot(s) -- -- define a different voice for the downed pilot(s)
-- my_aicsar:SetPilotTTSVoice(MSRS.Voices.Google.Standard.en_AU_Standard_D,"en-AU","male") -- my_aicsar:SetPilotTTSVoice(MSRS.Voices.Google.Standard.en_AU_Standard_D,"en-AU","male")
@@ -177,7 +179,7 @@
-- --
-- Switch on radio transmissions via **either** SRS **or** "normal" DCS radio e.g. like so: -- Switch on radio transmissions via **either** SRS **or** "normal" DCS radio e.g. like so:
-- --
-- my_aicsar:SetSRSRadio(true,"C:\\Program Files\\DCS-SimpleRadio-Standalone",270,radio.modulation.AM,nil,5002) -- my_aicsar:SetSRSRadio(true,"C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",270,radio.modulation.AM,nil,5002)
-- --
-- or -- or
-- --
@@ -191,7 +193,7 @@
-- @field #AICSAR -- @field #AICSAR
AICSAR = { AICSAR = {
ClassName = "AICSAR", ClassName = "AICSAR",
version = "0.1.16", version = "0.1.18",
lid = "", lid = "",
coalition = coalition.side.BLUE, coalition = coalition.side.BLUE,
template = "", template = "",
@@ -236,6 +238,8 @@ AICSAR = {
Altitude = 1500, Altitude = 1500,
UseEventEject = false, UseEventEject = false,
Delay = 100, Delay = 100,
UseRescueZone = false,
RescueZone = nil,
} }
-- TODO Messages -- TODO Messages
@@ -304,8 +308,9 @@ AICSAR.RadioLength = {
-- @param #string Helotemplate Helicopter template name. -- @param #string Helotemplate Helicopter template name.
-- @param Wrapper.Airbase#AIRBASE FARP FARP object or Airbase from where to start. -- @param Wrapper.Airbase#AIRBASE FARP FARP object or Airbase from where to start.
-- @param Core.Zone#ZONE MASHZone Zone where to drop pilots after rescue. -- @param Core.Zone#ZONE MASHZone Zone where to drop pilots after rescue.
-- @param #number Helonumber Max number of alive Ai Helos at the same time. Defaults to three.
-- @return #AICSAR self -- @return #AICSAR self
function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone) function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone,Helonumber)
-- Inherit everything from FSM class. -- Inherit everything from FSM class.
local self=BASE:Inherit(self, FSM:New()) local self=BASE:Inherit(self, FSM:New())
@@ -373,7 +378,7 @@ function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone)
-- limit number of available helos at the same time -- limit number of available helos at the same time
self.limithelos = true self.limithelos = true
self.helonumber = 3 self.helonumber = Helonumber or 3
-- localization -- localization
self:InitLocalization() self:InitLocalization()
@@ -524,10 +529,20 @@ function AICSAR:InitLocalization()
return self return self
end end
--- [User] Use a defined zone as area of operation and not the distance to FARP.
-- @param #AICSAR self
-- @param Core.Zone#ZONE Zone The operational zone to use. Downed pilots in this area will be rescued. Can be any known #ZONE type.
-- @return #AICSAR self
function AICSAR:SetUsingRescueZone(Zone)
self.UseRescueZone = true
self.RescueZone = Zone
return self
end
--- [User] Switch sound output on and use SRS output for sound files. --- [User] Switch sound output on and use SRS output for sound files.
-- @param #AICSAR self -- @param #AICSAR self
-- @param #boolean OnOff Switch on (true) or off (false). -- @param #boolean OnOff Switch on (true) or off (false).
-- @param #string Path Path to your SRS Server Component, e.g. "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone" -- @param #string Path Path to your SRS Server External Audio Component, e.g. "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone\\\\ExternalAudio"
-- @param #number Frequency Defaults to 243 (guard) -- @param #number Frequency Defaults to 243 (guard)
-- @param #number Modulation Radio modulation. Defaults to radio.modulation.AM -- @param #number Modulation Radio modulation. Defaults to radio.modulation.AM
-- @param #string SoundPath Where to find the audio files. Defaults to nil, i.e. add messages via "Sound to..." in the Mission Editor. -- @param #string SoundPath Where to find the audio files. Defaults to nil, i.e. add messages via "Sound to..." in the Mission Editor.
@@ -538,7 +553,7 @@ function AICSAR:SetSRSRadio(OnOff,Path,Frequency,Modulation,SoundPath,Port)
self.SRSRadio = OnOff and true self.SRSRadio = OnOff and true
self.SRSTTSRadio = false self.SRSTTSRadio = false
self.SRSFrequency = Frequency or 243 self.SRSFrequency = Frequency or 243
self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
self.SRS:SetLabel("ACSR") self.SRS:SetLabel("ACSR")
self.SRS:SetCoalition(self.coalition) self.SRS:SetCoalition(self.coalition)
self.SRSModulation = Modulation or radio.modulation.AM self.SRSModulation = Modulation or radio.modulation.AM
@@ -556,7 +571,7 @@ end
-- See `AICSAR:SetPilotTTSVoice()` and `AICSAR:SetOperatorTTSVoice()` -- See `AICSAR:SetPilotTTSVoice()` and `AICSAR:SetOperatorTTSVoice()`
-- @param #AICSAR self -- @param #AICSAR self
-- @param #boolean OnOff Switch on (true) or off (false). -- @param #boolean OnOff Switch on (true) or off (false).
-- @param #string Path Path to your SRS Server Component, e.g. "E:\\\\Program Files\\\\DCS-SimpleRadio-Standalone" -- @param #string Path Path to your SRS Server Component, e.g. "E:\\\\Program Files\\\\DCS-SimpleRadio-Standalone\\ExternalAudio"
-- @param #number Frequency (Optional) Defaults to 243 (guard) -- @param #number Frequency (Optional) Defaults to 243 (guard)
-- @param #number Modulation (Optional) Radio modulation. Defaults to radio.modulation.AM -- @param #number Modulation (Optional) Radio modulation. Defaults to radio.modulation.AM
-- @param #number Port (Optional) Port of the SRS, defaults to 5002. -- @param #number Port (Optional) Port of the SRS, defaults to 5002.
@@ -570,7 +585,7 @@ function AICSAR:SetSRSTTSRadio(OnOff,Path,Frequency,Modulation,Port,Voice,Cultur
self.SRSTTSRadio = OnOff and true self.SRSTTSRadio = OnOff and true
self.SRSRadio = false self.SRSRadio = false
self.SRSFrequency = Frequency or 243 self.SRSFrequency = Frequency or 243
self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
self.SRSModulation = Modulation or radio.modulation.AM self.SRSModulation = Modulation or radio.modulation.AM
self.SRSPort = Port or MSRS.port or 5002 self.SRSPort = Port or MSRS.port or 5002
if OnOff then if OnOff then
@@ -693,7 +708,7 @@ function AICSAR:_EjectEventHandler(EventData)
local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p) local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p)
local _country = _event.initiator:getCountry() local _country = _event.initiator:getCountry()
local _coalition = coalition.getCountryCoalition( _country ) local _coalition = coalition.getCountryCoalition( _country )
local data = UTILS.DeepCopy(EventData) --local data = UTILS.DeepCopy(EventData)
Unit.destroy(_event.initiator) -- shagrat remove static Pilot model Unit.destroy(_event.initiator) -- shagrat remove static Pilot model
self:ScheduleOnce(self.Delay,self._DelayedSpawnPilot,self,_LandingPos,_coalition) self:ScheduleOnce(self.Delay,self._DelayedSpawnPilot,self,_LandingPos,_coalition)
end end
@@ -709,6 +724,13 @@ end
function AICSAR:_DelayedSpawnPilot(_LandingPos,_coalition) function AICSAR:_DelayedSpawnPilot(_LandingPos,_coalition)
local distancetofarp = _LandingPos:Get2DDistance(self.farp:GetCoordinate()) local distancetofarp = _LandingPos:Get2DDistance(self.farp:GetCoordinate())
if self.UseRescueZone == true and self.RescueZone ~= nil then
if self.RescueZone:IsCoordinateInZone(_LandingPos) then
distancetofarp = self.maxdistance - 10
else
distancetofarp = self.maxdistance + 10
end
end
-- Mayday Message -- Mayday Message
local Text,Soundfile,Soundlength,Subtitle = self.gettext:GetEntry("PILOTDOWN",self.locale) local Text,Soundfile,Soundlength,Subtitle = self.gettext:GetEntry("PILOTDOWN",self.locale)
local text = "" local text = ""
@@ -795,7 +817,13 @@ function AICSAR:_EventHandler(EventData, FromEject)
-- DONE: add distance check -- DONE: add distance check
local distancetofarp = _LandingPos:Get2DDistance(self.farp:GetCoordinate()) local distancetofarp = _LandingPos:Get2DDistance(self.farp:GetCoordinate())
if self.UseRescueZone == true and self.RescueZone ~= nil then
if self.RescueZone:IsCoordinateInZone(_LandingPos) then
distancetofarp = self.maxdistance - 10
else
distancetofarp = self.maxdistance + 10
end
end
-- Mayday Message -- Mayday Message
local Text,Soundfile,Soundlength,Subtitle = self.gettext:GetEntry("PILOTDOWN",self.locale) local Text,Soundfile,Soundlength,Subtitle = self.gettext:GetEntry("PILOTDOWN",self.locale)
local text = "" local text = ""
@@ -817,7 +845,6 @@ function AICSAR:_EventHandler(EventData, FromEject)
if _coalition == self.coalition then if _coalition == self.coalition then
if self.verbose then if self.verbose then
MESSAGE:New(msgtxt,15,"AICSAR"):ToCoalition(self.coalition) MESSAGE:New(msgtxt,15,"AICSAR"):ToCoalition(self.coalition)
-- MESSAGE:New(msgtxt,15,"AICSAR"):ToLog()
end end
if self.SRSRadio then if self.SRSRadio then
local sound = SOUNDFILE:New(Soundfile,self.SRSSoundPath,Soundlength) local sound = SOUNDFILE:New(Soundfile,self.SRSSoundPath,Soundlength)
@@ -869,6 +896,7 @@ function AICSAR:_GetFlight()
:InitUnControlled(true) :InitUnControlled(true)
:OnSpawnGroup( :OnSpawnGroup(
function(Group) function(Group)
Group:OptionPreferVerticalLanding()
self:__HeloOnDuty(1,Group) self:__HeloOnDuty(1,Group)
end end
) )
@@ -934,6 +962,10 @@ function AICSAR:_InitMission(Pilot,Index)
helo:__UnloadingDone(5) helo:__UnloadingDone(5)
end end
function helo:OnAfterLandAtAirbase(From,Event,To,airbase)
helo:Despawn(2)
end
self.helos[Index] = helo self.helos[Index] = helo
return self return self
@@ -984,7 +1016,9 @@ function AICSAR:_CheckHelos()
local name = helo:GetName() local name = helo:GetName()
self:T("Helo group "..name.." in state "..state) self:T("Helo group "..name.." in state "..state)
if state == "Arrived" then if state == "Arrived" then
helo:__Stop(5) --helo:__Stop(5)
helo.OnAfterDead = nil
helo:Despawn(35)
self.helos[_index] = nil self.helos[_index] = nil
end end
else else
@@ -1025,7 +1059,7 @@ function AICSAR:_CheckQueue(OpsGroup)
if self:_CheckInMashZone(_pilot) then if self:_CheckInMashZone(_pilot) then
self:T("Pilot" .. _pilot.GroupName .. " rescued!") self:T("Pilot" .. _pilot.GroupName .. " rescued!")
if OpsGroup then if OpsGroup then
OpsGroup:Despawn(10) --OpsGroup:Despawn(10)
else else
_pilot:Destroy(true,10) _pilot:Destroy(true,10)
end end

View File

@@ -105,7 +105,7 @@ AUTOLASE = {
debug = false, debug = false,
smokemenu = true, smokemenu = true,
RoundingPrecision = 0, RoundingPrecision = 0,
increasegroundawareness = true, increasegroundawareness = false,
MonitorFrequency = 30, MonitorFrequency = 30,
} }
@@ -216,7 +216,7 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
self.smokemenu = true self.smokemenu = true
self.threatmenu = true self.threatmenu = true
self.RoundingPrecision = 0 self.RoundingPrecision = 0
self.increasegroundawareness = true self.increasegroundawareness = false
self.MonitorFrequency = 30 self.MonitorFrequency = 30
self:EnableSmokeMenu({Angle=math.random(0,359),Distance=math.random(10,20)}) self:EnableSmokeMenu({Angle=math.random(0,359),Distance=math.random(10,20)})
@@ -493,7 +493,7 @@ end
--- (User) Function enable sending messages via SRS. --- (User) Function enable sending messages via SRS.
-- @param #AUTOLASE self -- @param #AUTOLASE self
-- @param #boolean OnOff Switch usage on and off -- @param #boolean OnOff Switch usage on and off
-- @param #string Path Path to SRS directory, e.g. C:\\Program Files\\DCS-SimpleRadio-Standalone -- @param #string Path Path to SRS TTS directory, e.g. C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio
-- @param #number Frequency Frequency to send, e.g. 243 -- @param #number Frequency Frequency to send, e.g. 243
-- @param #number Modulation Modulation i.e. radio.modulation.AM or radio.modulation.FM -- @param #number Modulation Modulation i.e. radio.modulation.AM or radio.modulation.FM
-- @param #string Label (Optional) Short label to be used on the SRS Client Overlay -- @param #string Label (Optional) Short label to be used on the SRS Client Overlay
@@ -508,7 +508,7 @@ end
function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation,Label,Gender,Culture,Port,Voice,Volume,PathToGoogleKey) function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation,Label,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
if OnOff then if OnOff then
self.useSRS = true self.useSRS = true
self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" self.SRSPath = Path or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
self.SRSFreq = Frequency or 271 self.SRSFreq = Frequency or 271
self.SRSMod = Modulation or radio.modulation.AM self.SRSMod = Modulation or radio.modulation.AM
self.Gender = Gender or MSRS.gender or "male" self.Gender = Gender or MSRS.gender or "male"
@@ -1020,7 +1020,7 @@ function AUTOLASE:_Prescient()
self:T(self.lid.."Checking possibly visible STATICs for Recce "..unit:GetName()) self:T(self.lid.."Checking possibly visible STATICs for Recce "..unit:GetName())
for _,_static in pairs(Statics) do -- DCS static object here for _,_static in pairs(Statics) do -- DCS static object here
local static = STATIC:Find(_static) local static = STATIC:Find(_static)
if static and static:GetCoalition() ~= self.coalition then if static and static:GetCoalition() ~= self.coalition and static:GetCoordinate() then
local IsLOS = position:IsLOS(static:GetCoordinate()) local IsLOS = position:IsLOS(static:GetCoordinate())
if IsLOS then if IsLOS then
unit:KnowUnit(static,true,true) unit:KnowUnit(static,true,true)

View File

@@ -22,7 +22,7 @@
-- @module Functional.Mantis -- @module Functional.Mantis
-- @image Functional.Mantis.jpg -- @image Functional.Mantis.jpg
-- --
-- Last Update: Mar 2025 -- Last Update: August 2025
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **MANTIS** class, extends Core.Base#BASE --- **MANTIS** class, extends Core.Base#BASE
@@ -62,7 +62,9 @@
-- @field #table FilterZones Table of Core.Zone#ZONE Zones Consider SAM groups in this zone(s) only for this MANTIS instance, must be handed as #table of Zone objects. -- @field #table FilterZones Table of Core.Zone#ZONE Zones Consider SAM groups in this zone(s) only for this MANTIS instance, must be handed as #table of Zone objects.
-- @field #boolean SmokeDecoy If true, smoke short range SAM units as decoy if a plane is in firing range. -- @field #boolean SmokeDecoy If true, smoke short range SAM units as decoy if a plane is in firing range.
-- @field #number SmokeDecoyColor Color to use, defaults to SMOKECOLOR.White -- @field #number SmokeDecoyColor Color to use, defaults to SMOKECOLOR.White
-- @field #number checkcounter Counter for SAM Table refreshes -- @field #number checkcounter Counter for SAM Table refreshes.
-- @field #number DLinkCacheTime Seconds after which cached contacts in DLink will decay.
-- @field #boolean logsamstatus Log SAM status in dcs.log every cycle if true
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@@ -74,10 +76,9 @@
-- --
-- * Moose derived Modular, Automatic and Network capable Targeting and Interception System. -- * Moose derived Modular, Automatic and Network capable Targeting and Interception System.
-- * Controls a network of SAM sites. Uses detection to switch on the SAM site closest to the enemy. -- * Controls a network of SAM sites. Uses detection to switch on the SAM site closest to the enemy.
-- * **Automatic mode** (default since 0.8) will set-up your SAM site network automatically for you -- * **Automatic mode** (default) will set-up your SAM site network automatically for you.
-- * **Classic mode** behaves like before -- * Leverage evasiveness from SEAD, leverage attack range setting.
-- * Leverage evasiveness from SEAD, leverage attack range setting -- * Automatic setup of SHORAD based on groups of the class "short-range".
-- * Automatic setup of SHORAD based on groups of the class "short-range"
-- --
-- # 0. Base considerations and naming conventions -- # 0. Base considerations and naming conventions
-- --
@@ -107,10 +108,15 @@
-- * Patriot -- * Patriot
-- * Rapier -- * Rapier
-- * Roland -- * Roland
-- * IRIS-T SLM
-- * Pantsir S1
-- * TOR M2
-- * C-RAM
-- * Silkworm (though strictly speaking this is a surface to ship missile) -- * Silkworm (though strictly speaking this is a surface to ship missile)
-- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19 -- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19
-- * From IDF mod: STUNNER IDFA, TAMIR IDFA (Note all caps!) -- * From IDF mod: STUNNER IDFA, TAMIR IDFA (Note all caps!)
-- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2 -- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2, SAMP/T Block 1, SAMP/T Block 1INT, SAMP/T Block2
-- * Other Mods: Nike
-- --
-- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M -- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M
-- **NOTE** If you are using the Swedish Military Assets (SMA), please note that the **group name** for RBS-SAM types also needs to contain the keyword "SMA" -- **NOTE** If you are using the Swedish Military Assets (SMA), please note that the **group name** for RBS-SAM types also needs to contain the keyword "SMA"
@@ -124,19 +130,20 @@
-- * SA-2 (with V759 missile, e.g. "Red SAM SA-2 HDS") -- * SA-2 (with V759 missile, e.g. "Red SAM SA-2 HDS")
-- * SA-2 (with HQ-2 launcher, use HQ-2 in the group name, e.g. "Red SAM HQ-2" ) -- * SA-2 (with HQ-2 launcher, use HQ-2 in the group name, e.g. "Red SAM HQ-2" )
-- * SA-3 (with V601P missile, e.g. "Red SAM SA-3 HDS") -- * SA-3 (with V601P missile, e.g. "Red SAM SA-3 HDS")
-- * SA-10B (overlap with other SA-10 types, e.g. "Red SAM SA-10B HDS") -- * SA-10B (overlap with other SA-10 types, e.g. "Red SAM SA-10B HDS" with 5P85CE launcher)
-- * SA-10C (overlap with other SA-10 types, e.g. "Red SAM SA-10C HDS") -- * SA-10C (overlap with other SA-10 types, e.g. "Red SAM SA-10C HDS" with 5P85SE launcher)
-- * SA-12 (launcher dependent range, e.g. "Red SAM SA-12 HDS") -- * SA-12 (launcher dependent range, e.g. "Red SAM SA-12 HDS 2" for the 9A82 variant and "Red SAM SA-12 HDS 1" for the 9A83 variant)
-- * SA-23 (launcher dependent range, e.g. "Red SAM SA-23 HDS") -- * SA-23 (launcher dependent range, e.g. "Red SAM SA-23 HDS 2" for the 9A82ME variant and "Red SAM SA-23 HDS 1" for the 9A83ME variant)
-- * SAMP/T (launcher dependent range, e.g. "Blue SAM SAMPT Block 1 HDS" for Block 1, "Blue SAM SAMPT Block 1INT HDS", "Blue SAM SAMPT Block 2 HDS")
-- --
-- The other HDS types work like the rest of the known SAM systems. -- The other HDS types work like the rest of the known SAM systems.
-- --
-- # 0.1 Set-up in the mission editor -- # 0.1 Set-up in the mission editor
-- --
-- Set up your SAM sites in the mission editor. Name the groups using a systematic approach like above. -- Set up your SAM sites in the mission editor. Name the groups using a systematic approach like above.Can be e.g. AWACS or a combination of AWACS and Search Radars like e.g. EWR 1L13 etc.
-- Set up your EWR system in the mission editor. Name the groups using a systematic approach like above. Can be e.g. AWACS or a combination of AWACS and Search Radars like e.g. EWR 1L13 etc.
-- Search Radars usually have "SR" or "STR" in their names. Use the encyclopedia in the mission editor to inform yourself. -- Search Radars usually have "SR" or "STR" in their names. Use the encyclopedia in the mission editor to inform yourself.
-- Set up your SHORAD systems. They need to be **close** to (i.e. around) the SAM sites to be effective. Use **one** group per SAM location. SA-15 TOR systems offer a good missile defense. -- Set up your SHORAD systems. They need to be **close** to (i.e. around) the SAM sites to be effective. Use **one unit ** per group (multiple groups) for the SAM location.
-- Else, evasive manoevers might club up all defenders in one place. Red SA-15 TOR systems offer a good missile defense.
-- --
-- [optional] Set up your HQ. Can be any group, e.g. a command vehicle. -- [optional] Set up your HQ. Can be any group, e.g. a command vehicle.
-- --
@@ -188,7 +195,7 @@
-- --
-- ## 2.1 Auto mode features -- ## 2.1 Auto mode features
-- --
-- ### 2.1.1 You can now add Accept-, Reject- and Conflict-Zones to your setup, e.g. to consider borders or de-militarized zones: -- ### 2.1.1 You can add Accept-, Reject- and Conflict-Zones to your setup, e.g. to consider borders or de-militarized zones:
-- --
-- -- Parameters are tables of Core.Zone#ZONE objects! -- -- Parameters are tables of Core.Zone#ZONE objects!
-- -- This is effectively a 3-stage filter allowing for zone overlap. A coordinate is accepted first when -- -- This is effectively a 3-stage filter allowing for zone overlap. A coordinate is accepted first when
@@ -206,9 +213,6 @@
-- --
-- ### 2.1.4 Advanced features -- ### 2.1.4 Advanced features
-- --
-- -- Option to switch off auto mode **before** you start MANTIS (not recommended)
-- mybluemantis.automode = false
--
-- -- Option to set the scale of the activation range, i.e. don't activate at the fringes of max range, defaults below. -- -- Option to set the scale of the activation range, i.e. don't activate at the fringes of max range, defaults below.
-- -- also see engagerange below. -- -- also see engagerange below.
-- self.radiusscale[MANTIS.SamType.LONG] = 1.1 -- self.radiusscale[MANTIS.SamType.LONG] = 1.1
@@ -221,6 +225,12 @@
-- -- For some scenarios, like Cold War, it might be useful not to activate SAMs if friendly aircraft are around to avoid death by friendly fire. -- -- For some scenarios, like Cold War, it might be useful not to activate SAMs if friendly aircraft are around to avoid death by friendly fire.
-- mybluemantis.checkforfriendlies = true -- mybluemantis.checkforfriendlies = true
-- --
-- ### 2.1.6 Shoot & Scoot
--
-- -- Option to make the (driveable) SHORAD units drive around and shuffle positions
-- -- We use a SET_ZONE for that, number of zones to consider defaults to three, Random is true for random coordinates and Formation is e.g. "Vee".
-- mybluemantis:AddScootZones(ZoneSet, Number, Random, Formation)
--
-- # 3. Default settings [both modes unless stated otherwise] -- # 3. Default settings [both modes unless stated otherwise]
-- --
-- By default, the following settings are active: -- By default, the following settings are active:
@@ -243,25 +253,7 @@
-- --
-- Use this option if you want to make use of or allow advanced SEAD tactics. -- Use this option if you want to make use of or allow advanced SEAD tactics.
-- --
-- # 5. Integrate SHORAD [classic mode, not necessary in automode, not recommended for manual setup] -- # 5. Integrated SEAD
--
-- You can also choose to integrate Mantis with @{Functional.Shorad#SHORAD} for protection against HARMs and AGMs manually. When SHORAD detects a missile fired at one of MANTIS' SAM sites, it will activate SHORAD systems in
-- the given defense checkradius around that SAM site. Create a SHORAD object first, then integrate with MANTIS like so:
--
-- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()
-- myshorad = SHORAD:New("BlueShorad", "Blue SHORAD", SamSet, 22000, 600, "blue")
-- -- now set up MANTIS
-- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
-- mymantis:AddShorad(myshorad,720)
-- mymantis:Start()
--
-- If you systematically name your SHORAD groups starting with "Blue SHORAD" you'll need exactly **one** SHORAD instance to manage all SHORAD groups.
--
-- (Optionally) you can remove the link later on with
--
-- mymantis:RemoveShorad()
--
-- # 6. Integrated SEAD
-- --
-- MANTIS is using @{Functional.Sead#SEAD} internally to both detect and evade HARM attacks. No extra efforts needed to set this up! -- MANTIS is using @{Functional.Sead#SEAD} internally to both detect and evade HARM attacks. No extra efforts needed to set this up!
-- Once a HARM attack is detected, MANTIS (via SEAD) will shut down the radars of the attacked SAM site and take evasive action by moving the SAM -- Once a HARM attack is detected, MANTIS (via SEAD) will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
@@ -288,6 +280,7 @@
MANTIS = { MANTIS = {
ClassName = "MANTIS", ClassName = "MANTIS",
name = "mymantis", name = "mymantis",
version = "0.9.34",
SAM_Templates_Prefix = "", SAM_Templates_Prefix = "",
SAM_Group = nil, SAM_Group = nil,
EWR_Templates_Prefix = "", EWR_Templates_Prefix = "",
@@ -336,6 +329,8 @@ MANTIS = {
SmokeDecoy = false, SmokeDecoy = false,
SmokeDecoyColor = SMOKECOLOR.White, SmokeDecoyColor = SMOKECOLOR.White,
checkcounter = 1, checkcounter = 1,
DLinkCacheTime = 120,
logsamstatus = false,
} }
--- Advanced state enumerator --- Advanced state enumerator
@@ -374,7 +369,7 @@ MANTIS.radiusscale[MANTIS.SamType.POINT] = 3
MANTIS.SamData = { MANTIS.SamData = {
["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km ["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km
["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS" }, -- AIM 120B ["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS" }, -- AIM 120B
["Patriot"] = { Range=99, Blindspot=0, Height=25, Type="Long", Radar="Patriot" }, ["Patriot"] = { Range=99, Blindspot=0, Height=25, Type="Long", Radar="Patriot str" },
["Rapier"] = { Range=10, Blindspot=0, Height=3, Type="Short", Radar="rapier" }, ["Rapier"] = { Range=10, Blindspot=0, Height=3, Type="Short", Radar="rapier" },
["SA-2"] = { Range=40, Blindspot=7, Height=25, Type="Medium", Radar="S_75M_Volhov" }, ["SA-2"] = { Range=40, Blindspot=7, Height=25, Type="Medium", Radar="S_75M_Volhov" },
["SA-3"] = { Range=18, Blindspot=6, Height=18, Type="Short", Radar="5p73 s-125 ln" }, ["SA-3"] = { Range=18, Blindspot=6, Height=18, Type="Short", Radar="5p73 s-125 ln" },
@@ -382,7 +377,8 @@ MANTIS.SamData = {
["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" }, ["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" },
["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4"}, ["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4"},
["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" }, ["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" },
["Roland"] = { Range=5, Blindspot=0, Height=5, Type="Point", Radar="Roland" }, ["Roland"] = { Range=6, Blindspot=0, Height=5, Type="Short", Radar="Roland" },
["Gepard"] = { Range=5, Blindspot=0, Height=4, Type="Point", Radar="Gepard" },
["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" }, ["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" },
["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" }, ["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" },
["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" }, ["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" },
@@ -393,14 +389,21 @@ MANTIS.SamData = {
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" }, ["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Linebacker", Point="true" }, ["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Linebacker", Point="true" },
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" }, ["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
["C-RAM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="HEMTT_C-RAM_Phalanx", Point="true" },
-- units from HDS Mod, multi launcher options is tricky -- units from HDS Mod, multi launcher options is tricky
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"}, ["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
["SA-17"] = { Range=50, Blindspot=3, Height=30, Type="Medium", Radar="SA-17" }, ["SA-17"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17" },
["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"}, ["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"},
["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"}, ["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"},
["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" }, ["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" }, ["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" },
["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" }, ["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" },
["NIKE"] = { Range=155, Blindspot=6, Height=30, Type="Long", Radar="HIPAR" },
["Dog Ear"] = { Range=11, Blindspot=0, Height=9, Type="Point", Radar="Dog Ear", Point="true" },
-- CH Added to DCS core 2.9.19.x
["Pantsir S1"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1" , Point="true" },
["Tor M2"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true" },
["IRIS-T SLM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM" },
} }
--- SAM data HDS --- SAM data HDS
@@ -416,13 +419,17 @@ MANTIS.SamDataHDS = {
-- group name MUST contain HDS to ID launcher type correctly! -- group name MUST contain HDS to ID launcher type correctly!
["SA-2 HDS"] = { Range=56, Blindspot=7, Height=30, Type="Medium", Radar="V759" }, ["SA-2 HDS"] = { Range=56, Blindspot=7, Height=30, Type="Medium", Radar="V759" },
["SA-3 HDS"] = { Range=20, Blindspot=6, Height=30, Type="Short", Radar="V-601P" }, ["SA-3 HDS"] = { Range=20, Blindspot=6, Height=30, Type="Short", Radar="V-601P" },
["SA-10C HDS 2"] = { Range=90, Blindspot=5, Height=25, Type="Long" , Radar="5P85DE ln"}, -- V55RUD ["SA-10B HDS"] = { Range=90, Blindspot=5, Height=25, Type="Long" , Radar="5P85CE ln"}, -- V55RUD
["SA-10C HDS 1"] = { Range=90, Blindspot=5, Height=25, Type="Long" , Radar="5P85CE ln"}, -- V55RUD ["SA-10C HDS"] = { Range=75, Blindspot=5, Height=25, Type="Long" , Radar="5P85SE ln"}, -- V55RUD
["SA-12 HDS 2"] = { Range=100, Blindspot=10, Height=25, Type="Long" , Radar="S-300V 9A82 l"}, ["SA-17 HDS"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17 " },
["SA-12 HDS 1"] = { Range=75, Blindspot=1, Height=25, Type="Long" , Radar="S-300V 9A83 l"}, ["SA-12 HDS 2"] = { Range=100, Blindspot=13, Height=30, Type="Long" , Radar="S-300V 9A82 l"},
["SA-12 HDS 1"] = { Range=75, Blindspot=6, Height=25, Type="Long" , Radar="S-300V 9A83 l"},
["SA-23 HDS 2"] = { Range=200, Blindspot=5, Height=37, Type="Long", Radar="S-300VM 9A82ME" }, ["SA-23 HDS 2"] = { Range=200, Blindspot=5, Height=37, Type="Long", Radar="S-300VM 9A82ME" },
["SA-23 HDS 1"] = { Range=100, Blindspot=1, Height=50, Type="Long", Radar="S-300VM 9A83ME" }, ["SA-23 HDS 1"] = { Range=100, Blindspot=1, Height=50, Type="Long", Radar="S-300VM 9A83ME" },
["HQ-2 HDS"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" }, ["HQ-2 HDS"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
["SAMPT Block 1 HDS"] = { Range=120, Blindspot=1, Height=20, Type="long", Radar="SAMPT_MLT_Blk1" }, -- Block 1 Launcher
["SAMPT Block 1INT HDS"] = { Range=150, Blindspot=1, Height=25, Type="long", Radar="SAMPT_MLT_Blk1NT" }, -- Block 1-INT Launcher
["SAMPT Block 2 HDS"] = { Range=200, Blindspot=10, Height=70, Type="long", Radar="SAMPT_MLT_Blk2" }, -- Block 2 Launcher
} }
--- SAM data SMA --- SAM data SMA
@@ -437,16 +444,16 @@ MANTIS.SamDataSMA = {
-- units from SMA Mod (Sweedish Military Assets) -- units from SMA Mod (Sweedish Military Assets)
-- https://forum.dcs.world/topic/295202-swedish-military-assets-for-dcs-by-currenthill/ -- https://forum.dcs.world/topic/295202-swedish-military-assets-for-dcs-by-currenthill/
-- group name MUST contain SMA to ID launcher type correctly! -- group name MUST contain SMA to ID launcher type correctly!
["RBS98M SMA"] = { Range=20, Blindspot=0, Height=8, Type="Short", Radar="RBS-98" }, ["RBS98M SMA"] = { Range=20, Blindspot=0.2, Height=8, Type="Short", Radar="RBS-98" },
["RBS70 SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-70" }, ["RBS70 SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-70" },
["RBS70M SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="BV410_RBS70" }, ["RBS70M SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS70" },
["RBS90 SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-90" }, ["RBS90 SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-90" },
["RBS90M SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="BV410_RBS90" }, ["RBS90M SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS90" },
["RBS103A SMA"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103A" }, ["RBS103A SMA"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_Rb103A" },
["RBS103B SMA"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_Rb103B" }, ["RBS103B SMA"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103B" },
["RBS103AM SMA"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" }, ["RBS103AM SMA"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" },
["RBS103BM SMA"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_HX_Rb103B" }, ["RBS103BM SMA"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103B" },
["Lvkv9040M SMA"] = { Range=4, Blindspot=0, Height=2.5, Type="Point", Radar="LvKv9040",Point="true" }, ["Lvkv9040M SMA"] = { Range=2, Blindspot=0.1, Height=1.2, Type="Point", Radar="LvKv9040",Point="true" },
} }
--- SAM data CH --- SAM data CH
@@ -461,47 +468,49 @@ MANTIS.SamDataCH = {
-- units from CH (Military Assets by Currenthill) -- units from CH (Military Assets by Currenthill)
-- https://www.currenthill.com/ -- https://www.currenthill.com/
-- group name MUST contain CHM to ID launcher type correctly! -- group name MUST contain CHM to ID launcher type correctly!
["2S38 CHM"] = { Range=8, Blindspot=0.5, Height=6, Type="Short", Radar="2S38" }, ["2S38 CHM"] = { Range=6, Blindspot=0.1, Height=4.5, Type="Short", Radar="2S38" },
["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" }, ["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1", Point="true" },
["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" }, ["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
["PGL-625 CHM"] = { Range=10, Blindspot=0.5, Height=5, Type="Short", Radar="PGL_625" }, ["PGL-625 CHM"] = { Range=10, Blindspot=1, Height=5, Type="Short", Radar="PGL_625" },
["HQ-17A CHM"] = { Range=20, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" }, ["HQ-17A CHM"] = { Range=15, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
["M903PAC2 CHM"] = { Range=160, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" }, ["M903PAC2 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
["M903PAC3 CHM"] = { Range=120, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" }, ["M903PAC3 CHM"] = { Range=160, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" }, ["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true" },
["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" }, ["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2K", Point="true" },
["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" }, ["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Point", Radar="TorM2M", Point="true" },
["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" }, ["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" }, ["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" }, ["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" },
["PGZ-09 CHM"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="CH_PGZ09", Point="true" }, ["PGZ-09 CHM"] = { Range=4, Blindspot=0.5, Height=3, Type="Point", Radar="CH_PGZ09", Point="true" },
["S350-9M100 CHM"] = { Range=15, Blindspot=1.5, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" }, ["S350-9M100 CHM"] = { Range=15, Blindspot=1, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
["S350-9M96D CHM"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" }, ["S350-9M96D CHM"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" },
["LAV-AD CHM"] = { Range=8, Blindspot=0.2, Height=4.8, Type="Short", Radar="CH_LAVAD" }, ["LAV-AD CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_LAVAD" },
["HQ-22 CHM"] = { Range=170, Blindspot=5, Height=27, Type="Long", Radar="CH_HQ22_LN" }, ["HQ-22 CHM"] = { Range=170, Blindspot=5, Height=27, Type="Long", Radar="CH_HQ22_LN" },
["PGZ-95 CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_PGZ95",Point="true" }, ["PGZ-95 CHM"] = { Range=2.5, Blindspot=0.5, Height=2, Type="Point", Radar="CH_PGZ95",Point="true" },
["LD-3000 CHM"] = { Range=3, Blindspot=0, Height=3, Type="Point", Radar="CH_LD3000_stationary", Point="true" }, ["LD-3000 CHM"] = { Range=2.5, Blindspot=0.1, Height=3, Type="Point", Radar="CH_LD3000_stationary", Point="true" },
["LD-3000M CHM"] = { Range=3, Blindspot=0, Height=3, Type="Point", Radar="CH_LD3000", Point="true" }, ["LD-3000M CHM"] = { Range=2.5, Blindspot=0.1, Height=3, Type="Point", Radar="CH_LD3000", Point="true" },
["FlaRakRad CHM"] = { Range=8, Blindspot=1.5, Height=6, Type="Short", Radar="HQ17A" }, ["FlaRakRad CHM"] = { Range=8, Blindspot=1.5, Height=6, Type="Short", Radar="CH_FlaRakRad" },
["IRIS-T SLM CHM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM" }, ["IRIS-T SLM CHM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM" },
["M903PAC2KAT1 CHM"] = { Range=160, Blindspot=3, Height=24.5, Type="Long", Radar="CH_MIM104_M903_PAC2_KAT1" }, ["M903PAC2KAT1 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="CH_MIM104_M903_PAC2_KAT1" },
["Skynex CHM"] = { Range=3.5, Blindspot=0, Height=3.5, Type="Point", Radar="CH_SkynexHX", Point="true" }, ["Skynex CHM"] = { Range=3.5, Blindspot=0.1, Height=3.5, Type="Point", Radar="CH_SkynexHX", Point="true" },
["Skyshield CHM"] = { Range=3.5, Blindspot=0, Height=3.5, Type="Point", Radar="CH_Skyshield_Gun", Point="true" }, ["Skyshield CHM"] = { Range=3.5, Blindspot=0.1, Height=3.5, Type="Point", Radar="CH_Skyshield_Gun", Point="true" },
["WieselOzelot CHM"] = { Range=8, Blindspot=0.2, Height=4.8, Type="Short", Radar="CH_Wiesel2Ozelot" }, ["WieselOzelot CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_Wiesel2Ozelot" },
["BukM3-9M317M CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317M" }, ["BukM3-9M317M CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317M" },
["BukM3-9M317MA CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317MA" }, ["BukM3-9M317MA CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317MA" },
["SkySabre CHM"] = { Range=30, Blindspot=0.5, Height=10, Type="Medium", Radar="CH_SkySabreLN" }, ["SkySabre CHM"] = { Range=30, Blindspot=0.5, Height=10, Type="Medium", Radar="CH_SkySabreLN" },
["Stormer CHM"] = { Range=7.5, Blindspot=0.3, Height=7, Type="Short", Radar="CH_StormerHVM" }, ["Stormer CHM"] = { Range=7.5, Blindspot=0.3, Height=7, Type="Short", Radar="CH_StormerHVM" },
["THAAD CHM"] = { Range=200, Blindspot=40, Height=150, Type="Long", Radar="CH_THAAD_M1120" }, ["THAAD CHM"] = { Range=200, Blindspot=40, Height=150, Type="Long", Radar="CH_THAAD_M1120" },
["USInfantryFIM92K CHM"] = { Range=8, Blindspot=0.2, Height=4.8, Type="Short", Radar="CH_USInfantry_FIM92" }, ["USInfantryFIM92K CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_USInfantry_FIM92" },
["RBS98M CHM"] = { Range=20, Blindspot=0, Height=8, Type="Short", Radar="RBS-98" }, ["RBS98M CHM"] = { Range=20, Blindspot=0.2, Height=8, Type="Short", Radar="RBS-98" },
["RBS70 CHM"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-70" }, ["RBS70 CHM"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-70" },
["RBS90 CHM"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-90" }, ["RBS70M CHM"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS70" },
["RBS103A CHM"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103A" }, ["RBS90 CHM"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-90" },
["RBS103B CHM"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_Rb103B" }, ["RBS90M CHM"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS90" },
["RBS103AM CHM"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" }, ["RBS103A CHM"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_Rb103A" },
["RBS103BM CHM"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_HX_Rb103B" }, ["RBS103B CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103B" },
["Lvkv9040M CHM"] = { Range=4, Blindspot=0, Height=2.5, Type="Point", Radar="LvKv9040", Point="true" }, ["RBS103AM CHM"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" },
["RBS103BM CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103B" },
["Lvkv9040M CHM"] = { Range=2, Blindspot=0.1, Height=1.2, Type="Point", Radar="LvKv9040",Point="true" },
} }
----------------------------------------------------------------------- -----------------------------------------------------------------------
@@ -623,6 +632,7 @@ do
self.advAwacs = false self.advAwacs = false
end end
self:SetDLinkCacheTime()
-- Set the string id for output to DCS.log file. -- Set the string id for output to DCS.log file.
self.lid=string.format("MANTIS %s | ", self.name) self.lid=string.format("MANTIS %s | ", self.name)
@@ -656,6 +666,8 @@ do
table.insert(self.ewr_templates,awacs) table.insert(self.ewr_templates,awacs)
end end
self.logsamstatus = false
self:T({self.ewr_templates}) self:T({self.ewr_templates})
self.SAM_Group = SET_GROUP:New():FilterPrefixes(self.SAM_Templates_Prefix):FilterCoalitions(self.Coalition) self.SAM_Group = SET_GROUP:New():FilterPrefixes(self.SAM_Templates_Prefix):FilterCoalitions(self.Coalition)
@@ -685,9 +697,6 @@ do
-- counter for SAM table updates -- counter for SAM table updates
self.checkcounter = 1 self.checkcounter = 1
-- TODO Version
-- @field #string version
self.version="0.9.27"
self:I(string.format("***** Starting MANTIS Version %s *****", self.version)) self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
--- FSM Functions --- --- FSM Functions ---
@@ -884,7 +893,11 @@ do
self.AcceptZones = AcceptZones or {} self.AcceptZones = AcceptZones or {}
self.RejectZones = RejectZones or {} self.RejectZones = RejectZones or {}
self.ConflictZones = ConflictZones or {} self.ConflictZones = ConflictZones or {}
if #self.AcceptZones > 0 or #self.RejectZones > 0 or #self.ConflictZones > 0 then self.AcceptZonesNo = UTILS.TableLength(self.AcceptZones)
self.RejectZonesNo = UTILS.TableLength(self.RejectZones)
self.ConflictZonesNo = UTILS.TableLength(self.ConflictZones)
self:T(string.format("AcceptZonesNo = %d | RejectZonesNo = %d | ConflictZonesNo = %d",self.AcceptZonesNo,self.RejectZonesNo,self.ConflictZonesNo))
if self.AcceptZonesNo > 0 or self.RejectZonesNo > 0 or self.ConflictZonesNo > 0 then
self.usezones = true self.usezones = true
end end
return self return self
@@ -1038,6 +1051,16 @@ do
return self return self
end end
--- Function to set how long INTEL DLINK remembers contacts.
-- @param #MANTIS self
-- @param #number seconds Remember this many seconds, at least 5 seconds.
-- @return #MANTIS self
function MANTIS:SetDLinkCacheTime(seconds)
self.DLinkCacheTime = math.abs(seconds or 120)
if self.DLinkCacheTime < 5 then self.DLinkCacheTime = 5 end
return self
end
--- Function to set the detection interval --- Function to set the detection interval
-- @param #MANTIS self -- @param #MANTIS self
-- @param #number interval The interval in seconds -- @param #number interval The interval in seconds
@@ -1266,7 +1289,8 @@ do
self:T(self.lid.."_CheckCoordinateInZones") self:T(self.lid.."_CheckCoordinateInZones")
local inzone = false local inzone = false
-- acceptzones -- acceptzones
if #self.AcceptZones > 0 then self:T(string.format("AcceptZonesNo = %d | RejectZonesNo = %d | ConflictZonesNo = %d",self.AcceptZonesNo,self.RejectZonesNo,self.ConflictZonesNo))
if self.AcceptZonesNo > 0 then
for _,_zone in pairs(self.AcceptZones) do for _,_zone in pairs(self.AcceptZones) do
local zone = _zone -- Core.Zone#ZONE local zone = _zone -- Core.Zone#ZONE
if zone:IsCoordinateInZone(coord) then if zone:IsCoordinateInZone(coord) then
@@ -1277,7 +1301,7 @@ do
end end
end end
-- rejectzones -- rejectzones
if #self.RejectZones > 0 and inzone then -- maybe in accept zone, but check the overlaps if self.RejectZonesNo > 0 then
for _,_zone in pairs(self.RejectZones) do for _,_zone in pairs(self.RejectZones) do
local zone = _zone -- Core.Zone#ZONE local zone = _zone -- Core.Zone#ZONE
if zone:IsCoordinateInZone(coord) then if zone:IsCoordinateInZone(coord) then
@@ -1288,7 +1312,7 @@ do
end end
end end
-- conflictzones -- conflictzones
if #self.ConflictZones > 0 and not inzone then -- if not already accepted, might be in conflict zones if self.ConflictZonesNo > 0 then
for _,_zone in pairs(self.ConflictZones) do for _,_zone in pairs(self.ConflictZones) do
local zone = _zone -- Core.Zone#ZONE local zone = _zone -- Core.Zone#ZONE
if zone:IsCoordinateInZone(coord) then if zone:IsCoordinateInZone(coord) then
@@ -1354,6 +1378,7 @@ do
end end
-- check accept/reject zones -- check accept/reject zones
local zonecheck = true local zonecheck = true
self:T("self.usezones = "..tostring(self.usezones))
if self.usezones then if self.usezones then
-- DONE -- DONE
zonecheck = self:_CheckCoordinateInZones(coord) zonecheck = self:_CheckCoordinateInZones(coord)
@@ -1429,7 +1454,9 @@ do
--IntelTwo:SetClusterRadius(5000) --IntelTwo:SetClusterRadius(5000)
IntelTwo:Start() IntelTwo:Start()
local IntelDlink = INTEL_DLINK:New({IntelOne,IntelTwo},self.name.." DLINK",22,300) local CacheTime = self.DLinkCacheTime or 120
local IntelDlink = INTEL_DLINK:New({IntelOne,IntelTwo},self.name.." DLINK",22,CacheTime)
IntelDlink:__Start(1) IntelDlink:__Start(1)
self:SetUsingDLink(IntelDlink) self:SetUsingDLink(IntelDlink)
@@ -1491,7 +1518,7 @@ do
elseif chm then elseif chm then
SAMData = self.SamDataCH SAMData = self.SamDataCH
end end
--self:T("Looking to auto-match for "..grpname) --self:I("Looking to auto-match for "..grpname)
for _,_unit in pairs(units) do for _,_unit in pairs(units) do
local unit = _unit -- Wrapper.Unit#UNIT local unit = _unit -- Wrapper.Unit#UNIT
local type = string.lower(unit:GetTypeName()) local type = string.lower(unit:GetTypeName())
@@ -1692,7 +1719,9 @@ do
local grpname = group:GetName() local grpname = group:GetName()
local grpcoord = group:GetCoordinate() local grpcoord = group:GetCoordinate()
local grprange, grpheight,type,blind = self:_GetSAMRange(grpname) local grprange, grpheight,type,blind = self:_GetSAMRange(grpname)
local radaralive = group:IsSAM() -- TODO the below might stop working at some point after some hours, needs testing
--local radaralive = group:IsSAM()
local radaralive = true
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) -- make the table lighter, as I don't really use the zone here table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) -- make the table lighter, as I don't really use the zone here
table.insert( SEAD_Grps, grpname ) table.insert( SEAD_Grps, grpname )
if type == MANTIS.SamType.LONG and radaralive then if type == MANTIS.SamType.LONG and radaralive then
@@ -1789,7 +1818,7 @@ do
if self.Shorad and self.Shorad.ActiveGroups and self.Shorad.ActiveGroups[name] then if self.Shorad and self.Shorad.ActiveGroups and self.Shorad.ActiveGroups[name] then
activeshorad = true activeshorad = true
end end
if IsInZone and not suppressed and not activeshorad then --check any target in zone and not currently managed by SEAD if IsInZone and (not suppressed) and (not activeshorad) then --check any target in zone and not currently managed by SEAD
if samgroup:IsAlive() then if samgroup:IsAlive() then
-- switch on SAM -- switch on SAM
local switch = false local switch = false
@@ -1821,7 +1850,7 @@ do
-- link in to SHORAD if available -- link in to SHORAD if available
-- DONE: Test integration fully -- DONE: Test integration fully
if self.ShoradLink and (Distance < self.ShoradActDistance or Distance < blind ) then -- don't give SHORAD position away too early if self.ShoradLink and (Distance < self.ShoradActDistance or Distance < blind ) then -- don't give SHORAD position away too early
local Shorad = self.Shorad local Shorad = self.Shorad --Functional.Shorad#SHORAD
local radius = self.checkradius local radius = self.checkradius
local ontime = self.ShoradTime local ontime = self.ShoradTime
Shorad:WakeUpShorad(name, radius, ontime) Shorad:WakeUpShorad(name, radius, ontime)
@@ -1854,7 +1883,7 @@ do
end --end alive end --end alive
end --end check end --end check
end --for loop end --for loop
if self.debug or self.verbose then if self.debug or self.verbose or self.logsamstatus then
for _,_status in pairs(self.SamStateTracker) do for _,_status in pairs(self.SamStateTracker) do
if _status == "GREEN" then if _status == "GREEN" then
instatusgreen=instatusgreen+1 instatusgreen=instatusgreen+1
@@ -1875,8 +1904,9 @@ do
-- @param #MANTIS self -- @param #MANTIS self
-- @param Functional.Detection#DETECTION_AREAS detection Detection object -- @param Functional.Detection#DETECTION_AREAS detection Detection object
-- @param #boolean dlink -- @param #boolean dlink
-- @param #boolean reporttolog
-- @return #MANTIS self -- @return #MANTIS self
function MANTIS:_Check(detection,dlink) function MANTIS:_Check(detection,dlink,reporttolog)
self:T(self.lid .. "Check") self:T(self.lid .. "Check")
--get detected set --get detected set
local detset = detection:GetDetectedItemCoordinates() local detset = detection:GetDetectedItemCoordinates()
@@ -1903,7 +1933,8 @@ do
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic) instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic)
end end
if self.debug or self.verbose then
local function GetReport()
local statusreport = REPORT:New("\nMANTIS Status "..self.name) local statusreport = REPORT:New("\nMANTIS Status "..self.name)
statusreport:Add("+-----------------------------+") statusreport:Add("+-----------------------------+")
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred)) statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
@@ -1912,7 +1943,15 @@ do
statusreport:Add(string.format("+ SHORAD active: %2d",activeshorads)) statusreport:Add(string.format("+ SHORAD active: %2d",activeshorads))
end end
statusreport:Add("+-----------------------------+") statusreport:Add("+-----------------------------+")
return statusreport
end
if self.debug or self.verbose then
local statusreport = GetReport()
MESSAGE:New(statusreport:Text(),10):ToAll():ToLog() MESSAGE:New(statusreport:Text(),10):ToAll():ToLog()
elseif reporttolog == true then
local statusreport = GetReport()
MESSAGE:New(statusreport:Text(),10):ToLog()
end end
return self return self
end end
@@ -2020,7 +2059,7 @@ do
self:T({From, Event, To}) self:T({From, Event, To})
-- check detection -- check detection
if not self.state2flag then if not self.state2flag then
self:_Check(self.Detection,self.DLink) self:_Check(self.Detection,self.DLink,self.logsamstatus)
end end
local EWRAlive = self:_CheckAnyEWRAlive() local EWRAlive = self:_CheckAnyEWRAlive()
@@ -2091,7 +2130,7 @@ do
if self.debug and self.verbose then if self.debug and self.verbose then
self:I(self.lid .. "Status Report") self:I(self.lid .. "Status Report")
for _name,_state in pairs(self.SamStateTracker) do for _name,_state in pairs(self.SamStateTracker) do
self:I(string.format("Site %s\tStatus %s",_name,_state)) self:I(string.format("Site %s | Status %s",_name,_state))
end end
end end
local interval = self.detectinterval * -1 local interval = self.detectinterval * -1

View File

@@ -53,6 +53,8 @@
-- --
-- # Developer Note -- # Developer Note
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE. -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE.
-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality. -- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality.
-- --

View File

@@ -603,7 +603,7 @@ RANGE.MenuF10Root = nil
--- Range script version. --- Range script version.
-- @field #string version -- @field #string version
RANGE.version = "2.8.0" RANGE.version = "2.8.1"
-- TODO list: -- TODO list:
-- TODO: Verbosity level for messages. -- TODO: Verbosity level for messages.
@@ -2032,10 +2032,10 @@ function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackV
-- Smoke impact point of bomb. -- Smoke impact point of bomb.
if playerData and playerData.smokebombimpact and insidezone then if playerData and playerData.smokebombimpact and insidezone then
if playerData and playerData.delaysmoke then if playerData.delaysmoke then
timer.scheduleFunction( self._DelayedSmoke, { coord = impactcoord, color = playerData.smokecolor }, timer.getTime() + self.TdelaySmoke ) impactcoord:Smoke(playerData.smokecolor, 30, self.TdelaySmoke)
else else
impactcoord:Smoke( playerData.smokecolor ) impactcoord:Smoke(playerData.smokecolor, 30)
end end
end end
@@ -2102,7 +2102,12 @@ function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackV
result.attackHdg = attackHdg result.attackHdg = attackHdg
result.attackVel = attackVel result.attackVel = attackVel
result.attackAlt = attackAlt result.attackAlt = attackAlt
result.date=os and os.date() or "n/a" if os and os.date then
result.date=os.date()
else
self:E(self.lid.."os or os.date() not available")
result.date = "n/a"
end
-- Add to table. -- Add to table.
table.insert( _results, result ) table.insert( _results, result )
@@ -2635,13 +2640,6 @@ end
-- Display Messages -- Display Messages
----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Start smoking a coordinate with a delay.
-- @param #table _args Argements passed.
function RANGE._DelayedSmoke( _args )
_args.coord:Smoke(_args.color)
--trigger.action.smoke( _args.coord:GetVec3(), _args.color )
end
--- Display top 10 stafing results of a specific player. --- Display top 10 stafing results of a specific player.
-- @param #RANGE self -- @param #RANGE self
-- @param #string _unitName Name of the player unit. -- @param #string _unitName Name of the player unit.

View File

@@ -985,6 +985,7 @@ function SCORING:_EventOnHit( Event )
local TargetUnitCoalition = nil local TargetUnitCoalition = nil
local TargetUnitCategory = nil local TargetUnitCategory = nil
local TargetUnitType = nil local TargetUnitType = nil
local TargetIsScenery = false
if Event.IniDCSUnit then if Event.IniDCSUnit then
@@ -1025,6 +1026,12 @@ function SCORING:_EventOnHit( Event )
TargetCategory = Event.TgtCategory TargetCategory = Event.TgtCategory
TargetType = Event.TgtTypeName TargetType = Event.TgtTypeName
-- Scenery hit
if (not TargetCategory) and TargetUNIT ~= nil and TargetUnit:IsInstanceOf("SCENERY") then
TargetCategory = Unit.Category.STRUCTURE
TargetIsScenery = true
end
TargetUnitCoalition = _SCORINGCoalition[TargetCoalition] TargetUnitCoalition = _SCORINGCoalition[TargetCoalition]
TargetUnitCategory = _SCORINGCategory[TargetCategory] TargetUnitCategory = _SCORINGCategory[TargetCategory]
TargetUnitType = TargetType TargetUnitType = TargetType
@@ -1117,17 +1124,22 @@ function SCORING:_EventOnHit( Event )
MESSAGE.Type.Update ) MESSAGE.Type.Update )
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
else elseif TargetIsScenery ~= true then
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " .. MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " ..
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty, "Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
MESSAGE.Type.Update ) MESSAGE.Type.Update )
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
elseif TargetIsScenery == true then
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit scenery object." .. " Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
MESSAGE.Type.Update )
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
end end
self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
end end
else -- A scenery object was hit. else -- A scenery object was hit.
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit scenery object.", MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit nothing special.",
MESSAGE.Type.Update ) MESSAGE.Type.Update )
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )

View File

@@ -1,10 +1,10 @@
--- **Functional** - TIRESIAS - manages AI behaviour. ----- **Functional** - TIRESIAS - manages AI behaviour (OPTIMIZED VERSION).
---- ===
--- The @{#TIRESIAS} class is working in the back to keep your large-scale ground units in check.
-- --
-- === -- -- Features:
--
-- The @{#TIRESIAS} class is working in the back to keep your large-scale ground units in check.
--
-- ## Features:
-- --
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units. -- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
-- * Does not affect ships to keep the Navy guys happy. -- * Does not affect ships to keep the Navy guys happy.
@@ -16,24 +16,29 @@
-- --
-- === -- ===
-- --
-- ## Missions: -- ## Optimizations Applied:
-- --
-- ### [TIRESIAS](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master) -- * Cached frequently used functions and constants
-- * Reduced string concatenations and formatting
-- * Optimized loop structures and conditions
-- * Pre-allocated tables where possible
-- * Reduced function call overhead
-- * Improved memory management
-- --
-- === ---- ===
--
-- ### Author : **applevangelist **
-- --
---- #-- Author : **applevangelist ** (Optimized by AI)
---
-- @module Functional.Tiresias -- @module Functional.Tiresias
-- @image Functional.Tiresias.jpg -- @image Functional.Tiresias.jpg
--
-- Last Update: Dec 2023
------------------------------------------------------------------------- --- Last Update: July 2025
--- **TIRESIAS** class, extends Core.Base#BASE --- **TIRESIAS** class, extends Core.Base#BASE
-- @type TIRESIAS -- @type TIRESIAS
-- @field #string ClassName -- @field #string ClassName
-- @field #booelan debug -- @field #boolean debug
-- @field #string version -- @field #string version
-- @field #number Interval -- @field #number Interval
-- @field Core.Set#SET_GROUP GroundSet -- @field Core.Set#SET_GROUP GroundSet
@@ -48,6 +53,9 @@
-- @field #number PlaneSwitchRange -- @field #number PlaneSwitchRange
-- @field Core.Set#SET_GROUP FlightSet -- @field Core.Set#SET_GROUP FlightSet
-- @field #boolean SwitchAAA -- @field #boolean SwitchAAA
-- @field #string lid
-- @field #table _cached_zones
-- @field #table _cached_groupsets
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- ---
@@ -58,8 +66,8 @@
-- @field #boolean AIOff -- @field #boolean AIOff
-- @field #boolean exception -- @field #boolean exception
---
--- *Tiresias, Greek demi-god and shapeshifter, blinded by the Gods, works as oracle for you.* (Wiki) -- *Tiresias, Greek demi-god and shapeshifter, blinded by the Gods, works as oracle for you.* (Wiki)
-- --
-- === -- ===
-- --
@@ -74,18 +82,17 @@
-- * Easy setup. -- * Easy setup.
-- --
-- ## Setup -- ## Setup
-- -- -- Setup is a one-liner:
-- Setup is a one-liner:
-- --
-- local blinder = TIRESIAS:New() -- local blinder = TIRESIAS:New()
-- --
-- Optionally you can set up exceptions, e.g. for convoys driving around -- -- Optionally you can set up exceptions, e.g. for convoys driving around
-- --
-- local exceptionset = SET_GROUP:New():FilterCoalitions(" red" ):FilterPrefixes(" Convoy" ):FilterStart() -- local exceptionset = SET_GROUP:New():FilterCoalitions(" red" ):FilterPrefixes(" Convoy" ):FilterStart()
-- local blinder = TIRESIAS:New() -- local blinder = TIRESIAS:New()
-- blinder:AddExceptionSet(exceptionset) -- blinder:AddExceptionSet(exceptionset)
-- --
-- Options -- -- Options
-- --
-- -- Setup different radius for activation around helo and airplane groups (applies to AI and humans) -- -- Setup different radius for activation around helo and airplane groups (applies to AI and humans)
-- blinder:SetActivationRanges(10,25) -- defaults are 10, and 25 -- blinder:SetActivationRanges(10,25) -- defaults are 10, and 25
@@ -93,11 +100,12 @@
-- -- Setup engagement ranges for AAA (non-advanced SAM units like Flaks etc) and if you want them to be AIOff -- -- Setup engagement ranges for AAA (non-advanced SAM units like Flaks etc) and if you want them to be AIOff
-- blinder:SetAAARanges(60,true) -- defaults are 60, and true -- blinder:SetAAARanges(60,true) -- defaults are 60, and true
-- --
---
-- @field #TIRESIAS -- @field #TIRESIAS
TIRESIAS = { TIRESIAS = {
ClassName = "TIRESIAS", ClassName = "TIRESIAS",
debug = false, debug = true,
version = "0.0.5", version = " 0.0.7-OPT" ,
Interval = 20, Interval = 20,
GroundSet = nil, GroundSet = nil,
VehicleSet = nil, VehicleSet = nil,
@@ -108,9 +116,12 @@ TIRESIAS = {
HeloSwitchRange = 10, -- NM HeloSwitchRange = 10, -- NM
PlaneSwitchRange = 25, -- NM PlaneSwitchRange = 25, -- NM
SwitchAAA = true, SwitchAAA = true,
_cached_zones = {}, -- Cache for zone objects
_cached_groupsets = {}, -- Cache for group_set objects
} }
--- [USER] Create a new Tiresias object and start it up. ---
-- [USER] Create a new Tiresias object and start it up.
-- @param #TIRESIAS self -- @param #TIRESIAS self
-- @return #TIRESIAS self -- @return #TIRESIAS self
function TIRESIAS:New() function TIRESIAS:New()
@@ -129,11 +140,13 @@ function TIRESIAS:New()
self:AddTransition("*", "Status", "*") -- TIRESIAS status update. self:AddTransition("*", "Status", "*") -- TIRESIAS status update.
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
self.ExceptionSet = SET_GROUP:New():Clear(false) self.ExceptionSet = nil --SET_GROUP:New():Clear(false)
self._cached_zones = {} -- Initialize zone cache
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler) self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
self.lid = string.format("TIRESIAS %s | ",self.version) -- Cache the log identifier to avoid string concatenation in loops
self.lid = "TIRESIAS " .. self.version .. " | "
self:I(self.lid .. "Managing ground groups!") self:I(self.lid .. "Managing ground groups!")
@@ -156,14 +169,15 @@ function TIRESIAS:New()
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
self:__Start(1) self:__Start(1)
return self return self
end end
------------------------------------------------------------------------------------------------------------- -----
--
---
-- Helper Functions -- Helper Functions
-- ---
-------------------------------------------------------------------------------------------------------------
--- [USER] Set activation radius for Helos and Planes in Nautical Miles. --- [USER] Set activation radius for Helos and Planes in Nautical Miles.
-- @param #TIRESIAS self -- @param #TIRESIAS self
@@ -173,6 +187,8 @@ end
function TIRESIAS:SetActivationRanges(HeloMiles, PlaneMiles) function TIRESIAS:SetActivationRanges(HeloMiles, PlaneMiles)
self.HeloSwitchRange = HeloMiles or 10 self.HeloSwitchRange = HeloMiles or 10
self.PlaneSwitchRange = PlaneMiles or 25 self.PlaneSwitchRange = PlaneMiles or 25
-- Clear zone cache when ranges change
self._cached_zones = {}
return self return self
end end
@@ -193,238 +209,286 @@ end
-- @return #TIRESIAS self -- @return #TIRESIAS self
function TIRESIAS:AddExceptionSet(Set) function TIRESIAS:AddExceptionSet(Set)
self:T(self.lid .. " AddExceptionSet" ) self:T(self.lid .. " AddExceptionSet" )
if not self.ExceptionSet then
self.ExceptionSet = SET_GROUP:New()
end
local exceptions = self.ExceptionSet local exceptions = self.ExceptionSet
Set:ForEachGroupAlive(
function(grp) -- Cache the exception data structure for reuse
if not grp.Tiresias then local exception_data = {
grp.Tiresias = { -- #TIRESIAS.Data
type = " Exception" , type = " Exception" ,
exception = true, exception = true,
} }
Set:ForEachGroupAlive(
function(grp)
local inAAASet = self.AAASet:IsIncludeObject(grp)
local inVehSet = self.VehicleSet:IsIncludeObject(grp)
local inSAMSet = self.SAMSet:IsIncludeObject(grp)
if grp:IsGround() and (not grp.Tiresias) and (not inAAASet) and (not inVehSet) and (not inSAMSet) then
grp.Tiresias = exception_data
exceptions:AddGroup(grp, true) exceptions:AddGroup(grp, true)
end
BASE:T(" TIRESIAS: Added exception group: " .. grp:GetName()) BASE:T(" TIRESIAS: Added exception group: " .. grp:GetName())
end end
end
) )
return self return self
end end
--- [INTERNAL] Filter Function --- [INTERNAL] Filter Function - Optimized with cached calls
-- @param Wrapper.Group#GROUP Group -- @param Wrapper.Group#GROUP Group
-- @return #boolean isin -- @return #boolean isin
function TIRESIAS._FilterNotAAA(Group) function TIRESIAS._FilterNotAAA(Group)
local grp = Group -- Wrapper.Group#GROUP local grp = Group -- Wrapper.Group#GROUP
local isaaa = grp:IsAAA() -- Cache method calls to reduce overhead
if isaaa == true and grp:IsGround() and not grp:IsShip() then local is_air = grp:IsAir()
return false -- remove from SET local is_ship = grp:IsShip()
else local is_AAA = grp:IsAAA()
if is_air or grp:IsShip() then -- air or ship - no AAA
return true -- keep in SET return true -- keep in SET
end end
return not is_AAA -- remove AAA, keep others
end end
--- [INTERNAL] Filter Function --- [INTERNAL] Filter Function - Optimized with cached calls
-- @param Wrapper.Group#GROUP Group -- @param Wrapper.Group#GROUP Group
-- @return #boolean isin -- @return #boolean isin
function TIRESIAS._FilterNotSAM(Group) function TIRESIAS._FilterNotSAM(Group)
local grp = Group -- Wrapper.Group#GROUP local grp = Group -- Wrapper.Group#GROUP
local issam = grp:IsSAM() -- Cache method calls to reduce overhead
if issam == true and grp:IsGround() and not grp:IsShip() then local is_air = grp:IsGround()
return false -- remove from SET local is_ship = grp:IsShip()
else local is_SAM = grp:IsSAM()
if is_air or grp:IsShip() then
return true -- keep in SET return true -- keep in SET
end end
return not is_SAM -- remove SAM, keep others
end end
--- [INTERNAL] Filter Function --- [INTERNAL] Filter Function - Optimized with cached calls
-- @param Wrapper.Group#GROUP Group -- @param Wrapper.Group#GROUP Group
-- @return #boolean isin -- @return #boolean isin
function TIRESIAS._FilterAAA(Group) function TIRESIAS._FilterAAA(Group)
local grp = Group -- Wrapper.Group#GROUP local grp = Group -- Wrapper.Group#GROUP
local isaaa = grp:IsAAA() -- Cache method calls to reduce overhead
if isaaa == true and grp:IsGround() and not grp:IsShip() then local is_ground = grp:IsGround()
return true -- remove from SET if (not is_ground) or grp:IsShip() then
else return false -- not AAA
return false -- keep in SET
end end
return grp:IsAAA() -- only AAA
end end
--- [INTERNAL] Filter Function --- [INTERNAL] Filter Function - Optimized with cached calls
-- @param Wrapper.Group#GROUP Group -- @param Wrapper.Group#GROUP Group
-- @return #boolean isin -- @return #boolean isin
function TIRESIAS._FilterSAM(Group) function TIRESIAS._FilterSAM(Group)
local grp = Group -- Wrapper.Group#GROUP local grp = Group -- Wrapper.Group#GROUP
local issam = grp:IsSAM() -- Cache method calls to reduce overhead
if issam == true and grp:IsGround() and not grp:IsShip() then local is_ground = grp:IsGround()
return true -- remove from SET if (not is_ground) or grp:IsShip() then
else return false -- not SAM
return false -- keep in SET
end end
return grp:IsSAM() -- only SAM
end end
--- [INTERNAL] Init Groups --- [INTERNAL] Init Groups - Optimized with reduced function calls
-- @param #TIRESIAS self -- @param #TIRESIAS self
-- @return #TIRESIAS self -- @return #TIRESIAS self
function TIRESIAS:_InitGroups() function TIRESIAS:_InitGroups()
self:T(self.lid .. " _InitGroups" ) self:T(self.lid .. " _InitGroups" )
-- Set all groups invisible/motionless
-- Cache frequently used values
local EngageRange = self.AAARange local EngageRange = self.AAARange
local SwitchAAA = self.SwitchAAA local SwitchAAA = self.SwitchAAA
--- AAA
self.AAASet:ForEachGroupAlive( -- Pre-create data structures to avoid repeated table creation
function(grp) local aaa_data_template = {
if not grp.Tiresias then
grp:OptionEngageRange(EngageRange)
grp:SetCommandInvisible(true)
if SwitchAAA then
grp:SetAIOff()
grp:EnableEmission(false)
end
grp.Tiresias = { -- #TIRESIAS.Data
type = " AAA" , type = " AAA" ,
invisible = true, invisible = true,
range = EngageRange, range = EngageRange,
exception = false, exception = false,
AIOff = SwitchAAA, AIOff = SwitchAAA,
} }
end
if grp.Tiresias and (not grp.Tiresias.exception == true) then local vehicle_data_template = {
if grp.Tiresias.invisible == false then
grp:SetCommandInvisible(true)
grp.Tiresias.invisible = true
if SwitchAAA then
grp:SetAIOff()
grp:EnableEmission(false)
grp.Tiresias.AIOff = true
end
end
end
--BASE:I(string.format("Init/Switch off AAA %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
end
)
--- Vehicles
self.VehicleSet:ForEachGroupAlive(
function(grp)
if not grp.Tiresias then
grp:SetAIOff()
grp:SetCommandInvisible(true)
grp.Tiresias = { -- #TIRESIAS.Data
type = " Vehicle" , type = " Vehicle" ,
invisible = true, invisible = true,
AIOff = true, AIOff = true,
exception = false, exception = false,
} }
end
if grp.Tiresias and (not grp.Tiresias.exception == true) then local sam_data_template = {
if grp.Tiresias and grp.Tiresias.invisible == false then
grp:SetCommandInvisible(true)
grp:SetAIOff()
grp.Tiresias.invisible = true
grp.Tiresias.AIOff = true
end
end
--BASE:I(string.format("Init/Switch off Vehicle %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
end
)
--- SAM
self.SAMSet:ForEachGroupAlive(
function(grp)
if not grp.Tiresias then
grp:SetCommandInvisible(true)
grp.Tiresias = { -- #TIRESIAS.Data
type = " SAM" , type = " SAM" ,
invisible = true, invisible = true,
exception = false, exception = false,
} }
end
if grp.Tiresias and (not grp.Tiresias.exception == true) then --- AAA - Optimized loop
if grp.Tiresias and grp.Tiresias.invisible == false then self.AAASet:ForEachGroupAlive(
function(grp)
local tiresias_data = grp.Tiresias
if not tiresias_data then
grp:OptionEngageRange(EngageRange)
grp:SetCommandInvisible(true) grp:SetCommandInvisible(true)
grp.Tiresias.invisible = true if SwitchAAA then
grp:SetAIOff()
grp:EnableEmission(false)
end
grp.Tiresias = aaa_data_template
elseif not tiresias_data.exception == true then
if not tiresias_data.invisible == true then
grp:SetCommandInvisible(true)
tiresias_data.invisible = true
if SwitchAAA == true then
grp:SetAIOff()
grp:EnableEmission(false)
tiresias_data.AIOff = true
end
end end
end end
--BASE:I(string.format("Init/Switch off SAM %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
end end
) )
--- Vehicles - Optimized loop
self.VehicleSet:ForEachGroupAlive(
function(grp)
local tiresias_data = grp.Tiresias
if not tiresias_data then
grp:SetAIOff()
grp:SetCommandInvisible(true)
grp.Tiresias = vehicle_data_template
elseif not tiresias_data.exception == true then
if not tiresias_data.invisible then
grp:SetCommandInvisible(true)
grp:SetAIOff()
tiresias_data.invisible = true
tiresias_data.AIOff = true
end
end
end
)
--- SAM - Optimized loop
self.SAMSet:ForEachGroupAlive(
function(grp)
local tiresias_data = grp.Tiresias
if not tiresias_data then
grp:SetCommandInvisible(true)
grp.Tiresias = sam_data_template
elseif not tiresias_data.exception == true then
if not tiresias_data.invisible then
grp:SetCommandInvisible(true)
tiresias_data.invisible = true
end
end
end
)
return self return self
end end
--- [INTERNAL] Event handler function --- [INTERNAL] Event handler function - Optimized
-- @param #TIRESIAS self -- @param #TIRESIAS self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
-- @return #TIRESIAS self -- @return #TIRESIAS self
function TIRESIAS:_EventHandler(EventData) function TIRESIAS:_EventHandler(EventData)
self:T(string.format(" %s Event = %d" , self.lid, EventData.id)) self:T(string.format(" %s Event = %d" , self.lid, EventData.id))
local event = EventData -- Core.Event#EVENTDATA local event = EventData -- Core.Event#EVENTDATA
if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then
--local _coalition = event.IniCoalition
--if _coalition ~= self.Coalition then
-- return --ignore!
--end
local unitname = event.IniUnitName or "none"
local _unit = event.IniUnit
local _group = event.IniGroup local _group = event.IniGroup
if _group and _group:IsAlive() then if _group and _group:IsAlive() then
local radius = self.PlaneSwitchRange -- Cache the radius calculation
if _group:IsHelicopter() then local radius = _group:IsHelicopter() and self.HeloSwitchRange or self.PlaneSwitchRange
radius = self.HeloSwitchRange
end
self:_SwitchOnGroups(_group, radius) self:_SwitchOnGroups(_group, radius)
end end
end end
return self return self
end end
--- [INTERNAL] Switch Groups Behaviour --- [INTERNAL] Switch Groups Behaviour - Optimized with zone caching
-- @param #TIRESIAS self -- @param #TIRESIAS self
-- @param Wrapper.Group#GROUP group -- @param Wrapper.Group#GROUP group
-- @param #number radius Radius in NM -- @param #number radius Radius in NM
-- @return #TIRESIAS self -- @return #TIRESIAS self
function TIRESIAS:_SwitchOnGroups(group, radius) function TIRESIAS:_SwitchOnGroups(group, radius)
self:T(self.lid .. " _SwitchOnGroups " .. group:GetName() .. " Radius " .. radius .. " NM" ) self:T(self.lid .. " _SwitchOnGroups " .. group:GetName() .. " Radius " .. radius .. " NM" )
local zone = ZONE_GROUP:New("Zone-"..group:GetName(),group,UTILS.NMToMeters(radius))
local ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce() -- Use cached zones to reduce object creation
local count = ground:CountAlive() local group_name = group:GetName()
if self.debug then local cache_key = group_name .. " _" .. radius
local text = string.format("There are %d groups around this plane or helo!",count) local zone = self._cached_zones[cache_key]
self:I(text) local ground = self._cached_groupsets[cache_key]
if not zone then
zone = ZONE_GROUP:New(" Zone-" .. group_name, group, UTILS.NMToMeters(radius))
self._cached_zones[cache_key] = zone
else
-- Update zone center to current group position
zone:UpdateFromGroup(group)
end end
if not ground then
ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
self._cached_groupsets[cache_key] = ground
else
ground:FilterZones({zone},true):FilterOnce()
end
local count = ground:CountAlive()
if self.debug then
self:I(string.format(" There are %d groups around this plane or helo!" , count))
end
if count > 0 then
-- Cache values outside the loop
local SwitchAAA = self.SwitchAAA local SwitchAAA = self.SwitchAAA
if ground:CountAlive() > 0 then local group_coalition = group:GetCoalition()
ground:ForEachGroupAlive( ground:ForEachGroupAlive(
function(grp) function(grp)
local name = grp:GetName() local tiresias_data = grp.Tiresias
if grp:GetCoalition() ~= group:GetCoalition() if grp:GetCoalition() ~= group_coalition
and grp.Tiresias and grp.Tiresias.type and (not grp.Tiresias.exception == true ) then and tiresias_data
if grp.Tiresias.invisible == true then and tiresias_data.type
and not tiresias_data.exception == true then
-- Make group visible if invisible
if tiresias_data.invisible == true then
grp:SetCommandInvisible(false) grp:SetCommandInvisible(false)
grp.Tiresias.invisible = false tiresias_data.invisible = false
end end
if grp.Tiresias.type == "Vehicle" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
-- Handle AI activation based on type
local grp_type = tiresias_data.type
if grp_type == "Vehicle" and tiresias_data.AIOff == true then
grp:SetAIOn() grp:SetAIOn()
grp.Tiresias.AIOff = false tiresias_data.AIOff = false
end elseif SwitchAAA == true and grp_type == "AAA" and tiresias_data.AIOff == true then
if SwitchAAA and grp.Tiresias.type == "AAA" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
grp:SetAIOn() grp:SetAIOn()
grp:EnableEmission(true) grp:EnableEmission(true)
grp.Tiresias.AIOff = false tiresias_data.AIOff = false
end end
--BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
else else
BASE:T("TIRESIAS - This group "..tostring(name).. " has not been initialized or is an exception!") BASE:T("TIRESIAS - This group " .. tostring(grp:GetName()) .. " has not been initialized or is an exception!")
end end
end end
) )
end end
return self return self
end end
------------------------------------------------------------------------------------------------------------- -----
--
-- FSM Functions
--
-------------------------------------------------------------------------------------------------------------
--- [INTERNAL] FSM Function ---
-- FSM Functions
----
--- [INTERNAL] FSM Function - Optimized initialization
-- @param #TIRESIAS self -- @param #TIRESIAS self
-- @param #string From -- @param #string From
-- @param #string Event -- @param #string Event
@@ -433,29 +497,57 @@ end
function TIRESIAS:onafterStart(From, Event, To) function TIRESIAS:onafterStart(From, Event, To)
self:T({From, Event, To}) self:T({From, Event, To})
-- Create sets with optimized filters
local VehicleSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterNotAAA):FilterFunction(TIRESIAS._FilterNotSAM):FilterStart() local VehicleSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterNotAAA):FilterFunction(TIRESIAS._FilterNotSAM):FilterStart()
local AAASet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterAAA):FilterStart() local AAASet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterAAA):FilterStart()
local SAMSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterSAM):FilterStart() local SAMSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterSAM):FilterStart()
local OpsGroupSet = SET_OPSGROUP:New():FilterActive(true):FilterStart() local OpsGroupSet = SET_OPSGROUP:New():FilterActive(true):FilterStart()
self.FlightSet = SET_GROUP:New():FilterCategories({" plane" ," helicopter" }):FilterStart() self.FlightSet = SET_GROUP:New():FilterCategories({" plane" ," helicopter" }):FilterStart()
-- Cache frequently used values
local EngageRange = self.AAARange local EngageRange = self.AAARange
local SwitchAAA = self.SwitchAAA
local ExceptionSet = self.ExceptionSet local ExceptionSet = self.ExceptionSet
if self.ExceptionSet then
function ExceptionSet:OnAfterAdded(From,Event,To,ObjectName,Object) -- Pre-create data templates to reduce object creation
BASE:I("TIRESIAS: EXCEPTION Object Added: "..Object:GetName()) local exception_data = {
if Object and Object:IsAlive() then
Object.Tiresias = { -- #TIRESIAS.Data
type = " Exception" , type = " Exception" ,
exception = true, exception = true,
} }
local vehicle_data = {
type = " Vehicle" ,
invisible = true,
AIOff = true,
exception = false,
}
local aaa_data = {
type = " AAA" ,
invisible = true,
range = EngageRange,
exception = false,
AIOff = SwitchAAA,
}
local sam_data = {
type = " SAM" ,
invisible = true,
exception = false,
}
if ExceptionSet then
function ExceptionSet:OnAfterAdded(From, Event, To, ObjectName, Object)
BASE:I(" TIRESIAS: EXCEPTION Object Added: " .. Object:GetName())
if Object and Object:IsAlive() then
Object.Tiresias = exception_data
Object:SetAIOn() Object:SetAIOn()
Object:SetCommandInvisible(false) Object:SetCommandInvisible(false)
Object:EnableEmission(true) Object:EnableEmission(true)
end end
end end
-- Process existing OpsGroups more efficiently
local OGS = OpsGroupSet:GetAliveSet() local OGS = OpsGroupSet:GetAliveSet()
for _, _OG in pairs(OGS or {}) do for _, _OG in pairs(OGS or {}) do
local OG = _OG -- Ops.OpsGroup#OPSGROUP local OG = _OG -- Ops.OpsGroup#OPSGROUP
@@ -469,22 +561,16 @@ function TIRESIAS:onafterStart(From, Event, To)
end end
end end
-- Optimized event handlers with pre-created data objects
function VehicleSet:OnAfterAdded(From, Event, To, ObjectName, Object) function VehicleSet:OnAfterAdded(From, Event, To, ObjectName, Object)
BASE:I("TIRESIAS: VEHCILE Object Added: "..Object:GetName()) BASE:T(" TIRESIAS: VEHICLE Object Added: " .. Object:GetName())
if Object and Object:IsAlive() then if Object and Object:IsAlive() then
Object:SetAIOff() Object:SetAIOff()
Object:SetCommandInvisible(true) Object:SetCommandInvisible(true)
Object.Tiresias = { -- #TIRESIAS.Data Object.Tiresias = vehicle_data
type = "Vehicle",
invisible = true,
AIOff = true,
exception = false,
}
end end
end end
local SwitchAAA = self.SwitchAAA
function AAASet:OnAfterAdded(From, Event, To, ObjectName, Object) function AAASet:OnAfterAdded(From, Event, To, ObjectName, Object)
if Object and Object:IsAlive() then if Object and Object:IsAlive() then
BASE:I(" TIRESIAS: AAA Object Added: " .. Object:GetName()) BASE:I(" TIRESIAS: AAA Object Added: " .. Object:GetName())
@@ -494,28 +580,19 @@ function TIRESIAS:onafterStart(From, Event, To)
Object:SetAIOff() Object:SetAIOff()
Object:EnableEmission(false) Object:EnableEmission(false)
end end
Object.Tiresias = { -- #TIRESIAS.Data Object.Tiresias = aaa_data
type = "AAA",
invisible = true,
range = EngageRange,
exception = false,
AIOff = SwitchAAA,
}
end end
end end
function SAMSet:OnAfterAdded(From, Event, To, ObjectName, Object) function SAMSet:OnAfterAdded(From, Event, To, ObjectName, Object)
if Object and Object:IsAlive() then if Object and Object:IsAlive() then
BASE:I("TIRESIAS: SAM Object Added: "..Object:GetName()) BASE:T(" TIRESIAS: SAM Object Added: " .. Object:GetName())
Object:SetCommandInvisible(true) Object:SetCommandInvisible(true)
Object.Tiresias = { -- #TIRESIAS.Data Object.Tiresias = sam_data
type = "SAM",
invisible = true,
exception = false,
}
end end
end end
-- Store references
self.VehicleSet = VehicleSet self.VehicleSet = VehicleSet
self.AAASet = AAASet self.AAASet = AAASet
self.SAMSet = SAMSet self.SAMSet = SAMSet
@@ -535,13 +612,10 @@ end
-- @return #TIRESIAS self -- @return #TIRESIAS self
function TIRESIAS:onbeforeStatus(From, Event, To) function TIRESIAS:onbeforeStatus(From, Event, To)
self:T({From, Event, To}) self:T({From, Event, To})
if self:GetState() == "Stopped" then return self:GetState() ~= " Stopped"
return false
end
return self
end end
--- [INTERNAL] FSM Function --- [INTERNAL] FSM Function - Optimized status processing
-- @param #TIRESIAS self -- @param #TIRESIAS self
-- @param #string From -- @param #string From
-- @param #string Event -- @param #string Event
@@ -549,28 +623,36 @@ end
-- @return #TIRESIAS self -- @return #TIRESIAS self
function TIRESIAS:onafterStatus(From, Event, To) function TIRESIAS:onafterStatus(From, Event, To)
self:T({From, Event, To}) self:T({From, Event, To})
if self.debug then if self.debug then
local count = self.VehicleSet:CountAlive() local count = self.VehicleSet:CountAlive()
local AAAcount = self.AAASet:CountAlive() local AAAcount = self.AAASet:CountAlive()
local SAMcount = self.SAMSet:CountAlive() local SAMcount = self.SAMSet:CountAlive()
local text = string.format("Overall: %d | Vehicles: %d | AAA: %d | SAM: %d",count+AAAcount+SAMcount,count,AAAcount,SAMcount) self:I(string.format(" Overall: %d | Vehicles: %d | AAA: %d | SAM: %d" ,
self:I(text) count + AAAcount + SAMcount, count, AAAcount, SAMcount))
end end
self:_InitGroups() self:_InitGroups()
if self.FlightSet:CountAlive() > 0 then
-- Process flight groups more efficiently
local flight_count = self.FlightSet:CountAlive()
if flight_count > 0 then
local Set = self.FlightSet:GetAliveSet() local Set = self.FlightSet:GetAliveSet()
for _,_plane in pairs(Set) do -- Cache range values outside loop
local helo_range = self.HeloSwitchRange
local plane_range = self.PlaneSwitchRange
for _, _plane in pairs(Set or {}) do
local plane = _plane -- Wrapper.Group#GROUP local plane = _plane -- Wrapper.Group#GROUP
local radius = self.PlaneSwitchRange local radius = plane:IsHelicopter() and helo_range or plane_range
if plane:IsHelicopter() then self:_SwitchOnGroups(plane, radius)
radius = self.HeloSwitchRange
end
self:_SwitchOnGroups(_plane,radius)
end end
end end
if self:GetState() ~= " Stopped" then if self:GetState() ~= " Stopped" then
self:__Status(self.Interval) self:__Status(self.Interval)
end end
return self return self
end end
@@ -583,11 +665,11 @@ end
function TIRESIAS:onafterStop(From, Event, To) function TIRESIAS:onafterStop(From, Event, To)
self:T({From, Event, To}) self:T({From, Event, To})
self:UnHandleEvent(EVENTS.PlayerEnterAircraft) self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
-- Clear zone cache on stop to free memory
self._cached_zones = {}
return self return self
end end
------------------------------------------------------------------------------------------------------------- -----
-- ---- End
-- End -----
--
-------------------------------------------------------------------------------------------------------------

View File

@@ -3153,7 +3153,7 @@ end
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @return Core.Point#COORDINATE The coordinate of the warehouse. -- @return Core.Point#COORDINATE The coordinate of the warehouse.
function WAREHOUSE:GetCoordinate() function WAREHOUSE:GetCoordinate()
return self.warehouse:GetCoordinate() return self.warehouse:GetCoord()
end end
--- Get 3D vector of warehouse static. --- Get 3D vector of warehouse static.
@@ -6893,7 +6893,7 @@ function WAREHOUSE:_CheckConquered()
for _,_unit in pairs(units) do for _,_unit in pairs(units) do
local unit=_unit --Wrapper.Unit#UNIT local unit=_unit --Wrapper.Unit#UNIT
local distance=coord:Get2DDistance(unit:GetCoordinate()) local distance=coord:Get2DDistance(unit:GetCoord())
-- Filter only alive groud units. Also check distance again, because the scan routine might give some larger distances. -- Filter only alive groud units. Also check distance again, because the scan routine might give some larger distances.
if unit:IsGround() and unit:IsAlive() and distance <= radius then if unit:IsGround() and unit:IsAlive() and distance <= radius then

View File

@@ -7,6 +7,8 @@
-- --
-- # Developer Note -- # Developer Note
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --

View File

@@ -115,7 +115,6 @@ __Moose.Include( 'Ops\\Operation.lua' )
__Moose.Include( 'Ops\\FlightControl.lua' ) __Moose.Include( 'Ops\\FlightControl.lua' )
__Moose.Include( 'Ops\\PlayerRecce.lua' ) __Moose.Include( 'Ops\\PlayerRecce.lua' )
__Moose.Include( 'Ops\\EasyGCICAP.lua' ) __Moose.Include( 'Ops\\EasyGCICAP.lua' )
__Moose.Include( 'Ops\\EasyA2G.lua' )
__Moose.Include( 'AI\\AI_Balancer.lua' ) __Moose.Include( 'AI\\AI_Balancer.lua' )
__Moose.Include( 'AI\\AI_Air.lua' ) __Moose.Include( 'AI\\AI_Air.lua' )

View File

@@ -501,6 +501,7 @@ ATIS.Alphabet = {
-- @field #number Kola +15° (East). -- @field #number Kola +15° (East).
-- @field #number Afghanistan +3° (East). -- @field #number Afghanistan +3° (East).
-- @field #number Iraq +4.4° (East). -- @field #number Iraq +4.4° (East).
-- @field #number GermanyCW +0.1° (East).
ATIS.RunwayM2T = { ATIS.RunwayM2T = {
Caucasus = 0, Caucasus = 0,
Nevada = 12, Nevada = 12,
@@ -513,7 +514,8 @@ ATIS.RunwayM2T = {
SinaiMap = 5, SinaiMap = 5,
Kola = 15, Kola = 15,
Afghanistan = 3, Afghanistan = 3,
Iraq=4.4 Iraq=4.4,
GermanyCW=0.1,
} }
--- Whether ICAO phraseology is used for ATIS broadcasts. --- Whether ICAO phraseology is used for ATIS broadcasts.
@@ -530,6 +532,7 @@ ATIS.RunwayM2T = {
-- @field #boolean Kola true. -- @field #boolean Kola true.
-- @field #boolean Afghanistan true. -- @field #boolean Afghanistan true.
-- @field #boolean Iraq true. -- @field #boolean Iraq true.
-- @field #boolean GermanyCW true.
ATIS.ICAOPhraseology = { ATIS.ICAOPhraseology = {
Caucasus = true, Caucasus = true,
Nevada = false, Nevada = false,
@@ -543,6 +546,7 @@ ATIS.ICAOPhraseology = {
Kola = true, Kola = true,
Afghanistan = true, Afghanistan = true,
Iraq = true, Iraq = true,
GermanyCW = true,
} }
--- Nav point data. --- Nav point data.
@@ -2794,7 +2798,7 @@ function ATIS:onafterBroadcast( From, Event, To )
end end
_RUNACT = subtitle _RUNACT = subtitle
alltext = alltext .. ";\n" .. subtitle --alltext = alltext .. ";\n" .. subtitle
-- Runway length. -- Runway length.
if self.rwylength then if self.rwylength then

View File

@@ -159,6 +159,8 @@ AIRWING = {
-- @field #number refuelsystem Refueling system type: `0=Unit.RefuelingSystem.BOOM_AND_RECEPTACLE`, `1=Unit.RefuelingSystem.PROBE_AND_DROGUE`. -- @field #number refuelsystem Refueling system type: `0=Unit.RefuelingSystem.BOOM_AND_RECEPTACLE`, `1=Unit.RefuelingSystem.PROBE_AND_DROGUE`.
-- @field #number noccupied Number of flights on this patrol point. -- @field #number noccupied Number of flights on this patrol point.
-- @field Wrapper.Marker#MARKER marker F10 marker. -- @field Wrapper.Marker#MARKER marker F10 marker.
-- @field #boolean IsZonePoint flag for using a (moving) zone as point for patrol etc.
-- @field Core.Zone#ZONE_BASE patrolzone in case Patrol coordinate was handed as zone, store here.
--- Patrol zone. --- Patrol zone.
-- @type AIRWING.PatrolZone -- @type AIRWING.PatrolZone
@@ -187,13 +189,14 @@ AIRWING = {
--- AIRWING class version. --- AIRWING class version.
-- @field #string version -- @field #string version
AIRWING.version="0.9.6" AIRWING.version="0.9.7"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list -- ToDo list
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Check that airbase has enough parking spots if a request is BIG. -- TODO: Check that airbase has enough parking spots if a request is BIG.
-- DONE: Allow (moving) zones as base for patrol points.
-- DONE: Spawn in air ==> Needs WAREHOUSE update. -- DONE: Spawn in air ==> Needs WAREHOUSE update.
-- DONE: Spawn hot. -- DONE: Spawn hot.
-- DONE: Make special request to transfer squadrons to anther airwing (or warehouse). -- DONE: Make special request to transfer squadrons to anther airwing (or warehouse).
@@ -807,21 +810,30 @@ function AIRWING:_PatrolPointMarkerText(point)
end end
--- Update marker of the patrol point. --- Update marker of the patrol point.
-- @param #AIRWING self
-- @param #AIRWING.PatrolData point Patrol point table. -- @param #AIRWING.PatrolData point Patrol point table.
function AIRWING:UpdatePatrolPointMarker(point) function AIRWING:UpdatePatrolPointMarker(point)
if self.markpoints then -- sometimes there's a direct call from #OPSGROUP
if self and self.markpoints then -- sometimes there's a direct call from #OPSGROUP
local text=string.format("%s Occupied=%d\nheading=%03d, leg=%d NM, alt=%d ft, speed=%d kts", local text=string.format("%s Occupied=%d\nheading=%03d, leg=%d NM, alt=%d ft, speed=%d kts",
point.type, point.noccupied, point.heading, point.leg, point.altitude, point.speed) point.type, point.noccupied, point.heading, point.leg, point.altitude, point.speed)
if point.IsZonePoint and point.IsZonePoint == true and point.patrolzone then
-- update position
local Coordinate = point.patrolzone:GetCoordinate()
point.marker:UpdateCoordinate(Coordinate)
point.marker:UpdateText(text, 1.5)
else
point.marker:UpdateText(text, 1) point.marker:UpdateText(text, 1)
end end
end end
end
--- Create a new generic patrol point. --- Create a new generic patrol point.
-- @param #AIRWING self -- @param #AIRWING self
-- @param #string Type Patrol point type, e.g. "CAP" or "AWACS". Default "Unknown". -- @param #string Type Patrol point type, e.g. "CAP" or "AWACS". Default "Unknown".
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. Default 10-15 NM away from the location of the airwing. -- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. Default 10-15 NM away from the location of the airwing. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Orbit altitude in feet. Default random between Angels 10 and 20. -- @param #number Altitude Orbit altitude in feet. Default random between Angels 10 and 20.
-- @param #number Heading Heading in degrees. Default random (0, 360] degrees. -- @param #number Heading Heading in degrees. Default random (0, 360] degrees.
-- @param #number LegLength Length of race-track orbit in NM. Default 15 NM. -- @param #number LegLength Length of race-track orbit in NM. Default 15 NM.
@@ -830,14 +842,16 @@ end
-- @return #AIRWING.PatrolData Patrol point table. -- @return #AIRWING.PatrolData Patrol point table.
function AIRWING:NewPatrolPoint(Type, Coordinate, Altitude, Speed, Heading, LegLength, RefuelSystem) function AIRWING:NewPatrolPoint(Type, Coordinate, Altitude, Speed, Heading, LegLength, RefuelSystem)
-- Check if a zone was passed instead of a coordinate.
if Coordinate and Coordinate:IsInstanceOf("ZONE_BASE") then
Coordinate=Coordinate:GetCoordinate()
end
local patrolpoint={} --#AIRWING.PatrolData local patrolpoint={} --#AIRWING.PatrolData
patrolpoint.type=Type or "Unknown" patrolpoint.type=Type or "Unknown"
patrolpoint.coord=Coordinate or self:GetCoordinate():Translate(UTILS.NMToMeters(math.random(10, 15)), math.random(360)) patrolpoint.coord=Coordinate or self:GetCoordinate():Translate(UTILS.NMToMeters(math.random(10, 15)), math.random(360))
if Coordinate:IsInstanceOf("ZONE_BASE") then
patrolpoint.IsZonePoint = true
patrolpoint.patrolzone = Coordinate
patrolpoint.coord = patrolpoint.patrolzone:GetCoordinate()
else
patrolpoint.IsZonePoint = false
end
patrolpoint.heading=Heading or math.random(360) patrolpoint.heading=Heading or math.random(360)
patrolpoint.leg=LegLength or 15 patrolpoint.leg=LegLength or 15
patrolpoint.altitude=Altitude or math.random(10,20)*1000 patrolpoint.altitude=Altitude or math.random(10,20)*1000
@@ -847,7 +861,7 @@ function AIRWING:NewPatrolPoint(Type, Coordinate, Altitude, Speed, Heading, LegL
if self.markpoints then if self.markpoints then
patrolpoint.marker=MARKER:New(Coordinate, "New Patrol Point"):ToAll() patrolpoint.marker=MARKER:New(Coordinate, "New Patrol Point"):ToAll()
AIRWING.UpdatePatrolPointMarker(patrolpoint) self:UpdatePatrolPointMarker(patrolpoint)
end end
return patrolpoint return patrolpoint
@@ -855,7 +869,7 @@ end
--- Add a patrol Point for CAP missions. --- Add a patrol Point for CAP missions.
-- @param #AIRWING self -- @param #AIRWING self
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. -- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Orbit altitude in feet. -- @param #number Altitude Orbit altitude in feet.
-- @param #number Speed Orbit speed in knots. -- @param #number Speed Orbit speed in knots.
-- @param #number Heading Heading in degrees. -- @param #number Heading Heading in degrees.
@@ -872,7 +886,7 @@ end
--- Add a patrol Point for RECON missions. --- Add a patrol Point for RECON missions.
-- @param #AIRWING self -- @param #AIRWING self
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. -- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Orbit altitude in feet. -- @param #number Altitude Orbit altitude in feet.
-- @param #number Speed Orbit speed in knots. -- @param #number Speed Orbit speed in knots.
-- @param #number Heading Heading in degrees. -- @param #number Heading Heading in degrees.
@@ -889,7 +903,7 @@ end
--- Add a patrol Point for TANKER missions. --- Add a patrol Point for TANKER missions.
-- @param #AIRWING self -- @param #AIRWING self
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. -- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Orbit altitude in feet. -- @param #number Altitude Orbit altitude in feet.
-- @param #number Speed Orbit speed in knots. -- @param #number Speed Orbit speed in knots.
-- @param #number Heading Heading in degrees. -- @param #number Heading Heading in degrees.
@@ -907,7 +921,7 @@ end
--- Add a patrol Point for AWACS missions. --- Add a patrol Point for AWACS missions.
-- @param #AIRWING self -- @param #AIRWING self
-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. -- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Orbit altitude in feet. -- @param #number Altitude Orbit altitude in feet.
-- @param #number Speed Orbit speed in knots. -- @param #number Speed Orbit speed in knots.
-- @param #number Heading Heading in degrees. -- @param #number Heading Heading in degrees.
@@ -974,6 +988,46 @@ function AIRWING:SetTakeoffAir()
return self return self
end end
--- Set the aircraft of the AirWing to land straight in.
-- @param #AIRWING self
-- @return #FLIGHTGROUP self
function AIRWING:SetLandingStraightIn()
self.OptionLandingStraightIn = true
return self
end
--- Set the aircraft of the AirWing to land in pairs for groups > 1 aircraft.
-- @param #AIRWING self
-- @return #AIRWING self
function AIRWING:SetLandingForcePair()
self.OptionLandingForcePair = true
return self
end
--- Set the aircraft of the AirWing to NOT land in pairs.
-- @param #AIRWING self
-- @return #AIRWING self
function AIRWING:SetLandingRestrictPair()
self.OptionLandingRestrictPair = true
return self
end
--- Set the aircraft of the AirWing to land after overhead break.
-- @param #AIRWING self
-- @return #AIRWING self
function AIRWING:SetLandingOverheadBreak()
self.OptionLandingOverheadBreak = true
return self
end
--- [Helicopter] Set the aircraft of the AirWing to prefer vertical takeoff and landing.
-- @param #AIRWING self
-- @return #AIRWING self
function AIRWING:SetOptionPreferVerticalLanding()
self.OptionPreferVerticalLanding = true
return self
end
--- Set despawn after landing. Aircraft will be despawned after the landing event. --- Set despawn after landing. Aircraft will be despawned after the landing event.
-- Can help to avoid DCS AI taxiing issues. -- Can help to avoid DCS AI taxiing issues.
-- @param #AIRWING self -- @param #AIRWING self
@@ -1136,6 +1190,10 @@ function AIRWING:_GetPatrolData(PatrolPoints, RefuelSystem)
for _,_patrolpoint in pairs(PatrolPoints) do for _,_patrolpoint in pairs(PatrolPoints) do
local patrolpoint=_patrolpoint --#AIRWING.PatrolData local patrolpoint=_patrolpoint --#AIRWING.PatrolData
if patrolpoint.IsZonePoint and patrolpoint.IsZonePoint == true and patrolpoint.patrolzone then
-- update
patrolpoint.coord = patrolpoint.patrolzone:GetCoordinate()
end
if (RefuelSystem and patrolpoint.refuelsystem and RefuelSystem==patrolpoint.refuelsystem) or RefuelSystem==nil or patrolpoint.refuelsystem==nil then if (RefuelSystem and patrolpoint.refuelsystem and RefuelSystem==patrolpoint.refuelsystem) or RefuelSystem==nil or patrolpoint.refuelsystem==nil then
return patrolpoint return patrolpoint
end end
@@ -1195,7 +1253,7 @@ function AIRWING:CheckCAP()
patrol.noccupied=patrol.noccupied+1 patrol.noccupied=patrol.noccupied+1
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end if self.markpoints then self:UpdatePatrolPointMarker(patrol) end
self:AddMission(missionCAP) self:AddMission(missionCAP)
@@ -1247,7 +1305,7 @@ function AIRWING:CheckRECON()
patrol.noccupied=patrol.noccupied+1 patrol.noccupied=patrol.noccupied+1
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end if self.markpoints then self:UpdatePatrolPointMarker(patrol) end
self:AddMission(missionRECON) self:AddMission(missionRECON)
@@ -1292,7 +1350,7 @@ function AIRWING:CheckTANKER()
patrol.noccupied=patrol.noccupied+1 patrol.noccupied=patrol.noccupied+1
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end if self.markpoints then self:UpdatePatrolPointMarker(patrol) end
self:AddMission(mission) self:AddMission(mission)
@@ -1311,7 +1369,7 @@ function AIRWING:CheckTANKER()
patrol.noccupied=patrol.noccupied+1 patrol.noccupied=patrol.noccupied+1
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end if self.markpoints then self:UpdatePatrolPointMarker(patrol) end
self:AddMission(mission) self:AddMission(mission)
@@ -1349,7 +1407,7 @@ function AIRWING:CheckAWACS()
patrol.noccupied=patrol.noccupied+1 patrol.noccupied=patrol.noccupied+1
if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end if self.markpoints then self:UpdatePatrolPointMarker(patrol) end
self:AddMission(mission) self:AddMission(mission)
@@ -1465,6 +1523,20 @@ function AIRWING:onafterFlightOnMission(From, Event, To, FlightGroup, Mission)
if self.UseConnectedOpsAwacs and self.ConnectedOpsAwacs then if self.UseConnectedOpsAwacs and self.ConnectedOpsAwacs then
self.ConnectedOpsAwacs:__FlightOnMission(2,FlightGroup,Mission) self.ConnectedOpsAwacs:__FlightOnMission(2,FlightGroup,Mission)
end end
-- Landing Options
if self.OptionLandingForcePair then
FlightGroup:SetOptionLandingForcePair()
elseif self.OptionLandingOverheadBreak then
FlightGroup:SetOptionLandingOverheadBreak()
elseif self.OptionLandingRestrictPair then
FlightGroup:SetOptionLandingRestrictPair()
elseif self.OptionLandingStraightIn then
FlightGroup:SetOptionLandingStraightIn()
end
-- Landing Options Helo
if self.OptionPreferVerticalLanding then
FlightGroup:SetOptionPreferVertical()
end
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -397,6 +397,7 @@ AUFTRAG = {
conditionPush = {}, conditionPush = {},
conditionSuccessSet = false, conditionSuccessSet = false,
conditionFailureSet = false, conditionFailureSet = false,
repeatDelay = 1,
} }
--- Global mission counter. --- Global mission counter.
@@ -1428,7 +1429,7 @@ function AUFTRAG:NewCAP(ZoneCAP, Altitude, Speed, Coordinate, Heading, Leg, Targ
mission:_SetLogID() mission:_SetLogID()
-- DCS task parameters: -- DCS task parameters:
mission.engageZone=ZoneCAP mission.engageZone=ZoneCAP or Coordinate
mission.engageTargetTypes=TargetTypes or {"Air"} mission.engageTargetTypes=TargetTypes or {"Air"}
-- Mission options: -- Mission options:
@@ -1715,9 +1716,45 @@ function AUFTRAG:NewSEAD(Target, Altitude)
return mission return mission
end end
--- **[AIR]** Create a SEAD in Zone mission.
-- @param #AUFTRAG self
-- @param Core.Zone#ZONE TargetZone The target zone to attack.
-- @param #number Altitude Engage altitude in feet. Default 25000 ft.
-- @param #table TargetTypes Table of string of DCS known target types, defaults to {"Air Defence"}. See [DCS Target Attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes)
-- @param #number Duration Engage this much time when the AUFTRAG starts executing.
-- @return #AUFTRAG self
function AUFTRAG:NewSEADInZone(TargetZone, Altitude, TargetTypes, Duration)
local mission=AUFTRAG:New(AUFTRAG.Type.SEAD)
--mission:_TargetFromObject(TargetZone)
-- DCS Task options:
mission.engageWeaponType=ENUMS.WeaponFlag.Auto
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000)
mission.engageZone = TargetZone
mission.engageTargetTypes = TargetTypes or {"Air Defence"}
-- Mission options:
mission.missionTask=ENUMS.MissionTask.SEAD
mission.missionAltitude=mission.engageAltitude
mission.missionFraction=0.2
mission.optionROE=ENUMS.ROE.OpenFire
mission.optionROT=ENUMS.ROT.EvadeFire
mission.categories={AUFTRAG.Category.AIRCRAFT}
mission.DCStask=mission:GetDCSMissionTask()
mission:SetDuration(Duration or 1800)
return mission
end
--- **[AIR]** Create a STRIKE mission. Flight will attack the closest map object to the specified coordinate. --- **[AIR]** Create a STRIKE mission. Flight will attack the closest map object to the specified coordinate.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT, STATIC or TARGET object. -- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT, STATIC, SET_GROUP, SET_UNIT, SET_STATIC or TARGET object.
-- @param #number Altitude Engage altitude in feet. Default 2000 ft. -- @param #number Altitude Engage altitude in feet. Default 2000 ft.
-- @param #number EngageWeaponType Which weapon to use. Defaults to auto, ie ENUMS.WeaponFlag.Auto. See ENUMS.WeaponFlag for options. -- @param #number EngageWeaponType Which weapon to use. Defaults to auto, ie ENUMS.WeaponFlag.Auto. See ENUMS.WeaponFlag for options.
-- @return #AUFTRAG self -- @return #AUFTRAG self
@@ -1749,11 +1786,12 @@ end
--- **[AIR]** Create a BOMBING mission. Flight will drop bombs a specified coordinate. --- **[AIR]** Create a BOMBING mission. Flight will drop bombs a specified coordinate.
-- See [DCS task bombing](https://wiki.hoggitworld.com/view/DCS_task_bombing). -- See [DCS task bombing](https://wiki.hoggitworld.com/view/DCS_task_bombing).
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT, STATIC or TARGET object. -- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT, STATIC, SET_GROUP, SET_UNIT, SET_STATIC or TARGET object.
-- @param #number Altitude Engage altitude in feet. Default 25000 ft. -- @param #number Altitude Engage altitude in feet. Default 25000 ft.
-- @param #number EngageWeaponType Which weapon to use. Defaults to auto, ie ENUMS.WeaponFlag.Auto. See ENUMS.WeaponFlag for options. -- @param #number EngageWeaponType Which weapon to use. Defaults to auto, ie ENUMS.WeaponFlag.Auto. See ENUMS.WeaponFlag for options.
-- @param #boolean Divebomb If true, use a dive bombing attack approach.
-- @return #AUFTRAG self -- @return #AUFTRAG self
function AUFTRAG:NewBOMBING(Target, Altitude, EngageWeaponType) function AUFTRAG:NewBOMBING(Target, Altitude, EngageWeaponType, Divebomb)
local mission=AUFTRAG:New(AUFTRAG.Type.BOMBING) local mission=AUFTRAG:New(AUFTRAG.Type.BOMBING)
@@ -1770,6 +1808,7 @@ function AUFTRAG:NewBOMBING(Target, Altitude, EngageWeaponType)
mission.missionFraction=0.5 mission.missionFraction=0.5
mission.optionROE=ENUMS.ROE.OpenFire mission.optionROE=ENUMS.ROE.OpenFire
mission.optionROT=ENUMS.ROT.NoReaction -- No reaction is better. mission.optionROT=ENUMS.ROT.NoReaction -- No reaction is better.
mission.optionDivebomb = Divebomb or nil
-- Evaluate result after 5 min. We might need time until the bombs have dropped and targets have been detroyed. -- Evaluate result after 5 min. We might need time until the bombs have dropped and targets have been detroyed.
mission.dTevaluate=5*60 mission.dTevaluate=5*60
@@ -2966,6 +3005,16 @@ function AUFTRAG:SetRepeat(Nrepeat)
return self return self
end end
--- **[LEGION, COMMANDER, CHIEF]** Set the repeat delay in seconds after a mission is successful/failed. Only valid if the mission is handled by a LEGION (AIRWING, BRIGADE, FLEET) or higher level.
-- @param #AUFTRAG self
-- @param #number Nrepeat Repeat delay in seconds. Default 1.
-- @return #AUFTRAG self
function AUFTRAG:SetRepeatDelay(RepeatDelay)
self.repeatDelay = RepeatDelay
return self
end
--- **[LEGION, COMMANDER, CHIEF]** Set how many times the mission is repeated if it fails. Only valid if the mission is handled by a LEGION (AIRWING, BRIGADE, FLEET) or higher level. --- **[LEGION, COMMANDER, CHIEF]** Set how many times the mission is repeated if it fails. Only valid if the mission is handled by a LEGION (AIRWING, BRIGADE, FLEET) or higher level.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param #number Nrepeat Number of repeats. Default 0. -- @param #number Nrepeat Number of repeats. Default 0.
@@ -4765,6 +4814,8 @@ end
-- @return #boolean If `true`, all groups are done with the mission. -- @return #boolean If `true`, all groups are done with the mission.
function AUFTRAG:CheckGroupsDone() function AUFTRAG:CheckGroupsDone()
local fsmState = self:GetState()
-- Check status of all OPS groups. -- Check status of all OPS groups.
for groupname,data in pairs(self.groupdata) do for groupname,data in pairs(self.groupdata) do
local groupdata=data --#AUFTRAG.GroupData local groupdata=data --#AUFTRAG.GroupData
@@ -4823,6 +4874,11 @@ function AUFTRAG:CheckGroupsDone()
return true return true
end end
if (self:IsStarted() or self:IsExecuting()) and (fsmState == AUFTRAG.Status.STARTED or fsmState == AUFTRAG.Status.EXECUTING) and self:CountOpsGroups()>0 then
self:T(self.lid..string.format("CheckGroupsDone: Mission is STARTED state %s [FSM=%s] and count of alive OPSGROUP > zero. Mission NOT DONE!", self.status, self:GetState()))
return false
end
return true return true
end end
@@ -5160,7 +5216,7 @@ function AUFTRAG:onafterSuccess(From, Event, To)
-- Repeat mission. -- Repeat mission.
self:T(self.lid..string.format("Mission SUCCESS! Repeating mission for the %d time (max %d times) ==> Repeat mission!", self.repeated+1, N)) self:T(self.lid..string.format("Mission SUCCESS! Repeating mission for the %d time (max %d times) ==> Repeat mission!", self.repeated+1, N))
self:Repeat() self:__Repeat(self.repeatDelay)
else else
@@ -5202,7 +5258,7 @@ function AUFTRAG:onafterFailed(From, Event, To)
-- Repeat mission. -- Repeat mission.
self:T(self.lid..string.format("Mission FAILED! Repeating mission for the %d time (max %d times) ==> Repeat mission!", self.repeated+1, N)) self:T(self.lid..string.format("Mission FAILED! Repeating mission for the %d time (max %d times) ==> Repeat mission!", self.repeated+1, N))
self:Repeat() self:__Repeat(self.repeatDelay)
else else
@@ -6108,9 +6164,12 @@ function AUFTRAG:GetDCSMissionTask()
-- BOMBING Mission -- -- BOMBING Mission --
--------------------- ---------------------
local DCStask=CONTROLLABLE.TaskBombing(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, Divebomb) local coords = self.engageTarget:GetCoordinates()
for _, coord in pairs(coords) do
local DCStask = CONTROLLABLE.TaskBombing(nil, coord:GetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, self.optionDivebomb)
table.insert(DCStasks, DCStask) table.insert(DCStasks, DCStask)
end
elseif self.type==AUFTRAG.Type.STRAFING then elseif self.type==AUFTRAG.Type.STRAFING then
@@ -6148,7 +6207,15 @@ function AUFTRAG:GetDCSMissionTask()
-- CAP Mission -- -- CAP Mission --
----------------- -----------------
local DCStask=CONTROLLABLE.EnRouteTaskEngageTargetsInZone(nil, self.engageZone:GetVec2(), self.engageZone:GetRadius(), self.engageTargetTypes, Priority) local Vec2 = self.engageZone:GetVec2()
local Radius
if self.engageZone:IsInstanceOf("COORDINATE") then
Radius = UTILS.NMToMeters(20)
else
Radius = self.engageZone:GetRadius()
end
local DCStask=CONTROLLABLE.EnRouteTaskEngageTargetsInZone(nil, Vec2, Radius, self.engageTargetTypes, Priority)
table.insert(self.enrouteTasks, DCStask) table.insert(self.enrouteTasks, DCStask)
@@ -6303,17 +6370,46 @@ function AUFTRAG:GetDCSMissionTask()
--local DCStask=CONTROLLABLE.EnRouteTaskSEAD(nil, self.TargetType) --local DCStask=CONTROLLABLE.EnRouteTaskSEAD(nil, self.TargetType)
--table.insert(self.enrouteTasks, DCStask) --table.insert(self.enrouteTasks, DCStask)
if self.engageZone then
--local DCStask=CONTROLLABLE.EnRouteTaskSEAD(nil, self.engageTargetTypes)
--table.insert(self.enrouteTasks, DCStask)
self.engageZone:Scan({Object.Category.UNIT},{Unit.Category.GROUND_UNIT})
local ScanUnitSet = self.engageZone:GetScannedSetUnit()
local SeadUnitSet = SET_UNIT:New()
for _,_unit in pairs (ScanUnitSet.Set) do
local unit = _unit -- Wrapper.Unit#UNTI
if unit and unit:IsAlive() and unit:HasSEAD() then
self:T("Adding UNIT for SEAD: "..unit:GetName())
local task = CONTROLLABLE.TaskAttackUnit(nil,unit,GroupAttack,AI.Task.WeaponExpend.ALL,1,Direction,self.engageAltitude,2956984318)
table.insert(DCStasks, task)
SeadUnitSet:AddUnit(unit)
end
end
self.engageTarget = TARGET:New(SeadUnitSet)
--local OrbitTask = CONTROLLABLE.TaskOrbitCircle(nil,self.engageAltitude,self.missionSpeed,self.engageZone:GetCoordinate())
--local Point = self.engageZone:GetVec2()
--local OrbitTask = CONTROLLABLE.TaskOrbitCircleAtVec2(nil,Point,self.engageAltitude,self.missionSpeed)
--table.insert(DCStasks, OrbitTask)
else
self:_GetDCSAttackTask(self.engageTarget, DCStasks) self:_GetDCSAttackTask(self.engageTarget, DCStasks)
end
elseif self.type==AUFTRAG.Type.STRIKE then elseif self.type==AUFTRAG.Type.STRIKE then
-------------------- --------------------
-- STRIKE Mission -- -- STRIKE Mission --
-------------------- --------------------
local DCStask=CONTROLLABLE.TaskAttackMapObject(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType) local coords = self.engageTarget:GetCoordinates()
for _, coord in pairs(coords) do
local DCStask=CONTROLLABLE.TaskAttackMapObject(nil, coord:GetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType)
table.insert(DCStasks, DCStask) table.insert(DCStasks, DCStask)
end
elseif self.type==AUFTRAG.Type.TANKER or self.type==AUFTRAG.Type.RECOVERYTANKER then elseif self.type==AUFTRAG.Type.TANKER or self.type==AUFTRAG.Type.RECOVERYTANKER then

View File

@@ -17,7 +17,7 @@
-- === -- ===
-- --
-- ### Author: **applevangelist** -- ### Author: **applevangelist**
-- @date Last Update Jan 2025 -- @date Last Update July 2025
-- @module Ops.AWACS -- @module Ops.AWACS
-- @image OPS_AWACS.jpg -- @image OPS_AWACS.jpg
@@ -237,7 +237,7 @@ do
-- -- Callsign will be "Focus". We'll be a Angels 30, doing 300 knots, orbit leg to 88deg with a length of 25nm. -- -- Callsign will be "Focus". We'll be a Angels 30, doing 300 knots, orbit leg to 88deg with a length of 25nm.
-- testawacs:SetAwacsDetails(CALLSIGN.AWACS.Focus,1,30,300,88,25) -- testawacs:SetAwacsDetails(CALLSIGN.AWACS.Focus,1,30,300,88,25)
-- -- Set up SRS on port 5010 - change the below to your path and port -- -- Set up SRS on port 5010 - change the below to your path and port
-- testawacs:SetSRS("C:\\Program Files\\DCS-SimpleRadio-Standalone","female","en-GB",5010) -- testawacs:SetSRS("C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio","female","en-GB",5010)
-- -- Add a "red" border we don't want to cross, set up in the mission editor with a late activated helo named "Red Border#ZONE_POLYGON" -- -- Add a "red" border we don't want to cross, set up in the mission editor with a late activated helo named "Red Border#ZONE_POLYGON"
-- testawacs:SetRejectionZone(ZONE:FindByName("Red Border")) -- testawacs:SetRejectionZone(ZONE:FindByName("Red Border"))
-- -- Our CAP flight will have the callsign "Ford", we want 4 AI planes, Time-On-Station is four hours, doing 300 kn IAS. -- -- Our CAP flight will have the callsign "Ford", we want 4 AI planes, Time-On-Station is four hours, doing 300 kn IAS.
@@ -255,7 +255,7 @@ do
-- -- The CAP station zone is called "Fremont". We will be on 255 AM. Note the Orbit Zone is given as *nil* in the `New()`-Statement -- -- The CAP station zone is called "Fremont". We will be on 255 AM. Note the Orbit Zone is given as *nil* in the `New()`-Statement
-- local testawacs = AWACS:New("GCI Senaki",AwacsAW,"blue",AIRBASE.Caucasus.Senaki_Kolkhi,nil,ZONE:FindByName("Rock"),"Fremont",255,radio.modulation.AM ) -- local testawacs = AWACS:New("GCI Senaki",AwacsAW,"blue",AIRBASE.Caucasus.Senaki_Kolkhi,nil,ZONE:FindByName("Rock"),"Fremont",255,radio.modulation.AM )
-- -- Set up SRS on port 5010 - change the below to your path and port -- -- Set up SRS on port 5010 - change the below to your path and port
-- testawacs:SetSRS("C:\\Program Files\\DCS-SimpleRadio-Standalone","female","en-GB",5010) -- testawacs:SetSRS("C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio","female","en-GB",5010)
-- -- Add a "red" border we don't want to cross, set up in the mission editor with a late activated helo named "Red Border#ZONE_POLYGON" -- -- Add a "red" border we don't want to cross, set up in the mission editor with a late activated helo named "Red Border#ZONE_POLYGON"
-- testawacs:SetRejectionZone(ZONE:FindByName("Red Border")) -- testawacs:SetRejectionZone(ZONE:FindByName("Red Border"))
-- -- Our CAP flight will have the callsign "Ford", we want 4 AI planes, Time-On-Station is four hours, doing 300 kn IAS. -- -- Our CAP flight will have the callsign "Ford", we want 4 AI planes, Time-On-Station is four hours, doing 300 kn IAS.
@@ -509,7 +509,7 @@ do
-- @field #AWACS -- @field #AWACS
AWACS = { AWACS = {
ClassName = "AWACS", -- #string ClassName = "AWACS", -- #string
version = "0.2.71", -- #string version = "0.2.72", -- #string
lid = "", -- #string lid = "", -- #string
coalition = coalition.side.BLUE, -- #number coalition = coalition.side.BLUE, -- #number
coalitiontxt = "blue", -- #string coalitiontxt = "blue", -- #string
@@ -1123,7 +1123,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
self.EscortMissionReplacement = {} self.EscortMissionReplacement = {}
-- SRS -- SRS
self.PathToSRS = "C:\\Program Files\\DCS-SimpleRadio-Standalone" self.PathToSRS = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
self.Gender = "female" self.Gender = "female"
self.Culture = "en-GB" self.Culture = "en-GB"
self.Voice = nil self.Voice = nil
@@ -1242,6 +1242,8 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
self:AddTransition("*", "Intercept", "*") self:AddTransition("*", "Intercept", "*")
self:AddTransition("*", "InterceptSuccess", "*") self:AddTransition("*", "InterceptSuccess", "*")
self:AddTransition("*", "InterceptFailure", "*") self:AddTransition("*", "InterceptFailure", "*")
self:AddTransition("*", "VIDSuccess", "*")
self:AddTransition("*", "VIDFailure", "*")
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
@@ -1365,19 +1367,39 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
-- @param #string To To state. -- @param #string To To state.
--- On After "InterceptSuccess" event. Intercept successful. --- On After "InterceptSuccess" event. Intercept successful.
-- @function [parent=#AWACS] OnAfterIntercept -- @function [parent=#AWACS] OnAfterInterceptSuccess
-- @param #AWACS self -- @param #AWACS self
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
--- On After "InterceptFailure" event. Intercept failure. --- On After "InterceptFailure" event. Intercept failure.
-- @function [parent=#AWACS] OnAfterIntercept -- @function [parent=#AWACS] OnAfterInterceptFailure
-- @param #AWACS self -- @param #AWACS self
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
--- On After "VIDSuccess" event. Intercept successful.
-- @function [parent=#AWACS] OnAfterVIDSuccess
-- @param #AWACS self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #number GID Managed group ID (Player)
-- @param Wrapper.Group#GROUP Group (Player) Group done the VID
-- @param #AWACS.ManagedContact Contact The contact that was VID'd
--- On After "VIDFailure" event. Intercept failure.
-- @function [parent=#AWACS] OnAfterVIDFailure
-- @param #AWACS self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #number GID Managed group ID (Player)
-- @param Wrapper.Group#GROUP Group (Player) Group done the VID
-- @param #AWACS.ManagedContact Contact The contact that was VID'd
return self return self
end end
@@ -2091,7 +2113,7 @@ end
--- [User] Set AWACS SRS TTS details - see @{Sound.SRS} for details. `SetSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible. --- [User] Set AWACS SRS TTS details - see @{Sound.SRS} for details. `SetSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
-- @param #AWACS self -- @param #AWACS self
-- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone" -- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
-- @param #string Gender Defaults to "male" -- @param #string Gender Defaults to "male"
-- @param #string Culture Defaults to "en-US" -- @param #string Culture Defaults to "en-US"
-- @param #number Port Defaults to 5002 -- @param #number Port Defaults to 5002
@@ -2104,7 +2126,7 @@ end
-- @return #AWACS self -- @return #AWACS self
function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey,Backend) function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey,Backend)
self:T(self.lid.."SetSRS") self:T(self.lid.."SetSRS")
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
self.Gender = Gender or MSRS.gender or "male" self.Gender = Gender or MSRS.gender or "male"
self.Culture = Culture or MSRS.culture or "en-US" self.Culture = Culture or MSRS.culture or "en-US"
self.Port = Port or MSRS.port or 5002 self.Port = Port or MSRS.port or 5002
@@ -3263,12 +3285,14 @@ function AWACS:_VID(Group,Declaration)
local vidpos = self.gettext:GetEntry("VIDPOS",self.locale) local vidpos = self.gettext:GetEntry("VIDPOS",self.locale)
text = string.format(vidpos,Callsign,self.callsigntxt, Declaration) text = string.format(vidpos,Callsign,self.callsigntxt, Declaration)
self:T(text) self:T(text)
self:__VIDSuccess(3,GID,group,cluster)
else else
-- too far away -- too far away
self:T("Contact VID not close enough") self:T("Contact VID not close enough")
local vidneg = self.gettext:GetEntry("VIDNEG",self.locale) local vidneg = self.gettext:GetEntry("VIDNEG",self.locale)
text = string.format(vidneg,Callsign,self.callsigntxt) text = string.format(vidneg,Callsign,self.callsigntxt)
self:T(text) self:T(text)
self:__VIDFailure(3,GID,group,cluster)
end end
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true) self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
end end

View File

@@ -31,7 +31,7 @@
-- @image OPS_CSAR.jpg -- @image OPS_CSAR.jpg
--- ---
-- Last Update Jan 2025 -- Last Update July 2025
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
@@ -130,7 +130,7 @@
-- ## 2.2 SRS Features and Other Features -- ## 2.2 SRS Features and Other Features
-- --
-- mycsar.useSRS = false -- Set true to use FF\'s SRS integration -- mycsar.useSRS = false -- Set true to use FF\'s SRS integration
-- mycsar.SRSPath = "C:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!) -- mycsar.SRSPath = "C:\\Progra~1\\DCS-SimpleRadio-Standalone\\ExternalAudio\\" -- adjust your own path in your SRS installation -- server(!)
-- mycsar.SRSchannel = 300 -- radio channel -- mycsar.SRSchannel = 300 -- radio channel
-- mycsar.SRSModulation = radio.modulation.AM -- modulation -- mycsar.SRSModulation = radio.modulation.AM -- modulation
-- mycsar.SRSport = 5002 -- and SRS Server port -- mycsar.SRSport = 5002 -- and SRS Server port
@@ -263,6 +263,7 @@ CSAR = {
rescuedpilots = 0, rescuedpilots = 0,
limitmaxdownedpilots = true, limitmaxdownedpilots = true,
maxdownedpilots = 10, maxdownedpilots = 10,
useFIFOLimitReplacement = false, -- If true, it will remove the oldest downed pilot when a new one is added, if the limit is reached.
allheligroupset = nil, allheligroupset = nil,
topmenuname = "CSAR", topmenuname = "CSAR",
ADFRadioPwr = 1000, ADFRadioPwr = 1000,
@@ -313,7 +314,7 @@ CSAR.AircraftType["CH-47Fbl1"] = 31
--- CSAR class version. --- CSAR class version.
-- @field #string version -- @field #string version
CSAR.version="1.0.30" CSAR.version="1.0.33"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list -- ToDo list
@@ -468,7 +469,7 @@ function CSAR:New(Coalition, Template, Alias)
-- added 1.0.15 -- added 1.0.15
self.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane self.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane
self.ADFRadioPwr = 1000 self.ADFRadioPwr = 500
-- added 1.0.16 -- added 1.0.16
self.PilotWeight = 80 self.PilotWeight = 80
@@ -480,7 +481,7 @@ function CSAR:New(Coalition, Template, Alias)
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua -- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
-- needs SRS => 1.9.6 to work (works on the *server* side) -- needs SRS => 1.9.6 to work (works on the *server* side)
self.useSRS = false -- Use FF\'s SRS integration self.useSRS = false -- Use FF\'s SRS integration
self.SRSPath = "E:\\Program Files\\DCS-SimpleRadio-Standalone" -- adjust your own path in your server(!) self.SRSPath = "E:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio" -- adjust your own path in your server(!)
self.SRSchannel = 300 -- radio channel self.SRSchannel = 300 -- radio channel
self.SRSModulation = radio.modulation.AM -- modulation self.SRSModulation = radio.modulation.AM -- modulation
self.SRSport = 5002 -- port self.SRSport = 5002 -- port
@@ -1145,17 +1146,6 @@ function CSAR:_EventHandler(EventData)
return self return self
end end
-- limit no of pilots in the field.
if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then
self:T("Maxed Downed Pilot!")
return self
end
-- TODO: Over water check --- EVENTS.LandingAfterEjection NOT triggered by DCS, so handle csarUsePara = true case
-- might create dual pilots in edge cases
local wetfeet = false
local initdcscoord = nil local initdcscoord = nil
local initcoord = nil local initcoord = nil
@@ -1169,6 +1159,36 @@ function CSAR:_EventHandler(EventData)
self:T({initdcscoord}) self:T({initdcscoord})
end end
-- Remove downed pilot if already exists to replace with new one.
if _event.IniPlayerName then
local PilotTable = self.downedPilots --#CSAR.DownedPilot
local _foundPilot = nil
for _,_pilot in pairs(PilotTable) do
if _pilot.player == _event.IniPlayerName and _pilot.alive == true then
_foundPilot = _pilot
break
end
end
if _foundPilot then
self:T("Downed pilot already exists!")
_foundPilot.group:Destroy(false)
self:_RemoveNameFromDownedPilots(_foundPilot.name)
self:_CheckDownedPilotTable()
end
end
-- limit no of pilots in the field.
if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then
self:T("Maxed Downed Pilot!")
return self
end
-- TODO: Over water check --- EVENTS.LandingAfterEjection NOT triggered by DCS, so handle csarUsePara = true case
-- might create dual pilots in edge cases
local wetfeet = false
--local surface = _unit:GetCoordinate():GetSurfaceType() --local surface = _unit:GetCoordinate():GetSurfaceType()
local surface = initcoord:GetSurfaceType() local surface = initcoord:GetSurfaceType()
@@ -1179,7 +1199,7 @@ function CSAR:_EventHandler(EventData)
-- all checks passed, get going. -- all checks passed, get going.
if self.csarUsePara == false or (self.csarUsePara and wetfeet ) then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land if self.csarUsePara == false or (self.csarUsePara and wetfeet ) then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land
local _freq = self:_GenerateADFFrequency() local _freq = self:_GenerateADFFrequency()
self:_AddCsar(_coalition, _unit:GetCountry(), initcoord , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none") self:_AddCsar(_coalition, _unit:GetCountry(), initcoord , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, self.suppressmessages, "none")
return self return self
end end
@@ -1244,7 +1264,7 @@ function CSAR:_EventHandler(EventData)
if _coalition == self.coalition then if _coalition == self.coalition then
local _freq = self:_GenerateADFFrequency() local _freq = self:_GenerateADFFrequency()
self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq}) self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq})
self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, false, "none")--shagrat add CSAR at Parachute location. self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, self.suppressmessages, "none")--shagrat add CSAR at Parachute location.
Unit.destroy(_event.initiator) -- shagrat remove static Pilot model Unit.destroy(_event.initiator) -- shagrat remove static Pilot model
end end
@@ -2116,56 +2136,50 @@ end
--- (Internal) Determine distance to closest MASH. --- (Internal) Determine distance to closest MASH.
-- @param #CSAR self -- @param #CSAR self
-- @param Wrapper.Unit#UNIT _heli Helicopter #UNIT -- @param Wrapper.Unit#UNIT _heli Helicopter #UNIT
-- @return #CSAR self -- @return #number Distance in meters
-- @return #string MASH Name as string
function CSAR:_GetClosestMASH(_heli) function CSAR:_GetClosestMASH(_heli)
self:T(self.lid .. " _GetClosestMASH") self:T(self.lid .. " _GetClosestMASH")
local _mashset = self.mash -- Core.Set#SET_GROUP local _mashset = self.mash -- Core.Set#SET_GROUP
local _mashes = _mashset:GetSetObjects() -- #table local MashSets = {}
--local _mashes = _mashset.Set-- #table
table.insert(MashSets,_mashset.Set)
table.insert(MashSets,self.zonemashes.Set)
table.insert(MashSets,self.staticmashes.Set)
local _shortestDistance = -1 local _shortestDistance = -1
local _distance = 0 local _distance = 0
local _helicoord = _heli:GetCoordinate() local _helicoord = _heli:GetCoordinate()
local MashName = nil
local function GetCloseAirbase(coordinate,Coalition,Category)
local a=coordinate:GetVec3()
local distmin=math.huge
local airbase=nil
for DCSairbaseID, DCSairbase in pairs(world.getAirbases(Coalition)) do
local b=DCSairbase:getPoint()
local c=UTILS.VecSubstract(a,b)
local dist=UTILS.VecNorm(c)
if dist<distmin and (Category==nil or Category==DCSairbase:getDesc().category) then
distmin=dist
airbase=DCSairbase
end
end
return distmin
end
if self.allowFARPRescue then if self.allowFARPRescue then
local position = _heli:GetCoordinate() local position = _heli:GetCoordinate()
local afb,distance = position:GetClosestAirbase(nil,self.coalition) local afb,distance = position:GetClosestAirbase(nil,self.coalition)
_shortestDistance = distance _shortestDistance = distance
MashName = (afb ~= nil) and afb:GetName() or "Unknown"
end end
for _, _mashUnit in pairs(_mashes) do for _,_mashes in pairs(MashSets) do
if _mashUnit and _mashUnit:IsAlive() then for _, _mashUnit in pairs(_mashes or {}) do
local _mashcoord = _mashUnit:GetCoordinate() local _mashcoord
if _mashUnit and (not _mashUnit:IsInstanceOf("ZONE_BASE")) and _mashUnit:IsAlive() then
_mashcoord = _mashUnit:GetCoordinate()
elseif _mashUnit and _mashUnit:IsInstanceOf("ZONE_BASE") then
_mashcoord = _mashUnit:GetCoordinate()
end
_distance = self:_GetDistance(_helicoord, _mashcoord) _distance = self:_GetDistance(_helicoord, _mashcoord)
if _distance ~= nil and (_shortestDistance == -1 or _distance < _shortestDistance) then if _distance ~= nil and (_shortestDistance == -1 or _distance < _shortestDistance) then
_shortestDistance = _distance _shortestDistance = _distance
MashName = _mashUnit:GetName() or "Unknown"
end end
end end
end end
if _shortestDistance ~= -1 then if _shortestDistance ~= -1 then
return _shortestDistance return _shortestDistance, MashName
else else
return -1 return -1
end end
end end
--- (Internal) Display onboarded rescued pilots. --- (Internal) Display onboarded rescued pilots.
@@ -2323,9 +2337,9 @@ end
-- @param #CSAR self -- @param #CSAR self
-- @param Wrapper.Group#GROUP _group Group #GROUP object. -- @param Wrapper.Group#GROUP _group Group #GROUP object.
-- @param #number _freq Frequency to use -- @param #number _freq Frequency to use
-- @param #string _name Beacon Name to use -- @param #string BeaconName Beacon Name to use
-- @return #CSAR self -- @return #CSAR self
function CSAR:_AddBeaconToGroup(_group, _freq, _name) function CSAR:_AddBeaconToGroup(_group, _freq, BeaconName)
self:T(self.lid .. " _AddBeaconToGroup") self:T(self.lid .. " _AddBeaconToGroup")
if self.CreateRadioBeacons == false then return end if self.CreateRadioBeacons == false then return end
local _group = _group local _group = _group
@@ -2346,10 +2360,11 @@ function CSAR:_AddBeaconToGroup(_group, _freq, _name)
if _radioUnit then if _radioUnit then
local name = _radioUnit:GetName() local name = _radioUnit:GetName()
local Frequency = _freq -- Freq in Hertz local Frequency = _freq -- Freq in Hertz
local name = _radioUnit:GetName() --local name = _radioUnit:GetName()
local Sound = "l10n/DEFAULT/"..self.radioSound local Sound = "l10n/DEFAULT/"..self.radioSound
local vec3 = _radioUnit:GetVec3() or _radioUnit:GetPositionVec3() or {x=0,y=0,z=0} local vec3 = _radioUnit:GetVec3() or _radioUnit:GetPositionVec3() or {x=0,y=0,z=0}
trigger.action.radioTransmission(Sound, vec3, 0, false, Frequency, self.ADFRadioPwr or 1000,_name) -- Beacon in MP only runs for exactly 30secs straight self:I(self.lid..string.format("Added Radio Beacon %d Hertz | Name %s | Position {%d,%d,%d}",Frequency,BeaconName,vec3.x,vec3.y,vec3.z))
trigger.action.radioTransmission(Sound, vec3, 0, true, Frequency, self.ADFRadioPwr or 500,BeaconName) -- Beacon in MP only runs for exactly 30secs straight
end end
end end
@@ -2370,9 +2385,13 @@ function CSAR:_RefreshRadioBeacons()
local group = pilot.group local group = pilot.group
local frequency = pilot.frequency or 0 -- thanks to @Thrud local frequency = pilot.frequency or 0 -- thanks to @Thrud
local bname = pilot.BeaconName or pilot.name..math.random(1,100000) local bname = pilot.BeaconName or pilot.name..math.random(1,100000)
trigger.action.stopRadioTransmission(bname) --trigger.action.stopRadioTransmission(bname)
if group and group:IsAlive() and frequency > 0 then if group and group:IsAlive() and frequency > 0 then
self:_AddBeaconToGroup(group,frequency,bname) --self:_AddBeaconToGroup(group,frequency,bname)
else
if frequency > 0 then
trigger.action.stopRadioTransmission(bname)
end
end end
end end
end end
@@ -2403,6 +2422,21 @@ function CSAR:_ReachedPilotLimit()
local islimited = self.limitmaxdownedpilots local islimited = self.limitmaxdownedpilots
local count = self:_CountActiveDownedPilots() local count = self:_CountActiveDownedPilots()
if islimited and (count >= limit) then if islimited and (count >= limit) then
if self.useFIFOLimitReplacement then
local oldIndex = -1
local oldDownedPilot = nil
for _index, _downedpilot in pairs(self.downedPilots) do
oldIndex = _index
oldDownedPilot = _downedpilot
break
end
if oldDownedPilot then
oldDownedPilot.group:Destroy(false)
oldDownedPilot.alive = false
self:_CheckDownedPilotTable()
return false
end
end
return true return true
else else
return false return false
@@ -2454,9 +2488,10 @@ function CSAR:onafterStart(From, Event, To)
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart()
local staticmashes = SET_STATIC:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterOnce() self.staticmashes = SET_STATIC:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart()
local zonemashes = SET_ZONE:New():FilterPrefixes(self.mashprefix):FilterOnce() self.zonemashes = SET_ZONE:New():FilterPrefixes(self.mashprefix):FilterStart()
--[[
if staticmashes:Count() > 0 then if staticmashes:Count() > 0 then
for _,_mash in pairs(staticmashes.Set) do for _,_mash in pairs(staticmashes.Set) do
self.mash:AddObject(_mash) self.mash:AddObject(_mash)
@@ -2464,10 +2499,13 @@ function CSAR:onafterStart(From, Event, To)
end end
if zonemashes:Count() > 0 then if zonemashes:Count() > 0 then
self:T("Adding zones to self.mash SET")
for _,_mash in pairs(zonemashes.Set) do for _,_mash in pairs(zonemashes.Set) do
self.mash:AddObject(_mash) self.mash:AddObject(_mash)
end end
self:T("Objects in SET: "..self.mash:Count())
end end
--]]
if not self.coordinate then if not self.coordinate then
local csarhq = self.mash:GetRandom() local csarhq = self.mash:GetRandom()
@@ -2968,7 +3006,7 @@ function CSAR:onafterLoad(From, Event, To, path, filename)
local unitName = dataset[9] local unitName = dataset[9]
local freq = tonumber(dataset[10]) local freq = tonumber(dataset[10])
self:_AddCsar(coalition, country, point, typeName, unitName, playerName, freq, nil, description, nil) self:_AddCsar(coalition, country, point, typeName, unitName, playerName, freq, false, description, nil)
end end
return self return self

View File

@@ -20,11 +20,12 @@
-- --
-- ### Author: **Applevangelist** (Moose Version), ***Ciribob*** (original), Thanks to: Shadowze, Cammel (testing), bbirchnz (additional code!!) -- ### Author: **Applevangelist** (Moose Version), ***Ciribob*** (original), Thanks to: Shadowze, Cammel (testing), bbirchnz (additional code!!)
-- ### Repack addition for crates: **Raiden** -- ### Repack addition for crates: **Raiden**
-- ### Additional cool features: **Lekaa**
-- --
-- @module Ops.CTLD -- @module Ops.CTLD
-- @image OPS_CTLD.jpg -- @image OPS_CTLD.jpg
-- Last Update April 2025 -- Last Update July 2025
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -865,6 +866,8 @@ do
-- my_ctld.TroopUnloadDistGroundHook = 15 -- On the ground, unload troops this far behind the Chinook -- my_ctld.TroopUnloadDistGroundHook = 15 -- On the ground, unload troops this far behind the Chinook
-- my_ctld.TroopUnloadDistHoverHook = 5 -- When hovering, unload troops this far behind the Chinook -- my_ctld.TroopUnloadDistHoverHook = 5 -- When hovering, unload troops this far behind the Chinook
-- my_ctld.showstockinmenuitems = false -- When set to true, the menu lines will also show the remaining items in stock (that is, if you set any), downside is that the menu for all will be build every 30 seconds anew. -- my_ctld.showstockinmenuitems = false -- When set to true, the menu lines will also show the remaining items in stock (that is, if you set any), downside is that the menu for all will be build every 30 seconds anew.
-- my_ctld.onestepmenu = false -- When set to true, the menu will create Drop and build, Get and load, Pack and remove, Pack and load, Pack. it will be a 1 step solution.
-- my_ctld.VehicleMoveFormation = AI.Task.VehicleFormation.VEE -- When a group moves to a MOVE zone, then it takes this formation. Can be a table of formations, which are then randomly chosen. Defaults to "Vee".
-- --
-- ## 2.1 CH-47 Chinook support -- ## 2.1 CH-47 Chinook support
-- --
@@ -1242,6 +1245,20 @@ do
-- end -- end
-- end -- end
-- --
-- ## 8. Transport crates and troops with CA (Combined Arms) trucks
--
-- You can optionally also allow to CTLD with CA trucks and other vehicles:
--
-- -- Create a SET_CLIENT to capture CA vehicles steered by players
-- local truckers = SET_CLIENT:New():HandleCASlots():FilterCoalitions("blue"):FilterPrefixes("Truck"):FilterStart()
-- -- Allow CA transport
-- my_ctld:AllowCATransport(true,truckers)
-- -- Set truck capability by typename
-- my_ctld:SetUnitCapabilities("M 818", true, true, 2, 12, 9, 4500)
-- -- Alternatively set truck capability with a UNIT object
-- local GazTruck = UNIT:FindByName("GazTruck-1-1")
-- my_ctld:SetUnitCapabilities(GazTruck, true, true, 2, 12, 9, 4500)
--
-- --
-- @field #CTLD -- @field #CTLD
CTLD = { CTLD = {
@@ -1277,6 +1294,8 @@ CTLD = {
UserSetGroup = nil, UserSetGroup = nil,
LoadedGroupsTable = {}, LoadedGroupsTable = {},
keeploadtable = true, keeploadtable = true,
allowCATransport = false,
VehicleMoveFormation = AI.Task.VehicleFormation.VEE,
} }
------------------------------ ------------------------------
@@ -1384,6 +1403,7 @@ CTLD.UnitTypeCapabilities = {
["OH58D"] = {type="OH58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400}, ["OH58D"] = {type="OH58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400},
["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 20, cargoweightlimit = 10800}, ["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 20, cargoweightlimit = 10800},
["MosquitoFBMkVI"] = {type="MosquitoFBMkVI", crates= true, troops=false, cratelimit = 2, trooplimit = 0, length = 13, cargoweightlimit = 1800}, ["MosquitoFBMkVI"] = {type="MosquitoFBMkVI", crates= true, troops=false, cratelimit = 2, trooplimit = 0, length = 13, cargoweightlimit = 1800},
["M 818"] = {type="M 818", crates= true, troops=true, cratelimit = 4, trooplimit = 12, length = 9, cargoweightlimit = 4500},
} }
--- Allowed Fixed Wing Types --- Allowed Fixed Wing Types
@@ -1396,7 +1416,7 @@ CTLD.FixedWingTypes = {
--- CTLD class version. --- CTLD class version.
-- @field #string version -- @field #string version
CTLD.version="1.1.31" CTLD.version="1.3.37"
--- Instantiate a new CTLD. --- Instantiate a new CTLD.
-- @param #CTLD self -- @param #CTLD self
@@ -1463,6 +1483,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event. self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event.
self:AddTransition("*", "CratesBuildStarted", "*") -- CTLD build event. self:AddTransition("*", "CratesBuildStarted", "*") -- CTLD build event.
self:AddTransition("*", "CratesRepairStarted", "*") -- CTLD repair event. self:AddTransition("*", "CratesRepairStarted", "*") -- CTLD repair event.
self:AddTransition("*", "CratesPacked", "*") -- CTLD repack event.
self:AddTransition("*", "HelicopterLost", "*") -- CTLD lost event. self:AddTransition("*", "HelicopterLost", "*") -- CTLD lost event.
self:AddTransition("*", "Load", "*") -- CTLD load event. self:AddTransition("*", "Load", "*") -- CTLD load event.
self:AddTransition("*", "Loaded", "*") -- CTLD load event. self:AddTransition("*", "Loaded", "*") -- CTLD load event.
@@ -1535,6 +1556,8 @@ function CTLD:New(Coalition, Prefixes, Alias)
self.movetroopsdistance = 5000 self.movetroopsdistance = 5000
self.troopdropzoneradius = 100 self.troopdropzoneradius = 100
self.VehicleMoveFormation = AI.Task.VehicleFormation.VEE
-- added support Hercules Mod -- added support Hercules Mod
self.enableHercules = false -- deprecated self.enableHercules = false -- deprecated
self.enableFixedWing = false self.enableFixedWing = false
@@ -1575,6 +1598,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
self.subcats = {} self.subcats = {}
self.subcatsTroop = {} self.subcatsTroop = {}
self.showstockinmenuitems = false self.showstockinmenuitems = false
self.onestepmenu = false
-- disallow building in loadzones -- disallow building in loadzones
self.nobuildinloadzones = true self.nobuildinloadzones = true
@@ -1606,6 +1630,10 @@ function CTLD:New(Coalition, Prefixes, Alias)
math.random() math.random()
end end
-- CA Transport
self.allowCATransport = false -- #boolean
self.CATransportSet = nil -- Core.Set#SET_CLIENT
self:_GenerateVHFrequencies() self:_GenerateVHFrequencies()
self:_GenerateUHFrequencies() self:_GenerateUHFrequencies()
self:_GenerateFMFrequencies() self:_GenerateFMFrequencies()
@@ -1737,6 +1765,17 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired. -- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired.
-- @return #CTLD self -- @return #CTLD self
--- FSM Function OnBeforeCratesPacked.
-- @function [parent=#CTLD] OnBeforeCratesPacked
-- @param #CTLD self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @param #CTLD_CARGO Cargo Cargo crate that was repacked.
-- @return #CTLD self
--- FSM Function OnBeforeTroopsRTB. --- FSM Function OnBeforeTroopsRTB.
-- @function [parent=#CTLD] OnBeforeTroopsRTB -- @function [parent=#CTLD] OnBeforeTroopsRTB
-- @param #CTLD self -- @param #CTLD self
@@ -1823,6 +1862,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- @param #string To State. -- @param #string To State.
-- @param Wrapper.Group#GROUP Group Group Object. -- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object. -- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @param CargoName The name of the cargo being built.
-- @return #CTLD self -- @return #CTLD self
--- FSM Function OnAfterCratesRepairStarted. Info event that a repair has been started. --- FSM Function OnAfterCratesRepairStarted. Info event that a repair has been started.
@@ -1866,6 +1906,17 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired. -- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired.
-- @return #CTLD self -- @return #CTLD self
--- FSM Function OnAfterCratesPacked.
-- @function [parent=#CTLD] OnAfterCratesPacked
-- @param #CTLD self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @param #CTLD_CARGO Cargo Cargo crate that was repacked.
-- @return #CTLD self
--- FSM Function OnAfterTroopsRTB. --- FSM Function OnAfterTroopsRTB.
-- @function [parent=#CTLD] OnAfterTroopsRTB -- @function [parent=#CTLD] OnAfterTroopsRTB
-- @param #CTLD self -- @param #CTLD self
@@ -1949,6 +2000,16 @@ function CTLD:_GetUnitCapabilities(Unit)
return capabilities return capabilities
end end
--- (User) Function to allow transport via Combined Arms Trucks.
-- @param #CTLD self
-- @param #boolean OnOff Switch on (true) or off (false).
-- @param Core.Set#SET_CLIENT ClientSet The CA handling client set for ground transport.
-- @return #CTLD self
function CTLD:AllowCATransport(OnOff,ClientSet)
self.allowCATransport = OnOff -- #boolean
self.CATransportSet = ClientSet -- Core.Set#SET_CLIENT
return self
end
--- (Internal) Function to generate valid UHF Frequencies --- (Internal) Function to generate valid UHF Frequencies
-- @param #CTLD self -- @param #CTLD self
@@ -2029,6 +2090,12 @@ function CTLD:_EventHandler(EventData)
self.Loaded_Cargo[unitname] = nil self.Loaded_Cargo[unitname] = nil
self:_RefreshF10Menus() self:_RefreshF10Menus()
end end
-- CA support
if _unit:IsGround() and self.allowCATransport then
local unitname = event.IniUnitName or "none"
self.Loaded_Cargo[unitname] = nil
self:_RefreshF10Menus()
end
return return
elseif event.id == EVENTS.Land or event.id == EVENTS.Takeoff then elseif event.id == EVENTS.Land or event.id == EVENTS.Takeoff then
local unitname = event.IniUnitName local unitname = event.IniUnitName
@@ -2036,6 +2103,9 @@ function CTLD:_EventHandler(EventData)
local _group = event.IniGroup local _group = event.IniGroup
local _unit = event.IniUnit local _unit = event.IniUnit
self:_RefreshLoadCratesMenu(_group, _unit) self:_RefreshLoadCratesMenu(_group, _unit)
if self:IsFixedWing(_unit) and self.enableFixedWing then
self:_RefreshDropCratesMenu(_group, _unit)
end
end end
elseif event.id == EVENTS.PlayerLeaveUnit or event.id == EVENTS.UnitLost then elseif event.id == EVENTS.PlayerLeaveUnit or event.id == EVENTS.UnitLost then
-- remove from pilot table -- remove from pilot table
@@ -2742,6 +2812,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
-- spawn crates in front of helicopter -- spawn crates in front of helicopter
local IsHerc = self:IsFixedWing(Unit) -- Herc, Bronco and Hook load from behind local IsHerc = self:IsFixedWing(Unit) -- Herc, Bronco and Hook load from behind
local IsHook = self:IsHook(Unit) -- Herc, Bronco and Hook load from behind local IsHook = self:IsHook(Unit) -- Herc, Bronco and Hook load from behind
local IsTruck = Unit:IsGround()
local cargotype = Cargo -- Ops.CTLD#CTLD_CARGO local cargotype = Cargo -- Ops.CTLD#CTLD_CARGO
local number = number or cargotype:GetCratesNeeded() --#number local number = number or cargotype:GetCratesNeeded() --#number
local cratesneeded = cargotype:GetCratesNeeded() --#number local cratesneeded = cargotype:GetCratesNeeded() --#number
@@ -2763,7 +2834,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
local rheading = 0 local rheading = 0
local angleOffNose = 0 local angleOffNose = 0
local addon = 0 local addon = 0
if IsHerc or IsHook then if IsHerc or IsHook or IsTruck then
-- spawn behind the Herc -- spawn behind the Herc
addon = 180 addon = 180
end end
@@ -2784,7 +2855,11 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
if cratedistance > self.CrateDistance then cratedistance = self.CrateDistance end if cratedistance > self.CrateDistance then cratedistance = self.CrateDistance end
-- altered heading logic -- altered heading logic
-- DONE: right standard deviation? -- DONE: right standard deviation?
if self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) then
rheading = math.random(20,60)
else
rheading = UTILS.RandomGaussian(0, 30, -90, 90, 100) rheading = UTILS.RandomGaussian(0, 30, -90, 90, 100)
end
rheading=math.fmod((heading+rheading),360) rheading=math.fmod((heading+rheading),360)
cratecoord = position:Translate(cratedistance,rheading) cratecoord = position:Translate(cratedistance,rheading)
else else
@@ -2876,10 +2951,10 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
if drop then if drop then
text = string.format("Crates for %s have been dropped!",cratename) text = string.format("Crates for %s have been dropped!",cratename)
self:__CratesDropped(1, Group, Unit, droppedcargo) self:__CratesDropped(1, Group, Unit, droppedcargo)
end else
self:_SendMessage(text, 10, false, Group) self:_SendMessage(text, 10, false, Group)
end
self:_RefreshLoadCratesMenu(Group, Unit) self:_RefreshLoadCratesMenu(Group, Unit)
return self return self
end end
@@ -3093,24 +3168,24 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight, ignoretype
if not _ignoreweight then if not _ignoreweight then
maxloadable = self:_GetMaxLoadableMass(_unit) maxloadable = self:_GetMaxLoadableMass(_unit)
end end
self:T2(self.lid .. " Max loadable mass: " .. maxloadable) self:T(self.lid .. " Max loadable mass: " .. maxloadable)
for _,_cargoobject in pairs (existingcrates) do for _,_cargoobject in pairs (existingcrates) do
local cargo = _cargoobject -- #CTLD_CARGO local cargo = _cargoobject -- #CTLD_CARGO
local static = cargo:GetPositionable() -- Wrapper.Static#STATIC -- crates local static = cargo:GetPositionable() -- Wrapper.Static#STATIC -- crates
local weight = cargo:GetMass() -- weight in kgs of this cargo local weight = cargo:GetMass() -- weight in kgs of this cargo
local staticid = cargo:GetID() local staticid = cargo:GetID()
self:T2(self.lid .. " Found cargo mass: " .. weight) self:T(self.lid .. " Found cargo mass: " .. weight)
if static and static:IsAlive() then --or cargoalive) then if static and static:IsAlive() then --or cargoalive) then
local restricthooktononstatics = self.enableChinookGCLoading and IsHook local restricthooktononstatics = self.enableChinookGCLoading and IsHook
--self:I(self.lid .. " restricthooktononstatics: " .. tostring(restricthooktononstatics)) self:T(self.lid .. " restricthooktononstatics: " .. tostring(restricthooktononstatics))
local cargoisstatic = cargo:GetType() == CTLD_CARGO.Enum.STATIC and true or false local cargoisstatic = cargo:GetType() == CTLD_CARGO.Enum.STATIC and true or false
--self:I(self.lid .. " Cargo is static: " .. tostring(cargoisstatic)) self:T(self.lid .. " Cargo is static: " .. tostring(cargoisstatic))
local restricted = cargoisstatic and restricthooktononstatics local restricted = cargoisstatic and restricthooktononstatics
--self:I(self.lid .. " Loading restricted: " .. tostring(restricted)) self:T(self.lid .. " Loading restricted: " .. tostring(restricted))
local staticpos = static:GetCoordinate() --or dcsunitpos local staticpos = static:GetCoordinate() --or dcsunitpos
local cando = cargo:UnitCanCarry(_unit) local cando = cargo:UnitCanCarry(_unit)
if ignoretype == true then cando = true end if ignoretype == true then cando = true end
--self:I(self.lid .. " Unit can carry: " .. tostring(cando)) self:T(self.lid .. " Unit can carry: " .. tostring(cando))
--- Testing --- Testing
local distance = self:_GetDistance(location,staticpos) local distance = self:_GetDistance(location,staticpos)
self:T(self.lid .. string.format("Dist %dm/%dm | weight %dkg | maxloadable %dkg",distance,finddist,weight,maxloadable)) self:T(self.lid .. string.format("Dist %dm/%dm | weight %dkg | maxloadable %dkg",distance,finddist,weight,maxloadable))
@@ -3527,7 +3602,7 @@ end
function CTLD:IsFixedWing(Unit) function CTLD:IsFixedWing(Unit)
local typename = Unit:GetTypeName() or "none" local typename = Unit:GetTypeName() or "none"
for _,_name in pairs(self.FixedWingTypes or {}) do for _,_name in pairs(self.FixedWingTypes or {}) do
if typename == _name or string.find(typename,_name,1,true) then if _name and (typename==_name or string.find(typename,_name,1,true))then
return true return true
end end
end end
@@ -3539,7 +3614,10 @@ end
-- @param Wrapper.Unit#UNIT Unit -- @param Wrapper.Unit#UNIT Unit
-- @return #boolean Outcome -- @return #boolean Outcome
function CTLD:IsHook(Unit) function CTLD:IsHook(Unit)
if Unit and string.find(Unit:GetTypeName(),"CH.47") then if not Unit then return false end
local typeName = Unit:GetTypeName()
if not typeName then return false end
if string.find(typeName, "CH.47") then
return true return true
else else
return false return false
@@ -3729,7 +3807,6 @@ function CTLD:_UnloadCrates(Group, Unit)
self:T(self.lid .. " _UnloadCrates") self:T(self.lid .. " _UnloadCrates")
if not self.dropcratesanywhere then -- #1570 if not self.dropcratesanywhere then -- #1570
-- check if we are in DROP zone
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.DROP) local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.DROP)
if not inzone then if not inzone then
self:_SendMessage("You are not close enough to a drop zone!", 10, false, Group) self:_SendMessage("You are not close enough to a drop zone!", 10, false, Group)
@@ -3738,46 +3815,60 @@ function CTLD:_UnloadCrates(Group, Unit)
end end
end end
end end
-- Door check
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
self:_SendMessage("You need to open the door(s) to drop cargo!", 10, false, Group) self:_SendMessage("You need to open the door(s) to drop cargo!", 10, false, Group)
if not self.debug then return self end if not self.debug then return self end
end end
-- check for hover unload local hoverunload = self:IsCorrectHover(Unit)
local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters
local IsHerc = self:IsFixedWing(Unit) local IsHerc = self:IsFixedWing(Unit)
local IsHook = self:IsHook(Unit) local IsHook = self:IsHook(Unit)
if IsHerc and (not IsHook) then if IsHerc and (not IsHook) then
-- no hover but airdrop here
hoverunload = self:IsCorrectFlightParameters(Unit) hoverunload = self:IsCorrectFlightParameters(Unit)
end end
-- check if we\'re landed
local grounded = not self:IsUnitInAir(Unit) local grounded = not self:IsUnitInAir(Unit)
-- Get what we have loaded
local unitname = Unit:GetName() local unitname = Unit:GetName()
if self.Loaded_Cargo[unitname] and (grounded or hoverunload) then if self.Loaded_Cargo[unitname] and (grounded or hoverunload) then
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo local loadedcargo = self.Loaded_Cargo[unitname] or {}
-- looking for crate
local cargotable = loadedcargo.Cargo local cargotable = loadedcargo.Cargo
local droppedCount = {}
local neededMap = {}
for _,_cargo in pairs (cargotable) do for _,_cargo in pairs (cargotable) do
local cargo = _cargo -- #CTLD_CARGO local cargo = _cargo
local type = cargo:GetType() -- #CTLD_CARGO.Enum local type = cargo:GetType()
if type ~= CTLD_CARGO.Enum.TROOPS and type ~= CTLD_CARGO.Enum.ENGINEERS and type ~= CTLD_CARGO.Enum.GCLOADABLE and (not cargo:WasDropped() or self.allowcratepickupagain) then if type ~= CTLD_CARGO.Enum.TROOPS and type ~= CTLD_CARGO.Enum.ENGINEERS and type ~= CTLD_CARGO.Enum.GCLOADABLE and (not cargo:WasDropped() or self.allowcratepickupagain) then
-- unload crates
self:_GetCrates(Group, Unit, cargo, 1, true) self:_GetCrates(Group, Unit, cargo, 1, true)
cargo:SetWasDropped(true) cargo:SetWasDropped(true)
cargo:SetHasMoved(true) cargo:SetHasMoved(true)
local cname = cargo:GetName() or "Unknown"
droppedCount[cname] = (droppedCount[cname] or 0) + 1
if not neededMap[cname] then
neededMap[cname] = cargo:GetCratesNeeded() or 1
end end
end end
-- cleanup load list end
local loaded = {} -- #CTLD.LoadedCargo for cname,count in pairs(droppedCount) do
local needed = neededMap[cname] or 1
if needed > 1 then
local full = math.floor(count/needed)
local left = count % needed
if full > 0 and left == 0 then
self:_SendMessage(string.format("Dropped %d %s.",full,cname),10,false,Group)
elseif full > 0 and left > 0 then
self:_SendMessage(string.format("Dropped %d %s(s), with %d leftover crate(s).",full,cname,left),10,false,Group)
else
self:_SendMessage(string.format("Dropped %d/%d crate(s) of %s.",count,needed,cname),15,false,Group)
end
else
self:_SendMessage(string.format("Dropped %d %s(s).",count,cname),10,false,Group)
end
end
local loaded = {}
loaded.Troopsloaded = 0 loaded.Troopsloaded = 0
loaded.Cratesloaded = 0 loaded.Cratesloaded = 0
loaded.Cargo = {} loaded.Cargo = {}
for _,_cargo in pairs (cargotable) do for _,_cargo in pairs (cargotable) do
local cargo = _cargo -- #CTLD_CARGO local cargo = _cargo
local type = cargo:GetType() -- #CTLD_CARGO.Enum local type = cargo:GetType()
local size = cargo:GetCratesNeeded() local size = cargo:GetCratesNeeded()
if type == CTLD_CARGO.Enum.TROOPS or type == CTLD_CARGO.Enum.ENGINEERS then if type == CTLD_CARGO.Enum.TROOPS or type == CTLD_CARGO.Enum.ENGINEERS then
table.insert(loaded.Cargo,_cargo) table.insert(loaded.Cargo,_cargo)
@@ -3808,7 +3899,8 @@ end
-- @param Wrapper.Group#GROUP Group -- @param Wrapper.Group#GROUP Group
-- @param Wrapper.Unit#UNIT Unit -- @param Wrapper.Unit#UNIT Unit
-- @param #boolean Engineering If true build is by an engineering team. -- @param #boolean Engineering If true build is by an engineering team.
function CTLD:_BuildCrates(Group, Unit,Engineering) -- @param #boolean MultiDrop If true and not engineering or FOB, vary position a bit.
function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop)
self:T(self.lid .. " _BuildCrates") self:T(self.lid .. " _BuildCrates")
-- avoid users trying to build from flying Hercs -- avoid users trying to build from flying Hercs
if self:IsFixedWing(Unit) and self.enableFixedWing and not Engineering then if self:IsFixedWing(Unit) and self.enableFixedWing and not Engineering then
@@ -3902,12 +3994,13 @@ function CTLD:_BuildCrates(Group, Unit,Engineering)
if build.CanBuild then if build.CanBuild then
self:_CleanUpCrates(crates,build,number) self:_CleanUpCrates(crates,build,number)
if self.buildtime and self.buildtime > 0 then if self.buildtime and self.buildtime > 0 then
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate()) local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate(),MultiDrop)
buildtimer:Start(self.buildtime) buildtimer:Start(self.buildtime)
self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group) self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group)
self:__CratesBuildStarted(1,Group,Unit) self:__CratesBuildStarted(1,Group,Unit,build.Name)
self:_RefreshDropTroopsMenu(Group,Unit)
else else
self:_BuildObjectFromCrates(Group,Unit,build) self:_BuildObjectFromCrates(Group,Unit,build,false,nil,MultiDrop)
end end
end end
end end
@@ -3946,13 +4039,15 @@ function CTLD:_PackCratesNearby(Group, Unit)
_Group:Destroy() -- if a match is found destroy the Wrapper.Group#GROUP near the player _Group:Destroy() -- if a match is found destroy the Wrapper.Group#GROUP near the player
self:_GetCrates(Group, Unit, _entry, nil, false, true) -- spawn the appropriate crates near the player self:_GetCrates(Group, Unit, _entry, nil, false, true) -- spawn the appropriate crates near the player
self:_RefreshLoadCratesMenu(Group,Unit) -- call the refresher to show the crates in the menu self:_RefreshLoadCratesMenu(Group,Unit) -- call the refresher to show the crates in the menu
return self self:__CratesPacked(1,Group,Unit,_entry)
return true
end end
end end
end end
end end
end end
return self self:_SendMessage("Nothing to pack at this distance pilot!",10,false,Group)
return false
end end
--- (Internal) Function to repair nearby vehicles / FOBs --- (Internal) Function to repair nearby vehicles / FOBs
@@ -4045,7 +4140,8 @@ end
-- @param #CTLD.Buildable Build -- @param #CTLD.Buildable Build
-- @param #boolean Repair If true this is a repair and not a new build -- @param #boolean Repair If true this is a repair and not a new build
-- @param Core.Point#COORDINATE RepairLocation Location for repair (e.g. where the destroyed unit was) -- @param Core.Point#COORDINATE RepairLocation Location for repair (e.g. where the destroyed unit was)
function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation) -- @param #boolean MultiDrop if true and not a repair, vary location a bit if not a FOB
function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation,MultiDrop)
self:T(self.lid .. " _BuildObjectFromCrates") self:T(self.lid .. " _BuildObjectFromCrates")
-- Spawn-a-crate-content -- Spawn-a-crate-content
if Group and Group:IsAlive() or (RepairLocation and not Repair) then if Group and Group:IsAlive() or (RepairLocation and not Repair) then
@@ -4062,7 +4158,7 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
if type(temptable) == "string" then if type(temptable) == "string" then
temptable = {temptable} temptable = {temptable}
end end
local zone = nil local zone = nil -- Core.Zone#ZONE_RADIUS
if RepairLocation and not Repair then if RepairLocation and not Repair then
-- timed build -- timed build
zone = ZONE_RADIUS:New(string.format("Build zone-%d",math.random(1,10000)),RepairLocation:GetVec2(),100) zone = ZONE_RADIUS:New(string.format("Build zone-%d",math.random(1,10000)),RepairLocation:GetVec2(),100)
@@ -4071,6 +4167,10 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
end end
--local randomcoord = zone:GetRandomCoordinate(35):GetVec2() --local randomcoord = zone:GetRandomCoordinate(35):GetVec2()
local randomcoord = Build.Coord or zone:GetRandomCoordinate(35):GetVec2() local randomcoord = Build.Coord or zone:GetRandomCoordinate(35):GetVec2()
if MultiDrop and (not Repair) and canmove then
-- coordinate may be the same, avoid
local randomcoord = zone:GetRandomCoordinate(35):GetVec2()
end
if Repair then if Repair then
randomcoord = RepairLocation:GetVec2() randomcoord = RepairLocation:GetVec2()
end end
@@ -4101,6 +4201,17 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
return self return self
end end
--- (Internal) Function to get a vehicle formation for a moving group
-- @param #CTLD self
-- @return #string Formation
function CTLD:_GetVehicleFormation()
local VehicleMoveFormation = self.VehicleMoveFormation or AI.Task.VehicleFormation.VEE
if type(self.VehicleMoveFormation)=="table" then
VehicleMoveFormation = self.VehicleMoveFormation[math.random(1,#self.VehicleMoveFormation)]
end
return VehicleMoveFormation
end
--- (Internal) Function to move group to WP zone. --- (Internal) Function to move group to WP zone.
-- @param #CTLD self -- @param #CTLD self
-- @param Wrapper.Group#GROUP Group The Group to move. -- @param Wrapper.Group#GROUP Group The Group to move.
@@ -4110,22 +4221,25 @@ function CTLD:_MoveGroupToZone(Group)
local groupcoord = Group:GetCoordinate() local groupcoord = Group:GetCoordinate()
-- Get closest zone of type -- Get closest zone of type
local outcome, name, zone, distance = self:IsUnitInZone(Group,CTLD.CargoZoneType.MOVE) local outcome, name, zone, distance = self:IsUnitInZone(Group,CTLD.CargoZoneType.MOVE)
self:T({canmove=outcome, name=name, zone=zone, dist=distance,max=self.movetroopsdistance})
if (distance <= self.movetroopsdistance) and outcome == true and zone~= nil then if (distance <= self.movetroopsdistance) and outcome == true and zone~= nil then
-- yes, we can ;) -- yes, we can ;)
local groupname = Group:GetName() local groupname = Group:GetName()
local zonecoord = zone:GetRandomCoordinate(20,125) -- Core.Point#COORDINATE local zonecoord = zone:GetRandomCoordinate(20,125) -- Core.Point#COORDINATE
local coordinate = zonecoord:GetVec2() local formation = self:_GetVehicleFormation()
--local coordinate = zonecoord:GetVec2()
Group:SetAIOn() Group:SetAIOn()
Group:OptionAlarmStateAuto() Group:OptionAlarmStateAuto()
Group:OptionDisperseOnAttack(30) Group:OptionDisperseOnAttack(30)
Group:OptionROEOpenFirePossible() Group:OptionROEOpenFire()
Group:RouteToVec2(coordinate,5) Group:RouteGroundTo(zonecoord,25,formation)
end end
return self return self
end end
--- (Internal) Housekeeping - Cleanup crates when build --- (Internal) Housekeeping - Cleanup crates when build
-- @param #CTLD self -- @param #CTLD self
--
-- @param #table Crates Table of #CTLD_CARGO objects near the unit. -- @param #table Crates Table of #CTLD_CARGO objects near the unit.
-- @param #CTLD.Buildable Build Table build object. -- @param #CTLD.Buildable Build Table build object.
-- @param #number Number Number of objects in Crates (found) to limit search. -- @param #number Number Number of objects in Crates (found) to limit search.
@@ -4161,11 +4275,91 @@ function CTLD:_CleanUpCrates(Crates,Build,Number)
return self return self
end end
--- (Internal) Helper - Drop **all** loaded crates nearby and build them.
-- @param Wrapper.Group#GROUP Group The calling group
-- @param Wrapper.Unit#UNIT Unit The calling unit
function CTLD:_DropAndBuild(Group,Unit)
if self.nobuildinloadzones then
if self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD) then
self:_SendMessage("You cannot build in a loading area, Pilot!",10,false,Group)
return self
end
end
self:_UnloadCrates(Group,Unit)
timer.scheduleFunction(function() self:_BuildCrates(Group,Unit,false,true) end,{},timer.getTime()+1)
end
--- (Internal) Helper - Drop a **single** crate set and build it.
-- @param Wrapper.Group#GROUP Group The calling group
-- @param Wrapper.Unit#UNIT Unit The calling unit
-- @param number setIndex Index of the crate-set to drop
function CTLD:_DropSingleAndBuild(Group,Unit,setIndex)
if self.nobuildinloadzones then
if self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD) then
self:_SendMessage("You cannot build in a loading area, Pilot!",10,false,Group)
return self
end
end
self:_UnloadSingleCrateSet(Group,Unit,setIndex)
timer.scheduleFunction(function() self:_BuildCrates(Group,Unit,false) end,{},timer.getTime()+1)
end
--- (Internal) Helper - Pack crates near the unit and load them.
-- @param Wrapper.Group#GROUP Group The calling group
-- @param Wrapper.Unit#UNIT Unit The calling unit
function CTLD:_PackAndLoad(Group,Unit)
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
self:_SendMessage("You need to open the door(s) to load cargo!",10,false,Group)
return self
end
if not self:_PackCratesNearby(Group,Unit) then
return self
end
timer.scheduleFunction(function() self:_LoadCratesNearby(Group,Unit) end,{},timer.getTime()+1)
return self
end
--- (Internal) Helper - Pack crates near the unit and then remove them.
-- @param Wrapper.Group#GROUP Group The calling group
-- @param Wrapper.Unit#UNIT Unit The calling unit
function CTLD:_PackAndRemove(Group,Unit)
if not self:_PackCratesNearby(Group,Unit) then
return self
end
timer.scheduleFunction(function() self:_RemoveCratesNearby(Group,Unit) end,{},timer.getTime()+1)
return self
end
--- (Internal) Helper - get and load in one step
-- @param Wrapper.Group#GROUP Group The calling group
-- @param Wrapper.Unit#UNIT Unit The calling unit
function CTLD:_GetAndLoad(Group,Unit,cargoObj)
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
self:_SendMessage("You need to open the door(s) to load cargo!",10,false,Group)
return self
end
self:_GetCrates(Group,Unit,cargoObj)
timer.scheduleFunction(function() self:_LoadSingleCrateSet(Group,Unit,cargoObj.Name) end,{},timer.getTime()+1)
end
-- @param Wrapper.Group#GROUP Group The players group that triggered the action
-- @param Wrapper.Unit#UNIT Unit The unit performing the pack-and-load
function CTLD:_GetAllAndLoad(Group,Unit)
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
self:_SendMessage("You need to open the door(s) to load cargo!",10,false,Group)
return self
end
timer.scheduleFunction(function() self:_LoadCratesNearby(Group,Unit) end,{},timer.getTime()+1)
end
--- (Internal) Housekeeping - Function to refresh F10 menus. --- (Internal) Housekeeping - Function to refresh F10 menus.
-- @param #CTLD self -- @param #CTLD self
-- @return #CTLD self -- @return #CTLD self
function CTLD:_RefreshF10Menus() function CTLD:_RefreshF10Menus()
self:T(self.lid .. " _RefreshF10Menus") self:T(self.lid .. " _RefreshF10Menus")
self.onestepmenu = self.onestepmenu or false -- hybrid toggle (default = false)
-- 1) Gather all the pilot groups from our Set -- 1) Gather all the pilot groups from our Set
local PlayerSet = self.PilotGroups local PlayerSet = self.PilotGroups
@@ -4184,6 +4378,19 @@ function CTLD:_RefreshF10Menus()
end end
end end
end end
-- 3) CA Units
if self.allowCATransport and self.CATransportSet then
for _,_clientobj in pairs(self.CATransportSet.Set) do
local client = _clientobj -- Wrapper.Client#CLIENT
if client:IsGround() then
local cname = client:GetName()
self:T(self.lid.."Adding: "..cname)
_UnitList[cname] = cname
end
end
end
self.CtldUnits = _UnitList self.CtldUnits = _UnitList
-- subcats? -- subcats?
@@ -4212,10 +4419,15 @@ function CTLD:_RefreshF10Menus()
local menus = {} local menus = {}
for _, _unitName in pairs(self.CtldUnits) do for _, _unitName in pairs(self.CtldUnits) do
if (not self.MenusDone[_unitName]) or (self.showstockinmenuitems == true) then if (not self.MenusDone[_unitName]) or (self.showstockinmenuitems == true) then
self:T(self.lid.."Menu not done yet for ".._unitName)
local _unit = UNIT:FindByName(_unitName) local _unit = UNIT:FindByName(_unitName)
if not _unit and self.allowCATransport then
_unit = CLIENT:FindByName(_unitName)
end
if _unit and _unit:IsAlive() then if _unit and _unit:IsAlive() then
local _group = _unit:GetGroup() local _group = _unit:GetGroup()
if _group then if _group then
self:T(self.lid.."Unit and Group exist")
local capabilities = self:_GetUnitCapabilities(_unit) local capabilities = self:_GetUnitCapabilities(_unit)
local cantroops = capabilities.troops local cantroops = capabilities.troops
local cancrates = capabilities.crates local cancrates = capabilities.crates
@@ -4258,7 +4470,6 @@ function CTLD:_RefreshF10Menus()
local menutext = cargoObj.Name local menutext = cargoObj.Name
if (stock >= 0) and (self.showstockinmenuitems == true) then menutext = menutext.." ["..stock.."]" end if (stock >= 0) and (self.showstockinmenuitems == true) then menutext = menutext.." ["..stock.."]" end
MENU_GROUP_COMMAND:New(_group, menutext, troopsmenu, self._LoadTroops, self, _group, _unit, cargoObj) MENU_GROUP_COMMAND:New(_group, menutext, troopsmenu, self._LoadTroops, self, _group, _unit, cargoObj)
end end
end end
end end
@@ -4285,11 +4496,66 @@ function CTLD:_RefreshF10Menus()
-- Build the “Get Crates” sub-menu items -- Build the “Get Crates” sub-menu items
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates) local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
if self.onestepmenu then
if self.usesubcats then if self.usesubcats then
local subcatmenus = {} local subcatmenus = {}
for catName,_ in pairs(self.subcats) do for catName,_ in pairs(self.subcats) do
subcatmenus[catName] = MENU_GROUP:New(_group,catName,cratesmenu) subcatmenus[catName] = MENU_GROUP:New(_group,catName,cratesmenu)
end end
for _,cargoObj in pairs(self.Cargo_Crates) do
if not cargoObj.DontShowInMenu then
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
if cargoObj.Location then txt = txt.."[R]" end
local stock = cargoObj:GetStock()
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
local mSet = MENU_GROUP:New(_group,txt,subcatmenus[cargoObj.Subcategory])
MENU_GROUP_COMMAND:New(_group,"Get",mSet,self._GetCrates,self,_group,_unit,cargoObj)
MENU_GROUP_COMMAND:New(_group,"Get and Load",mSet,self._GetAndLoad,self,_group,_unit,cargoObj)
end
end
for _,cargoObj in pairs(self.Cargo_Statics) do
if not cargoObj.DontShowInMenu then
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
if cargoObj.Location then txt = txt.."[R]" end
local stock = cargoObj:GetStock()
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
local mSet = MENU_GROUP:New(_group,txt,subcatmenus[cargoObj.Subcategory])
MENU_GROUP_COMMAND:New(_group,"Get",mSet,self._GetCrates,self,_group,_unit,cargoObj)
MENU_GROUP_COMMAND:New(_group,"Get and Load",mSet,self._GetAndLoad,self,_group,_unit,cargoObj)
end
end
else
for _,cargoObj in pairs(self.Cargo_Crates) do
if not cargoObj.DontShowInMenu then
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
if cargoObj.Location then txt = txt.."[R]" end
local stock = cargoObj:GetStock()
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
local mSet = MENU_GROUP:New(_group,txt,cratesmenu)
MENU_GROUP_COMMAND:New(_group,"Get",mSet,self._GetCrates,self,_group,_unit,cargoObj)
MENU_GROUP_COMMAND:New(_group,"Get and Load",mSet,self._GetAndLoad,self,_group,_unit,cargoObj)
end
end
for _,cargoObj in pairs(self.Cargo_Statics) do
if not cargoObj.DontShowInMenu then
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
if cargoObj.Location then txt = txt.."[R]" end
local stock = cargoObj:GetStock()
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
local mSet = MENU_GROUP:New(_group,txt,cratesmenu)
MENU_GROUP_COMMAND:New(_group,"Get",mSet,self._GetCrates,self,_group,_unit,cargoObj)
MENU_GROUP_COMMAND:New(_group,"Get and Load",mSet,self._GetAndLoad,self,_group,_unit,cargoObj)
end
end
end
else
if self.usesubcats then
local subcatmenus = {}
for catName, _ in pairs(self.subcats) do
subcatmenus[catName] = MENU_GROUP:New(_group, catName, cratesmenu) -- fixed variable case
end
for _, cargoObj in pairs(self.Cargo_Crates) do for _, cargoObj in pairs(self.Cargo_Crates) do
if not cargoObj.DontShowInMenu then if not cargoObj.DontShowInMenu then
local txt = string.format("Crate %s (%dkg)", cargoObj.Name, cargoObj.PerCrateMass or 0) local txt = string.format("Crate %s (%dkg)", cargoObj.Name, cargoObj.PerCrateMass or 0)
@@ -4328,6 +4594,7 @@ function CTLD:_RefreshF10Menus()
end end
end end
end end
end
local loadCratesMenu=MENU_GROUP:New(_group,"Load Crates",topcrates) local loadCratesMenu=MENU_GROUP:New(_group,"Load Crates",topcrates)
_group.MyLoadCratesMenu=loadCratesMenu _group.MyLoadCratesMenu=loadCratesMenu
@@ -4345,8 +4612,16 @@ function CTLD:_RefreshF10Menus()
local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates) local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates)
MENU_GROUP_COMMAND:New(_group, "Remove crates nearby", removecratesmenu, self._RemoveCratesNearby, self, _group, _unit) MENU_GROUP_COMMAND:New(_group, "Remove crates nearby", removecratesmenu, self._RemoveCratesNearby, self, _group, _unit)
if self.onestepmenu then
local mPack=MENU_GROUP:New(_group,"Pack crates",topcrates)
MENU_GROUP_COMMAND:New(_group,"Pack",mPack,self._PackCratesNearby,self,_group,_unit)
MENU_GROUP_COMMAND:New(_group,"Pack and Load",mPack,self._PackAndLoad,self,_group,_unit)
MENU_GROUP_COMMAND:New(_group,"Pack and Remove",mPack,self._PackAndRemove,self,_group,_unit)
MENU_GROUP_COMMAND:New(_group, "List crates nearby", topcrates, self._ListCratesNearby, self, _group, _unit)
else
MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit) MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
MENU_GROUP_COMMAND:New(_group, "List crates nearby", topcrates, self._ListCratesNearby, self, _group, _unit) MENU_GROUP_COMMAND:New(_group, "List crates nearby", topcrates, self._ListCratesNearby, self, _group, _unit)
end
local uName = _unit:GetName() local uName = _unit:GetName()
local loadedData = self.Loaded_Cargo[uName] local loadedData = self.Loaded_Cargo[uName]
@@ -4367,8 +4642,6 @@ function CTLD:_RefreshF10Menus()
end end
end end
----------------------------------------------------- -----------------------------------------------------
-- Misc submenus -- Misc submenus
----------------------------------------------------- -----------------------------------------------------
@@ -4426,27 +4699,35 @@ function CTLD:_RefreshLoadCratesMenu(Group, Unit)
return return
end end
MENU_GROUP_COMMAND:New(Group,"Load ALL",Group.MyLoadCratesMenu,self._LoadCratesNearby,self,Group,Unit) MENU_GROUP_COMMAND:New(Group,"Load ALL",Group.MyLoadCratesMenu,self._LoadCratesNearby,self,Group,Unit)
local cargoByName={} local cargoByName={}
for _,crate in pairs(nearby) do for _,crate in pairs(nearby) do
local cName = crate:GetName() local name=crate:GetName()
cargoByName[cName] = cargoByName[cName] or {} cargoByName[name]=cargoByName[name] or{}
table.insert(cargoByName[cName], crate) table.insert(cargoByName[name],crate)
end end
for cName, cList in pairs(cargoByName) do local lineIndex=1
local needed = cList[1]:GetCratesNeeded() or 1 for cName,list in pairs(cargoByName) do
local found = #cList local needed=list[1]:GetCratesNeeded() or 1
table.sort(list,function(a,b)return a:GetID()<b:GetID() end)
local line local i=1
if found >= needed then while i<=#list do
line = string.format("Load %s", cName) local left=#list-i+1
local label
if left>=needed then
label=string.format("%d. Load %s",lineIndex,cName)
i=i+needed
else else
MENU_GROUP_COMMAND:New(Group, "Rescan?", Group.MyLoadCratesMenu, function() self:_RefreshLoadCratesMenu(Group, Unit) end) label=string.format("%d. Load %s (%d/%d)",lineIndex,cName,left,needed)
line = string.format("Load %s (%d/%d)", cName, found, needed) i=#list+1
end end
MENU_GROUP_COMMAND:New(Group, line, Group.MyLoadCratesMenu, self._LoadSingleCrateSet, self, Group, Unit, cName) MENU_GROUP_COMMAND:New(Group,label,Group.MyLoadCratesMenu,self._LoadSingleCrateSet,self,Group,Unit,cName)
lineIndex=lineIndex+1
end end
end end
end
--- ---
-- Loads exactly `CratesNeeded` crates for one cargoName in range. -- Loads exactly `CratesNeeded` crates for one cargoName in range.
@@ -4656,7 +4937,17 @@ function CTLD:_UnloadSingleCrateSet(Group, Unit, setIndex)
cObj:SetWasDropped(true) cObj:SetWasDropped(true)
cObj:SetHasMoved(true) cObj:SetHasMoved(true)
end end
local cname = crateObj:GetName() or "Unknown"
local count = #chunk
if needed > 1 then
if count == needed then
self:_SendMessage(string.format("Dropped %d %s.", 1, cname), 10, false, Group)
else
self:_SendMessage(string.format("Dropped %d/%d crate(s) of %s.", count, needed, cname), 15, false, Group)
end
else
self:_SendMessage(string.format("Dropped %d %s(s).", count, cname), 10, false, Group)
end
-- Rebuild the cargo list to remove the dropped crates -- Rebuild the cargo list to remove the dropped crates
local loadedData = self.Loaded_Cargo[unitName] local loadedData = self.Loaded_Cargo[unitName]
if loadedData and loadedData.Cargo then if loadedData and loadedData.Cargo then
@@ -4689,6 +4980,7 @@ end
-- @param Wrapper.Unit#UNIT Unit The calling unit. -- @param Wrapper.Unit#UNIT Unit The calling unit.
-- @return #CTLD self -- @return #CTLD self
function CTLD:_RefreshDropCratesMenu(Group, Unit) function CTLD:_RefreshDropCratesMenu(Group, Unit)
if not Group.CTLDTopmenu then return end if not Group.CTLDTopmenu then return end
local topCrates = Group.MyTopCratesMenu local topCrates = Group.MyTopCratesMenu
if not topCrates then return end if not topCrates then return end
@@ -4724,7 +5016,15 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit)
return return
end end
----------------------------------------------------------------------
-- DEFAULT (“classic”) versus ONE-STEP behaviour
----------------------------------------------------------------------
if not self.onestepmenu then
--------------------------------------------------------------------
-- classic menu
--------------------------------------------------------------------
MENU_GROUP_COMMAND:New(Group,"Drop ALL crates",dropCratesMenu,self._UnloadCrates,self,Group,Unit) MENU_GROUP_COMMAND:New(Group,"Drop ALL crates",dropCratesMenu,self._UnloadCrates,self,Group,Unit)
self.CrateGroupList=self.CrateGroupList or{} self.CrateGroupList=self.CrateGroupList or{}
self.CrateGroupList[Unit:GetName()]={} self.CrateGroupList[Unit:GetName()]={}
@@ -4759,6 +5059,56 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit)
lineIndex=lineIndex+1 lineIndex=lineIndex+1
end end
end end
else
--------------------------------------------------------------------
-- one-step (enhanced) menu
--------------------------------------------------------------------
local mAll=MENU_GROUP:New(Group,"Drop ALL crates",dropCratesMenu)
MENU_GROUP_COMMAND:New(Group,"Drop",mAll,self._UnloadCrates,self,Group,Unit)
if not ( self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) ) then
MENU_GROUP_COMMAND:New(Group,"Drop and build",mAll,self._DropAndBuild,self,Group,Unit)
end
self.CrateGroupList=self.CrateGroupList or{}
self.CrateGroupList[Unit:GetName()]={}
local lineIndex=1
for cName,list in pairs(cargoByName) do
local needed=list[1]:GetCratesNeeded() or 1
table.sort(list,function(a,b)return a:GetID()<b:GetID()end)
local i=1
while i<=#list do
local left=(#list-i+1)
if left>=needed then
local chunk={}
for n=i,i+needed-1 do
table.insert(chunk,list[n])
end
local label=string.format("%d. %s",lineIndex,cName)
table.insert(self.CrateGroupList[Unit:GetName()],chunk)
local setIndex=#self.CrateGroupList[Unit:GetName()]
local mSet=MENU_GROUP:New(Group,label,dropCratesMenu)
MENU_GROUP_COMMAND:New(Group,"Drop",mSet,self._UnloadSingleCrateSet,self,Group,Unit,setIndex)
if not ( self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) ) then
MENU_GROUP_COMMAND:New(Group,"Drop and build",mSet,self._DropSingleAndBuild,self,Group,Unit,setIndex)
end
i=i+needed
else
local chunk={}
for n=i,#list do
table.insert(chunk,list[n])
end
local label=string.format("%d. %s %d/%d",lineIndex,cName,left,needed)
table.insert(self.CrateGroupList[Unit:GetName()],chunk)
local setIndex=#self.CrateGroupList[Unit:GetName()]
MENU_GROUP_COMMAND:New(Group,label,dropCratesMenu,self._UnloadSingleCrateSet,self,Group,Unit,setIndex)
i=#list+1
end
lineIndex=lineIndex+1
end
end
end
end end
--- (Internal) Function to unload a single Troop group by ID. --- (Internal) Function to unload a single Troop group by ID.
@@ -4808,7 +5158,7 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
return self return self
end end
-- Drop ONLY the FIRST cargo in that chunk -- Drop the FIRST cargo in that chunk
local foundCargo = chunk[1] local foundCargo = chunk[1]
if not foundCargo then if not foundCargo then
self:_SendMessage(string.format("No troop cargo at chunk %d!", chunkID), 10, false, Group) self:_SendMessage(string.format("No troop cargo at chunk %d!", chunkID), 10, false, Group)
@@ -4869,6 +5219,8 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
foundCargo:SetWasDropped(true) foundCargo:SetWasDropped(true)
if cType == CTLD_CARGO.Enum.ENGINEERS then if cType == CTLD_CARGO.Enum.ENGINEERS then
self.Engineers = self.Engineers + 1 self.Engineers = self.Engineers + 1
local grpname = self.DroppedTroops[self.TroopCounter]:GetName()
self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname)
self:_SendMessage(string.format("Dropped Engineers %s into action!", name), 10, false, Group) self:_SendMessage(string.format("Dropped Engineers %s into action!", name), 10, false, Group)
else else
self:_SendMessage(string.format("Dropped Troops %s into action!", name), 10, false, Group) self:_SendMessage(string.format("Dropped Troops %s into action!", name), 10, false, Group)
@@ -5191,6 +5543,8 @@ function CTLD:ActivateZone(Name,ZoneType,NewState)
table = self.dropOffZones table = self.dropOffZones
elseif ZoneType == CTLD.CargoZoneType.SHIP then elseif ZoneType == CTLD.CargoZoneType.SHIP then
table = self.shipZones table = self.shipZones
elseif ZoneType == CTLD.CargoZoneType.BEACON then
table = self.droppedBeacons
else else
table = self.wpZones table = self.wpZones
end end
@@ -5604,6 +5958,7 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
if Zonetype == CTLD.CargoZoneType.SHIP then if Zonetype == CTLD.CargoZoneType.SHIP then
self:T("Checking Type Ship: "..zonename) self:T("Checking Type Ship: "..zonename)
local ZoneUNIT = UNIT:FindByName(zonename) local ZoneUNIT = UNIT:FindByName(zonename)
if not ZoneUNIT then return false end
zonecoord = ZoneUNIT:GetCoordinate() zonecoord = ZoneUNIT:GetCoordinate()
zoneradius = czone.shiplength zoneradius = czone.shiplength
zonewidth = czone.shipwidth zonewidth = czone.shipwidth
@@ -5623,7 +5978,8 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
end end
local distance = self:_GetDistance(zonecoord,unitcoord) local distance = self:_GetDistance(zonecoord,unitcoord)
self:T("Distance Zone: "..distance) self:T("Distance Zone: "..distance)
if (zone:IsVec2InZone(unitVec2) or Zonetype == CTLD.CargoZoneType.MOVE) and active == true and maxdist > distance then self:T("Zone Active: "..tostring(active))
if (zone:IsVec2InZone(unitVec2) or Zonetype == CTLD.CargoZoneType.MOVE) and active == true and distance < maxdist then
outcome = true outcome = true
maxdist = distance maxdist = distance
zoneret = zone zoneret = zone
@@ -5680,16 +6036,23 @@ function CTLD:SmokeZoneNearBy(Unit, Flare)
for index,cargozone in pairs(zones[i]) do for index,cargozone in pairs(zones[i]) do
local CZone = cargozone --#CTLD.CargoZone local CZone = cargozone --#CTLD.CargoZone
local zonename = CZone.name local zonename = CZone.name
local zone = nil local zone = nil -- Core.Zone#ZONE_RADIUS
local airbasezone = false
if i == 4 then if i == 4 then
zone = UNIT:FindByName(zonename) zone = UNIT:FindByName(zonename)
else else
zone = ZONE:FindByName(zonename) zone = ZONE:FindByName(zonename)
if not zone then if not zone then
zone = AIRBASE:FindByName(zonename):GetZone() zone = AIRBASE:FindByName(zonename):GetZone()
airbasezone = true
end end
end end
local zonecoord = zone:GetCoordinate() local zonecoord = zone:GetCoordinate()
-- Avoid smoke/flares on runways
if (i==1 or 1==3) and airbasezone==true and zone:IsInstanceOf("ZONE_BASE") then
zonecoord = zone:GetRandomCoordinate(inner,outer,{land.SurfaceType.LAND})
end
if zonecoord then
local active = CZone.active local active = CZone.active
local color = CZone.color local color = CZone.color
local distance = self:_GetDistance(zonecoord,unitcoord) local distance = self:_GetDistance(zonecoord,unitcoord)
@@ -5708,6 +6071,7 @@ function CTLD:SmokeZoneNearBy(Unit, Flare)
end end
end end
end end
end
if not smoked then if not smoked then
local distance = UTILS.MetersToNM(self.smokedistance) local distance = UTILS.MetersToNM(self.smokedistance)
self:_SendMessage(string.format("Negative, need to be closer than %dnm to a zone!",distance), 10, false, Group) self:_SendMessage(string.format("Negative, need to be closer than %dnm to a zone!",distance), 10, false, Group)
@@ -5730,9 +6094,8 @@ end
local unit = nil local unit = nil
if type(Unittype) == "string" then if type(Unittype) == "string" then
unittype = Unittype unittype = Unittype
elseif type(Unittype) == "table" then elseif type(Unittype) == "table" and Unittype.ClassName and Unittype:IsInstanceOf("UNIT") then
unit = UNIT:FindByName(Unittype) -- Wrapper.Unit#UNIT unittype = Unittype:GetTypeName()
unittype = unit:GetTypeName()
else else
return self return self
end end
@@ -6788,6 +7151,16 @@ end
local filepath = self.filepath local filepath = self.filepath
self:__Save(interval,filepath,filename) self:__Save(interval,filepath,filename)
end end
if type(self.VehicleMoveFormation) == "table" then
local Formations = {}
for _,_formation in pairs(self.VehicleMoveFormation) do
table.insert(Formations,_formation)
end
self.VehicleMoveFormation = nil
self.VehicleMoveFormation = Formations
end
return self return self
end end
@@ -6925,7 +7298,8 @@ end
-- right subtype? -- right subtype?
if Event == subtype and not task:IsDone() then if Event == subtype and not task:IsDone() then
local targetzone = task.Target:GetObject() -- Core.Zone#ZONE should be a zone in this case .... local targetzone = task.Target:GetObject() -- Core.Zone#ZONE should be a zone in this case ....
--self:T2({Name=Groupname,Property=task:GetProperty("ExtractName")}) self:T2({Name=Groupname,Property=task:GetProperty("ExtractName")})
if task:GetProperty("ExtractName") then
local okaygroup = string.find(Groupname,task:GetProperty("ExtractName"),1,true) local okaygroup = string.find(Groupname,task:GetProperty("ExtractName"),1,true)
if targetzone and targetzone.ClassName and string.match(targetzone.ClassName,"ZONE") and okaygroup then if targetzone and targetzone.ClassName and string.match(targetzone.ClassName,"ZONE") and okaygroup then
if task.Clients:HasUniqueID(playername) then if task.Clients:HasUniqueID(playername) then
@@ -6933,6 +7307,9 @@ end
task:__Success(-1) task:__Success(-1)
end end
end end
else
self:T({Text="'ExtractName' Property not set",Name=Groupname,Property=task.Type})
end
end end
end end
) )
@@ -7699,7 +8076,7 @@ end
--- [Internal] Function to spawn a soldier group of 10 units --- [Internal] Function to spawn a soldier group of 10 units
-- @param #CTLD_HERCULES self -- @param #CTLD_HERCULES self
-- @param Wrapper.Group#GROUP Cargo_Drop_initiator -- @param Wrapper.Group#GROUP Cargo_Drop_initiator
-- @param Core.Point#POINT_VEC3 Cargo_Drop_Position -- @param Core.Point#COORDINATE Cargo_Drop_Position
-- @param #string Cargo_Type_name -- @param #string Cargo_Type_name
-- @param #number CargoHeading -- @param #number CargoHeading
-- @param #number Cargo_Country -- @param #number Cargo_Country
@@ -7722,7 +8099,7 @@ end
--- [Internal] Function to spawn a group --- [Internal] Function to spawn a group
-- @param #CTLD_HERCULES self -- @param #CTLD_HERCULES self
-- @param Wrapper.Group#GROUP Cargo_Drop_initiator -- @param Wrapper.Group#GROUP Cargo_Drop_initiator
-- @param Core.Point#POINT_VEC3 Cargo_Drop_Position -- @param Core.Point#COORDINATE Cargo_Drop_Position
-- @param #string Cargo_Type_name -- @param #string Cargo_Type_name
-- @param #number CargoHeading -- @param #number CargoHeading
-- @param #number Cargo_Country -- @param #number Cargo_Country
@@ -7746,7 +8123,7 @@ end
--- [Internal] Function to spawn static cargo --- [Internal] Function to spawn static cargo
-- @param #CTLD_HERCULES self -- @param #CTLD_HERCULES self
-- @param Wrapper.Group#GROUP Cargo_Drop_initiator -- @param Wrapper.Group#GROUP Cargo_Drop_initiator
-- @param Core.Point#POINT_VEC3 Cargo_Drop_Position -- @param Core.Point#COORDINATE Cargo_Drop_Position
-- @param #string Cargo_Type_name -- @param #string Cargo_Type_name
-- @param #number CargoHeading -- @param #number CargoHeading
-- @param #boolean dead -- @param #boolean dead
@@ -7768,7 +8145,7 @@ end
--- [Internal] Function to spawn cargo by type at position --- [Internal] Function to spawn cargo by type at position
-- @param #CTLD_HERCULES self -- @param #CTLD_HERCULES self
-- @param #string Cargo_Type_name -- @param #string Cargo_Type_name
-- @param Core.Point#POINT_VEC3 Cargo_Drop_Position -- @param Core.Point#COORDINATE Cargo_Drop_Position
-- @return #CTLD_HERCULES self -- @return #CTLD_HERCULES self
function CTLD_HERCULES:Cargo_SpawnDroppedAsCargo(_name, _pos) function CTLD_HERCULES:Cargo_SpawnDroppedAsCargo(_name, _pos)
local theCargo = self.CTLD:_FindCratesCargoObject(_name) -- #CTLD_CARGO local theCargo = self.CTLD:_FindCratesCargoObject(_name) -- #CTLD_CARGO

View File

@@ -136,6 +136,7 @@ COMMANDER = {
awacsZones = {}, awacsZones = {},
tankerZones = {}, tankerZones = {},
limitMission = {}, limitMission = {},
maxMissionsAssignPerCycle = 1,
} }
--- COMMANDER class version. --- COMMANDER class version.
@@ -1535,6 +1536,8 @@ function COMMANDER:CheckMissionQueue()
end end
end end
local missionsAssigned = 0
-- Loop over missions in queue. -- Loop over missions in queue.
for _,_mission in pairs(self.missionqueue) do for _,_mission in pairs(self.missionqueue) do
local mission=_mission --Ops.Auftrag#AUFTRAG local mission=_mission --Ops.Auftrag#AUFTRAG
@@ -1595,10 +1598,13 @@ function COMMANDER:CheckMissionQueue()
LEGION.UnRecruitAssets(assets, mission) LEGION.UnRecruitAssets(assets, mission)
end end
-- Only ONE mission is assigned. missionsAssigned = missionsAssigned + 1
if missionsAssigned >= (self.maxMissionsAssignPerCycle or 1) then
return return
end end
end
else else
--- ---
@@ -1611,6 +1617,16 @@ function COMMANDER:CheckMissionQueue()
end end
--- Set how many missions can be assigned in a single status iteration. (eg. This is useful for persistent missions where you need to load all AUFTRAGs on mission start and then change it back to default)
--- Warning: Increasing this value will increase the number of missions started per iteration and thus may lead to performance issues if too many missions are started at once.
-- @param #COMMANDER self
-- @param #number Number of missions assigned per status iteration. Default is 1.
-- @return #COMMANDER self.
function COMMANDER:SetMaxMissionsAssignPerCycle(MaxMissionsAssignPerCycle)
self.maxMissionsAssignPerCycle = MaxMissionsAssignPerCycle or 1
return self
end
--- Get cohorts. --- Get cohorts.
-- @param #COMMANDER self -- @param #COMMANDER self
-- @param #table Legions Special legions. -- @param #table Legions Special legions.
@@ -1671,7 +1687,10 @@ function COMMANDER:_GetCohorts(Legions, Cohorts, Operation)
local legion=_legion --Ops.Legion#LEGION local legion=_legion --Ops.Legion#LEGION
-- Check that runway is operational. -- Check that runway is operational.
local Runway=legion:IsAirwing() and legion:IsRunwayOperational() or true local Runway=true
if legion:IsAirwing() then
Runway=legion:IsRunwayOperational() and legion.airbase and legion.airbase:GetCoalition() == legion:GetCoalition()
end
-- Legion has to be running. -- Legion has to be running.
if legion:IsRunning() and Runway then if legion:IsRunning() and Runway then
@@ -1704,7 +1723,10 @@ function COMMANDER:_GetCohorts(Legions, Cohorts, Operation)
local legion=_legion --Ops.Legion#LEGION local legion=_legion --Ops.Legion#LEGION
-- Check that runway is operational. -- Check that runway is operational.
local Runway=legion:IsAirwing() and legion:IsRunwayOperational() or true local Runway=true
if legion:IsAirwing() then
Runway=legion:IsRunwayOperational() and legion.airbase and legion.airbase:GetCoalition() == legion:GetCoalition()
end
-- Legion has to be running. -- Legion has to be running.
if legion:IsRunning() and Runway then if legion:IsRunning() and Runway then

View File

@@ -1,13 +1,18 @@
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- Easy CAP/GCI Class, based on OPS classes -- Easy CAP/GCI Class, based on OPS classes
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- Documentation --
-- ## Documentation:
-- --
-- https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Ops.EasyGCICAP.html -- https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Ops.EasyGCICAP.html
-- --
-- ## Example Missions:
--
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/EasyGCICAP).
--
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- Date: September 2023 -- Date: September 2023
-- Last Update: July 2024 -- Last Update: Aug 2025
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- --
--- **Ops** - Easy GCI & CAP Manager --- **Ops** - Easy GCI & CAP Manager
@@ -62,6 +67,7 @@
-- @field #number repeatsonfailure -- @field #number repeatsonfailure
-- @field Core.Set#SET_ZONE GoZoneSet -- @field Core.Set#SET_ZONE GoZoneSet
-- @field Core.Set#SET_ZONE NoGoZoneSet -- @field Core.Set#SET_ZONE NoGoZoneSet
-- @field Core.Set#SET_ZONE ConflictZoneSet
-- @field #boolean Monitor -- @field #boolean Monitor
-- @field #boolean TankerInvisible -- @field #boolean TankerInvisible
-- @field #number CapFormation -- @field #number CapFormation
@@ -69,6 +75,10 @@
-- @field #boolean DespawnAfterLanding -- @field #boolean DespawnAfterLanding
-- @field #boolean DespawnAfterHolding -- @field #boolean DespawnAfterHolding
-- @field #list<Ops.Auftrag#AUFTRAG> ListOfAuftrag -- @field #list<Ops.Auftrag#AUFTRAG> ListOfAuftrag
-- @field #string defaulttakeofftype Take off type
-- @field #number FuelLowThreshold
-- @field #number FuelCriticalThreshold
-- @field #boolean showpatrolpointmarks
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown. --- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown.
@@ -102,6 +112,11 @@
-- Next put a late activated template group for your CAP/GCI Squadron on the map. Last, put a zone on the map for the CAP operations, let's name it "Blue Zone 1". Size of the zone plays no role. -- Next put a late activated template group for your CAP/GCI Squadron on the map. Last, put a zone on the map for the CAP operations, let's name it "Blue Zone 1". Size of the zone plays no role.
-- Put an EW radar system on the map and name it aptly, like "Blue EWR". -- Put an EW radar system on the map and name it aptly, like "Blue EWR".
-- --
-- ### Zones
--
-- For our example, you create a RED and a BLUE border, as a closed polygonal zone representing the borderlines. You can also have conflict zone, where - for our example - BLUE will attack
-- RED planes, despite being on RED territory. Think of a no-fly zone or an limited area of engagement. Conflict zones take precedence over borders, i.e. they can overlap all borders.
--
-- ### Code it -- ### Code it
-- --
-- -- Set up a basic system for the blue side, we'll reside on Kutaisi, and use GROUP objects with "Blue EWR" in the name as EW Radar Systems. -- -- Set up a basic system for the blue side, we'll reside on Kutaisi, and use GROUP objects with "Blue EWR" in the name as EW Radar Systems.
@@ -114,10 +129,10 @@
-- mywing:AddSquadron("Blue Sq1 M2000c","CAP Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.GOOD,102,"ec1.5_Vendee_Jeanne_clean") -- mywing:AddSquadron("Blue Sq1 M2000c","CAP Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.GOOD,102,"ec1.5_Vendee_Jeanne_clean")
-- --
-- -- Add a couple of zones -- -- Add a couple of zones
-- -- We'll defend our border -- -- We'll defend our own border
-- mywing:AddAcceptZone(ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) )) -- mywing:AddAcceptZone(ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) ))
-- -- We'll attack intruders also here -- -- We'll attack intruders also here - conflictzones can overlap borders(!) - limited zone of engagement
-- mywing:AddAcceptZone(ZONE_POLYGON:New("Red Defense Zone", GROUP:FindByName( "Red Defense Zone" ))) -- mywing:AddConflictZone(ZONE_POLYGON:New("Red Defense Zone", GROUP:FindByName( "Red Defense Zone" )))
-- -- We'll leave the reds alone on their turf -- -- We'll leave the reds alone on their turf
-- mywing:AddRejectZone(ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) )) -- mywing:AddRejectZone(ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) ))
-- --
@@ -125,10 +140,10 @@
-- -- Set up borders on map -- -- Set up borders on map
-- local BlueBorder = ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) ) -- local BlueBorder = ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) )
-- BlueBorder:DrawZone(-1,{0,0,1},1,FillColor,FillAlpha,1,true) -- BlueBorder:DrawZone(-1,{0,0,1},1,FillColor,FillAlpha,1,true)
-- local BlueNoGoZone = ZONE_POLYGON:New("Red Defense Zone", GROUP:FindByName( "Red Defense Zone" )) -- local ConflictZone = ZONE_POLYGON:New("Red Defense Zone", GROUP:FindByName( "Red Defense Zone" ))
-- BlueNoGoZone:DrawZone(-1,{1,1,0},1,FillColor,FillAlpha,2,true) -- ConflictZone:DrawZone(-1,{1,1,0},1,FillColor,FillAlpha,2,true)
-- local BlueNoGoZone2 = ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) ) -- local BlueNoGoZone = ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) )
-- BlueNoGoZone2:DrawZone(-1,{1,0,0},1,FillColor,FillAlpha,4,true) -- BlueNoGoZone:DrawZone(-1,{1,0,0},1,FillColor,FillAlpha,4,true)
-- --
-- ### Add a second airwing with squads and own CAP point (optional) -- ### Add a second airwing with squads and own CAP point (optional)
-- --
@@ -210,13 +225,18 @@ EASYGCICAP = {
repeatsonfailure = 3, repeatsonfailure = 3,
GoZoneSet = nil, GoZoneSet = nil,
NoGoZoneSet = nil, NoGoZoneSet = nil,
ConflictZoneSet = nil,
Monitor = false, Monitor = false,
TankerInvisible = true, TankerInvisible = true,
CapFormation = nil, CapFormation = nil,
ReadyFlightGroups = {}, ReadyFlightGroups = {},
DespawnAfterLanding = false, DespawnAfterLanding = false,
DespawnAfterHolding = true, DespawnAfterHolding = true,
ListOfAuftrag = {} ListOfAuftrag = {},
defaulttakeofftype = "hot",
FuelLowThreshold = 25,
FuelCriticalThreshold = 10,
showpatrolpointmarks = false,
} }
--- Internal Squadron data type --- Internal Squadron data type
@@ -249,10 +269,11 @@ EASYGCICAP = {
-- @field #number Speed -- @field #number Speed
-- @field #number Heading -- @field #number Heading
-- @field #number LegLength -- @field #number LegLength
-- @field Core.Zone#ZONE_BASE Zone
--- EASYGCICAP class version. --- EASYGCICAP class version.
-- @field #string version -- @field #string version
EASYGCICAP.version="0.1.17" EASYGCICAP.version="0.1.27"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@@ -287,6 +308,7 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
self.airbase = AIRBASE:FindByName(self.airbasename) self.airbase = AIRBASE:FindByName(self.airbasename)
self.GoZoneSet = SET_ZONE:New() self.GoZoneSet = SET_ZONE:New()
self.NoGoZoneSet = SET_ZONE:New() self.NoGoZoneSet = SET_ZONE:New()
self.ConflictZoneSet = SET_ZONE:New()
self.resurrection = 900 self.resurrection = 900
self.capspeed = 300 self.capspeed = 300
self.capalt = 25000 self.capalt = 25000
@@ -304,6 +326,10 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
self.DespawnAfterLanding = false self.DespawnAfterLanding = false
self.DespawnAfterHolding = true self.DespawnAfterHolding = true
self.ListOfAuftrag = {} self.ListOfAuftrag = {}
self.defaulttakeofftype = "hot"
self.FuelLowThreshold = 25
self.FuelCriticalThreshold = 10
self.showpatrolpointmarks = false
-- Set some string id for output to DCS.log file. -- Set some string id for output to DCS.log file.
self.lid=string.format("EASYGCICAP %s | ", self.alias) self.lid=string.format("EASYGCICAP %s | ", self.alias)
@@ -328,6 +354,63 @@ end
-- Functions -- Functions
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- Get a specific managed AirWing by name
-- @param #EASYGCICAP self
-- @param #string AirbaseName Airbase name of the home of this wing.
-- @return Ops.AirWing#AIRWING Airwing or nil if not found
function EASYGCICAP:GetAirwing(AirbaseName)
self:T(self.lid.."GetAirwing")
if self.wings[AirbaseName] then
return self.wings[AirbaseName][1]
end
return nil
end
--- Get a table of all managed AirWings
-- @param #EASYGCICAP self
-- @return #table Table of Ops.AirWing#AIRWING Airwings
function EASYGCICAP:GetAirwingTable()
self:T(self.lid.."GetAirwingTable")
local Wingtable = {}
for _,_object in pairs(self.wings or {}) do
table.insert(Wingtable,_object[1])
end
return Wingtable
end
--- Set "fuel low" threshold for CAP and INTERCEPT flights.
-- @param #EASYGCICAP self
-- @param #number Percent RTB if fuel at this percent. Values: 1..100, defaults to 25.
-- @return #EASYGCICAP self
function EASYGCICAP:SetFuelLow(Percent)
self:T(self.lid.."SetFuelLow")
self.FuelLowThreshold = Percent or 25
return self
end
--- Set markers on the map for Patrol Points.
-- @param #EASYGCICAP self
-- @param #boolean onoff Set to true to switch markers on.
-- @return #EASYGCICAP self
function EASYGCICAP:ShowPatrolPointMarkers(onoff)
if onoff then
self.showpatrolpointmarks = true
else
self.showpatrolpointmarks = false
end
return self
end
--- Set "fuel critical" threshold for CAP and INTERCEPT flights.
-- @param #EASYGCICAP self
-- @param #number Percent RTB if fuel at this percent. Values: 1..100, defaults to 10.
-- @return #EASYGCICAP self
function EASYGCICAP:SetFuelCritical(Percent)
self:T(self.lid.."SetFuelCritical")
self.FuelCriticalThreshold = Percent or 10
return self
end
--- Set CAP formation. --- Set CAP formation.
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @param #number Formation Formation to fly, defaults to ENUMS.Formation.FixedWing.FingerFour.Group -- @param #number Formation Formation to fly, defaults to ENUMS.Formation.FixedWing.FingerFour.Group
@@ -348,7 +431,7 @@ function EASYGCICAP:SetTankerAndAWACSInvisible(Switch)
return self return self
end end
--- Count alive missions in our internal stack. --- (internal) Count alive missions in our internal stack.
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @return #number count -- @return #number count
function EASYGCICAP:_CountAliveAuftrags() function EASYGCICAP:_CountAliveAuftrags()
@@ -392,6 +475,16 @@ function EASYGCICAP:SetDefaultRepeatOnFailure(Retries)
return self return self
end end
--- Add default take off type for the airwings.
-- @param #EASYGCICAP self
-- @param #string Takeoff Can be "hot", "cold", or "air" - default is "hot".
-- @return #EASYGCICAP self
function EASYGCICAP:SetDefaultTakeOffType(Takeoff)
self:T(self.lid.."SetDefaultTakeOffType")
self.defaulttakeofftype = Takeoff or "hot"
return self
end
--- Set default CAP Speed in knots --- Set default CAP Speed in knots
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @param #number Speed Speed defaults to 300 -- @param #number Speed Speed defaults to 300
@@ -561,6 +654,13 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
local DespawnAfterLanding = self.DespawnAfterLanding local DespawnAfterLanding = self.DespawnAfterLanding
local DespawnAfterHolding = self.DespawnAfterHolding local DespawnAfterHolding = self.DespawnAfterHolding
-- Check STATIC name
local check = STATIC:FindByName(Airbasename,false) or UNIT:FindByName(Airbasename)
if check == nil then
MESSAGE:New(self.lid.."There's no warehouse static on the map (wrong naming?) for airbase "..tostring(Airbasename).."!",30,"CHECK"):ToAllIf(self.debug):ToLog()
return
end
-- Create Airwing -- Create Airwing
local CAP_Wing = AIRWING:New(Airbasename,Alias) local CAP_Wing = AIRWING:New(Airbasename,Alias)
CAP_Wing:SetVerbosityLevel(0) CAP_Wing:SetVerbosityLevel(0)
@@ -571,6 +671,10 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
CAP_Wing:SetNumberCAP(self.capgrouping) CAP_Wing:SetNumberCAP(self.capgrouping)
CAP_Wing:SetCapCloseRaceTrack(true) CAP_Wing:SetCapCloseRaceTrack(true)
if self.showpatrolpointmarks then
CAP_Wing:ShowPatrolPointMarkers(true)
end
if self.capOptionVaryStartTime then if self.capOptionVaryStartTime then
CAP_Wing:SetCapStartTimeVariation(self.capOptionVaryStartTime,self.capOptionVaryEndTime) CAP_Wing:SetCapStartTimeVariation(self.capOptionVaryStartTime,self.capOptionVaryEndTime)
end end
@@ -588,9 +692,8 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
if #self.ManagedREC > 0 then if #self.ManagedREC > 0 then
CAP_Wing:SetNumberRecon(1) CAP_Wing:SetNumberRecon(1)
end end
--local PatrolCoordinateKutaisi = ZONE:New(CapZoneName):GetCoordinate()
--CAP_Wing:AddPatrolPointCAP(PatrolCoordinateKutaisi,self.capalt,UTILS.KnotsToAltKIAS(self.capspeed,self.capalt),self.capdir,self.capleg) CAP_Wing:SetTakeoffType(self.defaulttakeofftype)
CAP_Wing:SetTakeoffHot()
CAP_Wing:SetLowFuelThreshold(0.3) CAP_Wing:SetLowFuelThreshold(0.3)
CAP_Wing.RandomAssetScore = math.random(50,100) CAP_Wing.RandomAssetScore = math.random(50,100)
CAP_Wing:Start() CAP_Wing:Start()
@@ -598,6 +701,11 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
local Intel = self.Intel local Intel = self.Intel
local TankerInvisible = self.TankerInvisible local TankerInvisible = self.TankerInvisible
local engagerange = self.engagerange
local GoZoneSet = self.GoZoneSet
local NoGoZoneSet = self.NoGoZoneSet
local FuelLow = self.FuelLowThreshold or 25
local FuelCritical = self.FuelCriticalThreshold or 10
function CAP_Wing:onbeforeFlightOnMission(From, Event, To, Flightgroup, Mission) function CAP_Wing:onbeforeFlightOnMission(From, Event, To, Flightgroup, Mission)
local flightgroup = Flightgroup -- Ops.FlightGroup#FLIGHTGROUP local flightgroup = Flightgroup -- Ops.FlightGroup#FLIGHTGROUP
@@ -609,10 +717,15 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
flightgroup:SetDestinationbase(AIRBASE:FindByName(Airbasename)) flightgroup:SetDestinationbase(AIRBASE:FindByName(Airbasename))
flightgroup:GetGroup():CommandEPLRS(true,5) flightgroup:GetGroup():CommandEPLRS(true,5)
flightgroup:GetGroup():SetOptionRadarUsingForContinousSearch() flightgroup:GetGroup():SetOptionRadarUsingForContinousSearch()
flightgroup:GetGroup():SetOptionLandingOverheadBreak()
if Mission.type ~= AUFTRAG.Type.TANKER and Mission.type ~= AUFTRAG.Type.AWACS and Mission.type ~= AUFTRAG.Type.RECON then if Mission.type ~= AUFTRAG.Type.TANKER and Mission.type ~= AUFTRAG.Type.AWACS and Mission.type ~= AUFTRAG.Type.RECON then
flightgroup:SetDetection(true) flightgroup:SetDetection(true)
flightgroup:SetEngageDetectedOn(self.engagerange,{"Air"},self.GoZoneSet,self.NoGoZoneSet) flightgroup:SetEngageDetectedOn(engagerange,{"Air"},GoZoneSet,NoGoZoneSet)
flightgroup:SetOutOfAAMRTB() flightgroup:SetOutOfAAMRTB()
flightgroup:SetFuelLowRTB(true)
flightgroup:SetFuelLowThreshold(FuelLow)
flightgroup:SetFuelCriticalRTB(true)
flightgroup:SetFuelCriticalThreshold(FuelCritical)
if CapFormation then if CapFormation then
flightgroup:GetGroup():SetOption(AI.Option.Air.id.FORMATION,CapFormation) flightgroup:GetGroup():SetOption(AI.Option.Air.id.FORMATION,CapFormation)
end end
@@ -651,24 +764,30 @@ end
--- Add a CAP patrol point to a Wing --- Add a CAP patrol point to a Wing
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @param #string AirbaseName Name of the Wing's airbase -- @param #string AirbaseName Name of the Wing's airbase
-- @param Core.Point#COORDINATE Coordinate. -- @param Core.Point#COORDINATE Coordinate. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Defaults to 25000 feet ASL. -- @param #number Altitude Defaults to 25000 feet ASL.
-- @param #number Speed Defaults to 300 knots TAS. -- @param #number Speed Defaults to 300 knots TAS.
-- @param #number Heading Defaults to 90 degrees (East). -- @param #number Heading Defaults to 90 degrees (East).
-- @param #number LegLength Defaults to 15 NM. -- @param #number LegLength Defaults to 15 NM.
-- @return #EASYGCICAP self -- @return #EASYGCICAP self
function EASYGCICAP:AddPatrolPointCAP(AirbaseName,Coordinate,Altitude,Speed,Heading,LegLength) function EASYGCICAP:AddPatrolPointCAP(AirbaseName,Coordinate,Altitude,Speed,Heading,LegLength)
self:T(self.lid.."AddPatrolPointCAP "..Coordinate:ToStringLLDDM()) self:T(self.lid.."AddPatrolPointCAP")--..Coordinate:ToStringLLDDM())
local coordinate = Coordinate
local EntryCAP = {} -- #EASYGCICAP.CapPoint local EntryCAP = {} -- #EASYGCICAP.CapPoint
if Coordinate:IsInstanceOf("ZONE_BASE") then
-- adjust coordinate and get the coordinate from the zone
coordinate = Coordinate:GetCoordinate()
EntryCAP.Zone = Coordinate
end
EntryCAP.AirbaseName = AirbaseName EntryCAP.AirbaseName = AirbaseName
EntryCAP.Coordinate = Coordinate EntryCAP.Coordinate = coordinate
EntryCAP.Altitude = Altitude or 25000 EntryCAP.Altitude = Altitude or 25000
EntryCAP.Speed = Speed or 300 EntryCAP.Speed = Speed or 300
EntryCAP.Heading = Heading or 90 EntryCAP.Heading = Heading or 90
EntryCAP.LegLength = LegLength or 15 EntryCAP.LegLength = LegLength or 15
self.ManagedCP[#self.ManagedCP+1] = EntryCAP self.ManagedCP[#self.ManagedCP+1] = EntryCAP
if self.debug then if self.debug then
local mark = MARKER:New(Coordinate,self.lid.."Patrol Point"):ToAll() local mark = MARKER:New(coordinate,self.lid.."Patrol Point"):ToAll()
end end
return self return self
end end
@@ -676,7 +795,7 @@ end
--- Add a RECON patrol point to a Wing --- Add a RECON patrol point to a Wing
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @param #string AirbaseName Name of the Wing's airbase -- @param #string AirbaseName Name of the Wing's airbase
-- @param Core.Point#COORDINATE Coordinate. -- @param Core.Point#COORDINATE Coordinate. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Defaults to 25000 feet. -- @param #number Altitude Defaults to 25000 feet.
-- @param #number Speed Defaults to 300 knots. -- @param #number Speed Defaults to 300 knots.
-- @param #number Heading Defaults to 90 degrees (East). -- @param #number Heading Defaults to 90 degrees (East).
@@ -701,7 +820,7 @@ end
--- Add a TANKER patrol point to a Wing --- Add a TANKER patrol point to a Wing
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @param #string AirbaseName Name of the Wing's airbase -- @param #string AirbaseName Name of the Wing's airbase
-- @param Core.Point#COORDINATE Coordinate. -- @param Core.Point#COORDINATE Coordinate. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Defaults to 25000 feet. -- @param #number Altitude Defaults to 25000 feet.
-- @param #number Speed Defaults to 300 knots. -- @param #number Speed Defaults to 300 knots.
-- @param #number Heading Defaults to 90 degrees (East). -- @param #number Heading Defaults to 90 degrees (East).
@@ -726,7 +845,7 @@ end
--- Add an AWACS patrol point to a Wing --- Add an AWACS patrol point to a Wing
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @param #string AirbaseName Name of the Wing's airbase -- @param #string AirbaseName Name of the Wing's airbase
-- @param Core.Point#COORDINATE Coordinate. -- @param Core.Point#COORDINATE Coordinate. Can be handed as a Core.Zone#ZONE object (e.g. in case you want the point to align with a moving zone).
-- @param #number Altitude Defaults to 25000 feet. -- @param #number Altitude Defaults to 25000 feet.
-- @param #number Speed Defaults to 300 knots. -- @param #number Speed Defaults to 300 knots.
-- @param #number Heading Defaults to 90 degrees (East). -- @param #number Heading Defaults to 90 degrees (East).
@@ -755,6 +874,11 @@ function EASYGCICAP:_SetTankerPatrolPoints()
self:T(self.lid.."_SetTankerPatrolPoints") self:T(self.lid.."_SetTankerPatrolPoints")
for _,_data in pairs(self.ManagedTK) do for _,_data in pairs(self.ManagedTK) do
local data = _data --#EASYGCICAP.CapPoint local data = _data --#EASYGCICAP.CapPoint
self:T("Airbasename = "..data.AirbaseName)
if not self.wings[data.AirbaseName] then
MESSAGE:New(self.lid.."You are trying to create a TANKER point for which there is no wing! "..tostring(data.AirbaseName),30,"CHECK"):ToAllIf(self.debug):ToLog()
return
end
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
local Coordinate = data.Coordinate local Coordinate = data.Coordinate
local Altitude = data.Altitude local Altitude = data.Altitude
@@ -774,6 +898,11 @@ function EASYGCICAP:_SetAwacsPatrolPoints()
self:T(self.lid.."_SetAwacsPatrolPoints") self:T(self.lid.."_SetAwacsPatrolPoints")
for _,_data in pairs(self.ManagedEWR) do for _,_data in pairs(self.ManagedEWR) do
local data = _data --#EASYGCICAP.CapPoint local data = _data --#EASYGCICAP.CapPoint
self:T("Airbasename = "..data.AirbaseName)
if not self.wings[data.AirbaseName] then
MESSAGE:New(self.lid.."You are trying to create an AWACS point for which there is no wing! "..tostring(data.AirbaseName),30,"CHECK"):ToAllIf(self.debug):ToLog()
return
end
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
local Coordinate = data.Coordinate local Coordinate = data.Coordinate
local Altitude = data.Altitude local Altitude = data.Altitude
@@ -793,14 +922,24 @@ function EASYGCICAP:_SetCAPPatrolPoints()
self:T(self.lid.."_SetCAPPatrolPoints") self:T(self.lid.."_SetCAPPatrolPoints")
for _,_data in pairs(self.ManagedCP) do for _,_data in pairs(self.ManagedCP) do
local data = _data --#EASYGCICAP.CapPoint local data = _data --#EASYGCICAP.CapPoint
self:T("Airbasename = "..data.AirbaseName)
if not self.wings[data.AirbaseName] then
MESSAGE:New(self.lid.."You are trying to create a CAP point for which there is no wing! "..tostring(data.AirbaseName),30,"CHECK"):ToAllIf(self.debug):ToLog()
return
end
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
local Coordinate = data.Coordinate local Coordinate = data.Coordinate
local Altitude = data.Altitude local Altitude = data.Altitude
local Speed = data.Speed local Speed = data.Speed
local Heading = data.Heading local Heading = data.Heading
local LegLength = data.LegLength local LegLength = data.LegLength
local Zone = _data.Zone
if Zone then
Wing:AddPatrolPointCAP(Zone,Altitude,Speed,Heading,LegLength)
else
Wing:AddPatrolPointCAP(Coordinate,Altitude,Speed,Heading,LegLength) Wing:AddPatrolPointCAP(Coordinate,Altitude,Speed,Heading,LegLength)
end end
end
return self return self
end end
@@ -812,6 +951,11 @@ function EASYGCICAP:_SetReconPatrolPoints()
self:T(self.lid.."_SetReconPatrolPoints") self:T(self.lid.."_SetReconPatrolPoints")
for _,_data in pairs(self.ManagedREC) do for _,_data in pairs(self.ManagedREC) do
local data = _data --#EASYGCICAP.CapPoint local data = _data --#EASYGCICAP.CapPoint
self:T("Airbasename = "..data.AirbaseName)
if not self.wings[data.AirbaseName] then
MESSAGE:New(self.lid.."You are trying to create a RECON point for which there is no wing! "..tostring(data.AirbaseName),30,"CHECK"):ToAllIf(self.debug):ToLog()
return
end
local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING local Wing = self.wings[data.AirbaseName][1] -- Ops.Airwing#AIRWING
local Coordinate = data.Coordinate local Coordinate = data.Coordinate
local Altitude = data.Altitude local Altitude = data.Altitude
@@ -1113,7 +1257,7 @@ end
-- @param Core.Zone#ZONE_BASE Zone -- @param Core.Zone#ZONE_BASE Zone
-- @return #EASYGCICAP self -- @return #EASYGCICAP self
function EASYGCICAP:AddAcceptZone(Zone) function EASYGCICAP:AddAcceptZone(Zone)
self:T(self.lid.."AddAcceptZone0") self:T(self.lid.."AddAcceptZone")
self.GoZoneSet:AddZone(Zone) self.GoZoneSet:AddZone(Zone)
return self return self
end end
@@ -1128,6 +1272,18 @@ function EASYGCICAP:AddRejectZone(Zone)
return self return self
end end
--- Add a zone to the conflict zones set.
-- @param #EASYGCICAP self
-- @param Core.Zone#ZONE_BASE Zone
-- @return #EASYGCICAP self
function EASYGCICAP:AddConflictZone(Zone)
self:T(self.lid.."AddConflictZone")
self.ConflictZoneSet:AddZone(Zone)
self.GoZoneSet:AddZone(Zone)
return self
end
--- (Internal) Try to assign the intercept to a FlightGroup already in air and ready. --- (Internal) Try to assign the intercept to a FlightGroup already in air and ready.
-- @param #EASYGCICAP self -- @param #EASYGCICAP self
-- @param #table ReadyFlightGroups ReadyFlightGroups -- @param #table ReadyFlightGroups ReadyFlightGroups
@@ -1137,19 +1293,19 @@ end
-- @return #boolean assigned -- @return #boolean assigned
-- @return #number leftover -- @return #number leftover
function EASYGCICAP:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,Group,WingSize) function EASYGCICAP:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,Group,WingSize)
self:I("_TryAssignIntercept for size "..WingSize or 1) self:T("_TryAssignIntercept for size "..WingSize or 1)
local assigned = false local assigned = false
local wingsize = WingSize or 1 local wingsize = WingSize or 1
local mindist = 0 local mindist = 0
local disttable = {} local disttable = {}
if Group and Group:IsAlive() then if Group and Group:IsAlive() then
local gcoord = Group:GetCoordinate() or COORDINATE:New(0,0,0) local gcoord = Group:GetCoordinate() or COORDINATE:New(0,0,0)
self:I(self.lid..string.format("Assignment for %s",Group:GetName())) self:T(self.lid..string.format("Assignment for %s",Group:GetName()))
for _name,_FG in pairs(ReadyFlightGroups or {}) do for _name,_FG in pairs(ReadyFlightGroups or {}) do
local FG = _FG -- Ops.FlightGroup#FLIGHTGROUP local FG = _FG -- Ops.FlightGroup#FLIGHTGROUP
local fcoord = FG:GetCoordinate() local fcoord = FG:GetCoordinate()
local dist = math.floor(UTILS.Round(fcoord:Get2DDistance(gcoord)/1000,1)) local dist = math.floor(UTILS.Round(fcoord:Get2DDistance(gcoord)/1000,1))
self:I(self.lid..string.format("FG %s Distance %dkm",_name,dist)) self:T(self.lid..string.format("FG %s Distance %dkm",_name,dist))
disttable[#disttable+1] = { FG=FG, dist=dist} disttable[#disttable+1] = { FG=FG, dist=dist}
if dist>mindist then mindist=dist end if dist>mindist then mindist=dist end
end end
@@ -1166,7 +1322,7 @@ function EASYGCICAP:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,Group
local cm = FG:GetMissionCurrent() local cm = FG:GetMissionCurrent()
if cm then cm:Cancel() end if cm then cm:Cancel() end
wingsize = wingsize - 1 wingsize = wingsize - 1
self:I(self.lid..string.format("Assigned to FG %s Distance %dkm",FG:GetName(),_entry.dist)) self:T(self.lid..string.format("Assigned to FG %s Distance %dkm",FG:GetName(),_entry.dist))
if wingsize == 0 then if wingsize == 0 then
assigned = true assigned = true
break break
@@ -1193,6 +1349,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
local ctlpts = self.ManagedCP local ctlpts = self.ManagedCP
local MaxAliveMissions = self.MaxAliveMissions --* self.capgrouping local MaxAliveMissions = self.MaxAliveMissions --* self.capgrouping
local nogozoneset = self.NoGoZoneSet local nogozoneset = self.NoGoZoneSet
local conflictzoneset = self.ConflictZoneSet
local ReadyFlightGroups = self.ReadyFlightGroups local ReadyFlightGroups = self.ReadyFlightGroups
-- Aircraft? -- Aircraft?
@@ -1240,6 +1397,10 @@ function EASYGCICAP:_AssignIntercept(Cluster)
local data = _data -- #EASYGCICAP.CapPoint local data = _data -- #EASYGCICAP.CapPoint
local name = data.AirbaseName local name = data.AirbaseName
local zonecoord = data.Coordinate local zonecoord = data.Coordinate
if data.Zone then
-- refresh coordinate in case we have a (moving) zone
zonecoord = data.Zone:GetCoordinate()
end
local airwing = wings[name][1] local airwing = wings[name][1]
local coa = AIRBASE:FindByName(name):GetCoalition() local coa = AIRBASE:FindByName(name):GetCoalition()
local samecoalitionab = coa == self.coalition and true or false local samecoalitionab = coa == self.coalition and true or false
@@ -1271,18 +1432,22 @@ function EASYGCICAP:_AssignIntercept(Cluster)
if nogozoneset:Count() > 0 then if nogozoneset:Count() > 0 then
InterceptAuftrag:AddConditionSuccess( InterceptAuftrag:AddConditionSuccess(
function(group,zoneset) function(group,zoneset,conflictset)
local success = false local success = false
if group and group:IsAlive() then if group and group:IsAlive() then
local coord = group:GetCoordinate() local coord = group:GetCoordinate()
if coord and zoneset:IsCoordinateInZone(coord) then if coord and zoneset:Count() > 0 and zoneset:IsCoordinateInZone(coord) then
success = true success = true
end end
if coord and conflictset:Count() > 0 and conflictset:IsCoordinateInZone(coord) then
success = false
end
end end
return success return success
end, end,
contact.group, contact.group,
nogozoneset nogozoneset,
conflictzoneset
) )
end end
@@ -1316,6 +1481,7 @@ function EASYGCICAP:_StartIntel()
BlueIntel:SetForgetTime(300) BlueIntel:SetForgetTime(300)
BlueIntel:SetAcceptZones(self.GoZoneSet) BlueIntel:SetAcceptZones(self.GoZoneSet)
BlueIntel:SetRejectZones(self.NoGoZoneSet) BlueIntel:SetRejectZones(self.NoGoZoneSet)
BlueIntel:SetConflictZones(self.ConflictZoneSet)
BlueIntel:SetVerbosity(0) BlueIntel:SetVerbosity(0)
BlueIntel:Start() BlueIntel:Start()
@@ -1336,7 +1502,7 @@ function EASYGCICAP:_StartIntel()
end end
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- FSM Functions -- TODO FSM Functions
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- (Internal) FSM Function onafterStart --- (Internal) FSM Function onafterStart
@@ -1432,7 +1598,7 @@ function EASYGCICAP:onafterStatus(From,Event,To)
local engage = FG:IsEngaging() local engage = FG:IsEngaging()
local hasmissiles = FG:IsOutOfMissiles() == nil and true or false local hasmissiles = FG:IsOutOfMissiles() == nil and true or false
local ready = hasmissiles and FG:IsFuelGood() and FG:IsAirborne() local ready = hasmissiles and FG:IsFuelGood() and FG:IsAirborne()
--self:I(string.format("Flightgroup %s Engaging = %s Ready = %s",tostring(name),tostring(engage),tostring(ready))) --self:T(string.format("Flightgroup %s Engaging = %s Ready = %s",tostring(name),tostring(engage),tostring(ready)))
if ready then if ready then
self.ReadyFlightGroups[name] = FG self.ReadyFlightGroups[name] = FG
end end
@@ -1467,5 +1633,8 @@ end
function EASYGCICAP:onafterStop(From,Event,To) function EASYGCICAP:onafterStop(From,Event,To)
self:T({From,Event,To}) self:T({From,Event,To})
self.Intel:Stop() self.Intel:Stop()
for _,_wing in pairs(self.wings or {}) do
_wing:Stop()
end
return self return self
end end

View File

@@ -2464,7 +2464,7 @@ end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Payer Menu -- Player Menu
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create player menu. --- Create player menu.

View File

@@ -259,7 +259,7 @@ function FLIGHTGROUP:New(group)
local self=BASE:Inherit(self, OPSGROUP:New(group)) -- #FLIGHTGROUP local self=BASE:Inherit(self, OPSGROUP:New(group)) -- #FLIGHTGROUP
-- Set some string id for output to DCS.log file. -- Set some string id for output to DCS.log file.
self.lid=string.format("FLIGHTGROUP %s | ", self.groupname) self.lid=string.format("FLIGHTGROUP %s | ", self.groupname or "N/A")
-- Defaults -- Defaults
self:SetDefaultROE() self:SetDefaultROE()
@@ -779,6 +779,61 @@ function FLIGHTGROUP:SetJettisonWeapons(Switch)
return self return self
end end
--- Set the aircraft to land straight in.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetOptionLandingStraightIn()
self.OptionLandingStraightIn = true
if self:GetGroup():IsAlive() then
self:GetGroup():SetOptionLandingStraightIn()
end
return self
end
--- Set the aircraft to land in pairs.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetOptionLandingForcePair()
self.OptionLandingForcePair = true
if self:GetGroup():IsAlive() then
self:GetGroup():SetOptionLandingForcePair()
end
return self
end
--- Set the aircraft to NOT land in pairs.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetOptionLandingRestrictPair()
self.OptionLandingRestrictPair = true
if self:GetGroup():IsAlive() then
self:GetGroup():SetOptionLandingRestrictPair()
end
return self
end
--- Set the aircraft to land after overhead break.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetOptionLandingOverheadBreak()
self.OptionLandingOverheadBreak = true
if self:GetGroup():IsAlive() then
self:GetGroup():SetOptionLandingOverheadBreak()
end
return self
end
--- [HELICOPTER] Set the aircraft to prefer takeoff and landing vertically.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetOptionPreferVertical()
self.OptionPreferVertical = true
if self:GetGroup():IsAlive() then
self:GetGroup():OptionPreferVerticalLanding()
end
return self
end
--- Set if group is ready for taxi/takeoff if controlled by a `FLIGHTCONTROL`. --- Set if group is ready for taxi/takeoff if controlled by a `FLIGHTCONTROL`.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @param #boolean ReadyTO If `true`, flight is ready for takeoff. -- @param #boolean ReadyTO If `true`, flight is ready for takeoff.
@@ -2003,6 +2058,9 @@ function FLIGHTGROUP:onafterElementAirborne(From, Event, To, Element)
-- Debug info. -- Debug info.
self:T2(self.lid..string.format("Element airborne %s", Element.name)) self:T2(self.lid..string.format("Element airborne %s", Element.name))
-- Set parking spot to free. Also for FC. This is usually done after taxiing but doing it here in case the group is teleported.
self:_SetElementParkingFree(Element)
-- Set element status. -- Set element status.
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.AIRBORNE) self:_UpdateStatus(Element, OPSGROUP.ElementStatus.AIRBORNE)
@@ -3076,7 +3134,7 @@ function FLIGHTGROUP:onbeforeLandAtAirbase(From, Event, To, airbase)
local Tsuspend=nil local Tsuspend=nil
if airbase==nil then if airbase==nil then
self:T(self.lid.."ERROR: Airbase is nil in LandAtAirase() call!") self:T(self.lid.."ERROR: Airbase is nil in LandAtAirbase() call!")
allowed=false allowed=false
end end
@@ -4494,6 +4552,11 @@ function FLIGHTGROUP:GetParkingSpot(element, maxdist, airbase)
-- Airbase. -- Airbase.
airbase=airbase or self:GetClosestAirbase() airbase=airbase or self:GetClosestAirbase()
if airbase == nil then
self:T(self.lid.."No airbase found for element "..element.name)
return nil
end
-- Parking table of airbase. -- Parking table of airbase.
local parking=airbase.parking --:GetParkingSpotsTable() local parking=airbase.parking --:GetParkingSpotsTable()
@@ -4604,12 +4667,14 @@ function FLIGHTGROUP:GetParking(airbase)
local coords={} local coords={}
for clientname, client in pairs(clients) do for clientname, client in pairs(clients) do
local template=_DATABASE:GetGroupTemplateFromUnitName(clientname) local template=_DATABASE:GetGroupTemplateFromUnitName(clientname)
if template then
local units=template.units local units=template.units
for i,unit in pairs(units) do for i,unit in pairs(units) do
local coord=COORDINATE:New(unit.x, unit.alt, unit.y) local coord=COORDINATE:New(unit.x, unit.alt, unit.y)
coords[unit.name]=coord coords[unit.name]=coord
end end
end end
end
return coords return coords
end end

View File

@@ -2324,7 +2324,7 @@ INTEL_DLINK = {
verbose = 0, verbose = 0,
lid = nil, lid = nil,
alias = nil, alias = nil,
cachetime = 300, cachetime = 120,
interval = 20, interval = 20,
contacts = {}, contacts = {},
clusters = {}, clusters = {},
@@ -2333,7 +2333,7 @@ INTEL_DLINK = {
--- Version string --- Version string
-- @field #string version -- @field #string version
INTEL_DLINK.version = "0.0.1" INTEL_DLINK.version = "0.0.2"
--- Function to instantiate a new object --- Function to instantiate a new object
-- @param #INTEL_DLINK self -- @param #INTEL_DLINK self
@@ -2384,15 +2384,15 @@ function INTEL_DLINK:New(Intels, Alias, Interval, Cachetime)
self.alias="SPECTRE" self.alias="SPECTRE"
end end
-- Cache time
self.cachetime = Cachetime or 300
-- Interval -- Interval
self.interval = Interval or 20 self.interval = Interval or 20
-- Set some string id for output to DCS.log file. -- Set some string id for output to DCS.log file.
self.lid=string.format("INTEL_DLINK %s | ", self.alias) self.lid=string.format("INTEL_DLINK %s | ", self.alias)
-- Cache time
self:SetDLinkCacheTime(Cachetime or 120)
-- Start State. -- Start State.
self:SetStartState("Stopped") self:SetStartState("Stopped")
@@ -2477,6 +2477,16 @@ function INTEL_DLINK:onafterStart(From, Event, To)
return self return self
end end
--- Function to set how long INTEL DLINK remembers contacts.
-- @param #INTEL_DLINK self
-- @param #number seconds Remember this many seconds. Defaults to 180.
-- @return #INTEL_DLINK self
function INTEL_DLINK:SetDLinkCacheTime(seconds)
self.cachetime = math.abs(seconds or 120)
self:I(self.lid.."Caching for "..self.cachetime.." seconds.")
return self
end
--- Function to collect data from the various #INTEL --- Function to collect data from the various #INTEL
-- @param #INTEL_DLINK self -- @param #INTEL_DLINK self
-- @param #string From The From state -- @param #string From The From state

View File

@@ -2514,7 +2514,10 @@ function LEGION._GetCohorts(Legions, Cohorts, Operation, OpsQueue)
local legion=_legion --Ops.Legion#LEGION local legion=_legion --Ops.Legion#LEGION
-- Check that runway is operational. -- Check that runway is operational.
local Runway=legion:IsAirwing() and legion:IsRunwayOperational() or true local Runway=true
if legion:IsAirwing() then
Runway=legion:IsRunwayOperational() and legion.airbase and legion.airbase:GetCoalition() == legion:GetCoalition()
end
-- Legion has to be running. -- Legion has to be running.
if legion:IsRunning() and Runway then if legion:IsRunning() and Runway then

View File

@@ -5589,10 +5589,13 @@ function OPSGROUP:onafterUnpauseMission(From, Event, To)
-- Debug info. -- Debug info.
self:T(self.lid..string.format("Unpausing mission %s [%s]", mission:GetName(), mission:GetType())) self:T(self.lid..string.format("Unpausing mission %s [%s]", mission:GetName(), mission:GetType()))
-- Set state of mission, e.g. for not teleporting again
mission.unpaused=true
-- Start mission. -- Start mission.
self:MissionStart(mission) self:MissionStart(mission)
-- Remove mission from -- Remove mission from pausedmissions queue
for i,mid in pairs(self.pausedmissions) do for i,mid in pairs(self.pausedmissions) do
--self:T(self.lid..string.format("Checking paused mission", mid)) --self:T(self.lid..string.format("Checking paused mission", mid))
if mid==mission.auftragsnummer then if mid==mission.auftragsnummer then
@@ -5727,7 +5730,7 @@ function OPSGROUP:onafterMissionDone(From, Event, To, Mission)
-- Decrease patrol data. -- Decrease patrol data.
if Mission.patroldata then if Mission.patroldata then
Mission.patroldata.noccupied=Mission.patroldata.noccupied-1 Mission.patroldata.noccupied=Mission.patroldata.noccupied-1
AIRWING.UpdatePatrolPointMarker(Mission.patroldata) AIRWING.UpdatePatrolPointMarker(self,Mission.patroldata)
end end
-- Switch auto engage detected off. This IGNORES that engage detected had been activated for the group! -- Switch auto engage detected off. This IGNORES that engage detected had been activated for the group!
@@ -6232,7 +6235,7 @@ function OPSGROUP:RouteToMission(mission, delay)
end end
-- Check if group is mobile. Note that some immobile units report a speed of 1 m/s = 3.6 km/h. -- Check if group is mobile. Note that some immobile units report a speed of 1 m/s = 3.6 km/h.
if self.speedMax<=3.6 or mission.teleport then if (self.speedMax<=3.6 or mission.teleport) and not mission.unpaused then
-- Teleport to waypoint coordinate. Mission will not be paused. -- Teleport to waypoint coordinate. Mission will not be paused.
self:Teleport(waypointcoord, nil, true) self:Teleport(waypointcoord, nil, true)
@@ -9045,7 +9048,7 @@ function OPSGROUP:AddWeightCargo(UnitName, Weight)
self:T(self.lid..string.format("%s: Adding %.1f kg cargo weight. New cargo weight=%.1f kg", UnitName, Weight, element.weightCargo)) self:T(self.lid..string.format("%s: Adding %.1f kg cargo weight. New cargo weight=%.1f kg", UnitName, Weight, element.weightCargo))
-- For airborne units, we set the weight in game. -- For airborne units, we set the weight in game.
if self.isFlightgroup then if self.isFlightgroup and element.unit and element.unit:IsAlive() then -- #2272 trying to deduct cargo weight from possibly dead units
trigger.action.setUnitInternalCargo(element.name, element.weightCargo) --https://wiki.hoggitworld.com/view/DCS_func_setUnitInternalCargo trigger.action.setUnitInternalCargo(element.name, element.weightCargo) --https://wiki.hoggitworld.com/view/DCS_func_setUnitInternalCargo
end end

View File

@@ -53,6 +53,7 @@
-- @field #number threatlevelCapture Threat level necessary to capture a zone. -- @field #number threatlevelCapture Threat level necessary to capture a zone.
-- @field Core.Set#SET_UNIT ScanUnitSet Set of scanned units. -- @field Core.Set#SET_UNIT ScanUnitSet Set of scanned units.
-- @field Core.Set#SET_GROUP ScanGroupSet Set of scanned groups. -- @field Core.Set#SET_GROUP ScanGroupSet Set of scanned groups.
-- @field #number UpdateSeconds Run status every this many seconds.
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- *Gentlemen, when the enemy is committed to a mistake we must not interrupt him too soon.* --- Horation Nelson --- *Gentlemen, when the enemy is committed to a mistake we must not interrupt him too soon.* --- Horation Nelson
@@ -77,6 +78,7 @@ OPSZONE = {
Tnut = 0, Tnut = 0,
chiefs = {}, chiefs = {},
Missions = {}, Missions = {},
UpdateSeconds = 120,
} }
--- OPSZONE.MISSION --- OPSZONE.MISSION
@@ -97,7 +99,7 @@ OPSZONE.ZoneType={
--- OPSZONE class version. --- OPSZONE class version.
-- @field #string version -- @field #string version
OPSZONE.version="0.6.1" OPSZONE.version="0.6.2"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list -- ToDo list
@@ -733,7 +735,8 @@ function OPSZONE:onafterStart(From, Event, To)
self.timerStatus=self.timerStatus or TIMER:New(OPSZONE.Status, self) self.timerStatus=self.timerStatus or TIMER:New(OPSZONE.Status, self)
-- Status update. -- Status update.
self.timerStatus:Start(1, 120) local EveryUpdateIn = self.UpdateSeconds or 120
self.timerStatus:Start(1, EveryUpdateIn)
-- Handle base captured event. -- Handle base captured event.
if self.airbase then if self.airbase then

View File

@@ -1544,7 +1544,7 @@ end
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations! -- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations!
-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies! -- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies!
-- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone" -- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
-- @param #string Gender (Optional) Defaults to "male" -- @param #string Gender (Optional) Defaults to "male"
-- @param #string Culture (Optional) Defaults to "en-US" -- @param #string Culture (Optional) Defaults to "en-US"
-- @param #number Port (Optional) Defaults to 5002 -- @param #number Port (Optional) Defaults to 5002
@@ -1556,7 +1556,7 @@ end
-- @return #PLAYERRECCE self -- @return #PLAYERRECCE self
function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,Backend) function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,Backend)
self:T(self.lid.."SetSRS") self:T(self.lid.."SetSRS")
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" -- self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio" --
self.Gender = Gender or MSRS.gender or "male" -- self.Gender = Gender or MSRS.gender or "male" --
self.Culture = Culture or MSRS.culture or "en-US" -- self.Culture = Culture or MSRS.culture or "en-US" --
self.Port = Port or MSRS.port or 5002 -- self.Port = Port or MSRS.port or 5002 --

View File

@@ -21,7 +21,7 @@
-- === -- ===
-- @module Ops.PlayerTask -- @module Ops.PlayerTask
-- @image OPS_PlayerTask.jpg -- @image OPS_PlayerTask.jpg
-- @date Last Update Jan 2025 -- @date Last Update May 2025
do do
@@ -98,7 +98,7 @@ PLAYERTASK = {
--- PLAYERTASK class version. --- PLAYERTASK class version.
-- @field #string version -- @field #string version
PLAYERTASK.version="0.1.25" PLAYERTASK.version="0.1.27"
--- Generic task condition. --- Generic task condition.
-- @type PLAYERTASK.Condition -- @type PLAYERTASK.Condition
@@ -556,6 +556,7 @@ end
-- @param #PLAYERTASK self -- @param #PLAYERTASK self
-- @param #SET_BASE CaptureSquadGroupNamePrefix The prefix of the group name that needs to capture the zone. -- @param #SET_BASE CaptureSquadGroupNamePrefix The prefix of the group name that needs to capture the zone.
-- @param #number Coalition The coalition that needs to capture the zone. -- @param #number Coalition The coalition that needs to capture the zone.
-- @param #boolean CheckClientInZone If true, a CLIENT assigned to this task also needs to be in the zone for the task to be successful.
-- @return #PLAYERTASK self -- @return #PLAYERTASK self
-- @usage -- @usage
-- -- We can use either STATIC, SET_STATIC, SCENERY or SET_SCENERY as target objects. -- -- We can use either STATIC, SET_STATIC, SCENERY or SET_SCENERY as target objects.
@@ -570,20 +571,20 @@ end
-- --
-- -- We set CaptureSquadGroupNamePrefix the group name prefix as set in the ME or the spawn of the group that need to be present at the OpsZone like a capture squad, -- -- We set CaptureSquadGroupNamePrefix the group name prefix as set in the ME or the spawn of the group that need to be present at the OpsZone like a capture squad,
-- -- and set the capturing Coalition in order to trigger a successful task. -- -- and set the capturing Coalition in order to trigger a successful task.
-- mytask:AddOpsZoneCaptureSuccessCondition("capture-squad", coalition.side.BLUE) -- mytask:AddOpsZoneCaptureSuccessCondition("capture-squad", coalition.side.BLUE, false)
-- --
-- playerTaskManager:AddPlayerTaskToQueue(mytask) -- playerTaskManager:AddPlayerTaskToQueue(mytask)
function PLAYERTASK:AddOpsZoneCaptureSuccessCondition(CaptureSquadGroupNamePrefix, Coalition) function PLAYERTASK:AddOpsZoneCaptureSuccessCondition(CaptureSquadGroupNamePrefix, Coalition, CheckClientInZone)
local task = self local task = self
task:AddConditionSuccess( task:AddConditionSuccess(
function(target) function(target)
if target:IsInstanceOf("OPSZONE") then if target:IsInstanceOf("OPSZONE") then
return task:_CheckCaptureOpsZoneSuccess(target, CaptureSquadGroupNamePrefix, Coalition, true) return task:_CheckCaptureOpsZoneSuccess(target, CaptureSquadGroupNamePrefix, Coalition, CheckClientInZone or true)
elseif target:IsInstanceOf("SET_OPSZONE") then elseif target:IsInstanceOf("SET_OPSZONE") then
local successes = 0 local successes = 0
local isClientInZone = false local isClientInZone = false
target:ForEachZone(function(opszone) target:ForEachZone(function(opszone)
if task:_CheckCaptureOpsZoneSuccess(opszone, CaptureSquadGroupNamePrefix, Coalition) then if task:_CheckCaptureOpsZoneSuccess(opszone, CaptureSquadGroupNamePrefix, Coalition, CheckClientInZone or true) then
successes = successes + 1 successes = successes + 1
end end
@@ -979,6 +980,12 @@ function PLAYERTASK:onafterStatus(From, Event, To)
if status == "Stopped" then return self end if status == "Stopped" then return self end
-- update marker in case target is moving
if self.TargetMarker then
local coordinate = self.Target:GetCoordinate()
self.TargetMarker:UpdateCoordinate(coordinate,0.5)
end
-- Check Target status -- Check Target status
local targetdead = false local targetdead = false
@@ -1433,9 +1440,9 @@ do
-- taskmanager:AddRejectZone(ZONE:FindByName("RejectZone")) -- taskmanager:AddRejectZone(ZONE:FindByName("RejectZone"))
-- --
-- -- Set up using SRS for messaging -- -- Set up using SRS for messaging
-- local hereSRSPath = "C:\\Program Files\\DCS-SimpleRadio-Standalone" -- local hereSRSPath = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
-- local hereSRSPort = 5002 -- local hereSRSPort = 5002
-- -- local hereSRSGoogle = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourkey.json" -- -- local hereSRSGoogle = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio\\yourkey.json"
-- taskmanager:SetSRS({130,255},{radio.modulation.AM,radio.modulation.AM},hereSRSPath,"female","en-GB",hereSRSPort,"Microsoft Hazel Desktop",0.7,hereSRSGoogle) -- taskmanager:SetSRS({130,255},{radio.modulation.AM,radio.modulation.AM},hereSRSPath,"female","en-GB",hereSRSPort,"Microsoft Hazel Desktop",0.7,hereSRSGoogle)
-- --
-- -- Controller will announce itself under these broadcast frequencies, handy to use cold-start frequencies here of your aircraft -- -- Controller will announce itself under these broadcast frequencies, handy to use cold-start frequencies here of your aircraft
@@ -1902,7 +1909,7 @@ PLAYERTASKCONTROLLER.Messages = {
--- PLAYERTASK class version. --- PLAYERTASK class version.
-- @field #string version -- @field #string version
PLAYERTASKCONTROLLER.version="0.1.69" PLAYERTASKCONTROLLER.version="0.1.70"
--- Create and run a new TASKCONTROLLER instance. --- Create and run a new TASKCONTROLLER instance.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
@@ -1944,7 +1951,7 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
self.taskinfomenu = false self.taskinfomenu = false
self.activehasinfomenu = false self.activehasinfomenu = false
self.MenuName = nil self.MenuName = nil
self.menuitemlimit = 5 self.menuitemlimit = 6
self.holdmenutime = 30 self.holdmenutime = 30
self.MarkerReadOnly = false self.MarkerReadOnly = false
@@ -2415,7 +2422,7 @@ function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode,Holdi
end end
) )
else else
self:E(self.lid.."No FLIGHTGROUP object passed or FLIGHTGROUP is not alive!") self:E(self.lid.."No OPSGROUP/SET_OPSGROUP object passed or object is not alive!")
end end
else else
self.autolase = nil self.autolase = nil
@@ -2574,7 +2581,7 @@ function PLAYERTASKCONTROLLER:SetMenuOptions(InfoMenu,ItemLimit,HoldTime)
if self.activehasinfomenu then if self.activehasinfomenu then
self:EnableTaskInfoMenu() self:EnableTaskInfoMenu()
end end
self.menuitemlimit = ItemLimit or 5 self.menuitemlimit = ItemLimit+1 or 6
self.holdmenutime = HoldTime or 30 self.holdmenutime = HoldTime or 30
return self return self
end end
@@ -3479,7 +3486,7 @@ end
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param Ops.PlayerTask#PLAYERTASK PlayerTask -- @param Ops.PlayerTask#PLAYERTASK PlayerTask
-- @param #boolean Silent If true, make no "has new task" announcement -- @param #boolean Silent If true, make no "has new task" announcement
-- @param #boolen TaskFilter If true, apply the white/black-list task filters here, also -- @param #boolean TaskFilter If true, apply the white/black-list task filters here, also
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
-- @usage -- @usage
-- Example to create a PLAYERTASK of type CTLD and give Players 10 minutes to complete: -- Example to create a PLAYERTASK of type CTLD and give Players 10 minutes to complete:
@@ -3703,6 +3710,7 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Task, Group, Client)
else else
CoordText = Coordinate:ToStringA2A(Client,nil,self.ShowMagnetic) CoordText = Coordinate:ToStringA2A(Client,nil,self.ShowMagnetic)
end end
--self:I("CoordText = "..CoordText)
-- Threat Level -- Threat Level
local ThreatLevel = task.Target:GetThreatLevelMax() local ThreatLevel = task.Target:GetThreatLevelMax()
--local ThreatLevelText = "high" --local ThreatLevelText = "high"
@@ -3837,7 +3845,8 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Task, Group, Client)
Text = string.gsub(Text,"9","niner") Text = string.gsub(Text,"9","niner")
CoordText = "MGRS;"..Text CoordText = "MGRS;"..Text
if self.PathToGoogleKey then if self.PathToGoogleKey then
CoordText = string.format("<say-as interpret-as='characters'>%s</say-as>",CoordText) --CoordText = string.format("<say-as interpret-as=\'characters\'>%s</say-as>",CoordText)
--doesn't seem to work any longer
end end
--self:I(self.lid.." | ".. CoordText) --self:I(self.lid.." | ".. CoordText)
end end
@@ -3855,10 +3864,12 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Task, Group, Client)
CoordText = string.gsub(ttstext," BR, "," Bee, Arr, ") CoordText = string.gsub(ttstext," BR, "," Bee, Arr, ")
end end
elseif task:HasFreetext() then elseif task:HasFreetext() then
-- add tts freetext -- add tts freetext
local brieftxt = self.gettext:GetEntry("BRIEFING",self.locale) local brieftxt = self.gettext:GetEntry("BRIEFING",self.locale)
ttstext = ttstext .. string.format("; %s: ",brieftxt)..task:GetFreetextTTS() ttstext = ttstext .. string.format("; %s: ",brieftxt)..task:GetFreetextTTS()
end end
--self:I("**** TTS Text ****\n"..ttstext.."\n*****")
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,2) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,2)
end end
else else
@@ -4357,7 +4368,7 @@ function PLAYERTASKCONTROLLER:SwitchDetectStatics(OnOff)
return self return self
end end
--- [User] Add accept zone to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this. --- [User] Add an accept zone to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set. -- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set.
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
@@ -4371,7 +4382,7 @@ function PLAYERTASKCONTROLLER:AddAcceptZone(AcceptZone)
return self return self
end end
--- [User] Add accept SET_ZONE to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this. --- [User] Add an accept SET_ZONE to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param Core.Set#SET_ZONE AcceptZoneSet Add a SET_ZONE to the accept zone set. -- @param Core.Set#SET_ZONE AcceptZoneSet Add a SET_ZONE to the accept zone set.
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
@@ -4385,7 +4396,7 @@ function PLAYERTASKCONTROLLER:AddAcceptZoneSet(AcceptZoneSet)
return self return self
end end
--- [User] Add reject zone to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this. --- [User] Add a reject zone to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set. -- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
@@ -4399,7 +4410,7 @@ function PLAYERTASKCONTROLLER:AddRejectZone(RejectZone)
return self return self
end end
--- [User] Add reject SET_ZONE to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this. --- [User] Add a reject SET_ZONE to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param Core.Set#SET_ZONE RejectZoneSet Add a zone to the reject zone set. -- @param Core.Set#SET_ZONE RejectZoneSet Add a zone to the reject zone set.
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
@@ -4413,9 +4424,37 @@ function PLAYERTASKCONTROLLER:AddRejectZoneSet(RejectZoneSet)
return self return self
end end
--- [User] Remove accept zone from INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this. --- [User] Add a conflict zone to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set. -- @param Core.Zone#ZONE ConflictZone Add a zone to the conflict zone set.
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:AddConflictZone(ConflictZone)
self:T(self.lid.."AddConflictZone")
if self.Intel then
self.Intel:AddConflictZone(ConflictZone)
else
self:E(self.lid.."*****NO detection has been set up (yet)!")
end
return self
end
--- [User] Add a conflict SET_ZONE to INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self
-- @param Core.Set#SET_ZONE ConflictZoneSet Add a zone to the conflict zone set.
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:AddConflictZoneSet(ConflictZoneSet)
self:T(self.lid.."AddConflictZoneSet")
if self.Intel then
self.Intel.conflictzoneset:AddSet(ConflictZoneSet)
else
self:E(self.lid.."*****NO detection has been set up (yet)!")
end
return self
end
--- [User] Remove an accept zone from INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self
-- @param Core.Zone#ZONE AcceptZone Remove this zone from the accept zone set.
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:RemoveAcceptZone(AcceptZone) function PLAYERTASKCONTROLLER:RemoveAcceptZone(AcceptZone)
self:T(self.lid.."RemoveAcceptZone") self:T(self.lid.."RemoveAcceptZone")
@@ -4427,11 +4466,11 @@ function PLAYERTASKCONTROLLER:RemoveAcceptZone(AcceptZone)
return self return self
end end
--- [User] Remove reject zone from INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this. --- [User] Remove a reject zone from INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set. -- @param Core.Zone#ZONE RejectZone Remove this zone from the reject zone set.
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:RemoveRejectZoneSet(RejectZone) function PLAYERTASKCONTROLLER:RemoveRejectZone(RejectZone)
self:T(self.lid.."RemoveRejectZone") self:T(self.lid.."RemoveRejectZone")
if self.Intel then if self.Intel then
self.Intel:RemoveRejectZone(RejectZone) self.Intel:RemoveRejectZone(RejectZone)
@@ -4441,6 +4480,20 @@ function PLAYERTASKCONTROLLER:RemoveRejectZoneSet(RejectZone)
return self return self
end end
--- [User] Remove a conflict zone from INTEL detection. You need to set up detection with @{#PLAYERTASKCONTROLLER.SetupIntel}() **before** using this.
-- @param #PLAYERTASKCONTROLLER self
-- @param Core.Zone#ZONE ConflictZone Remove this zone from the conflict zone set.
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:RemoveConflictZone(ConflictZone)
self:T(self.lid.."RemoveConflictZone")
if self.Intel then
self.Intel:RemoveConflictZone(ConflictZone)
else
self:E(self.lid.."*****NO detection has been set up (yet)!")
end
return self
end
--- [User] Set the top menu name to a custom string. --- [User] Set the top menu name to a custom string.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param #string Name The name to use as the top menu designation. -- @param #string Name The name to use as the top menu designation.
@@ -4553,7 +4606,7 @@ end
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations! -- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations!
-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies! -- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies!
-- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone" -- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
-- @param #string Gender (Optional) Defaults to "male" -- @param #string Gender (Optional) Defaults to "male"
-- @param #string Culture (Optional) Defaults to "en-US" -- @param #string Culture (Optional) Defaults to "en-US"
-- @param #number Port (Optional) Defaults to 5002 -- @param #number Port (Optional) Defaults to 5002
@@ -4567,7 +4620,7 @@ end
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey,Coordinate,Backend) function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey,Coordinate,Backend)
self:T(self.lid.."SetSRS") self:T(self.lid.."SetSRS")
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" -- self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio" --
self.Gender = Gender or MSRS.gender or "male" -- self.Gender = Gender or MSRS.gender or "male" --
self.Culture = Culture or MSRS.culture or "en-US" -- self.Culture = Culture or MSRS.culture or "en-US" --
self.Port = Port or MSRS.port or 5002 -- self.Port = Port or MSRS.port or 5002 --

View File

@@ -1715,6 +1715,26 @@ function TARGET:GetAverageCoordinate()
return nil return nil
end end
--- Get coordinates of all targets. (e.g. for a SET_STATIC)
-- @param #TARGET self
-- @return #table Table with coordinates of all targets.
function TARGET:GetCoordinates()
local coordinates={}
for _,_target in pairs(self.targets) do
local target=_target --#TARGET.Object
local coordinate=self:GetTargetCoordinate(target)
if coordinate then
table.insert(coordinates, coordinate)
end
end
return coordinates
end
--- Get heading of target. --- Get heading of target.
-- @param #TARGET self -- @param #TARGET self
-- @return #number Heading of the target in degrees. -- @return #number Heading of the target in degrees.
@@ -1968,6 +1988,21 @@ function TARGET:GetObject(RefCoordinate, Coalitions)
return nil return nil
end end
--- Get all target objects.
-- @param #TARGET self
-- @return #table List of target objects.
function TARGET:GetObjects()
local objects={}
for _,_target in pairs(self.targets) do
local target=_target --#TARGET.Object
table.insert(objects, target.Object)
end
return objects
end
--- Count alive objects. --- Count alive objects.
-- @param #TARGET self -- @param #TARGET self
-- @param #TARGET.Object Target Target objective. -- @param #TARGET.Object Target Target objective.

View File

@@ -72,7 +72,7 @@ end
--- Checks if a point is contained within the circle. --- Checks if a point is contained within the circle.
-- @param #table point The point to check -- @param #table point The point to check
-- @return #bool True if the point is contained, false otherwise -- @return #boolean True if the point is contained, false otherwise
function CIRCLE:ContainsPoint(point) function CIRCLE:ContainsPoint(point)
if ((point.x - self.CenterVec2.x) ^ 2 + (point.y - self.CenterVec2.y) ^ 2) ^ 0.5 <= self.Radius then if ((point.x - self.CenterVec2.x) ^ 2 + (point.y - self.CenterVec2.y) ^ 2) ^ 0.5 <= self.Radius then
return true return true
@@ -226,6 +226,11 @@ end
--- Returns a random Vec2 within the circle. --- Returns a random Vec2 within the circle.
-- @return #table The random Vec2 -- @return #table The random Vec2
function CIRCLE:GetRandomVec2() function CIRCLE:GetRandomVec2()
math.random()
math.random()
math.random()
local angle = math.random() * 2 * math.pi local angle = math.random() * 2 * math.pi
local rx = math.random(0, self.Radius) * math.cos(angle) + self.CenterVec2.x local rx = math.random(0, self.Radius) * math.cos(angle) + self.CenterVec2.x
@@ -237,6 +242,11 @@ end
--- Returns a random Vec2 on the border of the circle. --- Returns a random Vec2 on the border of the circle.
-- @return #table The random Vec2 -- @return #table The random Vec2
function CIRCLE:GetRandomVec2OnBorder() function CIRCLE:GetRandomVec2OnBorder()
math.random()
math.random()
math.random()
local angle = math.random() * 2 * math.pi local angle = math.random() * 2 * math.pi
local rx = self.Radius * math.cos(angle) + self.CenterVec2.x local rx = self.Radius * math.cos(angle) + self.CenterVec2.x

View File

@@ -352,6 +352,7 @@ end
--- Returns a random Vec2 within the polygon. The Vec2 is weighted by the areas of the triangles that make up the polygon. --- Returns a random Vec2 within the polygon. The Vec2 is weighted by the areas of the triangles that make up the polygon.
-- @return #table The random Vec2 -- @return #table The random Vec2
function POLYGON:GetRandomVec2() function POLYGON:GetRandomVec2()
local weights = {} local weights = {}
for _, triangle in pairs(self.Triangles) do for _, triangle in pairs(self.Triangles) do
weights[triangle] = triangle.SurfaceArea / self.SurfaceArea weights[triangle] = triangle.SurfaceArea / self.SurfaceArea

View File

@@ -73,6 +73,11 @@ end
-- @param #table points The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it -- @param #table points The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it
-- @return #table The random Vec2 -- @return #table The random Vec2
function TRIANGLE:GetRandomVec2(points) function TRIANGLE:GetRandomVec2(points)
math.random()
math.random()
math.random()
points = points or self.Points points = points or self.Points
local pt = {math.random(), math.random()} local pt = {math.random(), math.random()}
table.sort(pt) table.sort(pt)

View File

@@ -380,7 +380,8 @@ function RADIOQUEUE:Broadcast(transmission)
self:T(self.lid..string.format("Broadcasting from aircraft %s", sender:GetName())) self:T(self.lid..string.format("Broadcasting from aircraft %s", sender:GetName()))
if not self.senderinit then --if not self.senderinit then
-- TODO Seems to be a DCS bug - if I explode ANY unit in a group the BC assignment gets lost
-- Command to set the Frequency for the transmission. -- Command to set the Frequency for the transmission.
local commandFrequency={ local commandFrequency={
@@ -394,7 +395,7 @@ function RADIOQUEUE:Broadcast(transmission)
sender:SetCommand(commandFrequency) sender:SetCommand(commandFrequency)
self.senderinit=true self.senderinit=true
end --end
-- Set subtitle only if duration>0 sec. -- Set subtitle only if duration>0 sec.
local subtitle=nil local subtitle=nil

View File

@@ -443,28 +443,32 @@ MSRS.Voices = {
["en_AU_Standard_B"] = 'en-AU-Standard-B', -- [2] MALE ["en_AU_Standard_B"] = 'en-AU-Standard-B', -- [2] MALE
["en_AU_Standard_C"] = 'en-AU-Standard-C', -- [3] FEMALE ["en_AU_Standard_C"] = 'en-AU-Standard-C', -- [3] FEMALE
["en_AU_Standard_D"] = 'en-AU-Standard-D', -- [4] MALE ["en_AU_Standard_D"] = 'en-AU-Standard-D', -- [4] MALE
["en_IN_Standard_A"] = 'en-IN-Standard-A', -- [5] FEMALE -- IN
["en_IN_Standard_B"] = 'en-IN-Standard-B', -- [6] MALE ["en_IN_Standard_A"] = 'en-IN-Standard-A', -- Female
["en_IN_Standard_C"] = 'en-IN-Standard-C', -- [7] MALE ["en_IN_Standard_B"] = 'en-IN-Standard-B', -- Male
["en_IN_Standard_D"] = 'en-IN-Standard-D', -- [8] FEMALE ["en_IN_Standard_C"] = 'en-IN-Standard-C', -- Male
["en_IN_Standard_D"] = 'en-IN-Standard-D', -- Female
["en_IN_Standard_E"] = 'en-IN-Standard-E', -- Female
["en_IN_Standard_F"] = 'en-IN-Standard-F', -- Male
-- 2025 changes -- 2025 changes
["en_GB_Standard_A"] = 'en-GB-Standard-N', -- [9] FEMALE ["en_GB_Standard_A"] = 'en-GB-Standard-A', -- Female
["en_GB_Standard_B"] = 'en-GB-Standard-O', -- [10] MALE ["en_GB_Standard_B"] = 'en-GB-Standard-B', -- Male
["en_GB_Standard_C"] = 'en-GB-Standard-N', -- [11] FEMALE ["en_GB_Standard_C"] = 'en-GB-Standard-C', -- Female
["en_GB_Standard_D"] = 'en-GB-Standard-O', -- [12] MALE ["en_GB_Standard_D"] = 'en-GB-Standard-D', -- Male
["en_GB_Standard_F"] = 'en-GB-Standard-N', -- [13] FEMALE ["en_GB_Standard_F"] = 'en-GB-Standard-F', -- Female
["en_GB_Standard_O"] = 'en-GB-Standard-O', -- [12] MALE ["en_GB_Standard_N"] = 'en-GB-Standard-N', -- Female
["en_GB_Standard_N"] = 'en-GB-Standard-N', -- [13] FEMALE ["en_GB_Standard_O"] = 'en-GB-Standard-O', -- Male
["en_US_Standard_A"] = 'en-US-Standard-A', -- [14] MALE -- US
["en_US_Standard_B"] = 'en-US-Standard-B', -- [15] MALE ["en_US_Standard_A"] = 'en-US-Standard-A', -- Male
["en_US_Standard_C"] = 'en-US-Standard-C', -- [16] FEMALE ["en_US_Standard_B"] = 'en-US-Standard-B', -- Male
["en_US_Standard_D"] = 'en-US-Standard-D', -- [17] MALE ["en_US_Standard_C"] = 'en-US-Standard-C', -- Female
["en_US_Standard_E"] = 'en-US-Standard-E', -- [18] FEMALE ["en_US_Standard_D"] = 'en-US-Standard-D', -- Male
["en_US_Standard_F"] = 'en-US-Standard-F', -- [19] FEMALE ["en_US_Standard_E"] = 'en-US-Standard-E', -- Female
["en_US_Standard_G"] = 'en-US-Standard-G', -- [20] FEMALE ["en_US_Standard_F"] = 'en-US-Standard-F', -- Female
["en_US_Standard_H"] = 'en-US-Standard-H', -- [21] FEMALE ["en_US_Standard_G"] = 'en-US-Standard-G', -- Female
["en_US_Standard_I"] = 'en-US-Standard-I', -- [22] MALE ["en_US_Standard_H"] = 'en-US-Standard-H', -- Female
["en_US_Standard_J"] = 'en-US-Standard-J', -- [23] MALE ["en_US_Standard_I"] = 'en-US-Standard-I', -- Male
["en_US_Standard_J"] = 'en-US-Standard-J', -- Male
-- 2025 catalog changes -- 2025 catalog changes
["fr_FR_Standard_A"] = "fr-FR-Standard-F", -- Female ["fr_FR_Standard_A"] = "fr-FR-Standard-F", -- Female
["fr_FR_Standard_B"] = "fr-FR-Standard-G", -- Male ["fr_FR_Standard_B"] = "fr-FR-Standard-G", -- Male
@@ -474,14 +478,15 @@ MSRS.Voices = {
["fr_FR_Standard_G"] = "fr-FR-Standard-G", -- Male ["fr_FR_Standard_G"] = "fr-FR-Standard-G", -- Male
["fr_FR_Standard_F"] = "fr-FR-Standard-F", -- Female ["fr_FR_Standard_F"] = "fr-FR-Standard-F", -- Female
-- 2025 catalog changes -- 2025 catalog changes
["de_DE_Standard_A"] = "de-DE-Standard-G", -- Female ["de_DE_Standard_A"] = 'de-DE-Standard-A', -- Female
["de_DE_Standard_B"] = "de-DE-Standard-H", -- Male ["de_DE_Standard_B"] = 'de-DE-Standard-B', -- Male
["de_DE_Standard_C"] = "de-DE-Standard-G", -- Female ["de_DE_Standard_C"] = 'de-DE-Standard-C', -- Female
["de_DE_Standard_D"] = "de-DE-Standard-H", -- Male ["de_DE_Standard_D"] = 'de-DE-Standard-D', -- Male
["de_DE_Standard_E"] = "de-DE-Standard-H", -- Male ["de_DE_Standard_E"] = 'de-DE-Standard-E', -- Male
["de_DE_Standard_F"] = "de-DE-Standard-G", -- Female ["de_DE_Standard_F"] = 'de-DE-Standard-F', -- Female
["de_DE_Standard_H"] = "de-DE-Standard-H", -- Male ["de_DE_Standard_G"] = 'de-DE-Standard-G', -- Female
["de_DE_Standard_G"] = "de-DE-Standard-G", -- Female ["de_DE_Standard_H"] = 'de-DE-Standard-H', -- Male
-- ES
["es_ES_Standard_A"] = "es-ES-Standard-E", -- Female ["es_ES_Standard_A"] = "es-ES-Standard-E", -- Female
["es_ES_Standard_B"] = "es-ES-Standard-F", -- Male ["es_ES_Standard_B"] = "es-ES-Standard-F", -- Male
["es_ES_Standard_C"] = "es-ES-Standard-E", -- Female ["es_ES_Standard_C"] = "es-ES-Standard-E", -- Female
@@ -497,32 +502,36 @@ MSRS.Voices = {
["it_IT_Standard_F"] = "it-IT-Standard-F", -- Male ["it_IT_Standard_F"] = "it-IT-Standard-F", -- Male
}, },
Wavenet = { Wavenet = {
["en_AU_Wavenet_A"] = 'en-AU-Wavenet-A', -- [1] FEMALE ["en_AU_Wavenet_A"] = 'en-AU-Wavenet-A', -- Female
["en_AU_Wavenet_B"] = 'en-AU-Wavenet-B', -- [2] MALE ["en_AU_Wavenet_B"] = 'en-AU-Wavenet-B', -- Male
["en_AU_Wavenet_C"] = 'en-AU-Wavenet-C', -- [3] FEMALE ["en_AU_Wavenet_C"] = 'en-AU-Wavenet-C', -- Female
["en_AU_Wavenet_D"] = 'en-AU-Wavenet-D', -- [4] MALE ["en_AU_Wavenet_D"] = 'en-AU-Wavenet-D', -- Male
["en_IN_Wavenet_A"] = 'en-IN-Wavenet-A', -- [5] FEMALE -- IN
["en_IN_Wavenet_B"] = 'en-IN-Wavenet-B', -- [6] MALE ["en_IN_Wavenet_A"] = 'en-IN-Wavenet-A', -- Female
["en_IN_Wavenet_C"] = 'en-IN-Wavenet-C', -- [7] MALE ["en_IN_Wavenet_B"] = 'en-IN-Wavenet-B', -- Male
["en_IN_Wavenet_D"] = 'en-IN-Wavenet-D', -- [8] FEMALE ["en_IN_Wavenet_C"] = 'en-IN-Wavenet-C', -- Male
["en_IN_Wavenet_D"] = 'en-IN-Wavenet-D', -- Female
["en_IN_Wavenet_E"] = 'en-IN-Wavenet-E', -- Female
["en_IN_Wavenet_F"] = 'en-IN-Wavenet-F', -- Male
-- 2025 changes -- 2025 changes
["en_GB_Wavenet_A"] = 'en-GB-Wavenet-N', -- [9] FEMALE ["en_GB_Wavenet_A"] = 'en-GB-Wavenet-A', -- [9] FEMALE
["en_GB_Wavenet_B"] = 'en-GB-Wavenet-O', -- [10] MALE ["en_GB_Wavenet_B"] = 'en-GB-Wavenet-B', -- [10] MALE
["en_GB_Wavenet_C"] = 'en-GB-Wavenet-N', -- [11] FEMALE ["en_GB_Wavenet_C"] = 'en-GB-Wavenet-C', -- [11] FEMALE
["en_GB_Wavenet_D"] = 'en-GB-Wavenet-O', -- [12] MALE ["en_GB_Wavenet_D"] = 'en-GB-Wavenet-D', -- [12] MALE
["en_GB_Wavenet_F"] = 'en-GB-Wavenet-N', -- [13] FEMALE ["en_GB_Wavenet_F"] = 'en-GB-Wavenet-F', -- [13] FEMALE
["en_GB_Wavenet_O"] = 'en-GB-Wavenet-O', -- [12] MALE ["en_GB_Wavenet_O"] = 'en-GB-Wavenet-O', -- [12] MALE
["en_GB_Wavenet_N"] = 'en-GB-Wavenet-N', -- [13] FEMALE ["en_GB_Wavenet_N"] = 'en-GB-Wavenet-N', -- [13] FEMALE
["en_US_Wavenet_A"] = 'en-US-Wavenet-N', -- [14] MALE -- US
["en_US_Wavenet_B"] = 'en-US-Wavenet-B', -- [15] MALE ["en_US_Wavenet_A"] = 'en-US-Wavenet-A', -- Male
["en_US_Wavenet_C"] = 'en-US-Wavenet-C', -- [16] FEMALE ["en_US_Wavenet_B"] = 'en-US-Wavenet-B', -- Male
["en_US_Wavenet_D"] = 'en-US-Wavenet-D', -- [17] MALE ["en_US_Wavenet_C"] = 'en-US-Wavenet-C', -- Female
["en_US_Wavenet_E"] = 'en-US-Wavenet-E', -- [18] FEMALE ["en_US_Wavenet_D"] = 'en-US-Wavenet-D', -- Male
["en_US_Wavenet_F"] = 'en-US-Wavenet-F', -- [19] FEMALE ["en_US_Wavenet_E"] = 'en-US-Wavenet-E', -- Female
["en_US_Wavenet_G"] = 'en-US-Wavenet-G', -- [20] FEMALE ["en_US_Wavenet_F"] = 'en-US-Wavenet-F', -- Female
["en_US_Wavenet_H"] = 'en-US-Wavenet-H', -- [21] FEMALE ["en_US_Wavenet_G"] = 'en-US-Wavenet-G', -- Female
["en_US_Wavenet_I"] = 'en-US-Wavenet-I', -- [22] MALE ["en_US_Wavenet_H"] = 'en-US-Wavenet-H', -- Female
["en_US_Wavenet_J"] = 'en-US-Wavenet-J', -- [23] MALE ["en_US_Wavenet_I"] = 'en-US-Wavenet-I', -- Male
["en_US_Wavenet_J"] = 'en-US-Wavenet-J', -- Male
-- 2025 catalog changes -- 2025 catalog changes
["fr_FR_Wavenet_A"] = "fr-FR-Wavenet-F", -- Female ["fr_FR_Wavenet_A"] = "fr-FR-Wavenet-F", -- Female
["fr_FR_Wavenet_B"] = "fr-FR-Wavenet-G", -- Male ["fr_FR_Wavenet_B"] = "fr-FR-Wavenet-G", -- Male
@@ -532,14 +541,15 @@ MSRS.Voices = {
["fr_FR_Wavenet_G"] = "fr-FR-Wavenet-G", -- Male ["fr_FR_Wavenet_G"] = "fr-FR-Wavenet-G", -- Male
["fr_FR_Wavenet_F"] = "fr-FR-Wavenet-F", -- Female ["fr_FR_Wavenet_F"] = "fr-FR-Wavenet-F", -- Female
-- 2025 catalog changes -- 2025 catalog changes
["de_DE_Wavenet_A"] = "de-DE-Wavenet-G", -- Female ["de_DE_Wavenet_A"] = 'de-DE-Wavenet-A', -- Female
["de_DE_Wavenet_B"] = "de-DE-Wavenet-H", -- Male ["de_DE_Wavenet_B"] = 'de-DE-Wavenet-B', -- Male
["de_DE_Wavenet_C"] = "de-DE-Wavenet-G", -- Female ["de_DE_Wavenet_C"] = 'de-DE-Wavenet-C', -- Female
["de_DE_Wavenet_D"] = "de-DE-Wavenet-H", -- Male ["de_DE_Wavenet_D"] = 'de-DE-Wavenet-D', -- Male
["de_DE_Wavenet_E"] = "de-DE-Wavenet-H", -- Male ["de_DE_Wavenet_E"] = 'de-DE-Wavenet-E', -- Male
["de_DE_Wavenet_F"] = "de-DE-Wavenet-G", -- Female ["de_DE_Wavenet_F"] = 'de-DE-Wavenet-F', -- Female
["de_DE_Wavenet_H"] = "de-DE-Wavenet-H", -- Male ["de_DE_Wavenet_G"] = 'de-DE-Wavenet-G', -- Female
["de_DE_Wavenet_G"] = "de-DE-Wavenet-G", -- Female ["de_DE_Wavenet_H"] = 'de-DE-Wavenet-H', -- Male
-- ES
["es_ES_Wavenet_B"] = "es-ES-Wavenet-E", -- Male ["es_ES_Wavenet_B"] = "es-ES-Wavenet-E", -- Male
["es_ES_Wavenet_C"] = "es-ES-Wavenet-F", -- Female ["es_ES_Wavenet_C"] = "es-ES-Wavenet-F", -- Female
["es_ES_Wavenet_D"] = "es-ES-Wavenet-E", -- Female ["es_ES_Wavenet_D"] = "es-ES-Wavenet-E", -- Female
@@ -553,6 +563,134 @@ MSRS.Voices = {
["it_IT_Wavenet_E"] = "it-IT-Wavenet-E", -- Female ["it_IT_Wavenet_E"] = "it-IT-Wavenet-E", -- Female
["it_IT_Wavenet_F"] = "it-IT-Wavenet-F", -- Male ["it_IT_Wavenet_F"] = "it-IT-Wavenet-F", -- Male
} , } ,
Chirp3HD = {
["en_GB_Chirp3_HD_Aoede"] = 'en-GB-Chirp3-HD-Aoede', -- Female
["en_GB_Chirp3_HD_Charon"] = 'en-GB-Chirp3-HD-Charon', -- Male
["en_GB_Chirp3_HD_Fenrir"] = 'en-GB-Chirp3-HD-Fenrir', -- Male
["en_GB_Chirp3_HD_Kore"] = 'en-GB-Chirp3-HD-Kore', -- Female
["en_GB_Chirp3_HD_Leda"] = 'en-GB-Chirp3-HD-Leda', -- Female
["en_GB_Chirp3_HD_Orus"] = 'en-GB-Chirp3-HD-Orus', -- Male
["en_GB_Chirp3_HD_Puck"] = 'en-GB-Chirp3-HD-Puck', -- Male
["en_GB_Chirp3_HD_Zephyr"] = 'en-GB-Chirp3-HD-Zephyr', -- Female
--["de_DE_Chirp3_HD_Aoede"] = 'de-DE-Chirp3-HD-Aoede', -- Female (Datenfehler im Original)
["en_US_Chirp3_HD_Charon"] = 'en-US-Chirp3-HD-Charon', -- Male
["en_US_Chirp3_HD_Fenrir"] = 'en-US-Chirp3-HD-Fenrir', -- Male
["en_US_Chirp3_HD_Kore"] = 'en-US-Chirp3-HD-Kore', -- Female
["en_US_Chirp3_HD_Leda"] = 'en-US-Chirp3-HD-Leda', -- Female
["en_US_Chirp3_HD_Orus"] = 'en-US-Chirp3-HD-Orus', -- Male
["en_US_Chirp3_HD_Puck"] = 'en-US-Chirp3-HD-Puck', -- Male
--["de_DE_Chirp3_HD_Zephyr"] = 'de-DE-Chirp3-HD-Zephyr', -- Female (Datenfehler im Original)
-- DE
["de_DE_Chirp3_HD_Aoede"] = 'de-DE-Chirp3-HD-Aoede', -- Female
["de_DE_Chirp3_HD_Charon"] = 'de-DE-Chirp3-HD-Charon', -- Male
["de_DE_Chirp3_HD_Fenrir"] = 'de-DE-Chirp3-HD-Fenrir', -- Male
["de_DE_Chirp3_HD_Kore"] = 'de-DE-Chirp3-HD-Kore', -- Female
["de_DE_Chirp3_HD_Leda"] = 'de-DE-Chirp3-HD-Leda', -- Female
["de_DE_Chirp3_HD_Orus"] = 'de-DE-Chirp3-HD-Orus', -- Male
["de_DE_Chirp3_HD_Puck"] = 'de-DE-Chirp3-HD-Puck', -- Male
["de_DE_Chirp3_HD_Zephyr"] = 'de-DE-Chirp3-HD-Zephyr', -- Female
-- AU
["en_AU_Chirp3_HD_Aoede"] = 'en-AU-Chirp3-HD-Aoede', -- Female
["en_AU_Chirp3_HD_Charon"] = 'en-AU-Chirp3-HD-Charon', -- Male
["en_AU_Chirp3_HD_Fenrir"] = 'en-AU-Chirp3-HD-Fenrir', -- Male
["en_AU_Chirp3_HD_Kore"] = 'en-AU-Chirp3-HD-Kore', -- Female
["en_AU_Chirp3_HD_Leda"] = 'en-AU-Chirp3-HD-Leda', -- Female
["en_AU_Chirp3_HD_Orus"] = 'en-AU-Chirp3-HD-Orus', -- Male
["en_AU_Chirp3_HD_Puck"] = 'en-AU-Chirp3-HD-Puck', -- Male
["en_AU_Chirp3_HD_Zephyr"] = 'en-AU-Chirp3-HD-Zephyr', -- Female
-- IN
["en_IN_Chirp3_HD_Aoede"] = 'en-IN-Chirp3-HD-Aoede', -- Female
["en_IN_Chirp3_HD_Charon"] = 'en-IN-Chirp3-HD-Charon', -- Male
["en_IN_Chirp3_HD_Fenrir"] = 'en-IN-Chirp3-HD-Fenrir', -- Male
["en_IN_Chirp3_HD_Kore"] = 'en-IN-Chirp3-HD-Kore', -- Female
["en_IN_Chirp3_HD_Leda"] = 'en-IN-Chirp3-HD-Leda', -- Female
["en_IN_Chirp3_HD_Orus"] = 'en-IN-Chirp3-HD-Orus', -- Male
},
ChirpHD = {
["en_US_Chirp_HD_D"] = 'en-US-Chirp-HD-D', -- Male
["en_US_Chirp_HD_F"] = 'en-US-Chirp-HD-F', -- Female
["en_US_Chirp_HD_O"] = 'en-US-Chirp-HD-O', -- Female
-- DE
["de_DE_Chirp_HD_D"] = 'de-DE-Chirp-HD-D', -- Male
["de_DE_Chirp_HD_F"] = 'de-DE-Chirp-HD-F', -- Female
["de_DE_Chirp_HD_O"] = 'de-DE-Chirp-HD-O', -- Female
-- AU
["en_AU_Chirp_HD_D"] = 'en-AU-Chirp-HD-D', -- Male
["en_AU_Chirp_HD_F"] = 'en-AU-Chirp-HD-F', -- Female
["en_AU_Chirp_HD_O"] = 'en-AU-Chirp-HD-O', -- Female
-- IN
["en_IN_Chirp_HD_D"] = 'en-IN-Chirp-HD-D', -- Male
["en_IN_Chirp_HD_F"] = 'en-IN-Chirp-HD-F', -- Female
["en_IN_Chirp_HD_O"] = 'en-IN-Chirp-HD-O', -- Female
},
},
Neural2 = {
["en_GB_Neural2_A"] = 'en-GB-Neural2-A', -- Female
["en_GB_Neural2_B"] = 'en-GB-Neural2-B', -- Male
["en_GB_Neural2_C"] = 'en-GB-Neural2-C', -- Female
["en_GB_Neural2_D"] = 'en-GB-Neural2-D', -- Male
["en_GB_Neural2_F"] = 'en-GB-Neural2-F', -- Female
["en_GB_Neural2_N"] = 'en-GB-Neural2-N', -- Female
["en_GB_Neural2_O"] = 'en-GB-Neural2-O', -- Male
-- US
["en_US_Neural2_A"] = 'en-US-Neural2-A', -- Male
["en_US_Neural2_C"] = 'en-US-Neural2-C', -- Female
["en_US_Neural2_D"] = 'en-US-Neural2-D', -- Male
["en_US_Neural2_E"] = 'en-US-Neural2-E', -- Female
["en_US_Neural2_F"] = 'en-US-Neural2-F', -- Female
["en_US_Neural2_G"] = 'en-US-Neural2-G', -- Female
["en_US_Neural2_H"] = 'en-US-Neural2-H', -- Female
["en_US_Neural2_I"] = 'en-US-Neural2-I', -- Male
["en_US_Neural2_J"] = 'en-US-Neural2-J', -- Male
-- DE
["de_DE_Neural2_G"] = 'de-DE-Neural2-G', -- Female
["de_DE_Neural2_H"] = 'de-DE-Neural2-H', -- Male
-- AU
["en_AU_Neural2_A"] = 'en-AU-Neural2-A', -- Female
["en_AU_Neural2_B"] = 'en-AU-Neural2-B', -- Male
["en_AU_Neural2_C"] = 'en-AU-Neural2-C', -- Female
["en_AU_Neural2_D"] = 'en-AU-Neural2-D', -- Male
-- IN
["en_IN_Neural2_A"] = 'en-IN-Neural2-A', -- Female
["en_IN_Neural2_B"] = 'en-IN-Neural2-B', -- Male
["en_IN_Neural2_C"] = 'en-IN-Neural2-C', -- Male
["en_IN_Neural2_D"] = 'en-IN-Neural2-D', -- Female
},
News = {
["en_GB_News_G"] = 'en-GB-News-G', -- Female
["en_GB_News_H"] = 'en-GB-News-H', -- Female
["en_GB_News_I"] = 'en-GB-News-I', -- Female
["en_GB_News_J"] = 'en-GB-News-J', -- Male
["en_GB_News_K"] = 'en-GB-News-K', -- Male
["en_GB_News_L"] = 'en-GB-News-L', -- Male
["en_GB_News_M"] = 'en-GB-News-M', -- Male
-- US
["en_US_News_K"] = 'en-US-News-K', -- Female
["en_US_News_L"] = 'en-US-News-L', -- Female
["en_US_News_N"] = 'en-US-News-N', -- Male
-- AU
["en_AU_News_E"] = 'en-AU-News-E', -- Female
["en_AU_News_F"] = 'en-AU-News-F', -- Female
["en_AU_News_G"] = 'en-AU-News-G', -- Male
},
Casual = {
["en_US_Casual_K"] = 'en-US-Casual-K', -- Male
},
Polyglot = {
["en_US_Polyglot_1"] = 'en-US-Polyglot-1', -- Male
["de_DE_Polyglot_1"] = 'de-DE-Polyglot-1', -- Male
["en_AU_Polyglot_1"] = 'en-AU-Polyglot-1', -- Male
},
Studio = {
-- Englisch (UK) - Studio
["en_GB_Studio_B"] = 'en-GB-Studio-B', -- Male
["en_GB_Studio_C"] = 'en-GB-Studio-C', -- Female
-- Englisch (USA) - Studio
["en_US_Studio_O"] = 'en-US-Studio-O', -- Female
["en_US_Studio_Q"] = 'en-US-Studio-Q', -- Male
-- DE
["de_DE_Studio_B"] = 'de-DE-Studio-B', -- Male
["de_DE_Studio_C"] = 'de-DE-Studio-C', -- Female
}, },
} }
@@ -632,7 +770,7 @@ end
-- set the path to the exe file via @{#MSRS.SetPath}. -- set the path to the exe file via @{#MSRS.SetPath}.
-- --
-- @param #MSRS self -- @param #MSRS self
-- @param #string Path Path to SRS directory. Default `C:\\Program Files\\DCS-SimpleRadio-Standalone`. -- @param #string Path Path to SRS directory. Default `C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio`.
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. Can also be given as a #table of multiple frequencies. -- @param #number 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 Modulation Radio modulation: 0=AM (default), 1=FM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. Can also be given as a #table of multiple modulations.
-- @param #string Backend Backend used: `MSRS.Backend.SRSEXE` (default) or `MSRS.Backend.GRPC`. -- @param #string Backend Backend used: `MSRS.Backend.SRSEXE` (default) or `MSRS.Backend.GRPC`.
@@ -767,13 +905,13 @@ end
--- Set path to SRS install directory. More precisely, path to where the `DCS-SR-ExternalAudio.exe` is located. --- Set path to SRS install directory. More precisely, path to where the `DCS-SR-ExternalAudio.exe` is located.
-- @param #MSRS self -- @param #MSRS self
-- @param #string Path Path to the directory, where the sound file is located. Default is `C:\\Program Files\\DCS-SimpleRadio-Standalone`. -- @param #string Path Path to the directory, where the sound file is located. Default is `C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio`.
-- @return #MSRS self -- @return #MSRS self
function MSRS:SetPath(Path) function MSRS:SetPath(Path)
self:F( {Path=Path} ) self:F( {Path=Path} )
-- Set path. -- Set path.
self.path=Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" self.path=Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
-- Remove (back)slashes. -- Remove (back)slashes.
local n=1 ; local nmax=1000 local n=1 ; local nmax=1000
@@ -1817,7 +1955,7 @@ end
-- --
-- -- Moose MSRS default Config -- -- Moose MSRS default Config
-- MSRS_Config = { -- MSRS_Config = {
-- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- Path to SRS install directory. -- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio", -- Path to SRS install directory.
-- Port = 5002, -- Port of SRS server. Default 5002. -- Port = 5002, -- Port of SRS server. Default 5002.
-- Backend = "srsexe", -- Interface to SRS: "srsexe" or "grpc". -- Backend = "srsexe", -- Interface to SRS: "srsexe" or "grpc".
-- Frequency = {127, 243}, -- Default frequences. Must be a table 1..n entries! -- Frequency = {127, 243}, -- Default frequences. Must be a table 1..n entries!
@@ -1837,7 +1975,7 @@ end
-- -- Google Cloud -- -- Google Cloud
-- gcloud = { -- gcloud = {
-- voice = "en-GB-Standard-A", -- The Google Cloud voice to use (see https://cloud.google.com/text-to-speech/docs/voices). -- voice = "en-GB-Standard-A", -- The Google Cloud voice to use (see https://cloud.google.com/text-to-speech/docs/voices).
-- credentials="C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourfilename.json", -- Full path to credentials JSON file (only for SRS-TTS.exe backend) -- credentials="C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio\\yourfilename.json", -- Full path to credentials JSON file (only for SRS-TTS.exe backend)
-- key="Your access Key", -- Google API access key (only for DCS-gRPC backend) -- key="Your access Key", -- Google API access key (only for DCS-gRPC backend)
-- }, -- },
-- -- Amazon Web Service -- -- Amazon Web Service
@@ -1905,7 +2043,7 @@ function MSRS:LoadConfigFile(Path,Filename)
local Self = self or MSRS --#MSRS local Self = self or MSRS --#MSRS
Self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" Self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
Self.port = MSRS_Config.Port or 5002 Self.port = MSRS_Config.Port or 5002
Self.backend = MSRS_Config.Backend or MSRS.Backend.SRSEXE Self.backend = MSRS_Config.Backend or MSRS.Backend.SRSEXE
Self.frequencies = MSRS_Config.Frequency or {127,243} Self.frequencies = MSRS_Config.Frequency or {127,243}

View File

@@ -30,6 +30,8 @@
--- Governs multiple missions, the tasking and the reporting. --- Governs multiple missions, the tasking and the reporting.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- Command centers govern missions, communicates the task assignments between human players of the coalition, and manages the menu flow. -- Command centers govern missions, communicates the task assignments between human players of the coalition, and manages the menu flow.
-- It can assign a random task to a player when requested. -- It can assign a random task to a player when requested.
-- The commandcenter provides the facilitites to communicate between human players online, executing a task. -- The commandcenter provides the facilitites to communicate between human players online, executing a task.

View File

@@ -5,6 +5,8 @@
-- The @{#DETECTION_MANAGER} class defines the core functions to report detected objects to groups. -- The @{#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
-- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour. -- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- 1.1) DETECTION_MANAGER constructor: -- 1.1) DETECTION_MANAGER constructor:
-- ----------------------------------- -- -----------------------------------
-- * @{#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance. -- * @{#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.

View File

@@ -28,6 +28,8 @@
--- Models goals to be achieved and can contain multiple tasks to be executed to achieve the goals. --- Models goals to be achieved and can contain multiple tasks to be executed to achieve the goals.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- A mission contains multiple tasks and can be of different task types. -- A mission contains multiple tasks and can be of different task types.
-- These tasks need to be assigned to human players to be executed. -- These tasks need to be assigned to human players to be executed.
-- --

View File

@@ -12,6 +12,8 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- # 1) Tasking from a player perspective. -- # 1) Tasking from a player perspective.
-- --
-- Tasking can be controlled by using the "other" menu in the radio menu of the player group. -- Tasking can be controlled by using the "other" menu in the radio menu of the player group.

View File

@@ -18,6 +18,8 @@
--- ---
-- # TASKINFO class, extends @{Core.Base#BASE} -- # TASKINFO class, extends @{Core.Base#BASE}
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ## The TASKINFO class implements the methods to contain information and display information of a task. -- ## The TASKINFO class implements the methods to contain information and display information of a task.
-- --
-- # Developer Note -- # Developer Note

View File

@@ -20,6 +20,9 @@ do -- TASK_A2A
--- Defines Air To Air tasks for a @{Core.Set} of Target Units, --- Defines Air To Air tasks for a @{Core.Set} of Target Units,
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}. -- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
--
-- ![Banner Image](..\Images\deprecated.png)
--
-- The TASK_A2A is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses: -- The TASK_A2A is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
-- --
-- * **None**: Start of the process -- * **None**: Start of the process

View File

@@ -31,6 +31,8 @@ do -- TASK_A2A_DISPATCHER
--- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Core.Set} of EWR installation groups. --- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Core.Set} of EWR installation groups.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ![Banner Image](..\Presentations\TASK_A2A_DISPATCHER\Dia3.JPG) -- ![Banner Image](..\Presentations\TASK_A2A_DISPATCHER\Dia3.JPG)
-- --
-- The EWR will detect units, will group them, and will dispatch @{Tasking.Task}s to groups. Depending on the type of target detected, different tasks will be dispatched. -- The EWR will detect units, will group them, and will dispatch @{Tasking.Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.

View File

@@ -20,6 +20,9 @@ do -- TASK_A2G
--- The TASK_A2G class defines Air To Ground tasks for a @{Core.Set} of Target Units, --- The TASK_A2G class defines Air To Ground tasks for a @{Core.Set} of Target Units,
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}. -- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
--
-- ![Banner Image](..\Images\deprecated.png)
--
-- The TASK_A2G is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses: -- The TASK_A2G is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
-- --
-- * **None**: Start of the process -- * **None**: Start of the process

View File

@@ -34,6 +34,8 @@ do -- TASK_A2G_DISPATCHER
--- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Functional.Detection} object. --- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Functional.Detection} object.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- It uses the Tasking System within the MOOSE framework, which is a multi-player Tasking Orchestration system. -- It uses the Tasking System within the MOOSE framework, which is a multi-player Tasking Orchestration system.
-- It provides a truly dynamic battle environment for pilots and ground commanders to engage upon, -- It provides a truly dynamic battle environment for pilots and ground commanders to engage upon,
-- in a true co-operation environment wherein **Multiple Teams** will collaborate in Missions to **achieve a common Mission Goal**. -- in a true co-operation environment wherein **Multiple Teams** will collaborate in Missions to **achieve a common Mission Goal**.

View File

@@ -10,6 +10,8 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- ## Test Missions: -- ## Test Missions:
-- --
-- Test missions can be located on the main GITHUB site. -- Test missions can be located on the main GITHUB site.
@@ -1176,7 +1178,7 @@ do -- TASK_CARGO
end end
---@param Color Might be SMOKECOLOR.Blue, SMOKECOLOR.Red SMOKECOLOR.Orange, SMOKECOLOR.White or SMOKECOLOR.Green --@param Color Might be SMOKECOLOR.Blue, SMOKECOLOR.Red SMOKECOLOR.Orange, SMOKECOLOR.White or SMOKECOLOR.Green
function TASK_CARGO:SetSmokeColor(SmokeColor) function TASK_CARGO:SetSmokeColor(SmokeColor)
-- Makes sure Coloe is set -- Makes sure Coloe is set
if SmokeColor == nil then if SmokeColor == nil then

View File

@@ -76,6 +76,8 @@ do -- TASK_CAPTURE_DISPATCHER
--- Implements the dynamic dispatching of capture zone tasks. --- Implements the dynamic dispatching of capture zone tasks.
-- --
-- ![Banner Image](..\Images\deprecated.png)
--
-- The **TASK_CAPTURE_DISPATCHER** allows you to setup various tasks for let human -- The **TASK_CAPTURE_DISPATCHER** allows you to setup various tasks for let human
-- players capture zones in a co-operation effort. -- players capture zones in a co-operation effort.
-- --

Some files were not shown because too many files have changed in this diff Show More