Compare commits

..

238 Commits

Author SHA1 Message Date
Frank
ffc72a53ff Merge branch 'develop' into FF/OpsStuff 2023-12-05 21:02:24 +01:00
Frank
f789fbac70 Update Zone.lua
- Fixed ZONE_POLYGON:New called without initial points
2023-12-05 17:48:34 +01:00
Frank
375f12dc26 Merge branch 'develop' into FF/OpsStuff 2023-12-04 22:20:41 +01:00
Frank
bc3a5271dc Update OpsGroup.lua
- Fixed group returning to legion when told not to
2023-12-04 22:19:31 +01:00
Applevangelist
4d4b8862c2 Merge remote-tracking branch 'origin/develop' into develop 2023-12-04 10:42:26 +01:00
Applevangelist
31b75b7d17 Merge remote-tracking branch 'origin/master' into develop 2023-12-04 10:42:23 +01:00
Thomas
fac7a5fdc6 Update CTLD.lua (#2058)
Add Remove Crates option
2023-12-04 10:40:38 +01:00
Frank
cfca4fdc46 Merge branch 'develop' into FF/Ops 2023-12-03 21:09:17 +01:00
Frank
cca5a5d55d Fixes
- Fixed A/C starting on ALERT5
- Fixed nil check for DrawID in UndrawZone
2023-12-03 20:51:19 +01:00
Applevangelist
3243c92331 Merge remote-tracking branch 'origin/master' into develop 2023-12-03 15:35:17 +01:00
Applevangelist
49191fb144 clarifications 2023-12-03 15:34:55 +01:00
Applevangelist
eab37d5e48 Merge remote-tracking branch 'origin/master' into develop 2023-12-03 12:39:34 +01:00
Applevangelist
f739062463 #ZONE_OVAL - fix documentation and intellisense 2023-12-03 12:39:08 +01:00
Applevangelist
e838431b28 Merge remote-tracking branch 'origin/master' into develop 2023-12-03 12:25:51 +01:00
Applevangelist
c22304f2b0 Remove demo links which were empty 2023-12-03 12:25:25 +01:00
Applevangelist
1c10bfea92 Merge remote-tracking branch 'origin/master' into develop 2023-12-03 12:11:55 +01:00
Applevangelist
c97d2ecaba #ATIS - multi freq example added 2023-12-03 12:11:22 +01:00
Applevangelist
2dc9f19d78 Merge remote-tracking branch 'origin/master' into develop 2023-12-03 12:03:41 +01:00
Applevangelist
89a9d1d0a4 #CONTROLLABLE
* Fixed ID issue with AA Missile Attack Range option

#POINT
* Added methdo to get the BULLSEYE as coordinate
2023-12-03 12:01:50 +01:00
Applevangelist
cf7d41cd7f #ZONE_POLYGON improvements
#ZONE_OVAL NEW
2023-12-03 11:42:53 +01:00
Niels Vaes
fd191be274 Added ZONE_OVAL. (#2057)
* Added ZONE_OVAL. This can be useful for simulating the area of a view zone from an object looking down at the ground for example.

Can be constructed from a Mission Editor drawing.

* add to DB
2023-12-03 11:34:52 +01:00
Thomas
31bdde130a Update Event.lua (#2056)
Fix for playername in weapon target
2023-12-03 09:26:09 +01:00
Thomas
afe542cc63 Update Event.lua
Fix for playername in weapon target
2023-12-03 09:23:42 +01:00
Frank
494550fe91 Merge pull request #2054 from nielsvaes/moose_develop_vanilla
Update on the ZONE_POLYGON class, so we can finally use it with drawings made in the Mission Editor as well
2023-12-02 20:48:26 +01:00
Niels Vaes
29c0d81c27 Update on the ZONE_POLYGON class, so we can finally use it with drawings made in the Mission Editor as well.
Supports closed line segments, rects and freely drawn polygons.

Added the correct way of generating a point within a polygon with trial and error

Added a way to get the surface area.

Added a helper class (_ZONE_TRIANGLE), which shouldn't ever be used on its own. It's there to support the update ZONE_POLYGON.

Some test code, assuming there's a poygon drawn in the mission editor called "poly":

```Lua
-- make a new zone from a drawing
poly = ZONE_POLYGON:NewFromDrawing("poly")
-- draw the zone for everyone, include the individual triangles that make up the polygon
poly:DrawZone(-1, {1,0,0}, 1, {1,0,0}, 255, 4, false, true)
-- generate 500 random points, evenly distributed in the polygon
for i=1, 500 do
	COORDINATE:NewFromVec2(poly:GetRandomVec2()):CircleToAll(1000)
end

-- remove the drawing from the game
poly:UndrawZone()
```
2023-12-02 20:33:30 +01:00
Applevangelist
e79c2481da Merge remote-tracking branch 'origin/master' into develop 2023-12-02 15:11:35 +01:00
Applevangelist
89a902fd57 #ATIS
* make info multi-frequency safe
2023-12-02 15:11:14 +01:00
Applevangelist
460ad9db39 Merge remote-tracking branch 'origin/master' into develop 2023-12-02 14:46:04 +01:00
Applevangelist
ae604fd847 #AIRBASE
* Add'l Normandy Airfields
2023-12-02 14:45:42 +01:00
Applevangelist
099f059eec Merge remote-tracking branch 'origin/develop' into develop 2023-12-01 16:29:52 +01:00
Applevangelist
c3bba7d1fc #PLAYERRECCE
* Make the laser corridor a bit wider

#FLIGHtCONTROL
* Also create non-info when ATIS isn't set
2023-12-01 16:29:49 +01:00
Frank
db71610d72 Merge branch 'master' into develop 2023-11-30 23:29:39 +01:00
Frank
4b8d120f20 Update Warehouse.lua
- Added check that DCS warehouse has enough air assets for selfpropelled assets
2023-11-30 23:29:29 +01:00
Applevangelist
1dc31cc852 spawn 2023-11-29 18:01:37 +01:00
Applevangelist
68b97773fe #OPSZONE
* Added option to set own pikey-ish zone colors
2023-11-29 16:42:30 +01:00
Applevangelist
3c0e977584 #PLAYERRECCE
* Bug fix for clock view calculation
* Ensure lasing is switched off when using the menu
* Create SPOT more often
2023-11-28 10:37:45 +01:00
Applevangelist
f03a48b118 Merge remote-tracking branch 'origin/master' into develop 2023-11-27 16:49:56 +01:00
Applevangelist
c489a88106 #GROUP
* Get Link16 S/TN data from a group
2023-11-27 16:49:06 +01:00
Frank
a4704d0e2f Update ArmyGroup.lua 2023-11-26 23:57:21 +01:00
Applevangelist
4747dae51a Merge remote-tracking branch 'origin/master' into develop 2023-11-26 17:00:17 +01:00
Applevangelist
b1e8ba74a8 Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	Moose Development/Moose/Core/Spawn.lua
2023-11-26 16:59:57 +01:00
Applevangelist
641707f37b #UNIT
* Added `GetSTN()` to obtain Link16 info from a unit
2023-11-26 16:59:44 +01:00
Frank
7538f63c00 Merge branch 'develop' into FF/Ops 2023-11-26 16:46:13 +01:00
Applevangelist
52ed645f6c -- noise 2023-11-25 18:44:38 +01:00
Applevangelist
7c8f212b03 -- noise 2023-11-25 18:44:21 +01:00
Applevangelist
9f41cc51be Merge remote-tracking branch 'origin/master' into develop 2023-11-25 18:30:04 +01:00
Applevangelist
85c73cb0a5 #SPAWN
*Link16 fixes
* Wrongly created STN's will be replaced with random five digit octals with leading 0
* Voice call sign label will be the callsign's first and last letters, e.g. Enfield = ED. Navy One = NY
* Voice call sign number equals callsign minor major, e.g. Enfield 6-1 = ED 61
* Also works for A10CII which has a different entry with a four-digit octal with leading 0
* for fighter aircraft you can use :InitRandomizeCallsign() to give each spawn a random callsign
2023-11-25 18:28:59 +01:00
Applevangelist
6390b223b0 Merge remote-tracking branch 'origin/master' into develop 2023-11-24 12:17:56 +01:00
Applevangelist
b635490e47 SPAWN - Init Link16/datalink details in UNITs 2023-11-24 12:17:25 +01:00
Thomas
62e8302753 Update SRS.lua (#2047)
Fix for config load when not desanitized
2023-11-24 06:35:32 +01:00
Thomas
cac7b39823 Update SRS.lua
Fix for config load when not desanitized
2023-11-24 06:32:44 +01:00
Frank
bfaf88f017 Merge branch 'develop' into FF/Ops 2023-11-23 22:23:50 +01:00
Frank
cc79dc74d4 Merge branch 'master' into develop 2023-11-23 22:23:17 +01:00
Frank
427a11bd0f Merge pull request #2046 from nielsvaes/moose_master_vanilla
bugfix for impactHeading
2023-11-23 22:11:59 +01:00
Niels Vaes
6f3133d48c bugfix for impactHeading
clamping GetImpactHeading and GetReleaseHeading
2023-11-23 21:50:08 +01:00
Applevangelist
4f4e8b17c1 Merge remote-tracking branch 'origin/master' into develop 2023-11-23 18:46:03 +01:00
Applevangelist
aa7f26ac79 ATC_GROUND fix for scheduler 2023-11-23 18:45:36 +01:00
Applevangelist
0850796368 Merge remote-tracking branch 'origin/master' into develop 2023-11-23 18:15:01 +01:00
Applevangelist
343bf05c2c SPAWN - Set correct unit ID in the group callsign 2023-11-23 18:14:25 +01:00
Applevangelist
ff58649954 Merge remote-tracking branch 'origin/master' into develop 2023-11-23 17:02:20 +01:00
Applevangelist
bbf793febe #CLIENTMENU 2023-11-23 17:01:33 +01:00
Applevangelist
3e40d72e25 #ATC_GROUND 2023-11-23 17:00:58 +01:00
Frank
1c1daa4ebe Merge pull request #2045 from nielsvaes/moose_master_vanilla
Adding a bunch of various helper functions to UTILS
2023-11-23 16:16:05 +01:00
Niels Vaes
fdcda6e5f3 typos 2023-11-23 15:22:14 +01:00
Niels Vaes
a50dde7f2b added functions:
UTILS.TimeNow
UTILS.TimeDifferenceInSeconds
UTILS.TimeLaterThan
UTILS.TimeBefore
UTILS.CombineTimeStrings
UTILS.SubtractTimeStrings
UTILS.TimeBetween
UTILS.PercentageChance
UTILS.Clamp
UTILS.ClampAngle
UTILS.RemapValue
UTILS.RandomPointInTriangle
UTILS.AngleBetween
UTILS.WriteJSON
UTILS.ReadJSON
UTILS.GetZoneProperties
UTILS.RotatePointAroundPivot
UTILS.UniqueName

string.startswith
string.endswith
string.split
string.contains

table.contains_key
table.remove_by_value
table.remove_key
table.index_of
table.length
table.slice
table.count_value
table.combine
table.merge
table.add
table.shuffle
table.find_key_value_pair
2023-11-23 15:18:23 +01:00
Frank
1fb4cb1c4f Merge pull request #2044 from nielsvaes/moose_master_vanilla
Added functions to get info at the time of weapon release
2023-11-23 00:31:57 +01:00
Niels Vaes
cd0f854f41 added functions:
GetReleaseHeading
GetReleaseAltitudeASL
GetReleaseCoordinate
GetReleasePitch
GetImpactHeading
2023-11-22 23:48:00 +01:00
Applevangelist
f071c674d0 fix 2023-11-22 18:35:23 +01:00
Applevangelist
02a87d9fe0 fix 2023-11-22 18:35:12 +01:00
Applevangelist
3c53f627c2 Merge remote-tracking branch 'origin/master' into develop 2023-11-22 17:57:51 +01:00
Applevangelist
12d68a41ca #MSRS
* Added option to explicitly set/switch the TTS provider between Google and MS (the default)
* Added this option to the config file, so you can set up both but switch
2023-11-22 17:54:52 +01:00
Applevangelist
2dfde7d1fd xxx 2023-11-21 13:22:51 +01:00
Applevangelist
c011d38313 Merge remote-tracking branch 'origin/master' into develop 2023-11-21 13:21:48 +01:00
Applevangelist
6c4a64601f MSRS
Docu fix
2023-11-21 13:21:22 +01:00
Applevangelist
68350d6824 Merge remote-tracking branch 'origin/master' into develop 2023-11-21 10:13:08 +01:00
Applevangelist
434f985e77 #MSRS
* Cleaner config loading strategy
2023-11-21 10:12:46 +01:00
Thomas
2e6cac7bee Update Utils.lua 2023-11-20 14:50:12 +01:00
Thomas
ba1dcfcdba Update Utils.lua
Avoid file loading stop scripts
2023-11-20 14:49:16 +01:00
Frank
b5965bbf81 Merge branch 'develop' into FF/Ops 2023-11-20 13:52:16 +01:00
Thomas
b346dabdf8 Update introduction.md (#2043) 2023-11-20 11:24:25 +01:00
kaltokri
a0429458d0 Merge branch 'master' into develop 2023-11-20 10:15:46 +01:00
kaltokri
1376a16812 Make linkinator results more stable with retry features 2023-11-20 10:15:20 +01:00
kaltokri
847dc1839f Merge branch 'master' into develop 2023-11-20 09:59:36 +01:00
kaltokri
4267314260 Merge branch 'userguide' 2023-11-20 09:59:07 +01:00
kaltokri
b5110c8554 Migration of MOOSE user guide
introduction and hello world
2023-11-20 09:56:44 +01:00
Applevangelist
0dd4da1db4 Merge remote-tracking branch 'origin/master' into develop 2023-11-19 15:36:46 +01:00
Applevangelist
1f1d1e4f2f #CTLD
* Added info event for repairs and builds starting
2023-11-19 15:36:16 +01:00
Applevangelist
4d4f8e9d61 Merge remote-tracking branch 'origin/master' into develop 2023-11-19 12:40:45 +01:00
Applevangelist
522eb8b256 #EVENT
* Handler for 2.9 new events
2023-11-19 12:40:22 +01:00
Applevangelist
6fe883a17a Merge remote-tracking branch 'origin/master' into develop 2023-11-18 17:17:05 +01:00
Applevangelist
b662ecc76b #MANTIS, SHORAD
* Added more options for ScootZones
2023-11-18 17:16:27 +01:00
Applevangelist
fbbdac9b7e Merge remote-tracking branch 'origin/master' into develop 2023-11-18 16:44:46 +01:00
Applevangelist
6dd69eb6db CTLD - avoid old mission go haywire with UnitCapabilities() 2023-11-18 16:44:23 +01:00
Applevangelist
1b6aeff005 #CTLD
* if a unit cannot do troops/crates, those menus are not shown
* renamed `UnitCapabilities()` to `SetUnitCapabilities()`
2023-11-18 16:31:10 +01:00
Applevangelist
de380614fb Merge remote-tracking branch 'origin/master' into develop 2023-11-18 13:23:58 +01:00
Applevangelist
4287774d9f EVENT fix for borked target info 2023-11-18 13:23:15 +01:00
Frank
bcbda4eb64 Merge branch 'develop' into FF/Ops 2023-11-17 18:04:49 +01:00
Applevangelist
f6fdff927b Merge remote-tracking branch 'origin/master' into develop 2023-11-17 15:07:46 +01:00
Applevangelist
58ce4b001e #PLAYERRECCE
* Fix issue which stops lasing though target is alive and in sight
2023-11-17 15:07:29 +01:00
Applevangelist
6bba2fec0b Spot 2023-11-17 15:06:52 +01:00
Applevangelist
5d2656d679 SET 2023-11-17 15:05:19 +01:00
Applevangelist
9a360a3bd5 #AWACS
* Small fix for no text on clean call
2023-11-17 12:05:14 +01:00
Applevangelist
217b8fe71e Merge remote-tracking branch 'origin/master' into develop 2023-11-17 11:05:53 +01:00
Applevangelist
65a729a2d6 Merge remote-tracking branch 'origin/master' 2023-11-17 11:05:26 +01:00
Applevangelist
7868930fcb ATIS 2023-11-17 11:05:22 +01:00
Applevangelist
67248a290c ATIS small fix 2023-11-17 11:04:33 +01:00
Thomas
32ae4986ca Update PlayerTask.lua
Weapon check for bomb runway task
2023-11-17 06:28:33 +01:00
Frank
2a0086d3fe Merge branch 'master' into develop 2023-11-17 00:26:33 +01:00
Frank
0bc52eb331 DCS stable
- Added check that ` Airbase.getWarehouse`  method exists because it causes problems with DCS stable as this method does not exist there.
2023-11-17 00:26:21 +01:00
Frank
75a6a798ac Update OpsZone.lua
- Fix for new `getCategory` behaviour
2023-11-16 22:52:13 +01:00
Frank
067285f870 Merge branch 'master' into develop 2023-11-16 22:32:17 +01:00
Frank
5353be482e getCategory behaviour
- Fixed several classes for new `getCategory` behaviour (should be backwards compatible to earlier DCS versions).
2023-11-16 22:32:01 +01:00
Applevangelist
8075be92a7 Merge remote-tracking branch 'origin/master' into develop 2023-11-16 18:11:58 +01:00
Applevangelist
826ae86cb7 #MANTIS
* Added IDF data
2023-11-16 18:11:30 +01:00
Applevangelist
f453619c78 Merge remote-tracking branch 'origin/master' into develop 2023-11-16 16:11:20 +01:00
Applevangelist
475153be4c #RANGE
* Added coalition option to `New()`
2023-11-16 16:10:47 +01:00
Applevangelist
ca20e059a6 #PLAYERRECCE
* Fixes for new Gazelle models
2023-11-16 14:08:33 +01:00
Applevangelist
2044068393 Merge remote-tracking branch 'origin/master' into develop 2023-11-15 18:17:23 +01:00
Applevangelist
5f734a0d17 #MESSAGE
* Fixes for ToSRS() for MS Desktop
2023-11-15 18:16:46 +01:00
Thomas
2c3e9e992d Update PlayerTask.lua
Bugfix
2023-11-15 07:24:01 +01:00
Applevangelist
ef27daa282 Merge remote-tracking branch 'origin/master' into develop 2023-11-14 12:15:48 +01:00
Applevangelist
1b8c9367a3 #MANTIS/#SEAD/#SHORAD
* Added shoot and scoot for MANTIS and SHORAD
* Added detection of TALD ADM-141A (all)
2023-11-14 11:57:58 +01:00
Applevangelist
e36ade55d2 Merge remote-tracking branch 'origin/master' into develop 2023-11-12 16:54:07 +01:00
Applevangelist
19047843cc #SEAD
* Added data and actions for TALD ADM_141
2023-11-12 16:53:34 +01:00
Applevangelist
2d631cba3f #AUTOLASE - Menu for smoking 2023-11-12 12:13:12 +01:00
Applevangelist
9ccfcb8fb1 Merge remote-tracking branch 'origin/develop' into develop 2023-11-11 19:02:34 +01:00
Applevangelist
a8e58b8121 #AUTOLASE
* Added menu to change the laser code
2023-11-11 19:02:26 +01:00
kaltokri
dcc968c290 Merge branch 'master' into develop 2023-11-11 16:06:52 +01:00
kaltokri
174454b8c5 Migrated Text-To-Speech guide to docs 2023-11-11 16:06:22 +01:00
kaltokri
36aa697936 Merge branch 'master' into develop 2023-11-10 16:54:58 +01:00
kaltokri
d30a53333c Migration of eclipse installation guide from wiki to docs 2023-11-10 16:53:41 +01:00
kaltokri
8bace684c2 Merge branch 'master' into develop 2023-11-10 16:23:27 +01:00
kaltokri
30b89328f1 Extension of the build documentation 2023-11-10 16:22:58 +01:00
kaltokri
aa5163fe3a Merge branch 'master' into develop 2023-11-10 15:37:20 +01:00
kaltokri
b38dc62be7 Restructure of the docs content 2023-11-10 15:36:54 +01:00
kaltokri
097e0a3214 Merge branch 'master' into develop 2023-11-10 10:52:53 +01:00
kaltokri
6d9333aa94 Added new README.md 2023-11-10 10:50:20 +01:00
kaltokri
b5c9598cb0 Merge branch 'master' into develop 2023-11-09 16:39:15 +01:00
kaltokri
6947bcfcf2 Used newest Discord link and small enhancements 2023-11-09 16:38:50 +01:00
Applevangelist
bc454fdec2 #docu changes 2023-11-09 15:16:51 +01:00
Applevangelist
166a7ab7db #DATABASE
* Register players joining CA slots as CLIENTs
2023-11-09 15:09:39 +01:00
Applevangelist
db06154ad7 #DATABASE
* Register players joining CA slots as CLIENTs
2023-11-09 15:09:01 +01:00
Applevangelist
f459372720 #CLIENTMENUMANAGER
* Added `CLIENTMENUMANAGER:InitAutoPropagation()`

#PLAYERTASK
* Some menu fixes
2023-11-09 15:08:28 +01:00
Applevangelist
f5d2439d69 Merge remote-tracking branch 'origin/master' into develop 2023-11-08 17:54:08 +01:00
Applevangelist
fa43a6c40b Symlink fix 2023-11-08 17:53:43 +01:00
Applevangelist
04c092b9ef Merge remote-tracking branch 'origin/develop' into develop 2023-11-08 17:44:12 +01:00
Applevangelist
7af920891d Merge remote-tracking branch 'origin/master' into develop 2023-11-08 17:44:08 +01:00
Applevangelist
5056187fb9 #GROUP #UNIT
* Added `FindByMatching(Pattern)` and `FindAllByMatching(Pattern)`
2023-11-08 17:43:29 +01:00
kaltokri
d9d333a7af Merge branch 'master' into develop 2023-11-08 17:39:40 +01:00
kaltokri
72c5c2ee4d Parameter has different behaviour on Windows and Linux 2023-11-08 17:39:19 +01:00
kaltokri
8f73a4c27c Merge branch 'master' into develop 2023-11-08 17:33:57 +01:00
kaltokri
25936a526d Fixed small typo in gh-pages.yml 2023-11-08 17:33:25 +01:00
kaltokri
f4b83a97a9 Merge branch 'master' into develop 2023-11-08 17:27:30 +01:00
kaltokri
8bc735288f Skip java.com when checking links. Seems to be blocked for GitHub 2023-11-08 17:27:04 +01:00
Applevangelist
3360f511ee Merge remote-tracking branch 'origin/develop' into develop 2023-11-08 17:01:57 +01:00
Applevangelist
f64ec74d1c #PLAYERRECCE
* Added doku for OnAfter.. calls
2023-11-08 17:01:50 +01:00
kaltokri
b885ef7767 Merge branch 'master' into develop 2023-11-08 16:59:31 +01:00
kaltokri
f8afa1cb78 Renamed old-guides into archive 2023-11-08 16:59:20 +01:00
kaltokri
22f5104805 Merge branch 'master' into develop 2023-11-08 16:23:47 +01:00
kaltokri
e95eb2768d Replaced absolute links with relative ones to fix problem on GitHub pages 2023-11-08 16:23:31 +01:00
kaltokri
266e34a92d Merge branch 'master' into develop 2023-11-08 13:45:53 +01:00
kaltokri
f6091cd117 Migrated old documentation to just-the-docs 2023-11-08 13:44:56 +01:00
Applevangelist
500a7f938f Merge remote-tracking branch 'origin/master' into develop 2023-11-08 11:24:00 +01:00
Applevangelist
f408c11506 Merge remote-tracking branch 'origin/develop' into develop 2023-11-08 11:23:38 +01:00
Applevangelist
9fafdea0bb #EVENT #NET
* On a MP server, added IniPlayerUCID and TgtPlayerUCID to the EventData structure (filled in applicable Events)
2023-11-08 11:23:01 +01:00
Applevangelist
b4058ecab2 #FLIGHTCONTROL
* Fix for shelters, puts the guy out front and not on top.
2023-11-08 11:09:39 +01:00
Frank
7306cc1102 Merge branch 'develop' into FF/Ops 2023-11-07 00:05:16 +01:00
Frank
21aadc14b1 Merge branch 'master' into develop 2023-11-06 22:01:26 +01:00
Frank
fbf2c4c721 Update Event.lua
- Improved getCategory behaviour
2023-11-06 22:01:05 +01:00
Applevangelist
eed6119193 #FLIGHTGROUP
* Resolve a stalemate when all jobs are done but _CheckGroupDone isn't called any longer
2023-11-06 18:36:02 +01:00
Applevangelist
6db2e333ad Merge remote-tracking branch 'origin/master' into develop 2023-11-05 13:01:59 +01:00
Applevangelist
9d3cb4cc1b #MESSAGE
* SRS label correction
2023-11-05 13:01:27 +01:00
kaltokri
0eb9dfc7de Merge branch 'master' into develop 2023-11-03 16:34:36 +01:00
kaltokri
9d500186d1 Enhancement of build-docs to remove old files 2023-11-03 16:33:45 +01:00
kaltokri
f80265786d Fix broken links SetEngageRange 2023-11-03 15:52:53 +01:00
Applevangelist
4eb0f8e9ca Merge remote-tracking branch 'origin/master' into develop 2023-11-03 13:39:02 +01:00
Applevangelist
5a583671a7 #SRS - Improvements, set also a coordinate 2023-11-03 13:38:37 +01:00
Applevangelist
7b9d8d375d #SRS Improvements 2023-11-03 13:37:59 +01:00
Frank
6406ce696b Merge branch 'develop' into FF/Ops 2023-11-02 20:31:57 +01:00
Applevangelist
e560c3ffdd Merge remote-tracking branch 'origin/master' into develop 2023-11-02 19:25:50 +01:00
Applevangelist
7393cb2cbe #ATIS
* Some fixes
2023-11-02 19:25:28 +01:00
Applevangelist
74bd41743b Merge remote-tracking branch 'origin/develop' into develop 2023-11-02 18:20:49 +01:00
Applevangelist
56d4143a05 Merge remote-tracking branch 'origin/master' into develop 2023-11-02 18:20:45 +01:00
Applevangelist
1093e55ea8 #OPSGROUP #FLIGHTCONTROL
* Added setting coordinate for SRS
2023-11-02 18:19:55 +01:00
Applevangelist
bcbe872c7d #ATIS
* Added coordinate for SRS
* Added SRS calling out take off AND landing runway (if set)
2023-11-02 18:18:55 +01:00
kaltokri
cc95c45fb0 Merge branch 'master' into develop 2023-11-02 15:16:41 +01:00
kaltokri
bf60c535bc Merge branch 'master' of github.com:FlightControl-Master/MOOSE
# Conflicts:
#	Moose Development/Moose/Tasking/Task_Cargo_CSAR.lua
2023-11-02 15:16:12 +01:00
kaltokri
feb99e9405 Fix for SetEngageRange documentation in AI_A2A and A2G classes 2023-11-02 15:14:57 +01:00
Frank
6c36910ac7 Update FlightGroup.lua
#2033
2023-11-02 01:41:39 +01:00
Frank
d60f20a162 Merge branch 'master' into develop 2023-11-02 01:40:01 +01:00
Frank
9fde88d61a Merge branch 'master' of https://github.com/FlightControl-Master/MOOSE 2023-11-02 01:39:42 +01:00
Frank
430b4a274c Update Warehouse.lua
#2033
2023-11-02 01:39:40 +01:00
Thomas
dc26134845 Merge from master (#2036)
* Update Storage.lua

* Update Storage.lua (#2035)
2023-11-01 06:21:56 +01:00
Thomas
5996426119 Update Storage.lua (#2035) 2023-11-01 06:20:36 +01:00
Thomas
36d9460cdf Update Storage.lua 2023-11-01 06:19:53 +01:00
Frank
0d9d0be0c3 Merge branch 'develop' into FF/Ops 2023-10-31 20:14:46 +01:00
Frank
adad7ef901 Merge branch 'master' into develop 2023-10-31 19:53:35 +01:00
Frank
1561f49c9c Lings
- Fixed link in Core.Condition (will add demo miz)
- Fixed lings in Task_Cargo_CSAR und Task_Cargo_Transport
2023-10-31 19:53:20 +01:00
kaltokri
bb6bb20179 Merge branch 'master' into develop 2023-10-31 16:37:19 +01:00
kaltokri
e032781a92 Changed Core.Group to Wrapper.Group 2023-10-31 16:36:51 +01:00
kaltokri
07cac604cf Merge branch 'master' into develop 2023-10-31 16:31:01 +01:00
kaltokri
aa7d0b1e25 Fixed broken links 2023-10-31 16:30:48 +01:00
kaltokri
28cb44874f Merge branch 'master' into develop 2023-10-31 16:06:06 +01:00
kaltokri
13a8babe75 Fixed broken links 2023-10-31 16:05:48 +01:00
kaltokri
616f204f5b Merge branch 'master' into develop 2023-10-31 15:44:22 +01:00
kaltokri
87dda49113 Fixed broken links 2023-10-31 15:44:07 +01:00
kaltokri
211e1b41b0 Merge branch 'master' into develop 2023-10-31 15:23:53 +01:00
kaltokri
018830b539 Merge branch 'master' of github.com:FlightControl-Master/MOOSE
# Conflicts:
#	Moose Development/Moose/AI/AI_Air_Engage.lua
2023-10-31 15:23:26 +01:00
kaltokri
d92d2d07c5 Fixed broken links 2023-10-31 15:21:15 +01:00
Frank
cd316e6719 Merge branch 'master' into develop 2023-10-31 13:44:56 +01:00
Frank
046e49ac6b Merge branch 'master' of https://github.com/FlightControl-Master/MOOSE 2023-10-31 13:35:41 +01:00
Frank
52e66ae969 Broken Links
- AI_A2A_Gci Removed reference to SetEngageZone
- Fixed link to #AI_A2G_SEAD.SetEngageRange #2025
- AI_Air_Engage removed reference to SetEngageZone. Does not seem to exist any more.
- AI_Air_Patrol removed reference to SetEngageZone. Does not seem to exist any more or is passed as argument now.
- AI_FORMATION Fixed DCSTypes#AI.Option.Air.val.ROE OptionROE #2029
- SETTINGS Fixed link to Message #2021
- Fixed wrong indent of "Developer Note" in various classes
2023-10-31 13:33:45 +01:00
kaltokri
0fb8fd8886 Merge branch 'master' into develop 2023-10-31 13:07:02 +01:00
kaltokri
ca15d7cb00 Merge branch 'master' of github.com:FlightControl-Master/MOOSE 2023-10-31 13:05:29 +01:00
kaltokri
1086c61ccf Fixed broken links 2023-10-31 13:04:48 +01:00
Frank
77f9721102 AI
- Fixed various `@extends` errors pointing to non-existing classes for AI_*
2023-10-31 11:44:45 +01:00
Frank
059d8ccfc0 Merge branch 'FF/Ops' of https://github.com/FlightControl-Master/MOOSE into FF/Ops 2023-10-31 10:45:58 +01:00
Frank
bd9022c010 ARMYGROUP
Added parameter to delay init group
2023-10-31 10:45:56 +01:00
kaltokri
261a389ca5 Merge branch 'master' into develop 2023-10-31 10:25:38 +01:00
kaltokri
b05683d384 Fixed some broken links 2023-10-31 10:25:00 +01:00
kaltokri
708838c404 Merge branch 'master' into develop 2023-10-30 18:02:27 +01:00
kaltokri
d7df08d754 Fixed broken links in documentation 2023-10-30 18:01:57 +01:00
kaltokri
974a56b135 Merge branch 'master' into develop 2023-10-30 14:56:32 +01:00
kaltokri
92b21aa5c1 Fixed broken links in documentation 2023-10-30 14:48:49 +01:00
kaltokri
85c551cc59 Merge branch 'master' into develop 2023-10-29 23:06:31 +01:00
kaltokri
0e2dff4e6b Fixed some dead links in Ops.Airboss 2023-10-29 23:06:09 +01:00
kaltokri
f33ccee7b1 Merge branch 'master' into develop 2023-10-29 19:44:24 +01:00
kaltokri
5c9e3570e2 Added more docker jobs and apply same naming convention as build jobs 2023-10-29 19:43:55 +01:00
Applevangelist
7277221905 Merge remote-tracking branch 'origin/master' into develop 2023-10-29 17:45:23 +01:00
Applevangelist
497ac367ba #CTLD
* Adding re-packing dropped units
2023-10-29 17:45:02 +01:00
Applevangelist
51102e47ae #CTLD
* Adding re-packing dropped units
2023-10-29 17:44:31 +01:00
Xavier V
92e2414612 Added pack crates (#2019) 2023-10-29 17:29:01 +01:00
kaltokri
3ca4898860 Merge branch 'master' into develop 2023-10-27 17:49:14 +02:00
kaltokri
7643568706 Fixed dead links in documentation 2023-10-27 17:48:41 +02:00
kaltokri
e4d6e6d80e Merge branch 'master' into develop 2023-10-27 17:28:19 +02:00
kaltokri
3684a023da Fixed dead link 2023-10-27 17:27:38 +02:00
kaltokri
99ebebe13c Merge branch 'master' into develop 2023-10-27 17:05:11 +02:00
kaltokri
b0c8f05f38 Build optimization
- Remove appveyor
- Added docker compose for building docs locally
- Added manuall run of GitHub Action builds
- Added paths to trigger builds
2023-10-27 17:01:51 +02:00
306 changed files with 7815 additions and 1617 deletions

View File

@@ -1,87 +0,0 @@
version: 2.4.a.{build}
shallow_clone: true
skip_branch_with_pr: false
skip_commits:
message: /!nobuild/
skip_tags: false
environment:
access_token_documentation:
secure: JVBVVL8uJUcLXN+48eRdELEeCGOGCCaMzCqutsUqNuaZ/KblG5ZTt7+LV4UKv/0f
LUAROCKS_VER: 2.4.1
LUA_VER: 5.1.5
LUA: lua5.3
matrix:
- LUA_VER: 5.1.5
platform:
- x64
init:
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
throw "There are newer queued builds for this pull request, failing early." }
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
install:
- cmd:
# Outcomment if lua environment invalidates and needs to be reinstalled, otherwise all will run from the cache.
call choco install 7zip.commandline
call choco install lua51
call choco install luarocks
call refreshenv
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
cmd: PATH = %PATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\bin
cmd: set LUA_PATH = %LUA_PATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\share\lua\5.1\?.lua;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\share\lua\5.1\?\init.lua
cmd: set LUA_CPATH = %LUA_CPATH%;C:\ProgramData\chocolatey\lib\luarocks\luarocks-2.4.3-win32\systree\lib\lua\5.1\?.dll
call luarocks install luasrcdiet
call luarocks install checks
call luarocks install luadocumentor
call luarocks install luacheck
cache:
C:\ProgramData\chocolatey\lib
C:\ProgramData\chocolatey\bin
build_script:
- ps: |
if( $env:appveyor_repo_branch -eq 'master' -or $env:appveyor_repo_branch -eq 'develop' )
{
echo "Hello World!"
$apiUrl = 'https://ci.appveyor.com/api'
$token = 'v2.6hcv3ige78kg3yvg4ge8'
$headers = @{
"Authorization" = "Bearer $token"
"Content-type" = "application/json"
}
$RequestBody = @{ accountName = 'FlightControl-Master'; projectSlug = 'moose-include'; branch = "$env:appveyor_repo_branch"; environmentVariables = @{} } | ConvertTo-Json
# Generate the new version ...
$project = Invoke-RestMethod -method Post -Uri "$apiUrl/builds" -Headers $headers -Body $RequestBody
}
- ps: |
if( $env:appveyor_repo_branch -eq 'master' -or $env:appveyor_repo_branch -eq 'develop' )
{
$apiUrl = 'https://ci.appveyor.com/api'
$token = 'v2.6hcv3ige78kg3yvg4ge8'
$headers = @{
"Authorization" = "Bearer $token"
"Content-type" = "application/json"
}
$RequestBody = @{ accountName = 'FlightControl-Master'; projectSlug = 'moose-docs'; branch = "$env:appveyor_repo_branch"; environmentVariables = @{} } | ConvertTo-Json
# get project with last build details
$project = Invoke-RestMethod -method Post -Uri "$apiUrl/builds" -Headers $headers -Body $RequestBody
}
test: off
# test_script:
# - cmd: luacheck "Moose Development\Moose\moose.lua" "Moose Mission Setup\moose.lua"
on_finish:
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))

4
.gitattributes vendored
View File

@@ -15,3 +15,7 @@
*.PDF diff=astextplain *.PDF diff=astextplain
*.rtf diff=astextplain *.rtf diff=astextplain
*.RTF diff=astextplain *.RTF diff=astextplain
# Avoid Windows line endings on shell scripts
# Needed for dockerfile builds
*.sh text eol=lf

View File

@@ -5,6 +5,15 @@ on:
branches: branches:
- master - master
- develop - develop
paths:
- 'Moose Setup/**/*.lua'
- 'Moose Development/**/*.lua'
- 'Moose Development/**/*.py'
- 'Moose Development/**/*.html'
- '.github/workflows/build-docs.yml'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs: jobs:
Build: Build:

View File

@@ -5,6 +5,13 @@ on:
branches: branches:
- master - master
- develop - develop
paths:
- 'Moose Setup/**/*.lua'
- 'Moose Development/**/*.lua'
- '.github/workflows/build-includes.yml'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs: jobs:
Build: Build:

View File

@@ -11,7 +11,7 @@ on:
branches: ["master"] branches: ["master"]
paths: paths:
- 'docs/**' - 'docs/**'
- '.github/workflows/pages.yml' - '.github/workflows/gh-pages.yml'
# Allows you to run this workflow manually from the Actions tab # Allows you to run this workflow manually from the Actions tab
workflow_dispatch: workflow_dispatch:
@@ -75,4 +75,4 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
- run: npm install linkinator - run: npm install linkinator
- run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --recurse - run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --verbosity error --timeout 5000 --recurse --skip "(java.com)" --retry-errors --retry-errors-count 3 --retry-errors-jitter

2
.gitignore vendored
View File

@@ -42,6 +42,8 @@ local.properties
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
.vscode
# User-specific files # User-specific files
*.suo *.suo
*.user *.user

View File

@@ -91,12 +91,12 @@
-- An optional @{Core.Zone} can be set, -- An optional @{Core.Zone} can be set,
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{#AI_A2A_CAP.SetEngageZone}() to define that Zone. -- Use the method @{#AI_A2A_CAP.SetEngageZone}() to define that Zone.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_A2A_CAP -- @field #AI_A2A_CAP
@@ -123,7 +123,7 @@ function AI_A2A_CAP:New2( AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAlti
-- Multiple inheritance ... :-) -- Multiple inheritance ... :-)
local AI_Air = AI_AIR:New( AICap ) local AI_Air = AI_AIR:New( AICap )
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType ) local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
local self = BASE:Inherit( self, AI_Air_Engage ) --#AI_A2A_CAP local self = BASE:Inherit( self, AI_Air_Engage ) --#AI_A2A_CAP

View File

@@ -176,12 +176,12 @@
-- Per one, two, three, four? -- Per one, two, three, four?
-- --
-- **The default grouping is 1. That means, that each spawned defender will act individually.** -- **The default grouping is 1. That means, that each spawned defender will act individually.**
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- ### Authors: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons). -- ### Authors: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons).
@@ -310,7 +310,7 @@ do -- AI_A2A_DISPATCHER
-- Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to set a specific Engage Radius. -- Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to set a specific Engage Radius.
-- **The Engage Radius is defined for ALL squadrons which are operational.** -- **The Engage Radius is defined for ALL squadrons which are operational.**
-- --
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/release-2-2-pre/AID%20-%20AI%20Dispatching/AID-019%20-%20AI_A2A%20-%20Engage%20Range%20Test) -- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-019%20-%20Engage%20Range%20Test)
-- --
-- In this example an Engage Radius is set to various values. -- In this example an Engage Radius is set to various values.
-- --
@@ -333,7 +333,7 @@ do -- AI_A2A_DISPATCHER
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius. -- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.** -- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
-- --
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/release-2-2-pre/AID%20-%20AI%20Dispatching/AID-013%20-%20AI_A2A%20-%20Intercept%20Test) -- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-013%20-%20Intercept%20Test)
-- --
-- In these examples, the Gci Radius is set to various values: -- In these examples, the Gci Radius is set to various values:
-- --
@@ -366,7 +366,7 @@ do -- AI_A2A_DISPATCHER
-- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. -- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are.
-- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. -- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition.
-- --
-- Demonstration Mission: [AID-009 - AI_A2A - Border Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/release-2-2-pre/AID%20-%20AI%20Dispatching/AID-009 - AI_A2A - Border Test) -- Demonstration Mission: [AID-009 - AI_A2A - Border Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-009%20-%20Border%20Test)
-- --
-- In this example a border is set for the CCCP A2A dispatcher: -- In this example a border is set for the CCCP A2A dispatcher:
-- --
@@ -1233,7 +1233,7 @@ do -- AI_A2A_DISPATCHER
-- --
-- **Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to modify the default Engage Radius for ALL squadrons.** -- **Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to modify the default Engage Radius for ALL squadrons.**
-- --
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/release-2-2-pre/AID%20-%20AI%20Dispatching/AID-019%20-%20AI_A2A%20-%20Engage%20Range%20Test) -- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-019%20-%20Engage%20Range%20Test)
-- --
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param #number EngageRadius (Optional, Default = 100000) The radius to report friendlies near the target. -- @param #number EngageRadius (Optional, Default = 100000) The radius to report friendlies near the target.
@@ -1283,7 +1283,7 @@ do -- AI_A2A_DISPATCHER
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius. -- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.** -- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
-- --
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/release-2-2-pre/AID%20-%20AI%20Dispatching/AID-013%20-%20AI_A2A%20-%20Intercept%20Test) -- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-013%20-%20Intercept%20Test)
-- --
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param #number GciRadius (Optional, Default = 200000) The radius to ground control intercept detected targets from the nearest airbase. -- @param #number GciRadius (Optional, Default = 200000) The radius to ground control intercept detected targets from the nearest airbase.

View File

@@ -14,47 +14,31 @@
--- @type AI_A2A_GCI --- @type AI_A2A_GCI
-- @extends AI.AI_A2A#AI_A2A -- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
--- 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.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia3.JPG)
--
-- 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.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia4.JPG)
--
-- 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.
-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. -- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia5.JPG)
--
-- This cycle will continue. -- This cycle will continue.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia6.JPG)
--
-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. -- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia9.JPG)
--
-- When enemies are detected, the AI will automatically engage the enemy. -- When enemies are detected, the AI will automatically engage the enemy.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia10.JPG)
--
-- Until a fuel or damage threshold has been reached by the AI, or when the AI is commanded to RTB. -- Until a fuel or damage threshold has been reached by the AI, or when the AI is commanded to RTB.
-- When the fuel threshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. -- When the fuel threshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia13.JPG)
--
-- ## 1. AI_A2A_GCI constructor -- ## 1. AI_A2A_GCI constructor
-- --
-- * @{#AI_A2A_GCI.New}(): Creates a new AI_A2A_GCI object. -- * @{#AI_A2A_GCI.New}(): Creates a new AI_A2A_GCI object.
-- --
-- ## 2. AI_A2A_GCI is a FSM -- ## 2. AI_A2A_GCI is a FSM
-- --
-- ![Process](..\Presentations\AI_GCI\Dia2.JPG)
--
-- ### 2.1 AI_A2A_GCI States -- ### 2.1 AI_A2A_GCI States
-- --
-- * **None** ( Group ): The process is not started yet. -- * **None** ( Group ): The process is not started yet.
@@ -75,29 +59,11 @@
-- * **@{#AI_A2A_GCI.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task. -- * **@{#AI_A2A_GCI.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the thresholds have been reached, the AI will RTB. -- * **Status** ( Group ): The AI is checking status (fuel and damage). When the thresholds have been reached, the AI will RTB.
-- --
-- ## 3. Set the Range of Engagement -- # Developer Note
-- --
-- ![Range](..\Presentations\AI_GCI\Dia11.JPG) -- 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
-- --
-- An optional range can be set in meters,
-- that will define when the AI will engage with the detected airborne enemy targets.
-- The range can be beyond or smaller than the range of the Patrol Zone.
-- The range is applied at the position of the AI.
-- Use the method @{AI.AI_GCI#AI_A2A_GCI.SetEngageRange}() to define that range.
--
-- ## 4. Set the Zone of Engagement
--
-- ![Zone](..\Presentations\AI_GCI\Dia12.JPG)
--
-- An optional @{Core.Zone} can be set,
-- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageZone}() to define that Zone.
--
-- # Developer Note
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated
--
-- === -- ===
-- --
-- @field #AI_A2A_GCI -- @field #AI_A2A_GCI

View File

@@ -11,7 +11,7 @@
--- @type AI_A2A_PATROL --- @type AI_A2A_PATROL
-- @extends AI.AI_A2A#AI_A2A -- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
--- 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}.
-- --
@@ -111,12 +111,12 @@
-- When the AI is damaged, it is required that a new Patrol is started. However, damage cannon be foreseen early on. -- When the AI is damaged, it is required that a new Patrol is started. However, damage cannon be foreseen early on.
-- Therefore, when the damage threshold is reached, the AI will return immediately to the home base (RTB). -- Therefore, when the damage threshold is reached, the AI will return immediately to the home base (RTB).
-- Use the method @{#AI_A2A_PATROL.ManageDamage}() to have this proces in place. -- Use the method @{#AI_A2A_PATROL.ManageDamage}() to have this proces in place.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_A2A_PATROL -- @field #AI_A2A_PATROL

View File

@@ -12,15 +12,16 @@
-- @image AI_Air_To_Ground_Engage.JPG -- @image AI_Air_To_Ground_Engage.JPG
--- @type AI_A2G_BAI --- @type AI_A2G_BAI
-- @extends AI.AI_A2A_Engage#AI_A2A_Engage -- TODO: Documentation. This class does not exist, unable to determine what it extends. -- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
--- 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.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_A2G_BAI -- @field #AI_A2G_BAI
@@ -46,7 +47,7 @@ AI_A2G_BAI = {
function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
local AI_Air = AI_AIR:New( AIGroup ) local AI_Air = AI_AIR:New( AIGroup )
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType ) local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
local self = BASE:Inherit( self, AI_Air_Engage ) local self = BASE:Inherit( self, AI_Air_Engage )

View File

@@ -12,15 +12,16 @@
-- @image AI_Air_To_Ground_Engage.JPG -- @image AI_Air_To_Ground_Engage.JPG
--- @type AI_A2G_CAS --- @type AI_A2G_CAS
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL TODO: Documentation. This class does not exist, unable to determine what it extends. -- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
--- 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.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_A2G_CAS -- @field #AI_A2G_CAS
@@ -46,7 +47,7 @@ AI_A2G_CAS = {
function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
local AI_Air = AI_AIR:New( AIGroup ) local AI_Air = AI_AIR:New( AIGroup )
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType ) local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
local self = BASE:Inherit( self, AI_Air_Engage ) local self = BASE:Inherit( self, AI_Air_Engage )

View File

@@ -253,12 +253,12 @@
-- --
-- **The default grouping is 1. That means, that each spawned defender will act individually.** -- **The default grouping is 1. That means, that each spawned defender will act individually.**
-- But you can specify a number between 1 and 4, so that the defenders will act as a group. -- But you can specify a number between 1 and 4, so that the defenders will act as a group.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- ### Author: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons). -- ### Author: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons).
@@ -296,8 +296,6 @@ do -- AI_A2G_DISPATCHER
-- --
-- ## 1. AI\_A2G\_DISPATCHER constructor: -- ## 1. AI\_A2G\_DISPATCHER constructor:
-- --
-- ![Banner Image](..\Presentations\AI_A2G_DISPATCHER\AI_A2G_DISPATCHER-ME_1.JPG)
--
-- --
-- The @{#AI_A2G_DISPATCHER.New}() method creates a new AI_A2G_DISPATCHER instance. -- The @{#AI_A2G_DISPATCHER.New}() method creates a new AI_A2G_DISPATCHER instance.
-- --
@@ -311,8 +309,6 @@ do -- AI_A2G_DISPATCHER
-- A reconnaissance network, is used to detect enemy ground targets, -- A reconnaissance network, is used to detect enemy ground targets,
-- potentially group them into areas, and to understand the position, level of threat of the enemy. -- potentially group them into areas, and to understand the position, level of threat of the enemy.
-- --
-- ![Banner Image](..\Presentations\AI_A2G_DISPATCHER\Dia5.JPG)
--
-- As explained in the introduction, depending on the type of mission you want to achieve, different types of units can be applied to detect ground enemy targets. -- As explained in the introduction, depending on the type of mission you want to achieve, different types of units can be applied to detect ground enemy targets.
-- Ground based units are very useful to act as a reconnaissance, but they lack sometimes the visibility to detect targets at greater range. -- Ground based units are very useful to act as a reconnaissance, but they lack sometimes the visibility to detect targets at greater range.
-- Recce are very useful to acquire the position of enemy ground targets when spread out over the battlefield at strategic positions. -- Recce are very useful to acquire the position of enemy ground targets when spread out over the battlefield at strategic positions.
@@ -686,8 +682,6 @@ do -- AI_A2G_DISPATCHER
-- --
-- Use the method @{#AI_A2G_DISPATCHER.SetSquadronGrouping}() to set the grouping of aircraft when spawned in. -- Use the method @{#AI_A2G_DISPATCHER.SetSquadronGrouping}() to set the grouping of aircraft when spawned in.
-- --
-- ![Banner Image](..\Presentations\AI_A2G_DISPATCHER\Dia12.JPG)
--
-- In the case of **on call** engagement, the @{#AI_A2G_DISPATCHER.SetSquadronGrouping}() method has additional behaviour. -- In the case of **on call** engagement, the @{#AI_A2G_DISPATCHER.SetSquadronGrouping}() method has additional behaviour.
-- When there aren't enough patrol flights airborne, a on call will be initiated for the remaining -- When there aren't enough patrol flights airborne, a on call will be initiated for the remaining
-- targets to be engaged. Depending on the grouping parameter, the spawned flights for on call aircraft are grouped into this setting. -- targets to be engaged. Depending on the grouping parameter, the spawned flights for on call aircraft are grouped into this setting.
@@ -701,8 +695,6 @@ do -- AI_A2G_DISPATCHER
-- The effectiveness can be set with the **overhead parameter**. This is a number that is used to calculate the amount of Units that dispatching command will allocate to GCI in surplus of detected amount of units. -- The effectiveness can be set with the **overhead parameter**. This is a number that is used to calculate the amount of Units that dispatching command will allocate to GCI in surplus of detected amount of units.
-- The **default value** of the overhead parameter is 1.0, which means **equal balance**. -- The **default value** of the overhead parameter is 1.0, which means **equal balance**.
-- --
-- ![Banner Image](..\Presentations\AI_A2G_DISPATCHER\Dia11.JPG)
--
-- However, depending on the (type of) aircraft (strength and payload) in the squadron and the amount of resources available, this parameter can be changed. -- However, depending on the (type of) aircraft (strength and payload) in the squadron and the amount of resources available, this parameter can be changed.
-- --
-- The @{#AI_A2G_DISPATCHER.SetSquadronOverhead}() method can be used to tweak the defense strength, -- The @{#AI_A2G_DISPATCHER.SetSquadronOverhead}() method can be used to tweak the defense strength,
@@ -848,8 +840,6 @@ do -- AI_A2G_DISPATCHER
-- --
-- For example, the following setup will set the default refuel tanker to "Tanker": -- For example, the following setup will set the default refuel tanker to "Tanker":
-- --
-- ![Banner Image](..\Presentations\AI_A2G_DISPATCHER\AI_A2G_DISPATCHER-ME_11.JPG)
--
-- -- Set the default tanker for refuelling to "Tanker", when the default fuel threshold has reached 90% fuel left. -- -- Set the default tanker for refuelling to "Tanker", when the default fuel threshold has reached 90% fuel left.
-- A2GDispatcher:SetDefaultFuelThreshold( 0.9 ) -- A2GDispatcher:SetDefaultFuelThreshold( 0.9 )
-- A2GDispatcher:SetDefaultTanker( "Tanker" ) -- A2GDispatcher:SetDefaultTanker( "Tanker" )

View File

@@ -14,66 +14,43 @@
--- @type AI_A2G_SEAD --- @type AI_A2G_SEAD
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL -- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
--- 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.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia3.JPG)
--
-- 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.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia4.JPG)
--
-- 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.
-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. -- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia5.JPG)
--
-- This cycle will continue. -- This cycle will continue.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia6.JPG)
--
-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. -- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
--
-- ![Process](..\Presentations\AI_GCI\Dia9.JPG)
-- --
-- When enemies are detected, the AI will automatically engage the enemy. -- When enemies are detected, the AI will automatically engage the enemy.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia10.JPG)
--
-- Until a fuel or damage threshold has been reached by the AI, or when the AI is commanded to RTB. -- Until a fuel or damage threshold has been reached by the AI, or when the AI is commanded to RTB.
-- When the fuel threshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. -- When the fuel threshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia13.JPG)
--
-- ## 1. AI_A2G_SEAD constructor -- ## 1. AI_A2G_SEAD constructor
-- --
-- * @{#AI_A2G_SEAD.New}(): Creates a new AI_A2G_SEAD object. -- * @{#AI_A2G_SEAD.New}(): Creates a new AI_A2G_SEAD object.
-- --
-- ## 3. Set the Range of Engagement -- ## 3. Set the Range of Engagement
-- --
-- ![Range](..\Presentations\AI_GCI\Dia11.JPG)
--
-- An optional range can be set in meters, -- An optional range can be set in meters,
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- The range can be beyond or smaller than the range of the Patrol Zone. -- The range can be beyond or smaller than the range of the Patrol Zone.
-- The range is applied at the position of the AI. -- The range is applied at the position of the AI.
-- Use the method @{AI.AI_GCI#AI_A2G_SEAD.SetEngageRange}() to define that range. -- Use the method @{#AI_AIR_PATROL.SetEngageRange}() to define that range.
-- --
-- ## 4. Set the Zone of Engagement -- # Developer Note
-- --
-- ![Zone](..\Presentations\AI_GCI\Dia12.JPG) -- 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
-- An optional @{Core.Zone} can be set, --
-- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageZone}() to define that Zone. -- TODO: Documentation. Check that this is actually correct. The originally referenced class does not exist.
--
-- # Developer Note
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated
--
-- === -- ===
-- --
-- @field #AI_A2G_SEAD -- @field #AI_A2G_SEAD
@@ -99,7 +76,7 @@ AI_A2G_SEAD = {
function AI_A2G_SEAD:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) function AI_A2G_SEAD:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
local AI_Air = AI_AIR:New( AIGroup ) local AI_Air = AI_AIR:New( AIGroup )
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType ) local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
local self = BASE:Inherit( self, AI_Air_Engage ) local self = BASE:Inherit( self, AI_Air_Engage )

View File

@@ -45,12 +45,12 @@
-- * **Start**: Start the transport process. -- * **Start**: Start the transport process.
-- * **Stop**: Stop the transport process. -- * **Stop**: Stop the transport process.
-- * **Monitor**: Monitor and take action. -- * **Monitor**: Monitor and take action.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #AI_AIR -- @field #AI_AIR
AI_AIR = { AI_AIR = {
ClassName = "AI_AIR", ClassName = "AI_AIR",

View File

@@ -292,8 +292,6 @@ do -- AI_AIR_DISPATCHER
-- --
-- ## 1. AI\_AIR\_DISPATCHER constructor: -- ## 1. AI\_AIR\_DISPATCHER constructor:
-- --
-- ![Banner Image](..\Presentations\AI_AIR_DISPATCHER\AI_AIR_DISPATCHER-ME_1.JPG)
--
-- --
-- The @{#AI_AIR_DISPATCHER.New}() method creates a new AI_AIR_DISPATCHER instance. -- The @{#AI_AIR_DISPATCHER.New}() method creates a new AI_AIR_DISPATCHER instance.
-- --
@@ -306,8 +304,6 @@ do -- AI_AIR_DISPATCHER
-- A reconnaissance network, is used to detect enemy ground targets, -- A reconnaissance network, is used to detect enemy ground targets,
-- potentially group them into areas, and to understand the position, level of threat of the enemy. -- potentially group them into areas, and to understand the position, level of threat of the enemy.
-- --
-- ![Banner Image](..\Presentations\AI_AIR_DISPATCHER\Dia5.JPG)
--
-- As explained in the introduction, depending on the type of mission you want to achieve, different types of units can be applied to detect ground enemy targets. -- As explained in the introduction, depending on the type of mission you want to achieve, different types of units can be applied to detect ground enemy targets.
-- Ground based units are very useful to act as a reconnaissance, but they lack sometimes the visibility to detect targets at greater range. -- Ground based units are very useful to act as a reconnaissance, but they lack sometimes the visibility to detect targets at greater range.
-- Recce are very useful to acquire the position of enemy ground targets when spread out over the battlefield at strategic positions. -- Recce are very useful to acquire the position of enemy ground targets when spread out over the battlefield at strategic positions.
@@ -673,8 +669,6 @@ do -- AI_AIR_DISPATCHER
-- --
-- Use the method @{#AI_AIR_DISPATCHER.SetSquadronGrouping}() to set the grouping of aircraft when spawned in. -- Use the method @{#AI_AIR_DISPATCHER.SetSquadronGrouping}() to set the grouping of aircraft when spawned in.
-- --
-- ![Banner Image](..\Presentations\AI_AIR_DISPATCHER\Dia12.JPG)
--
-- In the case of **on call** engagement, the @{#AI_AIR_DISPATCHER.SetSquadronGrouping}() method has additional behaviour. -- In the case of **on call** engagement, the @{#AI_AIR_DISPATCHER.SetSquadronGrouping}() method has additional behaviour.
-- When there aren't enough patrol flights airborne, a on call will be initiated for the remaining -- When there aren't enough patrol flights airborne, a on call will be initiated for the remaining
-- targets to be engaged. Depending on the grouping parameter, the spawned flights for on call aircraft are grouped into this setting. -- targets to be engaged. Depending on the grouping parameter, the spawned flights for on call aircraft are grouped into this setting.
@@ -688,8 +682,6 @@ do -- AI_AIR_DISPATCHER
-- The effectiveness can be set with the **overhead parameter**. This is a number that is used to calculate the amount of Units that dispatching command will allocate to GCI in surplus of detected amount of units. -- The effectiveness can be set with the **overhead parameter**. This is a number that is used to calculate the amount of Units that dispatching command will allocate to GCI in surplus of detected amount of units.
-- The **default value** of the overhead parameter is 1.0, which means **equal balance**. -- The **default value** of the overhead parameter is 1.0, which means **equal balance**.
-- --
-- ![Banner Image](..\Presentations\AI_AIR_DISPATCHER\Dia11.JPG)
--
-- However, depending on the (type of) aircraft (strength and payload) in the squadron and the amount of resources available, this parameter can be changed. -- However, depending on the (type of) aircraft (strength and payload) in the squadron and the amount of resources available, this parameter can be changed.
-- --
-- The @{#AI_AIR_DISPATCHER.SetSquadronOverhead}() method can be used to tweak the defense strength, -- The @{#AI_AIR_DISPATCHER.SetSquadronOverhead}() method can be used to tweak the defense strength,
@@ -835,8 +827,6 @@ do -- AI_AIR_DISPATCHER
-- --
-- For example, the following setup will set the default refuel tanker to "Tanker": -- For example, the following setup will set the default refuel tanker to "Tanker":
-- --
-- ![Banner Image](..\Presentations\AI_AIR_DISPATCHER\AI_AIR_DISPATCHER-ME_11.JPG)
--
-- -- Define the CAP -- -- Define the CAP
-- A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-34" }, 20 ) -- A2ADispatcher:SetSquadron( "Sochi", AIRBASE.Caucasus.Sochi_Adler, { "SQ CCCP SU-34" }, 20 )
-- A2ADispatcher:SetSquadronCap( "Sochi", ZONE:New( "PatrolZone" ), 4000, 8000, 600, 800, 1000, 1300 ) -- A2ADispatcher:SetSquadronCap( "Sochi", ZONE:New( "PatrolZone" ), 4000, 8000, 600, 800, 1000, 1300 )

View File

@@ -14,58 +14,32 @@
--- @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.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia3.JPG)
--
-- 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.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia4.JPG)
--
-- 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.
-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. -- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia5.JPG)
--
-- This cycle will continue. -- This cycle will continue.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia6.JPG)
--
-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. -- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
--
-- ![Process](..\Presentations\AI_GCI\Dia9.JPG)
-- --
-- When enemies are detected, the AI will automatically engage the enemy. -- When enemies are detected, the AI will automatically engage the enemy.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia10.JPG)
--
-- Until a fuel or damage threshold has been reached by the AI, or when the AI is commanded to RTB. -- Until a fuel or damage threshold has been reached by the AI, or when the AI is commanded to RTB.
-- When the fuel threshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. -- When the fuel threshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia13.JPG)
--
-- ## 1. AI_AIR_ENGAGE constructor -- ## 1. AI_AIR_ENGAGE constructor
-- --
-- * @{#AI_AIR_ENGAGE.New}(): Creates a new AI_AIR_ENGAGE object. -- * @{#AI_AIR_ENGAGE.New}(): Creates a new AI_AIR_ENGAGE object.
-- --
-- ## 3. Set the Range of Engagement -- ## 2. Set the Zone of Engagement
--
-- ![Range](..\Presentations\AI_GCI\Dia11.JPG)
--
-- An optional range can be set in meters,
-- that will define when the AI will engage with the detected airborne enemy targets.
-- The range can be beyond or smaller than the range of the Patrol Zone.
-- The range is applied at the position of the AI.
-- Use the method @{AI.AI_GCI#AI_AIR_ENGAGE.SetEngageRange}() to define that range.
-- --
-- ## 4. Set the Zone of Engagement -- An optional @{Core.Zone} can be set,
--
-- ![Zone](..\Presentations\AI_GCI\Dia12.JPG)
--
-- An optional @{Core.Zone} can be set,
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{AI.AI_CAP#AI_AIR_ENGAGE.SetEngageZone}() to define that Zone. -- Use the method @{AI.AI_CAP#AI_AIR_ENGAGE.SetEngageZone}() to define that Zone.
-- --
@@ -74,6 +48,11 @@
-- 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
-- --
-- # Developer Note
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated
--
-- === -- ===
-- --
-- @field #AI_AIR_ENGAGE -- @field #AI_AIR_ENGAGE
@@ -456,12 +435,12 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
-- TODO: A factor of * 3 is way too close. This causes the AI not to engange until merged sometimes! -- TODO: A factor of * 3 is way too close. This causes the AI not to engange until merged sometimes!
if TargetDistance <= EngageDistance * 9 then if TargetDistance <= EngageDistance * 9 then
self:I(string.format("AI_AIR_ENGAGE onafterEngageRoute ==> __Engage - target distance = %.1f km", TargetDistance/1000)) --self:I(string.format("AI_AIR_ENGAGE onafterEngageRoute ==> __Engage - target distance = %.1f km", TargetDistance/1000))
self:__Engage( 0.1, AttackSetUnit ) self:__Engage( 0.1, AttackSetUnit )
else else
self:I(string.format("FF AI_AIR_ENGAGE onafterEngageRoute ==> Routing - target distance = %.1f km", TargetDistance/1000)) --self:I(string.format("FF AI_AIR_ENGAGE onafterEngageRoute ==> Routing - target distance = %.1f km", TargetDistance/1000))
local EngageRoute = {} local EngageRoute = {}
local AttackTasks = {} local AttackTasks = {}

View File

@@ -79,21 +79,13 @@
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- The range can be beyond or smaller than the range of the Patrol Zone. -- The range can be beyond or smaller than the range of the Patrol Zone.
-- The range is applied at the position of the AI. -- The range is applied at the position of the AI.
-- Use the method @{AI.AI_CAP#AI_AIR_PATROL.SetEngageRange}() to define that range. -- Use the method @{#AI_AIR_PATROL.SetEngageRange}() to define that range.
-- --
-- ## 4. Set the Zone of Engagement -- # Developer Note
-- --
-- ![Zone](..\Presentations\AI_CAP\Dia12.JPG) -- 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
-- An optional @{Core.Zone} can be set, --
-- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{AI.AI_CAP#AI_AIR_PATROL.SetEngageZone}() to define that Zone.
--
-- # Developer Note
--
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
-- Therefore, this class is considered to be deprecated
--
-- === -- ===
-- --
-- @field #AI_AIR_PATROL -- @field #AI_AIR_PATROL

View File

@@ -18,12 +18,12 @@
--- Implements the core functions modeling squadrons for airplanes and helicopters. --- Implements the core functions modeling squadrons for airplanes and helicopters.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_AIR_SQUADRON -- @field #AI_AIR_SQUADRON

View File

@@ -22,7 +22,7 @@
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- ### Contributions: -- ### Contributions:
-- --
-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. -- * **Gunterlund**: Test case revision.
-- --
-- === -- ===
-- --
@@ -130,12 +130,12 @@
-- AIBAIZone:SearchOff() -- AIBAIZone:SearchOff()
-- --
-- Searching can be switched back on with the method @{#AI_BAI_ZONE.SearchOn}(). Use the method @{#AI_BAI_ZONE.SearchOnOff}() to flexibily switch searching on or off. -- Searching can be switched back on with the method @{#AI_BAI_ZONE.SearchOn}(). Use the method @{#AI_BAI_ZONE.SearchOnOff}() to flexibily switch searching on or off.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_BAI_ZONE -- @field #AI_BAI_ZONE

View File

@@ -20,7 +20,7 @@
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- ### Contributions: -- ### Contributions:
-- --
-- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) -- * **Dutch_Baron**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-)
-- --
-- === -- ===
-- --
@@ -40,7 +40,7 @@
-- --
-- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM). -- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM).
-- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods. -- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods.
-- An explanation about state and event transition methods can be found in the @{FSM} module documentation. -- An explanation about state and event transition methods can be found in the @{Core.Fsm} module documentation.
-- --
-- The mission designer can tailor the AI_BALANCER behaviour, by implementing a state or event handling method for the following: -- The mission designer can tailor the AI_BALANCER behaviour, by implementing a state or event handling method for the following:
-- --
@@ -52,7 +52,7 @@
-- --
-- ## 2. AI_BALANCER is a FSM -- ## 2. AI_BALANCER is a FSM
-- --
-- ![Process](..\Presentations\AI_Balancer\Dia13.JPG) -- ![Process](..\Presentations\AI_BALANCER\Dia13.JPG)
-- --
-- ### 2.1. AI_BALANCER States -- ### 2.1. AI_BALANCER States
-- --
@@ -85,12 +85,12 @@
-- --
-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return, -- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return,
-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed. -- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #AI_BALANCER -- @field #AI_BALANCER
AI_BALANCER = { AI_BALANCER = {
ClassName = "AI_BALANCER", ClassName = "AI_BALANCER",

View File

@@ -20,11 +20,11 @@
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- ### Contributions: -- ### Contributions:
-- --
-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. -- * **Quax**: Concept, Advice & Testing.
-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. -- * **Pikey**: Concept, Advice & Testing.
-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. -- * **Gunterlund**: Test case revision.
-- * **[Whisper](http://forums.eagle.ru/member.php?u=3829): Testing. -- * **Whisper**: Testing.
-- * **[Delta99](https://forums.eagle.ru/member.php?u=125166): Testing. -- * **Delta99**: Testing.
-- --
-- === -- ===
-- --
@@ -112,12 +112,12 @@
-- An optional @{Core.Zone} can be set, -- An optional @{Core.Zone} can be set,
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{#AI_CAP_ZONE.SetEngageZone}() to define that Zone. -- Use the method @{#AI_CAP_ZONE.SetEngageZone}() to define that Zone.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_CAP_ZONE -- @field #AI_CAP_ZONE

View File

@@ -22,9 +22,9 @@
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- ### Contributions: -- ### Contributions:
-- --
-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. -- * **Quax**: Concept, Advice & Testing.
-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. -- * **Pikey**: Concept, Advice & Testing.
-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. -- * **Gunterlund**: Test case revision.
-- --
-- === -- ===
-- --
@@ -118,12 +118,12 @@
-- * **@{#AI_CAS_ZONE.Destroy}**: The AI has destroyed a target @{Wrapper.Unit}. -- * **@{#AI_CAS_ZONE.Destroy}**: The AI has destroyed a target @{Wrapper.Unit}.
-- * **@{#AI_CAS_ZONE.Destroyed}**: The AI has destroyed all target @{Wrapper.Unit}s assigned in the CAS task. -- * **@{#AI_CAS_ZONE.Destroyed}**: The AI has destroyed all target @{Wrapper.Unit}s assigned in the CAS task.
-- * **Status**: The AI is checking status (fuel and damage). When the thresholds have been reached, the AI will RTB. -- * **Status**: The AI is checking status (fuel and damage). When the thresholds have been reached, the AI will RTB.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_CAS_ZONE -- @field #AI_CAS_ZONE

View File

@@ -25,12 +25,12 @@
-- * @{AI.AI_Cargo_APC} - Cargo transportation using APCs and other vehicles between zones. -- * @{AI.AI_Cargo_APC} - Cargo transportation using APCs and other vehicles between zones.
-- * @{AI.AI_Cargo_Helicopter} - Cargo transportation using helicopters between zones. -- * @{AI.AI_Cargo_Helicopter} - Cargo transportation using helicopters between zones.
-- * @{AI.AI_Cargo_Airplane} - Cargo transportation using airplanes to and from airbases. -- * @{AI.AI_Cargo_Airplane} - Cargo transportation using airplanes to and from airbases.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #AI_CARGO -- @field #AI_CARGO
AI_CARGO = { AI_CARGO = {
ClassName = "AI_CARGO", ClassName = "AI_CARGO",

View File

@@ -75,12 +75,12 @@
-- Using the @{#AI_CARGO_APC.Pickup}() method, you are able to direct the APCs towards a point on the battlefield to board/load the cargo at the specific coordinate. -- Using the @{#AI_CARGO_APC.Pickup}() method, you are able to direct the APCs towards a point on the battlefield to board/load the cargo at the specific coordinate.
-- The APCs will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment. -- The APCs will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment.
-- --
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- --
-- @field #AI_CARGO_APC -- @field #AI_CARGO_APC
AI_CARGO_APC = { AI_CARGO_APC = {

View File

@@ -41,12 +41,12 @@
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every -- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
-- time is not so much of an issue ... -- time is not so much of an issue ...
-- --
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #AI_CARGO_AIRPLANE -- @field #AI_CARGO_AIRPLANE
AI_CARGO_AIRPLANE = { AI_CARGO_AIRPLANE = {
ClassName = "AI_CARGO_AIRPLANE", ClassName = "AI_CARGO_AIRPLANE",

View File

@@ -100,12 +100,12 @@
-- --
-- Yes, please ensure that the zones are declared using the @{Core.Zone} classes. -- Yes, please ensure that the zones are declared using the @{Core.Zone} classes.
-- Possible zones that function at the moment are ZONE, ZONE_GROUP, ZONE_UNIT, ZONE_POLYGON. -- Possible zones that function at the moment are ZONE, ZONE_GROUP, ZONE_UNIT, ZONE_POLYGON.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**

View File

@@ -137,12 +137,12 @@
-- Use @{#AI_CARGO_DISPATCHER_APC.SetHomeZone}() to specify the home zone. -- Use @{#AI_CARGO_DISPATCHER_APC.SetHomeZone}() to specify the home zone.
-- --
-- If no home zone is specified, the APCs will wait near the deploy zone for a new pickup command. -- If no home zone is specified, the APCs will wait near the deploy zone for a new pickup command.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_CARGO_DISPATCHER_APC -- @field #AI_CARGO_DISPATCHER_APC

View File

@@ -108,12 +108,12 @@
-- --
-- **There are a lot of templates available that allows you to quickly setup an event handler for a specific event type!** -- **There are a lot of templates available that allows you to quickly setup an event handler for a specific event type!**
-- --
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- --
-- @field #AI_CARGO_DISPATCHER_AIRPLANE -- @field #AI_CARGO_DISPATCHER_AIRPLANE
AI_CARGO_DISPATCHER_AIRPLANE = { AI_CARGO_DISPATCHER_AIRPLANE = {

View File

@@ -140,12 +140,12 @@
-- Use @{#AI_CARGO_DISPATCHER_HELICOPTER.SetHomeZone}() to specify the home zone. -- Use @{#AI_CARGO_DISPATCHER_HELICOPTER.SetHomeZone}() to specify the home zone.
-- --
-- If no home zone is specified, the helicopters will wait near the deploy zone for a new pickup command. -- If no home zone is specified, the helicopters will wait near the deploy zone for a new pickup command.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_CARGO_DISPATCHER_HELICOPTER -- @field #AI_CARGO_DISPATCHER_HELICOPTER

View File

@@ -130,12 +130,12 @@
-- Use @{#AI_CARGO_DISPATCHER_SHIP.SetHomeZone}() to specify the home zone. -- Use @{#AI_CARGO_DISPATCHER_SHIP.SetHomeZone}() to specify the home zone.
-- --
-- If no home zone is specified, the Ship will wait near the deploy zone for a new pickup command. -- If no home zone is specified, the Ship will wait near the deploy zone for a new pickup command.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_CARGO_DISPATCHER_SHIP -- @field #AI_CARGO_DISPATCHER_SHIP

View File

@@ -41,12 +41,12 @@
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every -- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
-- time is not so much of an issue ... -- time is not so much of an issue ...
-- --
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_CARGO_HELICOPTER -- @field #AI_CARGO_HELICOPTER

View File

@@ -54,12 +54,12 @@
-- Using the @{#AI_CARGO_SHIP.Pickup}() method, you are able to direct the Ship towards a Pickup zone to board/load the cargo at the specified -- Using the @{#AI_CARGO_SHIP.Pickup}() method, you are able to direct the Ship towards a Pickup zone to board/load the cargo at the specified
-- coordinate. The Ship will follow the Shipping Lane to ensure consistent cargo transportation within the simulation environment. -- coordinate. The Ship will follow the Shipping Lane to ensure consistent cargo transportation within the simulation environment.
-- --
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #AI_CARGO_SHIP -- @field #AI_CARGO_SHIP
AI_CARGO_SHIP = { AI_CARGO_SHIP = {
ClassName = "AI_CARGO_SHIP", ClassName = "AI_CARGO_SHIP",

View File

@@ -174,12 +174,12 @@
-- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." ) -- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
-- EscortPlanes:MenusAirplanes() -- create menus for airplanes -- EscortPlanes:MenusAirplanes() -- create menus for airplanes
-- EscortPlanes:__Start(2) -- EscortPlanes:__Start(2)
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #AI_ESCORT -- @field #AI_ESCORT
AI_ESCORT = { AI_ESCORT = {
ClassName = "AI_ESCORT", ClassName = "AI_ESCORT",
@@ -199,13 +199,6 @@ AI_ESCORT = {
-- @field Functional.Detection#DETECTION_AREAS -- @field Functional.Detection#DETECTION_AREAS
AI_ESCORT.Detection = nil AI_ESCORT.Detection = nil
--- MENUPARAM type
-- @type MENUPARAM
-- @field #AI_ESCORT ParamSelf
-- @field #Distance ParamDistance
-- @field #function ParamFunction
-- @field #string ParamMessage
--- AI_ESCORT class constructor for an AI group --- AI_ESCORT class constructor for an AI group
-- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Wrapper.Client#CLIENT EscortUnit The client escorted by the EscortGroup. -- @param Wrapper.Client#CLIENT EscortUnit The client escorted by the EscortGroup.
@@ -268,7 +261,7 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
EscortGroupSet:ForEachGroup( EscortGroupSet:ForEachGroup(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
-- Set EscortGroup known at EscortUnit. -- Set EscortGroup known at EscortUnit.
if not self.PlayerUnit._EscortGroups then if not self.PlayerUnit._EscortGroups then
@@ -350,7 +343,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
self:F() self:F()
EscortGroupSet:ForEachGroup( EscortGroupSet:ForEachGroup(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
EscortGroup:WayPointInitialize() EscortGroup:WayPointInitialize()
@@ -388,7 +381,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
self:_InitFlightMenus() self:_InitFlightMenus()
self.EscortGroupSet:ForSomeGroupAlive( self.EscortGroupSet:ForSomeGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
self:_InitEscortMenus( EscortGroup ) self:_InitEscortMenus( EscortGroup )
@@ -419,7 +412,7 @@ function AI_ESCORT:onafterStop( EscortGroupSet )
self:F() self:F()
EscortGroupSet:ForEachGroup( EscortGroupSet:ForEachGroup(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
EscortGroup:WayPointInitialize() EscortGroup:WayPointInitialize()
@@ -568,7 +561,7 @@ function AI_ESCORT:SetFlightMenuFormation( Formation )
local MenuFlightFormationID = MENU_GROUP_COMMAND:New( self.PlayerGroup, Formation, FlightMenuFormation, local MenuFlightFormationID = MENU_GROUP_COMMAND:New( self.PlayerGroup, Formation, FlightMenuFormation,
function ( self, Formation, ... ) function ( self, Formation, ... )
self.EscortGroupSet:ForSomeGroupAlive( self.EscortGroupSet:ForSomeGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup, self, Formation, Arguments ) function( EscortGroup, self, Formation, Arguments )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:E({FormationID=FormationID}) self:E({FormationID=FormationID})
@@ -1249,7 +1242,7 @@ function AI_ESCORT:MenuAssistedAttack()
self:F() self:F()
self.EscortGroupSet:ForSomeGroupAlive( self.EscortGroupSet:ForSomeGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if not EscortGroup:IsAir() then if not EscortGroup:IsAir() then
-- Request assistance from other escorts. -- Request assistance from other escorts.
@@ -1446,7 +1439,7 @@ function AI_ESCORT:_FlightHoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds )
local EscortUnit = self.PlayerUnit local EscortUnit = self.PlayerUnit
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup, OrbitGroup ) function( EscortGroup, OrbitGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
if OrbitGroup == nil then if OrbitGroup == nil then
@@ -1474,7 +1467,7 @@ end
function AI_ESCORT:_FlightJoinUp() function AI_ESCORT:_FlightJoinUp()
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_JoinUp( EscortGroup ) self:_JoinUp( EscortGroup )
@@ -1501,7 +1494,7 @@ end
function AI_ESCORT:_FlightFormationTrail( XStart, XSpace, YStart ) function AI_ESCORT:_FlightFormationTrail( XStart, XSpace, YStart )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_EscortFormationTrail( EscortGroup, XStart, XSpace, YStart ) self:_EscortFormationTrail( EscortGroup, XStart, XSpace, YStart )
@@ -1528,7 +1521,7 @@ end
function AI_ESCORT:_FlightFormationStack( XStart, XSpace, YStart, YSpace ) function AI_ESCORT:_FlightFormationStack( XStart, XSpace, YStart, YSpace )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_EscortFormationStack( EscortGroup, XStart, XSpace, YStart, YSpace ) self:_EscortFormationStack( EscortGroup, XStart, XSpace, YStart, YSpace )
@@ -1551,7 +1544,7 @@ end
function AI_ESCORT:_FlightFlare( Color, Message ) function AI_ESCORT:_FlightFlare( Color, Message )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_Flare( EscortGroup, Color, Message ) self:_Flare( EscortGroup, Color, Message )
@@ -1574,7 +1567,7 @@ end
function AI_ESCORT:_FlightSmoke( Color, Message ) function AI_ESCORT:_FlightSmoke( Color, Message )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_Smoke( EscortGroup, Color, Message ) self:_Smoke( EscortGroup, Color, Message )
@@ -1605,7 +1598,7 @@ end
function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets ) function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets ) self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets )
@@ -1813,7 +1806,7 @@ end
function AI_ESCORT:_FlightAttackTarget( DetectedItem ) function AI_ESCORT:_FlightAttackTarget( DetectedItem )
self.EscortGroupSet:ForEachGroupAlive( self.EscortGroupSet:ForEachGroupAlive(
-- @param Core.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup, DetectedItem ) function( EscortGroup, DetectedItem )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_AttackTarget( EscortGroup, DetectedItem ) self:_AttackTarget( EscortGroup, DetectedItem )

View File

@@ -20,12 +20,12 @@
--- Models the automatic assignment of AI escorts to player flights. --- Models the automatic assignment of AI escorts to player flights.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_ESCORT_DISPATCHER -- @field #AI_ESCORT_DISPATCHER

View File

@@ -20,12 +20,12 @@
--- 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.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_ESCORT_DISPATCHER_REQUEST -- @field #AI_ESCORT_DISPATCHER_REQUEST

View File

@@ -136,12 +136,12 @@
-- --
-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint. -- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint.
-- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission. -- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- ### Authors: **FlightControl** -- ### Authors: **FlightControl**
@@ -297,7 +297,7 @@ function AI_ESCORT_REQUEST:onafterStop( EscortGroupSet )
self:F() self:F()
EscortGroupSet:ForEachGroup( EscortGroupSet:ForEachGroup(
--- @param Core.Group#GROUP EscortGroup --- @param Wrapper.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
EscortGroup:WayPointInitialize() EscortGroup:WayPointInitialize()

View File

@@ -8,7 +8,7 @@
-- --
-- === -- ===
-- --
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/FOR%20-%20Formation) -- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/FOR%20-%20AI%20Group%20Formation)
-- --
-- === -- ===
-- --
@@ -31,11 +31,11 @@
-- @field Core.Set#SET_GROUP FollowGroupSet -- @field Core.Set#SET_GROUP FollowGroupSet
-- @field #string FollowName -- @field #string FollowName
-- @field #AI_FORMATION.MODE FollowMode The mode the escort is in. -- @field #AI_FORMATION.MODE FollowMode The mode the escort is in.
-- @field Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class. -- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
-- @field #number FollowDistance The current follow distance. -- @field #number FollowDistance The current follow distance.
-- @field #boolean ReportTargets If true, nearby targets are reported. -- @field #boolean ReportTargets If true, nearby targets are reported.
-- @Field DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup. -- @field DCS#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup.
-- @field DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup. -- @field DCS#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
-- @field #number dtFollow Time step between position updates. -- @field #number dtFollow Time step between position updates.
@@ -92,12 +92,12 @@
-- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" ) -- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" )
-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 ) -- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 )
-- LargeFormation:__Start( 1 ) -- LargeFormation:__Start( 1 )
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #AI_FORMATION -- @field #AI_FORMATION
AI_FORMATION = { AI_FORMATION = {
ClassName = "AI_FORMATION", ClassName = "AI_FORMATION",
@@ -164,15 +164,6 @@ AI_FORMATION.__Enum.ReportType = {
Ground = "G", Ground = "G",
} }
--- MENUPARAM type
-- @type MENUPARAM
-- @field #AI_FORMATION ParamSelf
-- @field #number ParamDistance
-- @field #function ParamFunction
-- @field #string ParamMessage
--- AI_FORMATION class constructor for an AI group --- AI_FORMATION class constructor for an AI group
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param Wrapper.Unit#UNIT FollowUnit The UNIT leading the FolllowGroupSet. -- @param Wrapper.Unit#UNIT FollowUnit The UNIT leading the FolllowGroupSet.
@@ -1005,7 +996,7 @@ function AI_FORMATION:SetFlightModeMission( FollowGroup )
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission ) FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
else else
self.FollowGroupSet:ForSomeGroupAlive( self.FollowGroupSet:ForSomeGroupAlive(
--- @param Core.Group#GROUP EscortGroup --- @param Wrapper.Group#GROUP EscortGroup
function( FollowGroup ) function( FollowGroup )
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) ) FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission ) FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
@@ -1029,7 +1020,7 @@ function AI_FORMATION:SetFlightModeAttack( FollowGroup )
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack ) FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
else else
self.FollowGroupSet:ForSomeGroupAlive( self.FollowGroupSet:ForSomeGroupAlive(
--- @param Core.Group#GROUP EscortGroup --- @param Wrapper.Group#GROUP EscortGroup
function( FollowGroup ) function( FollowGroup )
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) ) FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack ) FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
@@ -1053,7 +1044,7 @@ function AI_FORMATION:SetFlightModeFormation( FollowGroup )
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation ) FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
else else
self.FollowGroupSet:ForSomeGroupAlive( self.FollowGroupSet:ForSomeGroupAlive(
--- @param Core.Group#GROUP EscortGroup --- @param Wrapper.Group#GROUP EscortGroup
function( FollowGroup ) function( FollowGroup )
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) ) FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation ) FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )

View File

@@ -27,8 +27,8 @@
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- ### Contributions: -- ### Contributions:
-- --
-- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) -- * **Dutch_Baron**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-)
-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Testing and API concept review. -- * **Pikey**: Testing and API concept review.
-- --
-- === -- ===
-- --
@@ -144,12 +144,12 @@
-- When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on. -- When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on.
-- Therefore, when the damage threshold is reached, the AI will return immediately to the home base (RTB). -- Therefore, when the damage threshold is reached, the AI will return immediately to the home base (RTB).
-- Use the method @{#AI_PATROL_ZONE.ManageDamage}() to have this process in place. -- Use the method @{#AI_PATROL_ZONE.ManageDamage}() to have this process in place.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @field #AI_PATROL_ZONE -- @field #AI_PATROL_ZONE

View File

@@ -142,7 +142,7 @@ end -- ACT_ACCOUNT
do -- ACT_ACCOUNT_DEADS do -- ACT_ACCOUNT_DEADS
--- # @{#ACT_ACCOUNT_DEADS} FSM class, extends @{Core.Fsm.Account#ACT_ACCOUNT} --- # @{#ACT_ACCOUNT_DEADS} FSM class, extends @{#ACT_ACCOUNT}
-- --
-- The ACT_ACCOUNT_DEADS class accounts (detects, counts and reports) successful kills of DCS units. -- The ACT_ACCOUNT_DEADS class accounts (detects, counts and reports) successful kills of DCS units.
-- The process is given a @{Core.Set} of units that will be tracked upon successful destruction. -- The process is given a @{Core.Set} of units that will be tracked upon successful destruction.

View File

@@ -51,15 +51,15 @@
-- * **After** the state transition. -- * **After** the state transition.
-- The state transition method needs to start with the name **OnAfter + the name of the state**. -- The state transition method needs to start with the name **OnAfter + the name of the state**.
-- These state transition methods need to provide a return value, which is specified at the function description. -- These state transition methods need to provide a return value, which is specified at the function description.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- # 1) @{#ACT_ASSIGN_ACCEPT} class, extends @{Core.Fsm.Assign#ACT_ASSIGN} -- # 1) @{#ACT_ASSIGN_ACCEPT} class, extends @{Core.Fsm#ACT_ASSIGN}
-- --
-- The ACT_ASSIGN_ACCEPT class accepts by default a task for a player. No player intervention is allowed to reject the task. -- The ACT_ASSIGN_ACCEPT class accepts by default a task for a player. No player intervention is allowed to reject the task.
-- --
@@ -69,7 +69,7 @@
-- --
-- === -- ===
-- --
-- # 2) @{#ACT_ASSIGN_MENU_ACCEPT} class, extends @{Core.Fsm.Assign#ACT_ASSIGN} -- # 2) @{#ACT_ASSIGN_MENU_ACCEPT} class, extends @{Core.Fsm#ACT_ASSIGN}
-- --
-- The ACT_ASSIGN_MENU_ACCEPT class accepts a task when the player accepts the task through an added menu option. -- The ACT_ASSIGN_MENU_ACCEPT class accepts a task when the player accepts the task through an added menu option.
-- This assignment type is useful to conditionally allow the player to choose whether or not he would accept the task. -- This assignment type is useful to conditionally allow the player to choose whether or not he would accept the task.

View File

@@ -48,7 +48,7 @@
-- --
-- === -- ===
-- --
-- # 1) @{#ACT_ASSIST_SMOKE_TARGETS_ZONE} class, extends @{Core.Fsm.Route#ACT_ASSIST} -- # 1) @{#ACT_ASSIST_SMOKE_TARGETS_ZONE} class, extends @{#ACT_ASSIST}
-- --
-- The ACT_ASSIST_SMOKE_TARGETS_ZONE class implements the core functions to smoke targets in a @{Core.Zone}. -- The ACT_ASSIST_SMOKE_TARGETS_ZONE class implements the core functions to smoke targets in a @{Core.Zone}.
-- The targets are smoked within a certain range around each target, simulating a realistic smoking behaviour. -- The targets are smoked within a certain range around each target, simulating a realistic smoking behaviour.
@@ -57,12 +57,12 @@
-- # 1.1) ACT_ASSIST_SMOKE_TARGETS_ZONE constructor: -- # 1.1) ACT_ASSIST_SMOKE_TARGETS_ZONE constructor:
-- --
-- * @{#ACT_ASSIST_SMOKE_TARGETS_ZONE.New}(): Creates a new ACT_ASSIST_SMOKE_TARGETS_ZONE object. -- * @{#ACT_ASSIST_SMOKE_TARGETS_ZONE.New}(): Creates a new ACT_ASSIST_SMOKE_TARGETS_ZONE object.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @module Actions.Act_Assist -- @module Actions.Act_Assist

View File

@@ -60,7 +60,7 @@
-- --
-- === -- ===
-- --
-- # 1) @{#ACT_ROUTE_ZONE} class, extends @{Core.Fsm.Route#ACT_ROUTE} -- # 1) @{#ACT_ROUTE_ZONE} class, extends @{#ACT_ROUTE}
-- --
-- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Wrapper.Controllable} player @{Wrapper.Unit} to a @{Core.Zone}. -- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Wrapper.Controllable} player @{Wrapper.Unit} to a @{Core.Zone}.
-- The player receives on perioding times messages with the coordinates of the route to follow. -- The player receives on perioding times messages with the coordinates of the route to follow.
@@ -69,12 +69,12 @@
-- # 1.1) ACT_ROUTE_ZONE constructor: -- # 1.1) ACT_ROUTE_ZONE constructor:
-- --
-- * @{#ACT_ROUTE_ZONE.New}(): Creates a new ACT_ROUTE_ZONE object. -- * @{#ACT_ROUTE_ZONE.New}(): Creates a new ACT_ROUTE_ZONE object.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- @module Actions.Act_Route -- @module Actions.Act_Route

View File

@@ -86,7 +86,7 @@
-- There are also dispatchers that make AI work together to transport cargo automatically!!! -- There are also dispatchers that make AI work together to transport cargo automatically!!!
-- --
-- - @{AI.AI_Cargo_Dispatcher_APC} derived classes will create for your dynamic cargo handlers controlled by AI ground vehicle groups (APCs) to transport cargo between sites. -- - @{AI.AI_Cargo_Dispatcher_APC} derived classes will create for your dynamic cargo handlers controlled by AI ground vehicle groups (APCs) to transport cargo between sites.
-- - @{AI.AI_Cargo_Dispatcher_Helicopters} derived classes will create for your dynamic cargo handlers controlled by AI helicopter groups to transport cargo between sites. -- - @{AI.AI_Cargo_Dispatcher_Helicopter} derived classes will create for your dynamic cargo handlers controlled by AI helicopter groups to transport cargo between sites.
-- --
-- ## 3.3) Cargo transportation tasking. -- ## 3.3) Cargo transportation tasking.
-- --
@@ -233,12 +233,12 @@
-- Note that this option is optional, so can be omitted. The default value of the RR is 250 meters. -- Note that this option is optional, so can be omitted. The default value of the RR is 250 meters.
-- * **NR=** Provide the maximum range in meters when the cargo units will be boarded within the carrier during boarding. -- * **NR=** Provide the maximum range in meters when the cargo units will be boarded within the carrier during boarding.
-- Note that this option is optional, so can be omitted. The default value of the RR is 10 meters. -- Note that this option is optional, so can be omitted. The default value of the RR is 10 meters.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
@@ -398,7 +398,7 @@ do -- CARGO
-- --
-- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC#AI_CARGO_APC} class. -- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC#AI_CARGO_APC} class.
-- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter#AI_CARGO_HELICOPTER} class. -- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter#AI_CARGO_HELICOPTER} class.
-- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Plane#AI_CARGO_PLANE} class. -- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane#AI_CARGO_AIRPLANE} class.
-- * AI Ships is planned. -- * AI Ships is planned.
-- --
-- The above cargo classes are also used by the TASK\_CARGO\_ classes to allow human players to transport cargo as part of a tasking: -- The above cargo classes are also used by the TASK\_CARGO\_ classes to allow human players to transport cargo as part of a tasking:
@@ -980,7 +980,7 @@ do -- CARGO
--- Report to a Carrier Group with a Flaring signal. --- Report to a Carrier Group with a Flaring signal.
-- @param #CARGO self -- @param #CARGO self
-- @param Utils#UTILS.FlareColor FlareColor the color of the flare. -- @param Utilities.Utils#UTILS.FlareColor FlareColor the color of the flare.
-- @return #CARGO -- @return #CARGO
function CARGO:ReportFlare( FlareColor ) function CARGO:ReportFlare( FlareColor )
@@ -989,7 +989,7 @@ do -- CARGO
--- Report to a Carrier Group with a Smoking signal. --- Report to a Carrier Group with a Smoking signal.
-- @param #CARGO self -- @param #CARGO self
-- @param Utils#UTILS.SmokeColor SmokeColor the color of the smoke. -- @param Utilities.Utils#UTILS.SmokeColor SmokeColor the color of the smoke.
-- @return #CARGO -- @return #CARGO
function CARGO:ReportSmoke( SmokeColor ) function CARGO:ReportSmoke( SmokeColor )

View File

@@ -112,7 +112,7 @@
-- --
-- # Calculate the Path -- # Calculate the Path
-- --
-- Finally, we have to calculate the path. This is done by the @{ASTAR.GetPath}(*ExcludeStart, ExcludeEnd*) function. This function returns a table of nodes, which -- Finally, we have to calculate the path. This is done by the @{#GetPath}(*ExcludeStart, ExcludeEnd*) function. This function returns a table of nodes, which
-- describe the optimal path from the start node to the end node. -- describe the optimal path from the start node to the end node.
-- --
-- By default, the start and end node are include in the table that is returned. -- By default, the start and end node are include in the table that is returned.

View File

@@ -20,7 +20,7 @@
-- --
-- @module Core.ClientMenu -- @module Core.ClientMenu
-- @image Core_Menu.JPG -- @image Core_Menu.JPG
-- last change: Sept 2023 -- last change: Oct 2023
-- TODO -- TODO
---------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------
@@ -304,6 +304,8 @@ end
-- @field #table menutree -- @field #table menutree
-- @field #number entrycount -- @field #number entrycount
-- @field #boolean debug -- @field #boolean debug
-- @field #table PlayerMenu
-- @field #number Coalition
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- *As a child my family's menu consisted of two choices: take it, or leave it.* --- *As a child my family's menu consisted of two choices: take it, or leave it.*
@@ -345,7 +347,7 @@ end
-- local mymenu_lv3b = menumgr:NewEntry("Level 3 aab",mymenu_lv2a) -- local mymenu_lv3b = menumgr:NewEntry("Level 3 aab",mymenu_lv2a)
-- local mymenu_lv3c = menumgr:NewEntry("Level 3 aac",mymenu_lv2a) -- local mymenu_lv3c = menumgr:NewEntry("Level 3 aac",mymenu_lv2a)
-- --
-- menumgr:Propagate() -- menumgr:Propagate() -- propagate **once** to all clients in the SET_CLIENT
-- --
-- ## Remove a single entry's subtree -- ## Remove a single entry's subtree
-- --
@@ -384,13 +386,17 @@ end
-- --
-- ## Reset all and clear the reference tree -- ## Reset all and clear the reference tree
-- --
-- menumgr:ResetMenuComplete() -- menumgr:ResetMenuComplete()
--
-- ## Set to auto-propagate for CLIENTs joining the SET_CLIENT **after** the script is loaded - handy if you have a single menu tree.
--
-- menumgr:InitAutoPropagation()
-- --
-- @field #CLIENTMENUMANAGER -- @field #CLIENTMENUMANAGER
CLIENTMENUMANAGER = { CLIENTMENUMANAGER = {
ClassName = "CLIENTMENUMANAGER", ClassName = "CLIENTMENUMANAGER",
lid = "", lid = "",
version = "0.1.1", version = "0.1.4",
name = nil, name = nil,
clientset = nil, clientset = nil,
menutree = {}, menutree = {},
@@ -399,26 +405,108 @@ CLIENTMENUMANAGER = {
entrycount = 0, entrycount = 0,
rootentries = {}, rootentries = {},
debug = true, debug = true,
PlayerMenu = {},
Coalition = nil,
} }
--- Create a new ClientManager instance. --- Create a new ClientManager instance.
-- @param #CLIENTMENUMANAGER self -- @param #CLIENTMENUMANAGER self
-- @param Core.Set#SET_CLIENT ClientSet The set of clients to manage. -- @param Core.Set#SET_CLIENT ClientSet The set of clients to manage.
-- @param #string Alias The name of this manager. -- @param #string Alias The name of this manager.
-- @param #number Coalition (Optional) Coalition of this Manager, defaults to coalition.side.BLUE
-- @return #CLIENTMENUMANAGER self -- @return #CLIENTMENUMANAGER self
function CLIENTMENUMANAGER:New(ClientSet, Alias) function CLIENTMENUMANAGER:New(ClientSet, Alias, Coalition)
-- Inherit everything from FSM class. -- Inherit everything from FSM class.
local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENUMANAGER local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENUMANAGER
self.clientset = ClientSet self.clientset = ClientSet
self.PlayerMenu = {}
self.name = Alias or "Nightshift" self.name = Alias or "Nightshift"
self.Coalition = Coalition or coalition.side.BLUE
-- Log id. -- Log id.
self.lid=string.format("CLIENTMENUMANAGER %s | %s | ", self.version, self.name) self.lid=string.format("CLIENTMENUMANAGER %s | %s | ", self.version, self.name)
if self.debug then if self.debug then
self:T(self.lid.."Created") self:I(self.lid.."Created")
end end
return self return self
end end
--- [Internal] Event handling
-- @param #CLIENTMENUMANAGER self
-- @param Core.Event#EVENTDATA EventData
-- @return #CLIENTMENUMANAGER self
function CLIENTMENUMANAGER:_EventHandler(EventData)
self:T(self.lid.."_EventHandler: "..EventData.id)
--self:I(self.lid.."_EventHandler: "..tostring(EventData.IniPlayerName))
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
self:T(self.lid.."Leave event for player: "..tostring(EventData.IniPlayerName))
local Client = _DATABASE:FindClient( EventData.IniUnitName )
if Client then
self:ResetMenu(Client)
end
elseif (EventData.id == EVENTS.PlayerEnterAircraft) and EventData.IniCoalition == self.Coalition then
if EventData.IniPlayerName and EventData.IniGroup then
if (not self.clientset:IsIncludeObject(_DATABASE:FindClient( EventData.IniUnitName ))) then
self:T(self.lid.."Client not in SET: "..EventData.IniPlayerName)
return self
end
--self:I(self.lid.."Join event for player: "..EventData.IniPlayerName)
local player = _DATABASE:FindClient( EventData.IniUnitName )
self:Propagate(player)
end
elseif EventData.id == EVENTS.PlayerEnterUnit then
-- special for CA slots
local grp = GROUP:FindByName(EventData.IniGroupName)
if grp:IsGround() then
self:T(string.format("Player %s entered GROUND unit %s!",EventData.IniPlayerName,EventData.IniUnitName))
local IsPlayer = EventData.IniDCSUnit:getPlayerName()
if IsPlayer then
local client=_DATABASE.CLIENTS[EventData.IniDCSUnitName] --Wrapper.Client#CLIENT
-- Add client in case it does not exist already.
if not client then
-- Debug info.
self:I(string.format("Player '%s' joined ground unit '%s' of group '%s'", tostring(EventData.IniPlayerName), tostring(EventData.IniDCSUnitName), tostring(EventData.IniDCSGroupName)))
client=_DATABASE:AddClient(EventData.IniDCSUnitName)
-- Add player.
client:AddPlayer(EventData.IniPlayerName)
-- Add player.
if not _DATABASE.PLAYERS[EventData.IniPlayerName] then
_DATABASE:AddPlayer( EventData.IniUnitName, EventData.IniPlayerName )
end
-- Player settings.
local Settings = SETTINGS:Set( EventData.IniPlayerName )
Settings:SetPlayerMenu(EventData.IniUnit)
end
--local player = _DATABASE:FindClient( EventData.IniPlayerName )
self:Propagate(client)
end
end
end
return self
end
--- Set this Client Manager to auto-propagate menus to newly joined players. Useful if you have **one** menu structure only.
-- @param #CLIENTMENUMANAGER self
-- @return #CLIENTMENUMANAGER self
function CLIENTMENUMANAGER:InitAutoPropagation()
-- Player Events
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
self:HandleEvent(EVENTS.Crash, self._EventHandler)
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
self:SetEventPriority(5)
return self
end
--- Create a new entry in the generic structure. --- Create a new entry in the generic structure.
-- @param #CLIENTMENUMANAGER self -- @param #CLIENTMENUMANAGER self
-- @param #string Text Text of the F10 menu entry. -- @param #string Text Text of the F10 menu entry.
@@ -571,7 +659,7 @@ end
-- @return #CLIENTMENU Entry -- @return #CLIENTMENU Entry
function CLIENTMENUMANAGER:Propagate(Client) function CLIENTMENUMANAGER:Propagate(Client)
self:T(self.lid.."Propagate") self:T(self.lid.."Propagate")
self:T(Client) --self:I(UTILS.PrintTableToLog(Client,1))
local Set = self.clientset.Set local Set = self.clientset.Set
if Client then if Client then
Set = {Client} Set = {Client}
@@ -580,7 +668,7 @@ function CLIENTMENUMANAGER:Propagate(Client)
for _,_client in pairs(Set) do for _,_client in pairs(Set) do
local client = _client -- Wrapper.Client#CLIENT local client = _client -- Wrapper.Client#CLIENT
if client and client:IsAlive() then if client and client:IsAlive() then
local playername = client:GetPlayerName() local playername = client:GetPlayerName() or "none"
if not self.playertree[playername] then if not self.playertree[playername] then
self.playertree[playername] = {} self.playertree[playername] = {}
end end
@@ -792,4 +880,3 @@ end
-- End ClientMenu -- End ClientMenu
-- --
---------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------

View File

@@ -9,7 +9,7 @@
-- --
-- ## Example Missions: -- ## Example Missions:
-- --
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Operation). -- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Core/Condition).
-- --
-- === -- ===
-- --

View File

@@ -126,6 +126,8 @@ function DATABASE:New()
self:SetEventPriority( 1 ) self:SetEventPriority( 1 )
self:HandleEvent( EVENTS.Birth, self._EventOnBirth ) self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
-- DCS 2.9 fixed CA event for players -- TODO: reset unit when leaving
self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit )
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash )
@@ -680,7 +682,7 @@ do -- cargo
--- Finds an CARGO based on the CargoName. --- Finds an CARGO based on the CargoName.
-- @param #DATABASE self -- @param #DATABASE self
-- @param #string CargoName -- @param #string CargoName
-- @return Wrapper.Cargo#CARGO The found CARGO. -- @return Cargo.Cargo#CARGO The found CARGO.
function DATABASE:FindCargo( CargoName ) function DATABASE:FindCargo( CargoName )
local CargoFound = self.CARGOS[CargoName] local CargoFound = self.CARGOS[CargoName]
@@ -810,6 +812,7 @@ function DATABASE:AddPlayer( UnitName, PlayerName )
self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName ) self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName )
self.PLAYERSJOINED[PlayerName] = PlayerName self.PLAYERSJOINED[PlayerName] = PlayerName
end end
end end
--- Deletes a player from the DATABASE based on the Player Name. --- Deletes a player from the DATABASE based on the Player Name.
@@ -1470,39 +1473,43 @@ function DATABASE:_EventOnDeadOrCrash( Event )
end end
--- Handles the OnPlayerEnterUnit event to fill the active players table (with the unit filter applied). --- Handles the OnPlayerEnterUnit event to fill the active players table for CA units (with the unit filter applied).
-- @param #DATABASE self -- @param #DATABASE self
-- @param Core.Event#EVENTDATA Event -- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnPlayerEnterUnit( Event ) function DATABASE:_EventOnPlayerEnterUnit( Event )
self:F2( { Event } ) self:F2( { Event } )
if Event.IniDCSUnit then if Event.IniDCSUnit then
if Event.IniObjectCategory == 1 then -- Player entering a CA slot
if Event.IniObjectCategory == 1 and Event.IniGroup and Event.IniGroup:IsGround() then
local IsPlayer = Event.IniDCSUnit:getPlayerName()
if IsPlayer then
-- Add unit. -- Debug info.
self:AddUnit( Event.IniDCSUnitName ) self:I(string.format("Player '%s' joined GROUND unit '%s' of group '%s'", tostring(Event.IniPlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
local client= self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT
-- Add client in case it does not exist already.
if not client then
client=self:AddClient(Event.IniDCSUnitName)
end
-- Add player.
client:AddPlayer(Event.IniPlayerName)
-- Ini unit. -- Add player.
Event.IniUnit = self:FindUnit( Event.IniDCSUnitName ) if not self.PLAYERS[Event.IniPlayerName] then
self:AddPlayer( Event.IniUnitName, Event.IniPlayerName )
-- Add group.
self:AddGroup( Event.IniDCSGroupName )
-- Get player unit.
local PlayerName = Event.IniDCSUnit:getPlayerName()
if PlayerName then
if not self.PLAYERS[PlayerName] then
self:AddPlayer( Event.IniDCSUnitName, PlayerName )
end end
local Settings = SETTINGS:Set( PlayerName ) -- Player settings.
Settings:SetPlayerMenu( Event.IniUnit ) local Settings = SETTINGS:Set( Event.IniPlayerName )
Settings:SetPlayerMenu(Event.IniUnit)
else
self:E("ERROR: getPlayerName() returned nil for event PlayerEnterUnit")
end end
end end
end end
end end
@@ -1513,15 +1520,26 @@ end
-- @param Core.Event#EVENTDATA Event -- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnPlayerLeaveUnit( Event ) function DATABASE:_EventOnPlayerLeaveUnit( Event )
self:F2( { Event } ) self:F2( { Event } )
local function FindPlayerName(UnitName)
local playername = nil
for _name,_unitname in pairs(self.PLAYERS) do
if _unitname == UnitName then
playername = _name
break
end
end
return playername
end
if Event.IniUnit then if Event.IniUnit then
if Event.IniObjectCategory == 1 then if Event.IniObjectCategory == 1 then
-- Try to get the player name. This can be buggy for multicrew aircraft! -- Try to get the player name. This can be buggy for multicrew aircraft!
local PlayerName = Event.IniUnit:GetPlayerName() local PlayerName = Event.IniUnit:GetPlayerName() or FindPlayerName(Event.IniUnitName)
if PlayerName then --and self.PLAYERS[PlayerName] then if PlayerName then
-- Debug info. -- Debug info.
self:I(string.format("Player '%s' left unit %s", tostring(PlayerName), tostring(Event.IniUnitName))) self:I(string.format("Player '%s' left unit %s", tostring(PlayerName), tostring(Event.IniUnitName)))
@@ -2005,8 +2023,6 @@ end
TargetPlayerName = Event.IniPlayerName TargetPlayerName = Event.IniPlayerName
TargetCoalition = Event.IniCoalition TargetCoalition = Event.IniCoalition
--TargetCategory = TargetUnit:getCategory()
--TargetCategory = TargetUnit:getDesc().category -- Workaround
TargetCategory = Event.IniCategory TargetCategory = Event.IniCategory
TargetType = Event.IniTypeName TargetType = Event.IniTypeName

View File

@@ -173,7 +173,8 @@
-- @image Core_Event.JPG -- @image Core_Event.JPG
--- @type EVENT ---
-- @type EVENT
-- @field #EVENT.Events Events -- @field #EVENT.Events Events
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@@ -260,6 +261,15 @@ EVENTS = {
SimulationStart = world.event.S_EVENT_SIMULATION_START or -1, SimulationStart = world.event.S_EVENT_SIMULATION_START or -1,
WeaponRearm = world.event.S_EVENT_WEAPON_REARM or -1, WeaponRearm = world.event.S_EVENT_WEAPON_REARM or -1,
WeaponDrop = world.event.S_EVENT_WEAPON_DROP or -1, WeaponDrop = world.event.S_EVENT_WEAPON_DROP or -1,
-- Added with DCS 2.9.0
UnitTaskTimeout = world.event.S_EVENT_UNIT_TASK_TIMEOUT or -1,
UnitTaskStage = world.event.S_EVENT_UNIT_TASK_STAGE or -1,
MacSubtaskScore = world.event.S_EVENT_MAC_SUBTASK_SCORE or -1,
MacExtraScore = world.event.S_EVENT_MAC_EXTRA_SCORE or -1,
MissionRestart = world.event.S_EVENT_MISSION_RESTART or -1,
MissionWinner = world.event.S_EVENT_MISSION_WINNER or -1,
PostponedTakeoff = world.event.S_EVENT_POSTPONED_TAKEOFF or -1,
PostponedLand = world.event.S_EVENT_POSTPONED_LAND or -1,
} }
--- The Event structure --- The Event structure
@@ -282,6 +292,7 @@ EVENTS = {
-- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object. -- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object.
-- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName). -- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName).
-- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot. -- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot.
-- @field #string IniPlayerUCID (UNIT) The UCID of the initiating player in case the Unit is a client or player slot and on a multi-player server.
-- @field DCS#coalition.side IniCoalition (UNIT) The coalition of the initiator. -- @field DCS#coalition.side IniCoalition (UNIT) The coalition of the initiator.
-- @field DCS#Unit.Category IniCategory (UNIT) The category of the initiator. -- @field DCS#Unit.Category IniCategory (UNIT) The category of the initiator.
-- @field #string IniTypeName (UNIT) The type name of the initiator. -- @field #string IniTypeName (UNIT) The type name of the initiator.
@@ -297,6 +308,7 @@ EVENTS = {
-- @field Wrapper.Group#GROUP TgtGroup (UNIT) The target MOOSE wrapper @{Wrapper.Group#GROUP} of the target Group object. -- @field Wrapper.Group#GROUP TgtGroup (UNIT) The target MOOSE wrapper @{Wrapper.Group#GROUP} of the target Group object.
-- @field #string TgtGroupName (UNIT) The target GROUP name (same as TgtDCSGroupName). -- @field #string TgtGroupName (UNIT) The target GROUP name (same as TgtDCSGroupName).
-- @field #string TgtPlayerName (UNIT) The name of the target player in case the Unit is a client or player slot. -- @field #string TgtPlayerName (UNIT) The name of the target player in case the Unit is a client or player slot.
-- @field #string TgtPlayerUCID (UNIT) The UCID of the target player in case the Unit is a client or player slot and on a multi-player server.
-- @field DCS#coalition.side TgtCoalition (UNIT) The coalition of the target. -- @field DCS#coalition.side TgtCoalition (UNIT) The coalition of the target.
-- @field DCS#Unit.Category TgtCategory (UNIT) The category of the target. -- @field DCS#Unit.Category TgtCategory (UNIT) The category of the target.
-- @field #string TgtTypeName (UNIT) The type name of the target. -- @field #string TgtTypeName (UNIT) The type name of the target.
@@ -313,7 +325,7 @@ EVENTS = {
-- @field Cargo.Cargo#CARGO Cargo The cargo object. -- @field Cargo.Cargo#CARGO Cargo The cargo object.
-- @field #string CargoName The name of the cargo object. -- @field #string CargoName The name of the cargo object.
-- --
-- @field Core.ZONE#ZONE Zone The zone object. -- @field Core.Zone#ZONE Zone The zone object.
-- @field #string ZoneName The name of the zone. -- @field #string ZoneName The name of the zone.
@@ -633,6 +645,55 @@ local _EVENTMETA = {
Event = "OnEventWeaponDrop", Event = "OnEventWeaponDrop",
Text = "S_EVENT_WEAPON_DROP" Text = "S_EVENT_WEAPON_DROP"
}, },
-- DCS 2.9
[EVENTS.UnitTaskTimeout] = {
Order = 1,
Side = "I",
Event = "OnEventUnitTaskTimeout",
Text = "S_EVENT_UNIT_TASK_TIMEOUT "
},
[EVENTS.UnitTaskStage] = {
Order = 1,
Side = "I",
Event = "OnEventUnitTaskStage",
Text = "S_EVENT_UNIT_TASK_STAGE "
},
[EVENTS.MacSubtaskScore] = {
Order = 1,
Side = "I",
Event = "OnEventMacSubtaskScore",
Text = "S_EVENT_MAC_SUBTASK_SCORE"
},
[EVENTS.MacExtraScore] = {
Order = 1,
Side = "I",
Event = "OnEventMacExtraScore",
Text = "S_EVENT_MAC_EXTRA_SCOREP"
},
[EVENTS.MissionRestart] = {
Order = 1,
Side = "I",
Event = "OnEventMissionRestart",
Text = "S_EVENT_MISSION_RESTART"
},
[EVENTS.MissionWinner] = {
Order = 1,
Side = "I",
Event = "OnEventMissionWinner",
Text = "S_EVENT_MISSION_WINNER"
},
[EVENTS.PostponedTakeoff] = {
Order = 1,
Side = "I",
Event = "OnEventPostponedTakeoff",
Text = "S_EVENT_POSTPONED_TAKEOFF"
},
[EVENTS.PostponedLand] = {
Order = 1,
Side = "I",
Event = "OnEventPostponedLand",
Text = "S_EVENT_POSTPONED_LAND"
},
} }
--- The Events structure --- The Events structure
@@ -988,7 +1049,7 @@ do -- Event Creation
--- Creation of a New ZoneGoal Event. --- Creation of a New ZoneGoal Event.
-- @param #EVENT self -- @param #EVENT self
-- @param Core.Functional#ZONE_GOAL ZoneGoal The ZoneGoal created. -- @param Functional.ZoneGoal#ZONE_GOAL ZoneGoal The ZoneGoal created.
function EVENT:CreateEventNewZoneGoal( ZoneGoal ) function EVENT:CreateEventNewZoneGoal( ZoneGoal )
self:F( { ZoneGoal } ) self:F( { ZoneGoal } )
@@ -1080,9 +1141,9 @@ function EVENT:onEvent( Event )
if Event.initiator then if Event.initiator then
Event.IniObjectCategory = Event.initiator:getCategory() Event.IniObjectCategory = Object.getCategory(Event.initiator)
if Event.IniObjectCategory == Object.Category.STATIC then if Event.IniObjectCategory == Object.Category.STATIC then
--- ---
-- Static -- Static
--- ---
@@ -1118,10 +1179,9 @@ function EVENT:onEvent( Event )
local Unit=UNIT:FindByName(Event.IniDCSUnitName) local Unit=UNIT:FindByName(Event.IniDCSUnitName)
if Unit then if Unit then
Event.IniObjectCategory = Object.Category.UNIT Event.IniObjectCategory = Object.Category.UNIT
end end
end
if Event.IniObjectCategory == Object.Category.UNIT then elseif Event.IniObjectCategory == Object.Category.UNIT then
--- ---
-- Unit -- Unit
--- ---
@@ -1144,12 +1204,19 @@ function EVENT:onEvent( Event )
end end
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName() Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
if Event.IniPlayerName then
-- get UUCID
local PID = NET.GetPlayerIDByName(nil,Event.IniPlayerName)
if PID then
Event.IniPlayerUCID = net.get_player_info(tonumber(PID), 'ucid')
--env.info("Event.IniPlayerUCID="..tostring(Event.IniPlayerUCID),false)
end
end
Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniTypeName = Event.IniDCSUnit:getTypeName() Event.IniTypeName = Event.IniDCSUnit:getTypeName()
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniCategory = Event.IniDCSUnit:getDesc().category
end
if Event.IniObjectCategory == Object.Category.CARGO then elseif Event.IniObjectCategory == Object.Category.CARGO then
--- ---
-- Cargo -- Cargo
--- ---
@@ -1160,9 +1227,8 @@ function EVENT:onEvent( Event )
Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.IniDCSUnit:getTypeName() Event.IniTypeName = Event.IniDCSUnit:getTypeName()
end
if Event.IniObjectCategory == Object.Category.SCENERY then elseif Event.IniObjectCategory == Object.Category.SCENERY then
--- ---
-- Scenery -- Scenery
--- ---
@@ -1172,9 +1238,8 @@ function EVENT:onEvent( Event )
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator ) Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY" Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY"
end
if Event.IniObjectCategory == Object.Category.BASE then elseif Event.IniObjectCategory == Object.Category.BASE then
--- ---
-- Base Object -- Base Object
--- ---
@@ -1201,9 +1266,12 @@ function EVENT:onEvent( Event )
--- ---
-- Target category. -- Target category.
Event.TgtObjectCategory = Event.target:getCategory() Event.TgtObjectCategory = Object.getCategory(Event.target)
if Event.TgtObjectCategory == Object.Category.UNIT then if Event.TgtObjectCategory == Object.Category.UNIT then
---
-- UNIT
---
Event.TgtDCSUnit = Event.target Event.TgtDCSUnit = Event.target
Event.TgtDCSGroup = Event.TgtDCSUnit:getGroup() Event.TgtDCSGroup = Event.TgtDCSUnit:getGroup()
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName() Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
@@ -1216,21 +1284,33 @@ function EVENT:onEvent( Event )
Event.TgtGroupName = Event.TgtDCSGroupName Event.TgtGroupName = Event.TgtDCSGroupName
end end
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName() Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
if Event.TgtPlayerName then
-- get UUCID
local PID = NET.GetPlayerIDByName(nil,Event.TgtPlayerName)
if PID then
Event.TgtPlayerUCID = net.get_player_info(tonumber(PID), 'ucid')
--env.info("Event.TgtPlayerUCID="..tostring(Event.TgtPlayerUCID),false)
end
end
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition() Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName() Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
end
if Event.TgtObjectCategory == Object.Category.STATIC then elseif Event.TgtObjectCategory == Object.Category.STATIC then
-- get base data ---
-- STATIC
---
Event.TgtDCSUnit = Event.target Event.TgtDCSUnit = Event.target
if Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object if Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName() Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
Event.TgtUnitName = Event.TgtDCSUnitName -- Workaround for borked target info on cruise missiles
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false ) if Event.TgtDCSUnitName and Event.TgtDCSUnitName ~= "" then
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition() Event.TgtUnitName = Event.TgtDCSUnitName
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName() Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
end
else else
Event.TgtDCSUnitName = string.format("No target object for Event ID %s", tostring(Event.id)) Event.TgtDCSUnitName = string.format("No target object for Event ID %s", tostring(Event.id))
Event.TgtUnitName = Event.TgtDCSUnitName Event.TgtUnitName = Event.TgtDCSUnitName
@@ -1249,9 +1329,11 @@ function EVENT:onEvent( Event )
Event.TgtTypeName = "Static" Event.TgtTypeName = "Static"
end end
end end
end
if Event.TgtObjectCategory == Object.Category.SCENERY then elseif Event.TgtObjectCategory == Object.Category.SCENERY then
---
-- SCENERY
---
Event.TgtDCSUnit = Event.target Event.TgtDCSUnit = Event.target
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName() Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
Event.TgtUnitName = Event.TgtDCSUnitName Event.TgtUnitName = Event.TgtDCSUnitName
@@ -1266,7 +1348,8 @@ function EVENT:onEvent( Event )
Event.Weapon = Event.weapon Event.Weapon = Event.weapon
Event.WeaponName = Event.Weapon:getTypeName() Event.WeaponName = Event.Weapon:getTypeName()
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit! Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName() Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon.getPlayerName and Event.Weapon:getPlayerName()
--Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName()
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition() Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName() Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
@@ -1281,7 +1364,7 @@ function EVENT:onEvent( Event )
-- However, this is not a big thing, as the aircraft the pilot ejected from is usually long crashed before the ejected pilot touches the ground. -- However, this is not a big thing, as the aircraft the pilot ejected from is usually long crashed before the ejected pilot touches the ground.
--Event.Place=UNIT:Find(Event.place) --Event.Place=UNIT:Find(Event.place)
else else
if Event.place:isExist() and Event.place:getCategory() ~= Object.Category.SCENERY then if Event.place:isExist() and Object.getCategory(Event.place) ~= Object.Category.SCENERY then
Event.Place=AIRBASE:Find(Event.place) Event.Place=AIRBASE:Find(Event.place)
Event.PlaceName=Event.Place:GetName() Event.PlaceName=Event.Place:GetName()
end end

View File

@@ -249,7 +249,7 @@ do -- FSM
-- --
-- ### Linear Transition Example -- ### Linear Transition Example
-- --
-- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE/blob/master/Moose%20Test%20Missions/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua) -- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE_MISSIONS/blob/master/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua)
-- --
-- It models a unit standing still near Batumi, and flaring every 5 seconds while switching between a Green flare and a Red flare. -- It models a unit standing still near Batumi, and flaring every 5 seconds while switching between a Green flare and a Red flare.
-- The purpose of this example is not to show how exciting flaring is, but it demonstrates how a Linear Transition FSM can be build. -- The purpose of this example is not to show how exciting flaring is, but it demonstrates how a Linear Transition FSM can be build.
@@ -1260,7 +1260,7 @@ do -- FSM_PROCESS
--- Assign the process to a @{Wrapper.Unit} and activate the process. --- Assign the process to a @{Wrapper.Unit} and activate the process.
-- @param #FSM_PROCESS self -- @param #FSM_PROCESS self
-- @param Task.Tasking#TASK Task -- @param Tasking.Task#TASK Task
-- @param Wrapper.Unit#UNIT ProcessUnit -- @param Wrapper.Unit#UNIT ProcessUnit
-- @return #FSM_PROCESS self -- @return #FSM_PROCESS self
function FSM_PROCESS:Assign( ProcessUnit, Task ) function FSM_PROCESS:Assign( ProcessUnit, Task )

View File

@@ -513,7 +513,7 @@ do -- MENU_COALITION
--- @type MENU_COALITION --- @type MENU_COALITION
-- @extends Core.Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
--- Manages the main menus for @{DCS.coalition}s. --- Manages the main menus for DCS.coalition.
-- --
-- You can add menus with the @{#MENU_COALITION.New} method, which constructs a MENU_COALITION object and returns you the object reference. -- You can add menus with the @{#MENU_COALITION.New} method, which constructs a MENU_COALITION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION.Remove}.

View File

@@ -73,7 +73,7 @@ MESSAGE.Type = {
Detailed = "Detailed Report", Detailed = "Detailed Report",
} }
--- Creates a new MESSAGE object. Note that these MESSAGE objects are not yet displayed on the display panel. You must use the functions @{ToClient} or @{ToCoalition} or @{ToAll} to send these Messages to the respective recipients. --- Creates a new MESSAGE object. Note that these MESSAGE objects are not yet displayed on the display panel. You must use the functions @{#MESSAGE.ToClient} or @{#MESSAGE.ToCoalition} or @{#MESSAGE.ToAll} to send these Messages to the respective recipients.
-- @param self -- @param self
-- @param #string MessageText is the text of the Message. -- @param #string MessageText is the text of the Message.
-- @param #number MessageDuration is a number in seconds of how long the MESSAGE should be shown on the display panel. -- @param #number MessageDuration is a number in seconds of how long the MESSAGE should be shown on the display panel.
@@ -127,7 +127,7 @@ end
--- Creates a new MESSAGE object of a certain type. --- Creates a new MESSAGE object of a certain type.
-- Note that these MESSAGE objects are not yet displayed on the display panel. -- Note that these MESSAGE objects are not yet displayed on the display panel.
-- You must use the functions @{ToClient} or @{ToCoalition} or @{ToAll} to send these Messages to the respective recipients. -- You must use the functions @{Core.Message#ToClient} or @{Core.Message#ToCoalition} or @{Core.Message#ToAll} to send these Messages to the respective recipients.
-- The message display times are automatically defined based on the timing settings in the @{Core.Settings} menu. -- The message display times are automatically defined based on the timing settings in the @{Core.Settings} menu.
-- @param self -- @param self
-- @param #string MessageText is the text of the Message. -- @param #string MessageText is the text of the Message.
@@ -343,7 +343,7 @@ end
--- Sends a MESSAGE to a Coalition. --- Sends a MESSAGE to a Coalition.
-- @param #MESSAGE self -- @param #MESSAGE self
-- @param #DCS.coalition.side CoalitionSide @{#DCS.coalition.side} to which the message is displayed. -- @param DCS#coalition.side CoalitionSide @{#DCS.coalition.side} to which the message is displayed.
-- @param Core.Settings#SETTINGS Settings (Optional) Settings for message display. -- @param Core.Settings#SETTINGS Settings (Optional) Settings for message display.
-- @return #MESSAGE Message object. -- @return #MESSAGE Message object.
-- @usage -- @usage
@@ -379,7 +379,7 @@ end
--- Sends a MESSAGE to a Coalition if the given Condition is true. --- Sends a MESSAGE to a Coalition if the given Condition is true.
-- @param #MESSAGE self -- @param #MESSAGE self
-- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}. -- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{#DCS.coalition.side}.
-- @param #boolean Condition Sends the message only if the condition is true. -- @param #boolean Condition Sends the message only if the condition is true.
-- @return #MESSAGE self -- @return #MESSAGE self
function MESSAGE:ToCoalitionIf( CoalitionSide, Condition ) function MESSAGE:ToCoalitionIf( CoalitionSide, Condition )
@@ -465,7 +465,7 @@ _MESSAGESRS = {}
-- @param #string PathToCredentials (optional) Path to credentials file for e.g. Google. -- @param #string PathToCredentials (optional) Path to credentials file for e.g. Google.
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies. -- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
-- @param #number Modulation Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. -- @param #number Modulation Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations.
-- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "male". -- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "female".
-- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB" -- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB"
-- @param #string Voice (optional) Voice. Will override gender and culture settings, e.g. MSRS.Voices.Microsoft.Hazel or MSRS.Voices.Google.Standard.de_DE_Standard_D. Hint on Microsoft voices - working voices are limited to Hedda, Hazel, David, Zira and Hortense. **Must** be installed on your Desktop or Server! -- @param #string Voice (optional) Voice. Will override gender and culture settings, e.g. MSRS.Voices.Microsoft.Hazel or MSRS.Voices.Google.Standard.de_DE_Standard_D. Hint on Microsoft voices - working voices are limited to Hedda, Hazel, David, Zira and Hortense. **Must** be installed on your Desktop or Server!
-- @param #number Coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Defaults to coalition.side.NEUTRAL. -- @param #number Coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Defaults to coalition.side.NEUTRAL.
@@ -480,24 +480,42 @@ _MESSAGESRS = {}
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
-- --
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate) function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
_MESSAGESRS.MSRS = MSRS:New(PathToSRS,Frequency,Modulation,Volume) _MESSAGESRS.MSRS = MSRS:New(PathToSRS,Frequency or 243,Modulation or radio.modulation.AM,Volume)
_MESSAGESRS.MSRS:SetCoalition(Coalition)
_MESSAGESRS.frequency = Frequency
_MESSAGESRS.modulation = Modulation or radio.modulation.AM
_MESSAGESRS.MSRS:SetCoalition(Coalition or coalition.side.NEUTRAL)
_MESSAGESRS.coalition = Coalition or coalition.side.NEUTRAL
_MESSAGESRS.coordinate = Coordinate
_MESSAGESRS.MSRS:SetCoordinate(Coordinate) _MESSAGESRS.MSRS:SetCoordinate(Coordinate)
_MESSAGESRS.MSRS:SetCulture(Culture) _MESSAGESRS.MSRS:SetCulture(Culture)
_MESSAGESRS.Culture = Culture _MESSAGESRS.Culture = Culture or "en-GB"
--_MESSAGESRS.MSRS:SetFrequencies(Frequency)
_MESSAGESRS.MSRS:SetGender(Gender) _MESSAGESRS.MSRS:SetGender(Gender)
_MESSAGESRS.Gender = Gender _MESSAGESRS.Gender = Gender or "female"
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials) _MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
_MESSAGESRS.google = PathToCredentials
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE") _MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
--_MESSAGESRS.MSRS:SetModulations(Modulation) _MESSAGESRS.label = Label or "MESSAGE"
--_MESSAGESRS.MSRS:SetPath(PathToSRS)
_MESSAGESRS.MSRS:SetPort(Port) _MESSAGESRS.MSRS:SetPort(Port or 5002)
-- _MESSAGESRS.MSRS:SetVolume(Volume) _MESSAGESRS.port = Port or 5002
_MESSAGESRS.MSRS:SetVoice(Voice)
_MESSAGESRS.Voice = Voice _MESSAGESRS.volume = Volume or 1
_MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
_MESSAGESRS.voice = Voice --or MSRS.Voices.Microsoft.Hedda
--if _MESSAGESRS.google and not Voice then _MESSAGESRS.Voice = MSRS.Voices.Google.Standard.en_GB_Standard_A end
--_MESSAGESRS.MSRS:SetVoice(Voice or _MESSAGESRS.voice)
_MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE") _MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE")
env.info(_MESSAGESRS.MSRS.provider,false)
end end
--- Sends a message via SRS. --- Sends a message via SRS.
@@ -505,7 +523,7 @@ end
-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. -- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. -- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #string culture (optional) Culture, e.g. "en-US". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
-- @param #number coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #number coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
@@ -519,9 +537,16 @@ end
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
-- --
function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volume,coordinate) function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volume,coordinate)
local tgender = gender or _MESSAGESRS.Gender
if _MESSAGESRS.SRSQ then if _MESSAGESRS.SRSQ then
_MESSAGESRS.MSRS:SetVoice(voice or _MESSAGESRS.Voice) if voice then
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency,modulation,gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,voice or _MESSAGESRS.Voice,volume,self.MessageCategory) _MESSAGESRS.MSRS:SetVoice(voice or _MESSAGESRS.voice)
end
if coordinate then
_MESSAGESRS.MSRS:SetCoordinate(coordinate)
end
local category = string.gsub(self.MessageCategory,":","")
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency or _MESSAGESRS.frequency,modulation or _MESSAGESRS.modulation, gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,nil,volume or _MESSAGESRS.volume,category,coordinate or _MESSAGESRS.coordinate)
end end
return self return self
end end

View File

@@ -199,7 +199,7 @@ end
--- Get points of pathline. Not that points are tables, that contain more information as just the 2D or 3D position but also the surface type etc. --- Get points of pathline. Not that points are tables, that contain more information as just the 2D or 3D position but also the surface type etc.
-- @param #PATHLINE self -- @param #PATHLINE self
-- @return <#PATHLINE.Point> List of points. -- @return #list <#PATHLINE.Point> List of points.
function PATHLINE:GetPoints() function PATHLINE:GetPoints()
return self.points return self.points
end end

View File

@@ -8,22 +8,6 @@
-- --
-- === -- ===
-- --
-- # Demo Missions
--
-- ### [POINT_VEC Demo Missions source code]()
--
-- ### [POINT_VEC Demo Missions, only for beta testers]()
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ===
--
-- # YouTube Channel
--
-- ### [POINT_VEC YouTube Channel]()
--
-- ===
--
-- ### Authors: -- ### Authors:
-- --
-- * FlightControl (Design & Programming) -- * FlightControl (Design & Programming)
@@ -544,7 +528,7 @@ do -- COORDINATE
if ZoneObject then if ZoneObject then
-- Get category of scanned object. -- Get category of scanned object.
local ObjectCategory = ZoneObject:getCategory() local ObjectCategory = Object.getCategory(ZoneObject)
-- Check for unit or static objects -- Check for unit or static objects
if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() then if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() then
@@ -920,7 +904,7 @@ do -- COORDINATE
end end
--- Return an angle in radians from the COORDINATE using a direction vector in Vec3 format. --- Return an angle in radians from the COORDINATE using a **direction vector in Vec3 format**.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format. -- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @return #number DirectionRadians The angle in radians. -- @return #number DirectionRadians The angle in radians.
@@ -933,10 +917,12 @@ do -- COORDINATE
return DirectionRadians return DirectionRadians
end end
--- Return an angle in degrees from the COORDINATE using a direction vector in Vec3 format. --- Return an angle in degrees from the COORDINATE using a **direction vector in Vec3 format**.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format. -- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @return #number DirectionRadians The angle in degrees. -- @return #number DirectionRadians The angle in degrees.
-- @usage
-- local directionAngle = currentCoordinate:GetAngleDegrees(currentCoordinate:GetDirectionVec3(sourceCoordinate:GetVec3()))
function COORDINATE:GetAngleDegrees( DirectionVec3 ) function COORDINATE:GetAngleDegrees( DirectionVec3 )
local AngleRadians = self:GetAngleRadians( DirectionVec3 ) local AngleRadians = self:GetAngleRadians( DirectionVec3 )
local Angle = UTILS.ToDegree( AngleRadians ) local Angle = UTILS.ToDegree( AngleRadians )
@@ -3021,6 +3007,16 @@ do -- COORDINATE
return BRAANATO return BRAANATO
end end
--- Return the BULLSEYE as COORDINATE Object
-- @param #number Coalition Coalition of the bulls eye to return, e.g. coalition.side.BLUE
-- @return #COORDINATE self
-- @usage
-- -- note the dot (.) here,not using the colon (:)
-- local redbulls = COORDINATE.GetBullseyeCoordinate(coalition.side.RED)
function COORDINATE.GetBullseyeCoordinate(Coalition)
return COORDINATE:NewFromVec3( coalition.getMainRefPoint( Coalition ) )
end
--- Return a BULLS string out of the BULLS of the coalition to the COORDINATE. --- Return a BULLS string out of the BULLS of the coalition to the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param DCS#coalition.side Coalition The coalition. -- @param DCS#coalition.side Coalition The coalition.

View File

@@ -52,7 +52,7 @@
-- --
-- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**. -- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**.
-- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called. -- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called.
-- It is recommended to store the ScheduleID in a variable, as it is used in the methods @{SCHEDULER.Start}() and @{SCHEDULER.Stop}(), -- It is recommended to store the ScheduleID in a variable, as it is used in the methods @{#SCHEDULER.Start}() and @{#SCHEDULER.Stop}(),
-- which can start and stop specific repeating schedules respectively within a SCHEDULER object. -- which can start and stop specific repeating schedules respectively within a SCHEDULER object.
-- --
-- ## SCHEDULER constructor -- ## SCHEDULER constructor

View File

@@ -1065,8 +1065,15 @@ do
self:FilterActive( false ) self:FilterActive( false )
return self return self
--- Filter the set once
-- @function [parent=#SET_GROUP] FilterOnce
-- @param #SET_GROUP self
-- @return #SET_GROUP self
end end
--- Get a *new* set that only contains alive groups. --- Get a *new* set that only contains alive groups.
-- @param #SET_GROUP self -- @param #SET_GROUP self
-- @return #SET_GROUP Set of alive groups. -- @return #SET_GROUP Set of alive groups.
@@ -1976,6 +1983,7 @@ do
--- Get the closest group of the set with respect to a given reference coordinate. Optionally, only groups of given coalitions are considered in the search. --- Get the closest group of the set with respect to a given reference coordinate. Optionally, only groups of given coalitions are considered in the search.
-- @param #SET_GROUP self -- @param #SET_GROUP self
-- @param Core.Point#COORDINATE Coordinate Reference Coordinate from which the closest group is determined. -- @param Core.Point#COORDINATE Coordinate Reference Coordinate from which the closest group is determined.
-- @param #table Coalitions (Optional) Table of coalition #number entries to filter for.
-- @return Wrapper.Group#GROUP The closest group (if any). -- @return Wrapper.Group#GROUP The closest group (if any).
-- @return #number Distance in meters to the closest group. -- @return #number Distance in meters to the closest group.
function SET_GROUP:GetClosestGroup(Coordinate, Coalitions) function SET_GROUP:GetClosestGroup(Coordinate, Coalitions)
@@ -2425,6 +2433,26 @@ do -- SET_UNIT
return CountU return CountU
end end
--- Gets the alive set.
-- @param #SET_UNIT self
-- @return #table Table of SET objects
-- @return #SET_UNIT AliveSet
function SET_UNIT:GetAliveSet()
local AliveSet = SET_UNIT:New()
-- Clean the Set before returning with only the alive Groups.
for GroupName, GroupObject in pairs(self.Set) do
local GroupObject=GroupObject --Wrapper.Client#CLIENT
if GroupObject and GroupObject:IsAlive() then
AliveSet:Add(GroupName, GroupObject)
end
end
return AliveSet.Set or {}, AliveSet
end
--- [Internal] Private function for use of continous zone filter --- [Internal] Private function for use of continous zone filter
-- @param #SET_UNIT self -- @param #SET_UNIT self
-- @return #SET_UNIT self -- @return #SET_UNIT self
@@ -2819,51 +2847,58 @@ do -- SET_UNIT
-- @param #SET_UNIT self -- @param #SET_UNIT self
-- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units. -- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units.
function SET_UNIT:GetCoordinate() function SET_UNIT:GetCoordinate()
local Coordinate = self:GetRandom():GetCoordinate()
--self:F({Coordinate:GetVec3()})
local Coordinate = nil
local x1 = Coordinate.x local unit = self:GetRandom()
local x2 = Coordinate.x if self:Count() == 1 and unit then
local y1 = Coordinate.y return unit:GetCoordinate()
local y2 = Coordinate.y end
local z1 = Coordinate.z if unit then
local z2 = Coordinate.z local Coordinate = unit:GetCoordinate()
local MaxVelocity = 0 --self:F({Coordinate:GetVec3()})
local AvgHeading = nil
local MovingCount = 0
local x1 = Coordinate.x
for UnitName, UnitData in pairs( self:GetSet() ) do local x2 = Coordinate.x
local y1 = Coordinate.y
local Unit = UnitData -- Wrapper.Unit#UNIT local y2 = Coordinate.y
local Coordinate = Unit:GetCoordinate() local z1 = Coordinate.z
local z2 = Coordinate.z
x1 = (Coordinate.x < x1) and Coordinate.x or x1 local MaxVelocity = 0
x2 = (Coordinate.x > x2) and Coordinate.x or x2 local AvgHeading = nil
y1 = (Coordinate.y < y1) and Coordinate.y or y1 local MovingCount = 0
y2 = (Coordinate.y > y2) and Coordinate.y or y2
z1 = (Coordinate.y < z1) and Coordinate.z or z1 for UnitName, UnitData in pairs( self:GetAliveSet() ) do
z2 = (Coordinate.y > z2) and Coordinate.z or z2
local Unit = UnitData -- Wrapper.Unit#UNIT
local Velocity = Coordinate:GetVelocity() local Coordinate = Unit:GetCoordinate()
if Velocity ~= 0 then
MaxVelocity = (MaxVelocity < Velocity) and Velocity or MaxVelocity x1 = (Coordinate.x < x1) and Coordinate.x or x1
local Heading = Coordinate:GetHeading() x2 = (Coordinate.x > x2) and Coordinate.x or x2
AvgHeading = AvgHeading and (AvgHeading + Heading) or Heading y1 = (Coordinate.y < y1) and Coordinate.y or y1
MovingCount = MovingCount + 1 y2 = (Coordinate.y > y2) and Coordinate.y or y2
end z1 = (Coordinate.y < z1) and Coordinate.z or z1
z2 = (Coordinate.y > z2) and Coordinate.z or z2
local Velocity = Coordinate:GetVelocity()
if Velocity ~= 0 then
MaxVelocity = (MaxVelocity < Velocity) and Velocity or MaxVelocity
local Heading = Coordinate:GetHeading()
AvgHeading = AvgHeading and (AvgHeading + Heading) or Heading
MovingCount = MovingCount + 1
end
end
AvgHeading = AvgHeading and (AvgHeading / MovingCount)
Coordinate.x = (x2 - x1) / 2 + x1
Coordinate.y = (y2 - y1) / 2 + y1
Coordinate.z = (z2 - z1) / 2 + z1
Coordinate:SetHeading( AvgHeading )
Coordinate:SetVelocity( MaxVelocity )
self:F( { Coordinate = Coordinate } )
end end
AvgHeading = AvgHeading and (AvgHeading / MovingCount)
Coordinate.x = (x2 - x1) / 2 + x1
Coordinate.y = (y2 - y1) / 2 + y1
Coordinate.z = (z2 - z1) / 2 + z1
Coordinate:SetHeading( AvgHeading )
Coordinate:SetVelocity( MaxVelocity )
self:F( { Coordinate = Coordinate } )
return Coordinate return Coordinate
end end
@@ -4317,6 +4352,8 @@ do -- SET_CLIENT
self:UnHandleEvent(EVENTS.Birth) self:UnHandleEvent(EVENTS.Birth)
self:UnHandleEvent(EVENTS.Dead) self:UnHandleEvent(EVENTS.Dead)
self:UnHandleEvent(EVENTS.Crash) self:UnHandleEvent(EVENTS.Crash)
--self:UnHandleEvent(EVENTS.PlayerEnterUnit)
--self:UnHandleEvent(EVENTS.PlayerLeaveUnit)
if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then
self.ZoneTimer:Stop() self.ZoneTimer:Stop()
@@ -4335,6 +4372,9 @@ do -- SET_CLIENT
self:HandleEvent( EVENTS.Birth, self._EventOnBirth ) self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
--self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventPlayerEnterUnit)
--self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventPlayerLeaveUnit)
--self:SetEventPriority(1)
if self.Filter.Zones then if self.Filter.Zones then
self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self) self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self)
local timing = self.ZoneTimerInterval or 30 local timing = self.ZoneTimerInterval or 30
@@ -4345,6 +4385,43 @@ do -- SET_CLIENT
return self return self
end end
--- Handle CA slots addition
-- @param #SET_CLIENT self
-- @param Core.Event#EVENTDATA Event
-- @return #SET_CLIENT self
function SET_CLIENT:_EventPlayerEnterUnit(Event)
self:I( "_EventPlayerEnterUnit" )
if Event.IniDCSUnit then
if Event.IniObjectCategory == 1 and Event.IniGroup and Event.IniGroup:IsGround() then
-- CA Slot entered
local ObjectName, Object = self:AddInDatabase( Event )
self:I( ObjectName, UTILS.PrintTableToLog(Object) )
if Object and self:IsIncludeObject( Object ) then
self:Add( ObjectName, Object )
end
end
end
return self
end
--- Handle CA slots removal
-- @param #SET_CLIENT self
-- @param Core.Event#EVENTDATA Event
-- @return #SET_CLIENT self
function SET_CLIENT:_EventPlayerLeaveUnit(Event)
self:I( "_EventPlayerLeaveUnit" )
if Event.IniDCSUnit then
if Event.IniObjectCategory == 1 and Event.IniGroup and Event.IniGroup:IsGround() then
-- CA Slot left
local ObjectName, Object = self:FindInDatabase( Event )
if ObjectName then
self:Remove( ObjectName )
end
end
end
return self
end
--- Handles the Database to check on an event (birth) that the Object was added in the Database. --- Handles the Database to check on an event (birth) that the Object was added in the Database.
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event! -- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
@@ -5471,7 +5548,7 @@ do -- SET_CARGO
--- (R2.1) Remove CARGOs from SET_CARGO. --- (R2.1) Remove CARGOs from SET_CARGO.
-- @param Core.Set#SET_CARGO self -- @param Core.Set#SET_CARGO self
-- @param Wrapper.Cargo#CARGO RemoveCargoNames A single name or an array of CARGO names. -- @param Cargo.Cargo#CARGO RemoveCargoNames A single name or an array of CARGO names.
-- @return Core.Set#SET_CARGO self -- @return Core.Set#SET_CARGO self
function SET_CARGO:RemoveCargosByName( RemoveCargoNames ) -- R2.1 function SET_CARGO:RemoveCargosByName( RemoveCargoNames ) -- R2.1
@@ -5487,7 +5564,7 @@ do -- SET_CARGO
--- (R2.1) Finds a Cargo based on the Cargo Name. --- (R2.1) Finds a Cargo based on the Cargo Name.
-- @param #SET_CARGO self -- @param #SET_CARGO self
-- @param #string CargoName -- @param #string CargoName
-- @return Wrapper.Cargo#CARGO The found Cargo. -- @return Cargo.Cargo#CARGO The found Cargo.
function SET_CARGO:FindCargo( CargoName ) -- R2.1 function SET_CARGO:FindCargo( CargoName ) -- R2.1
local CargoFound = self.Set[CargoName] local CargoFound = self.Set[CargoName]
@@ -5630,7 +5707,7 @@ do -- SET_CARGO
--- (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#POINT_VEC2}.
-- @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#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest @{Cargo.Cargo#CARGO}.
-- @return Wrapper.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( PointVec2 ) -- R2.1
self:F2( PointVec2 ) self:F2( PointVec2 )
@@ -6195,7 +6272,7 @@ do -- SET_ZONE
--- Start watching if the Object or Objects move into or out of our set of zones. --- Start watching if the Object or Objects move into or out of our set of zones.
-- @param #SET_ZONE self -- @param #SET_ZONE self
-- @param Wrappe.Controllable#CONTROLLABLE Objects Object or Objects to watch, can be of type UNIT, GROUP, CLIENT, or SET\_UNIT, SET\_GROUP, SET\_CLIENT -- @param Wrapper.Controllable#CONTROLLABLE Objects Object or Objects to watch, can be of type UNIT, GROUP, CLIENT, or SET\_UNIT, SET\_GROUP, SET\_CLIENT
-- @return #SET_ZONE self -- @return #SET_ZONE self
-- @usage -- @usage
-- -- Create a SET_GROUP and a SET_ZONE for this: -- -- Create a SET_GROUP and a SET_ZONE for this:

View File

@@ -91,7 +91,7 @@
-- --
-- Will customize which display format is used to indicate A2G coordinates in text as part of the Command Center communications. -- Will customize which display format is used to indicate A2G coordinates in text as part of the Command Center communications.
-- --
-- - A2G BR: [Bearing Range](https://en.wikipedia.org/wiki/Bearing_(navigation)). -- - A2G BR: [Bearing Range](https://en.wikipedia.org/wiki/Bearing_\(navigation\)).
-- - A2G MGRS: The [Military Grid Reference System](https://en.wikipedia.org/wiki/Military_Grid_Reference_System). The accuracy can also be adapted. -- - A2G MGRS: The [Military Grid Reference System](https://en.wikipedia.org/wiki/Military_Grid_Reference_System). The accuracy can also be adapted.
-- - A2G LL DMS: Latitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted. -- - A2G LL DMS: Latitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted.
-- - A2G LL DDM: Latitude Longitude [Decimal Degrees Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted. -- - A2G LL DDM: Latitude Longitude [Decimal Degrees Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted.
@@ -105,9 +105,9 @@
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
-- --
-- - @{#SETTINGS.SetA2G_BR}(): Enable the BR display formatting by default. -- - @{#SETTINGS.SetA2G_BR}(): Enable the BR display formatting by default.
-- - @{#SETTINGS.SetA2G_MGRS}(): Enable the MGRS display formatting by default. Use @{SETTINGS.SetMGRS_Accuracy}() to adapt the accuracy of the MGRS formatting. -- - @{#SETTINGS.SetA2G_MGRS}(): Enable the MGRS display formatting by default. Use @{#SETTINGS.SetMGRS_Accuracy}() to adapt the accuracy of the MGRS formatting.
-- - @{#SETTINGS.SetA2G_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2G_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{#SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
-- - @{#SETTINGS.SetA2G_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2G_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{#SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
-- --
-- ### 3.1.4) A2G coordinates setting - additional notes -- ### 3.1.4) A2G coordinates setting - additional notes
-- --
@@ -120,7 +120,7 @@
-- --
-- Will customize which display format is used to indicate A2A coordinates in text as part of the Command Center communications. -- Will customize which display format is used to indicate A2A coordinates in text as part of the Command Center communications.
-- --
-- - A2A BRAA: [Bearing Range Altitude Aspect](https://en.wikipedia.org/wiki/Bearing_(navigation)). -- - A2A BRAA: [Bearing Range Altitude Aspect](https://en.wikipedia.org/wiki/Bearing_\(navigation\)).
-- - A2A MGRS: The [Military Grid Reference System](https://en.wikipedia.org/wiki/Military_Grid_Reference_System). The accuracy can also be adapted. -- - A2A MGRS: The [Military Grid Reference System](https://en.wikipedia.org/wiki/Military_Grid_Reference_System). The accuracy can also be adapted.
-- - A2A LL DMS: Lattitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted. -- - A2A LL DMS: Lattitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted.
-- - A2A LL DDM: Lattitude Longitude [Decimal Degrees and Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted. -- - A2A LL DDM: Lattitude Longitude [Decimal Degrees and Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted.
@@ -135,9 +135,9 @@
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
-- --
-- - @{#SETTINGS.SetA2A_BRAA}(): Enable the BR display formatting by default. -- - @{#SETTINGS.SetA2A_BRAA}(): Enable the BR display formatting by default.
-- - @{#SETTINGS.SetA2A_MGRS}(): Enable the MGRS display formatting by default. Use @{SETTINGS.SetMGRS_Accuracy}() to adapt the accuracy of the MGRS formatting. -- - @{#SETTINGS.SetA2A_MGRS}(): Enable the MGRS display formatting by default. Use @{#SETTINGS.SetMGRS_Accuracy}() to adapt the accuracy of the MGRS formatting.
-- - @{#SETTINGS.SetA2A_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2A_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{#SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
-- - @{#SETTINGS.SetA2A_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2A_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{#SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
-- - @{#SETTINGS.SetA2A_BULLS}(): Enable the BULLSeye display formatting by default. -- - @{#SETTINGS.SetA2A_BULLS}(): Enable the BULLSeye display formatting by default.
-- --
-- ### 3.2.4) A2A coordinates settings - additional notes -- ### 3.2.4) A2A coordinates settings - additional notes
@@ -190,8 +190,8 @@
-- --
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
-- --
-- - @{#SETTINGS.SetMessageTime}(): Define for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds. -- - @{#SETTINGS.SetMessageTime}(): Define for a specific @{Core.Message#MESSAGE.MessageType} the duration to be displayed in seconds.
-- - @{#SETTINGS.GetMessageTime}(): Retrieves for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds. -- - @{#SETTINGS.GetMessageTime}(): Retrieves for a specific @{Core.Message#MESSAGE.MessageType} the duration to be displayed in seconds.
-- --
-- ## 3.5) **Era** of the battle -- ## 3.5) **Era** of the battle
-- --
@@ -283,21 +283,21 @@ do -- SETTINGS
function SETTINGS:SetMetric() function SETTINGS:SetMetric()
self.Metric = true self.Metric = true
end end
--- Sets the SETTINGS default text locale. --- Sets the SETTINGS default text locale.
-- @param #SETTINGS self -- @param #SETTINGS self
-- @param #string Locale -- @param #string Locale
function SETTINGS:SetLocale(Locale) function SETTINGS:SetLocale(Locale)
self.Locale = Locale or "en" self.Locale = Locale or "en"
end end
--- Gets the SETTINGS text locale. --- Gets the SETTINGS text locale.
-- @param #SETTINGS self -- @param #SETTINGS self
-- @return #string -- @return #string
function SETTINGS:GetLocale() function SETTINGS:GetLocale()
return self.Locale or _SETTINGS:GetLocale() return self.Locale or _SETTINGS:GetLocale()
end end
--- Gets if the SETTINGS is metric. --- Gets if the SETTINGS is metric.
-- @param #SETTINGS self -- @param #SETTINGS self
-- @return #boolean true if metric. -- @return #boolean true if metric.

View File

@@ -58,7 +58,7 @@
-- @field #SPAWN.SpawnZoneTable SpawnZoneTable -- @field #SPAWN.SpawnZoneTable SpawnZoneTable
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- Allows to spawn dynamically new @{Core.Group}s. --- Allows to spawn dynamically new @{Wrapper.Group}s.
-- --
-- Each SPAWN object needs to be have related **template groups** setup in the Mission Editor (ME), -- Each SPAWN object needs to be have related **template groups** setup in the Mission Editor (ME),
-- which is a normal group with the **Late Activation** flag set. -- which is a normal group with the **Late Activation** flag set.
@@ -320,7 +320,7 @@ function SPAWN:New( SpawnTemplatePrefix )
self.AIOnOff = true -- The AI is on by default when spawning a group. self.AIOnOff = true -- The AI is on by default when spawning a group.
self.SpawnUnControlled = false self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name. self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group. self.DelayOnOff = false -- No initial delay when spawning the first group.
self.SpawnGrouping = nil -- No grouping. self.SpawnGrouping = nil -- No grouping.
self.SpawnInitLivery = nil -- No special livery. self.SpawnInitLivery = nil -- No special livery.
self.SpawnInitSkill = nil -- No special skill. self.SpawnInitSkill = nil -- No special skill.
@@ -332,6 +332,7 @@ function SPAWN:New( SpawnTemplatePrefix )
self.SpawnInitModexPostfix = nil self.SpawnInitModexPostfix = nil
self.SpawnInitAirbase = nil self.SpawnInitAirbase = nil
self.TweakedTemplate = false -- Check if the user is using self made template. self.TweakedTemplate = false -- Check if the user is using self made template.
self.SpawnRandomCallsign = false
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned. self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else else
@@ -1099,6 +1100,14 @@ function SPAWN:InitRandomizeZones( SpawnZoneTable )
return self return self
end end
--- [AIR/Fighter only!] This method randomizes the callsign for a new group.
-- @param #SPAWN self
-- @return #SPAWN self
function SPAWN:InitRandomizeCallsign()
self.SpawnRandomCallsign = true
return self
end
--- This method sets a spawn position for the group that is different from the location of the template. --- This method sets a spawn position for the group that is different from the location of the template.
-- @param #SPAWN self -- @param #SPAWN self
-- @param Core.Point#COORDINATE Coordinate The position to spawn from -- @param Core.Point#COORDINATE Coordinate The position to spawn from
@@ -1331,7 +1340,7 @@ do -- Delay methods
return self return self
end end
--- Turns the Delay On for the @{Wrapper.Group} when spawning with @{SpawnScheduled}(). In effect then the 1st group will only be spawned --- Turns the Delay On for the @{Wrapper.Group} when spawning with @{#SpawnScheduled}(). In effect then the 1st group will only be spawned
-- after the number of seconds given in SpawnScheduled as arguments, and not immediately. -- after the number of seconds given in SpawnScheduled as arguments, and not immediately.
-- @param #SPAWN self -- @param #SPAWN self
-- @return #SPAWN The SPAWN object -- @return #SPAWN The SPAWN object
@@ -1669,7 +1678,7 @@ end
-- @param #number SpawnTimeVariation The variation to be applied on the defined time interval between each new spawn. -- @param #number SpawnTimeVariation The variation to be applied on the defined time interval between each new spawn.
-- The variation is a number between 0 and 1, representing the % of variation to be applied on the time interval. -- The variation is a number between 0 and 1, representing the % of variation to be applied on the time interval.
-- @param #boolean WithDelay Do not spawn the **first** group immediately, but delay the spawn as per the calculation below. -- @param #boolean WithDelay Do not spawn the **first** group immediately, but delay the spawn as per the calculation below.
-- Effectively the same as @{InitDelayOn}(). -- Effectively the same as @{#InitDelayOn}().
-- @return #SPAWN self -- @return #SPAWN self
-- @usage -- @usage
-- -- NATO helicopters engaging in the battle field. -- -- NATO helicopters engaging in the battle field.
@@ -2783,7 +2792,7 @@ end
-- @return Wrapper.Group#GROUP that was spawned or #nil if nothing was spawned. -- @return Wrapper.Group#GROUP that was spawned or #nil if nothing was spawned.
-- @usage -- @usage
-- --
-- local SpawnPointVec2 = ZONE:New( ZoneName ):GetPointVec2() -- local SpawnPointVec2 = ZONE:New( ZoneName ):GetPointVec2()
-- --
-- -- Spawn at the zone center position at the height specified in the ME of the group template! -- -- Spawn at the zone center position at the height specified in the ME of the group template!
-- SpawnAirplanes:SpawnFromPointVec2( SpawnPointVec2 ) -- SpawnAirplanes:SpawnFromPointVec2( SpawnPointVec2 )
@@ -3275,22 +3284,143 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
end end
-- Callsign -- Callsign
if self.SpawnRandomCallsign and SpawnTemplate.units[1].callsign then
if type( SpawnTemplate.units[1].callsign ) ~= "number" then
-- change callsign
local min = 1
local max = 8
local ctable = CALLSIGN.Aircraft
if string.find(SpawnTemplate.units[1].type, "A-10",1,true) then
max = 12
end
if string.find(SpawnTemplate.units[1].type, "18",1,true) then
min = 9
max = 20
ctable = CALLSIGN.F18
end
if string.find(SpawnTemplate.units[1].type, "16",1,true) then
min = 9
max = 20
ctable = CALLSIGN.F16
end
if SpawnTemplate.units[1].type == "F-15E" then
min = 9
max = 18
ctable = CALLSIGN.F15E
end
local callsignnr = math.random(min,max)
local callsignname = "Enfield"
for name, value in pairs(ctable) do
if value==callsignnr then
callsignname = name
end
end
for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].callsign[1] = callsignnr
SpawnTemplate.units[UnitID].callsign[2] = UnitID
SpawnTemplate.units[UnitID].callsign[3] = "1"
SpawnTemplate.units[UnitID].callsign["name"] = tostring(callsignname)..tostring(UnitID).."1"
-- UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].callsign,1)
end
else
-- Russkis
for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].callsign = math.random(1,999)
end
end
end
for UnitID = 1, #SpawnTemplate.units do for UnitID = 1, #SpawnTemplate.units do
local Callsign = SpawnTemplate.units[UnitID].callsign local Callsign = SpawnTemplate.units[UnitID].callsign
if Callsign then if Callsign then
if type( Callsign ) ~= "number" then -- blue callsign if type( Callsign ) ~= "number" then -- blue callsign
-- UTILS.PrintTableToLog(Callsign,1)
Callsign[2] = ((SpawnIndex - 1) % 10) + 1 Callsign[2] = ((SpawnIndex - 1) % 10) + 1
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers
local CallsignLen = CallsignName:len() local CallsignLen = CallsignName:len()
SpawnTemplate.units[UnitID].callsign[2] = UnitID
SpawnTemplate.units[UnitID].callsign["name"] = CallsignName:sub( 1, CallsignLen ) .. SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3] SpawnTemplate.units[UnitID].callsign["name"] = CallsignName:sub( 1, CallsignLen ) .. SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
else else
SpawnTemplate.units[UnitID].callsign = Callsign + SpawnIndex SpawnTemplate.units[UnitID].callsign = Callsign + SpawnIndex
end end
end end
-- Link16
local AddProps = SpawnTemplate.units[UnitID].AddPropAircraft
if AddProps then
if SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 then
-- 4 digit octal with leading 0
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16) ~= nil then
local octal = SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16
local decimal = UTILS.OctalToDecimal(octal)+UnitID-1
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",UTILS.DecimalToOctal(decimal))
else -- ED bug - chars in here
local STN = math.floor(UTILS.RandomGaussian(4088/2,nil,1000,4088))
STN = STN+UnitID-1
local OSTN = UTILS.DecimalToOctal(STN)
SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",OSTN)
end
end
-- A10CII
if SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN then
-- 3 digit octal with leading 0
if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN) ~= nil then
local octal = SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN
local decimal = UTILS.OctalToDecimal(octal)+UnitID-1
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",UTILS.DecimalToOctal(decimal))
else -- ED bug - chars in here
local STN = math.floor(UTILS.RandomGaussian(504/2,nil,100,504))
STN = STN+UnitID-1
local OSTN = UTILS.DecimalToOctal(STN)
SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",OSTN)
end
end
-- VoiceCallsignNumber
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber then
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber = SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
end
-- VoiceCallsignLabel
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel then
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers
local label = "NY" -- Navy One exception
if not string.find(CallsignName," ") then
label = string.upper(string.match(CallsignName,"^%a")..string.match(CallsignName,"%a$"))
end
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel = label
end
-- UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].AddPropAircraft,1)
-- FlightLead
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.Link16 and SpawnTemplate.units[UnitID].datalinks.Link16.settings then
SpawnTemplate.units[UnitID].datalinks.Link16.settings.flightLead = UnitID == 1 and true or false
end
-- A10CII
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.SADL and SpawnTemplate.units[UnitID].datalinks.SADL.settings then
SpawnTemplate.units[UnitID].datalinks.SADL.settings.flightLead = UnitID == 1 and true or false
end
-- UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].datalinks,1)
end
end
-- Link16 team members
for UnitID = 1, #SpawnTemplate.units do
if SpawnTemplate.units[UnitID].datalinks and SpawnTemplate.units[UnitID].datalinks.Link16 and SpawnTemplate.units[UnitID].datalinks.Link16.network then
local team = {}
local isF16 = string.find(SpawnTemplate.units[UnitID].type,"F-16",1,true) and true or false
for ID = 1, #SpawnTemplate.units do
local member = {}
member.missionUnitId = ID
if isF16 then
member.TDOA = true
end
table.insert(team,member)
end
SpawnTemplate.units[UnitID].datalinks.Link16.network.teamMembers = team
end
end end
self:T3( { "Template:", SpawnTemplate } ) self:T3( { "Template:", SpawnTemplate } )
--UTILS.PrintTableToLog(SpawnTemplate,1)
return SpawnTemplate return SpawnTemplate
end end
@@ -3622,7 +3752,7 @@ function SPAWN:_OnLand( EventData )
end end
--- Will detect AIR Units shutting down their engines ... --- Will detect AIR Units shutting down their engines ...
-- When the event takes place, and the method @{RepeatOnEngineShutDown} was called, the spawned Group will Re-SPAWN. -- When the event takes place, and the method @{#InitRepeatOnEngineShutDown} was called, the spawned Group will Re-SPAWN.
-- But only when the Unit was registered to have landed. -- But only when the Unit was registered to have landed.
-- @param #SPAWN self -- @param #SPAWN self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData

View File

@@ -21,9 +21,9 @@
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- ### Contributions: -- ### Contributions:
-- --
-- * [**Ciribob**](https://forums.eagle.ru/member.php?u=112175): Showing the way how to lase targets + how laser codes work!!! Explained the autolase script. -- * **Ciribob**: Showing the way how to lase targets + how laser codes work!!! Explained the autolase script.
-- * [**EasyEB**](https://forums.eagle.ru/member.php?u=112055): Ideas and Beta Testing -- * **EasyEB**: Ideas and Beta Testing
-- * [**Wingthor**](https://forums.eagle.ru/member.php?u=123698): Beta Testing -- * **Wingthor**: Beta Testing
-- --
-- === -- ===
-- --
@@ -329,14 +329,14 @@ do
if self.Lasing then if self.Lasing then
if self.Target and self.Target:IsAlive() then if self.Target and self.Target:IsAlive() then
self.SpotIR:setPoint( self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/100):AddX(math.random(-100,100)/100):GetVec3() ) self.SpotIR:setPoint( self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/200):AddX(math.random(-100,100)/200):GetVec3() )
self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() ) self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() )
self:__Lasing(0.2) self:__Lasing(0.2)
elseif self.TargetCoord then elseif self.TargetCoord then
-- Wiggle the IR spot a bit. -- Wiggle the IR spot a bit.
local irvec3={x=self.TargetCoord.x+math.random(-100,100)/100, y=self.TargetCoord.y+math.random(-100,100)/100, z=self.TargetCoord.z} --#DCS.Vec3 local irvec3={x=self.TargetCoord.x+math.random(-100,100)/200, y=self.TargetCoord.y+math.random(-100,100)/200, z=self.TargetCoord.z} --#DCS.Vec3
local lsvec3={x=self.TargetCoord.x, y=self.TargetCoord.y, z=self.TargetCoord.z} --#DCS.Vec3 local lsvec3={x=self.TargetCoord.x, y=self.TargetCoord.y, z=self.TargetCoord.z} --#DCS.Vec3
self.SpotIR:setPoint(irvec3) self.SpotIR:setPoint(irvec3)

File diff suppressed because it is too large Load Diff

View File

@@ -20,13 +20,15 @@
-- ### Author: FlightControl - Framework Design & Programming -- ### Author: FlightControl - Framework Design & Programming
-- ### Refactoring to use the Runway auto-detection: Applevangelist -- ### Refactoring to use the Runway auto-detection: Applevangelist
-- @date August 2022 -- @date August 2022
-- Last Update Nov 2023
-- --
-- === -- ===
-- --
-- @module Functional.ATC_Ground -- @module Functional.ATC_Ground
-- @image Air_Traffic_Control_Ground_Operations.JPG -- @image Air_Traffic_Control_Ground_Operations.JPG
--- @type ATC_GROUND ---
-- @type ATC_GROUND
-- @field Core.Set#SET_CLIENT SetClient -- @field Core.Set#SET_CLIENT SetClient
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@@ -39,7 +41,8 @@ ATC_GROUND = {
AirbaseNames = nil, AirbaseNames = nil,
} }
--- @type ATC_GROUND.AirbaseNames ---
-- @type ATC_GROUND.AirbaseNames
-- @list <#string> -- @list <#string>
@@ -51,7 +54,7 @@ function ATC_GROUND:New( Airbases, AirbaseList )
-- Inherits from BASE -- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND
self:E( { self.ClassName, Airbases } ) self:T( { self.ClassName, Airbases } )
self.Airbases = Airbases self.Airbases = Airbases
self.AirbaseList = AirbaseList self.AirbaseList = AirbaseList
@@ -82,7 +85,7 @@ function ATC_GROUND:New( Airbases, AirbaseList )
end end
self.SetClient:ForEachClient( self.SetClient:ForEachClient(
--- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
function( Client ) function( Client )
Client:SetState( self, "Speeding", false ) Client:SetState( self, "Speeding", false )
Client:SetState( self, "Warnings", 0) Client:SetState( self, "Warnings", 0)
@@ -246,11 +249,11 @@ function ATC_GROUND:SetMaximumKickSpeedMiph( MaximumKickSpeedMiph, Airbase )
return self return self
end end
--- @param #ATC_GROUND self -- @param #ATC_GROUND self
function ATC_GROUND:_AirbaseMonitor() function ATC_GROUND:_AirbaseMonitor()
self.SetClient:ForEachClient( self.SetClient:ForEachClient(
--- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
function( Client ) function( Client )
if Client:IsAlive() then if Client:IsAlive() then
@@ -258,7 +261,7 @@ function ATC_GROUND:_AirbaseMonitor()
local IsOnGround = Client:InAir() == false local IsOnGround = Client:InAir() == false
for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do
self:E( AirbaseID, AirbaseMeta.KickSpeed ) self:T( AirbaseID, AirbaseMeta.KickSpeed )
if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then
@@ -271,7 +274,7 @@ function ATC_GROUND:_AirbaseMonitor()
if IsOnGround then if IsOnGround then
local Taxi = Client:GetState( self, "Taxi" ) local Taxi = Client:GetState( self, "Taxi" )
self:E( Taxi ) self:T( Taxi )
if Taxi == false then if Taxi == false then
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed ) local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " .. Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
@@ -331,7 +334,7 @@ function ATC_GROUND:_AirbaseMonitor()
Client:SetState( self, "Warnings", SpeedingWarnings + 1 ) Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
else else
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll() MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
--- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
Client:Destroy() Client:Destroy()
Client:SetState( self, "Speeding", false ) Client:SetState( self, "Speeding", false )
Client:SetState( self, "Warnings", 0 ) Client:SetState( self, "Warnings", 0 )
@@ -363,7 +366,7 @@ function ATC_GROUND:_AirbaseMonitor()
Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 ) Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 )
else else
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll() MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
--- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
Client:Destroy() Client:Destroy()
Client:SetState( self, "IsOffRunway", false ) Client:SetState( self, "IsOffRunway", false )
Client:SetState( self, "OffRunwayWarnings", 0 ) Client:SetState( self, "OffRunwayWarnings", 0 )
@@ -424,13 +427,20 @@ ATC_GROUND_UNIVERSAL = {
--- Creates a new ATC\_GROUND\_UNIVERSAL object. This works on any map. --- Creates a new ATC\_GROUND\_UNIVERSAL object. This works on any map.
-- @param #ATC_GROUND_UNIVERSAL self -- @param #ATC_GROUND_UNIVERSAL self
-- @param AirbaseList (Optional) A table of Airbase Names. -- @param AirbaseList A table of Airbase Names. Leave empty to cover **all** airbases of the map.
-- @return #ATC_GROUND_UNIVERSAL self -- @return #ATC_GROUND_UNIVERSAL self
-- @usage
-- -- define monitoring for one airbase
-- local atc=ATC_GROUND_UNIVERSAL:New({AIRBASE.Syria.Gecitkale})
-- -- set kick speed
-- atc:SetKickSpeed(UTILS.KnotsToMps(20))
-- -- start monitoring evey 10 secs
-- atc:Start(10)
function ATC_GROUND_UNIVERSAL:New(AirbaseList) function ATC_GROUND_UNIVERSAL:New(AirbaseList)
-- Inherits from BASE -- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND
self:E( { self.ClassName } ) self:T( { self.ClassName } )
self.Airbases = {} self.Airbases = {}
@@ -440,6 +450,13 @@ function ATC_GROUND_UNIVERSAL:New(AirbaseList)
self.AirbaseList = AirbaseList self.AirbaseList = AirbaseList
if not self.AirbaseList then
self.AirbaseList = {}
for _name,_ in pairs(_DATABASE.AIRBASES) do
self.AirbaseList[_name]=_name
end
end
self.SetClient = SET_CLIENT:New():FilterCategories( "plane" ):FilterStart() self.SetClient = SET_CLIENT:New():FilterCategories( "plane" ):FilterStart()
@@ -460,8 +477,9 @@ function ATC_GROUND_UNIVERSAL:New(AirbaseList)
self.Airbases[AirbaseName].Monitor = true self.Airbases[AirbaseName].Monitor = true
end end
self.SetClient:ForEachClient( self.SetClient:ForEachClient(
--- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
function( Client ) function( Client )
Client:SetState( self, "Speeding", false ) Client:SetState( self, "Speeding", false )
Client:SetState( self, "Warnings", 0) Client:SetState( self, "Warnings", 0)
@@ -679,7 +697,7 @@ end
-- @param #ATC_GROUND_UNIVERSAL self -- @param #ATC_GROUND_UNIVERSAL self
-- @return #ATC_GROUND_UNIVERSAL self -- @return #ATC_GROUND_UNIVERSAL self
function ATC_GROUND_UNIVERSAL:_AirbaseMonitor() function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
self:I("_AirbaseMonitor")
self.SetClient:ForEachClient( self.SetClient:ForEachClient(
--- @param Wrapper.Client#CLIENT Client --- @param Wrapper.Client#CLIENT Client
function( Client ) function( Client )
@@ -689,7 +707,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
local IsOnGround = Client:InAir() == false local IsOnGround = Client:InAir() == false
for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do
self:E( AirbaseID, AirbaseMeta.KickSpeed ) self:T( AirbaseID, AirbaseMeta.KickSpeed )
if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then
@@ -706,7 +724,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
if IsOnGround then if IsOnGround then
local Taxi = Client:GetState( self, "Taxi" ) local Taxi = Client:GetState( self, "Taxi" )
self:E( Taxi ) self:T( Taxi )
if Taxi == false then if Taxi == false then
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed ) local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " .. Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
@@ -766,7 +784,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
Client:SetState( self, "Warnings", SpeedingWarnings + 1 ) Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
else else
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll() MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
--- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
Client:Destroy() Client:Destroy()
Client:SetState( self, "Speeding", false ) Client:SetState( self, "Speeding", false )
Client:SetState( self, "Warnings", 0 ) Client:SetState( self, "Warnings", 0 )
@@ -798,7 +816,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 ) Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 )
else else
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll() MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
--- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
Client:Destroy() Client:Destroy()
Client:SetState( self, "IsOffRunway", false ) Client:SetState( self, "IsOffRunway", false )
Client:SetState( self, "OffRunwayWarnings", 0 ) Client:SetState( self, "OffRunwayWarnings", 0 )
@@ -838,15 +856,16 @@ end
--- Start SCHEDULER for ATC_GROUND_UNIVERSAL object. --- Start SCHEDULER for ATC_GROUND_UNIVERSAL object.
-- @param #ATC_GROUND_UNIVERSAL self -- @param #ATC_GROUND_UNIVERSAL self
-- @param RepeatScanSeconds Time in second for defining occurency of alerts. -- @param RepeatScanSeconds Time in second for defining schedule of alerts.
-- @return #ATC_GROUND_UNIVERSAL self -- @return #ATC_GROUND_UNIVERSAL self
function ATC_GROUND_UNIVERSAL:Start( RepeatScanSeconds ) function ATC_GROUND_UNIVERSAL:Start( RepeatScanSeconds )
RepeatScanSeconds = RepeatScanSeconds or 0.05 RepeatScanSeconds = RepeatScanSeconds or 0.05
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds ) self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
return self return self
end end
--- @type ATC_GROUND_CAUCASUS ---
-- @type ATC_GROUND_CAUCASUS
-- @extends #ATC_GROUND -- @extends #ATC_GROUND
--- # ATC\_GROUND\_CAUCASUS, extends @{#ATC_GROUND_UNIVERSAL} --- # ATC\_GROUND\_CAUCASUS, extends @{#ATC_GROUND_UNIVERSAL}
@@ -981,12 +1000,12 @@ end
-- @return nothing -- @return nothing
function ATC_GROUND_CAUCASUS:Start( RepeatScanSeconds ) function ATC_GROUND_CAUCASUS:Start( RepeatScanSeconds )
RepeatScanSeconds = RepeatScanSeconds or 0.05 RepeatScanSeconds = RepeatScanSeconds or 0.05
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds ) self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
end end
---
--- @type ATC_GROUND_NEVADA -- @type ATC_GROUND_NEVADA
-- @extends #ATC_GROUND -- @extends #ATC_GROUND
@@ -1120,11 +1139,11 @@ end
-- @return nothing -- @return nothing
function ATC_GROUND_NEVADA:Start( RepeatScanSeconds ) function ATC_GROUND_NEVADA:Start( RepeatScanSeconds )
RepeatScanSeconds = RepeatScanSeconds or 0.05 RepeatScanSeconds = RepeatScanSeconds or 0.05
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds ) self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
end end
---
--- @type ATC_GROUND_NORMANDY -- @type ATC_GROUND_NORMANDY
-- @extends #ATC_GROUND -- @extends #ATC_GROUND
@@ -1277,10 +1296,11 @@ end
-- @return nothing -- @return nothing
function ATC_GROUND_NORMANDY:Start( RepeatScanSeconds ) function ATC_GROUND_NORMANDY:Start( RepeatScanSeconds )
RepeatScanSeconds = RepeatScanSeconds or 0.05 RepeatScanSeconds = RepeatScanSeconds or 0.05
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds ) self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
end end
--- @type ATC_GROUND_PERSIANGULF ---
-- @type ATC_GROUND_PERSIANGULF
-- @extends #ATC_GROUND -- @extends #ATC_GROUND
@@ -1419,11 +1439,11 @@ end
-- @return nothing -- @return nothing
function ATC_GROUND_PERSIANGULF:Start( RepeatScanSeconds ) function ATC_GROUND_PERSIANGULF:Start( RepeatScanSeconds )
RepeatScanSeconds = RepeatScanSeconds or 0.05 RepeatScanSeconds = RepeatScanSeconds or 0.05
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds ) self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
end end
--- @type ATC_GROUND_MARIANAISLANDS -- @type ATC_GROUND_MARIANAISLANDS
-- @extends #ATC_GROUND -- @extends #ATC_GROUND
@@ -1517,7 +1537,7 @@ end
-- * @{#ATC_GROUND.SetMaximumKickSpeedKmph}(): Set the maximum speed allowed at an airbase in kilometers per hour. -- * @{#ATC_GROUND.SetMaximumKickSpeedKmph}(): Set the maximum speed allowed at an airbase in kilometers per hour.
-- * @{#ATC_GROUND.SetMaximumKickSpeedMiph}(): Set the maximum speed allowed at an airbase in miles per hour. -- * @{#ATC_GROUND.SetMaximumKickSpeedMiph}(): Set the maximum speed allowed at an airbase in miles per hour.
-- --
---- @field #ATC_GROUND_MARIANAISLANDS -- @field #ATC_GROUND_MARIANAISLANDS
ATC_GROUND_MARIANAISLANDS = { ATC_GROUND_MARIANAISLANDS = {
ClassName = "ATC_GROUND_MARIANAISLANDS", ClassName = "ATC_GROUND_MARIANAISLANDS",
} }
@@ -1529,7 +1549,7 @@ ATC_GROUND_MARIANAISLANDS = {
function ATC_GROUND_MARIANAISLANDS:New( AirbaseNames ) function ATC_GROUND_MARIANAISLANDS:New( AirbaseNames )
-- Inherits from BASE -- Inherits from BASE
local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New( self.Airbases, AirbaseNames ) ) local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New( AirbaseNames ) )
self:SetKickSpeedKmph( 50 ) self:SetKickSpeedKmph( 50 )
self:SetMaximumKickSpeedKmph( 150 ) self:SetMaximumKickSpeedKmph( 150 )
@@ -1543,5 +1563,5 @@ end
-- @return nothing -- @return nothing
function ATC_GROUND_MARIANAISLANDS:Start( RepeatScanSeconds ) function ATC_GROUND_MARIANAISLANDS:Start( RepeatScanSeconds )
RepeatScanSeconds = RepeatScanSeconds or 0.05 RepeatScanSeconds = RepeatScanSeconds or 0.05
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds ) self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
end end

View File

@@ -25,9 +25,9 @@
-- --
-- === -- ===
-- --
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- ### Author: **funkyfranky**
-- --
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536) -- ### Contributions: FlightControl
-- --
-- ==== -- ====
-- @module Functional.Artillery -- @module Functional.Artillery
@@ -291,14 +291,14 @@
-- ### Illumination Shells -- ### Illumination Shells
-- --
-- ARTY groups that possess shells can fire shells with illumination bombs. First, the group needs to be equipped with this weapon. This is done by the -- ARTY groups that possess shells can fire shells with illumination bombs. First, the group needs to be equipped with this weapon. This is done by the
-- function @{ARTY.SetIlluminationShells}(*n*, *power*), where *n* is the number of shells the group has available and *power* the illumination power in mega candela (mcd). -- function @{#ARTY.SetIlluminationShells}(*n*, *power*), where *n* is the number of shells the group has available and *power* the illumination power in mega candela (mcd).
-- --
-- In order to execute an engagement with illumination shells one has to use the weapon type *ARTY.WeaponType.IlluminationShells* in the -- In order to execute an engagement with illumination shells one has to use the weapon type *ARTY.WeaponType.IlluminationShells* in the
-- @{#ARTY.AssignTargetCoord}() function. -- @{#ARTY.AssignTargetCoord}() function.
-- --
-- In the simulation, the explosive shell that is fired is destroyed once it gets close to the target point but before it can actually impact. -- In the simulation, the explosive shell that is fired is destroyed once it gets close to the target point but before it can actually impact.
-- At this position an illumination bomb is triggered at a random altitude between 500 and 1000 meters. This interval can be set by the function -- At this position an illumination bomb is triggered at a random altitude between 500 and 1000 meters. This interval can be set by the function
-- @{ARTY.SetIlluminationMinMaxAlt}(*minalt*, *maxalt*). -- @{#ARTY.SetIlluminationMinMaxAlt}(*minalt*, *maxalt*).
-- --
-- ### Smoke Shells -- ### Smoke Shells
-- --

View File

@@ -74,7 +74,7 @@
-- @image Designation.JPG -- @image Designation.JPG
-- --
-- Date: 24 Oct 2021 -- Date: 24 Oct 2021
-- Last Update: Aug 2022 -- Last Update: Oct 2023
-- --
--- Class AUTOLASE --- Class AUTOLASE
-- @type AUTOLASE -- @type AUTOLASE
@@ -84,6 +84,9 @@
-- @field #string alias -- @field #string alias
-- @field #boolean debug -- @field #boolean debug
-- @field #string version -- @field #string version
-- @field Core.Set#SET_GROUP RecceSet
-- @field #table LaserCodes
-- @field #table playermenus
-- @extends Ops.Intel#INTEL -- @extends Ops.Intel#INTEL
--- ---
@@ -109,9 +112,10 @@ AUTOLASE = {
-- @field #string unittype -- @field #string unittype
-- @field Core.Point#COORDINATE coordinate -- @field Core.Point#COORDINATE coordinate
--- AUTOLASE class version. --- AUTOLASE class version.
-- @field #string version -- @field #string version
AUTOLASE.version = "0.1.21" AUTOLASE.version = "0.1.22"
------------------------------------------------------------------- -------------------------------------------------------------------
-- Begin Functional.Autolase.lua -- Begin Functional.Autolase.lua
@@ -196,6 +200,8 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
self.NoMenus = false self.NoMenus = false
self.minthreatlevel = 0 self.minthreatlevel = 0
self.blacklistattributes = {} self.blacklistattributes = {}
self:SetLaserCodes( { 1688, 1130, 4785, 6547, 1465, 4578 } ) -- set self.LaserCodes
self.playermenus = {}
-- Set some string id for output to DCS.log file. -- Set some string id for output to DCS.log file.
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown") self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
@@ -214,7 +220,7 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
if PilotSet then if PilotSet then
self.usepilotset = true self.usepilotset = true
self.pilotset = PilotSet self.pilotset = PilotSet
self:HandleEvent(EVENTS.PlayerEnterAircraft) self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
--self:SetPilotMenu() --self:SetPilotMenu()
end end
--self.SetPilotMenu() --self.SetPilotMenu()
@@ -298,6 +304,16 @@ end
-- Helper Functions -- Helper Functions
------------------------------------------------------------------- -------------------------------------------------------------------
--- [User] Set a table of possible laser codes.
-- Each new RECCE can select a code from this table, default is { 1688, 1130, 4785, 6547, 1465, 4578 } .
-- @param #AUTOLASE self
-- @param #list<#number> LaserCodes
-- @return #AUTOLASE
function AUTOLASE:SetLaserCodes( LaserCodes )
self.LaserCodes = ( type( LaserCodes ) == "table" ) and LaserCodes or { LaserCodes }
return self
end
--- (Internal) Function to set pilot menu. --- (Internal) Function to set pilot menu.
-- @param #AUTOLASE self -- @param #AUTOLASE self
-- @return #AUTOLASE self -- @return #AUTOLASE self
@@ -308,8 +324,31 @@ function AUTOLASE:SetPilotMenu()
local Unit = _unit -- Wrapper.Unit#UNIT local Unit = _unit -- Wrapper.Unit#UNIT
if Unit and Unit:IsAlive() then if Unit and Unit:IsAlive() then
local Group = Unit:GetGroup() local Group = Unit:GetGroup()
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Autolase Status",nil,self.ShowStatus,self,Group,Unit) local unitname = Unit:GetName()
lasemenu:Refresh() if self.playermenus[unitname] then self.playermenus[unitname]:Remove() end
local lasetopm = MENU_GROUP:New(Group,"Autolase",nil)
self.playermenus[unitname] = lasetopm
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Status",lasetopm,self.ShowStatus,self,Group,Unit)
local smoke = (self.smoketargets == true) and "off" or "on"
local smoketext = string.format("Switch smoke targets to %s",smoke)
local smokemenu = MENU_GROUP_COMMAND:New(Group,smoketext,lasetopm,self.SetSmokeTargets,self,(not self.smoketargets))
for _,_grp in pairs(self.RecceSet.Set) do
local grp = _grp -- Wrapper.Group#GROUP
local unit = grp:GetUnit(1)
--local name = grp:GetName()
if unit and unit:IsAlive() then
local name = unit:GetName()
local mname = string.gsub(name,".%d+.%d+$","")
local code = self:GetLaserCode(name)
local unittop = MENU_GROUP:New(Group,"Change laser code for "..mname,lasetopm)
for _,_code in pairs(self.LaserCodes) do
local text = tostring(_code)
if _code == code then text = text.."(*)" end
local changemenu = MENU_GROUP_COMMAND:New(Group,text,unittop,self.SetRecceLaserCode,self,name,_code,true)
end
end
end
--lasemenu:Refresh()
end end
end end
else else
@@ -324,7 +363,7 @@ end
-- @param #AUTOLASE self -- @param #AUTOLASE self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
-- @return #AUTOLASE self -- @return #AUTOLASE self
function AUTOLASE:OnEventPlayerEnterAircraft(EventData) function AUTOLASE:_EventHandler(EventData)
self:SetPilotMenu() self:SetPilotMenu()
return self return self
end end
@@ -397,7 +436,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-Standalon -- @param #string Path Path to SRS directory, e.g. C:\\Program Files\\DCS-SimpleRadio-Standalone
-- @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
@@ -465,10 +504,20 @@ end
-- @param #AUTOLASE self -- @param #AUTOLASE self
-- @param #string RecceName (Unit!) Name of the Recce -- @param #string RecceName (Unit!) Name of the Recce
-- @param #number Code The lase code -- @param #number Code The lase code
-- @param #boolean Refresh If true, refresh menu entries
-- @return #AUTOLASE self -- @return #AUTOLASE self
function AUTOLASE:SetRecceLaserCode(RecceName, Code) function AUTOLASE:SetRecceLaserCode(RecceName, Code, Refresh)
local code = Code or 1688 local code = Code or 1688
self.RecceLaserCode[RecceName] = code self.RecceLaserCode[RecceName] = code
if Refresh then
self:SetPilotMenu()
if self.notifypilots then
if string.find(RecceName,"#") then
RecceName = string.match(RecceName,"^(.*)#")
end
self:NotifyPilots(string.format("Code for %s set to: %d",RecceName,Code),15)
end
end
return self return self
end end
@@ -524,6 +573,9 @@ end
function AUTOLASE:SetSmokeTargets(OnOff,Color) function AUTOLASE:SetSmokeTargets(OnOff,Color)
self.smoketargets = OnOff self.smoketargets = OnOff
self.smokecolor = Color or SMOKECOLOR.Red self.smokecolor = Color or SMOKECOLOR.Red
local smktxt = OnOff == true and "on" or "off"
local Message = "Smoking targets is now "..smktxt.."!"
self:NotifyPilots(Message,10)
return self return self
end end
@@ -673,7 +725,7 @@ function AUTOLASE:ShowStatus(Group,Unit)
if playername then if playername then
local settings = _DATABASE:GetPlayerSettings(playername) local settings = _DATABASE:GetPlayerSettings(playername)
if settings then if settings then
--self:I("Get Settings ok!") self:I("Get Settings ok!")
if settings:IsA2G_MGRS() then if settings:IsA2G_MGRS() then
locationstring = entry.coordinate:ToStringMGRS(settings) locationstring = entry.coordinate:ToStringMGRS(settings)
elseif settings:IsA2G_LL_DMS() then elseif settings:IsA2G_LL_DMS() then
@@ -995,6 +1047,9 @@ end
function AUTOLASE:onbeforeRecceKIA(From,Event,To,RecceName) function AUTOLASE:onbeforeRecceKIA(From,Event,To,RecceName)
self:T({From, Event, To, RecceName}) self:T({From, Event, To, RecceName})
if self.notifypilots or self.debug then if self.notifypilots or self.debug then
if string.find(RecceName,"#") then
RecceName = string.match(RecceName,"^(.*)#")
end
local text = string.format("Recce %s KIA!",RecceName) local text = string.format("Recce %s KIA!",RecceName)
self:NotifyPilots(text,self.reporttimeshort) self:NotifyPilots(text,self.reporttimeshort)
end end
@@ -1029,6 +1084,9 @@ end
function AUTOLASE:onbeforeTargetLost(From,Event,To,UnitName,RecceName) function AUTOLASE:onbeforeTargetLost(From,Event,To,UnitName,RecceName)
self:T({From, Event, To, UnitName,RecceName}) self:T({From, Event, To, UnitName,RecceName})
if self.notifypilots or self.debug then if self.notifypilots or self.debug then
if string.find(RecceName,"#") then
RecceName = string.match(RecceName,"^(.*)#")
end
local text = string.format("%s lost sight of unit %s.",RecceName,UnitName) local text = string.format("%s lost sight of unit %s.",RecceName,UnitName)
self:NotifyPilots(text,self.reporttimeshort) self:NotifyPilots(text,self.reporttimeshort)
end end
@@ -1046,6 +1104,9 @@ end
function AUTOLASE:onbeforeLaserTimeout(From,Event,To,UnitName,RecceName) function AUTOLASE:onbeforeLaserTimeout(From,Event,To,UnitName,RecceName)
self:T({From, Event, To, UnitName,RecceName}) self:T({From, Event, To, UnitName,RecceName})
if self.notifypilots or self.debug then if self.notifypilots or self.debug then
if string.find(RecceName,"#") then
RecceName = string.match(RecceName,"^(.*)#")
end
local text = string.format("%s laser timeout on unit %s.",RecceName,UnitName) local text = string.format("%s laser timeout on unit %s.",RecceName,UnitName)
self:NotifyPilots(text,self.reporttimeshort) self:NotifyPilots(text,self.reporttimeshort)
end end
@@ -1063,10 +1124,9 @@ function AUTOLASE:onbeforeLasing(From,Event,To,LaserSpot)
self:T({From, Event, To, LaserSpot.unittype}) self:T({From, Event, To, LaserSpot.unittype})
if self.notifypilots or self.debug then if self.notifypilots or self.debug then
local laserspot = LaserSpot -- #AUTOLASE.LaserSpot local laserspot = LaserSpot -- #AUTOLASE.LaserSpot
local name = laserspot.reccename local name = laserspot.reccename if string.find(name,"#") then
if string.find(name,"#") then
name = string.match(name,"^(.*)#") name = string.match(name,"^(.*)#")
end end
local text = string.format("%s is lasing %s code %d\nat %s",name,laserspot.unittype,laserspot.lasercode,laserspot.location) local text = string.format("%s is lasing %s code %d\nat %s",name,laserspot.unittype,laserspot.lasercode,laserspot.location)
self:NotifyPilots(text,self.reporttimeshort+5) self:NotifyPilots(text,self.reporttimeshort+5)
end end

View File

@@ -167,9 +167,9 @@
-- --
-- ### Contributions: -- ### Contributions:
-- --
-- * [**Ciribob**](https://forums.eagle.ru/member.php?u=112175): Showing the way how to lase targets + how laser codes work!!! Explained the autolase script. -- * **Ciribob**: Showing the way how to lase targets + how laser codes work!!! Explained the autolase script.
-- * [**EasyEB**](https://forums.eagle.ru/member.php?u=112055): Ideas and Beta Testing -- * **EasyEB**: Ideas and Beta Testing
-- * [**Wingthor**](https://forums.eagle.ru/member.php?u=123698): Beta Testing -- * **Wingthor**: Beta Testing
-- --
-- ### Authors: -- ### Authors:
-- --

View File

@@ -2452,7 +2452,7 @@ do -- DETECTION_AREAS
-- --
-- Retrieve the DetectedItems[].Set with the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}(). A @{Core.Set#SET_UNIT} object will be returned. -- Retrieve the DetectedItems[].Set with the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}(). A @{Core.Set#SET_UNIT} object will be returned.
-- --
-- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Functional.Detection#DETECTION_AREAS.GetDetectionZones}(). -- Retrieve the formed @{Core.Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Functional.Detection#DETECTION_AREAS.GetDetectionZones}().
-- To understand the amount of zones created, use the method @{Functional.Detection#DETECTION_AREAS.GetDetectionZoneCount}(). -- To understand the amount of zones created, use the method @{Functional.Detection#DETECTION_AREAS.GetDetectionZoneCount}().
-- If you want to obtain a specific zone from the DetectedZones, use the method @{Functional.Detection#DETECTION_AREAS.GetDetectionZoneByID}() with a given index. -- If you want to obtain a specific zone from the DetectedZones, use the method @{Functional.Detection#DETECTION_AREAS.GetDetectionZoneByID}() with a given index.
-- --

View File

@@ -21,7 +21,7 @@ do -- DETECTION_ZONES
-- --
-- Retrieve the DetectedItems[].Set with the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}(). A @{Core.Set#SET_UNIT} object will be returned. -- Retrieve the DetectedItems[].Set with the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}(). A @{Core.Set#SET_UNIT} object will be returned.
-- --
-- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZones}(). -- Retrieve the formed @{Core.Zone#ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZones}().
-- To understand the amount of zones created, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZoneCount}(). -- To understand the amount of zones created, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZoneCount}().
-- If you want to obtain a specific zone from the DetectedZones, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZone}() with a given index. -- If you want to obtain a specific zone from the DetectedZones, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZone}() with a given index.
-- --

View File

@@ -252,7 +252,7 @@ end
--- Set a Detection method for the EscortClient to be reported upon. --- Set a Detection method for the EscortClient to be reported upon.
-- Detection methods are based on the derived classes from DETECTION_BASE. -- Detection methods are based on the derived classes from DETECTION_BASE.
-- @param #ESCORT self -- @param #ESCORT self
-- @param Function.Detection#DETECTION_BASE Detection -- @param Functional.Detection#DETECTION_BASE Detection
function ESCORT:SetDetection( Detection ) function ESCORT:SetDetection( Detection )
self.Detection = Detection self.Detection = Detection

View File

@@ -58,7 +58,7 @@
-- --
-- # The FOX Concept -- # The FOX Concept
-- --
-- As you probably know [Fox](https://en.wikipedia.org/wiki/Fox_(code_word)) is a NATO brevity code for launching air-to-air munition. Therefore, the class name is not 100% accurate as this -- As you probably know [Fox](https://en.wikipedia.org/wiki/Fox_\(code_word\)) is a NATO brevity code for launching air-to-air munition. Therefore, the class name is not 100% accurate as this
-- script handles air-to-air but also surface-to-air missiles. -- script handles air-to-air but also surface-to-air missiles.
-- --
-- # Basic Script -- # Basic Script

View File

@@ -22,7 +22,7 @@
-- @module Functional.Mantis -- @module Functional.Mantis
-- @image Functional.Mantis.jpg -- @image Functional.Mantis.jpg
-- --
-- Last Update: Sept 2023 -- Last Update: Nov 2023
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **MANTIS** class, extends Core.Base#BASE --- **MANTIS** class, extends Core.Base#BASE
@@ -103,6 +103,7 @@
-- * Roland -- * Roland
-- * 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 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
-- --
-- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M -- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M
@@ -373,7 +374,9 @@ MANTIS.SamData = {
["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" },
["SHORAD"] = { Range=3, Blindspot=0, Height=3, Type="Short", Radar="Igla" } ["SHORAD"] = { Range=3, Blindspot=0, Height=3, Type="Short", Radar="Igla" },
["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" },
} }
--- SAM data HDS --- SAM data HDS
@@ -487,7 +490,11 @@ do
-- mybluemantis:Start() -- mybluemantis:Start()
-- --
function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs, EmOnOff, Padding, Zones) function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs, EmOnOff, Padding, Zones)
-- Inherit everything from BASE class.
local self = BASE:Inherit(self, FSM:New()) -- #MANTIS
-- DONE: Create some user functions for these -- DONE: Create some user functions for these
-- DONE: Make HQ useful -- DONE: Make HQ useful
-- DONE: Set SAMs to auto if EWR dies -- DONE: Set SAMs to auto if EWR dies
@@ -549,6 +556,10 @@ do
self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP
self.FilterZones = Zones self.FilterZones = Zones
self.SkateZones = nil
self.SkateNumber = 3
self.shootandscoot = false
self.UseEmOnOff = true self.UseEmOnOff = true
if EmOnOff == false then if EmOnOff == false then
self.UseEmOnOff = false self.UseEmOnOff = false
@@ -560,9 +571,6 @@ do
self.advAwacs = false self.advAwacs = false
end end
-- Inherit everything from BASE class.
local self = BASE:Inherit(self, FSM:New()) -- #MANTIS
-- 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)
@@ -623,7 +631,7 @@ do
-- TODO Version -- TODO Version
-- @field #string version -- @field #string version
self.version="0.8.14" self.version="0.8.15"
self:I(string.format("***** Starting MANTIS Version %s *****", self.version)) self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
--- FSM Functions --- --- FSM Functions ---
@@ -787,6 +795,23 @@ do
return self return self
end end
--- Add a SET_ZONE of zones for Shoot&Scoot - SHORAD units will move around
-- @param #MANTIS self
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
-- @param #number Number Number of closest zones to be considered, defaults to 3.
-- @param #boolean Random If true, use a random coordinate inside the next zone to scoot to.
-- @param #string Formation Formation to use, defaults to "Cone". See mission editor dropdown for options.
-- @return #MANTIS self
function MANTIS:AddScootZones(ZoneSet, Number, Random, Formation)
self:T(self.lid .. " AddScootZones")
self.SkateZones = ZoneSet
self.SkateNumber = Number or 3
self.shootandscoot = true
self.ScootRandom = Random
self.ScootFormation = Formation or "Cone"
return self
end
--- Function to set accept and reject zones. --- Function to set accept and reject zones.
-- @param #MANTIS self -- @param #MANTIS self
-- @param #table AcceptZones Table of @{Core.Zone#ZONE} objects -- @param #table AcceptZones Table of @{Core.Zone#ZONE} objects
@@ -893,7 +918,7 @@ do
--- Function to get the HQ object for further use --- Function to get the HQ object for further use
-- @param #MANTIS self -- @param #MANTIS self
-- @return Wrapper.GROUP#GROUP The HQ #GROUP object or *nil* if it doesn't exist -- @return Wrapper.Group#GROUP The HQ #GROUP object or *nil* if it doesn't exist
function MANTIS:GetCommandCenter() function MANTIS:GetCommandCenter()
self:T(self.lid .. "GetCommandCenter") self:T(self.lid .. "GetCommandCenter")
if self.HQ_CC then if self.HQ_CC then
@@ -929,7 +954,7 @@ do
--- Function to set the HQ object for further use --- Function to set the HQ object for further use
-- @param #MANTIS self -- @param #MANTIS self
-- @param Wrapper.GROUP#GROUP group The #GROUP object to be set as HQ -- @param Wrapper.Group#GROUP group The #GROUP object to be set as HQ
function MANTIS:SetCommandCenter(group) function MANTIS:SetCommandCenter(group)
self:T(self.lid .. "SetCommandCenter") self:T(self.lid .. "SetCommandCenter")
local group = group or nil local group = group or nil
@@ -991,7 +1016,7 @@ do
--- Set using your own #INTEL_DLINK object instead of #DETECTION --- Set using your own #INTEL_DLINK object instead of #DETECTION
-- @param #MANTIS self -- @param #MANTIS self
-- @param Ops.Intelligence#INTEL_DLINK DLink The data link object to be used. -- @param Ops.Intel#INTEL_DLINK DLink The data link object to be used.
function MANTIS:SetUsingDLink(DLink) function MANTIS:SetUsingDLink(DLink)
self:T(self.lid .. "SetUsingDLink") self:T(self.lid .. "SetUsingDLink")
self.DLink = true self.DLink = true
@@ -1786,6 +1811,10 @@ do
self.Shorad:SetDefenseLimits(80,95) self.Shorad:SetDefenseLimits(80,95)
self.ShoradLink = true self.ShoradLink = true
self.Shorad.Groupset=self.ShoradGroupSet self.Shorad.Groupset=self.ShoradGroupSet
self.Shorad.debug = self.debug
end
if self.shootandscoot and self.SkateZones and self.Shorad then
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3,self.ScootRandom,self.ScootFormation)
end end
self:__Status(-math.random(1,10)) self:__Status(-math.random(1,10))
return self return self

View File

@@ -46,9 +46,9 @@
-- --
-- === -- ===
-- --
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- ### Author: **funkyfranky**
-- --
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536) -- ### Contributions: FlightControl
-- --
-- === -- ===
-- @module Functional.RAT -- @module Functional.RAT
@@ -225,7 +225,7 @@
-- --
-- * Landing: When an aircraft tries to land at an airport where it does not have a valid parking spot, it is immidiately despawned the moment its wheels touch the runway, i.e. -- * Landing: When an aircraft tries to land at an airport where it does not have a valid parking spot, it is immidiately despawned the moment its wheels touch the runway, i.e.
-- when a landing event is triggered. This leads to the loss of the RAT aircraft. On possible way to circumvent the this problem is to let another RAT aircraft spawn at landing -- when a landing event is triggered. This leads to the loss of the RAT aircraft. On possible way to circumvent the this problem is to let another RAT aircraft spawn at landing
-- and not when it shuts down its engines. See the @{RAT.RespawnAfterLanding}() function. -- and not when it shuts down its engines. See the @{#RAT.RespawnAfterLanding}() function.
-- * Spawning: When a big aircraft is dynamically spawned on a small airbase a few things can go wrong. For example, it could be spawned at a parking spot with a shelter. -- * Spawning: When a big aircraft is dynamically spawned on a small airbase a few things can go wrong. For example, it could be spawned at a parking spot with a shelter.
-- Or it could be damaged by a scenery object when it is taxiing out to the runway, or it could overlap with other aircraft on parking spots near by. -- Or it could be damaged by a scenery object when it is taxiing out to the runway, or it could overlap with other aircraft on parking spots near by.
-- --
@@ -2474,11 +2474,11 @@ end
-- @param #RAT self -- @param #RAT self
-- @param #number takeoff Takeoff type. Could also be air start. -- @param #number takeoff Takeoff type. Could also be air start.
-- @param #number landing Landing type. Could also be a destination in air. -- @param #number landing Landing type. Could also be a destination in air.
-- @param Wrapper.Airport#AIRBASE _departure (Optional) Departure airbase. -- @param Wrapper.Airbase#AIRBASE _departure (Optional) Departure airbase.
-- @param Wrapper.Airport#AIRBASE _destination (Optional) Destination airbase. -- @param Wrapper.Airbase#AIRBASE _destination (Optional) Destination airbase.
-- @param #table _waypoint Initial waypoint. -- @param #table _waypoint Initial waypoint.
-- @return Wrapper.Airport#AIRBASE Departure airbase. -- @return Wrapper.Airbase#AIRBASE Departure airbase.
-- @return Wrapper.Airport#AIRBASE Destination airbase. -- @return Wrapper.Airbase#AIRBASE Destination airbase.
-- @return #table Table of flight plan waypoints. -- @return #table Table of flight plan waypoints.
-- @return #nil If no valid departure or destination airport could be found. -- @return #nil If no valid departure or destination airport could be found.
function RAT:_SetRoute(takeoff, landing, _departure, _destination, _waypoint) function RAT:_SetRoute(takeoff, landing, _departure, _destination, _waypoint)
@@ -4605,7 +4605,7 @@ function RAT:_TaskHolding(P1, Altitude, Speed, Duration)
end end
--- Function which is called after passing every waypoint. Info on waypoint is given and special functions are executed. --- Function which is called after passing every waypoint. Info on waypoint is given and special functions are executed.
-- @param Core.Group#GROUP group Group of aircraft. -- @param Wrapper.Group#GROUP group Group of aircraft.
-- @param #RAT rat RAT object. -- @param #RAT rat RAT object.
-- @param #number wp Waypoint index. Running number of the waypoints. Determines the actions to be executed. -- @param #number wp Waypoint index. Running number of the waypoints. Determines the actions to be executed.
function RAT._WaypointFunction(group, rat, wp) function RAT._WaypointFunction(group, rat, wp)

View File

@@ -4,7 +4,7 @@
-- --
-- The RANGE class enables easy set up of bombing and strafing ranges within DCS World. -- The RANGE class enables easy set up of bombing and strafing ranges within DCS World.
-- --
-- Implementation is based on the [Simple Range Script](https://forums.eagle.ru/showthread.php?t=157991) by [Ciribob](https://forums.eagle.ru/member.php?u=112175), which itself was motivated -- Implementation is based on the [Simple Range Script](https://forums.eagle.ru/showthread.php?t=157991) by Ciribob, which itself was motivated
-- by a script by SNAFU [see here](https://forums.eagle.ru/showthread.php?t=109174). -- by a script by SNAFU [see here](https://forums.eagle.ru/showthread.php?t=109174).
-- --
-- [476th - Air Weapons Range Objects mod](http://www.476vfightergroup.com/downloads.php?do=file&id=287) is highly recommended for this class. -- [476th - Air Weapons Range Objects mod](http://www.476vfightergroup.com/downloads.php?do=file&id=287) is highly recommended for this class.
@@ -42,9 +42,9 @@
-- --
-- === -- ===
-- --
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- ### Author: **funkyfranky**
-- --
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536), [Ciribob](https://forums.eagle.ru/member.php?u=112175) -- ### Contributions: FlightControl, Ciribob
-- ### SRS Additions: Applevangelist -- ### SRS Additions: Applevangelist
-- --
-- === -- ===
@@ -105,6 +105,7 @@
-- @field Sound.SRS#MSRSQUEUE controlsrsQ SRS queue for range controller. -- @field Sound.SRS#MSRSQUEUE controlsrsQ SRS queue for range controller.
-- @field Sound.SRS#MSRS instructmsrs SRS wrapper for range instructor. -- @field Sound.SRS#MSRS instructmsrs SRS wrapper for range instructor.
-- @field Sound.SRS#MSRSQUEUE instructsrsQ SRS queue for range instructor. -- @field Sound.SRS#MSRSQUEUE instructsrsQ SRS queue for range instructor.
-- @field #number Coalition Coalition side for the menu, if any.
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- *Don't only practice your art, but force your way into its secrets; art deserves that, for it and knowledge can raise man to the Divine.* - Ludwig van Beethoven --- *Don't only practice your art, but force your way into its secrets; art deserves that, for it and knowledge can raise man to the Divine.* - Ludwig van Beethoven
@@ -355,7 +356,8 @@ RANGE = {
targetsheet = nil, targetsheet = nil,
targetpath = nil, targetpath = nil,
targetprefix = nil, targetprefix = nil,
} Coalition = nil,
}
--- Default range parameters. --- Default range parameters.
-- @type RANGE.Defaults -- @type RANGE.Defaults
@@ -591,7 +593,7 @@ RANGE.MenuF10Root = nil
--- Range script version. --- Range script version.
-- @field #string version -- @field #string version
RANGE.version = "2.7.1" RANGE.version = "2.7.3"
-- TODO list: -- TODO list:
-- TODO: Verbosity level for messages. -- TODO: Verbosity level for messages.
@@ -613,8 +615,9 @@ RANGE.version = "2.7.1"
--- RANGE contructor. Creates a new RANGE object. --- RANGE contructor. Creates a new RANGE object.
-- @param #RANGE self -- @param #RANGE self
-- @param #string RangeName Name of the range. Has to be unique. Will we used to create F10 menu items etc. -- @param #string RangeName Name of the range. Has to be unique. Will we used to create F10 menu items etc.
-- @param #number Coalition (optional) Coalition of the range, if any, e.g. coalition.side.BLUE.
-- @return #RANGE RANGE object. -- @return #RANGE RANGE object.
function RANGE:New( RangeName ) function RANGE:New( RangeName, Coalition )
-- Inherit BASE. -- Inherit BASE.
local self = BASE:Inherit( self, FSM:New() ) -- #RANGE local self = BASE:Inherit( self, FSM:New() ) -- #RANGE
@@ -622,7 +625,9 @@ function RANGE:New( RangeName )
-- Get range name. -- Get range name.
-- TODO: make sure that the range name is not given twice. This would lead to problems in the F10 radio menu. -- TODO: make sure that the range name is not given twice. This would lead to problems in the F10 radio menu.
self.rangename = RangeName or "Practice Range" self.rangename = RangeName or "Practice Range"
self.Coalition = Coalition
-- Log id. -- Log id.
self.lid = string.format( "RANGE %s | ", self.rangename ) self.lid = string.format( "RANGE %s | ", self.rangename )
@@ -1229,7 +1234,7 @@ function RANGE:SetSRS(PathToSRS, Port, Coalition, Frequency, Modulation, Volume,
return self return self
end end
--- (SRS) Set range control frequency and voice. --- (SRS) Set range control frequency and voice. Use `RANGE:SetSRS()` once first before using this function.
-- @param #RANGE self -- @param #RANGE self
-- @param #number frequency Frequency in MHz. Default 256 MHz. -- @param #number frequency Frequency in MHz. Default 256 MHz.
-- @param #number modulation Modulation, defaults to radio.modulation.AM. -- @param #number modulation Modulation, defaults to radio.modulation.AM.
@@ -1239,6 +1244,10 @@ end
-- @param #string relayunitname Name of the unit used for transmission location. -- @param #string relayunitname Name of the unit used for transmission location.
-- @return #RANGE self -- @return #RANGE self
function RANGE:SetSRSRangeControl( frequency, modulation, voice, culture, gender, relayunitname ) function RANGE:SetSRSRangeControl( frequency, modulation, voice, culture, gender, relayunitname )
if not self.instructmsrs then
self:E(self.lid.."Use myrange:SetSRS() once first before using myrange:SetSRSRangeControl!")
return self
end
self.rangecontrolfreq = frequency or 256 self.rangecontrolfreq = frequency or 256
self.controlmsrs:SetFrequencies(self.rangecontrolfreq) self.controlmsrs:SetFrequencies(self.rangecontrolfreq)
self.controlmsrs:SetModulations(modulation or radio.modulation.AM) self.controlmsrs:SetModulations(modulation or radio.modulation.AM)
@@ -1254,7 +1263,7 @@ function RANGE:SetSRSRangeControl( frequency, modulation, voice, culture, gender
return self return self
end end
--- (SRS) Set range instructor frequency and voice. --- (SRS) Set range instructor frequency and voice. Use `RANGE:SetSRS()` once first before using this function.
-- @param #RANGE self -- @param #RANGE self
-- @param #number frequency Frequency in MHz. Default 305 MHz. -- @param #number frequency Frequency in MHz. Default 305 MHz.
-- @param #number modulation Modulation, defaults to radio.modulation.AM. -- @param #number modulation Modulation, defaults to radio.modulation.AM.
@@ -1264,6 +1273,10 @@ end
-- @param #string relayunitname Name of the unit used for transmission location. -- @param #string relayunitname Name of the unit used for transmission location.
-- @return #RANGE self -- @return #RANGE self
function RANGE:SetSRSRangeInstructor( frequency, modulation, voice, culture, gender, relayunitname ) function RANGE:SetSRSRangeInstructor( frequency, modulation, voice, culture, gender, relayunitname )
if not self.instructmsrs then
self:E(self.lid.."Use myrange:SetSRS() once first before using myrange:SetSRSRangeInstructor!")
return self
end
self.instructorfreq = frequency or 305 self.instructorfreq = frequency or 305
self.instructmsrs:SetFrequencies(self.instructorfreq) self.instructmsrs:SetFrequencies(self.instructorfreq)
self.instructmsrs:SetModulations(modulation or radio.modulation.AM) self.instructmsrs:SetModulations(modulation or radio.modulation.AM)
@@ -1745,10 +1758,16 @@ function RANGE:OnEventBirth( EventData )
-- Reset current strafe status. -- Reset current strafe status.
self.strafeStatus[_uid] = nil self.strafeStatus[_uid] = nil
-- Add Menu commands after a delay of 0.1 seconds. if self.Coalition then
self:ScheduleOnce( 0.1, self._AddF10Commands, self, _unitName ) if EventData.IniCoalition == self.Coalition then
self:ScheduleOnce( 0.1, self._AddF10Commands, self, _unitName )
end
else
-- Add Menu commands after a delay of 0.1 seconds.
self:ScheduleOnce( 0.1, self._AddF10Commands, self, _unitName )
end
-- By default, some bomb impact points and do not flare each hit on target. -- By default, some bomb impact points and do not flare each hit on target.
self.PlayerSettings[_playername] = {} -- #RANGE.PlayerData self.PlayerSettings[_playername] = {} -- #RANGE.PlayerData
self.PlayerSettings[_playername].smokebombimpact = self.defaultsmokebomb self.PlayerSettings[_playername].smokebombimpact = self.defaultsmokebomb

View File

@@ -27,7 +27,7 @@
-- and creates a CSV file logging the scoring events and results for use at team or squadron websites. -- and creates a CSV file logging the scoring events and results for use at team or squadron websites.
-- --
-- SCORING automatically calculates the threat level of the objects hit and destroyed by players, -- SCORING automatically calculates the threat level of the objects hit and destroyed by players,
-- which can be @{Wrapper.Unit}, @{Static) and @{Scenery} objects. -- which can be @{Wrapper.Unit}, @{Wrapper.Static) and @{Scenery} objects.
-- --
-- Positive score points are granted when enemy or neutral targets are destroyed. -- Positive score points are granted when enemy or neutral targets are destroyed.
-- Negative score points or penalties are given when a friendly target is hit or destroyed. -- Negative score points or penalties are given when a friendly target is hit or destroyed.
@@ -81,7 +81,7 @@
-- --
-- * **Wingthor (TAW)**: Testing & Advice. -- * **Wingthor (TAW)**: Testing & Advice.
-- * **Dutch-Baron (TAW)**: Testing & Advice. -- * **Dutch-Baron (TAW)**: Testing & Advice.
-- * **[Whisper](http://forums.eagle.ru/member.php?u=3829): Testing and Advice. -- * **Whisper**: Testing and Advice.
-- --
-- === -- ===
-- --

View File

@@ -19,7 +19,7 @@
-- --
-- ### Authors: **FlightControl**, **applevangelist** -- ### Authors: **FlightControl**, **applevangelist**
-- --
-- Last Update: September 2023 -- Last Update: Oct 2023
-- --
-- === -- ===
-- --
@@ -34,7 +34,7 @@
-- --
-- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon. -- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon.
-- Once a HARM attack is detected, 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, SEAD will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
-- vehicles around (*if* they are drivable, that is). There's a component of randomness in detection and evasion, which is based on the -- vehicles around (*if* they are driveable, that is). There's a component of randomness in detection and evasion, which is based on the
-- skill set of the SAM set (the higher the skill, the more likely). When a missile is fired from far away, the SAM will stay active for a -- skill set of the SAM set (the higher the skill, the more likely). When a missile is fired from far away, the SAM will stay active for a
-- period of time to stay defensive, before it takes evasive actions. -- period of time to stay defensive, before it takes evasive actions.
-- --
@@ -66,7 +66,6 @@ SEAD = {
-- @field Harms -- @field Harms
SEAD.Harms = { SEAD.Harms = {
["AGM_88"] = "AGM_88", ["AGM_88"] = "AGM_88",
--["AGM_45"] = "AGM_45",
["AGM_122"] = "AGM_122", ["AGM_122"] = "AGM_122",
["AGM_84"] = "AGM_84", ["AGM_84"] = "AGM_84",
["AGM_45"] = "AGM_45", ["AGM_45"] = "AGM_45",
@@ -80,6 +79,7 @@ SEAD = {
["BGM_109"] = "BGM_109", ["BGM_109"] = "BGM_109",
["AGM_154"] = "AGM_154", ["AGM_154"] = "AGM_154",
["HY-2"] = "HY-2", ["HY-2"] = "HY-2",
["ADM_141A"] = "ADM_141A",
} }
--- Missile enumerators - from DCS ME and Wikipedia --- Missile enumerators - from DCS ME and Wikipedia
@@ -100,6 +100,7 @@ SEAD = {
["BGM_109"] = {460, 0.705}, --in-game ~465kn ["BGM_109"] = {460, 0.705}, --in-game ~465kn
["AGM_154"] = {130, 0.61}, ["AGM_154"] = {130, 0.61},
["HY-2"] = {90,1}, ["HY-2"] = {90,1},
["ADM_141A"] = {126,0.6},
} }
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles. --- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
@@ -143,7 +144,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
self:AddTransition("*", "ManageEvasion", "*") self:AddTransition("*", "ManageEvasion", "*")
self:AddTransition("*", "CalculateHitZone", "*") self:AddTransition("*", "CalculateHitZone", "*")
self:I("*** SEAD - Started Version 0.4.4") self:I("*** SEAD - Started Version 0.4.5")
return self return self
end end
@@ -348,8 +349,9 @@ end
-- @param #string SEADWeaponName -- @param #string SEADWeaponName
-- @param Wrapper.Group#GROUP SEADGroup Attacker Group -- @param Wrapper.Group#GROUP SEADGroup Attacker Group
-- @param #number timeoffset Offset for tti calc -- @param #number timeoffset Offset for tti calc
-- @param Wrapper.Weapon#WEAPON Weapon
-- @return #SEAD self -- @return #SEAD self
function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,timeoffset) function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,timeoffset,Weapon)
local timeoffset = timeoffset or 0 local timeoffset = timeoffset or 0
if _targetskill == "Random" then -- when skill is random, choose a skill if _targetskill == "Random" then -- when skill is random, choose a skill
local Skills = { "Average", "Good", "High", "Excellent" } local Skills = { "Average", "Good", "High", "Excellent" }
@@ -372,6 +374,10 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
reach = wpndata[1] * 1.1 reach = wpndata[1] * 1.1
local mach = wpndata[2] local mach = wpndata[2]
wpnspeed = math.floor(mach * 340.29) wpnspeed = math.floor(mach * 340.29)
if Weapon then
wpnspeed = Weapon:GetSpeed()
self:T(string.format("*** SEAD - Weapon Speed from WEAPON: %f m/s",wpnspeed))
end
end end
-- time to impact -- time to impact
local _tti = math.floor(_distance / wpnspeed) - timeoffset -- estimated impact time local _tti = math.floor(_distance / wpnspeed) - timeoffset -- estimated impact time
@@ -457,6 +463,9 @@ function SEAD:HandleEventShot( EventData )
local SEADWeapon = EventData.Weapon -- Identify the weapon fired local SEADWeapon = EventData.Weapon -- Identify the weapon fired
local SEADWeaponName = EventData.WeaponName -- return weapon type local SEADWeaponName = EventData.WeaponName -- return weapon type
local WeaponWrapper = WEAPON:New(EventData.Weapon)
--local SEADWeaponSpeed = WeaponWrapper:GetSpeed() -- mps
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName) self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
--self:T({ SEADWeapon }) --self:T({ SEADWeapon })
@@ -475,7 +484,7 @@ function SEAD:HandleEventShot( EventData )
end end
return self return self
end end
local targetcat = _target:getCategory() -- Identify category local targetcat = Object.getCategory(_target) -- Identify category
local _targetUnit = nil -- Wrapper.Unit#UNIT local _targetUnit = nil -- Wrapper.Unit#UNIT
local _targetgroup = nil -- Wrapper.Group#GROUP local _targetgroup = nil -- Wrapper.Group#GROUP
self:T(string.format("*** Targetcat = %d",targetcat)) self:T(string.format("*** Targetcat = %d",targetcat))
@@ -513,7 +522,11 @@ function SEAD:HandleEventShot( EventData )
end end
end end
if SEADGroupFound == true then -- yes we are being attacked if SEADGroupFound == true then -- yes we are being attacked
self:ManageEvasion(_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup) if string.find(SEADWeaponName,"ADM_141",1,true) then
self:__ManageEvasion(2,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
else
self:ManageEvasion(_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
end
end end
end end
return self return self

View File

@@ -21,6 +21,7 @@
-- @image Functional.Shorad.jpg -- @image Functional.Shorad.jpg
-- --
-- Date: Nov 2021 -- Date: Nov 2021
-- Last Update: Nov 2023
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **SHORAD** class, extends Core.Base#BASE --- **SHORAD** class, extends Core.Base#BASE
@@ -39,8 +40,15 @@
-- @field #boolean DefendHarms Default true, intercept incoming HARMS -- @field #boolean DefendHarms Default true, intercept incoming HARMS
-- @field #boolean DefendMavs Default true, intercept incoming AG-Missiles -- @field #boolean DefendMavs Default true, intercept incoming AG-Missiles
-- @field #number DefenseLowProb Default 70, minimum detection limit -- @field #number DefenseLowProb Default 70, minimum detection limit
-- @field #number DefenseHighProb Default 90, maximim detection limit -- @field #number DefenseHighProb Default 90, maximum detection limit
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green. -- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green
-- @field #boolean shootandscoot If true, shoot and scoot between zones
-- @field #number SkateNumber Number of zones to consider
-- @field Core.Set#SET_ZONE SkateZones Zones in this set are considered
-- @field #number minscootdist Min distance of the next zone
-- @field #number maxscootdist Max distance of the next zone
-- @field #boolean scootrandomcoord If true, use a random coordinate in the zone and not the center
-- @field #string scootformation Formation to take for scooting, e.g. "Vee" or "Cone"
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@@ -73,14 +81,15 @@
-- --
-- `myshorad = SHORAD:New("RedShorad", "Red SHORAD", SamSet, 25000, 600, "red")` -- `myshorad = SHORAD:New("RedShorad", "Red SHORAD", SamSet, 25000, 600, "red")`
-- --
-- ## Customize options -- ## Customization options
-- --
-- * SHORAD:SwitchDebug(debug) -- * myshorad:SwitchDebug(debug)
-- * SHORAD:SwitchHARMDefense(onoff) -- * myshorad:SwitchHARMDefense(onoff)
-- * SHORAD:SwitchAGMDefense(onoff) -- * myshorad:SwitchAGMDefense(onoff)
-- * SHORAD:SetDefenseLimits(low,high) -- * myshorad:SetDefenseLimits(low,high)
-- * SHORAD:SetActiveTimer(seconds) -- * myshorad:SetActiveTimer(seconds)
-- * SHORAD:SetDefenseRadius(meters) -- * myshorad:SetDefenseRadius(meters)
-- * myshorad:AddScootZones(ZoneSet,Number,Random,Formation)
-- --
-- @field #SHORAD -- @field #SHORAD
SHORAD = { SHORAD = {
@@ -99,7 +108,13 @@ SHORAD = {
DefendMavs = true, DefendMavs = true,
DefenseLowProb = 70, DefenseLowProb = 70,
DefenseHighProb = 90, DefenseHighProb = 90,
UseEmOnOff = false, UseEmOnOff = true,
shootandscoot = false,
SkateNumber = 3,
SkateZones = nil,
minscootdist = 100,
minscootdist = 3000,
scootrandomcoord = false,
} }
----------------------------------------------------------------------- -----------------------------------------------------------------------
@@ -112,7 +127,6 @@ do
-- @field Harms -- @field Harms
SHORAD.Harms = { SHORAD.Harms = {
["AGM_88"] = "AGM_88", ["AGM_88"] = "AGM_88",
["AGM_45"] = "AGM_45",
["AGM_122"] = "AGM_122", ["AGM_122"] = "AGM_122",
["AGM_84"] = "AGM_84", ["AGM_84"] = "AGM_84",
["AGM_45"] = "AGM_45", ["AGM_45"] = "AGM_45",
@@ -123,6 +137,8 @@ do
["X_25"] = "X_25", ["X_25"] = "X_25",
["X_31"] = "X_31", ["X_31"] = "X_31",
["Kh25"] = "Kh25", ["Kh25"] = "Kh25",
["HY-2"] = "HY-2",
["ADM_141A"] = "ADM_141A",
} }
--- TODO complete list? --- TODO complete list?
@@ -134,7 +150,6 @@ do
["Kh29"] = "Kh29", ["Kh29"] = "Kh29",
["Kh31"] = "Kh31", ["Kh31"] = "Kh31",
["Kh66"] = "Kh66", ["Kh66"] = "Kh66",
--["BGM_109"] = "BGM_109",
} }
--- Instantiates a new SHORAD object --- Instantiates a new SHORAD object
@@ -146,7 +161,7 @@ do
-- @param #number ActiveTimer Determines how many seconds the systems stay on red alert after wake-up call -- @param #number ActiveTimer Determines how many seconds the systems stay on red alert after wake-up call
-- @param #string Coalition Coalition, i.e. "blue", "red", or "neutral" -- @param #string Coalition Coalition, i.e. "blue", "red", or "neutral"
-- @param #boolean UseEmOnOff Use Emissions On/Off rather than Alarm State Red/Green (default: use Emissions switch) -- @param #boolean UseEmOnOff Use Emissions On/Off rather than Alarm State Red/Green (default: use Emissions switch)
-- @retunr #SHORAD self -- @return #SHORAD self
function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff) function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff)
local self = BASE:Inherit( self, FSM:New() ) local self = BASE:Inherit( self, FSM:New() )
self:T({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition}) self:T({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition})
@@ -165,8 +180,9 @@ do
self.DefendMavs = true self.DefendMavs = true
self.DefenseLowProb = 70 -- probability to detect a missile shot, low margin self.DefenseLowProb = 70 -- probability to detect a missile shot, low margin
self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin
self.UseEmOnOff = UseEmOnOff or false -- Decide if we are using Emission on/off (default) or AlarmState red/green self.UseEmOnOff = true -- Decide if we are using Emission on/off (default) or AlarmState red/green
self:I("*** SHORAD - Started Version 0.3.1") if UseEmOnOff == false then self.UseEmOnOff = UseEmOnOff end
self:I("*** SHORAD - Started Version 0.3.4")
-- Set the string id for output to DCS.log file. -- Set the string id for output to DCS.log file.
self.lid=string.format("SHORAD %s | ", self.name) self.lid=string.format("SHORAD %s | ", self.name)
self:_InitState() self:_InitState()
@@ -176,12 +192,14 @@ do
self:SetStartState("Running") self:SetStartState("Running")
self:AddTransition("*", "WakeUpShorad", "*") self:AddTransition("*", "WakeUpShorad", "*")
self:AddTransition("*", "CalculateHitZone", "*") self:AddTransition("*", "CalculateHitZone", "*")
self:AddTransition("*", "ShootAndScoot", "*")
return self return self
end end
--- Initially set all groups to alarm state GREEN --- Initially set all groups to alarm state GREEN
-- @param #SHORAD self -- @param #SHORAD self
-- @return #SHORAD self
function SHORAD:_InitState() function SHORAD:_InitState()
self:T(self.lid .. " _InitState") self:T(self.lid .. " _InitState")
local table = {} local table = {}
@@ -205,21 +223,40 @@ do
return self return self
end end
--- Add a SET_ZONE of zones for Shoot&Scoot
-- @param #SHORAD self
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
-- @param #number Number Number of closest zones to be considered, defaults to 3.
-- @param #boolean Random If true, use a random coordinate inside the next zone to scoot to.
-- @param #string Formation Formation to use, defaults to "Cone". See mission editor dropdown for options.
-- @return #SHORAD self
function SHORAD:AddScootZones(ZoneSet, Number, Random, Formation)
self:T(self.lid .. " AddScootZones")
self.SkateZones = ZoneSet
self.SkateNumber = Number or 3
self.shootandscoot = true
self.scootrandomcoord = Random
self.scootformation = Formation or "Cone"
return self
end
--- Switch debug state on --- Switch debug state on
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean debug Switch debug on (true) or off (false) -- @param #boolean debug Switch debug on (true) or off (false)
-- @return #SHORAD self
function SHORAD:SwitchDebug(onoff) function SHORAD:SwitchDebug(onoff)
self:T( { onoff } ) self:T( { onoff } )
if onoff then if onoff then
self:SwitchDebugOn() self:SwitchDebugOn()
else else
self.SwitchDebugOff() self:SwitchDebugOff()
end end
return self return self
end end
--- Switch debug state on --- Switch debug state on
-- @param #SHORAD self -- @param #SHORAD self
-- @return #SHORAD self
function SHORAD:SwitchDebugOn() function SHORAD:SwitchDebugOn()
self.debug = true self.debug = true
--tracing --tracing
@@ -230,6 +267,7 @@ do
--- Switch debug state off --- Switch debug state off
-- @param #SHORAD self -- @param #SHORAD self
-- @return #SHORAD self
function SHORAD:SwitchDebugOff() function SHORAD:SwitchDebugOff()
self.debug = false self.debug = false
BASE:TraceOff() BASE:TraceOff()
@@ -239,6 +277,7 @@ do
--- Switch defense for HARMs --- Switch defense for HARMs
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean onoff -- @param #boolean onoff
-- @return #SHORAD self
function SHORAD:SwitchHARMDefense(onoff) function SHORAD:SwitchHARMDefense(onoff)
self:T( { onoff } ) self:T( { onoff } )
local onoff = onoff or true local onoff = onoff or true
@@ -249,6 +288,7 @@ do
--- Switch defense for AGMs --- Switch defense for AGMs
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean onoff -- @param #boolean onoff
-- @return #SHORAD self
function SHORAD:SwitchAGMDefense(onoff) function SHORAD:SwitchAGMDefense(onoff)
self:T( { onoff } ) self:T( { onoff } )
local onoff = onoff or true local onoff = onoff or true
@@ -260,6 +300,7 @@ do
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number low Minimum detection limit, integer 1-100 -- @param #number low Minimum detection limit, integer 1-100
-- @param #number high Maximum detection limit integer 1-100 -- @param #number high Maximum detection limit integer 1-100
-- @return #SHORAD self
function SHORAD:SetDefenseLimits(low,high) function SHORAD:SetDefenseLimits(low,high)
self:T( { low, high } ) self:T( { low, high } )
local low = low or 70 local low = low or 70
@@ -278,6 +319,7 @@ do
--- Set the number of seconds a SHORAD site will stay active --- Set the number of seconds a SHORAD site will stay active
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number seconds Number of seconds systems stay active -- @param #number seconds Number of seconds systems stay active
-- @return #SHORAD self
function SHORAD:SetActiveTimer(seconds) function SHORAD:SetActiveTimer(seconds)
self:T(self.lid .. " SetActiveTimer") self:T(self.lid .. " SetActiveTimer")
local timer = seconds or 600 local timer = seconds or 600
@@ -291,6 +333,7 @@ do
--- Set the number of meters for the SHORAD defense zone --- Set the number of meters for the SHORAD defense zone
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number meters Radius of the defense search zone in meters. #SHORADs in this range around a targeted group will go active -- @param #number meters Radius of the defense search zone in meters. #SHORADs in this range around a targeted group will go active
-- @return #SHORAD self
function SHORAD:SetDefenseRadius(meters) function SHORAD:SetDefenseRadius(meters)
self:T(self.lid .. " SetDefenseRadius") self:T(self.lid .. " SetDefenseRadius")
local radius = meters or 20000 local radius = meters or 20000
@@ -304,6 +347,7 @@ do
--- Set using Emission on/off instead of changing alarm state --- Set using Emission on/off instead of changing alarm state
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean switch Decide if we are changing alarm state or AI state -- @param #boolean switch Decide if we are changing alarm state or AI state
-- @return #SHORAD self
function SHORAD:SetUsingEmOnOff(switch) function SHORAD:SetUsingEmOnOff(switch)
self:T(self.lid .. " SetUsingEmOnOff") self:T(self.lid .. " SetUsingEmOnOff")
self.UseEmOnOff = switch or false self.UseEmOnOff = switch or false
@@ -375,11 +419,11 @@ do
local shorad = self.Groupset local shorad = self.Groupset
local shoradset = shorad:GetAliveSet() --#table local shoradset = shorad:GetAliveSet() --#table
local returnname = false local returnname = false
--local TDiff = 1
for _,_groups in pairs (shoradset) do for _,_groups in pairs (shoradset) do
local groupname = _groups:GetName() local groupname = _groups:GetName()
if string.find(groupname, tgtgrp, 1, true) then if string.find(groupname, tgtgrp, 1, true) then
returnname = true returnname = true
--_groups:RelocateGroundRandomInRadius(7,100,false,false) -- be a bit evasive
end end
end end
return returnname return returnname
@@ -426,6 +470,7 @@ do
-- @param #number Radius Radius of the #ZONE -- @param #number Radius Radius of the #ZONE
-- @param #number ActiveTimer Number of seconds to stay active -- @param #number ActiveTimer Number of seconds to stay active
-- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC -- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC
-- @return #SHORAD self
-- @usage Use this function to integrate with other systems, example -- @usage Use this function to integrate with other systems, example
-- --
-- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart() -- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()
@@ -452,28 +497,35 @@ do
local targetzone = ZONE_RADIUS:New("Shorad",targetvec2,Radius) -- create a defense zone to check local targetzone = ZONE_RADIUS:New("Shorad",targetvec2,Radius) -- create a defense zone to check
local groupset = self.Groupset --Core.Set#SET_GROUP local groupset = self.Groupset --Core.Set#SET_GROUP
local shoradset = groupset:GetAliveSet() --#table local shoradset = groupset:GetAliveSet() --#table
-- local function to switch off shorad again -- local function to switch off shorad again
local function SleepShorad(group) local function SleepShorad(group)
local groupname = group:GetName() if group and group:IsAlive() then
self.ActiveGroups[groupname] = nil local groupname = group:GetName()
if self.UseEmOnOff then self.ActiveGroups[groupname] = nil
group:EnableEmission(false) if self.UseEmOnOff then
--group:SetAIOff() group:EnableEmission(false)
else else
group:OptionAlarmStateGreen() group:OptionAlarmStateGreen()
end
local text = string.format("Sleeping SHORAD %s", group:GetName())
self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
--Shoot and Scoot
if self.shootandscoot then
self:__ShootAndScoot(1,group)
end
end end
local text = string.format("Sleeping SHORAD %s", group:GetName())
self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
end end
-- go through set and find the one(s) to activate -- go through set and find the one(s) to activate
local TDiff = 4
for _,_group in pairs (shoradset) do for _,_group in pairs (shoradset) do
if _group:IsAnyInZone(targetzone) then if _group:IsAnyInZone(targetzone) then
local text = string.format("Waking up SHORAD %s", _group:GetName()) local text = string.format("Waking up SHORAD %s", _group:GetName())
self:T(text) self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
if self.UseEmOnOff then if self.UseEmOnOff then
--_group:SetAIOn()
_group:EnableEmission(true) _group:EnableEmission(true)
end end
_group:OptionAlarmStateRed() _group:OptionAlarmStateRed()
@@ -481,91 +533,132 @@ do
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
self.ActiveGroups[groupname] = { Timing = ActiveTimer } self.ActiveGroups[groupname] = { Timing = ActiveTimer }
local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit
timer.scheduleFunction(SleepShorad, _group, endtime) self.ActiveGroups[groupname].Timer = TIMER:New(SleepShorad,_group):Start(endtime)
--Shoot and Scoot
if self.shootandscoot then
self:__ShootAndScoot(TDiff,_group)
TDiff=TDiff+1
end
end end
end end
end end
return self return self
end end
--- (Internal) Calculate hit zone of an AGM-88 --- (Internal) Calculate hit zone of an AGM-88
-- @param #SHORAD self -- @param #SHORAD self
-- @param #table SEADWeapon DCS.Weapon object -- @param #table SEADWeapon DCS.Weapon object
-- @param Core.Point#COORDINATE pos0 Position of the plane when it fired -- @param Core.Point#COORDINATE pos0 Position of the plane when it fired
-- @param #number height Height when the missile was fired -- @param #number height Height when the missile was fired
-- @param Wrapper.Group#GROUP SEADGroup Attacker group -- @param Wrapper.Group#GROUP SEADGroup Attacker group
-- @return #SHORAD self -- @return #SHORAD self
function SHORAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADGroup) function SHORAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADGroup)
self:T("**** Calculating hit zone") self:T("**** Calculating hit zone")
if SEADWeapon and SEADWeapon:isExist() then if SEADWeapon and SEADWeapon:isExist() then
--local pos = SEADWeapon:getPoint() --local pos = SEADWeapon:getPoint()
-- postion and height
local position = SEADWeapon:getPosition()
local mheight = height
-- heading
local wph = math.atan2(position.x.z, position.x.x)
if wph < 0 then
wph=wph+2*math.pi
end
wph=math.deg(wph)
-- velocity
local wpndata = SEAD.HarmData["AGM_88"]
local mveloc = math.floor(wpndata[2] * 340.29)
local c1 = (2*mheight*9.81)/(mveloc^2)
local c2 = (mveloc^2) / 9.81
local Ropt = c2 * math.sqrt(c1+1)
if height <= 5000 then
Ropt = Ropt * 0.72
elseif height <= 7500 then
Ropt = Ropt * 0.82
elseif height <= 10000 then
Ropt = Ropt * 0.87
elseif height <= 12500 then
Ropt = Ropt * 0.98
end
-- look at a couple of zones across the trajectory
for n=1,3 do
local dist = Ropt - ((n-1)*20000)
local predpos= pos0:Translate(dist,wph)
if predpos then
-- postion and height local targetzone = ZONE_RADIUS:New("Target Zone",predpos:GetVec2(),20000)
local position = SEADWeapon:getPosition()
local mheight = height if self.debug then
-- heading predpos:MarkToAll(string.format("height=%dm | heading=%d | velocity=%ddeg | Ropt=%dm",mheight,wph,mveloc,Ropt),false)
local wph = math.atan2(position.x.z, position.x.x) targetzone:DrawZone(coalition.side.BLUE,{0,0,1},0.2,nil,nil,3,true)
if wph < 0 then end
wph=wph+2*math.pi
end local seadset = self.Groupset
wph=math.deg(wph) local tgtcoord = targetzone:GetRandomPointVec2()
local tgtgrp = seadset:FindNearestGroupFromPointVec2(tgtcoord)
-- velocity local _targetgroup = nil
local wpndata = SEAD.HarmData["AGM_88"] local _targetgroupname = "none"
local mveloc = math.floor(wpndata[2] * 340.29) local _targetskill = "Random"
local c1 = (2*mheight*9.81)/(mveloc^2) if tgtgrp and tgtgrp:IsAlive() then
local c2 = (mveloc^2) / 9.81 _targetgroup = tgtgrp
local Ropt = c2 * math.sqrt(c1+1) _targetgroupname = tgtgrp:GetName() -- group name
if height <= 5000 then _targetskill = tgtgrp:GetUnit(1):GetSkill()
Ropt = Ropt * 0.72 self:T("*** Found Target = ".. _targetgroupname)
elseif height <= 7500 then self:WakeUpShorad(_targetgroupname, self.Radius, self.ActiveTimer, Object.Category.UNIT)
Ropt = Ropt * 0.82 end
elseif height <= 10000 then end
Ropt = Ropt * 0.87 end
elseif height <= 12500 then
Ropt = Ropt * 0.98
end end
return self
-- look at a couple of zones across the trajectory end
for n=1,3 do
local dist = Ropt - ((n-1)*20000)
local predpos= pos0:Translate(dist,wph)
if predpos then
local targetzone = ZONE_RADIUS:New("Target Zone",predpos:GetVec2(),20000) --- (Internal) Shoot and Scoot
-- @param #SHORAD self
if self.debug then -- @param #string From
predpos:MarkToAll(string.format("height=%dm | heading=%d | velocity=%ddeg | Ropt=%dm",mheight,wph,mveloc,Ropt),false) -- @param #string Event
targetzone:DrawZone(coalition.side.BLUE,{0,0,1},0.2,nil,nil,3,true) -- @param #string To
end -- @param Wrapper.Group#GROUP Shorad Shorad group
-- @return #SHORAD self
local seadset = self.Groupset function SHORAD:onafterShootAndScoot(From,Event,To,Shorad)
local tgtcoord = targetzone:GetRandomPointVec2() self:T( { From,Event,To } )
local tgtgrp = seadset:FindNearestGroupFromPointVec2(tgtcoord) local possibleZones = {}
local _targetgroup = nil local mindist = self.minscootdist or 100
local _targetgroupname = "none" local maxdist = self.maxscootdist or 3000
local _targetskill = "Random" if Shorad and Shorad:IsAlive() then
if tgtgrp and tgtgrp:IsAlive() then local NowCoord = Shorad:GetCoordinate()
_targetgroup = tgtgrp for _,_zone in pairs(self.SkateZones.Set) do
_targetgroupname = tgtgrp:GetName() -- group name local zone = _zone -- Core.Zone#ZONE_RADIUS
_targetskill = tgtgrp:GetUnit(1):GetSkill() local dist = NowCoord:Get2DDistance(zone:GetCoordinate())
self:T("*** Found Target = ".. _targetgroupname) if dist >= mindist and dist <= maxdist then
self:WakeUpShorad(_targetgroupname, self.Radius, self.ActiveTimer, Object.Category.UNIT) possibleZones[#possibleZones+1] = zone
if #possibleZones == self.SkateNumber then break end
end end
end end
end if #possibleZones > 0 and Shorad:GetVelocityKMH() < 2 then
local rand = math.floor(math.random(1,#possibleZones*1000)/1000+0.5)
if rand == 0 then rand = 1 end
self:T(self.lid .. " ShootAndScoot to zone "..rand)
local ToCoordinate = possibleZones[rand]:GetCoordinate()
if self.scootrandomcoord then
ToCoordinate = possibleZones[rand]:GetRandomCoordinate(nil,nil,{land.SurfaceType.LAND,land.SurfaceType.ROAD})
end
local formation = self.scootformation or "Cone"
Shorad:RouteGroundTo(ToCoordinate,20,formation,1)
end
end
return self
end end
return self
end
--- Main function - work on the EventData --- Main function - work on the EventData
-- @param #SHORAD self -- @param #SHORAD self
-- @param Core.Event#EVENTDATA EventData The event details table data set -- @param Core.Event#EVENTDATA EventData The event details table data set
-- @return #SHORAD self
function SHORAD:HandleEventShot( EventData ) function SHORAD:HandleEventShot( EventData )
self:T( { EventData } ) self:T( { EventData } )
self:T(self.lid .. " HandleEventShot") self:T(self.lid .. " HandleEventShot")
--local ShootingUnit = EventData.IniDCSUnit
--local ShootingUnitName = EventData.IniDCSUnitName
local ShootingWeapon = EventData.Weapon -- Identify the weapon fired local ShootingWeapon = EventData.Weapon -- Identify the weapon fired
local ShootingWeaponName = EventData.WeaponName -- return weapon type local ShootingWeaponName = EventData.WeaponName -- return weapon type
-- get firing coalition -- get firing coalition
@@ -596,27 +689,18 @@ end
return self return self
end end
local targetcat = targetdata:getCategory() -- Identify category local targetcat = Object.getCategory(targetdata) -- Identify category
self:T(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat))) self:T(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat)))
self:T({targetdata}) self:T({targetdata})
local targetunit = nil local targetunit = nil
if targetcat == Object.Category.UNIT then -- UNIT if targetcat == Object.Category.UNIT then -- UNIT
targetunit = UNIT:Find(targetdata) targetunit = UNIT:Find(targetdata)
elseif targetcat == Object.Category.STATIC then -- STATIC elseif targetcat == Object.Category.STATIC then -- STATIC
--self:T("Static Target Data")
--self:T({targetdata:isExist()})
--self:T({targetdata:getPoint()})
local tgtcoord = COORDINATE:NewFromVec3(targetdata:getPoint()) local tgtcoord = COORDINATE:NewFromVec3(targetdata:getPoint())
--tgtcoord:MarkToAll("Missile Target",true) local tgtgrp1 = self.Samset:FindNearestGroupFromPointVec2(tgtcoord)
local tgtgrp1 = self.Samset:FindNearestGroupFromPointVec2(tgtcoord)
local tgtcoord1 = tgtgrp1:GetCoordinate() local tgtcoord1 = tgtgrp1:GetCoordinate()
--tgtcoord1:MarkToAll("Close target SAM",true)
local tgtgrp2 = self.Groupset:FindNearestGroupFromPointVec2(tgtcoord) local tgtgrp2 = self.Groupset:FindNearestGroupFromPointVec2(tgtcoord)
local tgtcoord2 = tgtgrp2:GetCoordinate() local tgtcoord2 = tgtgrp2:GetCoordinate()
--tgtcoord2:MarkToAll("Close target SHORAD",true)
local dist1 = tgtcoord:Get2DDistance(tgtcoord1) local dist1 = tgtcoord:Get2DDistance(tgtcoord1)
local dist2 = tgtcoord:Get2DDistance(tgtcoord2) local dist2 = tgtcoord:Get2DDistance(tgtcoord2)
@@ -628,10 +712,8 @@ end
targetcat = Object.Category.UNIT targetcat = Object.Category.UNIT
end end
end end
--local targetunitname = Unit.getName(targetdata) -- Unit name
if targetunit and targetunit:IsAlive() then if targetunit and targetunit:IsAlive() then
local targetunitname = targetunit:GetName() local targetunitname = targetunit:GetName()
--local targetgroup = Unit.getGroup(Weapon.getTarget(ShootingWeapon)) --targeted group
local targetgroup = nil local targetgroup = nil
local targetgroupname = "none" local targetgroupname = "none"
if targetcat == Object.Category.UNIT then if targetcat == Object.Category.UNIT then
@@ -649,7 +731,6 @@ end
self:T( text ) self:T( text )
local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug)
-- check if we or a SAM site are the target -- check if we or a SAM site are the target
--local TargetGroup = EventData.TgtGroup -- Wrapper.Group#GROUP
local shotatus = self:_CheckShotAtShorad(targetgroupname) --#boolean local shotatus = self:_CheckShotAtShorad(targetgroupname) --#boolean
local shotatsams = self:_CheckShotAtSams(targetgroupname) --#boolean local shotatsams = self:_CheckShotAtSams(targetgroupname) --#boolean
-- if being shot at, find closest SHORADs to activate -- if being shot at, find closest SHORADs to activate
@@ -666,4 +747,4 @@ end
end end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- SHORAD end -- SHORAD end
----------------------------------------------------------------------- -----------------------------------------------------------------------

View File

@@ -33,9 +33,9 @@
-- --
-- === -- ===
-- --
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- ### Author: **funkyfranky**
-- --
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536) -- ### Contributions: FlightControl
-- --
-- === -- ===
-- --

View File

@@ -742,7 +742,7 @@
-- --
-- ## Save Assets -- ## Save Assets
-- --
-- Saving asset data to file is achieved by the @{WAREHOUSE.Save}(*path*, *filename*) function. The parameter *path* specifies the path on the file system where the -- Saving asset data to file is achieved by the @{#WAREHOUSE.Save}(*path*, *filename*) function. The parameter *path* specifies the path on the file system where the
-- warehouse data is saved. If you do not specify a path, the file is saved your the DCS installation root directory. -- warehouse data is saved. If you do not specify a path, the file is saved your the DCS installation root directory.
-- The parameter *filename* is optional and defines the name of the saved file. By default this is automatically created from the warehouse id and name, for example -- The parameter *filename* is optional and defines the name of the saved file. By default this is automatically created from the warehouse id and name, for example
-- "Warehouse-1234_Batumi.txt". -- "Warehouse-1234_Batumi.txt".
@@ -753,13 +753,13 @@
-- --
-- ### Automatic Save at Mission End -- ### Automatic Save at Mission End
-- --
-- The assets can be saved automatically when the mission is ended via the @{WAREHOUSE.SetSaveOnMissionEnd}(*path*, *filename*) function, i.e. -- The assets can be saved automatically when the mission is ended via the @{#WAREHOUSE.SetSaveOnMissionEnd}(*path*, *filename*) function, i.e.
-- --
-- warehouseBatumi:SetSaveOnMissionEnd("D:\\My Warehouse Data\\") -- warehouseBatumi:SetSaveOnMissionEnd("D:\\My Warehouse Data\\")
-- --
-- ## Load Assets -- ## Load Assets
-- --
-- Loading assets data from file is achieved by the @{WAREHOUSE.Load}(*path*, *filename*) function. The parameter *path* specifies the path on the file system where the -- Loading assets data from file is achieved by the @{#WAREHOUSE.Load}(*path*, *filename*) function. The parameter *path* specifies the path on the file system where the
-- warehouse data is loaded from. If you do not specify a path, the file is loaded from your the DCS installation root directory. -- warehouse data is loaded from. If you do not specify a path, the file is loaded from your the DCS installation root directory.
-- The parameter *filename* is optional and defines the name of the file to load. By default this is automatically generated from the warehouse id and name, for example -- The parameter *filename* is optional and defines the name of the file to load. By default this is automatically generated from the warehouse id and name, for example
-- "Warehouse-1234_Batumi.txt". -- "Warehouse-1234_Batumi.txt".
@@ -7404,6 +7404,8 @@ function WAREHOUSE:_CheckRequestNow(request)
-- Check if at least one (cargo) asset is available. -- Check if at least one (cargo) asset is available.
if _nassets>0 then if _nassets>0 then
local asset=_assets[1] --#WAREHOUSE.Assetitem
-- Get the attibute of the requested asset. -- Get the attibute of the requested asset.
_assetattribute=_assets[1].attribute _assetattribute=_assets[1].attribute
@@ -7414,11 +7416,24 @@ function WAREHOUSE:_CheckRequestNow(request)
if _assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER then if _assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER then
if self.airbase and self.airbase:GetCoalition()==self:GetCoalition() then if self.airbase and self.airbase:GetCoalition()==self:GetCoalition() then
-- Check if DCS warehouse of airbase has enough assets
if self.airbase.storage then
local nS=self.airbase.storage:GetAmount(asset.unittype)
local nA=asset.nunits*request.nasset -- Number of units requested
if nS<nA then
local text=string.format("Warehouse %s: Request denied! DCS Warehouse has only %d assets of type %s ==> NOT enough to spawn the requested %d asset units (%d groups)",
self.alias, nS, asset.unittype, nA, request.nasset)
self:_InfoMessage(text, 5)
return false
end
end
if self:IsRunwayOperational() or _assetairstart then if self:IsRunwayOperational() or _assetairstart then
if _assetairstart then if _assetairstart then
-- Airstart no need to check parking -- Airstart no need to check parking
else else
-- Check parking. -- Check parking.
@@ -7530,6 +7545,9 @@ function WAREHOUSE:_CheckRequestNow(request)
self:_InfoMessage(text, 5) self:_InfoMessage(text, 5)
return false return false
end end
elseif _assetcategory==Group.Category.AIRPLANE or _assetcategory==Group.Category.HELICOPTER then
end end
@@ -7870,7 +7888,7 @@ function WAREHOUSE:_GetTerminal(_attribute, _category)
-- Default terminal is "large". -- Default terminal is "large".
local _terminal=AIRBASE.TerminalType.OpenBig local _terminal=AIRBASE.TerminalType.OpenBig
if _attribute==WAREHOUSE.Attribute.AIR_FIGHTER then if _attribute==WAREHOUSE.Attribute.AIR_FIGHTER or _attribute==WAREHOUSE.Attribute.AIR_UAV then
-- Fighter ==> small. -- Fighter ==> small.
_terminal=AIRBASE.TerminalType.FighterAircraft _terminal=AIRBASE.TerminalType.FighterAircraft
elseif _attribute==WAREHOUSE.Attribute.AIR_BOMBER or _attribute==WAREHOUSE.Attribute.AIR_TRANSPORTPLANE or _attribute==WAREHOUSE.Attribute.AIR_TANKER or _attribute==WAREHOUSE.Attribute.AIR_AWACS then elseif _attribute==WAREHOUSE.Attribute.AIR_BOMBER or _attribute==WAREHOUSE.Attribute.AIR_TRANSPORTPLANE or _attribute==WAREHOUSE.Attribute.AIR_TANKER or _attribute==WAREHOUSE.Attribute.AIR_AWACS then

View File

@@ -363,8 +363,8 @@ do -- ZONE_CAPTURE_COALITION
--- ZONE_CAPTURE_COALITION Constructor. --- ZONE_CAPTURE_COALITION Constructor.
-- @param #ZONE_CAPTURE_COALITION self -- @param #ZONE_CAPTURE_COALITION self
-- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved. Alternatively, can be handed as the name of late activated group describing a @{ZONE_POLYGON} with its waypoints. -- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved. Alternatively, can be handed as the name of late activated group describing a @{Core.Zone#ZONE_POLYGON} with its waypoints.
-- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. -- @param #number Coalition The initial coalition owning the zone.
-- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}. -- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}.
-- @param #table ObjectCategories Table of unit categories. See [DCS Class Object](https://wiki.hoggitworld.com/view/DCS_Class_Object). Default {Object.Category.UNIT, Object.Category.STATIC}, i.e. all UNITS and STATICS. -- @param #table ObjectCategories Table of unit categories. See [DCS Class Object](https://wiki.hoggitworld.com/view/DCS_Class_Object). Default {Object.Category.UNIT, Object.Category.STATIC}, i.e. all UNITS and STATICS.
-- @return #ZONE_CAPTURE_COALITION -- @return #ZONE_CAPTURE_COALITION

View File

@@ -4,12 +4,12 @@
-- --
-- ZONE_GOAL_CARGO models processes that have a Goal with a defined achievement involving a Zone and Cargo. -- ZONE_GOAL_CARGO models processes that have a Goal with a defined achievement involving a Zone and Cargo.
-- Derived classes implement the ways how the achievements can be realized. -- Derived classes implement the ways how the achievements can be realized.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
@@ -61,7 +61,7 @@ do -- ZoneGoal
--- ZONE_GOAL_CARGO Constructor. --- ZONE_GOAL_CARGO Constructor.
-- @param #ZONE_GOAL_CARGO self -- @param #ZONE_GOAL_CARGO self
-- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved. -- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved.
-- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. -- @param #number Coalition The initial coalition owning the zone.
-- @return #ZONE_GOAL_CARGO -- @return #ZONE_GOAL_CARGO
function ZONE_GOAL_CARGO:New( Zone, Coalition ) function ZONE_GOAL_CARGO:New( Zone, Coalition )
@@ -259,7 +259,7 @@ do -- ZoneGoal
--- Set the owning coalition of the zone. --- Set the owning coalition of the zone.
-- @param #ZONE_GOAL_CARGO self -- @param #ZONE_GOAL_CARGO self
-- @param DCSCoalition.DCSCoalition#coalition Coalition -- @param #number Coalition
function ZONE_GOAL_CARGO:SetCoalition( Coalition ) function ZONE_GOAL_CARGO:SetCoalition( Coalition )
self.Coalition = Coalition self.Coalition = Coalition
end end
@@ -267,7 +267,7 @@ do -- ZoneGoal
--- Get the owning coalition of the zone. --- Get the owning coalition of the zone.
-- @param #ZONE_GOAL_CARGO self -- @param #ZONE_GOAL_CARGO self
-- @return DCSCoalition.DCSCoalition#coalition Coalition. -- @return #number Coalition.
function ZONE_GOAL_CARGO:GetCoalition() function ZONE_GOAL_CARGO:GetCoalition()
return self.Coalition return self.Coalition
end end

View File

@@ -54,7 +54,7 @@ do -- ZoneGoal
--- ZONE_GOAL_COALITION Constructor. --- ZONE_GOAL_COALITION Constructor.
-- @param #ZONE_GOAL_COALITION self -- @param #ZONE_GOAL_COALITION self
-- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved. -- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved.
-- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. Default coalition.side.NEUTRAL. -- @param #number Coalition The initial coalition owning the zone. Default coalition.side.NEUTRAL.
-- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}. -- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}.
-- @return #ZONE_GOAL_COALITION -- @return #ZONE_GOAL_COALITION
function ZONE_GOAL_COALITION:New( Zone, Coalition, UnitCategories ) function ZONE_GOAL_COALITION:New( Zone, Coalition, UnitCategories )
@@ -80,7 +80,7 @@ do -- ZoneGoal
--- Set the owning coalition of the zone. --- Set the owning coalition of the zone.
-- @param #ZONE_GOAL_COALITION self -- @param #ZONE_GOAL_COALITION self
-- @param DCSCoalition.DCSCoalition#coalition Coalition The coalition ID, e.g. *coalition.side.RED*. -- @param #number Coalition The coalition ID, e.g. *coalition.side.RED*.
-- @return #ZONE_GOAL_COALITION -- @return #ZONE_GOAL_COALITION
function ZONE_GOAL_COALITION:SetCoalition( Coalition ) function ZONE_GOAL_COALITION:SetCoalition( Coalition )
self.PreviousCoalition = self.Coalition or Coalition self.PreviousCoalition = self.Coalition or Coalition
@@ -120,14 +120,14 @@ do -- ZoneGoal
--- Get the owning coalition of the zone. --- Get the owning coalition of the zone.
-- @param #ZONE_GOAL_COALITION self -- @param #ZONE_GOAL_COALITION self
-- @return DCSCoalition.DCSCoalition#coalition Coalition. -- @return #number Coalition.
function ZONE_GOAL_COALITION:GetCoalition() function ZONE_GOAL_COALITION:GetCoalition()
return self.Coalition return self.Coalition
end end
--- Get the previous coalition, i.e. the one owning the zone before the current one. --- Get the previous coalition, i.e. the one owning the zone before the current one.
-- @param #ZONE_GOAL_COALITION self -- @param #ZONE_GOAL_COALITION self
-- @return DCSCoalition.DCSCoalition#coalition Coalition. -- @return #number Coalition.
function ZONE_GOAL_COALITION:GetPreviousCoalition() function ZONE_GOAL_COALITION:GetPreviousCoalition()
return self.PreviousCoalition return self.PreviousCoalition
end end

View File

@@ -312,10 +312,16 @@
-- --
-- atis=ATIS:New("Batumi", 305, radio.modulation.AM) -- atis=ATIS:New("Batumi", 305, radio.modulation.AM)
-- atis:SetSRS("D:\\DCS\\_SRS\\", "male", "en-US") -- atis:SetSRS("D:\\DCS\\_SRS\\", "male", "en-US")
-- atis:Start() -- atis:Start()
-- --
-- This uses a male voice with US accent. It requires SRS to be installed in the `D:\DCS\_SRS\` directory. Note that backslashes need to be escaped or simply use slashes (as in linux). -- This uses a male voice with US accent. It requires SRS to be installed in the `D:\DCS\_SRS\` directory. Note that backslashes need to be escaped or simply use slashes (as in linux).
-- --
-- ### SRS can use multiple frequencies:
--
-- atis=ATIS:New("Batumi", {305,103.85}, {radio.modulation.AM,radio.modulation.FM})
-- atis:SetSRS("D:\\DCS\\_SRS\\", "male", "en-US")
-- atis:Start()
--
-- ### SRS Localization -- ### SRS Localization
-- --
-- You can localize the SRS output, all you need is to provide a table of translations and set the `locale` of your instance. You need to provide the translations in your script **before you instantiate your ATIS**. -- You can localize the SRS output, all you need is to provide a table of translations and set the `locale` of your instance. You need to provide the translations in your script **before you instantiate your ATIS**.
@@ -353,6 +359,7 @@
-- DEWPOINT = "Taupunkt", -- DEWPOINT = "Taupunkt",
-- ALTIMETER = "Hoehenmesser", -- ALTIMETER = "Hoehenmesser",
-- ACTIVERUN = "Aktive Startbahn", -- ACTIVERUN = "Aktive Startbahn",
-- ACTIVELANDING = "Aktive Landebahn",
-- LEFT = "Links", -- LEFT = "Links",
-- RIGHT = "Rechts", -- RIGHT = "Rechts",
-- RWYLENGTH = "Startbahn", -- RWYLENGTH = "Startbahn",
@@ -721,7 +728,8 @@ ATIS.Messages = {
TEMPERATURE = "Temperature", TEMPERATURE = "Temperature",
DEWPOINT = "Dew point", DEWPOINT = "Dew point",
ALTIMETER = "Altimeter", ALTIMETER = "Altimeter",
ACTIVERUN = "Active runway", ACTIVERUN = "Active runway departure",
ACTIVELANDING = "Active runway arrival",
LEFT = "Left", LEFT = "Left",
RIGHT = "Right", RIGHT = "Right",
RWYLENGTH = "Runway length", RWYLENGTH = "Runway length",
@@ -781,6 +789,7 @@ ATIS.Messages = {
DEWPOINT = "Taupunkt", DEWPOINT = "Taupunkt",
ALTIMETER = "Hoehenmesser", ALTIMETER = "Hoehenmesser",
ACTIVERUN = "Aktive Startbahn", ACTIVERUN = "Aktive Startbahn",
ACTIVELANDING = "Aktive Landebahn",
LEFT = "Links", LEFT = "Links",
RIGHT = "Rechts", RIGHT = "Rechts",
RWYLENGTH = "Startbahn", RWYLENGTH = "Startbahn",
@@ -841,6 +850,7 @@ ATIS.Messages = {
DEWPOINT = "Punto de rocio", DEWPOINT = "Punto de rocio",
ALTIMETER = "Altímetro", ALTIMETER = "Altímetro",
ACTIVERUN = "Pista activa", ACTIVERUN = "Pista activa",
ACTIVELANDING = "Pista de aterrizaje activa",
LEFT = "Izquierda", LEFT = "Izquierda",
RIGHT = "Derecha", RIGHT = "Derecha",
RWYLENGTH = "Longitud de pista", RWYLENGTH = "Longitud de pista",
@@ -880,13 +890,14 @@ _ATIS = {}
--- ATIS class version. --- ATIS class version.
-- @field #string version -- @field #string version
ATIS.version = "0.10.2" ATIS.version = "0.10.4"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Correct fog for elevation. -- TODO: Correct fog for elevation.
-- DONE: Option to add multiple frequencies for SRS
-- DONE: Zulu time --> Zulu in output. -- DONE: Zulu time --> Zulu in output.
-- DONE: Fix for AB not having a runway - Helopost like Naqoura -- DONE: Fix for AB not having a runway - Helopost like Naqoura
-- DONE: Add new Normandy airfields. -- DONE: Add new Normandy airfields.
@@ -895,13 +906,14 @@ ATIS.version = "0.10.2"
-- DONE: Visibility reported twice over SRS -- DONE: Visibility reported twice over SRS
-- DONE: Add text report for output. -- DONE: Add text report for output.
-- DONE: Add stop FMS functions. -- DONE: Add stop FMS functions.
-- NOGO: Use local time. Not realisitc! -- NOGO: Use local time. Not realistic!
-- DONE: Dew point. Approx. done. -- DONE: Dew point. Approx. done.
-- DONE: Metric units. -- DONE: Metric units.
-- DONE: Set UTC correction. -- DONE: Set UTC correction.
-- DONE: Set magnetic variation. -- DONE: Set magnetic variation.
-- DONE: New DCS 2.7 weather presets. -- DONE: New DCS 2.7 weather presets.
-- DONE: Added TextAndSound localization -- DONE: Added TextAndSound localization
-- DONE: Added SRS spelling out both take off and landing runway
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor -- Constructor
@@ -910,8 +922,8 @@ ATIS.version = "0.10.2"
--- Create a new ATIS class object for a specific airbase. --- Create a new ATIS class object for a specific airbase.
-- @param #ATIS self -- @param #ATIS self
-- @param #string AirbaseName Name of the airbase. -- @param #string AirbaseName Name of the airbase.
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. -- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. When using **SRS** this can be passed as a table of multiple frequencies.
-- @param #number Modulation Radio modulation: 0=AM, 1=FM. Default 0=AM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. -- @param #number Modulation Radio modulation: 0=AM, 1=FM. Default 0=AM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. When using **SRS** this can be passed as a table of multiple modulations.
-- @return #ATIS self -- @return #ATIS self
function ATIS:New(AirbaseName, Frequency, Modulation) function ATIS:New(AirbaseName, Frequency, Modulation)
@@ -1534,6 +1546,7 @@ function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey)
self.msrs:SetCoalition(self:GetCoalition()) self.msrs:SetCoalition(self:GetCoalition())
self.msrs:SetLabel("ATIS") self.msrs:SetLabel("ATIS")
self.msrs:SetGoogle(GoogleKey) self.msrs:SetGoogle(GoogleKey)
self.msrs:SetCoordinate(self.airbase:GetCoordinate())
self.msrsQ = MSRSQUEUE:New("ATIS") self.msrsQ = MSRSQUEUE:New("ATIS")
self.msrsQ:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers) self.msrsQ:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
if self.dTQueueCheck<=10 then if self.dTQueueCheck<=10 then
@@ -1588,8 +1601,16 @@ function ATIS:onafterStart( From, Event, To )
end end
-- Info. -- Info.
self:I( self.lid .. string.format( "Starting ATIS v%s for airbase %s on %.3f MHz Modulation=%d", ATIS.version, self.airbasename, self.frequency, self.modulation ) ) if type(self.frequency) == "table" then
local frequency = table.concat(self.frequency,"/")
local modulation = self.modulation
if type(self.modulation) == "table" then
modulation = table.concat(self.modulation,"/")
end
self:I( self.lid .. string.format( "Starting ATIS v%s for airbase %s on %s MHz Modulation=%s", ATIS.version, self.airbasename, frequency, modulation ) )
else
self:I( self.lid .. string.format( "Starting ATIS v%s for airbase %s on %.3f MHz Modulation=%d", ATIS.version, self.airbasename, self.frequency, self.modulation ) )
end
-- Start radio queue. -- Start radio queue.
if not self.useSRS then if not self.useSRS then
self.radioqueue = RADIOQUEUE:New( self.frequency, self.modulation, string.format( "ATIS %s", self.airbasename ) ) self.radioqueue = RADIOQUEUE:New( self.frequency, self.modulation, string.format( "ATIS %s", self.airbasename ) )
@@ -1647,7 +1668,17 @@ function ATIS:onafterStatus( From, Event, To )
end end
-- Info text. -- Info text.
local text = string.format( "State %s: Freq=%.3f MHz %s", fsmstate, self.frequency, UTILS.GetModulationName( self.modulation ) ) local text = ""
if type(self.frequency) == "table" then
local frequency = table.concat(self.frequency,"/")
local modulation = self.modulation
if type(self.modulation) == "table" then
modulation = table.concat(self.modulation,"/")
end
text = string.format( "State %s: Freq=%s MHz %s", fsmstate, frequency, modulation )
else
text = string.format( "State %s: Freq=%.3f MHz %s", fsmstate, self.frequency, UTILS.GetModulationName( self.modulation ) )
end
if self.useSRS then if self.useSRS then
text = text .. string.format( ", SRS path=%s (%s), gender=%s, culture=%s, voice=%s", tostring( self.msrs.path ), tostring( self.msrs.port ), tostring( self.msrs.gender ), tostring( self.msrs.culture ), tostring( self.msrs.voice ) ) text = text .. string.format( ", SRS path=%s (%s), gender=%s, culture=%s, voice=%s", tostring( self.msrs.path ), tostring( self.msrs.port ), tostring( self.msrs.gender ), tostring( self.msrs.culture ), tostring( self.msrs.voice ) )
else else
@@ -2506,10 +2537,10 @@ function ATIS:onafterBroadcast( From, Event, To )
if not self.ATISforFARPs then if not self.ATISforFARPs then
-- Active runway. -- Active runway.
local subtitle local subtitle = ""
if runwayLanding then if runwayLanding then
local actrun = self.gettext:GetEntry("ACTIVERUN",self.locale) local actrun = self.gettext:GetEntry("ACTIVELANDING",self.locale)
--subtitle=string.format("Active runway %s", runwayLanding) --subtitle=string.format("Active runway landing %s", runwayLanding)
subtitle=string.format("%s %s", actrun, runwayLanding) subtitle=string.format("%s %s", actrun, runwayLanding)
if rwyLandingLeft==true then if rwyLandingLeft==true then
--subtitle=subtitle.." Left" --subtitle=subtitle.." Left"
@@ -2518,6 +2549,19 @@ function ATIS:onafterBroadcast( From, Event, To )
--subtitle=subtitle.." Right" --subtitle=subtitle.." Right"
subtitle=subtitle.." "..self.gettext:GetEntry("RIGHT",self.locale) subtitle=subtitle.." "..self.gettext:GetEntry("RIGHT",self.locale)
end end
alltext = alltext .. ";\n" .. subtitle
end
if runwayTakeoff then
local actrun = self.gettext:GetEntry("ACTIVERUN",self.locale)
--subtitle=string.format("Active runway %s", runwayLanding)
subtitle=string.format("%s %s", actrun, runwayTakeoff)
if rwyTakeoffLeft==true then
--subtitle=subtitle.." Left"
subtitle=subtitle.." "..self.gettext:GetEntry("LEFT",self.locale)
elseif rwyTakeoffLeft==false then
--subtitle=subtitle.." Right"
subtitle=subtitle.." "..self.gettext:GetEntry("RIGHT",self.locale)
end
end end
_RUNACT = subtitle _RUNACT = subtitle
if not self.useSRS then if not self.useSRS then
@@ -2900,8 +2944,17 @@ function ATIS:UpdateMarker( information, runact, wind, altimeter, temperature )
if self.markerid then if self.markerid then
self.airbase:GetCoordinate():RemoveMark( self.markerid ) self.airbase:GetCoordinate():RemoveMark( self.markerid )
end end
local text = ""
local text = string.format( "ATIS on %.3f %s, %s:\n", self.frequency, UTILS.GetModulationName( self.modulation ), tostring( information ) ) if type(self.frequency) == "table" then
local frequency = table.concat(self.frequency,"/")
local modulation = self.modulation
if type(modulation) == "table" then
modulation = table.concat(self.modulation,"/")
end
text = string.format( "ATIS on %s %s, %s:\n", tostring(frequency), tostring(modulation), tostring( information ) )
else
text = string.format( "ATIS on %.3f %s, %s:\n", self.frequency, UTILS.GetModulationName( self.modulation ), tostring( information ) )
end
text = text .. string.format( "%s\n", tostring( runact ) ) text = text .. string.format( "%s\n", tostring( runact ) )
text = text .. string.format( "%s\n", tostring( wind ) ) text = text .. string.format( "%s\n", tostring( wind ) )
text = text .. string.format( "%s\n", tostring( altimeter ) ) text = text .. string.format( "%s\n", tostring( altimeter ) )

View File

@@ -27,17 +27,17 @@
-- **Supported Carriers:** -- **Supported Carriers:**
-- --
-- * [USS John C. Stennis](https://en.wikipedia.org/wiki/USS_John_C._Stennis) (CVN-74) -- * [USS John C. Stennis](https://en.wikipedia.org/wiki/USS_John_C._Stennis) (CVN-74)
-- * [USS Theodore Roosevelt](https://en.wikipedia.org/wiki/USS_Theodore_Roosevelt_(CVN-71\)) (CVN-71) [Super Carrier Module] -- * [USS Theodore Roosevelt](https://en.wikipedia.org/wiki/USS_Theodore_Roosevelt_\(CVN-71\)) (CVN-71) [Super Carrier Module]
-- * [USS Abraham Lincoln](https://en.wikipedia.org/wiki/USS_Abraham_Lincoln_(CVN-72\)) (CVN-72) [Super Carrier Module] -- * [USS Abraham Lincoln](https://en.wikipedia.org/wiki/USS_Abraham_Lincoln_\(CVN-72\)) (CVN-72) [Super Carrier Module]
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73\)) (CVN-73) [Super Carrier Module] -- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_\(CVN-73\)) (CVN-73) [Super Carrier Module]
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module] -- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
-- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_(CV-59\)) (CV-59) [Heatblur Carrier Module] -- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_\(CV-59\)) (CV-59) [Heatblur Carrier Module]
-- * [HMS Hermes](https://en.wikipedia.org/wiki/HMS_Hermes_(R12\)) (R12) -- * [HMS Hermes](https://en.wikipedia.org/wiki/HMS_Hermes_\(R12\)) (R12)
-- * [HMS Invincible](https://en.wikipedia.org/wiki/HMS_Invincible_(R05\)) (R05) -- * [HMS Invincible](https://en.wikipedia.org/wiki/HMS_Invincible_\(R05\)) (R05)
-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1\)) (LHA-1) -- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_\(LHA-1\)) (LHA-1)
-- * [USS America](https://en.wikipedia.org/wiki/USS_America_(LHA-6\)) (LHA-6) -- * [USS America](https://en.wikipedia.org/wiki/USS_America_\(LHA-6\)) (LHA-6)
-- * [Juan Carlos I](https://en.wikipedia.org/wiki/Spanish_amphibious_assault_ship_Juan_Carlos_I) (L61) -- * [Juan Carlos I](https://en.wikipedia.org/wiki/Spanish_amphibious_assault_ship_Juan_Carlos_I) (L61)
-- * [HMAS Canberra](https://en.wikipedia.org/wiki/HMAS_Canberra_(L02\)) (L02) -- * [HMAS Canberra](https://en.wikipedia.org/wiki/HMAS_Canberra_\(L02\)) (L02)
-- --
-- **Supported Aircraft:** -- **Supported Aircraft:**
-- --
@@ -45,7 +45,7 @@
-- * [F-14A/B Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI) -- * [F-14A/B Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI)
-- * [A-4E Skyhawk Community Mod](https://forums.eagle.ru/showthread.php?t=224989) (Player & AI) -- * [A-4E Skyhawk Community Mod](https://forums.eagle.ru/showthread.php?t=224989) (Player & AI)
-- * [AV-8B N/A Harrier](https://forums.eagle.ru/forumdisplay.php?f=555) (Player & AI) -- * [AV-8B N/A Harrier](https://forums.eagle.ru/forumdisplay.php?f=555) (Player & AI)
-- * [T-45C Goshawk](https://www.vnao-cvw-7.com/t-45-goshawk) (VNAO mod) (Player & AI) -- * [T-45C Goshawk](https://forum.dcs.world/topic/203816-vnao-t-45-goshawk/) (VNAO mod) (Player & AI)
-- * [FE/A-18E/F/G Superhornet](https://forum.dcs.world/topic/316971-cjs-super-hornet-community-mod-v20-official-thread/) (CJS mod) (Player & AI) -- * [FE/A-18E/F/G Superhornet](https://forum.dcs.world/topic/316971-cjs-super-hornet-community-mod-v20-official-thread/) (CJS mod) (Player & AI)
-- * F/A-18C Hornet (AI) -- * F/A-18C Hornet (AI)
-- * F-14A Tomcat (AI) -- * F-14A Tomcat (AI)
@@ -61,7 +61,7 @@
-- --
-- Heatblur's mighty F-14B Tomcat has been added (March 13th 2019) as well. Same goes for the A version. -- Heatblur's mighty F-14B Tomcat has been added (March 13th 2019) as well. Same goes for the A version.
-- --
-- The [DCS Supercarriers](https://forums.eagle.ru/forum/151-dcs-supercarrier/) are also supported. -- The [DCS Supercarriers](https://www.digitalcombatsimulator.com/de/shop/modules/supercarrier/) are also supported.
-- --
-- ## Discussion -- ## Discussion
-- --
@@ -95,11 +95,6 @@
-- * [[MOOSE] Airboss - CASE I, "Until We Go Down" featuring the F-14B by Pikes](https://www.youtube.com/watch?v=ojgHDSw3Doc) -- * [[MOOSE] Airboss - CASE I, "Until We Go Down" featuring the F-14B by Pikes](https://www.youtube.com/watch?v=ojgHDSw3Doc)
-- * [[MOOSE] Airboss - Skipper Menu](https://youtu.be/awnecCxRoNQ) -- * [[MOOSE] Airboss - Skipper Menu](https://youtu.be/awnecCxRoNQ)
-- --
-- ### Lex explaining Boat Ops:
--
-- * [( DCS HORNET ) Some boat ops basics VID 1](https://www.youtube.com/watch?v=LvGQS-3AzMc)
-- * [( DCS HORNET ) Some boat ops basics VID 2](https://www.youtube.com/watch?v=bN44wvtRsw0)
--
-- ### Jabbers Case I and III Recovery Tutorials: -- ### Jabbers Case I and III Recovery Tutorials:
-- --
-- * [DCS World - F/A-18 - Case I Carrier Recovery Tutorial](https://www.youtube.com/watch?v=lm-M3VUy-_I) -- * [DCS World - F/A-18 - Case I Carrier Recovery Tutorial](https://www.youtube.com/watch?v=lm-M3VUy-_I)
@@ -1735,10 +1730,10 @@ AIRBOSS.Difficulty = {
-- @field #table trapsheet Groove data table recorded every 0.5 seconds. -- @field #table trapsheet Groove data table recorded every 0.5 seconds.
-- @field #boolean trapon If true, save trap sheets. -- @field #boolean trapon If true, save trap sheets.
-- @field #string debriefschedulerID Debrief scheduler ID. -- @field #string debriefschedulerID Debrief scheduler ID.
-- --
-- @field Sound.SRS#MSRS SRS -- @field Sound.SRS#MSRS SRS
-- @field Sound.SRS#MSRSQUEUE SRSQ -- @field Sound.SRS#MSRSQUEUE SRSQ
-- --
-- @extends #AIRBOSS.FlightGroup -- @extends #AIRBOSS.FlightGroup
--- Main group level radio menu: F10 Other/Airboss. --- Main group level radio menu: F10 Other/Airboss.
@@ -1751,7 +1746,7 @@ AIRBOSS.MenuF10Root = nil
--- Airboss class version. --- Airboss class version.
-- @field #string version -- @field #string version
AIRBOSS.version = "1.3.2" AIRBOSS.version = "1.3.3"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -3058,7 +3053,7 @@ end
-- @param #number Port Port of the SRS server, defaults to 5002. -- @param #number Port Port of the SRS server, defaults to 5002.
-- @param #string Culture (Optional, Airboss Culture) Culture, defaults to "en-US". -- @param #string Culture (Optional, Airboss Culture) Culture, defaults to "en-US".
-- @param #string Gender (Optional, Airboss Gender) Gender, e.g. "male" or "female". Defaults to "male". -- @param #string Gender (Optional, Airboss Gender) Gender, e.g. "male" or "female". Defaults to "male".
-- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings. -- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings.
-- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json". -- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json".
-- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest). -- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest).
-- @param #table AltBackend (Optional) See MSRS for details. -- @param #table AltBackend (Optional) See MSRS for details.
@@ -3076,6 +3071,7 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
self.SRS:SetPath(PathToSRS) self.SRS:SetPath(PathToSRS)
self.SRS:SetPort(Port or 5002) self.SRS:SetPort(Port or 5002)
self.SRS:SetLabel(self.AirbossRadio.alias or "AIRBOSS") self.SRS:SetLabel(self.AirbossRadio.alias or "AIRBOSS")
self.SRS:SetCoordinate(self.carrier:GetCoordinate())
--self.SRS:SetModulations(Modulations) --self.SRS:SetModulations(Modulations)
if GoogleCreds then if GoogleCreds then
self.SRS:SetGoogle(GoogleCreds) self.SRS:SetGoogle(GoogleCreds)
@@ -3087,10 +3083,10 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
-- SRSQUEUE -- SRSQUEUE
self.SRSQ = MSRSQUEUE:New("AIRBOSS") self.SRSQ = MSRSQUEUE:New("AIRBOSS")
self.SRSQ:SetTransmitOnlyWithPlayers(true) self.SRSQ:SetTransmitOnlyWithPlayers(true)
if not self.PilotRadio then if not self.PilotRadio then
self:SetSRSPilotVoice() self:SetSRSPilotVoice()
end end
return self return self
end end
--- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM. --- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM.
@@ -10271,7 +10267,7 @@ function AIRBOSS:_GetSternCoord()
elseif case==2 or case==1 then elseif case==2 or case==1 then
-- V/Stol: Translate 8 meters port. -- V/Stol: Translate 8 meters port.
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true) self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true)
end end
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
-- Stennis: translate 7 meters starboard wrt Final bearing. -- Stennis: translate 7 meters starboard wrt Final bearing.
self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( 7, FB + 90, true, true ) self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( 7, FB + 90, true, true )
@@ -11558,7 +11554,7 @@ function AIRBOSS:GetHeadingIntoWind_old( magnetic, coord )
local function adjustDegreesForWindSpeed(windSpeed) local function adjustDegreesForWindSpeed(windSpeed)
local degreesAdjustment = 0 local degreesAdjustment = 0
-- the windspeeds are in m/s -- the windspeeds are in m/s
-- +0 degrees at 15m/s = 37kts -- +0 degrees at 15m/s = 37kts
-- +0 degrees at 14m/s = 35kts -- +0 degrees at 14m/s = 35kts
-- +0 degrees at 13m/s = 33kts -- +0 degrees at 13m/s = 33kts
@@ -11573,7 +11569,7 @@ function AIRBOSS:GetHeadingIntoWind_old( magnetic, coord )
-- +20 degrees at 4m/s = 26kts -- +20 degrees at 4m/s = 26kts
-- +20 degrees at 3m/s = 26kts -- +20 degrees at 3m/s = 26kts
-- +30 degrees at 2m/s = 26kts 1s -- +30 degrees at 2m/s = 26kts 1s
if windSpeed > 0 and windSpeed < 3 then if windSpeed > 0 and windSpeed < 3 then
degreesAdjustment = 30 degreesAdjustment = 30
elseif windSpeed >= 3 and windSpeed < 5 then elseif windSpeed >= 3 and windSpeed < 5 then
@@ -11585,7 +11581,7 @@ function AIRBOSS:GetHeadingIntoWind_old( magnetic, coord )
elseif windSpeed >= 13 then elseif windSpeed >= 13 then
degreesAdjustment = 0 degreesAdjustment = 0
end end
return degreesAdjustment return degreesAdjustment
end end
@@ -14829,12 +14825,12 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
if radio == nil or call == nil then if radio == nil or call == nil then
return return
end end
if not self.SRS then if not self.SRS then
-- Create a new radio transmission item. -- Create a new radio transmission item.
local transmission = {} -- #AIRBOSS.Radioitem local transmission = {} -- #AIRBOSS.Radioitem
transmission.radio = radio transmission.radio = radio
transmission.call = call transmission.call = call
transmission.Tplay = timer.getAbsTime() + (delay or 0) transmission.Tplay = timer.getAbsTime() + (delay or 0)
@@ -14842,12 +14838,12 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
transmission.isplaying = false transmission.isplaying = false
transmission.Tstarted = nil transmission.Tstarted = nil
transmission.loud = loud and call.loud transmission.loud = loud and call.loud
-- Player onboard number if sender has one. -- Player onboard number if sender has one.
if self:_IsOnboard( call.modexsender ) then if self:_IsOnboard( call.modexsender ) then
self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall ) self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall )
end end
-- Play onboard number if receiver has one. -- Play onboard number if receiver has one.
if self:_IsOnboard( call.modexreceiver ) then if self:_IsOnboard( call.modexreceiver ) then
self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall ) self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall )
@@ -14890,16 +14886,12 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
-- SRS transmission -- SRS transmission
if call.subtitle ~= nil and string.len(call.subtitle) > 1 then if call.subtitle ~= nil and string.len(call.subtitle) > 1 then
else
-- SRS transmission
local frequency = self.MarshalRadio.frequency local frequency = self.MarshalRadio.frequency
local modulation = self.MarshalRadio.modulation local modulation = self.MarshalRadio.modulation
local voice = nil local voice = nil
local gender = nil local gender = nil
local culture = nil local culture = nil
if radio.alias == "AIRBOSS" then if radio.alias == "AIRBOSS" then
frequency = self.AirbossRadio.frequency frequency = self.AirbossRadio.frequency
modulation = self.AirbossRadio.modulation modulation = self.AirbossRadio.modulation
@@ -14907,13 +14899,13 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
gender = self.AirbossRadio.gender gender = self.AirbossRadio.gender
culture = self.AirbossRadio.culture culture = self.AirbossRadio.culture
end end
if radio.alias == "MARSHAL" then if radio.alias == "MARSHAL" then
voice = self.MarshalRadio.voice voice = self.MarshalRadio.voice
gender = self.MarshalRadio.gender gender = self.MarshalRadio.gender
culture = self.MarshalRadio.culture culture = self.MarshalRadio.culture
end end
if radio.alias == "LSO" then if radio.alias == "LSO" then
frequency = self.LSORadio.frequency frequency = self.LSORadio.frequency
modulation = self.LSORadio.modulation modulation = self.LSORadio.modulation
@@ -14921,7 +14913,7 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
gender = self.LSORadio.gender gender = self.LSORadio.gender
culture = self.LSORadio.culture culture = self.LSORadio.culture
end end
if pilotcall then if pilotcall then
voice = self.PilotRadio.voice voice = self.PilotRadio.voice
gender = self.PilotRadio.gender gender = self.PilotRadio.gender
@@ -14935,18 +14927,18 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
modulation = self.AirbossRadio.modulation modulation = self.AirbossRadio.modulation
radio.alias = "AIRBOSS" radio.alias = "AIRBOSS"
end end
local volume = nil local volume = nil
if loud then if loud then
volume = 1.0 volume = 1.0
end end
--local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle --local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle
local text = call.subtitle local text = call.subtitle
self:I(self.lid..text) self:T(self.lid..text)
local srstext = self:_GetNiceSRSText(text) local srstext = self:_GetNiceSRSText(text)
self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, tstart, 0.1, subgroups, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias) self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, nil, 0.1, nil, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias)
end end
end end
end end
@@ -15259,7 +15251,7 @@ end
-- @param #boolean clear If true, clear screen from previous messages. -- @param #boolean clear If true, clear screen from previous messages.
-- @param #number delay Delay in seconds, before the message is displayed. -- @param #number delay Delay in seconds, before the message is displayed.
function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duration, clear, delay ) function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duration, clear, delay )
self:I({sender,receiver,message}) self:T({sender,receiver,message})
if playerData and message and message ~= "" then if playerData and message and message ~= "" then
-- Default duration. -- Default duration.
@@ -15282,44 +15274,44 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
-- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay) -- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay)
self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear ) self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear )
else else
if not self.SRS then if not self.SRS then
-- Wait until previous sound finished. -- Wait until previous sound finished.
local wait = 0 local wait = 0
-- Onboard number to get the attention. -- Onboard number to get the attention.
if receiver == playerData.onboard then if receiver == playerData.onboard then
-- Which voice over number to use. -- Which voice over number to use.
if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then
-- User sound of board number. -- User sound of board number.
wait = wait + self:_Number2Sound( playerData, sender, receiver ) wait = wait + self:_Number2Sound( playerData, sender, receiver )
end end
end end
-- Negative. -- Negative.
if string.find( text:lower(), "negative" ) then if string.find( text:lower(), "negative" ) then
local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" ) local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait ) USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.NEGATIVE.duration wait = wait + self.MarshalCall.NEGATIVE.duration
end end
-- Affirm. -- Affirm.
if string.find( text:lower(), "affirm" ) then if string.find( text:lower(), "affirm" ) then
local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" ) local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait ) USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.AFFIRMATIVE.duration wait = wait + self.MarshalCall.AFFIRMATIVE.duration
end end
-- Roger. -- Roger.
if string.find( text:lower(), "roger" ) then if string.find( text:lower(), "roger" ) then
local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" ) local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" )
USERSOUND:New( filename ):ToGroup( playerData.group, wait ) USERSOUND:New( filename ):ToGroup( playerData.group, wait )
wait = wait + self.MarshalCall.ROGER.duration wait = wait + self.MarshalCall.ROGER.duration
end end
-- Play click sound to end message. -- Play click sound to end message.
if wait > 0 then if wait > 0 then
local filename = self:_RadioFilename( self.MarshalCall.CLICK ) local filename = self:_RadioFilename( self.MarshalCall.CLICK )
@@ -15332,7 +15324,7 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
local voice = self.MarshalRadio.voice local voice = self.MarshalRadio.voice
local gender = self.MarshalRadio.gender local gender = self.MarshalRadio.gender
local culture = self.MarshalRadio.culture local culture = self.MarshalRadio.culture
if not sender then sender = "AIRBOSS" end if not sender then sender = "AIRBOSS" end
if string.find(sender,"AIRBOSS" ) then if string.find(sender,"AIRBOSS" ) then
@@ -15362,10 +15354,10 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
--sender = "AIRBOSS" --sender = "AIRBOSS"
end end
self:I(self.lid..text) self:T(self.lid..text)
self:I({sender,frequency,modulation,voice}) self:T({sender,frequency,modulation,voice})
local srstext = self:_GetNiceSRSText(text) local srstext = self:_GetNiceSRSText(text)
self.SRSQ:NewTransmission(srstext,duration,self.SRS,tstart,0.1,subgroups,subtitle,subduration,frequency,modulation,gender,culture,voice,volume,sender) self.SRSQ:NewTransmission(srstext,duration,self.SRS,nil,0.1,nil,nil,nil,frequency,modulation,gender,culture,voice,nil,sender)
end end
-- Text message to player client. -- Text message to player client.
if playerData.client then if playerData.client then

View File

@@ -976,7 +976,8 @@ function ARMYGROUP:onafterSpawned(From, Event, To)
-- Update route. -- Update route.
if Nwp>1 and self.isMobile then if Nwp>1 and self.isMobile then
self:T(self.lid..string.format("Got %d waypoints on spawn ==> Cruise in -1.0 sec!", Nwp)) self:T(self.lid..string.format("Got %d waypoints on spawn ==> Cruise in -1.0 sec!", Nwp))
self:__Cruise(-1, nil, self.option.Formation) --self:__Cruise(-1, nil, self.option.Formation)
self:__Cruise(-1)
else else
self:T(self.lid.."No waypoints on spawn ==> Full Stop!") self:T(self.lid.."No waypoints on spawn ==> Full Stop!")
self:FullStop() self:FullStop()
@@ -1948,7 +1949,7 @@ function ARMYGROUP:onafterCruise(From, Event, To, Speed, Formation)
self.dTwait=nil self.dTwait=nil
-- Debug info. -- Debug info.
self:T(self.lid.."Cruise ==> Update route in 0.01 sec") self:T(self.lid..string.format("Cruise ==> Update route in 0.01 sec (speed=%s, formation=%s)", tostring(Speed), tostring(Formation)))
-- Update route. -- Update route.
self:__UpdateRoute(-0.01, nil, nil, Speed, Formation) self:__UpdateRoute(-0.01, nil, nil, Speed, Formation)
@@ -2003,7 +2004,7 @@ function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation
elseif self.optionDefault.Formation then elseif self.optionDefault.Formation then
Formation = self.optionDefault.Formation Formation = self.optionDefault.Formation
elseif self.option.Formation then elseif self.option.Formation then
Formation = self.option.Formation Formation = self.option.Formation
else else
-- Default formation is on road. -- Default formation is on road.
Formation = ENUMS.Formation.Vehicle.OnRoad Formation = ENUMS.Formation.Vehicle.OnRoad
@@ -2043,82 +2044,90 @@ end
-- @param #ARMYGROUP self -- @param #ARMYGROUP self
-- @param #table Template Template used to init the group. Default is `self.template`. -- @param #table Template Template used to init the group. Default is `self.template`.
-- @return #ARMYGROUP self -- @return #ARMYGROUP self
function ARMYGROUP:_InitGroup(Template) function ARMYGROUP:_InitGroup(Template, Delay)
-- First check if group was already initialized. if Delay and Delay>0 then
if self.groupinitialized then self:ScheduleOnce(Delay, ARMYGROUP._InitGroup, self, Template, 0)
self:T(self.lid.."WARNING: Group was already initialized! Will NOT do it again!")
return
end
-- Get template of group.
local template=Template or self:_GetTemplate()
-- Ground are always AI.
self.isAI=true
-- Is (template) group late activated.
self.isLateActivated=template.lateActivation
-- Ground groups cannot be uncontrolled.
self.isUncontrolled=false
-- Max speed in km/h.
self.speedMax=self.group:GetSpeedMax()
-- Is group mobile?
if self.speedMax>3.6 then
self.isMobile=true
else else
self.isMobile=false
end
-- Cruise speed in km/h
self.speedCruise=self.speedMax*0.7
-- Group ammo.
self.ammo=self:GetAmmoTot()
-- Radio parameters from template.
self.radio.On=false -- Radio is always OFF for ground.
self.radio.Freq=133
self.radio.Modu=radio.modulation.AM
-- Set default radio.
self:SetDefaultRadio(self.radio.Freq, self.radio.Modu, self.radio.On)
-- Get current formation from first waypoint.
self.option.Formation=template.route.points[1].action
-- Set default formation to "on road".
self.optionDefault.Formation=ENUMS.Formation.Vehicle.OnRoad
-- Default TACAN off. -- First check if group was already initialized.
self:SetDefaultTACAN(nil, nil, nil, nil, true) if self.groupinitialized then
self.tacan=UTILS.DeepCopy(self.tacanDefault) self:T(self.lid.."WARNING: Group was already initialized! Will NOT do it again!")
return
end
self:I(self.lid.."FF Initializing Group")
-- Units of the group. -- Get template of group.
local units=self.group:GetUnits() local template=Template or self:_GetTemplate()
-- Ground are always AI.
self.isAI=true
-- Is (template) group late activated.
self.isLateActivated=template.lateActivation
-- Ground groups cannot be uncontrolled.
self.isUncontrolled=false
-- Max speed in km/h.
self.speedMax=self.group:GetSpeedMax()
-- Is group mobile?
if self.speedMax>3.6 then
self.isMobile=true
else
self.isMobile=false
end
-- Cruise speed in km/h
self.speedCruise=self.speedMax*0.7
-- Group ammo.
self.ammo=self:GetAmmoTot()
-- Radio parameters from template.
self.radio.On=false -- Radio is always OFF for ground.
self.radio.Freq=133
self.radio.Modu=radio.modulation.AM
-- Set default radio.
self:SetDefaultRadio(self.radio.Freq, self.radio.Modu, self.radio.On)
-- Get current formation from first waypoint.
self.option.Formation=template.route.points[1].action
-- Set default formation to "on road".
self.optionDefault.Formation=ENUMS.Formation.Vehicle.OnRoad
-- DCS group. -- Default TACAN off.
local dcsgroup=Group.getByName(self.groupname) self:SetDefaultTACAN(nil, nil, nil, nil, true)
local size0=dcsgroup:getInitialSize() self.tacan=UTILS.DeepCopy(self.tacanDefault)
-- Units of the group.
local units=self.group:GetUnits()
-- DCS group.
local dcsgroup=Group.getByName(self.groupname)
local size0=dcsgroup:getInitialSize()
local u=dcsgroup:getUnits()
-- Quick check.
if #units~=size0 then
self:T(self.lid..string.format("ERROR: Got #units=%d but group consists of %d units! u=%d", #units, size0, #u))
end
-- Add elemets.
for _,unit in pairs(units) do
local unitname=unit:GetName()
self:_AddElementByName(unitname)
end
-- Quick check. -- Init done.
if #units~=size0 then self.groupinitialized=true
self:T(self.lid..string.format("ERROR: Got #units=%d but group consists of %d units!", #units, size0))
end end
-- Add elemets.
for _,unit in pairs(units) do
local unitname=unit:GetName()
self:_AddElementByName(unitname)
end
-- Init done.
self.groupinitialized=true
return self return self
end end

View File

@@ -17,7 +17,7 @@
-- === -- ===
-- --
-- ### Author: **applevangelist** -- ### Author: **applevangelist**
-- @date Last Update July 2023 -- @date Last Update Nov 2023
-- @module Ops.AWACS -- @module Ops.AWACS
-- @image OPS_AWACS.jpg -- @image OPS_AWACS.jpg
@@ -507,7 +507,7 @@ do
-- @field #AWACS -- @field #AWACS
AWACS = { AWACS = {
ClassName = "AWACS", -- #string ClassName = "AWACS", -- #string
version = "0.2.57", -- #string version = "0.2.59", -- #string
lid = "", -- #string lid = "", -- #string
coalition = coalition.side.BLUE, -- #number coalition = coalition.side.BLUE, -- #number
coalitiontxt = "blue", -- #string coalitiontxt = "blue", -- #string
@@ -971,6 +971,7 @@ AWACS.TaskStatus = {
-- DONE - (WIP) Reporting -- DONE - (WIP) Reporting
-- DONE - Do not report non-airborne groups -- DONE - Do not report non-airborne groups
-- DONE - Added option for helos -- DONE - Added option for helos
-- DONE - Added setting a coordinate for SRS
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor -- Constructor
@@ -2987,7 +2988,7 @@ function AWACS:_Picture(Group,IsGeneral)
if clustersAO == 0 and clustersEWR == 0 then if clustersAO == 0 and clustersEWR == 0 then
-- clean -- clean
self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false) self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
else else
if clustersAO > 0 then if clustersAO > 0 then
@@ -6191,6 +6192,16 @@ function AWACS:onafterStatus(From, Event, To)
-- Check on AUFTRAG status for CAP AI -- Check on AUFTRAG status for CAP AI
if self:Is("Running") and (awacsalive or self.AwacsInZone) then if self:Is("Running") and (awacsalive or self.AwacsInZone) then
-- update coord for SRS
if self.AwacsSRS then
self.AwacsSRS:SetCoordinate(self.AwacsFG:GetCoordinate())
if self.TacticalSRS then
self.TacticalSRS:SetCoordinate(self.AwacsFG:GetCoordinate())
end
end
self:_CheckAICAPOnStation() self:_CheckAICAPOnStation()
self:_CleanUpContacts() self:_CleanUpContacts()

View File

@@ -31,6 +31,7 @@
-- @image OPS_CSAR.jpg -- @image OPS_CSAR.jpg
-- Date: May 2023 -- Date: May 2023
-- Last: Update Oct 2024
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
@@ -46,8 +47,6 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](OPS_CSAR.jpg)
--
-- # CSAR Concept -- # CSAR Concept
-- --
-- * MOOSE-based Helicopter CSAR Operations for Players. -- * MOOSE-based Helicopter CSAR Operations for Players.
@@ -118,21 +117,21 @@
-- mycsar.ADFRadioPwr = 1000 -- ADF Beacons sending with 1KW as default -- mycsar.ADFRadioPwr = 1000 -- ADF Beacons sending with 1KW as default
-- mycsar.PilotWeight = 80 -- Loaded pilots weigh 80kgs each -- mycsar.PilotWeight = 80 -- Loaded pilots weigh 80kgs each
-- --
-- ## 2.1 Experimental Features -- ## 2.1 SRS Features and Other Features
-- --
-- WARNING - Here\'ll be dragons!
-- DANGER - For this to work you need to de-sanitize your mission environment (all three entries) in <DCS root>\Scripts\MissionScripting.lua
-- Needs SRS => 1.9.6 to work (works on the **server** side of SRS)
-- 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\\" -- 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
-- mycsar.SRSCulture = "en-GB" -- SRS voice culture -- mycsar.SRSCulture = "en-GB" -- SRS voice culture
-- mycsar.SRSVoice = nil -- SRS voice, relevant for Google TTS -- mycsar.SRSVoice = nil -- SRS voice for downed pilot, relevant for Google TTS
-- mycsar.SRSGPathToCredentials = nil -- Path to your Google credentials json file, set this if you want to use Google TTS -- mycsar.SRSGPathToCredentials = nil -- Path to your Google credentials json file, set this if you want to use Google TTS
-- mycsar.SRSVolume = 1 -- Volume, between 0 and 1 -- mycsar.SRSVolume = 1 -- Volume, between 0 and 1
-- mycsar.SRSGender = "male" -- male or female voice -- mycsar.SRSGender = "male" -- male or female voice
-- mycsar.CSARVoice = MSRS.Voices.Google.Standard.en_US_Standard_A -- SRS voice for CSAR Controller, relevant for Google TTS
-- mycsar.CSARVoiceMS = MSRS.Voices.Microsoft.Hedda -- SRS voice for CSAR Controller, relevant for MS Desktop TTS
-- mycsar.coordinate -- Coordinate from which CSAR TTS is sending. Defaults to a random MASH object position
-- -- -- --
-- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection. Requires mycsar.enableForAI to be set to true. --shagrat -- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection. Requires mycsar.enableForAI to be set to true. --shagrat
-- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases. -- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases.
@@ -232,7 +231,7 @@ CSAR = {
takenOff = {}, takenOff = {},
csarUnits = {}, -- table of unit names csarUnits = {}, -- table of unit names
downedPilots = {}, downedPilots = {},
woundedGroups = {}, -- = {},
landedStatus = {}, landedStatus = {},
addedTo = {}, addedTo = {},
woundedGroups = {}, -- contains the new group of units woundedGroups = {}, -- contains the new group of units
@@ -467,7 +466,10 @@ function CSAR:New(Coalition, Template, Alias)
self.SRSGPathToCredentials = nil self.SRSGPathToCredentials = nil
self.SRSVolume = 1.0 -- volume 0.0 to 1.0 self.SRSVolume = 1.0 -- volume 0.0 to 1.0
self.SRSGender = "male" -- male or female self.SRSGender = "male" -- male or female
self.CSARVoice = MSRS.Voices.Google.Standard.en_US_Standard_A
self.CSARVoiceMS = MSRS.Voices.Microsoft.Hedda
self.coordinate = nil -- Core.Point#COORDINATE
local AliaS = string.gsub(self.alias," ","_") local AliaS = string.gsub(self.alias," ","_")
self.filename = string.format("CSAR_%s_Persist.csv",AliaS) self.filename = string.format("CSAR_%s_Persist.csv",AliaS)
@@ -1308,7 +1310,7 @@ end
-- @param #string UnitName -- @param #string UnitName
-- @return #string CallSign -- @return #string CallSign
function CSAR:_GetCustomCallSign(UnitName) function CSAR:_GetCustomCallSign(UnitName)
local callsign = Unitname local callsign = UnitName
local unit = UNIT:FindByName(UnitName) local unit = UNIT:FindByName(UnitName)
if unit and unit:IsAlive() then if unit and unit:IsAlive() then
local group = unit:GetGroup() local group = unit:GetGroup()
@@ -1739,7 +1741,16 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _overrid
end end
-- integrate SRS -- integrate SRS
if _speak and self.useSRS then if _speak and self.useSRS then
self.SRSQueue:NewTransmission(_text,nil,self.msrs,nil,2) local coord = _unit:GetCoordinate()
if coord then
self.msrs:SetCoordinate(coord)
end
_text = string.gsub(_text,"km"," kilometer")
_text = string.gsub(_text,"nm"," nautical miles")
--self.msrs:SetVoice(self.SRSVoice)
--self.SRSQueue:NewTransmission(_text,nil,self.msrs,nil,1)
self:I("Voice = "..self.SRSVoice)
self.SRSQueue:NewTransmission(_text,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,self.SRSVoice,volume,label,coord)
end end
return self return self
end end
@@ -1878,7 +1889,7 @@ function CSAR:_SignalFlare(_unitName)
if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then
local _clockDir = self:_GetClockDirection(_heli, _closest.pilot) local _clockDir = self:_GetClockDirection(_heli, _closest.pilot)
local _distance = 0 local _distance = ""
if _SETTINGS:IsImperial() then if _SETTINGS:IsImperial() then
_distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance)) _distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance))
else else
@@ -1891,12 +1902,13 @@ function CSAR:_SignalFlare(_unitName)
_coord:FlareRed(_clockDir) _coord:FlareRed(_clockDir)
else else
local _distance = smokedist local _distance = smokedist
local dtext = ""
if _SETTINGS:IsImperial() then if _SETTINGS:IsImperial() then
_distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist)) dtext = string.format("%.1fnm",UTILS.MetersToNM(smokedist))
else else
_distance = string.format("%.1fkm",smokedist/1000) dtext = string.format("%.1fkm",smokedist/1000)
end end
self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime, false, false, true) self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",dtext), self.messageTime, false, false, true)
end end
return self return self
end end
@@ -1909,6 +1921,14 @@ end
function CSAR:_DisplayToAllSAR(_message, _side, _messagetime) function CSAR:_DisplayToAllSAR(_message, _side, _messagetime)
self:T(self.lid .. " _DisplayToAllSAR") self:T(self.lid .. " _DisplayToAllSAR")
local messagetime = _messagetime or self.messageTime local messagetime = _messagetime or self.messageTime
if self.msrs then
local voice = self.CSARVoice or MSRS.Voices.Google.Standard.en_GB_Standard_F
if self.msrs.google == nil then
voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda
end
self:I("Voice = "..voice)
self.SRSQueue:NewTransmission(_message,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,voice,volume,label,self.coordinate)
end
for _, _unitName in pairs(self.csarUnits) do for _, _unitName in pairs(self.csarUnits) do
local _unit = self:_GetSARHeli(_unitName) local _unit = self:_GetSARHeli(_unitName)
if _unit and not self.suppressmessages then if _unit and not self.suppressmessages then
@@ -1932,7 +1952,7 @@ function CSAR:_Reqsmoke( _unitName )
local _closest = self:_GetClosestDownedPilot(_heli) local _closest = self:_GetClosestDownedPilot(_heli)
if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then
local _clockDir = self:_GetClockDirection(_heli, _closest.pilot) local _clockDir = self:_GetClockDirection(_heli, _closest.pilot)
local _distance = 0 local _distance = string.format("%.1fkm",_closest.distance/1000)
if _SETTINGS:IsImperial() then if _SETTINGS:IsImperial() then
_distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance)) _distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance))
else else
@@ -1944,7 +1964,7 @@ function CSAR:_Reqsmoke( _unitName )
local color = self.smokecolor local color = self.smokecolor
_coord:Smoke(color) _coord:Smoke(color)
else else
local _distance = 0 local _distance = string.format("%.1fkm",smokedist/1000)
if _SETTINGS:IsImperial() then if _SETTINGS:IsImperial() then
_distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist)) _distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist))
else else
@@ -2269,6 +2289,12 @@ function CSAR:onafterStart(From, Event, To)
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart() self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
end end
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also? self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
if not self.coordinate then
local csarhq = self.mash:GetRandom()
if csarhq then
self.coordinate = csarhq:GetCoordinate()
end
end
if self.wetfeettemplate then if self.wetfeettemplate then
self.usewetfeet = true self.usewetfeet = true
end end
@@ -2276,7 +2302,7 @@ function CSAR:onafterStart(From, Event, To)
local path = self.SRSPath local path = self.SRSPath
local modulation = self.SRSModulation local modulation = self.SRSModulation
local channel = self.SRSchannel local channel = self.SRSchannel
self.msrs = MSRS:New(path,channel,modulation) self.msrs = MSRS:New(path,channel,modulation) -- Sound.SRS#MSRS
self.msrs:SetPort(self.SRSport) self.msrs:SetPort(self.SRSport)
self.msrs:SetLabel("CSAR") self.msrs:SetLabel("CSAR")
self.msrs:SetCulture(self.SRSCulture) self.msrs:SetCulture(self.SRSCulture)
@@ -2288,7 +2314,7 @@ function CSAR:onafterStart(From, Event, To)
end end
self.msrs:SetVolume(self.SRSVolume) self.msrs:SetVolume(self.SRSVolume)
self.msrs:SetLabel("CSAR") self.msrs:SetLabel("CSAR")
self.SRSQueue = MSRSQUEUE:New("CSAR") self.SRSQueue = MSRSQUEUE:New("CSAR") -- Sound.SRS#MSRSQUEUE
end end
self:__Status(-10) self:__Status(-10)

View File

@@ -19,10 +19,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**
--
-- @module Ops.CTLD -- @module Ops.CTLD
-- @image OPS_CTLD.jpg -- @image OPS_CTLD.jpg
-- Last Update June 2023 -- Last Update November 2023
do do
@@ -599,7 +601,7 @@ do
-- --
-- === -- ===
-- --
-- ![Banner Image](OPS_CTLD.jpg) -- ![Banner Image](../Images/OPS_CTLD.jpg)
-- --
-- # CTLD Concept -- # CTLD Concept
-- --
@@ -700,6 +702,7 @@ do
-- --
-- my_ctld.useprefix = true -- (DO NOT SWITCH THIS OFF UNLESS YOU KNOW WHAT YOU ARE DOING!) Adjust **before** starting CTLD. If set to false, *all* choppers of the coalition side will be enabled for CTLD. -- my_ctld.useprefix = true -- (DO NOT SWITCH THIS OFF UNLESS YOU KNOW WHAT YOU ARE DOING!) Adjust **before** starting CTLD. If set to false, *all* choppers of the coalition side will be enabled for CTLD.
-- my_ctld.CrateDistance = 35 -- List and Load crates in this radius only. -- my_ctld.CrateDistance = 35 -- List and Load crates in this radius only.
-- my_ctld.PackDistance = 35 -- Pack crates in this radius only
-- my_ctld.dropcratesanywhere = false -- Option to allow crates to be dropped anywhere. -- my_ctld.dropcratesanywhere = false -- Option to allow crates to be dropped anywhere.
-- my_ctld.dropAsCargoCrate = false -- Parachuted herc cargo is not unpacked automatically but placed as crate to be unpacked. Needs a cargo with the same name defined like the cargo that was dropped. -- my_ctld.dropAsCargoCrate = false -- Parachuted herc cargo is not unpacked automatically but placed as crate to be unpacked. Needs a cargo with the same name defined like the cargo that was dropped.
-- my_ctld.maximumHoverHeight = 15 -- Hover max this high to load. -- my_ctld.maximumHoverHeight = 15 -- Hover max this high to load.
@@ -738,7 +741,7 @@ do
-- --
-- -- E.g. update unit capabilities for testing. Please stay realistic in your mission design. -- -- E.g. update unit capabilities for testing. Please stay realistic in your mission design.
-- -- Make a Gazelle into a heavy truck, this type can load both crates and troops and eight of each type, up to 4000 kgs: -- -- Make a Gazelle into a heavy truck, this type can load both crates and troops and eight of each type, up to 4000 kgs:
-- my_ctld:UnitCapabilities("SA342L", true, true, 8, 8, 12, 4000) -- my_ctld:SetUnitCapabilities("SA342L", true, true, 8, 8, 12, 4000)
-- --
-- -- Default unit type capabilities are: -- -- Default unit type capabilities are:
-- ["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400}, -- ["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
@@ -1121,6 +1124,7 @@ CTLD = {
Spawned_Crates = {}, -- Holds objects for crates spawned generally Spawned_Crates = {}, -- Holds objects for crates spawned generally
Spawned_Cargo = {}, -- Binds together spawned_crates and their CTLD_CARGO objects Spawned_Cargo = {}, -- Binds together spawned_crates and their CTLD_CARGO objects
CrateDistance = 35, -- list crates in this radius CrateDistance = 35, -- list crates in this radius
PackDistance = 35, -- pack crates in this radius
debug = false, debug = false,
wpZones = {}, wpZones = {},
dropOffZones = {}, dropOffZones = {},
@@ -1144,6 +1148,7 @@ CTLD = {
-- DONE: List cargo in stock -- DONE: List cargo in stock
-- DONE: Limit of troops, crates buildable? -- DONE: Limit of troops, crates buildable?
-- DONE: Allow saving of Troops & Vehicles -- DONE: Allow saving of Troops & Vehicles
-- DONE: Adding re-packing dropped units
------------------------------ ------------------------------
--- Radio Beacons --- Radio Beacons
@@ -1195,14 +1200,14 @@ CTLD.CargoZoneType = {
-- @field #CTLD_CARGO.Enum Type Type enumerator (for moves). -- @field #CTLD_CARGO.Enum Type Type enumerator (for moves).
--- Unit capabilities. --- Unit capabilities.
-- @type CTLD.UnitCapabilities -- @type CTLD.UnitTypeCapabilities
-- @field #string type Unit type. -- @field #string type Unit type.
-- @field #boolean crates Can transport crate. -- @field #boolean crates Can transport crate.
-- @field #boolean troops Can transport troops. -- @field #boolean troops Can transport troops.
-- @field #number cratelimit Number of crates transportable. -- @field #number cratelimit Number of crates transportable.
-- @field #number trooplimit Number of troop units transportable. -- @field #number trooplimit Number of troop units transportable.
-- @field #number cargoweightlimit Max loadable kgs of cargo. -- @field #number cargoweightlimit Max loadable kgs of cargo.
CTLD.UnitTypes = { CTLD.UnitTypeCapabilities = {
["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400}, ["SA342Mistral"] = {type="SA342Mistral", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
["SA342L"] = {type="SA342L", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 12, cargoweightlimit = 400}, ["SA342L"] = {type="SA342L", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 12, cargoweightlimit = 400},
["SA342M"] = {type="SA342M", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400}, ["SA342M"] = {type="SA342M", crates=false, troops=true, cratelimit = 0, trooplimit = 4, length = 12, cargoweightlimit = 400},
@@ -1223,7 +1228,7 @@ CTLD.UnitTypes = {
--- CTLD class version. --- CTLD class version.
-- @field #string version -- @field #string version
CTLD.version="1.0.40" CTLD.version="1.0.43"
--- Instantiate a new CTLD. --- Instantiate a new CTLD.
-- @param #CTLD self -- @param #CTLD self
@@ -1288,6 +1293,8 @@ function CTLD:New(Coalition, Prefixes, Alias)
self:AddTransition("*", "CratesDropped", "*") -- CTLD deploy event. self:AddTransition("*", "CratesDropped", "*") -- CTLD deploy event.
self:AddTransition("*", "CratesBuild", "*") -- CTLD build event. self:AddTransition("*", "CratesBuild", "*") -- CTLD build event.
self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event. self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event.
self:AddTransition("*", "CratesBuildStarted", "*") -- CTLD build event.
self:AddTransition("*", "CratesRepairStarted", "*") -- CTLD repair event.
self:AddTransition("*", "Load", "*") -- CTLD load event. self:AddTransition("*", "Load", "*") -- CTLD load event.
self:AddTransition("*", "Save", "*") -- CTLD save event. self:AddTransition("*", "Save", "*") -- CTLD save event.
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
@@ -1341,6 +1348,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- setup -- setup
self.CrateDistance = 35 -- list/load crates in this radius self.CrateDistance = 35 -- list/load crates in this radius
self.PackDistance = 35 -- pack objects in this radius
self.ExtractFactor = 3.33 -- factor for troops extraction, i.e. CrateDistance * Extractfactor self.ExtractFactor = 3.33 -- factor for troops extraction, i.e. CrateDistance * Extractfactor
self.prefixes = Prefixes or {"Cargoheli"} self.prefixes = Prefixes or {"Cargoheli"}
self.useprefix = true self.useprefix = true
@@ -1469,7 +1477,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- @param #CTLD self -- @param #CTLD self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--- FSM Function OnBeforeTroopsPickedUp. --- FSM Function OnBeforeTroopsPickedUp.
-- @function [parent=#CTLD] OnBeforeTroopsPickedUp -- @function [parent=#CTLD] OnBeforeTroopsPickedUp
-- @param #CTLD self -- @param #CTLD self
-- @param #string From State. -- @param #string From State.
@@ -1621,6 +1629,46 @@ function CTLD:New(Coalition, Prefixes, Alias)
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB build. -- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB build.
-- @return #CTLD self -- @return #CTLD self
--- FSM Function OnAfterCratesBuildStarted. Info event that a build has been started.
-- @function [parent=#CTLD] OnAfterCratesBuildStarted
-- @param #CTLD self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @return #CTLD self
--- FSM Function OnAfterCratesRepairStarted. Info event that a repair has been started.
-- @function [parent=#CTLD] OnAfterCratesRepairStarted
-- @param #CTLD self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @return #CTLD self
--- FSM Function OnBeforeCratesBuildStarted. Info event that a build has been started.
-- @function [parent=#CTLD] OnBeforeCratesBuildStarted
-- @param #CTLD self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @return #CTLD self
--- FSM Function OnBeforeCratesRepairStarted. Info event that a repair has been started.
-- @function [parent=#CTLD] OnBeforeCratesRepairStarted
-- @param #CTLD self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Group#GROUP Group Group Object.
-- @param Wrapper.Unit#UNIT Unit Unit Object.
-- @return #CTLD self
--- FSM Function OnAfterCratesRepaired. --- FSM Function OnAfterCratesRepaired.
-- @function [parent=#CTLD] OnAfterCratesRepaired -- @function [parent=#CTLD] OnAfterCratesRepaired
-- @param #CTLD self -- @param #CTLD self
@@ -1674,7 +1722,7 @@ function CTLD:_GetUnitCapabilities(Unit)
self:T(self.lid .. " _GetUnitCapabilities") self:T(self.lid .. " _GetUnitCapabilities")
local _unit = Unit -- Wrapper.Unit#UNIT local _unit = Unit -- Wrapper.Unit#UNIT
local unittype = _unit:GetTypeName() local unittype = _unit:GetTypeName()
local capabilities = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities local capabilities = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
if not capabilities or capabilities == {} then if not capabilities or capabilities == {} then
-- e.g. ["Ka-50"] = {type="Ka-50", crates=false, troops=false, cratelimit = 0, trooplimit = 0}, -- e.g. ["Ka-50"] = {type="Ka-50", crates=false, troops=false, cratelimit = 0, trooplimit = 0},
capabilities = {} capabilities = {}
@@ -1865,7 +1913,7 @@ function CTLD:_PreloadCrates(Group, Unit, Cargo, NumberOfCrates)
local unitname = unit:GetName() local unitname = unit:GetName()
-- see if this heli can load crates -- see if this heli can load crates
local unittype = unit:GetTypeName() local unittype = unit:GetTypeName()
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
local cancrates = capabilities.crates -- #boolean local cancrates = capabilities.crates -- #boolean
local cratelimit = capabilities.cratelimit -- #number local cratelimit = capabilities.cratelimit -- #number
if not cancrates then if not cancrates then
@@ -2118,6 +2166,7 @@ function CTLD:_RepairObjectFromCrates(Group,Unit,Crates,Build,Number,Engineering
desttimer:Start(self.repairtime - 1) desttimer:Start(self.repairtime - 1)
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,object,true,NearestGroup:GetCoordinate()) local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,object,true,NearestGroup:GetCoordinate())
buildtimer:Start(self.repairtime) buildtimer:Start(self.repairtime)
self:__CratesRepairStarted(1,Group,Unit)
else else
if not Engineering then if not Engineering then
self:_SendMessage("Can't repair this unit with " .. build.Name, 10, false, Group) self:_SendMessage("Can't repair this unit with " .. build.Name, 10, false, Group)
@@ -2260,9 +2309,10 @@ end
-- @param #CTLD_CARGO Cargo -- @param #CTLD_CARGO Cargo
-- @param #number number Number of crates to generate (for dropping) -- @param #number number Number of crates to generate (for dropping)
-- @param #boolean drop If true we\'re dropping from heli rather than loading. -- @param #boolean drop If true we\'re dropping from heli rather than loading.
function CTLD:_GetCrates(Group, Unit, Cargo, number, drop) -- @param #boolean pack If true we\'re packing crates from a template rather than loading or dropping
function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
self:T(self.lid .. " _GetCrates") self:T(self.lid .. " _GetCrates")
if not drop then if not drop and not pack then
local cgoname = Cargo:GetName() local cgoname = Cargo:GetName()
-- check if we have stock -- check if we have stock
local instock = Cargo:GetStock() local instock = Cargo:GetStock()
@@ -2279,18 +2329,20 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
local width = 20 local width = 20
local distance = nil local distance = nil
local zone = nil local zone = nil
if not drop then if not drop and not pack then
inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD) inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
if not inzone then if not inzone then
---@diagnostic disable-next-line: cast-local-type ---@diagnostic disable-next-line: cast-local-type
inzone, ship, zone, distance, width = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP) inzone, ship, zone, distance, width = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
end end
else elseif drop and not pack then
if self.dropcratesanywhere then -- #1570 if self.dropcratesanywhere then -- #1570
inzone = true inzone = true
else else
inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.DROP) inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.DROP)
end end
elseif pack and not drop then
inzone = true
end end
if not inzone then if not inzone then
@@ -2299,7 +2351,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
end end
-- avoid crate spam -- avoid crate spam
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
local canloadcratesno = capabilities.cratelimit local canloadcratesno = capabilities.cratelimit
local loaddist = self.CrateDistance or 35 local loaddist = self.CrateDistance or 35
local nearcrates, numbernearby = self:_FindCratesNearby(Group,Unit,loaddist,true) local nearcrates, numbernearby = self:_FindCratesNearby(Group,Unit,loaddist,true)
@@ -2509,6 +2561,40 @@ function CTLD:_ListCratesNearby( _group, _unit)
return self return self
end end
-- (Internal) Function to find and Remove nearby crates.
-- @param #CTLD self
-- @param Wrapper.Group#GROUP Group
-- @param Wrapper.Unit#UNIT Unit
-- @return #CTLD self
function CTLD:_RemoveCratesNearby( _group, _unit)
self:T(self.lid .. " _RemoveCratesNearby")
local finddist = self.CrateDistance or 35
local crates,number = self:_FindCratesNearby(_group,_unit, finddist,true) -- #table
if number > 0 then
local text = REPORT:New("Removing Crates Found Nearby:")
text:Add("------------------------------------------------------------")
for _,_entry in pairs (crates) do
local entry = _entry -- #CTLD_CARGO
local name = entry:GetName() --#string
local dropped = entry:WasDropped()
if dropped then
text:Add(string.format("Crate for %s, %dkg removed",name, entry.PerCrateMass))
else
text:Add(string.format("Crate for %s, %dkg removed",name, entry.PerCrateMass))
end
entry:GetPositionable():Destroy(false)
end
if text:GetCount() == 1 then
text:Add(" N O N E")
end
text:Add("------------------------------------------------------------")
self:_SendMessage(text:Text(), 30, true, _group)
else
self:_SendMessage(string.format("No (loadable) crates within %d meters!",finddist), 10, false, _group)
end
return self
end
--- (Internal) Return distance in meters between two coordinates. --- (Internal) Return distance in meters between two coordinates.
-- @param #CTLD self -- @param #CTLD self
-- @param Core.Point#COORDINATE _point1 Coordinate one -- @param Core.Point#COORDINATE _point1 Coordinate one
@@ -2592,8 +2678,8 @@ function CTLD:_LoadCratesNearby(Group, Unit)
local unitname = unit:GetName() local unitname = unit:GetName()
-- see if this heli can load crates -- see if this heli can load crates
local unittype = unit:GetTypeName() local unittype = unit:GetTypeName()
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
--local capabilities = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities --local capabilities = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
local cancrates = capabilities.crates -- #boolean local cancrates = capabilities.crates -- #boolean
local cratelimit = capabilities.cratelimit -- #number local cratelimit = capabilities.cratelimit -- #number
local grounded = not self:IsUnitInAir(Unit) local grounded = not self:IsUnitInAir(Unit)
@@ -2744,7 +2830,7 @@ function CTLD:_GetMaxLoadableMass(Unit)
if not Unit then return 0 end if not Unit then return 0 end
local loadable = 0 local loadable = 0
local loadedmass = self:_GetUnitCargoMass(Unit) local loadedmass = self:_GetUnitCargoMass(Unit)
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
local maxmass = capabilities.cargoweightlimit or 2000 -- max 2 tons local maxmass = capabilities.cargoweightlimit or 2000 -- max 2 tons
loadable = maxmass - loadedmass loadable = maxmass - loadedmass
return loadable return loadable
@@ -2769,7 +2855,7 @@ function CTLD:_ListCargo(Group, Unit)
self:T(self.lid .. " _ListCargo") self:T(self.lid .. " _ListCargo")
local unitname = Unit:GetName() local unitname = Unit:GetName()
local unittype = Unit:GetTypeName() local unittype = Unit:GetTypeName()
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
local trooplimit = capabilities.trooplimit -- #boolean local trooplimit = capabilities.trooplimit -- #boolean
local cratelimit = capabilities.cratelimit -- #number local cratelimit = capabilities.cratelimit -- #number
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
@@ -3217,6 +3303,7 @@ function CTLD:_BuildCrates(Group, Unit,Engineering)
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate()) local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate())
buildtimer:Start(self.buildtime) buildtimer:Start(self.buildtime)
self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group) self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group)
self:__CratesBuildStarted(1,Group,Unit)
else else
self:_BuildObjectFromCrates(Group,Unit,build) self:_BuildObjectFromCrates(Group,Unit,build)
end end
@@ -3229,6 +3316,42 @@ function CTLD:_BuildCrates(Group, Unit,Engineering)
return self return self
end end
--- (Internal) Function to repair nearby vehicles / FOBs
-- @param #CTLD self
-- @param Wrapper.Group#GROUP Group
-- @param Wrapper.Unit#UNIT Unit
function CTLD:_PackCratesNearby(Group, Unit)
self:T(self.lid .. " _PackCratesNearby")
-----------------------------------------
-- search for nearest group to player
-- determine if group is packable
-- generate crates and destroy group
-----------------------------------------
-- get nearby vehicles
local location = Group:GetCoordinate() -- get coordinate of group using function
local nearestGroups = SET_GROUP:New():FilterCoalitions("blue"):FilterZones({ZONE_RADIUS:New("TempZone", location:GetVec2(), self.PackDistance, false)}):FilterOnce() -- get all groups withing PackDistance from group using function
-- get template name of all vehicles in zone
-- determine if group is packable
for _, _Group in pairs(nearestGroups.Set) do -- convert #SET_GROUP to a list of Wrapper.Group#GROUP
for _, _Template in pairs(_DATABASE.Templates.Groups) do -- iterate through the database of templates
if (string.match(_Group:GetName(), _Template.GroupName)) then -- check if the Wrapper.Group#GROUP near the player is in the list of templates by name
-- generate crates and destroy group
for _, _entry in pairs(self.Cargo_Crates) do -- iterate through #CTLD_CARGO
if (_entry.Templates[1] == _Template.GroupName) then -- check if the #CTLD_CARGO matches the template name
_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
return self
end
end
end
end
end
return self
end
--- (Internal) Function to repair nearby vehicles / FOBs --- (Internal) Function to repair nearby vehicles / FOBs
-- @param #CTLD self -- @param #CTLD self
-- @param Wrapper.Group#GROUP Group -- @param Wrapper.Group#GROUP Group
@@ -3491,13 +3614,19 @@ function CTLD:_RefreshF10Menus()
if _group then if _group then
-- get chopper capabilities -- get chopper capabilities
local unittype = _unit:GetTypeName() local unittype = _unit:GetTypeName()
local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitCapabilities local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitTypeCapabilities
local cantroops = capabilities.troops local cantroops = capabilities.troops
local cancrates = capabilities.crates local cancrates = capabilities.crates
-- top menu -- top menu
local topmenu = MENU_GROUP:New(_group,"CTLD",nil) local topmenu = MENU_GROUP:New(_group,"CTLD",nil)
local toptroops = MENU_GROUP:New(_group,"Manage Troops",topmenu) local toptroops = nil
local topcrates = MENU_GROUP:New(_group,"Manage Crates",topmenu) local topcrates = nil
if cantroops then
toptroops = MENU_GROUP:New(_group,"Manage Troops",topmenu)
end
if cancrates then
topcrates = MENU_GROUP:New(_group,"Manage Crates",topmenu)
end
local listmenu = MENU_GROUP_COMMAND:New(_group,"List boarded cargo",topmenu, self._ListCargo, self, _group, _unit) local listmenu = MENU_GROUP_COMMAND:New(_group,"List boarded cargo",topmenu, self._ListCargo, self, _group, _unit)
local invtry = MENU_GROUP_COMMAND:New(_group,"Inventory",topmenu, self._ListInventory, self, _group, _unit) local invtry = MENU_GROUP_COMMAND:New(_group,"Inventory",topmenu, self._ListInventory, self, _group, _unit)
local rbcns = MENU_GROUP_COMMAND:New(_group,"List active zone beacons",topmenu, self._ListRadioBeacons, self, _group, _unit) local rbcns = MENU_GROUP_COMMAND:New(_group,"List active zone beacons",topmenu, self._ListRadioBeacons, self, _group, _unit)
@@ -3541,6 +3670,7 @@ function CTLD:_RefreshF10Menus()
if cancrates then if cancrates then
local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit) local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit)
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates) local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
local packmenu = MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
if self.usesubcats then if self.usesubcats then
local subcatmenus = {} local subcatmenus = {}
@@ -3576,6 +3706,7 @@ function CTLD:_RefreshF10Menus()
end end
end end
listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit) listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit)
listmenu = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",topcrates, self._RemoveCratesNearby, self, _group, _unit)
local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit) local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit)
if not self.nobuildmenu then if not self.nobuildmenu then
local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit) local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit)
@@ -4293,7 +4424,7 @@ end
-- @param #number Trooplimit Unit can carry number of troops. Default 0. -- @param #number Trooplimit Unit can carry number of troops. Default 0.
-- @param #number Length Unit lenght (in metres) for the load radius. Default 20. -- @param #number Length Unit lenght (in metres) for the load radius. Default 20.
-- @param #number Maxcargoweight Maxmimum weight in kgs this helo can carry. Default 500. -- @param #number Maxcargoweight Maxmimum weight in kgs this helo can carry. Default 500.
function CTLD:UnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight) function CTLD:SetUnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
self:T(self.lid .. " UnitCapabilities") self:T(self.lid .. " UnitCapabilities")
local unittype = nil local unittype = nil
local unit = nil local unit = nil
@@ -4307,13 +4438,13 @@ end
end end
local length = 20 local length = 20
local maxcargo = 500 local maxcargo = 500
local existingcaps = self.UnitTypes[unittype] -- #CTLD.UnitCapabilities local existingcaps = self.UnitTypeCapabilities[unittype] -- #CTLD.UnitTypeCapabilities
if existingcaps then if existingcaps then
length = existingcaps.length or 20 length = existingcaps.length or 20
maxcargo = existingcaps.cargoweightlimit or 500 maxcargo = existingcaps.cargoweightlimit or 500
end end
-- set capabilities -- set capabilities
local capabilities = {} -- #CTLD.UnitCapabilities local capabilities = {} -- #CTLD.UnitTypeCapabilities
capabilities.type = unittype capabilities.type = unittype
capabilities.crates = Cancrates or false capabilities.crates = Cancrates or false
capabilities.troops = Cantroops or false capabilities.troops = Cantroops or false
@@ -4321,10 +4452,26 @@ end
capabilities.trooplimit = Trooplimit or 0 capabilities.trooplimit = Trooplimit or 0
capabilities.length = Length or length capabilities.length = Length or length
capabilities.cargoweightlimit = Maxcargoweight or maxcargo capabilities.cargoweightlimit = Maxcargoweight or maxcargo
self.UnitTypes[unittype] = capabilities self.UnitTypeCapabilities[unittype] = capabilities
return self return self
end end
--- [Deprecated] - Function to add/adjust unittype capabilities. Has been replaced with `SetUnitCapabilities()` - pls use the new one going forward!
-- @param #CTLD self
-- @param #string Unittype The unittype to adjust. If passed as Wrapper.Unit#UNIT, it will search for the unit in the mission.
-- @param #boolean Cancrates Unit can load crates. Default false.
-- @param #boolean Cantroops Unit can load troops. Default false.
-- @param #number Cratelimit Unit can carry number of crates. Default 0.
-- @param #number Trooplimit Unit can carry number of troops. Default 0.
-- @param #number Length Unit lenght (in metres) for the load radius. Default 20.
-- @param #number Maxcargoweight Maxmimum weight in kgs this helo can carry. Default 500.
function CTLD:UnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
self:I(self.lid.."This function been replaced with `SetUnitCapabilities()` - pls use the new one going forward!")
self:SetUnitCapabilities(Unittype, Cancrates, Cantroops, Cratelimit, Trooplimit, Length, Maxcargoweight)
return self
end
--- (Internal) Check if a unit is hovering *in parameters*. --- (Internal) Check if a unit is hovering *in parameters*.
-- @param #CTLD self -- @param #CTLD self
-- @param Wrapper.Unit#UNIT Unit -- @param Wrapper.Unit#UNIT Unit
@@ -4477,7 +4624,7 @@ end
local unittype = Unit:GetTypeName() local unittype = Unit:GetTypeName()
local unitname = Unit:GetName() local unitname = Unit:GetName()
local Group = Unit:GetGroup() local Group = Unit:GetGroup()
local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitCapabilities local capabilities = self:_GetUnitCapabilities(Unit) -- #CTLD.UnitTypeCapabilities
local cancrates = capabilities.crates -- #boolean local cancrates = capabilities.crates -- #boolean
local cratelimit = capabilities.cratelimit -- #number local cratelimit = capabilities.cratelimit -- #number
if cancrates then if cancrates then

View File

@@ -329,7 +329,7 @@ FLIGHTCONTROL.FlightStatus={
--- FlightControl class version. --- FlightControl class version.
-- @field #string version -- @field #string version
FLIGHTCONTROL.version="0.7.4" FLIGHTCONTROL.version="0.7.5"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@@ -424,12 +424,14 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS, Port,
self.msrsTower=MSRS:New(PathToSRS, Frequency, Modulation) self.msrsTower=MSRS:New(PathToSRS, Frequency, Modulation)
self.msrsTower:SetPort(self.Port) self.msrsTower:SetPort(self.Port)
self.msrsTower:SetGoogle(GoogleKey) self.msrsTower:SetGoogle(GoogleKey)
self.msrsTower:SetCoordinate(self:GetCoordinate())
self:SetSRSTower() self:SetSRSTower()
-- SRS for Pilot. -- SRS for Pilot.
self.msrsPilot=MSRS:New(PathToSRS, Frequency, Modulation) self.msrsPilot=MSRS:New(PathToSRS, Frequency, Modulation)
self.msrsPilot:SetPort(self.Port) self.msrsPilot:SetPort(self.Port)
self.msrsPilot:SetGoogle(GoogleKey) self.msrsPilot:SetGoogle(GoogleKey)
self.msrsTower:SetCoordinate(self:GetCoordinate())
self:SetSRSPilot() self:SetSRSPilot()
-- Wait at least 10 seconds after last radio message before calling the next status update. -- Wait at least 10 seconds after last radio message before calling the next status update.
@@ -2809,7 +2811,11 @@ function FLIGHTCONTROL:_PlayerInfoATIS(groupname)
-- Radio message. -- Radio message.
self:TransmissionPilot(rtext, flight) self:TransmissionPilot(rtext, flight)
self:TransmissionTower(srstxt,flight,10) if self.atis then
self:TransmissionTower(srstxt,flight,10)
else
self:TransmissionTower(text,flight,10)
end
else else
self:E(self.lid..string.format("Cannot find flight group %s.", tostring(groupname))) self:E(self.lid..string.format("Cannot find flight group %s.", tostring(groupname)))
@@ -4341,7 +4347,7 @@ function FLIGHTCONTROL:TransmissionPilot(Text, Flight, Delay)
local text=self:_GetTextForSpeech(Text) local text=self:_GetTextForSpeech(Text)
-- MSRS instance to use. -- MSRS instance to use.
local msrs=self.msrsPilot local msrs=self.msrsPilot -- Sound.SRS#MSRS
if Flight.useSRS and Flight.msrs then if Flight.useSRS and Flight.msrs then
@@ -4361,6 +4367,8 @@ function FLIGHTCONTROL:TransmissionPilot(Text, Flight, Delay)
end end
-- Add transmission to msrsqueue. -- Add transmission to msrsqueue.
local coordinate = Flight:GetCoordinate(true)
msrs:SetCoordinate()
self.msrsqueue:NewTransmission(text, nil, msrs, nil, 1, subgroups, Text, nil, self.frequency, self.modulation) self.msrsqueue:NewTransmission(text, nil, msrs, nil, 1, subgroups, Text, nil, self.frequency, self.modulation)
end end
@@ -4437,11 +4445,21 @@ function FLIGHTCONTROL:SpawnParkingGuard(unit)
-- Length of the unit + 3 meters. -- Length of the unit + 3 meters.
local size, x, y, z=unit:GetObjectSize() local size, x, y, z=unit:GetObjectSize()
local xdiff = 3
--Fix for hangars, puts the guy out front and not on top.
if AIRBASE._CheckTerminalType(spot.TerminalType, AIRBASE.TerminalType.Shelter) then
xdiff = 27-(x*0.5)
end
if (AIRBASE._CheckTerminalType(spot.TerminalType, AIRBASE.TerminalType.OpenMed) or AIRBASE._CheckTerminalType(spot.TerminalType, AIRBASE.TerminalType.Shelter)) and self.airbasename == AIRBASE.Sinai.Ramon_Airbase then
xdiff = 12
end
-- Debug message. -- Debug message.
self:T2(self.lid..string.format("Parking guard for %s: heading=%d, distance x=%.1f m", unit:GetName(), heading, x)) self:T2(self.lid..string.format("Parking guard for %s: heading=%d, length x=%.1f m, xdiff=%.1f m", unit:GetName(), heading, x, xdiff))
-- Coordinate for the guard. -- Coordinate for the guard.
local Coordinate=coordinate:Translate(0.75*x+3, heading) local Coordinate=coordinate:Translate(x*0.5+xdiff, heading)
-- Let him face the aircraft. -- Let him face the aircraft.
local lookat=heading-180 local lookat=heading-180

View File

@@ -216,7 +216,7 @@ FLIGHTGROUP.Players={}
--- FLIGHTGROUP class version. --- FLIGHTGROUP class version.
-- @field #string version -- @field #string version
FLIGHTGROUP.version="1.0.1" FLIGHTGROUP.version="1.0.2"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@@ -1256,21 +1256,21 @@ function FLIGHTGROUP:Status()
-- Check damage. -- Check damage.
self:_CheckDamage() self:_CheckDamage()
-- Get current mission (if any).
local mission=self:GetMissionCurrent()
-- TODO: Check if group is waiting? -- TODO: Check if group is waiting?
if self:IsWaiting() then if self:IsWaiting() then
if self.Twaiting and self.dTwait then if self.Twaiting and self.dTwait then
if timer.getAbsTime()>self.Twaiting+self.dTwait then if timer.getAbsTime()>self.Twaiting+self.dTwait then
--self.Twaiting=nil --self.Twaiting=nil
--self.dTwait=nil --self.dTwait=nil
--self:Cruise() --self:_CheckGroupDone()
end end
end end
end end
-- Get current mission (if any).
local mission=self:GetMissionCurrent()
-- If mission, check if DCS task needs to be updated. -- If mission, check if DCS task needs to be updated.
if mission and mission.updateDCSTask then if mission and mission.updateDCSTask then
@@ -1363,7 +1363,7 @@ function FLIGHTGROUP:Status()
else else
-- Check damage. -- Check damage.
self:_CheckDamage() self:_CheckDamage()
end end
--- ---
@@ -1617,9 +1617,15 @@ function FLIGHTGROUP:Status()
--- ---
self:_PrintTaskAndMissionStatus() self:_PrintTaskAndMissionStatus()
-- Current mission. -- All done?
-- Get current mission (if any).
local mission=self:GetMissionCurrent() local mission=self:GetMissionCurrent()
if not mission then
self.Twaiting=nil
self.dTwait=nil
self:_CheckGroupDone()
end
end end
@@ -2857,8 +2863,11 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
end end
else else
-- Check if not parking (could be on ALERT5 and just spawned (current mission=nil)
if not self:IsParking() then
self:T(self.lid..string.format("Passed Final WP but Tasks=%d or Missions=%d left in the queue. Wait!", nTasks, nMissions)) self:T(self.lid..string.format("Passed Final WP but Tasks=%d or Missions=%d left in the queue. Wait!", nTasks, nMissions))
self:__Wait(-1) self:__Wait(-1)
end
end end
else else
self:T(self.lid..string.format("Passed Final WP but still have current Task (#%s) or Mission (#%s) left to do", tostring(self.taskcurrent), tostring(self.currentmission))) self:T(self.lid..string.format("Passed Final WP but still have current Task (#%s) or Mission (#%s) left to do", tostring(self.taskcurrent), tostring(self.currentmission)))
@@ -4789,7 +4798,7 @@ function FLIGHTGROUP:_GetTerminal(_attribute, _category)
-- Default terminal is "large". -- Default terminal is "large".
local _terminal=AIRBASE.TerminalType.OpenBig local _terminal=AIRBASE.TerminalType.OpenBig
if _attribute==FLIGHTGROUP.Attribute.AIR_FIGHTER then if _attribute==FLIGHTGROUP.Attribute.AIR_FIGHTER or _attribute==FLIGHTGROUP.Attribute.AIR_UAV then
-- Fighter ==> small. -- Fighter ==> small.
_terminal=AIRBASE.TerminalType.FighterAircraft _terminal=AIRBASE.TerminalType.FighterAircraft
elseif _attribute==FLIGHTGROUP.Attribute.AIR_BOMBER or _attribute==FLIGHTGROUP.Attribute.AIR_TRANSPORTPLANE or _attribute==FLIGHTGROUP.Attribute.AIR_TANKER or _attribute==FLIGHTGROUP.Attribute.AIR_AWACS then elseif _attribute==FLIGHTGROUP.Attribute.AIR_BOMBER or _attribute==FLIGHTGROUP.Attribute.AIR_TRANSPORTPLANE or _attribute==FLIGHTGROUP.Attribute.AIR_TANKER or _attribute==FLIGHTGROUP.Attribute.AIR_AWACS then

View File

@@ -1768,6 +1768,8 @@ function OPSGROUP:GetDCSUnit(UnitNumber)
if DCSGroup then if DCSGroup then
local unit=DCSGroup:getUnit(UnitNumber or 1) local unit=DCSGroup:getUnit(UnitNumber or 1)
return unit return unit
else
self:E(self.lid..string.format("ERROR: DCS group does not exist! Cannot get unit"))
end end
return nil return nil
@@ -2345,6 +2347,10 @@ function OPSGROUP:RadioTransmission(Text, Delay, SayCallsign, Frequency)
local freq, modu, radioon=self:GetRadio() local freq, modu, radioon=self:GetRadio()
local coord = self:GetCoordinate()
self.msrs:SetCoordinate(coord)
if Frequency then if Frequency then
self.msrs:SetFrequencies(Frequency) self.msrs:SetFrequencies(Frequency)
else else
@@ -3468,10 +3474,9 @@ function OPSGROUP:RemoveWaypoint(wpindex)
-- Could be that the waypoint we are currently moving to was the LAST waypoint. Then we now passed the final waypoint. -- Could be that the waypoint we are currently moving to was the LAST waypoint. Then we now passed the final waypoint.
if (self.adinfinitum or istemp) then if (self.adinfinitum or istemp) then
self:_PassedFinalWaypoint(false, "Removed PASSED temporary waypoint ") self:_PassedFinalWaypoint(false, "Removed PASSED temporary waypoint")
end end
end end
end end
@@ -3517,9 +3522,11 @@ function OPSGROUP:OnEventBirth(EventData)
local element=self:GetElementByName(unitname) local element=self:GetElementByName(unitname)
if element and element.status~=OPSGROUP.ElementStatus.SPAWNED then if element and element.status~=OPSGROUP.ElementStatus.SPAWNED then
-- Debug info. -- Debug info.
self:T(self.lid..string.format("EVENT: Element %s born ==> spawned", unitname)) self:T(self.lid..string.format("EVENT: Element %s born ==> spawned", unitname))
self:T2(self.lid..string.format("DCS unit=%s isExist=%s", tostring(EventData.IniDCSUnit:getName()), tostring(EventData.IniDCSUnit:isExist()) ))
-- Set element to spawned state. -- Set element to spawned state.
self:ElementSpawned(element) self:ElementSpawned(element)
@@ -5797,6 +5804,27 @@ function OPSGROUP:onafterMissionDone(From, Event, To, Mission)
end end
end end
if self.legion and self.legionReturn==false and self.waypoints and #self.waypoints==1 then
---
-- This is the case where a group was send on a mission (which is over now), has no addional
-- waypoints or tasks and should NOT return to its legion.
-- We create a new waypoint at the current position and let it hold here.
---
local Coordinate=self:GetCoordinate()
if self.isArmygroup then
ARMYGROUP.AddWaypoint(self, Coordinate, 0, nil, nil, false)
elseif self.isNavygroup then
NAVYGROUP.AddWaypoint(self,Coordinate, 0, nil, nil, false)
end
-- Remove original waypoint.
self:RemoveWaypoint(1)
self:_PassedFinalWaypoint(true, "Passed final waypoint as group is done with mission but should NOT return to its legion")
end
-- Check if group is done. -- Check if group is done.
self:_CheckGroupDone(delay) self:_CheckGroupDone(delay)

View File

@@ -1025,7 +1025,7 @@ function OPSZONE:Scan()
if ZoneObject then if ZoneObject then
-- Object category. -- Object category.
local ObjectCategory=ZoneObject:getCategory() local ObjectCategory=Object.getCategory(ZoneObject)
if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() then if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() then
@@ -1483,11 +1483,11 @@ function OPSZONE:_GetZoneColor()
local color={0,0,0} local color={0,0,0}
if self.ownerCurrent==coalition.side.NEUTRAL then if self.ownerCurrent==coalition.side.NEUTRAL then
color={1, 1, 1} color=self.ZoneOwnerNeutral or {1, 1, 1}
elseif self.ownerCurrent==coalition.side.BLUE then elseif self.ownerCurrent==coalition.side.BLUE then
color={0, 0, 1} color=self.ZoneOwnerBlue or {0, 0, 1}
elseif self.ownerCurrent==coalition.side.RED then elseif self.ownerCurrent==coalition.side.RED then
color={1, 0, 0} color=self.ZoneOwnerRed or {1, 0, 0}
else else
end end
@@ -1495,6 +1495,21 @@ function OPSZONE:_GetZoneColor()
return color return color
end end
--- Set custom RGB color of zone depending on current owner.
-- @param #OPSZONE self
-- @param #table Neutral Color is a table of RGB values 0..1 for Red, Green, and Blue respectively, e.g. {1,0,0} for red.
-- @param #table Blue Color is a table of RGB values 0..1 for Red, Green, and Blue respectively, e.g. {0,1,0} for green.
-- @param #table Red Color is a table of RGB values 0..1 for Red, Green, and Blue respectively, e.g. {0,0,1} for blue.
-- @return #OPSZONE self
function OPSZONE:SetZoneColor(Neutral, Blue, Red)
self.ZoneOwnerNeutral = Neutral or {1, 1, 1}
self.ZoneOwnerBlue = Blue or {0, 0, 1}
self.ZoneOwnerRed = Red or {1, 0, 0}
return self
end
--- Update marker on the F10 map. --- Update marker on the F10 map.
-- @param #OPSZONE self -- @param #OPSZONE self
function OPSZONE:_UpdateMarker() function OPSZONE:_UpdateMarker()

View File

@@ -104,7 +104,7 @@ PLAYERRECCE = {
ClassName = "PLAYERRECCE", ClassName = "PLAYERRECCE",
verbose = true, verbose = true,
lid = nil, lid = nil,
version = "0.0.18", version = "0.0.22",
ViewZone = {}, ViewZone = {},
ViewZoneVisual = {}, ViewZoneVisual = {},
ViewZoneLaser = {}, ViewZoneLaser = {},
@@ -268,6 +268,146 @@ function PLAYERRECCE:New(Name, Coalition, PlayerSet)
self:I(self.lid.." Started.") self:I(self.lid.." Started.")
------------------------
--- Pseudo Functions ---
------------------------
--- Triggers the FSM event "Start". Starts the PLAYERRECCE. Note: Start() is called automatically after New().
-- @function [parent=#PLAYERRECCE] Start
-- @param #PLAYERRECCE self
--- Triggers the FSM event "Start" after a delay. Starts the PLAYERRECCE. Note: Start() is called automatically after New().
-- @function [parent=#PLAYERRECCE] __Start
-- @param #PLAYERRECCE self
-- @param #number delay Delay in seconds.
--- Triggers the FSM event "Stop". Stops the PLAYERRECCE and all its event handlers.
-- @param #PLAYERRECCE self
--- Triggers the FSM event "Stop" after a delay. Stops the PLAYERRECCE and all its event handlers.
-- @function [parent=#PLAYERRECCE] __Stop
-- @param #PLAYERRECCE self
-- @param #number delay Delay in seconds.
--- FSM Function OnAfterRecceOnStation. Recce came on station.
-- @function [parent=#PLAYERRECCE] OnAfterRecceOnStation
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @return #PLAYERRECCE self
--- FSM Function OnAfterRecceOffStation. Recce went off duty.
-- @function [parent=#PLAYERRECCE] OnAfterRecceOffStation
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetDetected. Targets detected.
-- @function [parent=#PLAYERRECCE] OnAfterTargetDetected
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param #table Targetsbyclock #table with index 1..12 containing a #table of Wrapper.Unit#UNIT objects each.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetsSmoked. Smoke grenade shot.
-- @function [parent=#PLAYERRECCE] OnAfterTargetsSmoked
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @param Core.Set#SET_UNIT TargetSet
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetsFlared. Flares shot.
-- @function [parent=#PLAYERRECCE] OnAfterTargetsFlared
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @param Core.Set#SET_UNIT TargetSet
-- @return #PLAYERRECCE self
--- FSM Function OnAfterIllumination. Illumination rocket shot.
-- @function [parent=#PLAYERRECCE] OnAfterIllumination
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @param Core.Set#SET_UNIT TargetSet
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetLasing. Lasing a new target.
-- @function [parent=#PLAYERRECCE] OnAfterTargetLasing
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param Wrapper.Unit#UNIT Target
-- @param #number Lasercode
-- @param #number Lasingtime
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetLOSLost. Lost LOS on lased target.
-- @function [parent=#PLAYERRECCE] OnAfterTargetLOSLost
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param Wrapper.Unit#UNIT Target
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetReport. Laser target report sent.
-- @function [parent=#PLAYERRECCE] OnAfterTargetReport
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param Core.Set#SET_UNIT TargetSet
-- @param Wrapper.Unit#UNIT Target Target currently lased
-- @param #string Text
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetReportSent. All targets report sent.
-- @function [parent=#PLAYERRECCE] OnAfterTargetReportSent
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client Client sending the report
-- @param #string Playername Player name
-- @param Core.Set#SET_UNIT TargetSet Set of targets
-- @return #PLAYERRECCE self
--- FSM Function OnAfterShack. Lased target has been destroyed.
-- @function [parent=#PLAYERRECCE] OnAfterShack
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param Wrapper.Unit#UNIT Target The destroyed target (if obtainable)
-- @return #PLAYERRECCE self
return self return self
end end
@@ -329,8 +469,10 @@ function PLAYERRECCE:_GetClockDirection(unit, target)
local _playerPosition = unit:GetCoordinate() -- get position of helicopter local _playerPosition = unit:GetCoordinate() -- get position of helicopter
local _targetpostions = target:GetCoordinate() -- get position of downed pilot local _targetpostions = target:GetCoordinate() -- get position of downed pilot
local _heading = unit:GetHeading() -- heading local _heading = unit:GetHeading() -- heading
--self:I("Heading = ".._heading)
local DirectionVec3 = _playerPosition:GetDirectionVec3( _targetpostions ) local DirectionVec3 = _playerPosition:GetDirectionVec3( _targetpostions )
local Angle = _playerPosition:GetAngleDegrees( DirectionVec3 ) local Angle = _playerPosition:GetAngleDegrees( DirectionVec3 )
--self:I("Angle = "..Angle)
local clock = 12 local clock = 12
local hours = 0 local hours = 0
if _heading and Angle then if _heading and Angle then
@@ -338,15 +480,18 @@ function PLAYERRECCE:_GetClockDirection(unit, target)
--if angle == 0 then angle = 360 end --if angle == 0 then angle = 360 end
clock = _heading-Angle clock = _heading-Angle
hours = (clock/30)*-1 hours = (clock/30)*-1
--self:I("hours = "..hours)
clock = 12+hours clock = 12+hours
clock = UTILS.Round(clock,0) clock = UTILS.Round(clock,0)
if clock > 12 then clock = clock-12 end if clock > 12 then clock = clock-12 end
end if clock == 0 then clock = 12 end
end
--self:I("Clock ="..clock)
return clock return clock
end end
--- [User] Set a table of possible laser codes. --- [User] Set a table of possible laser codes.
-- Each new RECCE can select a code from this table, default is 1688. -- Each new RECCE can select a code from this table, default is { 1688, 1130, 4785, 6547, 1465, 4578 }.
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param #list<#number> LaserCodes -- @param #list<#number> LaserCodes
-- @return #PLAYERRECCE -- @return #PLAYERRECCE
@@ -399,7 +544,7 @@ end
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param Wrapper.Client#CLIENT client -- @param Wrapper.Client#CLIENT client
-- @param #string playername -- @param #string playername
-- @return #boolen OnOff -- @return #boolean OnOff
function PLAYERRECCE:_CameraOn(client,playername) function PLAYERRECCE:_CameraOn(client,playername)
local camera = true local camera = true
local unit = client -- Wrapper.Unit#UNIT local unit = client -- Wrapper.Unit#UNIT
@@ -430,26 +575,31 @@ function PLAYERRECCE:_GetGazelleVivianneSight(Gazelle)
local unit = Gazelle -- Wrapper.Unit#UNIT local unit = Gazelle -- Wrapper.Unit#UNIT
if unit and unit:IsAlive() then if unit and unit:IsAlive() then
local dcsunit = Unit.getByName(Gazelle:GetName()) local dcsunit = Unit.getByName(Gazelle:GetName())
local vivihorizontal = dcsunit:getDrawArgumentValue(215) or 0 -- (not in MiniGun) 1 to -1 -- zero is straight ahead, 1/-1 = 180 deg local vivihorizontal = dcsunit:getDrawArgumentValue(215) or 0 -- (not in MiniGun) 1 to -1 -- zero is straight ahead, 1/-1 = 180 deg,
local vivivertical = dcsunit:getDrawArgumentValue(216) or 0 -- L/Mistral/Minigun model has no 216, ca 10deg up (=1) and down (=-1) local vivivertical = dcsunit:getDrawArgumentValue(216) or 0 -- L/Mistral/Minigun model has no 216, ca 10deg up (=1) and down (=-1)
-- vertical model limits 1.53846, -1.10731
local vivioff = false local vivioff = false
-- -1 = -180, 1 = 180 -- -1 = -180, 1 = 180
-- Actual view -0,66 to 0,66 -- Actual model view -0,66 to 0,66
-- Nick view -0,98 to 0,98 for +/- 30° -- Nick view 1.53846, -1.10731 for - 30° to +45°
if vivihorizontal < -0.7 then if vivihorizontal < -0.67 then -- model end
vivihorizontal = -0.7 vivihorizontal = -0.67
vivioff = true vivioff = false
return 0,0,0,false --return 0,0,0,false
elseif vivihorizontal > 0.7 then elseif vivihorizontal > 0.67 then -- vivi off
vivihorizontal = 0.7 vivihorizontal = 0.67
vivioff = true vivioff = true
return 0,0,0,false return 0,0,0,false
end end
vivivertical = vivivertical / 1.10731 -- normalize
local horizontalview = vivihorizontal * -180 local horizontalview = vivihorizontal * -180
local verticalview = vivivertical * -30 -- ca +/- 30° local verticalview = vivivertical * 30 -- ca +/- 30°
--self:I(string.format("vivihorizontal=%.5f | vivivertical=%.5f",vivihorizontal,vivivertical))
--self:I(string.format("horizontal=%.5f | vertical=%.5f",horizontalview,verticalview))
local heading = unit:GetHeading() local heading = unit:GetHeading()
local viviheading = (heading+horizontalview)%360 local viviheading = (heading+horizontalview)%360
local maxview = self:_GetActualMaxLOSight(unit,viviheading, verticalview,vivioff) local maxview = self:_GetActualMaxLOSight(unit,viviheading, verticalview,vivioff)
--self:I(string.format("maxview=%.5f",maxview))
-- visual skew -- visual skew
local factor = 3.15 local factor = 3.15
self.GazelleViewFactors = { self.GazelleViewFactors = {
@@ -469,16 +619,18 @@ function PLAYERRECCE:_GetGazelleVivianneSight(Gazelle)
} }
local lfac = UTILS.Round(maxview,-2) local lfac = UTILS.Round(maxview,-2)
if lfac <= 1300 then if lfac <= 1300 then
factor = self.GazelleViewFactors[lfac/100] --factor = self.GazelleViewFactors[lfac/100]
factor = 3.15
maxview = math.ceil((maxview*factor)/100)*100 maxview = math.ceil((maxview*factor)/100)*100
end end
if maxview > 8000 then maxview = 8000 end if maxview > 8000 then maxview = 8000 end
--self:I(string.format("corrected maxview=%.5f",maxview))
return viviheading, verticalview,maxview, not vivioff return viviheading, verticalview,maxview, not vivioff
end end
return 0,0,0,false return 0,0,0,false
end end
--- [Internal] Get the max line of sight based on unit head and camera nod via trigonometrie. Returns 0 if camera is off. --- [Internal] Get the max line of sight based on unit head and camera nod via trigonometry. Returns 0 if camera is off.
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param Wrapper.Unit#UNIT unit The unit which LOS we want -- @param Wrapper.Unit#UNIT unit The unit which LOS we want
-- @param #number vheading Heading where the unit or camera is looking -- @param #number vheading Heading where the unit or camera is looking
@@ -488,12 +640,13 @@ end
function PLAYERRECCE:_GetActualMaxLOSight(unit,vheading, vnod, vivoff) function PLAYERRECCE:_GetActualMaxLOSight(unit,vheading, vnod, vivoff)
self:T(self.lid.."_GetActualMaxLOSight") self:T(self.lid.."_GetActualMaxLOSight")
if vivoff then return 0 end if vivoff then return 0 end
--if vnod < -0.03 then vnod = -0.03 end
local maxview = 0 local maxview = 0
if unit and unit:IsAlive() then if unit and unit:IsAlive() then
local typename = unit:GetTypeName() local typename = unit:GetTypeName()
maxview = self.MaxViewDistance[typename] or 8000 maxview = self.MaxViewDistance[typename] or 8000
local CamHeight = self.Cameraheight[typename] or 0 local CamHeight = self.Cameraheight[typename] or 0
if vnod > 0 then if vnod < 0 then
-- Looking down -- Looking down
-- determine max distance we're looking at -- determine max distance we're looking at
local beta = 90 local beta = 90
@@ -505,7 +658,7 @@ function PLAYERRECCE:_GetActualMaxLOSight(unit,vheading, vnod, vivoff)
maxview = c*1.2 -- +20% maxview = c*1.2 -- +20%
end end
end end
return maxview return math.abs(maxview)
end end
--- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns. --- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns.
@@ -561,8 +714,8 @@ function PLAYERRECCE:_GetViewZone(unit, vheading, minview, maxview, angle, camon
local heading2 = (vheading-90)%360 local heading2 = (vheading-90)%360
self:T({heading1,heading2}) self:T({heading1,heading2})
local startpos = startp:Translate(minview,vheading) local startpos = startp:Translate(minview,vheading)
local pos1 = startpos:Translate(10,heading1) local pos1 = startpos:Translate(12.5,heading1)
local pos2 = startpos:Translate(10,heading2) local pos2 = startpos:Translate(12.5,heading2)
local pos3 = pos1:Translate(maxview,vheading) local pos3 = pos1:Translate(maxview,vheading)
local pos4 = pos2:Translate(maxview,vheading) local pos4 = pos2:Translate(maxview,vheading)
local array = {} local array = {}
@@ -764,31 +917,49 @@ function PLAYERRECCE:_LaseTarget(client,targetset)
else else
laser = self.LaserSpots[playername] laser = self.LaserSpots[playername]
end end
-- old target
if self.LaserTarget[playername] then if self.LaserTarget[playername] then
-- still looking at target? -- still looking at target?
local target=self.LaserTarget[playername] -- Ops.Target#TARGET local target=self.LaserTarget[playername] -- Ops.Target#TARGET
local oldtarget = target:GetObject() --or laser.Target local oldtarget = target:GetObject() --or laser.Target
self:T("Targetstate: "..target:GetState()) self:T("Targetstate: "..target:GetState())
if not oldtarget or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then self:T("Laser State: "..tostring(laser:IsLasing()))
if (not oldtarget) or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then
-- lost LOS or dead -- lost LOS or dead
laser:LaseOff() laser:LaseOff()
if target:IsDead() or target:IsDestroyed() or target:GetLife() < 2 then if target:IsDead() or target:IsDestroyed() or target:GetLife() < 2 then
self:__Shack(-1,client,oldtarget) self:__Shack(-1,client,oldtarget)
self.LaserTarget[playername] = nil --self.LaserTarget[playername] = nil
else else
self:__TargetLOSLost(-1,client,oldtarget) self:__TargetLOSLost(-1,client,oldtarget)
self.LaserTarget[playername] = nil --self.LaserTarget[playername] = nil
end end
self.LaserTarget[playername] = nil
oldtarget = nil
self.LaserSpots[playername] = nil
elseif oldtarget and laser and (not laser:IsLasing()) then
--laser:LaseOff()
self:T("Switching laser back on ..")
local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688
local lasingtime = self.lasingtime or 60
--local targettype = target:GetTypeName()
laser:LaseOn(oldtarget,lasercode,lasingtime)
--self:__TargetLasing(-1,client,oldtarget,lasercode,lasingtime)
else
-- we should not be here...
self:T("Target alive and laser is on!")
--self.LaserSpots[playername] = nil
end end
elseif not laser:IsLasing() and target then -- new target
elseif (not laser:IsLasing()) and target then
local relativecam = self.LaserRelativePos[client:GetTypeName()] local relativecam = self.LaserRelativePos[client:GetTypeName()]
laser:SetRelativeStartPosition(relativecam) laser:SetRelativeStartPosition(relativecam)
local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688 local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688
local lasingtime = self.lasingtime or 60 local lasingtime = self.lasingtime or 60
local targettype = target:GetTypeName() --local targettype = target:GetTypeName()
laser:LaseOn(target,lasercode,lasingtime) laser:LaseOn(target,lasercode,lasingtime)
self.LaserTarget[playername] = TARGET:New(target) self.LaserTarget[playername] = TARGET:New(target)
self.LaserTarget[playername].TStatus = 9 --self.LaserTarget[playername].TStatus = 9
self:__TargetLasing(-1,client,target,lasercode,lasingtime) self:__TargetLasing(-1,client,target,lasercode,lasingtime)
end end
return self return self
@@ -870,6 +1041,13 @@ function PLAYERRECCE:_SwitchLasing(client,group,playername)
MESSAGE:New("Lasing is now ON",10,self.Name or "FACA"):ToClient(client) MESSAGE:New("Lasing is now ON",10,self.Name or "FACA"):ToClient(client)
else else
self.AutoLase[playername] = false self.AutoLase[playername] = false
if self.LaserSpots[playername] then
local laser = self.LaserSpots[playername] -- Core.Spot#SPOT
if laser:IsLasing() then
laser:LaseOff()
end
self.LaserSpots[playername] = nil
end
MESSAGE:New("Lasing is now OFF",10,self.Name or "FACA"):ToClient(client) MESSAGE:New("Lasing is now OFF",10,self.Name or "FACA"):ToClient(client)
end end
if self.ClientMenus[playername] then if self.ClientMenus[playername] then
@@ -953,9 +1131,13 @@ function PLAYERRECCE:_SmokeTargets(client,group,playername)
end end
end end
local coordinate = nil
local setthreat = 0
-- smoke everything else -- smoke everything else
local coordinate = cameraset:GetCoordinate() if cameraset:CountAlive() > 1 then
local setthreat = cameraset:CalculateThreatLevelA2G() local coordinate = cameraset:GetCoordinate()
local setthreat = cameraset:CalculateThreatLevelA2G()
end
if coordinate then if coordinate then
local color = lowsmoke local color = lowsmoke
@@ -1520,12 +1702,16 @@ function PLAYERRECCE:onafterRecceOnStation(From, Event, To, Client, Playername)
local text2tts = string.format("All stations, FACA %s on station at %s!",callsign, coordtext) local text2tts = string.format("All stations, FACA %s on station at %s!",callsign, coordtext)
text2tts = self:_GetTextForSpeech(text2tts) text2tts = self:_GetTextForSpeech(text2tts)
if self.debug then if self.debug then
self:I(text2.."\n"..text2tts) self:T(text2.."\n"..text2tts)
end end
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(text1,nil,self.SRS,nil,2) self.SRSQueue:NewTransmission(text1,nil,self.SRS,nil,2)
self.SRSQueue:NewTransmission(text2tts,nil,self.SRS,nil,2) self.SRSQueue:NewTransmission(text2tts,nil,self.SRS,nil,3)
MESSAGE:New(text2,10,self.Name or "FACA"):ToCoalition(self.Coalition) MESSAGE:New(text2,10,self.Name or "FACA"):ToCoalition(self.Coalition)
else else
MESSAGE:New(text1,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text1,10,self.Name or "FACA"):ToClient(Client)
@@ -1555,13 +1741,17 @@ function PLAYERRECCE:onafterRecceOffStation(From, Event, To, Client, Playername)
local texttts = string.format("All stations, FACA %s leaving station at %s, good bye!",callsign, coordtext) local texttts = string.format("All stations, FACA %s leaving station at %s, good bye!",callsign, coordtext)
texttts = self:_GetTextForSpeech(texttts) texttts = self:_GetTextForSpeech(texttts)
if self.debug then if self.debug then
self:I(text.."\n"..texttts) self:T(text.."\n"..texttts)
end end
local text1 = "Going home!" local text1 = "Going home!"
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(text1,nil,self.SRS,nil,2) self.SRSQueue:NewTransmission(text1,nil,self.SRS,nil,2)
self.SRSQueue:NewTransmission(texttts,nil,self.SRS,nil,2) self.SRSQueue:NewTransmission(texttts,nil,self.SRS,nil,3)
MESSAGE:New(text,10,self.Name or "FACA"):ToCoalition(self.Coalition) MESSAGE:New(text,10,self.Name or "FACA"):ToCoalition(self.Coalition)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToCoalition(self.Coalition) MESSAGE:New(text,10,self.Name or "FACA"):ToCoalition(self.Coalition)
@@ -1574,7 +1764,7 @@ end
-- @param #string From -- @param #string From
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param #table Targetsbyclock -- @param #table Targetsbyclock. #table with index 1..12 containing a #table of Wrapper.Unit#UNIT objects each.
-- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
-- @param #string Playername -- @param #string Playername
-- @return #PLAYERRECCE self -- @return #PLAYERRECCE self
@@ -1617,6 +1807,9 @@ function PLAYERRECCE:onafterTargetDetected(From, Event, To, Targetsbyclock, Clie
local ttstext = string.format("Target! %s! %s oh clock, %d %s!", ThreatTxt, i, targetdistance, dunits) local ttstext = string.format("Target! %s! %s oh clock, %d %s!", ThreatTxt, i, targetdistance, dunits)
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
if clientcoord then
self.SRS:SetCoordinate(clientcoord)
end
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)
@@ -1653,6 +1846,10 @@ function PLAYERRECCE:onafterTargetDetected(From, Event, To, Targetsbyclock, Clie
local ttstext = string.format("%d targets! %s oh clock, %d %s!", targetno, i, targetdistance, dunits) local ttstext = string.format("%d targets! %s oh clock, %d %s!", targetno, i, targetdistance, dunits)
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)
@@ -1694,6 +1891,10 @@ function PLAYERRECCE:onafterIllumination(From, Event, To, Client, Playername, Ta
local ttstext = "Sunshine!" local ttstext = "Sunshine!"
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)
@@ -1733,6 +1934,10 @@ function PLAYERRECCE:onafterTargetsSmoked(From, Event, To, Client, Playername, T
local ttstext = "Smoke and Mirrors!" local ttstext = "Smoke and Mirrors!"
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)
@@ -1772,6 +1977,10 @@ function PLAYERRECCE:onafterTargetsFlared(From, Event, To, Client, Playername, T
local ttstext = "Fire works!" local ttstext = "Fire works!"
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)
@@ -1808,7 +2017,7 @@ function PLAYERRECCE:onafterTargetLasing(From, Event, To, Client, Target, Laserc
coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings) coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings)
end end
local coordtext = coord:ToStringA2G(client,Settings) local coordtext = coord:ToStringA2G(client,Settings)
local text = string.format("All stations, %s lasing %s\nat %s!\nCode %d, Duration %d seconds!",callsign, targettype, coordtext, Lasercode, Lasingtime) local text = string.format("All stations, %s lasing %s\nat %s!\nCode %d, Duration %d plus seconds!",callsign, targettype, coordtext, Lasercode, Lasingtime)
MESSAGE:New(text,15,self.Name or "FACA"):ToClient(client) MESSAGE:New(text,15,self.Name or "FACA"):ToClient(client)
end end
end end
@@ -1817,6 +2026,10 @@ function PLAYERRECCE:onafterTargetLasing(From, Event, To, Client, Target, Laserc
local ttstext = "Laser on!" local ttstext = "Laser on!"
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)
@@ -1831,9 +2044,8 @@ end
-- @param #string To -- @param #string To
-- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
-- @param Wrapper.Unit#UNIT Target -- @param Wrapper.Unit#UNIT Target
-- @param #string Targettype
-- @return #PLAYERRECCE self -- @return #PLAYERRECCE self
function PLAYERRECCE:onafterShack(From, Event, To, Client, Target, Targettype) function PLAYERRECCE:onafterShack(From, Event, To, Client, Target)
self:T({From, Event, To}) self:T({From, Event, To})
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations) local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS
@@ -1861,6 +2073,10 @@ function PLAYERRECCE:onafterShack(From, Event, To, Client, Target, Targettype)
local ttstext = "Shack!" local ttstext = "Shack!"
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)
@@ -1904,6 +2120,10 @@ function PLAYERRECCE:onafterTargetLOSLost(From, Event, To, Client, Target)
local ttstext = "Lost L O S!" local ttstext = "Lost L O S!"
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10) self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,1,{grp},text,10)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)
@@ -1933,7 +2153,6 @@ function PLAYERRECCE:onafterTargetReport(From, Event, To, Client, TargetSet, Tar
end end
end end
end end
--self:__TargetReportSent(-2,Client, TargetSet, Target, Text)
return self return self
end end
@@ -1942,16 +2161,19 @@ end
-- @param #string From -- @param #string From
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client Client sending the report
-- @param Core.Set#SET_UNIT TargetSet -- @param #string Playername Player name
-- @param Wrapper.Unit#UNIT Target -- @param Core.Set#SET_UNIT TargetSet Set of targets
-- @param #string Text
-- @return #PLAYERRECCE self -- @return #PLAYERRECCE self
function PLAYERRECCE:onafterTargetReportSent(From, Event, To, Client, TargetSet) function PLAYERRECCE:onafterTargetReportSent(From, Event, To, Client, Playername, TargetSet)
self:T({From, Event, To}) self:T({From, Event, To})
local text = "Upload completed!" local text = "Upload completed!"
if self.UseSRS then if self.UseSRS then
local grp = Client:GetGroup() local grp = Client:GetGroup()
local coord = grp:GetCoordinate()
if coord then
self.SRS:SetCoordinate(coord)
end
self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,1,{grp},text,10) self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,1,{grp},text,10)
else else
MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client) MESSAGE:New(text,10,self.Name or "FACA"):ToClient(Client)

View File

@@ -98,7 +98,7 @@ PLAYERTASK = {
--- PLAYERTASK class version. --- PLAYERTASK class version.
-- @field #string version -- @field #string version
PLAYERTASK.version="0.1.21" PLAYERTASK.version="0.1.22"
--- Generic task condition. --- Generic task condition.
-- @type PLAYERTASK.Condition -- @type PLAYERTASK.Condition
@@ -935,7 +935,7 @@ end
do do
------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------
-- PLAYERTASKCONTROLLER -- PLAYERTASKCONTROLLER
-- TODO: PLAYERTASKCONTROLLER -- TODO: PLAYERTASKCONTROLLER
-- DONE Playername customized -- DONE Playername customized
-- DONE Coalition-level screen info to SET based -- DONE Coalition-level screen info to SET based
-- DONE Flash directions -- DONE Flash directions
@@ -1552,7 +1552,7 @@ PLAYERTASKCONTROLLER.Messages = {
--- PLAYERTASK class version. --- PLAYERTASK class version.
-- @field #string version -- @field #string version
PLAYERTASKCONTROLLER.version="0.1.62" PLAYERTASKCONTROLLER.version="0.1.63"
--- Create and run a new TASKCONTROLLER instance. --- Create and run a new TASKCONTROLLER instance.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
@@ -1579,13 +1579,13 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
self.ClusterRadius = 0.5 self.ClusterRadius = 0.5
self.TargetRadius = 500 self.TargetRadius = 500
self.ClientFilter = ClientFilter or "" self.ClientFilter = ClientFilter --or ""
self.TargetQueue = FIFO:New() -- Utilities.FiFo#FIFO self.TargetQueue = FIFO:New() -- Utilities.FiFo#FIFO
self.TaskQueue = FIFO:New() -- Utilities.FiFo#FIFO self.TaskQueue = FIFO:New() -- Utilities.FiFo#FIFO
self.TasksPerPlayer = FIFO:New() -- Utilities.FiFo#FIFO self.TasksPerPlayer = FIFO:New() -- Utilities.FiFo#FIFO
self.PrecisionTasks = FIFO:New() -- Utilities.FiFo#FIFO self.PrecisionTasks = FIFO:New() -- Utilities.FiFo#FIFO
self.PlayerMenu = {} -- #table --self.PlayerMenu = {} -- #table
self.FlashPlayer = {} -- #table self.FlashPlayer = {} -- #table
self.AllowFlash = false self.AllowFlash = false
self.lasttaskcount = 0 self.lasttaskcount = 0
@@ -2175,10 +2175,10 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
if EventData.IniPlayerName then if EventData.IniPlayerName then
self:T(self.lid.."Event for player: "..EventData.IniPlayerName) self:T(self.lid.."Event for player: "..EventData.IniPlayerName)
if self.PlayerMenu[EventData.IniPlayerName] then --if self.PlayerMenu[EventData.IniPlayerName] then
self.PlayerMenu[EventData.IniPlayerName]:Remove() --self.PlayerMenu[EventData.IniPlayerName]:Remove()
self.PlayerMenu[EventData.IniPlayerName] = nil --self.PlayerMenu[EventData.IniPlayerName] = nil
end --end
local text = "" local text = ""
if self.TasksPerPlayer:HasUniqueID(EventData.IniPlayerName) then if self.TasksPerPlayer:HasUniqueID(EventData.IniPlayerName) then
local task = self.TasksPerPlayer:PullByID(EventData.IniPlayerName) -- Ops.PlayerTask#PLAYERTASK local task = self.TasksPerPlayer:PullByID(EventData.IniPlayerName) -- Ops.PlayerTask#PLAYERTASK
@@ -2187,6 +2187,8 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
task:RemoveClient(Client) task:RemoveClient(Client)
--text = "Task aborted!" --text = "Task aborted!"
text = self.gettext:GetEntry("TASKABORT",self.locale) text = self.gettext:GetEntry("TASKABORT",self.locale)
self.ActiveTaskMenuTemplate:ResetMenu(Client)
self.JoinTaskMenuTemplate:ResetMenu(Client)
else else
task:RemoveClient(nil,EventData.IniPlayerName) task:RemoveClient(nil,EventData.IniPlayerName)
--text = "Task aborted!" --text = "Task aborted!"
@@ -2236,8 +2238,8 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
self.SRSQueue:NewTransmission(text,nil,self.SRS,timer.getAbsTime()+60,2,{EventData.IniGroup},text,30,self.BCFrequency,self.BCModulation) self.SRSQueue:NewTransmission(text,nil,self.SRS,timer.getAbsTime()+60,2,{EventData.IniGroup},text,30,self.BCFrequency,self.BCModulation)
end end
if EventData.IniPlayerName then if EventData.IniPlayerName then
self.PlayerMenu[EventData.IniPlayerName] = nil --self.PlayerMenu[EventData.IniPlayerName] = nil
local player = CLIENT:FindByName(EventData.IniUnitName) local player = _DATABASE:FindClient( EventData.IniUnitName )
self:_SwitchMenuForClient(player,"Info") self:_SwitchMenuForClient(player,"Info")
end end
end end
@@ -2949,7 +2951,7 @@ function PLAYERTASKCONTROLLER:_AddTask(Target)
task:HandleEvent(EVENTS.Shot) task:HandleEvent(EVENTS.Shot)
function task:OnEventShot(EventData) function task:OnEventShot(EventData)
local data = EventData -- Core.Event#EVENTDATA EventData local data = EventData -- Core.Event#EVENTDATA EventData
local wcat = data.Weapon:getCategory() -- cat 2 or 3 local wcat = Object.getCategory(data.Weapon) -- cat 2 or 3
local coord = data.IniUnit:GetCoordinate() or data.IniGroup:GetCoordinate() local coord = data.IniUnit:GetCoordinate() or data.IniGroup:GetCoordinate()
local vec2 = coord:GetVec2() or {x=0, y=0} local vec2 = coord:GetVec2() or {x=0, y=0}
local coal = data.IniCoalition local coal = data.IniCoalition
@@ -4003,8 +4005,9 @@ end
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS. -- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest) -- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS -- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
-- @param Core.Point#COORDINATE Coordinate Coordinate from which the controller radio is sending
-- @return #PLAYERTASKCONTROLLER self -- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey) function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,Coordinate)
self:T(self.lid.."SetSRS") self:T(self.lid.."SetSRS")
self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone" -- self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
self.Gender = Gender or "male" -- self.Gender = Gender or "male" --
@@ -4029,6 +4032,9 @@ function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Cultu
if self.PathToGoogleKey then if self.PathToGoogleKey then
self.SRS:SetGoogle(self.PathToGoogleKey) self.SRS:SetGoogle(self.PathToGoogleKey)
end end
if Coordinate then
self.SRS:SetCoordinate(Coordinate)
end
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name) self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers) self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
return self return self

View File

@@ -64,8 +64,6 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\RESCUEHELO\RescueHelo_Main.png)
--
-- # Recue Helo -- # Recue Helo
-- --
-- The rescue helo will fly in close formation with another unit, which is typically an aircraft carrier. -- The rescue helo will fly in close formation with another unit, which is typically an aircraft carrier.

View File

@@ -44,7 +44,7 @@
-- --
-- * First, you need to **"add a @{#RADIO} object** to your @{Wrapper.Positionable#POSITIONABLE}. This is done using the @{Wrapper.Positionable#POSITIONABLE.GetRadio}() function, -- * First, you need to **"add a @{#RADIO} object** to your @{Wrapper.Positionable#POSITIONABLE}. This is done using the @{Wrapper.Positionable#POSITIONABLE.GetRadio}() function,
-- * Then, you will **set the relevant parameters** to the transmission (see below), -- * Then, you will **set the relevant parameters** to the transmission (see below),
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function. -- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{#RADIO.Broadcast}() function.
-- --
-- Methods to set relevant parameters for both a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or any other @{Wrapper.Positionable#POSITIONABLE} -- Methods to set relevant parameters for both a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or any other @{Wrapper.Positionable#POSITIONABLE}
-- --

View File

@@ -17,15 +17,15 @@
--- Makes the radio speak. --- Makes the radio speak.
-- --
-- # RADIOSPEECH usage -- # RADIOSPEECH usage
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- --
-- @type RADIOSPEECH -- @type RADIOSPEECH
-- @extends Core.RadioQueue#RADIOQUEUE -- @extends Sound.RadioQueue#RADIOQUEUE
RADIOSPEECH = { RADIOSPEECH = {
ClassName = "RADIOSPEECH", ClassName = "RADIOSPEECH",
Vocabulary = { Vocabulary = {

View File

@@ -50,6 +50,7 @@
-- @field #string ConfigFileName Name of the standard config file -- @field #string ConfigFileName Name of the standard config file
-- @field #string ConfigFilePath Path to the standard config file -- @field #string ConfigFilePath Path to the standard config file
-- @field #boolean ConfigLoaded -- @field #boolean ConfigLoaded
-- @field #string ttsprovider Default provider TTS backend, e.g. "Google" or "Microsoft", default is Microsoft
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- *It is a very sad thing that nowadays there is so little useless information.* - Oscar Wilde --- *It is a very sad thing that nowadays there is so little useless information.* - Oscar Wilde
@@ -127,6 +128,10 @@
-- --
-- Use @{#MSRS.SetVolume} to define the SRS volume. Defaults to 1.0. Allowed values are between 0.0 and 1.0, from silent to loudest. -- Use @{#MSRS.SetVolume} to define the SRS volume. Defaults to 1.0. Allowed values are between 0.0 and 1.0, from silent to loudest.
-- --
-- ## Config file for many variables, auto-loaded by Moose
--
-- See @{#MSRS.LoadConfigFile} for details on how to set this up.
--
-- ## Set DCS-gRPC as an alternative to 'DCS-SR-ExternalAudio.exe' for TTS -- ## Set DCS-gRPC as an alternative to 'DCS-SR-ExternalAudio.exe' for TTS
-- --
-- Use @{#MSRS.SetDefaultBackendGRPC} to enable [DCS-gRPC](https://github.com/DCS-gRPC/rust-server) as an alternate backend for transmitting text-to-speech over SRS. -- Use @{#MSRS.SetDefaultBackendGRPC} to enable [DCS-gRPC](https://github.com/DCS-gRPC/rust-server) as an alternate backend for transmitting text-to-speech over SRS.
@@ -191,11 +196,12 @@ MSRS = {
ConfigFileName = "Moose_MSRS.lua", ConfigFileName = "Moose_MSRS.lua",
ConfigFilePath = "Config\\", ConfigFilePath = "Config\\",
ConfigLoaded = false, ConfigLoaded = false,
ttsprovider = "Microsoft",
} }
--- MSRS class version. --- MSRS class version.
-- @field #string version -- @field #string version
MSRS.version="0.1.2" MSRS.version="0.1.3"
--- Voices --- Voices
-- @type MSRS.Voices -- @type MSRS.Voices
@@ -377,9 +383,7 @@ function MSRS:New(PathToSRS, Frequency, Modulation, Volume, AltBackend)
return self:_NewAltBackend(Backend) return self:_NewAltBackend(Backend)
end end
local success = self:LoadConfigFile(nil,nil,self.ConfigLoaded) if not self.ConfigLoaded then
if (not success) and (not self.ConfigLoaded) then
-- If no AltBackend table, the proceed with default initialisation -- If no AltBackend table, the proceed with default initialisation
self:SetPath(PathToSRS) self:SetPath(PathToSRS)
@@ -446,7 +450,7 @@ function MSRS:SetPath(Path)
end end
-- Debug output. -- Debug output.
self:I(string.format("SRS path=%s", self:GetPath())) self:T(string.format("SRS path=%s", self:GetPath()))
end end
return self return self
end end
@@ -674,7 +678,7 @@ function MSRS:SetCoordinate(Coordinate)
return self return self
end end
--- Use google text-to-speech. --- Use google text-to-speech credentials. Also sets Google as default TTS provider.
-- @param #MSRS self -- @param #MSRS self
-- @param #string PathToCredentials Full path to the google credentials JSON file, e.g. "C:\Users\username\Downloads\service-account-file.json". Can also be the Google API key. -- @param #string PathToCredentials Full path to the google credentials JSON file, e.g. "C:\Users\username\Downloads\service-account-file.json". Can also be the Google API key.
-- @return #MSRS self -- @return #MSRS self
@@ -688,13 +692,14 @@ function MSRS:SetGoogle(PathToCredentials)
self.GRPCOptions.DefaultProvider = "gcloud" self.GRPCOptions.DefaultProvider = "gcloud"
self.GRPCOptions.gcloud.key = PathToCredentials self.GRPCOptions.gcloud.key = PathToCredentials
self.ttsprovider = "Google"
end end
return self return self
end end
--- Use google text-to-speech. --- gRPC Backend: Use google text-to-speech set the API key.
-- @param #MSRS self -- @param #MSRS self
-- @param #string APIKey API Key, usually a string of length 40 with characters and numbers. -- @param #string APIKey API Key, usually a string of length 40 with characters and numbers.
-- @return #MSRS self -- @return #MSRS self
@@ -708,6 +713,22 @@ function MSRS:SetGoogleAPIKey(APIKey)
return self return self
end end
--- Use Google text-to-speech as default.
-- @param #MSRS self
-- @return #MSRS self
function MSRS:SetTTSProviderGoogle()
self.ttsprovider = "Google"
return self
end
--- Use Microsoft text-to-speech as default.
-- @param #MSRS self
-- @return #MSRS self
function MSRS:SetTTSProviderMicrosoft()
self.ttsprovider = "Microsoft"
return self
end
--- Print SRS STTS help to DCS log file. --- Print SRS STTS help to DCS log file.
-- @param #MSRS self -- @param #MSRS self
-- @return #MSRS self -- @return #MSRS self
@@ -769,7 +790,7 @@ end
--- Play sound file (ogg or mp3) via SRS. --- Play sound file (ogg or mp3) via SRS.
-- @param #MSRS self -- @param #MSRS self
-- @param Sound.SoundFile#SOUNDFILE Soundfile Sound file to play. -- @param Sound.SoundOutput#SOUNDFILE Soundfile Sound file to play.
-- @param #number Delay Delay in seconds, before the sound file is played. -- @param #number Delay Delay in seconds, before the sound file is played.
-- @return #MSRS self -- @return #MSRS self
function MSRS:PlaySoundFile(Soundfile, Delay) function MSRS:PlaySoundFile(Soundfile, Delay)
@@ -797,7 +818,7 @@ end
--- Play a SOUNDTEXT text-to-speech object. --- Play a SOUNDTEXT text-to-speech object.
-- @param #MSRS self -- @param #MSRS self
-- @param Sound.SoundFile#SOUNDTEXT SoundText Sound text. -- @param Sound.SoundOutput#SOUNDTEXT SoundText Sound text.
-- @param #number Delay Delay in seconds, before the sound file is played. -- @param #number Delay Delay in seconds, before the sound file is played.
-- @return #MSRS self -- @return #MSRS self
function MSRS:PlaySoundText(SoundText, Delay) function MSRS:PlaySoundText(SoundText, Delay)
@@ -824,15 +845,16 @@ end
-- @param #MSRS self -- @param #MSRS self
-- @param #string Text Text message. -- @param #string Text Text message.
-- @param #number Delay Delay in seconds, before the message is played. -- @param #number Delay Delay in seconds, before the message is played.
-- @param Core.Point#COORDINATE Coordinate Coordinate.
-- @return #MSRS self -- @return #MSRS self
function MSRS:PlayText(Text, Delay) function MSRS:PlayText(Text, Delay, Coordinate)
if Delay and Delay>0 then if Delay and Delay>0 then
self:ScheduleOnce(Delay, MSRS.PlayText, self, Text, 0) self:ScheduleOnce(Delay, MSRS.PlayText, self, Text, nil, Coordinate)
else else
-- Get command line. -- Get command line.
local command=self:_GetCommand() local command=self:_GetCommand(nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,Coordinate)
-- Append text. -- Append text.
command=command..string.format(" --text=\"%s\"", tostring(Text)) command=command..string.format(" --text=\"%s\"", tostring(Text))
@@ -856,11 +878,12 @@ end
-- @param #string Voice Voice. -- @param #string Voice Voice.
-- @param #number Volume Volume. -- @param #number Volume Volume.
-- @param #string Label Label. -- @param #string Label Label.
-- @param Core.Point#COORDINATE Coordinate Coordinate.
-- @return #MSRS self -- @return #MSRS self
function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label) function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate)
if Delay and Delay>0 then if Delay and Delay>0 then
self:ScheduleOnce(Delay, MSRS.PlayTextExt, self, Text, 0, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label) self:ScheduleOnce(Delay, MSRS.PlayTextExt, self, Text, 0, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate)
else else
-- Ensure table. -- Ensure table.
@@ -874,7 +897,7 @@ function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture
end end
-- Get command line. -- Get command line.
local command=self:_GetCommand(Frequencies, Modulations, nil, Gender, Voice, Culture, Volume, nil, nil, Label) local command=self:_GetCommand(Frequencies, Modulations, nil, Gender, Voice, Culture, Volume, nil, nil, Label, Coordinate)
-- Append text. -- Append text.
command=command..string.format(" --text=\"%s\"", tostring(Text)) command=command..string.format(" --text=\"%s\"", tostring(Text))
@@ -1065,8 +1088,9 @@ end
-- @param #number speed Speed. -- @param #number speed Speed.
-- @param #number port Port. -- @param #number port Port.
-- @param #string label Label, defaults to "ROBOT" (displayed sender name in the radio overlay of SRS) - No spaces allowed! -- @param #string label Label, defaults to "ROBOT" (displayed sender name in the radio overlay of SRS) - No spaces allowed!
-- @param Core.Point#COORDINATE coordinate Coordinate.
-- @return #string Command. -- @return #string Command.
function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, speed, port,label) function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, speed, port,label,coordinate)
local path=self:GetPath() or STTS.DIRECTORY local path=self:GetPath() or STTS.DIRECTORY
local exe=STTS.EXECUTABLE or "DCS-SR-ExternalAudio.exe" local exe=STTS.EXECUTABLE or "DCS-SR-ExternalAudio.exe"
@@ -1080,6 +1104,7 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
speed=speed or self.speed speed=speed or self.speed
port=port or self.port port=port or self.port
label=label or self.Label label=label or self.Label
coordinate=coordinate or self.coordinate
-- Replace modulation -- Replace modulation
modus=modus:gsub("0", "AM") modus=modus:gsub("0", "AM")
@@ -1104,13 +1129,13 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
end end
-- Set coordinate. -- Set coordinate.
if self.coordinate then if coordinate then
local lat,lon,alt=self:_GetLatLongAlt(self.coordinate) local lat,lon,alt=self:_GetLatLongAlt(coordinate)
command=command..string.format(" -L %.4f -O %.4f -A %d", lat, lon, alt) command=command..string.format(" -L %.4f -O %.4f -A %d", lat, lon, alt)
end end
-- Set google. -- Set google.
if self.google then if self.google and self.ttsprovider == "Google" then
command=command..string.format(' --ssml -G "%s"', self.google) command=command..string.format(' --ssml -G "%s"', self.google)
end end
@@ -1124,7 +1149,6 @@ end
-- @param #MSRS self -- @param #MSRS self
-- @param #string Path Path to config file, defaults to "C:\Users\<yourname>\Saved Games\DCS\Config" -- @param #string Path Path to config file, defaults to "C:\Users\<yourname>\Saved Games\DCS\Config"
-- @param #string Filename File to load, defaults to "Moose_MSRS.lua" -- @param #string Filename File to load, defaults to "Moose_MSRS.lua"
-- @param #boolean ConfigLoaded - if true, skip the loading
-- @return #boolean success -- @return #boolean success
-- @usage -- @usage
-- 0) Benefits: Centralize configuration of SRS, keep paths and keys out of the mission source code, making it safer and easier to move missions to/between servers, -- 0) Benefits: Centralize configuration of SRS, keep paths and keys out of the mission source code, making it safer and easier to move missions to/between servers,
@@ -1134,18 +1158,19 @@ end
-- --
-- -- Moose MSRS default Config -- -- Moose MSRS default Config
-- MSRS_Config = { -- MSRS_Config = {
-- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- adjust as needed -- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- adjust as needed, note double \\
-- Port = 5002, -- adjust as needed -- Port = 5002, -- adjust as needed
-- Frequency = {127,243}, -- must be a table, 1..n entries! -- Frequency = {127,243}, -- must be a table, 1..n entries!
-- Modulation = {0,0}, -- must be a table, 1..n entries, one for each frequency! -- Modulation = {0,0}, -- must be a table, 1..n entries, one for each frequency!
-- Volume = 1.0, -- Volume = 1.0, -- 0.0 to 1.0
-- Coalition = 0, -- 0 = Neutral, 1 = Red, 2 = Blue -- Coalition = 0, -- 0 = Neutral, 1 = Red, 2 = Blue
-- Coordinate = {0,0,0}, -- x,y,alt - optional -- Coordinate = {0,0,0}, -- x,y,altitude - optional, all in meters
-- Culture = "en-GB", -- Culture = "en-GB",
-- Gender = "male", -- Gender = "male",
-- Google = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourfilename.json", -- path to google json key file - optional -- Google = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourfilename.json", -- path to google json key file - optional.
-- Label = "MSRS", -- Label = "MSRS",
-- Voice = "Microsoft Hazel Desktop", -- Voice = "Microsoft Hazel Desktop",
-- Provider = "Microsoft", -- this is the default TTS provider, e.g. "Google" or "Microsoft"
-- -- gRPC (optional) -- -- gRPC (optional)
-- GRPC = { -- see https://github.com/DCS-gRPC/rust-server -- GRPC = { -- see https://github.com/DCS-gRPC/rust-server
-- coalition = "blue", -- blue, red, neutral -- coalition = "blue", -- blue, red, neutral
@@ -1162,14 +1187,18 @@ end
-- } -- }
-- } -- }
-- --
-- 3) Load the config into the MSRS raw class before you do anything else: -- 3) The config file is automatically loaded when Moose starts. YOu can also load the config into the MSRS raw class manually before you do anything else:
-- --
-- MSRS.LoadConfigFile() -- Note the "." here -- MSRS.LoadConfigFile() -- Note the "." here
--
-- Optionally, your might want to provide a specific path and filename:
--
-- MSRS.LoadConfigFile(nil,MyPath,MyFilename) -- Note the "." here
-- --
-- This will populate variables for the MSRS raw class and all instances you create with e.g. `mysrs = MSRS:New()` -- This will populate variables for the MSRS raw class and all instances you create with e.g. `mysrs = MSRS:New()`
-- Optionally you can also load this per **single instance** if so needed, i.e. -- Optionally you can also load this per **single instance** if so needed, i.e.
-- --
-- mysrs:LoadConfig(Path,Filename) -- mysrs:LoadConfigFile(Path,Filename)
-- --
-- 4) Use the config in your code like so, variable names are basically the same as in the config file, but all lower case, examples: -- 4) Use the config in your code like so, variable names are basically the same as in the config file, but all lower case, examples:
-- --
@@ -1186,46 +1215,21 @@ end
-- atis:SetSRS(nil,nil,nil,MSRS.Voices.Google.Standard.en_US_Standard_H) -- atis:SetSRS(nil,nil,nil,MSRS.Voices.Google.Standard.en_US_Standard_H)
-- --Start ATIS -- --Start ATIS
-- atis:Start() -- atis:Start()
function MSRS:LoadConfigFile(Path,Filename,ConfigLoaded) function MSRS:LoadConfigFile(Path,Filename)
if lfs == nil then
env.info("*****Note - lfs and os need to be desanitized for MSRS to work!")
return false
end
local path = Path or lfs.writedir()..MSRS.ConfigFilePath local path = Path or lfs.writedir()..MSRS.ConfigFilePath
local file = Filename or MSRS.ConfigFileName or "Moose_MSRS.lua" local file = Filename or MSRS.ConfigFileName or "Moose_MSRS.lua"
local pathandfile = path..file
local filexsists = UTILS.FileExists(pathandfile)
if UTILS.CheckFileExists(path,file) and not ConfigLoaded then if filexsists and not MSRS.ConfigLoaded then
assert(loadfile(path..file))() assert(loadfile(path..file))()
-- now we should have a global var MSRS_Config -- now we should have a global var MSRS_Config
if MSRS_Config then if MSRS_Config then
--[[
-- Moose MSRS default Config
MSRS_Config = {
Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- adjust as needed
Port = 5002, -- adjust as needed
Frequency = {127,243}, -- must be a table, 1..n entries!
Modulation = {0,0}, -- must be a table, 1..n entries, one for each frequency!
Volume = 1.0,
Coalition = 0, -- 0 = Neutral, 1 = Red, 2 = Blue
Coordinate = {0,0,0}, -- x,y,alt - optional
Culture = "en-GB",
Gender = "male",
Google = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourfilename.json", -- path to google json key file - optional
Label = "MSRS",
Voice = "Microsoft Hazel Desktop",
-- gRPC (optional)
GRPC = { -- see https://github.com/DCS-gRPC/rust-server
coalition = "blue", -- blue, red, neutral
DefaultProvider = "gcloud", -- win, gcloud, aws, or azure, some of the values below depend on your cloud provider
gcloud = {
key = "<API Google Key>", -- for gRPC Google API key
--secret = "", -- needed for aws
--region = "",-- needed for aws
defaultVoice = MSRS.Voices.Google.Standard.en_GB_Standard_F,
},
win = {
defaultVoice = "Hazel",
},
}
}
--]]
if self then if self then
self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
self.port = MSRS_Config.Port or 5002 self.port = MSRS_Config.Port or 5002
@@ -1238,8 +1242,11 @@ function MSRS:LoadConfigFile(Path,Filename,ConfigLoaded)
self.culture = MSRS_Config.Culture or "en-GB" self.culture = MSRS_Config.Culture or "en-GB"
self.gender = MSRS_Config.Gender or "male" self.gender = MSRS_Config.Gender or "male"
self.google = MSRS_Config.Google self.google = MSRS_Config.Google
if MSRS_Config.Provider then
self.ttsprovider = MSRS_Config.Provider
end
self.Label = MSRS_Config.Label or "MSRS" self.Label = MSRS_Config.Label or "MSRS"
self.voice = MSRS_Config.Voice or MSRS.Voices.Microsoft.Hazel self.voice = MSRS_Config.Voice --or MSRS.Voices.Microsoft.Hazel
if MSRS_Config.GRPC then if MSRS_Config.GRPC then
self.provider = MSRS_Config.GRPC.DefaultProvider self.provider = MSRS_Config.GRPC.DefaultProvider
if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then
@@ -1262,8 +1269,11 @@ function MSRS:LoadConfigFile(Path,Filename,ConfigLoaded)
MSRS.culture = MSRS_Config.Culture or "en-GB" MSRS.culture = MSRS_Config.Culture or "en-GB"
MSRS.gender = MSRS_Config.Gender or "male" MSRS.gender = MSRS_Config.Gender or "male"
MSRS.google = MSRS_Config.Google MSRS.google = MSRS_Config.Google
if MSRS_Config.Provider then
MSRS.ttsprovider = MSRS_Config.Provider
end
MSRS.Label = MSRS_Config.Label or "MSRS" MSRS.Label = MSRS_Config.Label or "MSRS"
MSRS.voice = MSRS_Config.Voice or MSRS.Voices.Microsoft.Hazel MSRS.voice = MSRS_Config.Voice --or MSRS.Voices.Microsoft.Hazel
if MSRS_Config.GRPC then if MSRS_Config.GRPC then
MSRS.provider = MSRS_Config.GRPC.DefaultProvider MSRS.provider = MSRS_Config.GRPC.DefaultProvider
if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then
@@ -1276,9 +1286,10 @@ function MSRS:LoadConfigFile(Path,Filename,ConfigLoaded)
MSRS.ConfigLoaded = true MSRS.ConfigLoaded = true
end end
end end
env.info("MSRS - Sucessfully loaded default configuration from disk!",false) env.info("MSRS - Successfully loaded default configuration from disk!",false)
else end
env.info("MSRS - Cannot load default configuration from disk!",false) if not filexsists then
env.info("MSRS - Cannot find default configuration file!",false)
return false return false
end end
@@ -1417,7 +1428,7 @@ end
--- Replacement function for @{#MSRS.PlaySoundText} --- Replacement function for @{#MSRS.PlaySoundText}
-- @param #MSRS self -- @param #MSRS self
-- @param Sound.SoundFile#SOUNDTEXT SoundText Sound text. -- @param Sound.SoundOutput#SOUNDTEXT SoundText Sound text.
-- @param #number Delay Delay in seconds, before the sound file is played. -- @param #number Delay Delay in seconds, before the sound file is played.
-- @return #MSRS self -- @return #MSRS self
MSRS_BACKEND_DCSGRPC.Functions.PlaySoundText = function (self, SoundText, Delay) MSRS_BACKEND_DCSGRPC.Functions.PlaySoundText = function (self, SoundText, Delay)
@@ -1649,6 +1660,7 @@ MSRSQUEUE = {
-- @field #string voice Voice if any -- @field #string voice Voice if any
-- @field #number volume Volume -- @field #number volume Volume
-- @field #string label Label to be used -- @field #string label Label to be used
-- @field Core.Point#COORDINATE coordinate Coordinate for this transmission
--- Create a new MSRSQUEUE object for a given radio frequency/modulation. --- Create a new MSRSQUEUE object for a given radio frequency/modulation.
-- @param #MSRSQUEUE self -- @param #MSRSQUEUE self
@@ -1672,7 +1684,7 @@ end
-- @param #MSRSQUEUE self -- @param #MSRSQUEUE self
-- @return #MSRSQUEUE self The MSRSQUEUE object. -- @return #MSRSQUEUE self The MSRSQUEUE object.
function MSRSQUEUE:Clear() function MSRSQUEUE:Clear()
self:I(self.lid.."Clearning MSRSQUEUE") self:I(self.lid.."Clearing MSRSQUEUE")
self.queue={} self.queue={}
return self return self
end end
@@ -1733,8 +1745,9 @@ end
-- @param #string voice Specific voice -- @param #string voice Specific voice
-- @param #number volume Volume setting -- @param #number volume Volume setting
-- @param #string label Label to be used -- @param #string label Label to be used
-- @param Core.Point#COORDINATE coordinate Coordinate to be used
-- @return #MSRSQUEUE.Transmission Radio transmission table. -- @return #MSRSQUEUE.Transmission Radio transmission table.
function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation, gender, culture, voice, volume, label) function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation, gender, culture, voice, volume, label,coordinate)
if self.TransmitOnlyWithPlayers then if self.TransmitOnlyWithPlayers then
if self.PlayerSet and self.PlayerSet:CountAlive() == 0 then if self.PlayerSet and self.PlayerSet:CountAlive() == 0 then
@@ -1772,9 +1785,10 @@ function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgr
transmission.gender = gender transmission.gender = gender
transmission.culture = culture transmission.culture = culture
transmission.voice = voice transmission.voice = voice
transmission.gender = volume transmission.volume = volume
transmission.label = label transmission.label = label
transmission.coordinate = coordinate
-- Add transmission to queue. -- Add transmission to queue.
self:AddTransmission(transmission) self:AddTransmission(transmission)
@@ -1785,11 +1799,11 @@ end
-- @param #MSRSQUEUE self -- @param #MSRSQUEUE self
-- @param #MSRSQUEUE.Transmission transmission The transmission. -- @param #MSRSQUEUE.Transmission transmission The transmission.
function MSRSQUEUE:Broadcast(transmission) function MSRSQUEUE:Broadcast(transmission)
if transmission.frequency then if transmission.frequency then
transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, transmission.gender, transmission.culture, transmission.voice, transmission.volume, transmission.label) transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, transmission.gender, transmission.culture, transmission.voice, transmission.volume, transmission.label, transmission.coordinate)
else else
transmission.msrs:PlayText(transmission.text) transmission.msrs:PlayText(transmission.text,nil,transmission.coordinate)
end end
local function texttogroup(gid) local function texttogroup(gid)
@@ -1988,6 +2002,7 @@ function MSRSQUEUE:_CheckRadioQueue(delay)
end end
MSRS.LoadConfigFile()
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -313,7 +313,7 @@ do -- Text-To-Speech
-- --
-- ## Specific Voice -- ## Specific Voice
-- --
-- You can use a specific voice for the transmission with the @{SOUNDTEXT.SetVoice}(*VoiceName*) function. Here are some examples -- You can use a specific voice for the transmission with the @{#SOUNDTEXT.SetVoice}(*VoiceName*) function. Here are some examples
-- --
-- * Name: Microsoft Hazel Desktop, Culture: en-GB, Gender: Female, Age: Adult, Desc: Microsoft Hazel Desktop - English (Great Britain) -- * Name: Microsoft Hazel Desktop, Culture: en-GB, Gender: Female, Age: Adult, Desc: Microsoft Hazel Desktop - English (Great Britain)
-- * Name: Microsoft David Desktop, Culture: en-US, Gender: Male, Age: Adult, Desc: Microsoft David Desktop - English (United States) -- * Name: Microsoft David Desktop, Culture: en-US, Gender: Male, Age: Adult, Desc: Microsoft David Desktop - English (United States)

View File

@@ -162,12 +162,12 @@
-- choose from 2 added menu options either to accept or reject the assigned task within 30 seconds. -- choose from 2 added menu options either to accept or reject the assigned task within 30 seconds.
-- If the task is not accepted within 30 seconds; the task will be cancelled and a new task will be assigned. -- If the task is not accepted within 30 seconds; the task will be cancelled and a new task will be assigned.
-- --
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #COMMANDCENTER -- @field #COMMANDCENTER
COMMANDCENTER = { COMMANDCENTER = {
ClassName = "COMMANDCENTER", ClassName = "COMMANDCENTER",
@@ -339,7 +339,7 @@ end
--- Gets the coalition of the command center. --- Gets the coalition of the command center.
-- @param #COMMANDCENTER self -- @param #COMMANDCENTER self
-- @return DCScoalition#coalition -- @return #number Coalition of the command center.
function COMMANDCENTER:GetCoalition() function COMMANDCENTER:GetCoalition()
return self.CommandCenterCoalition return self.CommandCenterCoalition

View File

@@ -18,7 +18,7 @@
-- Derived classes need to implement the method @{#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report. -- Derived classes need to implement the method @{#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report.
-- --
-- Reporting can be started and stopped using the methods @{#DETECTION_MANAGER.StartReporting}() and @{#DETECTION_MANAGER.StopReporting}() respectively. -- Reporting can be started and stopped using the methods @{#DETECTION_MANAGER.StartReporting}() and @{#DETECTION_MANAGER.StopReporting}() respectively.
-- If an ad-hoc report is requested, use the method @{#DETECTION_MANAGER#ReportNow}(). -- If an ad-hoc report is requested, use the method @{#DETECTION_MANAGER.ReportNow}().
-- --
-- The default reporting interval is every 60 seconds. The reporting messages are displayed 15 seconds. -- The default reporting interval is every 60 seconds. The reporting messages are displayed 15 seconds.
-- --
@@ -32,12 +32,12 @@
-- ------------------------------- -- -------------------------------
-- The @{#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance. -- The @{#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
-- --
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- ### Contributions: Mechanist, Prof_Hilactic, FlightControl - Concept & Testing -- ### Contributions: Mechanist, Prof_Hilactic, FlightControl - Concept & Testing

View File

@@ -117,12 +117,12 @@
-- - @{#MISSION.ReportPlayersPerTask}(): Generates a report showing the active players per task. -- - @{#MISSION.ReportPlayersPerTask}(): Generates a report showing the active players per task.
-- - @{#MISSION.ReportPlayersProgress}(): Generates a report showing the task progress per player. -- - @{#MISSION.ReportPlayersProgress}(): Generates a report showing the task progress per player.
-- --
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- @field #MISSION -- @field #MISSION
MISSION = { MISSION = {
ClassName = "MISSION", ClassName = "MISSION",

View File

@@ -203,12 +203,12 @@
-- --
-- These different completion states are important for the mission designer to reflect scoring to a player. -- These different completion states are important for the mission designer to reflect scoring to a player.
-- A success could mean a positive score to be given, while a failure could mean a negative score or penalties to be awarded. -- A success could mean a positive score to be given, while a failure could mean a negative score or penalties to be awarded.
-- --
-- # 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
-- Therefore, this class is considered to be deprecated -- Therefore, this class is considered to be deprecated
-- --
-- === -- ===
-- --
-- ### Author(s): **FlightControl** -- ### Author(s): **FlightControl**
@@ -1773,7 +1773,7 @@ do -- Links
--- Set detection of a task --- Set detection of a task
-- @param #TASK self -- @param #TASK self
-- @param Function.Detection#DETECTION_BASE Detection -- @param Functional.Detection#DETECTION_BASE Detection
-- @param DetectedItem -- @param DetectedItem
-- @return #TASK -- @return #TASK
function TASK:SetDetection( Detection, DetectedItem ) function TASK:SetDetection( Detection, DetectedItem )

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