Compare commits

..

150 Commits
v1.1 ... v1.1.0

Author SHA1 Message Date
Sven Van de Velde
71374f0ce1 Merge pull request #316 from FlightControl-Master/FlightControl
Fixed weaponexpend problem for gunterlund in AI_CAS
-- The attack sequence was commented out. Put it back in.
-- Fixed documentation order glitch.
-- Documented the usage of AI.Task.WeaponExpend
-- Deleted weaponType from Controller Task
2017-03-18 07:44:17 +01:00
FlightControl
d216fc96da Fixed weaponexpend problem for gunterlund in AI_CAS.
-- The attack sequence was commented out. Put it back in.
-- Fixed documentation order glitch.
-- Documented the usage of AI.Task.WeaponExpend
-- Deleted weaponType from Controller Task
2017-03-18 07:42:41 +01:00
FlightControl
80ba6bf40d Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl 2017-03-18 05:45:44 +01:00
Sven Van de Velde
46e8f30c4a Merge pull request #315 from FlightControl-Master/FlightControl
New tasking system
2017-03-17 21:53:41 +01:00
FlightControl
4e59f1a674 Final commit ... 2017-03-17 21:49:06 +01:00
FlightControl
ce00cbf83e Better 2017-03-17 18:46:00 +01:00
FlightControl
9f2179a428 Trying to get the dependency on EVENTs solved. 2017-03-17 18:33:08 +01:00
FlightControl
3f0c983194 Updates 2017-03-17 13:59:19 +01:00
FlightControl
7231492eaa Release prep 2017-03-17 11:50:24 +01:00
Sven Van de Velde
8c4ae420e2 Merge pull request #314 from FlightControl-Master/FlightControl-menu-optimization
Flightcontrol menu optimization
2017-03-17 11:30:09 +01:00
FlightControl
83ed29a90a OK. Menu is working again ... 2017-03-17 11:29:23 +01:00
FlightControl
af55214c52 Menu optimization 2017-03-17 06:57:32 +01:00
FlightControl
4c64548bea Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
2017-03-16 05:03:43 +01:00
Sven Van de Velde
9b54e32b50 Merge pull request #313 from FlightControl-Master/master-bugfix-cas-engage
Fix of Engage trigger loosing given parameters when rerouting
2017-03-15 19:17:10 +01:00
FlightControl
0555ced241 Fix of Engage trigger loosing given parameters when rerouting
This is fixed now.
2017-03-15 19:16:29 +01:00
FlightControl
056bebe4c3 Updated all test missions 2017-03-15 19:09:33 +01:00
FlightControl
520ee6e459 Updated Mission, cleaned it up and removed stuff. 2017-03-15 11:49:47 +01:00
FlightControl
9fc3f7a601 Made user exits for Mission Completion evaluation...
Man, this is going to rock!
2017-03-15 10:08:03 +01:00
Sven Van de Velde
450892bfd9 Merge pull request #312 from FlightControl-Master/flightcontrol-nillification
Flightcontrol nillification
2017-03-15 09:40:59 +01:00
FlightControl
d77405bf9b nillification of the unit processes for tasks is fixed. 2017-03-15 09:35:41 +01:00
FlightControl
65c15281fd Merge remote-tracking branch 'refs/remotes/origin/master' into flightcontrol-nillification
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
2017-03-15 05:06:23 +01:00
FlightControl
d7f75eaab6 Generate moose.lua 2017-03-14 15:30:37 +01:00
Sven Van de Velde
03d921831f Merge pull request #311 from FlightControl-Master/Whisper_TaskRouteToZone
TaskRouteToZone formation fix
2017-03-14 15:28:36 +01:00
kalbuth
dbb710a980 TaskRouteToZone formation fix
setting initial point of TaskRouteToZone mission waypoints to have
expected Formation set up.
2017-03-14 15:03:12 +01:00
FlightControl
d160b24b0d Commit 2017-03-14 09:31:17 +01:00
FlightControl
b7e5af772a Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air
Patrol/CAP-001 - Combat Air Patrol.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage
within Range/CAP-010 - CAP and Engage within Range.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-011 - CAP and Engage
within Zone/CAP-011 - CAP and Engage within Zone.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-020 - Combat Air
Patrol RTB Test/CAP-020 - Combat Air Patrol RTB Test.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a Zone by
Airplane Group/CAS-001 - CAS in a ZONE-ME Test.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a Zone by
Airplane Group/CAS-001 - CAS in a Zone by Airplane Group.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-002 - CAS in a Zone by
Airplane Group - Engage with Speed/CAS-002 - CAS in a Zone by Airplane
Group - Engage with Speed.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-003 - CAS in a Zone by
Airplane Group - Engage with Speed and Altitude/CAS-003 - CAS in a Zone
by Airplane Group - Engage with Speed and Altitude.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-010 - CAS in a Zone by
Helicopter/CAS-010 - CAS in a Zone by Helicopter.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-011 - CAS in a Zone by
Helicopter Group/CAS-011 - CAS in a Zone by Helicopter Group.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-111 - Multiple CAS in
1 Radius Zone by Helicopter and AirPlane Groups/CAS-111 - Multiple CAS
in 1 Radius Zone by Helicopter and AirPlane Groups.miz
#	Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 -
Spawn Demo.miz
#	Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple
Spawning/SPA-011 - Ground Ops - Simple Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple
Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz
#	Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled
Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz
#	Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled
Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz
#	Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize
Route/SPA-015 - Ground Ops - Randomize Route.miz
#	Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize
Zones/SPA-016 - Ground Ops - Randomize Zones.miz
#	Moose Test Missions/SPA - Spawning/SPA-017 - Ground Ops - Set AI
inactive while spawning/SPA-017 - Ground Ops - Set AI inactive while
spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-018 - Ground Ops - Randomize
Templates/SPA-018 - Ground Ops - Randomize Templates.miz
#	Moose Test Missions/SPA - Spawning/SPA-019 - Ground Ops - Randomize
Templates without Waypoints/SPA-019 - Ground Ops - Randomize Templates
without Waypoints.miz
#	Moose Test Missions/SPA - Spawning/SPA-020 - Ground Ops - Randomize
Templates in Random Zones without Waypoints/SPA-020 - Ground Ops -
Randomize Templates in Random Zones without Waypoints.miz
#	Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive
Units/SPA-100 - CleanUp Inactive Units.miz
#	Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 -
Limit Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-120 - Air Ops - Scheduled Spawn
with Repeat on Landing with Limit/SPA-120 - Air Ops - Scheduled Spawn
with Repeat on Landing with Limit.miz
#	Moose Test Missions/SPA - Spawning/SPA-121 - Air Ops - Scheduled
Spawns with Repeat on Landing with Limit/SPA-121 - Air Ops - Scheduled
Spawns with Repeat on Landing with Limit.miz
#	Moose Test Missions/SPA - Spawning/SPA-130 - Uncontrolled
Spawning/SPA-130 - Uncontrolled Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit
Types/SPA-200 - Randomize Unit Types.miz
#	Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 -
Randomize Zones.miz
#	Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static
position/SPA-310 - Spawn at Static position.miz
#	Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit
position/SPA-320 - Spawn at Unit position.miz
#	Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2
position/SPA-330 - Spawn at Vec2 position.miz
#	Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3
position/SPA-340 - Spawn at Vec3 position.miz
#	docs/Documentation/AI_Cas.html
2017-03-14 09:30:54 +01:00
FlightControl
ed81858f0c Move of header template 2017-03-14 09:19:26 +01:00
Sven Van de Velde
78625b0f7f Merge pull request #309 from FlightControl-Master/master-addon-spawn-InitSpawnRandomizeGroups
SPAWN: Added InitRandomizePosition API
2017-03-14 09:10:19 +01:00
FlightControl
a0100d0980 SPAWN: Added InitRandomizePosition API
-- SPAWN:InitRandomizePosition( RandomizePosition, OuterRadius,
InnerRadius ) added.
-- SPA-350 test missions
-- Documentation Update
-- testing.
2017-03-14 09:09:48 +01:00
Sven Van de Velde
8c8e95d8fb Merge pull request #308 from FlightControl-Master/master-bugfix-ai-cas-cap-abort
Fixed abort in AI_CAP_ZONE and CAI_CAS_ZONE
2017-03-14 06:45:39 +01:00
FlightControl
782af122dd Fixed abort in AI_CAP_ZONE and CAI_CAS_ZONE
-- When the event Abort was triggered, nothing happened.
Is fixed now. AI will fly back to the patrol zone and will continue
patrolling.
2017-03-14 06:45:14 +01:00
Sven Van de Velde
985a922d5f Merge pull request #307 from FlightControl-Master/master-addon-SPAWN
SPAWN: Keep unit names
2017-03-14 05:38:13 +01:00
FlightControl
8d535fa3dd SPAWN: Keep unit names
-- new method SPAWN:InitKeepUnitNames() added.
-- Added test mission SPA-021
-- Documentation
-- Testing
2017-03-14 05:37:36 +01:00
FlightControl
fe79821474 Fixing SCHEDULER - TO BE FURTHER STUDIES AND FIXED
TASK object should dissapear after nillified.
They are hooked to the SCHEDULER... SCHEDULEs should dissapear, but they
don't....

To be further studied.
2017-03-14 03:36:12 +01:00
FlightControl
32d23927b6 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Development/Moose/AI/AI_CAS.lua
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/CAS - Close Air Support/CAS-003 - CAS in a Zone by
Airplane Group - Engage with Speed and Altitude/CAS-003 - CAS in a Zone
by Airplane Group - Engage with Speed and Altitude.miz
#	docs/Documentation/AI_Cas.html
2017-03-13 10:13:17 +01:00
Sven Van de Velde
9d67015649 Merge pull request #305 from FlightControl-Master/master-fix-ai-cap
Master fix ai cap
2017-03-13 10:00:52 +01:00
FlightControl
6b5fbc530b Updated documentation and test mission to show the mechanism. 2017-03-13 10:00:19 +01:00
FlightControl
e997e0769b Merge remote-tracking branch 'refs/remotes/origin/master' into master-fix-ai-cap 2017-03-13 08:39:20 +01:00
FlightControl
36123f02c7 Test of unit types detection 2017-03-12 19:35:28 +01:00
FlightControl
c07ac8e1ba DETECTION_TYPES working! 2017-03-12 19:32:36 +01:00
FlightControl
13ac7e0c41 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air
Patrol/CAP-001 - Combat Air Patrol.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage
within Range/CAP-010 - CAP and Engage within Range.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-011 - CAP and Engage
within Zone/CAP-011 - CAP and Engage within Zone.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-020 - Combat Air
Patrol RTB Test/CAP-020 - Combat Air Patrol RTB Test.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a Zone by
Airplane Group/CAS-001 - CAS in a ZONE-ME Test.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a Zone by
Airplane Group/CAS-001 - CAS in a Zone by Airplane Group.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-002 - CAS in a Zone by
Airplane Group - Engage with Speed/CAS-002 - CAS in a Zone by Airplane
Group - Engage with Speed.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-003 - CAS in a Zone by
Airplane Group - Engage with Speed and Altitude/CAS-003 - CAS in a Zone
by Airplane Group - Engage with Speed and Altitude.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-010 - CAS in a Zone by
Helicopter/CAS-010 - CAS in a Zone by Helicopter.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-011 - CAS in a Zone by
Helicopter Group/CAS-011 - CAS in a Zone by Helicopter Group.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-111 - Multiple CAS in
1 Radius Zone by Helicopter and AirPlane Groups/CAS-111 - Multiple CAS
in 1 Radius Zone by Helicopter and AirPlane Groups.miz
#	Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol
Zones/PAT-001 - Switching Patrol Zones.miz
2017-03-12 17:51:18 +01:00
FlightControl
052ca384a5 Progress 2017-03-12 17:48:19 +01:00
FlightControl
82f505ddb0 Progress
-- Got DETECTION_TYPES running with A2G_TASK_DISPATCHER
2017-03-12 17:14:00 +01:00
Sven Van de Velde
c53b3cd1e0 Merge pull request #303 from FlightControl-Master/master-fix-ai-cap
Fixes bug sending messages upon a Destroy event
2017-03-12 07:21:46 +01:00
FlightControl
e4fec6432d Fixes bug sending messages upon a Destroy event
-- Removed the Messages from the Destroy event handler.
-- AI_CAP_ZONE never got a Destroy event trigger because the Dead event
was never catched.
-- The Dead event handlers are now the default name to keep up with the
standard.
-- Check that ONLY the Destroy event is triggered for the targets in
scope.
2017-03-12 07:20:01 +01:00
FlightControl
e9a7898410 Updates on presentation 2017-03-11 09:22:03 +01:00
FlightControl
8add761982 Updated documentation 2017-03-10 23:05:02 +01:00
FlightControl
d70d13449d Regression Testing 2017-03-10 22:40:16 +01:00
FlightControl
b606041c11 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl 2017-03-10 20:45:06 +01:00
FlightControl
7ebf0cdb0f Updates 2017-03-10 14:50:14 +01:00
Sven Van de Velde
5e25851f36 Merge pull request #301 from FlightControl-Master/Logo
Logo
2017-03-10 14:13:04 +01:00
FlightControl
4100000edf New avatars etc 2017-03-10 14:12:17 +01:00
FlightControl
801d6a6f30 Merge remote-tracking branch 'refs/remotes/origin/master' into Logo 2017-03-10 14:11:11 +01:00
FlightControl
cfc4dd8846 Progress 2017-03-10 14:09:15 +01:00
FlightControl
907b9c9abb Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose.lua
2017-03-10 06:23:51 +01:00
EasyEB
5b18773f6c Merge pull request #300 from FlightControl-Master/Logo
MOOSE Brand
2017-03-09 21:16:51 +01:00
EasyEB
fb3f6149c7 Add files via upload 2017-03-09 21:11:06 +01:00
FlightControl
df96c55c5a Logo placeholder 2017-03-09 20:53:28 +01:00
FlightControl
01e2aa5b5d Progress 2017-03-09 20:47:34 +01:00
dwpenney
958d97ad9d Merge pull request #299 from FlightControl-Master/Issue-292
Issue 292
2017-03-09 13:23:23 -04:00
FlightControl
3bd0cdbe32 Progress 2017-03-09 17:44:56 +01:00
David Penney
20239a1248 Update the static Moose w/ the component changes 2017-03-09 12:02:09 -04:00
David Penney
57099ad136 A random fix for code I notices
This relates to the Vec2/Vec3 redefinition of y. Vec3 is (x=Latitude, y=Altitude and z=Longitude). Vec2 is (x=Latitude, y=Longitude).
2017-03-09 11:49:20 -04:00
David Penney
29148cf8fd But fix for Issue-292
By accessing the values directly, we skip past the problem where GetY returns different values for POINT_VEC2 and POINT_VEC3 objects.
2017-03-09 11:47:40 -04:00
David Penney
670768df42 Addition of GetLat, GetLon, SetLat, SetLon for POINT_VEC2
This should help clarify the difference between Vec2 and Vec3. The original GetX, Gety, SetX and SetY functions remain so that it does not break other peoples stuff.
2017-03-09 11:46:31 -04:00
FlightControl
fbae55b9f9 Progress on tasking 2017-03-09 13:37:13 +01:00
FlightControl
40884cd411 removed trash 2017-03-09 10:39:20 +01:00
FlightControl
5d6ac9419f Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Development/Moose/Core/Event.lua
#	Moose Development/Moose/Functional/Scoring.lua
#	Moose Development/Moose/Wrapper/Controllable.lua
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/EVT - Event Handling/EVT-100 - OnEventShot
Example/EVT-100 - OnEventShot Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-101 - OnEventHit
Example/EVT-101 - OnEventHit Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-102 - OnEventTakeoff
Example/EVT-102 - OnEventTakeoff Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-103 - OnEventLand
Example/EVT-103 - OnEventLand Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-104 - OnEventCrash
Example/EVT-104 - OnEventCrash Example.miz
#	Moose Test Missions/SCO - Scoring/SCO-100 - Scoring of Statics/SCO-100
- Scoring of Statics.miz
#	Moose Test Missions/SCO - Scoring/SCO-101 - Scoring Client to
Client/SCO-101 - Scoring Client to Client.miz
#	docs/Documentation/Controllable.html
#	docs/Documentation/Event.html
#	docs/Documentation/Point.html
#	docs/Documentation/Zone.html
2017-03-09 10:38:55 +01:00
Sven Van de Velde
d16b68e03a Merge pull request #298 from FlightControl-Master/master-bugfix
fixes of base and scoring
2017-03-08 21:41:04 +01:00
FlightControl
95b091c5d0 static moose 2017-03-08 21:40:02 +01:00
FlightControl
1c3e737d8e Bugfixes of BASE and SCORING 2017-03-08 21:39:41 +01:00
Sven Van de Velde
891ecf996c Merge pull request #297 from FlightControl-Master/master-bugfix
Events with initiator and target will now properly be handled for UNIT and GROUP level event handlers.
2017-03-08 20:50:48 +01:00
FlightControl
c6ad706c1e Fixed a potential glitch.
Now target will ALWAYS be tested too.
2017-03-08 20:49:19 +01:00
FlightControl
894854440b Test mission to test HIT event handling of target units 2017-03-08 20:37:18 +01:00
FlightControl
9354e23630 Fix to also handle events for UNIT and GROUP when the target is in the event data.
The target was never checked, and thus in a HIT event, a HIT event was
never called. This is fixed now.
2017-03-08 20:02:03 +01:00
FlightControl
bcb68e2d64 Merge remote-tracking branch 'refs/remotes/origin/master' into master-bugfix 2017-03-08 19:40:35 +01:00
Sven Van de Velde
7c38bbce2d Merge pull request #296 from FlightControl-Master/developer-configuration
Developer configuration
2017-03-08 19:38:43 +01:00
FlightControl
43848e8dc7 New launch files 2017-03-08 19:25:30 +01:00
FlightControl
9fee299e0f Updates 2017-03-08 14:00:43 +01:00
FlightControl
28f81990f5 Eclipse share configuration files 2017-03-08 13:44:07 +01:00
Sven Van de Velde
3077631bb4 Merge pull request #295 from FlightControl-Master/Grey-Echo
Test of Permissions
2017-03-08 13:42:06 +01:00
Grey_Echo
fc03ba4661 Test of Permissions 2017-03-08 13:33:13 +01:00
Sven Van de Velde
1bdacbdad9 Merge pull request #291 from FlightControl-Master/master-bugfix
Documentation refinement of Core Classes
2017-03-07 21:00:46 +01:00
FlightControl
0bfbf042b5 Documentation refinement of Core Classes 2017-03-07 20:58:53 +01:00
Sven Van de Velde
343de7fe69 Merge pull request #290 from FlightControl-Master/master-bugfix
Fix problem with AttackControllable as a result of a stupid rename problem.
2017-03-07 12:03:29 +01:00
FlightControl
f708d3d33d Fix problem with AttackControllable as a result of a stupid rename problem. 2017-03-07 12:02:58 +01:00
Sven Van de Velde
f4c2637d66 Merge pull request #289 from FlightControl-Master/master-bugfix
Fixed Client to Client SCORING problem.
The TargetPlayerName was not logged in the CSV file. This is now also added. So, now, both the PlayerName and the Target PlayerName will be logged in the CSV. So when Client to Client kills happen, both player names will be listed.
Nice for statistics.
2017-03-07 10:29:53 +01:00
FlightControl
e84c9cc83b Fixed a problem that the TargetPlayerName was not logged in the CSV.
I adapted the CSV file, and added as the second parameter the
TargetPlayerName.
Where relevant, the TargetPlayerName will be mentioned in the CSV
logging.
IMPORTANT, the method SCORING:ScoreCSV has been adapted!!! The second
parameter is now the TargetPlayerName. Provide a "" or nil, if there is
no TargetPlayerName, but ensure the order of the parameters is correct!

function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType,
ScoreTimes, ScoreAmount, PlayerUnitName, PlayerUnitCoalition,
PlayerUnitCategory, PlayerUnitType, TargetUnitName, TargetUnitCoalition,
TargetUnitCategory, TargetUnitType )
2017-03-07 10:27:59 +01:00
FlightControl
2f7bcbe7c6 Merge remote-tracking branch 'refs/remotes/origin/master' into master-bugfix 2017-03-07 09:57:41 +01:00
Sven Van de Velde
ad90a08ec0 Merge pull request #288 from FlightControl-Master/master-adding
Master Bugfix
2017-03-07 09:44:00 +01:00
FlightControl
ef6885b63b Updated mission naming, documentation, briefing and tested all 2017-03-07 09:38:20 +01:00
FlightControl
02c44c158f Updated mission briefing 2017-03-07 09:26:25 +01:00
FlightControl
8dc13f7a0c Finalization of patch. 2017-03-07 09:24:10 +01:00
FlightControl
af85399975 Implemented event dispatching for GROUP
-- Created EVT-200 test mission
-- Documentation
2017-03-07 09:15:44 +01:00
FlightControl
ef67c82c0f AI_PATROL_ZONE
Added a Stop event and Stopped state to trigger a state transition from
* to Stopped when the AI process needs to be stopped.
2017-03-07 08:31:18 +01:00
FlightControl
e6db83047f Merge remote-tracking branch 'refs/remotes/origin/master' into master-adding 2017-03-07 08:27:35 +01:00
Sven Van de Velde
3a847fed9b Merge pull request #285 from FlightControl-Master/master-bugfix
New test mission to test OnEventHit for a SET_UNIT...
2017-03-06 16:38:36 +01:00
FlightControl
ef536022cc Removed smoke from AI_CAS 2017-03-06 16:32:14 +01:00
FlightControl
4b008f8879 New test mission demonstrating OnEventHit for a SET_UNIT object 2017-03-06 16:31:06 +01:00
FlightControl
454d96d4af Merge remote-tracking branch 'refs/remotes/origin/master' into master-bugfix 2017-03-06 15:44:37 +01:00
FlightControl
a2f4ce1db5 Updates on missions 2017-03-06 14:34:34 +01:00
FlightControl
25bd0f8049 Fixed DETECTION_AREAS, working again and complete with test missions. 2017-03-06 13:56:34 +01:00
FlightControl
8d73df48ce Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/SCO - Scoring/SCO-100 - Scoring of Statics/SCO-100
- Scoring of Statics.miz
#	Moose Test Missions/SCO - Scoring/SCO-101 - Scoring Client to
Client/SCO-101 - Scoring Client to Client.miz
#	docs/Documentation/Point.html
2017-03-06 12:28:27 +01:00
Sven Van de Velde
e6fcc15965 Merge pull request #284 from FlightControl-Master/master-adding
Renamed TaskRouteToVec2 and TaskRouteToVec3
2017-03-06 11:44:18 +01:00
FlightControl
9d0f264d5c Point optmized. 2017-03-06 11:43:13 +01:00
FlightControl
6f3e076f13 Merge remote-tracking branch 'refs/remotes/origin/master' into master-adding 2017-03-06 10:38:47 +01:00
FlightControl
0315bf5aa0 Fixed test mission 2017-03-05 14:52:12 +01:00
FlightControl
2cf27b3b0f SCO-500 Demo Mission for SCORING system demonstration on a MP server 2017-03-05 14:37:18 +01:00
FlightControl
a6c596f724 Check scoring test mission in master. 2017-03-05 14:23:13 +01:00
FlightControl
32d6233cf1 Progress Dispatcher 2017-03-05 12:37:56 +01:00
FlightControl
6710bfba26 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
2017-03-05 10:28:54 +01:00
FlightControl
fc3b66c06c Removed trace from Zone.lua 2017-03-05 10:27:54 +01:00
FlightControl
b004f0f968 Removed trace 2017-03-05 10:27:29 +01:00
FlightControl
86e684dc63 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
2017-03-05 10:26:36 +01:00
FlightControl
56c9401ce3 Merge remote-tracking branch 'refs/remotes/origin/master' into master-bugfix 2017-03-05 10:15:27 +01:00
FlightControl
3244f46e88 Moose.lua with the changes 2017-03-05 10:14:53 +01:00
FlightControl
b4527635d6 Progress 2017-03-05 10:14:29 +01:00
FlightControl
a1ae1cc519 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl 2017-03-05 10:05:36 +01:00
FlightControl
538e040fdf Updated Database 2017-03-05 10:05:12 +01:00
FlightControl
61cd592967 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl 2017-03-05 10:02:28 +01:00
Sven Van de Velde
158e41e04e Merge pull request #279 from FlightControl-Master/master-bugfix
Master bugfix
2017-03-05 10:01:58 +01:00
FlightControl
0d474b2286 Updated Database 2017-03-05 10:01:28 +01:00
FlightControl
79657efaf8 Merge remote-tracking branch 'refs/remotes/origin/master' into master-bugfix 2017-03-05 09:54:43 +01:00
FlightControl
8905a49d0c Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
2017-03-05 09:52:13 +01:00
Sven Van de Velde
48841f2412 Merge pull request #278 from FlightControl-Master/master-bugfix
Master bugfix
2017-03-05 09:51:01 +01:00
FlightControl
0ebff60e8d Updated Set 2017-03-05 09:50:31 +01:00
FlightControl
5c5bedd794 Merge remote-tracking branch 'refs/remotes/origin/master' into master-bugfix 2017-03-05 09:46:00 +01:00
FlightControl
21c2dd8c80 Progress 2017-03-05 09:45:49 +01:00
FlightControl
de84accffa Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
2017-03-05 09:37:06 +01:00
Sven Van de Velde
91bc509984 Merge pull request #277 from FlightControl-Master/master-adding
Zone boundaries by tires with a white flag.
2017-03-05 09:33:21 +01:00
FlightControl
f7bf997511 Implemented a new method on ZONE:BoundZone
Creates a visual boundary around a ZONE_* of tires with a white flag.
These tires will also move when the ZONE is "rebound".
2017-03-05 09:32:17 +01:00
FlightControl
5793e04aeb Merge remote-tracking branch 'refs/remotes/origin/master' into master-adding 2017-03-05 07:46:09 +01:00
FlightControl
cd3648f03d Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Development/Moose/Functional/Scoring.lua
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 -
Caucasus.miz
#	Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 -
Nevada.miz
#	Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase
CleanUp/ACL-001 - Airbase CleanUp.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 -
Spawned AI.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 -
Patrol AI.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions
InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when
Destroyed/AIB-004 - Respawn Test when Destroyed.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and
Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at
Airbases/AIB-006 - Declutter AI at Airbases.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air
Patrol/CAP-001 - Combat Air Patrol.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage
within Range/CAP-010 - CAP and Engage within Range.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-011 - CAP and Engage
within Zone/CAP-011 - CAP and Engage within Zone.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a Zone by
Airplane Group/CAS-001 - CAS in a ZONE-ME Test.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a Zone by
Airplane Group/CAS-001 - CAS in a Zone by Airplane Group.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-002 - CAS in a Zone by
Airplane Group - Engage with Speed/CAS-002 - CAS in a Zone by Airplane
Group - Engage with Speed.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-003 - CAS in a Zone by
Airplane Group - Engage with Speed and Altitude/CAS-003 - CAS in a Zone
by Airplane Group - Engage with Speed and Altitude.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-010 - CAS in a Zone by
Helicopter/CAS-010 - CAS in a Zone by Helicopter.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-011 - CAS in a Zone by
Helicopter Group/CAS-011 - CAS in a Zone by Helicopter Group.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-111 - Multiple CAS in
1 Radius Zone by Helicopter and AirPlane Groups/CAS-111 - Multiple CAS
in 1 Radius Zone by Helicopter and AirPlane Groups.miz
#	Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit
Boarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 -
Unit Unboarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 -
Unit Transferring.miz
#	Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 -
Group Boarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 -
Group Unboarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 -
Group Transferring.miz
#	Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 -
Package Boarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 -
Package Unboarding.miz
#	Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001
- Detection Areas.miz
#	Moose Test Missions/DET - Detection/DET-101 - Detection
Reporting/DET-101 - Detection Reporting.miz
#	Moose Test Missions/ESC - Escorting/ESC-001 - Escorting
Helicopters/ESC-001 - Escorting Helicopters.miz
#	Moose Test Missions/EVT - Event Handling/EVT-001 - API Demo 1/EVT-001
- API Demo 1.miz
#	Moose Test Missions/EVT - Event Handling/EVT-100 - OnEventShot
Example/EVT-100 - OnEventShot Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-101 - OnEventHit
Example/EVT-101 - OnEventHit Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-102 - OnEventTakeoff
Example/EVT-102 - OnEventTakeoff Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-103 - OnEventLand
Example/EVT-103 - OnEventLand Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-104 - OnEventCrash
Example/EVT-104 - OnEventCrash Example.miz
#	Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition
Explanation/FSM-100 - Transition Explanation.miz
#	Moose Test Missions/GRP - Group Commands/GRP-200 - Follow
Group/GRP-200 - Follow Group.miz
#	Moose Test Missions/GRP - Group Commands/GRP-300 - Switch
WayPoints/GRP-300 - Switch WayPoints.miz
#	Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz
#	Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 -
Menu Client.miz
#	Moose Test Missions/MEN - Menu Options/MEN-002 - Menu
Coalition/MEN-002 - Menu Coalition.miz
#	Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 -
Menu Group.miz
#	Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile
Trainer/MIT-001 - Missile Trainer.miz
#	Moose Test Missions/MOOSE_Test_Template.miz
#	Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol
Zones/PAT-001 - Switching Patrol Zones.miz
#	Moose Test Missions/SCH - Scheduler/SCH-000 - Simple
Scheduling/SCH-000 - Simple Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object
Scheduling/SCH-001 - Simple Object Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat
Scheduling/SCH-100 - Simple Repeat Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat
Scheduling/SCH-110 - Object Repeat Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling
Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz
#	Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object
Scheduling/SCH-300 - GC Simple Object Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat
Scheduling/SCH-310 - GC Object Repeat Scheduling.miz
#	Moose Test Missions/SCO - Scoring/SCO-100 - Scoring of Statics/SCO-100
- Scoring of Statics.miz
#	Moose Test Missions/SCO - Scoring/SCO-101 - Scoring Client to
Client/SCO-101 - Scoring Client to Client.miz
#	Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 -
Airbase Sets.miz
#	Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 -
Group Sets.miz
#	Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 -
Client Sets.miz
#	Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001
- SEAD Evasion.miz
#	Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 -
Spawn Demo.miz
#	Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple
Spawning/SPA-011 - Ground Ops - Simple Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple
Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz
#	Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled
Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz
#	Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled
Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz
#	Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize
Route/SPA-015 - Ground Ops - Randomize Route.miz
#	Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize
Zones/SPA-016 - Ground Ops - Randomize Zones.miz
#	Moose Test Missions/SPA - Spawning/SPA-017 - Ground Ops - Set AI
inactive while spawning/SPA-017 - Ground Ops - Set AI inactive while
spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-018 - Ground Ops - Randomize
Templates/SPA-018 - Ground Ops - Randomize Templates.miz
#	Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive
Units/SPA-100 - CleanUp Inactive Units.miz
#	Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 -
Limit Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-121 - Air Ops - Scheduled
Spawns with Repeat on Landing with Limit/SPA-121 - Air Ops - Scheduled
Spawns with Repeat on Landing with Limit.miz
#	Moose Test Missions/SPA - Spawning/SPA-130 - Uncontrolled
Spawning/SPA-130 - Uncontrolled Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit
Types/SPA-200 - Randomize Unit Types.miz
#	Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 -
Randomize Zones.miz
#	Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static
position/SPA-310 - Spawn at Static position.miz
#	Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit
position/SPA-320 - Spawn at Unit position.miz
#	Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2
position/SPA-330 - Spawn at Vec2 position.miz
#	Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3
position/SPA-340 - Spawn at Vec3 position.miz
#	Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching
Demo/TAD-010 - Task Dispatching Demo.miz
#	Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling -
SEAD/TSK-010 - Task Modelling - SEAD.miz
#	Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling -
Pickup/TSK-020 - Task Modelling - Pickup.miz
#	Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 -
Polygon Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-510 - Send message if Clients fly
the first time in the Polygon Zones/ZON-510 - Send message if Clients
fly the first time in the Polygon Zones.miz
2017-03-05 07:45:08 +01:00
FlightControl
32e52731ae Detection Progress 2017-03-05 07:35:03 +01:00
FlightControl
b46d61d865 Got Task_SEAD template working with all the variations and complexity! 2017-03-04 08:51:31 +01:00
FlightControl
5ddeb8d396 Progress on SEAD 2017-03-03 12:34:52 +01:00
FlightControl
22fdf034ee Progress on SEAD 2017-03-03 10:49:38 +01:00
FlightControl
a99924d9ed Progress on SEAD model 2017-03-03 10:27:09 +01:00
FlightControl
846edca815 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 -
Spawn Demo.miz
#	Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple
Spawning/SPA-011 - Ground Ops - Simple Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple
Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz
#	Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled
Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz
#	Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled
Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz
#	Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize
Route/SPA-015 - Ground Ops - Randomize Route.miz
#	Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize
Zones/SPA-016 - Ground Ops - Randomize Zones.miz
#	Moose Test Missions/SPA - Spawning/SPA-017 - Ground Ops - Set AI
inactive while spawning/SPA-017 - Ground Ops - Set AI inactive while
spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-018 - Ground Ops - Randomize
Templates/SPA-018 - Ground Ops - Randomize Templates.miz
#	Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive
Units/SPA-100 - CleanUp Inactive Units.miz
#	Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 -
Limit Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-121 - Air Ops - Scheduled
Spawns with Repeat on Landing with Limit/SPA-121 - Air Ops - Scheduled
Spawns with Repeat on Landing with Limit.miz
#	Moose Test Missions/SPA - Spawning/SPA-130 - Uncontrolled
Spawning/SPA-130 - Uncontrolled Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit
Types/SPA-200 - Randomize Unit Types.miz
#	Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 -
Randomize Zones.miz
#	Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static
position/SPA-310 - Spawn at Static position.miz
#	Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit
position/SPA-320 - Spawn at Unit position.miz
#	Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2
position/SPA-330 - Spawn at Vec2 position.miz
#	Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3
position/SPA-340 - Spawn at Vec3 position.miz
#	Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal
Zone.miz
#	docs/Documentation/Zone.html
2017-03-03 09:51:17 +01:00
FlightControl
41eb39c2a5 Task Templates 2017-02-26 13:30:29 +01:00
Sven Van de Velde
a3aee1e154 Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 -
Polygon Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-510 - Send message if Clients fly
the first time in the Polygon Zones/ZON-510 - Send message if Clients
fly the first time in the Polygon Zones.miz
2017-02-24 10:37:48 +01:00
Sven Van de Velde
8c4a6e2301 Progress 2017-02-21 11:09:40 +01:00
Sven Van de Velde
6d3a2b0f52 Progress 2017-02-20 14:43:55 +01:00
Sven Van de Velde
e56e81ee57 Progress SEAD Tasking 2017-02-20 14:38:50 +01:00
FlightControl
e243ff32fa Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Development/Moose/Core/Zone.lua
#	Moose Development/ReleaseNotes.txt
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 -
Polygon Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-510 - Send message if Clients fly
the first time in the Polygon Zones/ZON-510 - Send message if Clients
fly the first time in the Polygon Zones.miz
#	docs/Documentation/Zone.html
2017-02-19 13:43:44 +01:00
FlightControl
4ff9766690 Analysis of TASK_SEAD 2017-02-19 13:32:43 +01:00
FlightControl
f9708de598 Progress 2017-02-18 19:51:20 +01:00
FlightControl
5c090b108c Merge remote-tracking branch 'refs/remotes/origin/master' into FlightControl
# Conflicts:
#	Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
#	Moose Mission Setup/Moose.lua
#	Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 -
Caucasus.miz
#	Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 -
Nevada.miz
#	Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase
CleanUp/ACL-001 - Airbase CleanUp.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 -
Spawned AI.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 -
Patrol AI.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions
InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when
Destroyed/AIB-004 - Respawn Test when Destroyed.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and
Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz
#	Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at
Airbases/AIB-006 - Declutter AI at Airbases.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air
Patrol/CAP-001 - Combat Air Patrol.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage
within Range/CAP-010 - CAP and Engage within Range.miz
#	Moose Test Missions/CAP - Combat Air Patrol/CAP-011 - CAP and Engage
within Zone/CAP-011 - CAP and Engage within Zone.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a Zone by
Airplane Group/CAS-001 - CAS in a ZONE-ME Test.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a Zone by
Airplane Group/CAS-001 - CAS in a Zone by Airplane Group.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-002 - CAS in a Zone by
Airplane Group - Engage with Speed/CAS-002 - CAS in a Zone by Airplane
Group - Engage with Speed.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-003 - CAS in a Zone by
Airplane Group - Engage with Speed and Altitude/CAS-003 - CAS in a Zone
by Airplane Group - Engage with Speed and Altitude.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-010 - CAS in a Zone by
Helicopter/CAS-010 - CAS in a Zone by Helicopter.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-011 - CAS in a Zone by
Helicopter Group/CAS-011 - CAS in a Zone by Helicopter Group.miz
#	Moose Test Missions/CAS - Close Air Support/CAS-111 - Multiple CAS in
1 Radius Zone by Helicopter and AirPlane Groups/CAS-111 - Multiple CAS
in 1 Radius Zone by Helicopter and AirPlane Groups.miz
#	Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit
Boarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 -
Unit Unboarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 -
Unit Transferring.miz
#	Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 -
Group Boarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 -
Group Unboarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 -
Group Transferring.miz
#	Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 -
Package Boarding.miz
#	Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 -
Package Unboarding.miz
#	Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001
- Detection Areas.miz
#	Moose Test Missions/DET - Detection/DET-101 - Detection
Reporting/DET-101 - Detection Reporting.miz
#	Moose Test Missions/ESC - Escorting/ESC-001 - Escorting
Helicopters/ESC-001 - Escorting Helicopters.miz
#	Moose Test Missions/EVT - Event Handling/EVT-001 - API Demo 1/EVT-001
- API Demo 1.miz
#	Moose Test Missions/EVT - Event Handling/EVT-100 - OnEventShot
Example/EVT-100 - OnEventShot Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-101 - OnEventHit
Example/EVT-101 - OnEventHit Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-102 - OnEventTakeoff
Example/EVT-102 - OnEventTakeoff Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-103 - OnEventLand
Example/EVT-103 - OnEventLand Example.miz
#	Moose Test Missions/EVT - Event Handling/EVT-104 - OnEventCrash
Example/EVT-104 - OnEventCrash Example.miz
#	Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition
Explanation/FSM-100 - Transition Explanation.miz
#	Moose Test Missions/GRP - Group Commands/GRP-200 - Follow
Group/GRP-200 - Follow Group.miz
#	Moose Test Missions/GRP - Group Commands/GRP-300 - Switch
WayPoints/GRP-300 - Switch WayPoints.miz
#	Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz
#	Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 -
Menu Client.miz
#	Moose Test Missions/MEN - Menu Options/MEN-002 - Menu
Coalition/MEN-002 - Menu Coalition.miz
#	Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 -
Menu Group.miz
#	Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile
Trainer/MIT-001 - Missile Trainer.miz
#	Moose Test Missions/MOOSE_Test_Template.miz
#	Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol
Zones/PAT-001 - Switching Patrol Zones.miz
#	Moose Test Missions/SCH - Scheduler/SCH-000 - Simple
Scheduling/SCH-000 - Simple Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object
Scheduling/SCH-001 - Simple Object Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat
Scheduling/SCH-100 - Simple Repeat Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat
Scheduling/SCH-110 - Object Repeat Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling
Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz
#	Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object
Scheduling/SCH-300 - GC Simple Object Scheduling.miz
#	Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat
Scheduling/SCH-310 - GC Object Repeat Scheduling.miz
#	Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 -
Airbase Sets.miz
#	Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 -
Group Sets.miz
#	Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 -
Client Sets.miz
#	Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001
- SEAD Evasion.miz
#	Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 -
Spawn Demo.miz
#	Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple
Spawning/SPA-011 - Ground Ops - Simple Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple
Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz
#	Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled
Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz
#	Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled
Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz
#	Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize
Route/SPA-015 - Ground Ops - Randomize Route.miz
#	Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize
Zones/SPA-016 - Ground Ops - Randomize Zones.miz
#	Moose Test Missions/SPA - Spawning/SPA-017 - Ground Ops - Set AI
inactive while spawning/SPA-017 - Ground Ops - Set AI inactive while
spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-018 - Ground Ops - Randomize
Templates/SPA-018 - Ground Ops - Randomize Templates.miz
#	Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive
Units/SPA-100 - CleanUp Inactive Units.miz
#	Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 -
Limit Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 -
Repeat Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-121 - Air Ops - Scheduled
Spawns with Repeat on Landing with Limit/SPA-121 - Air Ops - Scheduled
Spawns with Repeat on Landing with Limit.miz
#	Moose Test Missions/SPA - Spawning/SPA-130 - Uncontrolled
Spawning/SPA-130 - Uncontrolled Spawning.miz
#	Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit
Types/SPA-200 - Randomize Unit Types.miz
#	Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 -
Randomize Zones.miz
#	Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static
position/SPA-310 - Spawn at Static position.miz
#	Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit
position/SPA-320 - Spawn at Unit position.miz
#	Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2
position/SPA-330 - Spawn at Vec2 position.miz
#	Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3
position/SPA-340 - Spawn at Vec3 position.miz
#	Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching
Demo/TAD-010 - Task Dispatching Demo.miz
#	Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling -
SEAD/TSK-010 - Task Modelling - SEAD.miz
#	Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling -
Pickup/TSK-020 - Task Modelling - Pickup.miz
#	Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius
Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 -
Polygon Zone.miz
#	Moose Test Missions/ZON - Zones/ZON-510 - Send message if Clients fly
the first time in the Polygon Zones/ZON-510 - Send message if Clients
fly the first time in the Polygon Zones.miz
2017-02-15 17:44:34 +01:00
FlightControl
62b668029b Updates 2017-02-14 08:49:59 +01:00
FlightControl
a47195198e Fixes and framework stabilization 2017-02-08 22:40:26 +01:00
342 changed files with 24986 additions and 13349 deletions

3
.gitignore vendored
View File

@@ -19,8 +19,6 @@ local.properties
# External tool builders # External tool builders
.externalToolBuilders/ .externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific # CDT-specific
.cproject .cproject
@@ -224,3 +222,4 @@ _gsdata_/
#GITHUB #GITHUB
.gitattributes .gitattributes
.gitignore .gitignore
Moose Test Missions/MOOSE_Test_Template.miz

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\Program Files\lua\5.1\bin\luadocumentor.bat"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;Moose\Core\*.lua&quot; &quot;Moose\Wrapper\*.lua&quot; &quot;Moose\Actions\*.lua&quot; &quot;Moose\Functional\*.lua&quot; &quot;Moose\Tasking\*.lua&quot; &quot;Moose\Utilities\*.lua&quot; &quot;Moose\AI\*.lua&quot; --dir &quot;${project_loc:}/docs/Documentation&quot; --style &quot;${project_loc:}/docs/Stylesheet/stylesheet.css&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc:}/Moose Development"/>
</launchConfiguration>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc:}/Moose Mission Setup\Moose_Create.bat"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;${project_loc:}/Moose Development&quot; &quot;${current_date}&quot; &quot;${project_loc:}/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT&quot; &quot;D&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc:}/Moose Mission Setup"/>
</launchConfiguration>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc:}/Moose Mission Setup\Moose_Create.bat"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;${project_loc:}/Moose Development/Moose&quot; &quot;${current_date}&quot; &quot;${project_loc:}/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT&quot; &quot;S&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc:}/Moose Mission Setup"/>
</launchConfiguration>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc:}/Moose Mission Setup/Moose Mission Update\Moose_Update_Missions.bat"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;${project_loc:}/Moose Test Missions&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc:}/Moose Mission Setup/Moose Mission Update"/>
</launchConfiguration>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc:}/Moose Mission Setup/Moose Mission Update\Moose_Update_Missions.bat"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;${selected_resource_loc}&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc:}/Moose Mission Setup/Moose Mission Update"/>
</launchConfiguration>

Binary file not shown.

View File

@@ -54,12 +54,15 @@
-- --
-- ### 1.2.2) AI_CAP_ZONE Events -- ### 1.2.2) AI_CAP_ZONE Events
-- --
-- * **Start** ( Group ): Start the process. -- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. -- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
-- * **Engage** ( Group ): Let the AI engage the bogeys. -- * **@{#AI_CAP_ZONE.Engage}**: Let the AI engage the bogeys.
-- * **RTB** ( Group ): Route the AI to the home base. -- * **@{#AI_CAP_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
-- * **Detect** ( Group ): The AI is detecting targets. -- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
-- * **Detected** ( Group ): The AI has detected new targets. -- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
-- * **@{#AI_CAP_ZONE.Destroy}**: The AI has destroyed a bogey @{Unit}.
-- * **@{#AI_CAP_ZONE.Destroyed}**: The AI has destroyed all bogeys @{Unit}s assigned in the CAS task.
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
-- --
-- ## 1.3) Set the Range of Engagement -- ## 1.3) Set the Range of Engagement
@@ -340,9 +343,12 @@ function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To )
-- Call the parent Start event handler -- Call the parent Start event handler
self:GetParent(self).onafterStart( self, Controllable, From, Event, To ) self:GetParent(self).onafterStart( self, Controllable, From, Event, To )
self:HandleEvent( EVENTS.Dead )
end end
-- todo: need to fix this global function
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable --- @param Wrapper.Controllable#CONTROLLABLE AIControllable
function _NewEngageCapRoute( AIControllable ) function _NewEngageCapRoute( AIControllable )
@@ -392,6 +398,18 @@ function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To )
end end
--- @param #AI_CAP_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_CAP_ZONE:onafterAbort( Controllable, From, Event, To )
Controllable:ClearTasks()
self:__Route( 1 )
end
--- @param #AI_CAP_ZONE self --- @param #AI_CAP_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
@@ -505,14 +523,9 @@ end
-- @param #string From The From State string. -- @param #string From The From State string.
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param Core.Event#EVENTDATA EventData function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To )
function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData ) self.Accomplished = true
self:SetDetectionOff()
if EventData.IniUnit then
self.DetectedUnits[EventData.IniUnit] = nil
end
Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
end end
--- @param #AI_CAP_ZONE self --- @param #AI_CAP_ZONE self
@@ -520,9 +533,22 @@ end
-- @param #string From The From State string. -- @param #string From The From State string.
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To ) -- @param Core.Event#EVENTDATA EventData
self.Accomplished = true function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
self:SetDetectionOff()
if EventData.IniUnit then
self.DetectedUnits[EventData.IniUnit] = nil
end
end end
--- @param #AI_CAP_ZONE self
-- @param Core.Event#EVENTDATA EventData
function AI_CAP_ZONE:OnEventDead( EventData )
self:F( { "EventDead", EventData } )
if EventData.IniDCSUnit then
if self.DetectedUnits and self.DetectedUnits[EventData.IniUnit] then
self:__Destroy( 1, EventData )
end
end
end

View File

@@ -80,13 +80,16 @@
-- --
-- ### 1.2.2) AI_CAS_ZONE Events -- ### 1.2.2) AI_CAS_ZONE Events
-- --
-- * **Start** ( Group ): Start the process. -- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. -- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
-- * **Engage** ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds. -- * **@{#AI_CAS_ZONE.Engage}**: Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.
-- * **RTB** ( Group ): Route the AI to the home base. -- * **@{#AI_CAS_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
-- * **Detect** ( Group ): The AI is detecting targets. -- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
-- * **Detected** ( Group ): The AI has detected new targets. -- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
-- * **@{#AI_CAS_ZONE.Destroy}**: The AI has destroyed a target @{Unit}.
-- * **@{#AI_CAS_ZONE.Destroyed}**: The AI has destroyed all target @{Unit}s assigned in the CAS task.
-- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
-- --
-- ==== -- ====
-- --
@@ -158,11 +161,6 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
-- @param #string From The From State string. -- @param #string From The From State string.
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @return #boolean Return false to cancel Transition. -- @return #boolean Return false to cancel Transition.
@@ -173,20 +171,29 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
-- @param #string From The From State string. -- @param #string From The From State string.
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- Synchronous Event Trigger for Event Engage. --- Synchronous Event Trigger for Event Engage.
-- @function [parent=#AI_CAS_ZONE] Engage -- @function [parent=#AI_CAS_ZONE] Engage
-- @param #AI_CAS_ZONE self -- @param #AI_CAS_ZONE self
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
-- If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- Asynchronous Event Trigger for Event Engage. --- Asynchronous Event Trigger for Event Engage.
-- @function [parent=#AI_CAS_ZONE] __Engage -- @function [parent=#AI_CAS_ZONE] __Engage
-- @param #AI_CAS_ZONE self -- @param #AI_CAS_ZONE self
-- @param #number Delay The delay in seconds. -- @param #number Delay The delay in seconds.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
-- If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- OnLeave Transition Handler for State Engaging. --- OnLeave Transition Handler for State Engaging.
-- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging -- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging
@@ -350,7 +357,7 @@ function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To )
-- Call the parent Start event handler -- Call the parent Start event handler
self:GetParent(self).onafterStart( self, Controllable, From, Event, To ) self:GetParent(self).onafterStart( self, Controllable, From, Event, To )
self:HandleEvent( EVENTS.Dead, self.OnDead ) self:HandleEvent( EVENTS.Dead )
self:SetDetectionDeactivated() -- When not engaging, set the detection off. self:SetDetectionDeactivated() -- When not engaging, set the detection off.
end end
@@ -360,9 +367,10 @@ function _NewEngageRoute( AIControllable )
AIControllable:T( "NewEngageRoute" ) AIControllable:T( "NewEngageRoute" )
local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE
EngageZone:__Engage( 1 ) EngageZone:__Engage( 1, EngageZone.EngageSpeed, EngageZone.EngageAltitude, EngageZone.EngageWeaponExpend, EngageZone.EngageAttackQty, EngageZone.EngageDirection )
end end
--- @param #AI_CAS_ZONE self --- @param #AI_CAS_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string. -- @param #string From The From State string.
@@ -394,7 +402,7 @@ function AI_CAS_ZONE:onafterTarget( Controllable, From, Event, To )
if Detected == true then if Detected == true then
self:E( {"Target: ", DetectedUnit } ) self:E( {"Target: ", DetectedUnit } )
self.DetectedUnits[DetectedUnit] = false self.DetectedUnits[DetectedUnit] = false
local AttackTask = Controllable:EnRouteTaskEngageUnit( DetectedUnit, 1, true, self.EngageWeaponExpend, self.EngageAttackQty, self.EngageDirection, self.EngageAltitude, nil ) local AttackTask = Controllable:TaskAttackUnit( DetectedUnit, false, self.EngageWeaponExpend, self.EngageAttackQty, self.EngageDirection, self.EngageAltitude, nil )
self.Controllable:PushTask( AttackTask, 1 ) self.Controllable:PushTask( AttackTask, 1 )
end end
end end
@@ -409,6 +417,15 @@ function AI_CAS_ZONE:onafterTarget( Controllable, From, Event, To )
end end
--- @param #AI_CAS_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_CAS_ZONE:onafterAbort( Controllable, From, Event, To )
Controllable:ClearTasks()
self:__Route( 1 )
end
--- @param #AI_CAS_ZONE self --- @param #AI_CAS_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
@@ -416,12 +433,17 @@ end
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. -- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To, EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection ) function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
self:E("onafterEngage") EngageSpeed,
EngageAltitude,
EngageWeaponExpend,
EngageAttackQty,
EngageDirection )
self:F("onafterEngage")
self.EngageSpeed = EngageSpeed or 400 self.EngageSpeed = EngageSpeed or 400
self.EngageAltitude = EngageAltitude or 2000 self.EngageAltitude = EngageAltitude or 2000
@@ -452,28 +474,28 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To, EngageSpeed,
EngageRoute[#EngageRoute+1] = CurrentRoutePoint EngageRoute[#EngageRoute+1] = CurrentRoutePoint
if self.Controllable:IsNotInZone( self.EngageZone ) then -- if self.Controllable:IsNotInZone( self.EngageZone ) then
--
-- Find a random 2D point in EngageZone. -- -- Find a random 2D point in EngageZone.
local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2() -- local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2()
self:T2( ToEngageZoneVec2 ) -- self:T2( ToEngageZoneVec2 )
--
-- Obtain a 3D @{Point} from the 2D point + altitude. -- -- Obtain a 3D @{Point} from the 2D point + altitude.
local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, self.EngageAltitude, ToEngageZoneVec2.y ) -- local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, self.EngageAltitude, ToEngageZoneVec2.y )
--
-- Create a route point of type air. -- -- Create a route point of type air.
local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir( -- local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir(
self.PatrolAltType, -- self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint, -- POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint, -- POINT_VEC3.RoutePointAction.TurningPoint,
self.EngageSpeed, -- self.EngageSpeed,
true -- true
) -- )
--
EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint -- EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint
--
end -- end
--
--- Define a random point in the @{Zone}. The AI will fly to that point within the zone. --- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
--- Find a random 2D point in EngageZone. --- Find a random 2D point in EngageZone.
@@ -492,7 +514,7 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To, EngageSpeed,
true true
) )
ToTargetPointVec3:SmokeBlue() --ToTargetPointVec3:SmokeBlue()
EngageRoute[#EngageRoute+1] = ToTargetRoutePoint EngageRoute[#EngageRoute+1] = ToTargetRoutePoint
@@ -500,22 +522,27 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To, EngageSpeed,
Controllable:OptionROEOpenFire() Controllable:OptionROEOpenFire()
Controllable:OptionROTVertical() Controllable:OptionROTVertical()
-- local AttackTasks = {} local AttackTasks = {}
--
-- for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
-- local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
-- self:T( DetectedUnit ) self:T( DetectedUnit )
-- if DetectedUnit:IsAlive() then if DetectedUnit:IsAlive() then
-- if DetectedUnit:IsInZone( self.EngageZone ) then if DetectedUnit:IsInZone( self.EngageZone ) then
-- self:E( {"Engaging ", DetectedUnit } ) self:E( {"Engaging ", DetectedUnit } )
-- AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit,
-- end true,
-- else EngageWeaponExpend,
-- self.DetectedUnits[DetectedUnit] = nil EngageAttackQty,
-- end EngageDirection
-- end )
-- end
-- EngageRoute[1].task = Controllable:TaskCombo( AttackTasks ) else
self.DetectedUnits[DetectedUnit] = nil
end
end
EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
--- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
self.Controllable:WayPointInitialize( EngageRoute ) self.Controllable:WayPointInitialize( EngageRoute )
@@ -528,12 +555,24 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To, EngageSpeed,
--- NOW ROUTE THE GROUP! --- NOW ROUTE THE GROUP!
self.Controllable:WayPointExecute( 1 ) self.Controllable:WayPointExecute( 1 )
self:SetDetectionInterval( 10 ) self:SetDetectionInterval( 2 )
self:SetDetectionActivated() self:SetDetectionActivated()
self:__Target( -10 ) -- Start Targetting self:__Target( -2 ) -- Start Targetting
end end
end end
--- @param #AI_CAS_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
self.Accomplished = true
self:SetDetectionDeactivated()
end
--- @param #AI_CAS_ZONE self --- @param #AI_CAS_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string. -- @param #string From The From State string.
@@ -545,28 +584,19 @@ function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
if EventData.IniUnit then if EventData.IniUnit then
self.DetectedUnits[EventData.IniUnit] = nil self.DetectedUnits[EventData.IniUnit] = nil
end end
Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
end end
--- @param #AI_CAS_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
self.Accomplished = true
self:SetDetectionDeactivated()
end
--- @param #AI_CAS_ZONE self --- @param #AI_CAS_ZONE self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function AI_CAS_ZONE:OnDead( EventData ) function AI_CAS_ZONE:OnEventDead( EventData )
self:T( { "EventDead", EventData } ) self:F( { "EventDead", EventData } )
if EventData.IniDCSUnit then if EventData.IniDCSUnit then
if self.DetectedUnits and self.DetectedUnits[EventData.IniUnit] then
self:__Destroy( 1, EventData ) self:__Destroy( 1, EventData )
end end
end
end end

View File

@@ -50,11 +50,14 @@
-- --
-- * **None** ( Group ): The process is not started yet. -- * **None** ( Group ): The process is not started yet.
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. -- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
-- * **Returning** ( Group ): The AI is returning to Base.. -- * **Returning** ( Group ): The AI is returning to Base.
-- * **Stopped** ( Group ): The process is stopped.
-- * **Crashed** ( Group ): The AI has crashed or is dead.
-- --
-- ### 1.2.2) AI_PATROL_ZONE Events -- ### 1.2.2) AI_PATROL_ZONE Events
-- --
-- * **Start** ( Group ): Start the process. -- * **Start** ( Group ): Start the process.
-- * **Stop** ( Group ): Stop the process.
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. -- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
-- * **RTB** ( Group ): Route the AI to the home base. -- * **RTB** ( Group ): Route the AI to the home base.
-- * **Detect** ( Group ): The AI is detecting targets. -- * **Detect** ( Group ): The AI is detecting targets.
@@ -201,6 +204,51 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit
self:SetStartState( "None" ) self:SetStartState( "None" )
self:AddTransition( "*", "Stop", "Stopped" )
--- OnLeave Transition Handler for State Stopped.
-- @function [parent=#AI_PATROL_ZONE] OnLeaveStopped
-- @param #AI_PATROL_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Stopped.
-- @function [parent=#AI_PATROL_ZONE] OnEnterStopped
-- @param #AI_PATROL_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- OnBefore Transition Handler for Event Stop.
-- @function [parent=#AI_PATROL_ZONE] OnBeforeStop
-- @param #AI_PATROL_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Stop.
-- @function [parent=#AI_PATROL_ZONE] OnAfterStop
-- @param #AI_PATROL_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Stop.
-- @function [parent=#AI_PATROL_ZONE] Stop
-- @param #AI_PATROL_ZONE self
--- Asynchronous Event Trigger for Event Stop.
-- @function [parent=#AI_PATROL_ZONE] __Stop
-- @param #AI_PATROL_ZONE self
-- @param #number Delay The delay in seconds.
self:AddTransition( "None", "Start", "Patrolling" ) self:AddTransition( "None", "Start", "Patrolling" )
--- OnBefore Transition Handler for Event Start. --- OnBefore Transition Handler for Event Start.

View File

@@ -192,15 +192,6 @@ do -- ACT_ACCOUNT_DEADS
self.TaskName = FsmAccount.TaskName self.TaskName = FsmAccount.TaskName
end end
function ACT_ACCOUNT_DEADS:_Destructor()
self:E("_Destructor")
self:EventRemoveAll()
end
--- Process Events --- Process Events
--- StateMachine callback function --- StateMachine callback function
@@ -231,7 +222,6 @@ do -- ACT_ACCOUNT_DEADS
if self.TargetSetUnit:FindUnit( EventData.IniUnitName ) then if self.TargetSetUnit:FindUnit( EventData.IniUnitName ) then
local TaskGroup = ProcessUnit:GetGroup() local TaskGroup = ProcessUnit:GetGroup()
self.TargetSetUnit:RemoveUnitsByName( EventData.IniUnitName )
self:Message( "You hit a target. Your group with assigned " .. self.TaskName .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed." ) self:Message( "You hit a target. Your group with assigned " .. self.TaskName .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed." )
end end
end end
@@ -244,7 +234,7 @@ do -- ACT_ACCOUNT_DEADS
-- @param #string To -- @param #string To
function ACT_ACCOUNT_DEADS:onafterEvent( ProcessUnit, From, Event, To, EventData ) function ACT_ACCOUNT_DEADS:onafterEvent( ProcessUnit, From, Event, To, EventData )
if self.TargetSetUnit:Count() > 0 then if self.TargetSetUnit:Count() > 1 then
self:__More( 1 ) self:__More( 1 )
else else
self:__NoMore( 1 ) self:__NoMore( 1 )
@@ -259,7 +249,7 @@ do -- ACT_ACCOUNT_DEADS
self:T( { "EventDead", EventData } ) self:T( { "EventDead", EventData } )
if EventData.IniDCSUnit then if EventData.IniDCSUnit then
self:__Event( 1, EventData ) self:Event( EventData )
end end
end end

View File

@@ -175,7 +175,7 @@ do -- ACT_ASSIGN_ACCEPT
self:Message( "You are assigned to the task " .. self.Task:GetName() ) self:Message( "You are assigned to the task " .. self.Task:GetName() )
self.Task:Assign() self.Task:Assign( ProcessUnit, self.Task )
end end
end -- ACT_ASSIGN_ACCEPT end -- ACT_ASSIGN_ACCEPT

View File

@@ -108,7 +108,7 @@ do -- ACT_ASSIST
function ACT_ASSIST:onafterStart( ProcessUnit, From, Event, To ) function ACT_ASSIST:onafterStart( ProcessUnit, From, Event, To )
local ProcessGroup = ProcessUnit:GetGroup() local ProcessGroup = ProcessUnit:GetGroup()
local MissionMenu = self:GetMission():GetMissionMenu( ProcessGroup ) local MissionMenu = self:GetMission():GetMenu( ProcessGroup )
local function MenuSmoke( MenuParam ) local function MenuSmoke( MenuParam )
self:E( MenuParam ) self:E( MenuParam )
@@ -126,6 +126,17 @@ do -- ACT_ASSIST
self.MenuSmokeWhite = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop White smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.White } ) self.MenuSmokeWhite = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop White smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.White } )
end end
--- StateMachine callback function
-- @param #ACT_ASSIST self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIST:onafterStop( ProcessUnit, From, Event, To )
self.Menu:Remove() -- When stopped, remove the menus
end
end end
do -- ACT_ASSIST_SMOKE_TARGETS_ZONE do -- ACT_ASSIST_SMOKE_TARGETS_ZONE

View File

@@ -56,8 +56,7 @@ function PROCESS_JTAC:New( Task, ProcessUnit, TargetSetUnit, FACUnit )
endstates = { 'Failed' } endstates = { 'Failed' }
} ) } )
self:HandleEvent( EVENTS.Dead, self.EventDead )
_EVENTDISPATCHER:OnDead( self.EventDead, self )
return self return self
end end

View File

@@ -81,7 +81,7 @@ do -- ACT_ROUTE
-- @type ACT_ROUTE -- @type ACT_ROUTE
-- @field Tasking.Task#TASK TASK -- @field Tasking.Task#TASK TASK
-- @field Wrapper.Unit#UNIT ProcessUnit -- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Zone#ZONE_BASE TargetZone -- @field Core.Zone#ZONE_BASE Zone
-- @extends Core.Fsm#FSM_PROCESS -- @extends Core.Fsm#FSM_PROCESS
ACT_ROUTE = { ACT_ROUTE = {
ClassName = "ACT_ROUTE", ClassName = "ACT_ROUTE",
@@ -177,6 +177,115 @@ do -- ACT_ROUTE
end -- ACT_ROUTE end -- ACT_ROUTE
do -- ACT_ROUTE_POINT
--- ACT_ROUTE_POINT class
-- @type ACT_ROUTE_POINT
-- @field Tasking.Task#TASK TASK
-- @extends #ACT_ROUTE
ACT_ROUTE_POINT = {
ClassName = "ACT_ROUTE_POINT",
}
--- Creates a new routing state machine.
-- The task will route a controllable to a PointVec2 until the controllable is within the Range.
-- @param #ACT_ROUTE_POINT self
-- @param Core.Point#POINT_VEC2 The PointVec2 to Target.
-- @param #number Range The Distance to Target.
-- @param Core.Zone#ZONE_BASE Zone
function ACT_ROUTE_POINT:New( PointVec2, Range )
local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_POINT
self.PointVec2 = PointVec2
self.Range = Range or 0
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
return self
end
function ACT_ROUTE_POINT:Init( FsmRoute )
self.PointVec2 = FsmRoute.PointVec2
self.Range = FsmRoute.Range or 0
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
end
--- Set PointVec2
-- @param #ACT_ROUTE_POINT self
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to route to.
function ACT_ROUTE_POINT:SetPointVec2( PointVec2 )
self:F2( { PointVec2 } )
self.PointVec2 = PointVec2
end
--- Get PointVec2
-- @param #ACT_ROUTE_POINT self
-- @return Core.Point#POINT_VEC2 PointVec2 The PointVec2 to route to.
function ACT_ROUTE_POINT:GetPointVec2()
self:F2( { self.PointVec2 } )
return self.PointVec2
end
--- Set Range around PointVec2
-- @param #ACT_ROUTE_POINT self
-- @param #number Range The Range to consider the arrival. Default is 10000 meters.
function ACT_ROUTE_POINT:SetRange( Range )
self:F2( { self.Range } )
self.Range = Range or 10000
end
--- Get Range around PointVec2
-- @param #ACT_ROUTE_POINT self
-- @return #number The Range to consider the arrival. Default is 10000 meters.
function ACT_ROUTE_POINT:GetRange()
return self.Range
end
--- Method override to check if the controllable has arrived.
-- @param #ACT_ROUTE_POINT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @return #boolean
function ACT_ROUTE_POINT:onfuncHasArrived( ProcessUnit )
if ProcessUnit:IsAlive() then
local Distance = self.PointVec2:Get2DDistance( ProcessUnit:GetPointVec2() )
if Distance <= self.Range then
local RouteText = "You have arrived."
self:Message( RouteText )
return true
end
end
return false
end
--- Task Events
--- StateMachine callback function
-- @param #ACT_ROUTE_POINT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ROUTE_POINT:onenterReporting( ProcessUnit, From, Event, To )
local TaskUnitPointVec2 = ProcessUnit:GetPointVec2()
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( self.PointVec2 ) .. " km."
self:Message( RouteText )
end
end -- ACT_ROUTE_POINT
do -- ACT_ROUTE_ZONE do -- ACT_ROUTE_ZONE
@@ -184,7 +293,7 @@ do -- ACT_ROUTE_ZONE
-- @type ACT_ROUTE_ZONE -- @type ACT_ROUTE_ZONE
-- @field Tasking.Task#TASK TASK -- @field Tasking.Task#TASK TASK
-- @field Wrapper.Unit#UNIT ProcessUnit -- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Zone#ZONE_BASE TargetZone -- @field Core.Zone#ZONE_BASE Zone
-- @extends #ACT_ROUTE -- @extends #ACT_ROUTE
ACT_ROUTE_ZONE = { ACT_ROUTE_ZONE = {
ClassName = "ACT_ROUTE_ZONE", ClassName = "ACT_ROUTE_ZONE",
@@ -193,11 +302,11 @@ do -- ACT_ROUTE_ZONE
--- Creates a new routing state machine. The task will route a controllable to a ZONE until the controllable is within that ZONE. --- Creates a new routing state machine. The task will route a controllable to a ZONE until the controllable is within that ZONE.
-- @param #ACT_ROUTE_ZONE self -- @param #ACT_ROUTE_ZONE self
-- @param Core.Zone#ZONE_BASE TargetZone -- @param Core.Zone#ZONE_BASE Zone
function ACT_ROUTE_ZONE:New( TargetZone ) function ACT_ROUTE_ZONE:New( Zone )
local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_ZONE local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_ZONE
self.TargetZone = TargetZone self.Zone = Zone
self.DisplayInterval = 30 self.DisplayInterval = 30
self.DisplayCount = 30 self.DisplayCount = 30
@@ -209,7 +318,7 @@ do -- ACT_ROUTE_ZONE
function ACT_ROUTE_ZONE:Init( FsmRoute ) function ACT_ROUTE_ZONE:Init( FsmRoute )
self.TargetZone = FsmRoute.TargetZone self.Zone = FsmRoute.Zone
self.DisplayInterval = 30 self.DisplayInterval = 30
self.DisplayCount = 30 self.DisplayCount = 30
@@ -217,18 +326,32 @@ do -- ACT_ROUTE_ZONE
self.DisplayTime = 10 -- 10 seconds is the default self.DisplayTime = 10 -- 10 seconds is the default
end end
--- Set Zone
-- @param #ACT_ROUTE_ZONE self
-- @param Core.Zone#ZONE_BASE Zone The Zone object where to route to.
function ACT_ROUTE_ZONE:SetZone( Zone )
self.Zone = Zone
end
--- Get Zone
-- @param #ACT_ROUTE_ZONE self
-- @return Core.Zone#ZONE_BASE Zone The Zone object where to route to.
function ACT_ROUTE_ZONE:GetZone()
return self.Zone
end
--- Method override to check if the controllable has arrived. --- Method override to check if the controllable has arrived.
-- @param #ACT_ROUTE self -- @param #ACT_ROUTE self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit -- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @return #boolean -- @return #boolean
function ACT_ROUTE_ZONE:onfuncHasArrived( ProcessUnit ) function ACT_ROUTE_ZONE:onfuncHasArrived( ProcessUnit )
if ProcessUnit:IsInZone( self.TargetZone ) then if ProcessUnit:IsInZone( self.Zone ) then
local RouteText = "You have arrived within the zone." local RouteText = "You have arrived within the zone."
self:Message( RouteText ) self:Message( RouteText )
end end
return ProcessUnit:IsInZone( self.TargetZone ) return ProcessUnit:IsInZone( self.Zone )
end end
--- Task Events --- Task Events
@@ -241,11 +364,11 @@ do -- ACT_ROUTE_ZONE
-- @param #string To -- @param #string To
function ACT_ROUTE_ZONE:onenterReporting( ProcessUnit, From, Event, To ) function ACT_ROUTE_ZONE:onenterReporting( ProcessUnit, From, Event, To )
local ZoneVec2 = self.TargetZone:GetVec2() local ZoneVec2 = self.Zone:GetVec2()
local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y ) local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y )
local TaskUnitVec2 = ProcessUnit:GetVec2() local TaskUnitVec2 = ProcessUnit:GetVec2()
local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y ) local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y )
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target." local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km."
self:Message( RouteText ) self:Message( RouteText )
end end

View File

@@ -1,34 +1,66 @@
--- This module contains the BASE class. --- **Core** - BASE forms **the basis of the MOOSE framework**. Each class within the MOOSE framework derives from BASE.
-- --
-- 1) @{#BASE} class -- ![Banner Image](..\Presentations\BASE\Dia1.JPG)
-- =================
-- The @{#BASE} class is the super class for all the classes defined within MOOSE.
-- --
-- It handles: -- ===
-- --
-- * The construction and inheritance of child classes. -- # 1) @{#BASE} class
-- * The tracing of objects during mission execution within the **DCS.log** file, under the **"Saved Games\DCS\Logs"** folder.
-- --
-- Note: Normally you would not use the BASE class unless you are extending the MOOSE framework with new classes. -- All classes within the MOOSE framework are derived from the @{#BASE} class.
--
-- BASE provides facilities for :
--
-- * The construction and inheritance of MOOSE classes.
-- * The class naming and numbering system.
-- * The class hierarchy search system.
-- * The tracing of information or objects during mission execution for debuggin purposes.
-- * The subscription to DCS events for event handling in MOOSE objects.
--
-- Note: The BASE class is an abstract class and is not meant to be used directly.
-- --
-- ## 1.1) BASE constructor -- ## 1.1) BASE constructor
-- --
-- Any class derived from BASE, must use the @{Base#BASE.New) constructor within the @{Base#BASE.Inherit) method. -- Any class derived from BASE, will use the @{Base#BASE.New} constructor embedded in the @{Base#BASE.Inherit} method.
-- See an example at the @{Base#BASE.New} method how this is done. -- See an example at the @{Base#BASE.New} method how this is done.
-- --
-- ## 1.2) BASE Trace functionality -- ## 1.2) Trace information for debugging
-- --
-- The BASE class contains trace methods to trace progress within a mission execution of a certain object. -- The BASE class contains trace methods to trace progress within a mission execution of a certain object.
-- Note that these trace methods are inherited by each MOOSE class interiting BASE. -- These trace methods are inherited by each MOOSE class interiting BASE, soeach object created from derived class from BASE can use the tracing methods to trace its execution.
-- As such, each object created from derived class from BASE can use the tracing functions to trace its execution.
-- --
-- ### 1.2.1) Tracing functions -- Any type of information can be passed to these tracing methods. See the following examples:
-- --
-- There are basically 3 types of tracing methods available within BASE: -- self:E( "Hello" )
-- --
-- * @{#BASE.F}: Trace the beginning of a function and its given parameters. An F is indicated at column 44 in the DCS.log file. -- Result in the word "Hello" in the dcs.log.
-- * @{#BASE.T}: Trace further logic within a function giving optional variables or parameters. A T is indicated at column 44 in the DCS.log file. --
-- * @{#BASE.E}: Trace an exception within a function giving optional variables or parameters. An E is indicated at column 44 in the DCS.log file. An exception will always be traced. -- local Array = { 1, nil, "h", { "a","b" }, "x" }
-- self:E( Array )
--
-- Results with the text [1]=1,[3]="h",[4]={[1]="a",[2]="b"},[5]="x"} in the dcs.log.
--
-- local Object1 = "Object1"
-- local Object2 = 3
-- local Object3 = { Object 1, Object 2 }
-- self:E( { Object1, Object2, Object3 } )
--
-- Results with the text [1]={[1]="Object",[2]=3,[3]={[1]="Object",[2]=3}} in the dcs.log.
--
-- local SpawnObject = SPAWN:New( "Plane" )
-- local GroupObject = GROUP:FindByName( "Group" )
-- self:E( { Spawn = SpawnObject, Group = GroupObject } )
--
-- Results with the text [1]={Spawn={....),Group={...}} in the dcs.log.
--
-- Below a more detailed explanation of the different method types for tracing.
--
-- ### 1.2.1) Tracing methods categories
--
-- There are basically 3 types of tracing methods available:
--
-- * @{#BASE.F}: Used to trace the entrance of a function and its given parameters. An F is indicated at column 44 in the DCS.log file.
-- * @{#BASE.T}: Used to trace further logic within a function giving optional variables or parameters. A T is indicated at column 44 in the DCS.log file.
-- * @{#BASE.E}: Used to always trace information giving optional variables or parameters. An E is indicated at column 44 in the DCS.log file.
-- --
-- ### 1.2.2) Tracing levels -- ### 1.2.2) Tracing levels
-- --
@@ -51,6 +83,7 @@
-- * Activate only the tracing of a certain class (name) through the @{#BASE.TraceClass}() method. -- * Activate only the tracing of a certain class (name) through the @{#BASE.TraceClass}() method.
-- * Activate only the tracing of a certain method of a certain class through the @{#BASE.TraceClassMethod}() method. -- * Activate only the tracing of a certain method of a certain class through the @{#BASE.TraceClassMethod}() method.
-- * Activate only the tracing of a certain level through the @{#BASE.TraceLevel}() method. -- * Activate only the tracing of a certain level through the @{#BASE.TraceLevel}() method.
--
-- ### 1.2.4) Check if tracing is on. -- ### 1.2.4) Check if tracing is on.
-- --
-- The method @{#BASE.IsTrace}() will validate if tracing is activated or not. -- The method @{#BASE.IsTrace}() will validate if tracing is activated or not.
@@ -64,7 +97,7 @@
-- --
-- At first, the mission designer will need to **Subscribe** to a specific DCS event for the class. -- At first, the mission designer will need to **Subscribe** to a specific DCS event for the class.
-- So, when the DCS event occurs, the class will be notified of that event. -- So, when the DCS event occurs, the class will be notified of that event.
-- There are two functions which you use to subscribe to or unsubscribe from an event. -- There are two methods which you use to subscribe to or unsubscribe from an event.
-- --
-- * @{#BASE.HandleEvent}(): Subscribe to a DCS Event. -- * @{#BASE.HandleEvent}(): Subscribe to a DCS Event.
-- * @{#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event. -- * @{#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event.
@@ -116,8 +149,10 @@
-- --
-- A mechanism is in place in MOOSE, that allows to let the objects administer **states**. -- A mechanism is in place in MOOSE, that allows to let the objects administer **states**.
-- States are essentially properties of objects, which are identified by a **Key** and a **Value**. -- States are essentially properties of objects, which are identified by a **Key** and a **Value**.
--
-- The method @{#BASE.SetState}() can be used to set a Value with a reference Key to the object. -- The method @{#BASE.SetState}() can be used to set a Value with a reference Key to the object.
-- To **read or retrieve** a state Value based on a Key, use the @{#BASE.GetState} method. -- To **read or retrieve** a state Value based on a Key, use the @{#BASE.GetState} method.
--
-- These two methods provide a very handy way to keep state at long lasting processes. -- These two methods provide a very handy way to keep state at long lasting processes.
-- Values can be stored within the objects, and later retrieved or changed when needed. -- Values can be stored within the objects, and later retrieved or changed when needed.
-- There is one other important thing to note, the @{#BASE.SetState}() and @{#BASE.GetState} methods -- There is one other important thing to note, the @{#BASE.SetState}() and @{#BASE.GetState} methods
@@ -125,9 +160,9 @@
-- Thus, if the state is to be set for the same object as the object for which the method is used, then provide the same -- Thus, if the state is to be set for the same object as the object for which the method is used, then provide the same
-- object name to the method. -- object name to the method.
-- --
-- ## 1.10) BASE Inheritance (tree) support -- ## 1.10) Inheritance
-- --
-- The following methods are available to support inheritance: -- The following methods are available to implement inheritance
-- --
-- * @{#BASE.Inherit}: Inherits from a class. -- * @{#BASE.Inherit}: Inherits from a class.
-- * @{#BASE.GetParent}: Returns the parent object from the object it is handling, or nil if there is no parent object. -- * @{#BASE.GetParent}: Returns the parent object from the object it is handling, or nil if there is no parent object.
@@ -192,7 +227,17 @@ FORMATION = {
-- @todo need to investigate if the deepCopy is really needed... Don't think so. --- BASE constructor.
--
-- This is an example how to use the BASE:New() constructor in a new class definition when inheriting from BASE.
--
-- function EVENT:New()
-- local self = BASE:Inherit( self, BASE:New() ) -- #EVENT
-- return self
-- end
--
-- @param #BASE self
-- @return #BASE
function BASE:New() function BASE:New()
local self = routines.utils.deepCopy( self ) -- Create a new self instance local self = routines.utils.deepCopy( self ) -- Create a new self instance
local MetaTable = {} local MetaTable = {}
@@ -211,12 +256,14 @@ function BASE:_Destructor()
--self:EventRemoveAll() --self:EventRemoveAll()
end end
-- THIS IS WHY WE NEED LUA 5.2 ...
function BASE:_SetDestructor() function BASE:_SetDestructor()
-- TODO: Okay, this is really technical... -- TODO: Okay, this is really technical...
-- When you set a proxy to a table to catch __gc, weak tables don't behave like weak... -- When you set a proxy to a table to catch __gc, weak tables don't behave like weak...
-- Therefore, I am parking this logic until I've properly discussed all this with the community. -- Therefore, I am parking this logic until I've properly discussed all this with the community.
--[[
local proxy = newproxy(true) local proxy = newproxy(true)
local proxyMeta = getmetatable(proxy) local proxyMeta = getmetatable(proxy)
@@ -231,7 +278,7 @@ function BASE:_SetDestructor()
-- table is about to be garbage-collected - then the __gc hook -- table is about to be garbage-collected - then the __gc hook
-- will be invoked and the destructor called -- will be invoked and the destructor called
rawset( self, '__proxy', proxy ) rawset( self, '__proxy', proxy )
--]]
end end
--- This is the worker method to inherit from a parent class. --- This is the worker method to inherit from a parent class.
@@ -247,13 +294,18 @@ function BASE:Inherit( Child, Parent )
setmetatable( Child, Parent ) setmetatable( Child, Parent )
Child.__index = Child Child.__index = Child
Child:_SetDestructor() --Child:_SetDestructor()
end end
--self:T( 'Inherited from ' .. Parent.ClassName ) --self:T( 'Inherited from ' .. Parent.ClassName )
return Child return Child
end end
--- This is the worker method to retrieve the Parent class. --- This is the worker method to retrieve the Parent class.
-- Note that the Parent class must be passed to call the parent class method.
--
-- self:GetParent(self):ParentMethod()
--
--
-- @param #BASE self -- @param #BASE self
-- @param #BASE Child is the Child class from which the Parent class needs to be retrieved. -- @param #BASE Child is the Child class from which the Parent class needs to be retrieved.
-- @return #BASE -- @return #BASE

View File

@@ -54,6 +54,8 @@ DATABASE = {
PLAYERSJOINED = {}, PLAYERSJOINED = {},
CLIENTS = {}, CLIENTS = {},
AIRBASES = {}, AIRBASES = {},
COUNTRY_ID = {},
COUNTRY_NAME = {},
NavPoints = {}, NavPoints = {},
} }
@@ -542,8 +544,14 @@ function DATABASE:_EventOnBirth( Event )
self:F2( { Event } ) self:F2( { Event } )
if Event.IniDCSUnit then if Event.IniDCSUnit then
if Event.IniObjectCategory == 3 then
self:AddStatic( Event.IniDCSUnitName )
else
if Event.IniObjectCategory == 1 then
self:AddUnit( Event.IniDCSUnitName ) self:AddUnit( Event.IniDCSUnitName )
self:AddGroup( Event.IniDCSGroupName ) self:AddGroup( Event.IniDCSGroupName )
end
end
self:_EventOnPlayerEnterUnit( Event ) self:_EventOnPlayerEnterUnit( Event )
end end
end end
@@ -556,9 +564,16 @@ function DATABASE:_EventOnDeadOrCrash( Event )
self:F2( { Event } ) self:F2( { Event } )
if Event.IniDCSUnit then if Event.IniDCSUnit then
if Event.IniObjectCategory == 3 then
if self.STATICS[Event.IniDCSUnitName] then
self:DeleteStatic( Event.IniDCSUnitName )
end
else
if Event.IniObjectCategory == 1 then
if self.UNITS[Event.IniDCSUnitName] then if self.UNITS[Event.IniDCSUnitName] then
self:DeleteUnit( Event.IniDCSUnitName ) self:DeleteUnit( Event.IniDCSUnitName )
-- add logic to correctly remove a group once all units are destroyed... end
end
end end
end end
end end
@@ -571,6 +586,7 @@ function DATABASE:_EventOnPlayerEnterUnit( Event )
self:F2( { Event } ) self:F2( { Event } )
if Event.IniUnit then if Event.IniUnit then
if Event.IniObjectCategory == 1 then
self:AddUnit( Event.IniDCSUnitName ) self:AddUnit( Event.IniDCSUnitName )
self:AddGroup( Event.IniDCSGroupName ) self:AddGroup( Event.IniDCSGroupName )
local PlayerName = Event.IniUnit:GetPlayerName() local PlayerName = Event.IniUnit:GetPlayerName()
@@ -578,6 +594,7 @@ function DATABASE:_EventOnPlayerEnterUnit( Event )
self:AddPlayer( Event.IniUnitName, PlayerName ) self:AddPlayer( Event.IniUnitName, PlayerName )
end end
end end
end
end end
@@ -588,11 +605,13 @@ function DATABASE:_EventOnPlayerLeaveUnit( Event )
self:F2( { Event } ) self:F2( { Event } )
if Event.IniUnit then if Event.IniUnit then
if Event.IniObjectCategory == 1 then
local PlayerName = Event.IniUnit:GetPlayerName() local PlayerName = Event.IniUnit:GetPlayerName()
if self.PLAYERS[PlayerName] then if self.PLAYERS[PlayerName] then
self:DeletePlayer( PlayerName ) self:DeletePlayer( PlayerName )
end end
end end
end
end end
--- Iterators --- Iterators
@@ -744,6 +763,9 @@ function DATABASE:_RegisterTemplates()
local CountryName = string.upper(cntry_data.name) local CountryName = string.upper(cntry_data.name)
local CountryID = cntry_data.id local CountryID = cntry_data.id
self.COUNTRY_ID[CountryName] = CountryID
self.COUNTRY_NAME[CountryID] = CountryName
--self.Units[coa_name][countryName] = {} --self.Units[coa_name][countryName] = {}
--self.Units[coa_name][countryName]["countryId"] = cntry_data.id --self.Units[coa_name][countryName]["countryId"] = cntry_data.id

View File

@@ -1,5 +1,4 @@
--- This core module models the dispatching of DCS Events to subscribed MOOSE classes, --- **Core** - EVENT models DCS **event dispatching** using a **publish-subscribe** model.
-- following a given priority.
-- --
-- ![Banner Image](..\Presentations\EVENT\Dia1.JPG) -- ![Banner Image](..\Presentations\EVENT\Dia1.JPG)
-- --
@@ -65,6 +64,13 @@
-- * @{Base#BASE.HandleEvent}(): Subscribe to a DCS Event. -- * @{Base#BASE.HandleEvent}(): Subscribe to a DCS Event.
-- * @{Base#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event. -- * @{Base#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event.
-- --
-- Note that for a UNIT, the event will be handled **for that UNIT only**!
-- Note that for a GROUP, the event will be handled **for all the UNITs in that GROUP only**!
--
-- For all objects of other classes, the subscribed events will be handled for **all UNITs within the Mission**!
-- So if a UNIT within the mission has the subscribed event for that object,
-- then the object event handler will receive the event for that UNIT!
--
-- ### 1.3.2 Event Handling of DCS Events -- ### 1.3.2 Event Handling of DCS Events
-- --
-- Once the class is subscribed to the event, an **Event Handling** method on the object or class needs to be written that will be called -- Once the class is subscribed to the event, an **Event Handling** method on the object or class needs to be written that will be called
@@ -165,7 +171,9 @@
-- --
-- Hereby the change log: -- Hereby the change log:
-- --
-- * 2016-02-07: Did a complete revision of the Event Handing API and underlying mechanisms. -- * 2017-03-07: Added the correct event dispatching in case the event is subscribed by a GROUP.
--
-- * 2017-02-07: Did a complete revision of the Event Handing API and underlying mechanisms.
-- --
-- === -- ===
-- --
@@ -179,10 +187,6 @@
-- --
-- @module Event -- @module Event
-- TODO: Need to update the EVENTDATA documentation with IniPlayerName and TgtPlayerName
-- TODO: Need to update the EVENTDATA documentation with IniObjectCategory and TgtObjectCategory
--- The EVENT structure --- The EVENT structure
-- @type EVENT -- @type EVENT
@@ -280,7 +284,7 @@ local _EVENTMETA = {
}, },
[world.event.S_EVENT_TAKEOFF] = { [world.event.S_EVENT_TAKEOFF] = {
Order = 1, Order = 1,
Event = "OnEventTakeOff", Event = "OnEventTakeoff",
Text = "S_EVENT_TAKEOFF" Text = "S_EVENT_TAKEOFF"
}, },
[world.event.S_EVENT_LAND] = { [world.event.S_EVENT_LAND] = {
@@ -421,11 +425,11 @@ function EVENT:Init( EventID, EventClass )
-- Each event has a subtable of EventClasses, ordered by EventPriority. -- Each event has a subtable of EventClasses, ordered by EventPriority.
local EventPriority = EventClass:GetEventPriority() local EventPriority = EventClass:GetEventPriority()
if not self.Events[EventID][EventPriority] then if not self.Events[EventID][EventPriority] then
self.Events[EventID][EventPriority] = {} self.Events[EventID][EventPriority] = setmetatable( {}, { __mode = "k" } )
end end
if not self.Events[EventID][EventPriority][EventClass] then if not self.Events[EventID][EventPriority][EventClass] then
self.Events[EventID][EventPriority][EventClass] = setmetatable( {}, { __mode = "k" } ) self.Events[EventID][EventPriority][EventClass] = setmetatable( {}, { __mode = "v" } )
end end
return self.Events[EventID][EventPriority][EventClass] return self.Events[EventID][EventPriority][EventClass]
end end
@@ -443,8 +447,9 @@ function EVENT:Remove( EventClass, EventID )
self.Events[EventID][EventPriority][EventClass] = nil self.Events[EventID][EventPriority][EventClass] = nil
end end
--- Removes an Events entry for a Unit --- Removes an Events entry for a UNIT.
-- @param #EVENT self -- @param #EVENT self
-- @param #string UnitName The name of the UNIT.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is. -- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID -- @param Dcs.DCSWorld#world.event EventID
-- @return #EVENT.Events -- @return #EVENT.Events
@@ -454,7 +459,22 @@ function EVENT:RemoveForUnit( UnitName, EventClass, EventID )
local EventClass = EventClass local EventClass = EventClass
local EventPriority = EventClass:GetEventPriority() local EventPriority = EventClass:GetEventPriority()
local Event = self.Events[EventID][EventPriority][EventClass] local Event = self.Events[EventID][EventPriority][EventClass]
Event.IniUnit[UnitName] = nil Event.EventUnit[UnitName] = nil
end
--- Removes an Events entry for a GROUP.
-- @param #EVENT self
-- @param #string GroupName The name of the GROUP.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID
-- @return #EVENT.Events
function EVENT:RemoveForGroup( GroupName, EventClass, EventID )
self:F3( { EventClass, _EVENTMETA[EventID].Text } )
local EventClass = EventClass
local EventPriority = EventClass:GetEventPriority()
local Event = self.Events[EventID][EventPriority][EventClass]
Event.EventGroup[GroupName] = nil
end end
--- Clears all event subscriptions for a @{Base#BASE} derived object. --- Clears all event subscriptions for a @{Base#BASE} derived object.
@@ -479,11 +499,11 @@ end
-- @param EventClass The instance of the class for which the event is. -- @param EventClass The instance of the class for which the event is.
-- @param #function OnEventFunction -- @param #function OnEventFunction
-- @return #EVENT -- @return #EVENT
function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventClass, OnEventFunction ) function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EventID )
self:F2( EventTemplate.name ) self:F2( EventTemplate.name )
for EventUnitID, EventUnit in pairs( EventTemplate.units ) do for EventUnitID, EventUnit in pairs( EventTemplate.units ) do
OnEventFunction( self, EventUnit.name, EventFunction, EventClass ) self:OnEventForUnit( EventUnit.name, EventFunction, EventClass, EventID )
end end
return self return self
end end
@@ -497,31 +517,51 @@ end
function EVENT:OnEventGeneric( EventFunction, EventClass, EventID ) function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
self:F2( { EventID } ) self:F2( { EventID } )
local Event = self:Init( EventID, EventClass ) local EventData = self:Init( EventID, EventClass )
Event.EventFunction = EventFunction EventData.EventFunction = EventFunction
Event.EventClass = EventClass EventData.EventClass = EventClass
return self return self
end end
--- Set a new listener for an S_EVENT_X event --- Set a new listener for an S_EVENT_X event for a UNIT.
-- @param #EVENT self -- @param #EVENT self
-- @param #string EventDCSUnitName -- @param #string UnitName The name of the UNIT.
-- @param #function EventFunction The function to be called when the event occurs for the unit. -- @param #function EventFunction The function to be called when the event occurs for the GROUP.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is. -- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param EventID -- @param EventID
-- @return #EVENT -- @return #EVENT
function EVENT:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, EventID ) function EVENT:OnEventForUnit( UnitName, EventFunction, EventClass, EventID )
self:F2( EventDCSUnitName ) self:F2( UnitName )
local EventData = self:Init( EventID, EventClass )
if not EventData.EventUnit then
EventData.EventUnit = {}
end
EventData.EventUnit[UnitName] = {}
EventData.EventUnit[UnitName].EventFunction = EventFunction
EventData.EventUnit[UnitName].EventClass = EventClass
return self
end
--- Set a new listener for an S_EVENT_X event for a GROUP.
-- @param #EVENT self
-- @param #string GroupName The name of the GROUP.
-- @param #function EventFunction The function to be called when the event occurs for the GROUP.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param EventID
-- @return #EVENT
function EVENT:OnEventForGroup( GroupName, EventFunction, EventClass, EventID )
self:F2( GroupName )
local Event = self:Init( EventID, EventClass ) local Event = self:Init( EventID, EventClass )
if not Event.IniUnit then if not Event.EventGroup then
Event.IniUnit = {} Event.EventGroup = {}
end end
Event.IniUnit[EventDCSUnitName] = {} Event.EventGroup[GroupName] = {}
Event.IniUnit[EventDCSUnitName].EventFunction = EventFunction Event.EventGroup[GroupName].EventFunction = EventFunction
Event.IniUnit[EventDCSUnitName].EventClass = EventClass Event.EventGroup[GroupName].EventClass = EventClass
return self return self
end end
@@ -536,51 +576,11 @@ do -- OnBirth
function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventClass ) function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name ) self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnBirthForUnit ) self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Birth )
return self return self
end end
--- Set a new listener for an S_EVENT_BIRTH event, and registers the unit born.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnBirth( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_BIRTH )
return self
end
--- Set a new listener for an S_EVENT_BIRTH event.
-- @param #EVENT self
-- @param #string EventDCSUnitName The id of the unit for the event to be handled.
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnBirthForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_BIRTH )
return self
end
--- Stop listening to S_EVENT_BIRTH event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnBirthRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_BIRTH )
return self
end
end end
do -- OnCrash do -- OnCrash
@@ -594,46 +594,7 @@ do -- OnCrash
function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventClass ) function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name ) self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnCrashForUnit ) self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Crash )
return self
end
--- Set a new listener for an S_EVENT_CRASH event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnCrash( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_CRASH )
return self
end
--- Set a new listener for an S_EVENT_CRASH event.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnCrashForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_CRASH )
return self
end
--- Stop listening to S_EVENT_CRASH event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnCrashRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_CRASH )
return self return self
end end
@@ -651,97 +612,14 @@ do -- OnDead
function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventClass ) function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name ) self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnDeadForUnit ) self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Dead )
return self
end
--- Set a new listener for an S_EVENT_DEAD event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnDead( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_DEAD )
return self
end
--- Set a new listener for an S_EVENT_DEAD event.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnDeadForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_DEAD )
return self
end
--- Stop listening to S_EVENT_DEAD event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnDeadRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_DEAD )
return self
end
end
do -- OnPilotDead
--- Set a new listener for an S_EVENT_PILOT_DEAD event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnPilotDead( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PILOT_DEAD )
return self
end
--- Set a new listener for an S_EVENT_PILOT_DEAD event.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnPilotDeadForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_PILOT_DEAD )
return self
end
--- Stop listening to S_EVENT_PILOT_DEAD event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnPilotDeadRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_PILOT_DEAD )
return self return self
end end
end end
do -- OnLand do -- OnLand
--- Create an OnLand event handler for a group --- Create an OnLand event handler for a group
-- @param #EVENT self -- @param #EVENT self
@@ -752,38 +630,11 @@ do -- OnLand
function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventClass ) function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name ) self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnLandForUnit ) self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Land )
return self return self
end end
--- Set a new listener for an S_EVENT_LAND event.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnLandForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_LAND )
return self
end
--- Stop listening to S_EVENT_LAND event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnLandRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_LAND )
return self
end
end end
do -- OnTakeOff do -- OnTakeOff
@@ -796,38 +647,11 @@ do -- OnTakeOff
function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventClass ) function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name ) self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnTakeOffForUnit ) self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Takeoff )
return self return self
end end
--- Set a new listener for an S_EVENT_TAKEOFF event.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnTakeOffForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_TAKEOFF )
return self
end
--- Stop listening to S_EVENT_TAKEOFF event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnTakeOffRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_TAKEOFF )
return self
end
end end
do -- OnEngineShutDown do -- OnEngineShutDown
@@ -841,213 +665,13 @@ do -- OnEngineShutDown
function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventClass ) function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name ) self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnEngineShutDownForUnit ) self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.EngineShutdown )
return self
end
--- Set a new listener for an S_EVENT_ENGINE_SHUTDOWN event.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnEngineShutDownForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_ENGINE_SHUTDOWN )
return self
end
--- Stop listening to S_EVENT_ENGINE_SHUTDOWN event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnEngineShutDownRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_ENGINE_SHUTDOWN )
return self return self
end end
end end
do -- OnEngineStartUp
--- Set a new listener for an S_EVENT_ENGINE_STARTUP event.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnEngineStartUpForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_ENGINE_STARTUP )
return self
end
--- Stop listening to S_EVENT_ENGINE_STARTUP event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnEngineStartUpRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_ENGINE_STARTUP )
return self
end
end
do -- OnShot
--- Set a new listener for an S_EVENT_SHOT event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnShot( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_SHOT )
return self
end
--- Set a new listener for an S_EVENT_SHOT event for a unit.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnShotForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_SHOT )
return self
end
--- Stop listening to S_EVENT_SHOT event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnShotRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_SHOT )
return self
end
end
do -- OnHit
--- Set a new listener for an S_EVENT_HIT event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnHit( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_HIT )
return self
end
--- Set a new listener for an S_EVENT_HIT event.
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnHitForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_HIT )
return self
end
--- Stop listening to S_EVENT_HIT event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnHitRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_HIT )
return self
end
end
do -- OnPlayerEnterUnit
--- Set a new listener for an S_EVENT_PLAYER_ENTER_UNIT event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnPlayerEnterUnit( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PLAYER_ENTER_UNIT )
return self
end
--- Stop listening to S_EVENT_PLAYER_ENTER_UNIT event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnPlayerEnterRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_PLAYER_ENTER_UNIT )
return self
end
end
do -- OnPlayerLeaveUnit
--- Set a new listener for an S_EVENT_PLAYER_LEAVE_UNIT event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnPlayerLeaveUnit( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
return self
end
--- Stop listening to S_EVENT_PLAYER_LEAVE_UNIT event.
-- @param #EVENT self
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnPlayerLeaveRemove( EventClass )
self:F2()
self:Remove( EventClass, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
return self
end
end
--- @param #EVENT self --- @param #EVENT self
-- @param #EVENTDATA Event -- @param #EVENTDATA Event
@@ -1084,7 +708,9 @@ function EVENT:onEvent( Event )
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
Event.IniDCSGroupName = Event.IniDCSGroup:getName() Event.IniDCSGroupName = Event.IniDCSGroup:getName()
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName ) Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
self:E( { IniGroup = Event.IniGroup } ) if Event.IniGroup then
Event.IniGroupName = Event.IniDCSGroupName
end
end end
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName() Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCoalition = Event.IniDCSUnit:getCoalition()
@@ -1096,7 +722,7 @@ function EVENT:onEvent( Event )
Event.IniDCSUnit = Event.initiator Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName() Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = STATIC:FindByName( Event.IniDCSUnitName ) Event.IniUnit = STATIC:FindByName( Event.IniDCSUnitName, false )
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()
@@ -1125,6 +751,10 @@ function EVENT:onEvent( Event )
Event.TgtDCSGroupName = "" Event.TgtDCSGroupName = ""
if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then
Event.TgtDCSGroupName = Event.TgtDCSGroup:getName() Event.TgtDCSGroupName = Event.TgtDCSGroup:getName()
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
if Event.TgtGroup then
Event.TgtGroupName = Event.TgtDCSGroupName
end
end end
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName() Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition() Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
@@ -1162,7 +792,9 @@ function EVENT:onEvent( Event )
local PriorityBegin = PriorityOrder == -1 and 5 or 1 local PriorityBegin = PriorityOrder == -1 and 5 or 1
local PriorityEnd = PriorityOrder == -1 and 1 or 5 local PriorityEnd = PriorityOrder == -1 and 1 or 5
if Event.IniObjectCategory ~= 3 then
self:E( { _EVENTMETA[Event.id].Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } ) self:E( { _EVENTMETA[Event.id].Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
end
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
@@ -1171,18 +803,25 @@ function EVENT:onEvent( Event )
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called. -- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT. -- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
if Event.IniDCSUnitName and EventData.IniUnit and EventData.IniUnit[Event.IniDCSUnitName] then if ( Event.IniDCSUnitName and EventData.EventUnit and EventData.EventUnit[Event.IniDCSUnitName] ) or
( Event.TgtDCSUnitName and EventData.EventUnit and EventData.EventUnit[Event.TgtDCSUnitName] ) then
if EventData.EventUnit[Event.IniDCSUnitName] then
-- First test if a EventFunction is Set, otherwise search for the default function -- First test if a EventFunction is Set, otherwise search for the default function
if EventData.IniUnit[Event.IniDCSUnitName].EventFunction then if EventData.EventUnit[Event.IniDCSUnitName].EventFunction then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } ) if Event.IniObjectCategory ~= 3 then
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName ) self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end
local Result, Value = xpcall( local Result, Value = xpcall(
function() function()
return EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventClass, Event ) return EventData.EventUnit[Event.IniDCSUnitName].EventFunction( EventClass, Event )
end, ErrorHandler ) end, ErrorHandler )
else else
@@ -1192,22 +831,125 @@ function EVENT:onEvent( Event )
if EventFunction and type( EventFunction ) == "function" then if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function. -- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } ) self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName ) end
local Result, Value = xpcall( local Result, Value = xpcall(
function() function()
return EventFunction( EventClass, Event ) return EventFunction( EventClass, Event )
end, ErrorHandler ) end, ErrorHandler )
end end
end
end
if EventData.EventUnit[Event.TgtDCSUnitName] then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventUnit[Event.TgtDCSUnitName].EventFunction then
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventUnit[Event.TgtDCSUnitName].EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
else
-- If the EventData is for a GROUP, the call directly the EventClass EventFunction for the UNIT in that GROUP.
if ( Event.IniDCSUnitName and Event.IniDCSGroupName and Event.IniGroupName and EventData.EventGroup and EventData.EventGroup[Event.IniGroupName] ) or
( Event.TgtDCSUnitName and Event.TgtDCSGroupName and Event.TgtGroupName and EventData.EventGroup and EventData.EventGroup[Event.TgtGroupName] ) then
if EventData.EventGroup[Event.IniGroupName] then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventGroup[Event.IniGroupName].EventFunction then
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventGroup[Event.IniGroupName].EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
if EventData.EventGroup[Event.TgtGroupName] then
if EventData.EventGroup[Event.TgtGroupName].EventFunction then
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventGroup[Event.TgtGroupName].EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end end
else else
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction. -- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon. -- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
if Event.IniDCSUnit and not EventData.IniUnit then if Event.IniDCSUnit and not EventData.EventUnit then
if EventClass == EventData.EventClass then if EventClass == EventData.EventClass then
@@ -1215,9 +957,9 @@ function EVENT:onEvent( Event )
if EventData.EventFunction then if EventData.EventFunction then
-- There is an EventFunction defined, so call the EventFunction. -- There is an EventFunction defined, so call the EventFunction.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } ) self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName ) end
local Result, Value = xpcall( local Result, Value = xpcall(
function() function()
return EventData.EventFunction( EventClass, Event ) return EventData.EventFunction( EventClass, Event )
@@ -1229,12 +971,14 @@ function EVENT:onEvent( Event )
if EventFunction and type( EventFunction ) == "function" then if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function. -- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } ) self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName ) end
local Result, Value = xpcall( local Result, Value = xpcall(
function() function()
return EventFunction( EventClass, Event ) local Result, Value = EventFunction( EventClass, Event )
return Result, Value
end, ErrorHandler ) end, ErrorHandler )
end end
end end
@@ -1244,9 +988,12 @@ function EVENT:onEvent( Event )
end end
end end
end end
end
else else
self:E( { _EVENTMETA[Event.id].Text, Event } ) self:E( { _EVENTMETA[Event.id].Text, Event } )
end end
Event = nil
end end
--- The EVENTHANDLER structure --- The EVENTHANDLER structure

View File

@@ -1,5 +1,5 @@
--- This module contains the **FSM** (**F**inite **S**tate **M**achine) class and derived **FSM\_** classes. --- **Core** - The **FSM** (**F**inite **S**tate **M**achine) class and derived **FSM\_** classes
-- ## Finite State Machines (FSM) are design patterns allowing efficient (long-lasting) processes and workflows. -- are design patterns allowing efficient (long-lasting) processes and workflows.
-- --
-- ![Banner Image](..\Presentations\FSM\Dia1.JPG) -- ![Banner Image](..\Presentations\FSM\Dia1.JPG)
-- --
@@ -530,10 +530,20 @@ do -- FSM
function FSM:_call_handler( handler, params, EventName ) function FSM:_call_handler( handler, params, EventName )
local ErrorHandler = function( errmsg )
env.info( "Error in SCHEDULER function:" .. errmsg )
if debug ~= nil then
env.info( debug.traceback() )
end
return errmsg
end
if self[handler] then if self[handler] then
self:T( "Calling " .. handler ) self:T( "Calling " .. handler )
self._EventSchedules[EventName] = nil self._EventSchedules[EventName] = nil
local Value = self[handler]( self, unpack(params) ) local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
return Value return Value
end end
end end
@@ -732,9 +742,67 @@ do -- FSM_CONTROLLABLE
self:SetControllable( Controllable ) self:SetControllable( Controllable )
end end
self:AddTransition( "*", "Stop", "Stopped" )
--- OnBefore Transition Handler for Event Stop.
-- @function [parent=#FSM_CONTROLLABLE] OnBeforeStop
-- @param #FSM_CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Stop.
-- @function [parent=#FSM_CONTROLLABLE] OnAfterStop
-- @param #FSM_CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Stop.
-- @function [parent=#FSM_CONTROLLABLE] Stop
-- @param #FSM_CONTROLLABLE self
--- Asynchronous Event Trigger for Event Stop.
-- @function [parent=#FSM_CONTROLLABLE] __Stop
-- @param #FSM_CONTROLLABLE self
-- @param #number Delay The delay in seconds.
--- OnLeave Transition Handler for State Stopped.
-- @function [parent=#FSM_CONTROLLABLE] OnLeaveStopped
-- @param #FSM_CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Stopped.
-- @function [parent=#FSM_CONTROLLABLE] OnEnterStopped
-- @param #FSM_CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
return self return self
end end
--- OnAfter Transition Handler for Event Stop.
-- @function [parent=#FSM_CONTROLLABLE] OnAfterStop
-- @param #FSM_CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function FSM_CONTROLLABLE:OnAfterStop(Controllable,From,Event,To)
-- Clear all pending schedules
self.CallScheduler:Clear()
end
--- Sets the CONTROLLABLE object that the FSM_CONTROLLABLE governs. --- Sets the CONTROLLABLE object that the FSM_CONTROLLABLE governs.
-- @param #FSM_CONTROLLABLE self -- @param #FSM_CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE FSMControllable -- @param Wrapper.Controllable#CONTROLLABLE FSMControllable
@@ -802,12 +870,34 @@ do -- FSM_PROCESS
self:T( "No Initialisation" ) self:T( "No Initialisation" )
end end
function FSM_PROCESS:_call_handler( handler, params, EventName )
local ErrorHandler = function( errmsg )
env.info( "Error in FSM_PROCESS call handler:" .. errmsg )
if debug ~= nil then
env.info( debug.traceback() )
end
return errmsg
end
if self[handler] then
self:F3( "Calling " .. handler )
self._EventSchedules[EventName] = nil
local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, self.Task, unpack( params ) ) end, ErrorHandler )
return Value
--return self[handler]( self, self.Controllable, unpack( params ) )
end
end
--- Creates a new FSM_PROCESS object based on this FSM_PROCESS. --- Creates a new FSM_PROCESS object based on this FSM_PROCESS.
-- @param #FSM_PROCESS self -- @param #FSM_PROCESS self
-- @return #FSM_PROCESS -- @return #FSM_PROCESS
function FSM_PROCESS:Copy( Controllable, Task ) function FSM_PROCESS:Copy( Controllable, Task )
self:T( { self:GetClassNameAndID() } ) self:T( { self:GetClassNameAndID() } )
local NewFsm = self:New( Controllable, Task ) -- Core.Fsm#FSM_PROCESS local NewFsm = self:New( Controllable, Task ) -- Core.Fsm#FSM_PROCESS
NewFsm:Assign( Controllable, Task ) NewFsm:Assign( Controllable, Task )
@@ -825,7 +915,7 @@ do -- FSM_PROCESS
-- Copy Processes -- Copy Processes
for ProcessID, Process in pairs( self:GetProcesses() ) do for ProcessID, Process in pairs( self:GetProcesses() ) do
self:T( { Process} ) self:E( { Process} )
local FsmProcess = NewFsm:AddProcess( Process.From, Process.Event, Process.fsm:Copy( Controllable, Task ), Process.ReturnEvents ) local FsmProcess = NewFsm:AddProcess( Process.From, Process.Event, Process.fsm:Copy( Controllable, Task ), Process.ReturnEvents )
end end
@@ -844,6 +934,22 @@ do -- FSM_PROCESS
return NewFsm return NewFsm
end end
--- Removes an FSM_PROCESS object.
-- @param #FSM_PROCESS self
-- @return #FSM_PROCESS
function FSM_PROCESS:Remove()
self:T( { self:GetClassNameAndID() } )
-- Copy Processes
for ProcessID, Process in pairs( self:GetProcesses() ) do
self:E( { Process} )
Process.fsm:Remove()
Process.fsm = nil
end
return self
end
--- Sets the task of the process. --- Sets the task of the process.
-- @param #FSM_PROCESS self -- @param #FSM_PROCESS self
-- @param Tasking.Task#TASK Task -- @param Tasking.Task#TASK Task

View File

@@ -1,4 +1,4 @@
--- This module contains the MENU classes. --- **Core** -- MENU_ classes model the definition of **hierarchical menu structures** and **commands for players** within a mission.
-- --
-- === -- ===
-- --
@@ -138,6 +138,8 @@ do -- MENU_BASE
} }
--- Consructor --- Consructor
-- @param #MENU_BASE
-- @return #MENU_BASE
function MENU_BASE:New( MenuText, ParentMenu ) function MENU_BASE:New( MenuText, ParentMenu )
local MenuParentPath = {} local MenuParentPath = {}
@@ -150,10 +152,43 @@ do -- MENU_BASE
self.MenuPath = nil self.MenuPath = nil
self.MenuText = MenuText self.MenuText = MenuText
self.MenuParentPath = MenuParentPath self.MenuParentPath = MenuParentPath
self.Menus = {}
self.MenuCount = 0
self.MenuRemoveParent = false
self.MenuTime = timer.getTime()
return self return self
end end
--- Gets a @{Menu} from a parent @{Menu}
-- @param #MENU_BASE self
-- @param #string MenuText The text of the child menu.
-- @return #MENU_BASE
function MENU_BASE:GetMenu( MenuText )
self:F( { self.Menus, MenuText } )
return self.Menus[MenuText]
end
--- Sets a @{Menu} to remove automatically the parent menu when the menu removed is the last child menu of that parent @{Menu}.
-- @param #MENU_BASE self
-- @param #boolean RemoveParent If true, the parent menu is automatically removed when this menu is the last child menu of that parent @{Menu}.
-- @return #MENU_BASE
function MENU_BASE:SetRemoveParent( RemoveParent )
self:F( { RemoveParent } )
self.MenuRemoveParent = RemoveParent
return self
end
--- Sets a time stamp for later prevention of menu removal.
-- @param #MENU_BASE self
-- @param MenuTime
-- @return #MENU_BASE
function MENU_BASE:SetTime( MenuTime )
self.MenuTime = MenuTime
return self
end
end end
do -- MENU_COMMAND_BASE do -- MENU_COMMAND_BASE
@@ -161,7 +196,7 @@ do -- MENU_COMMAND_BASE
--- The MENU_COMMAND_BASE class --- The MENU_COMMAND_BASE class
-- @type MENU_COMMAND_BASE -- @type MENU_COMMAND_BASE
-- @field #function MenuCallHandler -- @field #function MenuCallHandler
-- @extends Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
MENU_COMMAND_BASE = { MENU_COMMAND_BASE = {
ClassName = "MENU_COMMAND_BASE", ClassName = "MENU_COMMAND_BASE",
CommandMenuFunction = nil, CommandMenuFunction = nil,
@@ -170,6 +205,8 @@ do -- MENU_COMMAND_BASE
} }
--- Constructor --- Constructor
-- @param #MENU_COMMAND_BASE
-- @return #MENU_COMMAND_BASE
function MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, CommandMenuArguments ) function MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, CommandMenuArguments )
local self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) ) local self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
@@ -189,7 +226,7 @@ do -- MENU_MISSION
--- The MENU_MISSION class --- The MENU_MISSION class
-- @type MENU_MISSION -- @type MENU_MISSION
-- @extends Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
MENU_MISSION = { MENU_MISSION = {
ClassName = "MENU_MISSION" ClassName = "MENU_MISSION"
} }
@@ -198,7 +235,7 @@ do -- MENU_MISSION
-- @param #MENU_MISSION self -- @param #MENU_MISSION self
-- @param #string MenuText The text for the menu. -- @param #string MenuText The text for the menu.
-- @param #table ParentMenu The parent menu. This parameter can be ignored if you want the menu to be located at the perent menu of DCS world (under F10 other). -- @param #table ParentMenu The parent menu. This parameter can be ignored if you want the menu to be located at the perent menu of DCS world (under F10 other).
-- @return #MENU_MISSION self -- @return #MENU_MISSION
function MENU_MISSION:New( MenuText, ParentMenu ) function MENU_MISSION:New( MenuText, ParentMenu )
local self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) ) local self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
@@ -225,7 +262,7 @@ do -- MENU_MISSION
--- Removes the sub menus recursively of this MENU_MISSION. Note that the main menu is kept! --- Removes the sub menus recursively of this MENU_MISSION. Note that the main menu is kept!
-- @param #MENU_MISSION self -- @param #MENU_MISSION self
-- @return #MENU_MISSION self -- @return #MENU_MISSION
function MENU_MISSION:RemoveSubMenus() function MENU_MISSION:RemoveSubMenus()
self:F( self.MenuPath ) self:F( self.MenuPath )
@@ -256,7 +293,7 @@ do -- MENU_MISSION_COMMAND
--- The MENU_MISSION_COMMAND class --- The MENU_MISSION_COMMAND class
-- @type MENU_MISSION_COMMAND -- @type MENU_MISSION_COMMAND
-- @extends Menu#MENU_COMMAND_BASE -- @extends Core.Menu#MENU_COMMAND_BASE
MENU_MISSION_COMMAND = { MENU_MISSION_COMMAND = {
ClassName = "MENU_MISSION_COMMAND" ClassName = "MENU_MISSION_COMMAND"
} }
@@ -306,7 +343,7 @@ do -- MENU_COALITION
--- The MENU_COALITION class --- The MENU_COALITION class
-- @type MENU_COALITION -- @type MENU_COALITION
-- @extends Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
-- @usage -- @usage
-- -- This demo creates a menu structure for the planes within the red coalition. -- -- This demo creates a menu structure for the planes within the red coalition.
-- -- To test, join the planes, then look at the other radio menus (Option F10). -- -- To test, join the planes, then look at the other radio menus (Option F10).
@@ -380,7 +417,7 @@ do -- MENU_COALITION
--- Removes the sub menus recursively of this MENU_COALITION. Note that the main menu is kept! --- Removes the sub menus recursively of this MENU_COALITION. Note that the main menu is kept!
-- @param #MENU_COALITION self -- @param #MENU_COALITION self
-- @return #MENU_COALITION self -- @return #MENU_COALITION
function MENU_COALITION:RemoveSubMenus() function MENU_COALITION:RemoveSubMenus()
self:F( self.MenuPath ) self:F( self.MenuPath )
@@ -411,7 +448,7 @@ do -- MENU_COALITION_COMMAND
--- The MENU_COALITION_COMMAND class --- The MENU_COALITION_COMMAND class
-- @type MENU_COALITION_COMMAND -- @type MENU_COALITION_COMMAND
-- @extends Menu#MENU_COMMAND_BASE -- @extends Core.Menu#MENU_COMMAND_BASE
MENU_COALITION_COMMAND = { MENU_COALITION_COMMAND = {
ClassName = "MENU_COALITION_COMMAND" ClassName = "MENU_COALITION_COMMAND"
} }
@@ -423,7 +460,7 @@ do -- MENU_COALITION_COMMAND
-- @param Menu#MENU_COALITION ParentMenu The parent menu. -- @param Menu#MENU_COALITION ParentMenu The parent menu.
-- @param CommandMenuFunction A function that is called when the menu key is pressed. -- @param CommandMenuFunction A function that is called when the menu key is pressed.
-- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this. -- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this.
-- @return #MENU_COALITION_COMMAND self -- @return #MENU_COALITION_COMMAND
function MENU_COALITION_COMMAND:New( Coalition, MenuText, ParentMenu, CommandMenuFunction, ... ) function MENU_COALITION_COMMAND:New( Coalition, MenuText, ParentMenu, CommandMenuFunction, ... )
local self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) ) local self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
@@ -468,7 +505,7 @@ do -- MENU_CLIENT
--- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters. --- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters.
-- @type MENU_CLIENT -- @type MENU_CLIENT
-- @extends Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
-- @usage -- @usage
-- -- This demo creates a menu structure for the two clients of planes. -- -- This demo creates a menu structure for the two clients of planes.
-- -- Each client will receive a different menu structure. -- -- Each client will receive a different menu structure.
@@ -609,7 +646,7 @@ do -- MENU_CLIENT
--- The MENU_CLIENT_COMMAND class --- The MENU_CLIENT_COMMAND class
-- @type MENU_CLIENT_COMMAND -- @type MENU_CLIENT_COMMAND
-- @extends Menu#MENU_COMMAND -- @extends Core.Menu#MENU_COMMAND
MENU_CLIENT_COMMAND = { MENU_CLIENT_COMMAND = {
ClassName = "MENU_CLIENT_COMMAND" ClassName = "MENU_CLIENT_COMMAND"
} }
@@ -695,7 +732,7 @@ do
--- The MENU_GROUP class --- The MENU_GROUP class
-- @type MENU_GROUP -- @type MENU_GROUP
-- @extends Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
-- @usage -- @usage
-- -- This demo creates a menu structure for the two groups of planes. -- -- This demo creates a menu structure for the two groups of planes.
-- -- Each group will receive a different menu structure. -- -- Each group will receive a different menu structure.
@@ -769,8 +806,6 @@ do
self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) ) self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
MenuGroup._Menus[Path] = self MenuGroup._Menus[Path] = self
self.Menus = {}
self.MenuGroup = MenuGroup self.MenuGroup = MenuGroup
self.Path = Path self.Path = Path
self.MenuGroupID = MenuGroup:GetID() self.MenuGroupID = MenuGroup:GetID()
@@ -780,8 +815,10 @@ do
self:T( { "Adding Menu ", MenuText, self.MenuParentPath } ) self:T( { "Adding Menu ", MenuText, self.MenuParentPath } )
self.MenuPath = missionCommands.addSubMenuForGroup( self.MenuGroupID, MenuText, self.MenuParentPath ) self.MenuPath = missionCommands.addSubMenuForGroup( self.MenuGroupID, MenuText, self.MenuParentPath )
if ParentMenu and ParentMenu.Menus then if self.ParentMenu and self.ParentMenu.Menus then
ParentMenu.Menus[self.MenuPath] = self self.ParentMenu.Menus[MenuText] = self
self:F( { self.ParentMenu.Menus, MenuText } )
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount + 1
end end
end end
@@ -792,42 +829,56 @@ do
--- Removes the sub menus recursively of this MENU_GROUP. --- Removes the sub menus recursively of this MENU_GROUP.
-- @param #MENU_GROUP self -- @param #MENU_GROUP self
-- @param MenuTime
-- @return #MENU_GROUP self -- @return #MENU_GROUP self
function MENU_GROUP:RemoveSubMenus() function MENU_GROUP:RemoveSubMenus( MenuTime )
self:F( self.MenuPath ) self:F2( { self.MenuPath, MenuTime, self.MenuTime } )
for MenuID, Menu in pairs( self.Menus ) do self:T( { "Removing Group SubMenus:", self.MenuGroup:GetName(), self.MenuPath } )
Menu:Remove() for MenuText, Menu in pairs( self.Menus ) do
Menu:Remove( MenuTime )
end end
end end
--- Removes the main menu and sub menus recursively of this MENU_GROUP. --- Removes the main menu and sub menus recursively of this MENU_GROUP.
-- @param #MENU_GROUP self -- @param #MENU_GROUP self
-- @param MenuTime
-- @return #nil -- @return #nil
function MENU_GROUP:Remove() function MENU_GROUP:Remove( MenuTime )
self:F( { self.MenuGroupID, self.MenuPath } ) self:F( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
self:RemoveSubMenus() self:RemoveSubMenus( MenuTime )
if not MenuTime or self.MenuTime ~= MenuTime then
if self.MenuGroup._Menus[self.Path] then if self.MenuGroup._Menus[self.Path] then
self = self.MenuGroup._Menus[self.Path] self = self.MenuGroup._Menus[self.Path]
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath ) missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
if self.ParentMenu then if self.ParentMenu then
self.ParentMenu.Menus[self.MenuPath] = nil self.ParentMenu.Menus[self.MenuText] = nil
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
if self.ParentMenu.MenuCount == 0 then
if self.MenuRemoveParent == true then
self:T( "Removing Parent Menu " )
self.ParentMenu:Remove()
end end
self:E( self.MenuGroup._Menus[self.Path] ) end
end
self:T( { "Removing Group Menu:", self.MenuGroup:GetName(), self.MenuGroup._Menus[self.Path].Path } )
self.MenuGroup._Menus[self.Path] = nil self.MenuGroup._Menus[self.Path] = nil
self = nil self = nil
end end
end
return nil return nil
end end
--- The MENU_GROUP_COMMAND class --- The MENU_GROUP_COMMAND class
-- @type MENU_GROUP_COMMAND -- @type MENU_GROUP_COMMAND
-- @extends Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
MENU_GROUP_COMMAND = { MENU_GROUP_COMMAND = {
ClassName = "MENU_GROUP_COMMAND" ClassName = "MENU_GROUP_COMMAND"
} }
@@ -839,13 +890,14 @@ do
-- @param ParentMenu The parent menu. -- @param ParentMenu The parent menu.
-- @param CommandMenuFunction A function that is called when the menu key is pressed. -- @param CommandMenuFunction A function that is called when the menu key is pressed.
-- @param CommandMenuArgument An argument for the function. -- @param CommandMenuArgument An argument for the function.
-- @return Menu#MENU_GROUP_COMMAND self -- @return #MENU_GROUP_COMMAND
function MENU_GROUP_COMMAND:New( MenuGroup, MenuText, ParentMenu, CommandMenuFunction, ... ) function MENU_GROUP_COMMAND:New( MenuGroup, MenuText, ParentMenu, CommandMenuFunction, ... )
MenuGroup._Menus = MenuGroup._Menus or {} MenuGroup._Menus = MenuGroup._Menus or {}
local Path = ( ParentMenu and ( table.concat( ParentMenu.MenuPath or {}, "@" ) .. "@" .. MenuText ) ) or MenuText local Path = ( ParentMenu and ( table.concat( ParentMenu.MenuPath or {}, "@" ) .. "@" .. MenuText ) ) or MenuText
if MenuGroup._Menus[Path] then if MenuGroup._Menus[Path] then
self = MenuGroup._Menus[Path] self = MenuGroup._Menus[Path]
self:T( { "Re-using Group Command Menu:", MenuGroup:GetName(), MenuText } )
else else
self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) ) self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
MenuGroup._Menus[Path] = self MenuGroup._Menus[Path] = self
@@ -856,34 +908,46 @@ do
self.MenuText = MenuText self.MenuText = MenuText
self.ParentMenu = ParentMenu self.ParentMenu = ParentMenu
self:T( { "Adding Command Menu ", MenuText, self.MenuParentPath } ) self:T( { "Adding Group Command Menu:", MenuGroup:GetName(), MenuText, self.MenuParentPath } )
self.MenuPath = missionCommands.addCommandForGroup( self.MenuGroupID, MenuText, self.MenuParentPath, self.MenuCallHandler, arg ) self.MenuPath = missionCommands.addCommandForGroup( self.MenuGroupID, MenuText, self.MenuParentPath, self.MenuCallHandler, arg )
if ParentMenu and ParentMenu.Menus then if self.ParentMenu and self.ParentMenu.Menus then
ParentMenu.Menus[self.MenuPath] = self self.ParentMenu.Menus[MenuText] = self
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount + 1
self:F( { ParentMenu.Menus, MenuText } )
end end
end end
--self:F( { MenuGroup:GetName(), MenuText, ParentMenu.MenuPath } )
return self return self
end end
--- Removes a menu structure for a group. --- Removes a menu structure for a group.
-- @param #MENU_GROUP_COMMAND self -- @param #MENU_GROUP_COMMAND self
-- @param MenuTime
-- @return #nil -- @return #nil
function MENU_GROUP_COMMAND:Remove() function MENU_GROUP_COMMAND:Remove( MenuTime )
self:F( { self.MenuGroupID, self.MenuPath } ) self:F( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
if not MenuTime or self.MenuTime ~= MenuTime then
if self.MenuGroup._Menus[self.Path] then if self.MenuGroup._Menus[self.Path] then
self = self.MenuGroup._Menus[self.Path] self = self.MenuGroup._Menus[self.Path]
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath ) missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
self.ParentMenu.Menus[self.MenuPath] = nil self:T( { "Removing Group Command Menu:", self.MenuGroup:GetName(), self.MenuText, self.Path, self.MenuGroup._Menus[self.Path].Path } )
self:E( self.MenuGroup._Menus[self.Path] )
self.ParentMenu.Menus[self.MenuText] = nil
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
if self.ParentMenu.MenuCount == 0 then
if self.MenuRemoveParent == true then
self:T( "Removing Parent Menu " )
self.ParentMenu:Remove()
end
end
self.MenuGroup._Menus[self.Path] = nil self.MenuGroup._Menus[self.Path] = nil
self = nil self = nil
end end
end
return nil return nil
end end

View File

@@ -1,26 +1,40 @@
--- This module contains the MESSAGE class. --- **Core** - MESSAGE class takes are of the **real-time notifications** and **messages to players** during a simulation.
--
-- ![Banner Image](..\Presentations\MESSAGE\Dia1.JPG)
--
-- ===
--
-- # 1) @{Message#MESSAGE} class, extends @{Base#BASE}
-- --
-- 1) @{Message#MESSAGE} class, extends @{Base#BASE}
-- =================================================
-- Message System to display Messages to Clients, Coalitions or All. -- Message System to display Messages to Clients, Coalitions or All.
-- Messages are shown on the display panel for an amount of seconds, and will then disappear. -- Messages are shown on the display panel for an amount of seconds, and will then disappear.
-- Messages can contain a category which is indicating the category of the message. -- Messages can contain a category which is indicating the category of the message.
-- --
-- 1.1) MESSAGE construction methods -- ## 1.1) MESSAGE construction
-- --------------------------------- --
-- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet. -- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
-- To send messages, you need to use the To functions. -- To send messages, you need to use the To functions.
-- --
-- 1.2) Send messages with MESSAGE To methods -- ## 1.2) Send messages to an audience
-- ------------------------------------------ --
-- Messages are sent to: -- Messages are sent:
--
-- * To a @{Client} using @{Message#MESSAGE.ToClient}().
-- * To a @{Group} using @{Message#MESSAGE.ToGroup}()
-- * To a coalition using @{Message#MESSAGE.ToCoalition}().
-- * To the red coalition using @{Message#MESSAGE.ToRed}().
-- * To the blue coalition using @{Message#MESSAGE.ToBlue}().
-- * To all Players using @{Message#MESSAGE.ToAll}().
--
-- ## 1.3) Send conditionally to an audience
--
-- Messages can be sent conditionally to an audience (when a condition is true):
--
-- * To all players using @{Message#MESSAGE.ToAllIf}().
-- * To a coalition using @{Message#MESSAGE.ToCoalitionIf}().
-- --
-- * Clients with @{Message#MESSAGE.ToClient}.
-- * Coalitions with @{Message#MESSAGE.ToCoalition}.
-- * All Players with @{Message#MESSAGE.ToAll}.
-- --
-- @module Message -- @module Message
-- @author FlightControl
--- The MESSAGE class --- The MESSAGE class
-- @type MESSAGE -- @type MESSAGE
@@ -229,80 +243,3 @@ function MESSAGE:ToAllIf( Condition )
return self return self
end end
----- The MESSAGEQUEUE class
---- @type MESSAGEQUEUE
--MESSAGEQUEUE = {
-- ClientGroups = {},
-- CoalitionSides = {}
--}
--
--function MESSAGEQUEUE:New( RefreshInterval )
-- local self = BASE:Inherit( self, BASE:New() )
-- self:F( { RefreshInterval } )
--
-- self.RefreshInterval = RefreshInterval
--
-- --self.DisplayFunction = routines.scheduleFunction( self._DisplayMessages, { self }, 0, RefreshInterval )
-- self.DisplayFunction = SCHEDULER:New( self, self._DisplayMessages, {}, 0, RefreshInterval )
--
-- return self
--end
--
----- This function is called automatically by the MESSAGEQUEUE scheduler.
--function MESSAGEQUEUE:_DisplayMessages()
--
-- -- First we display all messages that a coalition needs to receive... Also those who are not in a client (CA module clients...).
-- for CoalitionSideID, CoalitionSideData in pairs( self.CoalitionSides ) do
-- for MessageID, MessageData in pairs( CoalitionSideData.Messages ) do
-- if MessageData.MessageSent == false then
-- --trigger.action.outTextForCoalition( CoalitionSideID, MessageData.MessageCategory .. '\n' .. MessageData.MessageText:gsub("\n$",""):gsub("\n$",""), MessageData.MessageDuration )
-- MessageData.MessageSent = true
-- end
-- local MessageTimeLeft = ( MessageData.MessageTime + MessageData.MessageDuration ) - timer.getTime()
-- if MessageTimeLeft <= 0 then
-- MessageData = nil
-- end
-- end
-- end
--
-- -- Then we send the messages for each individual client, but also to be included are those Coalition messages for the Clients who belong to a coalition.
-- -- Because the Client messages will overwrite the Coalition messages (for that Client).
-- for ClientGroupName, ClientGroupData in pairs( self.ClientGroups ) do
-- for MessageID, MessageData in pairs( ClientGroupData.Messages ) do
-- if MessageData.MessageGroup == false then
-- trigger.action.outTextForGroup( Group.getByName(ClientGroupName):getID(), MessageData.MessageCategory .. '\n' .. MessageData.MessageText:gsub("\n$",""):gsub("\n$",""), MessageData.MessageDuration )
-- MessageData.MessageGroup = true
-- end
-- local MessageTimeLeft = ( MessageData.MessageTime + MessageData.MessageDuration ) - timer.getTime()
-- if MessageTimeLeft <= 0 then
-- MessageData = nil
-- end
-- end
--
-- -- Now check if the Client also has messages that belong to the Coalition of the Client...
-- for CoalitionSideID, CoalitionSideData in pairs( self.CoalitionSides ) do
-- for MessageID, MessageData in pairs( CoalitionSideData.Messages ) do
-- local CoalitionGroup = Group.getByName( ClientGroupName )
-- if CoalitionGroup and CoalitionGroup:getCoalition() == CoalitionSideID then
-- if MessageData.MessageCoalition == false then
-- trigger.action.outTextForGroup( Group.getByName(ClientGroupName):getID(), MessageData.MessageCategory .. '\n' .. MessageData.MessageText:gsub("\n$",""):gsub("\n$",""), MessageData.MessageDuration )
-- MessageData.MessageCoalition = true
-- end
-- end
-- local MessageTimeLeft = ( MessageData.MessageTime + MessageData.MessageDuration ) - timer.getTime()
-- if MessageTimeLeft <= 0 then
-- MessageData = nil
-- end
-- end
-- end
-- end
--
-- return true
--end
--
----- The _MessageQueue object is created when the MESSAGE class module is loaded.
----_MessageQueue = MESSAGEQUEUE:New( 0.5 )
--

View File

@@ -1,4 +1,4 @@
--- This module contains the POINT classes. --- **Core** - **POINT\_VEC** classes define an **extensive API** to **manage 3D points** in the simulation space.
-- --
-- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE} -- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE}
-- ================================================== -- ==================================================
@@ -27,6 +27,10 @@
-- --
-- local Vec3 = PointVec3:AddX( 100 ):AddZ( 150 ):GetVec3() -- local Vec3 = PointVec3:AddX( 100 ):AddZ( 150 ):GetVec3()
-- --
-- ## 1.3) Create waypoints for routes
--
-- A POINT_VEC3 can prepare waypoints for Ground, Air and Naval groups to be embedded into a Route.
--
-- --
-- ## 1.5) Smoke, flare, explode, illuminate -- ## 1.5) Smoke, flare, explode, illuminate
-- --
@@ -76,6 +80,7 @@
-- --
-- The current X, Altitude, Y axis can be retrieved with the methods @{#POINT_VEC2.GetX}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetY}() respectively. -- The current X, Altitude, Y axis can be retrieved with the methods @{#POINT_VEC2.GetX}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetY}() respectively.
-- The methods @{#POINT_VEC2.SetX}(), @{#POINT_VEC2.SetAlt}(), @{#POINT_VEC2.SetY}() change the respective axis with a new value. -- The methods @{#POINT_VEC2.SetX}(), @{#POINT_VEC2.SetAlt}(), @{#POINT_VEC2.SetY}() change the respective axis with a new value.
-- The current Lat(itude), Alt(itude), Lon(gitude) values can also be retrieved with the methods @{#POINT_VEC2.GetLat}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetLon}() respectively.
-- The current axis values can be changed by using the methods @{#POINT_VEC2.AddX}(), @{#POINT_VEC2.AddAlt}(), @{#POINT_VEC2.AddY}() -- The current axis values can be changed by using the methods @{#POINT_VEC2.AddX}(), @{#POINT_VEC2.AddAlt}(), @{#POINT_VEC2.AddY}()
-- to add or substract a value from the current respective axis value. -- to add or substract a value from the current respective axis value.
-- Note that the Set and Add methods return the current POINT_VEC2 object, so these manipulation methods can be chained... For example: -- Note that the Set and Add methods return the current POINT_VEC2 object, so these manipulation methods can be chained... For example:
@@ -119,7 +124,6 @@
--- The POINT_VEC3 class --- The POINT_VEC3 class
-- @type POINT_VEC3 -- @type POINT_VEC3
-- @extends Core.Base#BASE
-- @field #number x The x coordinate in 3D space. -- @field #number x The x coordinate in 3D space.
-- @field #number y The y coordinate in 3D space. -- @field #number y The y coordinate in 3D space.
-- @field #number z The z coordiante in 3D space. -- @field #number z The z coordiante in 3D space.
@@ -128,6 +132,7 @@
-- @field #POINT_VEC3.RoutePointAltType RoutePointAltType -- @field #POINT_VEC3.RoutePointAltType RoutePointAltType
-- @field #POINT_VEC3.RoutePointType RoutePointType -- @field #POINT_VEC3.RoutePointType RoutePointType
-- @field #POINT_VEC3.RoutePointAction RoutePointAction -- @field #POINT_VEC3.RoutePointAction RoutePointAction
-- @extends Core.Base#BASE
POINT_VEC3 = { POINT_VEC3 = {
ClassName = "POINT_VEC3", ClassName = "POINT_VEC3",
Metric = true, Metric = true,
@@ -146,9 +151,9 @@ POINT_VEC3 = {
--- The POINT_VEC2 class --- The POINT_VEC2 class
-- @type POINT_VEC2 -- @type POINT_VEC2
-- @extends #POINT_VEC3
-- @field Dcs.DCSTypes#Distance x The x coordinate in meters. -- @field Dcs.DCSTypes#Distance x The x coordinate in meters.
-- @field Dcs.DCSTypes#Distance y the y coordinate in meters. -- @field Dcs.DCSTypes#Distance y the y coordinate in meters.
-- @extends Core.Point#POINT_VEC3
POINT_VEC2 = { POINT_VEC2 = {
ClassName = "POINT_VEC2", ClassName = "POINT_VEC2",
} }
@@ -359,7 +364,7 @@ function POINT_VEC3:GetRandomVec3InRadius( OuterRadius, InnerRadius )
local RandomVec2 = self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) local RandomVec2 = self:GetRandomVec2InRadius( OuterRadius, InnerRadius )
local y = self:GetY() + math.random( InnerRadius, OuterRadius ) local y = self:GetY() + math.random( InnerRadius, OuterRadius )
local RandomVec3 = { x = RandomVec2.x, y = y, z = RandomVec2.z } local RandomVec3 = { x = RandomVec2.x, y = y, z = RandomVec2.y }
return RandomVec3 return RandomVec3
end end
@@ -525,9 +530,9 @@ function POINT_VEC3:RoutePointAir( AltType, Type, Action, Speed, SpeedLocked )
self:F2( { AltType, Type, Action, Speed, SpeedLocked } ) self:F2( { AltType, Type, Action, Speed, SpeedLocked } )
local RoutePoint = {} local RoutePoint = {}
RoutePoint.x = self:GetX() RoutePoint.x = self.x
RoutePoint.y = self:GetZ() RoutePoint.y = self.z
RoutePoint.alt = self:GetY() RoutePoint.alt = self.y
RoutePoint.alt_type = AltType RoutePoint.alt_type = AltType
RoutePoint.type = Type RoutePoint.type = Type
@@ -566,8 +571,8 @@ function POINT_VEC3:RoutePointGround( Speed, Formation )
self:F2( { Formation, Speed } ) self:F2( { Formation, Speed } )
local RoutePoint = {} local RoutePoint = {}
RoutePoint.x = self:GetX() RoutePoint.x = self.x
RoutePoint.y = self:GetZ() RoutePoint.y = self.z
RoutePoint.action = Formation or "" RoutePoint.action = Formation or ""
@@ -768,13 +773,27 @@ function POINT_VEC2:GetY()
return self.z return self.z
end end
--- Return the altitude of the land at the POINT_VEC2. --- Return the altitude (height) of the land at the POINT_VEC2.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @return #number The land altitude. -- @return #number The land altitude.
function POINT_VEC2:GetAlt() function POINT_VEC2:GetAlt()
return land.getHeight( { x = self.x, y = self.z } ) return land.getHeight( { x = self.x, y = self.z } )
end end
--- Return Return the Lat(itude) coordinate of the POINT_VEC2 (ie: (parent)POINT_VEC3.x).
-- @param #POINT_VEC2 self
-- @return #number The x coodinate.
function POINT_VEC2:GetLat()
return self.x
end
--- Return the Lon(gitude) coordinate of the POINT_VEC2 (ie: (parent)POINT_VEC3.z).
-- @param #POINT_VEC2 self
-- @return #number The y coodinate.
function POINT_VEC2:GetLon()
return self.z
end
--- Set the x coordinate of the POINT_VEC2. --- Set the x coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @param #number x The x coordinate. -- @param #number x The x coordinate.
@@ -793,6 +812,15 @@ function POINT_VEC2:SetY( y )
return self return self
end end
--- Set the Lat(itude) coordinate of the POINT_VEC2 (ie: POINT_VEC3.x).
-- @param #POINT_VEC2 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetLat( x )
self.x = x
return self
end
--- Set the altitude of the POINT_VEC2. --- Set the altitude of the POINT_VEC2.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @param #number Altitude The land altitude. If nothing (nil) is given, then the current land altitude is set. -- @param #number Altitude The land altitude. If nothing (nil) is given, then the current land altitude is set.
@@ -802,6 +830,15 @@ function POINT_VEC2:SetAlt( Altitude )
return self return self
end end
--- Set the Lon(gitude) coordinate of the POINT_VEC2 (ie: POINT_VEC3.z).
-- @param #POINT_VEC2 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetLon( z )
self.z = z
return self
end
--- Add to the x coordinate of the POINT_VEC2. --- Add to the x coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @param #number x The x coordinate. -- @param #number x The x coordinate.

View File

@@ -64,7 +64,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
-- Initialize the ObjectSchedulers array, which is a weakly coupled table. -- Initialize the ObjectSchedulers array, which is a weakly coupled table.
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array. -- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
self.ObjectSchedulers = self.ObjectSchedulers or {} -- setmetatable( {}, { __mode = "v" } ) self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } ) -- or {}
if Scheduler.MasterObject then if Scheduler.MasterObject then
self.ObjectSchedulers[self.CallID] = Scheduler self.ObjectSchedulers[self.CallID] = Scheduler
@@ -181,11 +181,15 @@ function SCHEDULEDISPATCHER:Start( Scheduler, CallID )
if CallID then if CallID then
local Schedule = self.Schedule[Scheduler] local Schedule = self.Schedule[Scheduler]
-- Only start when there is no ScheduleID defined!
-- This prevents to "Start" the scheduler twice with the same CallID...
if not Schedule[CallID].ScheduleID then
Schedule[CallID].ScheduleID = timer.scheduleFunction( Schedule[CallID].ScheduleID = timer.scheduleFunction(
Schedule[CallID].CallHandler, Schedule[CallID].CallHandler,
CallID, CallID,
timer.getTime() + Schedule[CallID].Start timer.getTime() + Schedule[CallID].Start
) )
end
else else
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
self:Start( Scheduler, CallID ) -- Recursive self:Start( Scheduler, CallID ) -- Recursive
@@ -198,7 +202,12 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
if CallID then if CallID then
local Schedule = self.Schedule[Scheduler] local Schedule = self.Schedule[Scheduler]
-- Only stop when there is a ScheduleID defined for the CallID.
-- So, when the scheduler was stopped before, do nothing.
if Schedule[CallID].ScheduleID then
timer.removeFunction( Schedule[CallID].ScheduleID ) timer.removeFunction( Schedule[CallID].ScheduleID )
Schedule[CallID].ScheduleID = nil
end
else else
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
self:Stop( Scheduler, CallID ) -- Recursive self:Stop( Scheduler, CallID ) -- Recursive
@@ -206,5 +215,13 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
end end
end end
function SCHEDULEDISPATCHER:Clear( Scheduler )
self:F2( { Scheduler = Scheduler } )
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
self:Stop( Scheduler, CallID ) -- Recursive
end
end

View File

@@ -1,4 +1,8 @@
--- This module contains the SCHEDULER class. --- **Core** - SCHEDULER prepares and handles the **execution of functions over scheduled time (intervals)**.
--
-- ![Banner Image](..\Presentations\SCHEDULER\Dia1.JPG)
--
-- ===
-- --
-- # 1) @{Scheduler#SCHEDULER} class, extends @{Base#BASE} -- # 1) @{Scheduler#SCHEDULER} class, extends @{Base#BASE}
-- --
@@ -147,6 +151,13 @@ function SCHEDULER:Remove( ScheduleID )
_SCHEDULEDISPATCHER:Remove( self, ScheduleID ) _SCHEDULEDISPATCHER:Remove( self, ScheduleID )
end end
--- Clears all pending schedules.
-- @param #SCHEDULER self
function SCHEDULER:Clear()
self:F3( )
_SCHEDULEDISPATCHER:Clear( self )
end

View File

@@ -1,4 +1,4 @@
--- This module contains the SET classes. --- **Core** - SET classes define **collections** of objects to perform **bulk actions** and logically **group** objects.
-- --
-- === -- ===
-- --
@@ -240,6 +240,7 @@ SET_BASE = {
Filter = {}, Filter = {},
Set = {}, Set = {},
List = {}, List = {},
Index = {},
} }
--- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names. --- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
@@ -258,10 +259,14 @@ function SET_BASE:New( Database )
self.YieldInterval = 10 self.YieldInterval = 10
self.TimeInterval = 0.001 self.TimeInterval = 0.001
self.Set = {}
self.List = {} self.List = {}
self.List.__index = self.List self.List.__index = self.List
self.List = setmetatable( { Count = 0 }, self.List ) self.List = setmetatable( { Count = 0 }, self.List )
self.Index = {}
self.CallScheduler = SCHEDULER:New( self ) self.CallScheduler = SCHEDULER:New( self )
self:SetEventPriority( 2 ) self:SetEventPriority( 2 )
@@ -313,6 +318,8 @@ function SET_BASE:Add( ObjectName, Object )
self.Set[ObjectName] = t._ self.Set[ObjectName] = t._
table.insert( self.Index, ObjectName )
end end
--- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using the Object Name as the index. --- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using the Object Name as the index.
@@ -364,7 +371,15 @@ function SET_BASE:Remove( ObjectName )
t._prev = nil t._prev = nil
self.List.Count = self.List.Count - 1 self.List.Count = self.List.Count - 1
for Index, Key in ipairs( self.Index ) do
if Key == ObjectName then
table.remove( self.Index, Index )
break
end
end
self.Set[ObjectName] = nil self.Set[ObjectName] = nil
end end
end end
@@ -384,12 +399,50 @@ function SET_BASE:Get( ObjectName )
end end
--- Gets the first object from the @{Set#SET_BASE} and derived classes.
-- @param #SET_BASE self
-- @return Core.Base#BASE
function SET_BASE:GetFirst()
self:F()
local ObjectName = self.Index[1]
local FirstObject = self.Set[ObjectName]
self:T3( { FirstObject } )
return FirstObject
end
--- Gets the last object from the @{Set#SET_BASE} and derived classes.
-- @param #SET_BASE self
-- @return Core.Base#BASE
function SET_BASE:GetLast()
self:F()
local ObjectName = self.Index[#self.Index]
local LastObject = self.Set[ObjectName]
self:T3( { LastObject } )
return LastObject
end
--- Gets a random object from the @{Set#SET_BASE} and derived classes.
-- @param #SET_BASE self
-- @return Core.Base#BASE
function SET_BASE:GetRandom()
self:F()
local RandomItem = self.Set[self.Index[math.random(#self.Index)]]
self:T3( { RandomItem } )
return RandomItem
end
--- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes. --- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes.
-- @param #SET_BASE self -- @param #SET_BASE self
-- @return #number Count -- @return #number Count
function SET_BASE:Count() function SET_BASE:Count()
return self.List.Count return #self.Index
end end
@@ -538,7 +591,7 @@ function SET_BASE:_EventOnBirth( Event )
if Event.IniDCSUnit then if Event.IniDCSUnit then
local ObjectName, Object = self:AddInDatabase( Event ) local ObjectName, Object = self:AddInDatabase( Event )
self:T3( ObjectName, Object ) self:T3( ObjectName, Object )
if self:IsIncludeObject( Object ) then if Object and self:IsIncludeObject( Object ) then
self:Add( ObjectName, Object ) self:Add( ObjectName, Object )
--self:_EventOnPlayerEnterUnit( Event ) --self:_EventOnPlayerEnterUnit( Event )
end end
@@ -652,7 +705,8 @@ function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArgumen
return false return false
end end
self.CallScheduler:Schedule( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 ) --self.CallScheduler:Schedule( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 )
Schedule()
return self return self
end end
@@ -725,7 +779,7 @@ end
--- SET_GROUP class --- SET_GROUP class
-- @type SET_GROUP -- @type SET_GROUP
-- @extends #SET_BASE -- @extends Core.Set#SET_BASE
SET_GROUP = { SET_GROUP = {
ClassName = "SET_GROUP", ClassName = "SET_GROUP",
Filter = { Filter = {
@@ -908,10 +962,12 @@ end
function SET_GROUP:AddInDatabase( Event ) function SET_GROUP:AddInDatabase( Event )
self:F3( { Event } ) self:F3( { Event } )
if Event.IniObjectCategory == 1 then
if not self.Database[Event.IniDCSGroupName] then if not self.Database[Event.IniDCSGroupName] then
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName ) self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
self:T3( self.Database[Event.IniDCSGroupName] ) self:T3( self.Database[Event.IniDCSGroupName] )
end end
end
return Event.IniDCSGroupName, self.Database[Event.IniDCSGroupName] return Event.IniDCSGroupName, self.Database[Event.IniDCSGroupName]
end end
@@ -1333,10 +1389,12 @@ end
function SET_UNIT:AddInDatabase( Event ) function SET_UNIT:AddInDatabase( Event )
self:F3( { Event } ) self:F3( { Event } )
if Event.IniObjectCategory == 1 then
if not self.Database[Event.IniDCSUnitName] then if not self.Database[Event.IniDCSUnitName] then
self.Database[Event.IniDCSUnitName] = UNIT:Register( Event.IniDCSUnitName ) self.Database[Event.IniDCSUnitName] = UNIT:Register( Event.IniDCSUnitName )
self:T3( self.Database[Event.IniDCSUnitName] ) self:T3( self.Database[Event.IniDCSUnitName] )
end end
end
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end end

View File

@@ -1,4 +1,8 @@
--- This core module contains the ZONE classes, inherited from @{Zone#ZONE_BASE}. --- **Core** - ZONE classes define **zones** within your mission of **various forms**, with **various capabilities**.
--
-- ![Banner Image](..\Presentations\ZONE\Dia1.JPG)
--
-- ===
-- --
-- There are essentially two core functions that zones accomodate: -- There are essentially two core functions that zones accomodate:
-- --
@@ -171,7 +175,6 @@
-- === -- ===
-- --
-- @module Zone -- @module Zone
-- @author FlightControl
--- The ZONE_BASE class --- The ZONE_BASE class
@@ -246,6 +249,58 @@ function ZONE_BASE:GetVec2()
return nil return nil
end end
--- Returns a @{Point#POINT_VEC2} of the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC2 The PointVec2 of the zone.
function ZONE_BASE:GetPointVec2()
self:F2( self.ZoneName )
local Vec2 = self:GetVec2()
local PointVec2 = POINT_VEC2:NewFromVec2( Vec2 )
self:T2( { PointVec2 } )
return PointVec2
end
--- Returns the @{DCSTypes#Vec3} of the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Dcs.DCSTypes#Vec3 The Vec3 of the zone.
function ZONE_BASE:GetVec3( Height )
self:F2( self.ZoneName )
Height = Height or 0
local Vec2 = self:GetVec2()
local Vec3 = { x = Vec2.x, y = land.getHeight( self:GetVec2() ) + Height, z = Vec2.y }
self:T2( { Vec3 } )
return Vec3
end
--- Returns a @{Point#POINT_VEC3} of the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC3 The PointVec3 of the zone.
function ZONE_BASE:GetPointVec3( Height )
self:F2( self.ZoneName )
local Vec3 = self:GetVec3( Height )
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 )
self:T2( { PointVec3 } )
return PointVec3
end
--- Define a random @{DCSTypes#Vec2} within the zone. --- Define a random @{DCSTypes#Vec2} within the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinates. -- @return Dcs.DCSTypes#Vec2 The Vec2 coordinates.
@@ -260,6 +315,13 @@ function ZONE_BASE:GetRandomPointVec2()
return nil return nil
end end
--- Define a random @{Point#POINT_VEC3} within the zone.
-- @param #ZONE_BASE self
-- @return Core.Point#POINT_VEC3 The PointVec3 coordinates.
function ZONE_BASE:GetRandomPointVec3()
return nil
end
--- Get the bounding square the zone. --- Get the bounding square the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #nil The bounding square. -- @return #nil The bounding square.
@@ -268,6 +330,12 @@ function ZONE_BASE:GetBoundingSquare()
return nil return nil
end end
--- Bound the zone boundaries with a tires.
-- @param #ZONE_BASE self
function ZONE_BASE:BoundZone()
self:F2()
end
--- Smokes the zone boundaries in a color. --- Smokes the zone boundaries in a color.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
@@ -328,7 +396,7 @@ ZONE_RADIUS = {
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone. -- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
-- @return #ZONE_RADIUS self -- @return #ZONE_RADIUS self
function ZONE_RADIUS:New( ZoneName, Vec2, Radius ) function ZONE_RADIUS:New( ZoneName, Vec2, Radius )
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS
self:F( { ZoneName, Vec2, Radius } ) self:F( { ZoneName, Vec2, Radius } )
self.Radius = Radius self.Radius = Radius
@@ -337,6 +405,52 @@ function ZONE_RADIUS:New( ZoneName, Vec2, Radius )
return self return self
end end
--- Bounds the zone with tires.
-- @param #ZONE_RADIUS self
-- @param #number Points (optional) The amount of points in the circle.
-- @param #boolean UnBound If true the tyres will be destroyed.
-- @return #ZONE_RADIUS self
function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound )
local Point = {}
local Vec2 = self:GetVec2()
Points = Points and Points or 360
local Angle
local RadialBase = math.pi*2
--
for Angle = 0, 360, (360 / Points ) do
local Radial = Angle * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
local CountryName = _DATABASE.COUNTRY_NAME[CountryID]
local Tire = {
["country"] = CountryName,
["category"] = "Fortifications",
["canCargo"] = false,
["shape_name"] = "H-tyre_B_WF",
["type"] = "Black_Tyre_WF",
--["unitId"] = Angle + 10000,
["y"] = Point.y,
["x"] = Point.x,
["name"] = string.format( "%s-Tire #%0d", self:GetName(), Angle ),
["heading"] = 0,
} -- end of ["group"]
local Group = coalition.addStaticObject( CountryID, Tire )
if UnBound and UnBound == true then
Group:destroy()
end
end
return self
end
--- Smokes the zone boundaries in a color. --- Smokes the zone boundaries in a color.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color. -- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
@@ -761,6 +875,54 @@ function ZONE_POLYGON_BASE:Flush()
return self return self
end end
--- Smokes the zone boundaries in a color.
-- @param #ZONE_POLYGON_BASE self
-- @param #boolean UnBound If true, the tyres will be destroyed.
-- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:BoundZone( UnBound )
local i
local j
local Segments = 10
i = 1
j = #self.Polygon
while i <= #self.Polygon do
self:T( { i, j, self.Polygon[i], self.Polygon[j] } )
local DeltaX = self.Polygon[j].x - self.Polygon[i].x
local DeltaY = self.Polygon[j].y - self.Polygon[i].y
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
local PointX = self.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self.Polygon[i].y + ( Segment * DeltaY / Segments )
local Tire = {
["country"] = "USA",
["category"] = "Fortifications",
["canCargo"] = false,
["shape_name"] = "H-tyre_B_WF",
["type"] = "Black_Tyre_WF",
["y"] = PointY,
["x"] = PointX,
["name"] = string.format( "%s-Tire #%0d", self:GetName(), ((i - 1) * Segments) + Segment ),
["heading"] = 0,
} -- end of ["group"]
local Group = coalition.addStaticObject( country.id.USA, Tire )
if UnBound and UnBound == true then
Group:destroy()
end
end
j = i
i = i + 1
end
return self
end
--- Smokes the zone boundaries in a color. --- Smokes the zone boundaries in a color.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self

View File

@@ -29,7 +29,9 @@ CLEANUP = {
-- or -- or
-- CleanUpTbilisi = CLEANUP:New( 'CLEAN Tbilisi', 150 ) -- CleanUpTbilisi = CLEANUP:New( 'CLEAN Tbilisi', 150 )
-- CleanUpKutaisi = CLEANUP:New( 'CLEAN Kutaisi', 600 ) -- CleanUpKutaisi = CLEANUP:New( 'CLEAN Kutaisi', 600 )
function CLEANUP:New( ZoneNames, TimeInterval ) local self = BASE:Inherit( self, BASE:New() ) function CLEANUP:New( ZoneNames, TimeInterval )
local self = BASE:Inherit( self, BASE:New() ) -- #CLEANUP
self:F( { ZoneNames, TimeInterval } ) self:F( { ZoneNames, TimeInterval } )
if type( ZoneNames ) == 'table' then if type( ZoneNames ) == 'table' then
@@ -41,7 +43,7 @@ function CLEANUP:New( ZoneNames, TimeInterval ) local self = BASE:Inherit( self,
self.TimeInterval = TimeInterval self.TimeInterval = TimeInterval
end end
_EVENTDISPATCHER:OnBirth( self._OnEventBirth, self ) self:HandleEvent( EVENTS.Birth )
self.CleanUpScheduler = SCHEDULER:New( self, self._CleanUpScheduler, {}, 1, TimeInterval ) self.CleanUpScheduler = SCHEDULER:New( self, self._CleanUpScheduler, {}, 1, TimeInterval )
@@ -102,32 +104,24 @@ function CLEANUP:_DestroyMissile( MissileObject )
end end
end end
function CLEANUP:_OnEventBirth( Event ) --- @param #CLEANUP self
self:F( { Event } ) -- @param Core.Event#EVENTDATA EventData
function CLEANUP:_OnEventBirth( EventData )
self:F( { EventData } )
self.CleanUpList[Event.IniDCSUnitName] = {} self.CleanUpList[EventData.IniDCSUnitName] = {}
self.CleanUpList[Event.IniDCSUnitName].CleanUpUnit = Event.IniDCSUnit self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnit = EventData.IniDCSUnit
self.CleanUpList[Event.IniDCSUnitName].CleanUpGroup = Event.IniDCSGroup self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroup = EventData.IniDCSGroup
self.CleanUpList[Event.IniDCSUnitName].CleanUpGroupName = Event.IniDCSGroupName self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroupName = EventData.IniDCSGroupName
self.CleanUpList[Event.IniDCSUnitName].CleanUpUnitName = Event.IniDCSUnitName self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnitName = EventData.IniDCSUnitName
_EVENTDISPATCHER:OnEngineShutDownForUnit( Event.IniDCSUnitName, self._EventAddForCleanUp, self )
_EVENTDISPATCHER:OnEngineStartUpForUnit( Event.IniDCSUnitName, self._EventAddForCleanUp, self )
_EVENTDISPATCHER:OnHitForUnit( Event.IniDCSUnitName, self._EventAddForCleanUp, self )
_EVENTDISPATCHER:OnPilotDeadForUnit( Event.IniDCSUnitName, self._EventCrash, self )
_EVENTDISPATCHER:OnDeadForUnit( Event.IniDCSUnitName, self._EventCrash, self )
_EVENTDISPATCHER:OnCrashForUnit( Event.IniDCSUnitName, self._EventCrash, self )
_EVENTDISPATCHER:OnShotForUnit( Event.IniDCSUnitName, self._EventShot, self )
--self:AddEvent( world.event.S_EVENT_ENGINE_SHUTDOWN, self._EventAddForCleanUp )
--self:AddEvent( world.event.S_EVENT_ENGINE_STARTUP, self._EventAddForCleanUp )
-- self:AddEvent( world.event.S_EVENT_HIT, self._EventAddForCleanUp ) -- , self._EventHitCleanUp )
-- self:AddEvent( world.event.S_EVENT_CRASH, self._EventCrash ) -- , self._EventHitCleanUp )
-- --self:AddEvent( world.event.S_EVENT_DEAD, self._EventCrash )
-- self:AddEvent( world.event.S_EVENT_SHOT, self._EventShot )
--
-- self:EnableEvents()
EventData.IniUnit:HandleEvent( EVENTS.EngineShutdown , self._EventAddForCleanUp )
EventData.IniUnit:HandleEvent( EVENTS.EngineStartup, self._EventAddForCleanUp )
EventData.IniUnit:HandleEvent( EVENTS.Hit, self._EventAddForCleanUp )
EventData.IniUnit:HandleEvent( EVENTS.PilotDead, self._EventCrash )
EventData.IniUnit:HandleEvent( EVENTS.Dead, self._EventCrash )
EventData.IniUnit:HandleEvent( EVENTS.Crash, self._EventCrash )
EventData.IniUnit:HandleEvent( EVENTS.Shot, self._EventShot )
end end

File diff suppressed because it is too large Load Diff

View File

@@ -84,7 +84,7 @@
-- --
-- ESCORT initialization methods. -- ESCORT initialization methods.
-- ============================== -- ==============================
-- The following menus are created within the RADIO MENU of an active unit hosted by a player: -- The following menus are created within the RADIO MENU (F10) of an active unit hosted by a player:
-- --
-- * @{#ESCORT.MenuFollowAt}: Creates a menu to make the escort follow the client. -- * @{#ESCORT.MenuFollowAt}: Creates a menu to make the escort follow the client.
-- * @{#ESCORT.MenuHoldAtEscortPosition}: Creates a menu to hold the escort at its current position. -- * @{#ESCORT.MenuHoldAtEscortPosition}: Creates a menu to hold the escort at its current position.
@@ -128,6 +128,7 @@
-- @Field Dcs.DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup. -- @Field Dcs.DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup.
-- @field Dcs.DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup. -- @field Dcs.DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup.
-- @field Core.Menu#MENU_CLIENT EscortMenuResumeMission -- @field Core.Menu#MENU_CLIENT EscortMenuResumeMission
-- @field Functional.Detection#DETECTION_BASE Detection
ESCORT = { ESCORT = {
ClassName = "ESCORT", ClassName = "ESCORT",
EscortName = nil, -- The Escort Name EscortName = nil, -- The Escort Name
@@ -176,7 +177,8 @@ ESCORT = {
-- -- Now use these 2 objects to construct the new EscortPlanes object. -- -- Now use these 2 objects to construct the new EscortPlanes object.
-- EscortPlanes = ESCORT:New( EscortClient, 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 = ESCORT:New( EscortClient, 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." )
function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing ) function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
local self = BASE:Inherit( self, BASE:New() )
local self = BASE:Inherit( self, BASE:New() ) -- #ESCORT
self:F( { EscortClient, EscortGroup, EscortName } ) self:F( { EscortClient, EscortGroup, EscortName } )
self.EscortClient = EscortClient -- Wrapper.Client#CLIENT self.EscortClient = EscortClient -- Wrapper.Client#CLIENT
@@ -184,6 +186,13 @@ function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
self.EscortName = EscortName self.EscortName = EscortName
self.EscortBriefing = EscortBriefing self.EscortBriefing = EscortBriefing
self.EscortSetGroup = SET_GROUP:New()
self.EscortSetGroup:AddObject( self.EscortGroup )
self.EscortSetGroup:Flush()
self.Detection = DETECTION_UNITS:New( self.EscortSetGroup, 15000 )
self.EscortGroup.Detection = self.Detection
-- Set EscortGroup known at EscortClient. -- Set EscortGroup known at EscortClient.
if not self.EscortClient._EscortGroups then if not self.EscortClient._EscortGroups then
self.EscortClient._EscortGroups = {} self.EscortClient._EscortGroups = {}
@@ -193,7 +202,7 @@ function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
self.EscortClient._EscortGroups[EscortGroup:GetName()] = {} self.EscortClient._EscortGroups[EscortGroup:GetName()] = {}
self.EscortClient._EscortGroups[EscortGroup:GetName()].EscortGroup = self.EscortGroup self.EscortClient._EscortGroups[EscortGroup:GetName()].EscortGroup = self.EscortGroup
self.EscortClient._EscortGroups[EscortGroup:GetName()].EscortName = self.EscortName self.EscortClient._EscortGroups[EscortGroup:GetName()].EscortName = self.EscortName
self.EscortClient._EscortGroups[EscortGroup:GetName()].Targets = {} self.EscortClient._EscortGroups[EscortGroup:GetName()].Detection = self.EscortGroup.Detection
end end
self.EscortMenu = MENU_CLIENT:New( self.EscortClient, self.EscortName ) self.EscortMenu = MENU_CLIENT:New( self.EscortClient, self.EscortName )
@@ -218,13 +227,30 @@ function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
self.FollowDistance = 100 self.FollowDistance = 100
self.CT1 = 0 self.CT1 = 0
self.GT1 = 0 self.GT1 = 0
self.FollowScheduler = SCHEDULER:New( self, self._FollowScheduler, {}, 1, .5, .01 )
self.FollowScheduler, self.FollowSchedule = SCHEDULER:New( self, self._FollowScheduler, {}, 1, .5, .01 )
self.FollowScheduler:Stop( self.FollowSchedule )
self.EscortMode = ESCORT.MODE.MISSION self.EscortMode = ESCORT.MODE.MISSION
self.FollowScheduler:Stop()
return self return self
end end
--- Set a Detection method for the EscortClient to be reported upon.
-- Detection methods are based on the derived classes from DETECTION_BASE.
-- @param #ESCORT self
-- @param Function.Detection#DETECTION_BASE Detection
function ESCORT:SetDetection( Detection )
self.Detection = Detection
self.EscortGroup.Detection = self.Detection
self.EscortClient._EscortGroups[self.EscortGroup:GetName()].Detection = self.EscortGroup.Detection
Detection:__Start( 1 )
end
--- This function is for test, it will put on the frequency of the FollowScheduler a red smoke at the direction vector calculated for the escort to fly to. --- This function is for test, it will put on the frequency of the FollowScheduler a red smoke at the direction vector calculated for the escort to fly to.
-- This allows to visualize where the escort is flying to. -- This allows to visualize where the escort is flying to.
-- @param #ESCORT self -- @param #ESCORT self
@@ -282,7 +308,7 @@ function ESCORT:MenuFollowAt( Distance )
self.EscortMenuJoinUpAndFollow = {} self.EscortMenuJoinUpAndFollow = {}
end end
self.EscortMenuJoinUpAndFollow[#self.EscortMenuJoinUpAndFollow+1] = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow at " .. Distance, self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, { ParamSelf = self, ParamDistance = Distance } ) self.EscortMenuJoinUpAndFollow[#self.EscortMenuJoinUpAndFollow+1] = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow at " .. Distance, self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, self, Distance )
self.EscortMode = ESCORT.MODE.FOLLOW self.EscortMode = ESCORT.MODE.FOLLOW
end end
@@ -340,11 +366,10 @@ function ESCORT:MenuHoldAtEscortPosition( Height, Seconds, MenuTextFormat )
MenuText, MenuText,
self.EscortMenuHold, self.EscortMenuHold,
ESCORT._HoldPosition, ESCORT._HoldPosition,
{ ParamSelf = self, self,
ParamOrbitGroup = self.EscortGroup, self.EscortGroup,
ParamHeight = Height, Height,
ParamSeconds = Seconds Seconds
}
) )
end end
@@ -461,9 +486,8 @@ function ESCORT:MenuScanForTargets( Height, Seconds, MenuTextFormat )
MenuText, MenuText,
self.EscortMenuScan, self.EscortMenuScan,
ESCORT._ScanTargets, ESCORT._ScanTargets,
{ ParamSelf = self, self,
ParamScanDuration = 30 30
}
) )
end end
@@ -493,11 +517,11 @@ function ESCORT:MenuFlare( MenuTextFormat )
end end
if not self.EscortMenuFlare then if not self.EscortMenuFlare then
self.EscortMenuFlare = MENU_CLIENT:New( self.EscortClient, MenuText, self.EscortMenuReportNavigation, ESCORT._Flare, { ParamSelf = self } ) self.EscortMenuFlare = MENU_CLIENT:New( self.EscortClient, MenuText, self.EscortMenuReportNavigation, ESCORT._Flare, self )
self.EscortMenuFlareGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Green, ParamMessage = "Released a green flare!" } ) self.EscortMenuFlareGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green flare", self.EscortMenuFlare, ESCORT._Flare, self, FLARECOLOR.Green, "Released a green flare!" )
self.EscortMenuFlareRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Red, ParamMessage = "Released a red flare!" } ) self.EscortMenuFlareRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red flare", self.EscortMenuFlare, ESCORT._Flare, self, FLARECOLOR.Red, "Released a red flare!" )
self.EscortMenuFlareWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.White, ParamMessage = "Released a white flare!" } ) self.EscortMenuFlareWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white flare", self.EscortMenuFlare, ESCORT._Flare, self, FLARECOLOR.White, "Released a white flare!" )
self.EscortMenuFlareYellow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release yellow flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Yellow, ParamMessage = "Released a yellow flare!" } ) self.EscortMenuFlareYellow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release yellow flare", self.EscortMenuFlare, ESCORT._Flare, self, FLARECOLOR.Yellow, "Released a yellow flare!" )
end end
return self return self
@@ -526,12 +550,12 @@ function ESCORT:MenuSmoke( MenuTextFormat )
end end
if not self.EscortMenuSmoke then if not self.EscortMenuSmoke then
self.EscortMenuSmoke = MENU_CLIENT:New( self.EscortClient, "Smoke", self.EscortMenuReportNavigation, ESCORT._Smoke, { ParamSelf = self } ) self.EscortMenuSmoke = MENU_CLIENT:New( self.EscortClient, "Smoke", self.EscortMenuReportNavigation, ESCORT._Smoke, self )
self.EscortMenuSmokeGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.Green, ParamMessage = "Releasing green smoke!" } ) self.EscortMenuSmokeGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.Green, "Releasing green smoke!" )
self.EscortMenuSmokeRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.Red, ParamMessage = "Releasing red smoke!" } ) self.EscortMenuSmokeRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.Red, "Releasing red smoke!" )
self.EscortMenuSmokeWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.White, ParamMessage = "Releasing white smoke!" } ) self.EscortMenuSmokeWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.White, "Releasing white smoke!" )
self.EscortMenuSmokeOrange = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release orange smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.Orange, ParamMessage = "Releasing orange smoke!" } ) self.EscortMenuSmokeOrange = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release orange smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.Orange, "Releasing orange smoke!" )
self.EscortMenuSmokeBlue = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release blue smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.Blue, ParamMessage = "Releasing blue smoke!" } ) self.EscortMenuSmokeBlue = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release blue smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.Blue, "Releasing blue smoke!" )
end end
end end
@@ -556,9 +580,9 @@ function ESCORT:MenuReportTargets( Seconds )
end end
-- Report Targets -- Report Targets
self.EscortMenuReportNearbyTargetsNow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets now!", self.EscortMenuReportNearbyTargets, ESCORT._ReportNearbyTargetsNow, { ParamSelf = self } ) self.EscortMenuReportNearbyTargetsNow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets now!", self.EscortMenuReportNearbyTargets, ESCORT._ReportNearbyTargetsNow, self )
self.EscortMenuReportNearbyTargetsOn = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets on", self.EscortMenuReportNearbyTargets, ESCORT._SwitchReportNearbyTargets, { ParamSelf = self, ParamReportTargets = true } ) self.EscortMenuReportNearbyTargetsOn = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets on", self.EscortMenuReportNearbyTargets, ESCORT._SwitchReportNearbyTargets, self, true )
self.EscortMenuReportNearbyTargetsOff = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets off", self.EscortMenuReportNearbyTargets, ESCORT._SwitchReportNearbyTargets, { ParamSelf = self, ParamReportTargets = false, } ) self.EscortMenuReportNearbyTargetsOff = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets off", self.EscortMenuReportNearbyTargets, ESCORT._SwitchReportNearbyTargets, self, false )
-- Attack Targets -- Attack Targets
self.EscortMenuAttackNearbyTargets = MENU_CLIENT:New( self.EscortClient, "Attack targets", self.EscortMenu ) self.EscortMenuAttackNearbyTargets = MENU_CLIENT:New( self.EscortClient, "Attack targets", self.EscortMenu )
@@ -595,16 +619,16 @@ function ESCORT:MenuROE( MenuTextFormat )
-- Rules of Engagement -- Rules of Engagement
self.EscortMenuROE = MENU_CLIENT:New( self.EscortClient, "ROE", self.EscortMenu ) self.EscortMenuROE = MENU_CLIENT:New( self.EscortClient, "ROE", self.EscortMenu )
if self.EscortGroup:OptionROEHoldFirePossible() then if self.EscortGroup:OptionROEHoldFirePossible() then
self.EscortMenuROEHoldFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Hold Fire", self.EscortMenuROE, ESCORT._ROE, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROEHoldFire(), ParamMessage = "Holding weapons!" } ) self.EscortMenuROEHoldFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Hold Fire", self.EscortMenuROE, ESCORT._ROE, self, self.EscortGroup:OptionROEHoldFire(), "Holding weapons!" )
end end
if self.EscortGroup:OptionROEReturnFirePossible() then if self.EscortGroup:OptionROEReturnFirePossible() then
self.EscortMenuROEReturnFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Return Fire", self.EscortMenuROE, ESCORT._ROE, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROEReturnFire(), ParamMessage = "Returning fire!" } ) self.EscortMenuROEReturnFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Return Fire", self.EscortMenuROE, ESCORT._ROE, self, self.EscortGroup:OptionROEReturnFire(), "Returning fire!" )
end end
if self.EscortGroup:OptionROEOpenFirePossible() then if self.EscortGroup:OptionROEOpenFirePossible() then
self.EscortMenuROEOpenFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Open Fire", self.EscortMenuROE, ESCORT._ROE, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROEOpenFire(), ParamMessage = "Opening fire on designated targets!!" } ) self.EscortMenuROEOpenFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Open Fire", self.EscortMenuROE, ESCORT._ROE, self, self.EscortGroup:OptionROEOpenFire(), "Opening fire on designated targets!!" )
end end
if self.EscortGroup:OptionROEWeaponFreePossible() then if self.EscortGroup:OptionROEWeaponFreePossible() then
self.EscortMenuROEWeaponFree = MENU_CLIENT_COMMAND:New( self.EscortClient, "Weapon Free", self.EscortMenuROE, ESCORT._ROE, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROEWeaponFree(), ParamMessage = "Opening fire on targets of opportunity!" } ) self.EscortMenuROEWeaponFree = MENU_CLIENT_COMMAND:New( self.EscortClient, "Weapon Free", self.EscortMenuROE, ESCORT._ROE, self, self.EscortGroup:OptionROEWeaponFree(), "Opening fire on targets of opportunity!" )
end end
end end
@@ -624,16 +648,16 @@ function ESCORT:MenuEvasion( MenuTextFormat )
-- Reaction to Threats -- Reaction to Threats
self.EscortMenuEvasion = MENU_CLIENT:New( self.EscortClient, "Evasion", self.EscortMenu ) self.EscortMenuEvasion = MENU_CLIENT:New( self.EscortClient, "Evasion", self.EscortMenu )
if self.EscortGroup:OptionROTNoReactionPossible() then if self.EscortGroup:OptionROTNoReactionPossible() then
self.EscortMenuEvasionNoReaction = MENU_CLIENT_COMMAND:New( self.EscortClient, "Fight until death", self.EscortMenuEvasion, ESCORT._ROT, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROTNoReaction(), ParamMessage = "Fighting until death!" } ) self.EscortMenuEvasionNoReaction = MENU_CLIENT_COMMAND:New( self.EscortClient, "Fight until death", self.EscortMenuEvasion, ESCORT._ROT, self, self.EscortGroup:OptionROTNoReaction(), "Fighting until death!" )
end end
if self.EscortGroup:OptionROTPassiveDefensePossible() then if self.EscortGroup:OptionROTPassiveDefensePossible() then
self.EscortMenuEvasionPassiveDefense = MENU_CLIENT_COMMAND:New( self.EscortClient, "Use flares, chaff and jammers", self.EscortMenuEvasion, ESCORT._ROT, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROTPassiveDefense(), ParamMessage = "Defending using jammers, chaff and flares!" } ) self.EscortMenuEvasionPassiveDefense = MENU_CLIENT_COMMAND:New( self.EscortClient, "Use flares, chaff and jammers", self.EscortMenuEvasion, ESCORT._ROT, self, self.EscortGroup:OptionROTPassiveDefense(), "Defending using jammers, chaff and flares!" )
end end
if self.EscortGroup:OptionROTEvadeFirePossible() then if self.EscortGroup:OptionROTEvadeFirePossible() then
self.EscortMenuEvasionEvadeFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Evade enemy fire", self.EscortMenuEvasion, ESCORT._ROT, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROTEvadeFire(), ParamMessage = "Evading on enemy fire!" } ) self.EscortMenuEvasionEvadeFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Evade enemy fire", self.EscortMenuEvasion, ESCORT._ROT, self, self.EscortGroup:OptionROTEvadeFire(), "Evading on enemy fire!" )
end end
if self.EscortGroup:OptionROTVerticalPossible() then if self.EscortGroup:OptionROTVerticalPossible() then
self.EscortMenuOptionEvasionVertical = MENU_CLIENT_COMMAND:New( self.EscortClient, "Go below radar and evade fire", self.EscortMenuEvasion, ESCORT._ROT, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROTVertical(), ParamMessage = "Evading on enemy fire with vertical manoeuvres!" } ) self.EscortMenuOptionEvasionVertical = MENU_CLIENT_COMMAND:New( self.EscortClient, "Go below radar and evade fire", self.EscortMenuEvasion, ESCORT._ROT, self, self.EscortGroup:OptionROTVertical(), "Evading on enemy fire with vertical manoeuvres!" )
end end
end end
end end
@@ -658,18 +682,14 @@ end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._HoldPosition( MenuParam ) function ESCORT:_HoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local OrbitGroup = MenuParam.ParamOrbitGroup -- Wrapper.Group#GROUP
local OrbitUnit = OrbitGroup:GetUnit(1) -- Wrapper.Unit#UNIT local OrbitUnit = OrbitGroup:GetUnit(1) -- Wrapper.Unit#UNIT
local OrbitHeight = MenuParam.ParamHeight
local OrbitSeconds = MenuParam.ParamSeconds -- Not implemented yet
self.FollowScheduler:Stop() self.FollowScheduler:Stop( self.FollowSchedule )
local PointFrom = {} local PointFrom = {}
local GroupVec3 = EscortGroup:GetUnit(1):GetVec3() local GroupVec3 = EscortGroup:GetUnit(1):GetVec3()
@@ -702,13 +722,12 @@ function ESCORT._HoldPosition( MenuParam )
end end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._JoinUpAndFollow( MenuParam ) function ESCORT:_JoinUpAndFollow( Distance )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
self.Distance = MenuParam.ParamDistance self.Distance = Distance
self:JoinUpAndFollow( EscortGroup, EscortClient, self.Distance ) self:JoinUpAndFollow( EscortGroup, EscortClient, self.Distance )
end end
@@ -721,7 +740,7 @@ end
function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance ) function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
self:F( { EscortGroup, EscortClient, Distance } ) self:F( { EscortGroup, EscortClient, Distance } )
self.FollowScheduler:Stop() self.FollowScheduler:Stop( self.FollowSchedule )
EscortGroup:OptionROEHoldFire() EscortGroup:OptionROEHoldFire()
EscortGroup:OptionROTPassiveDefense() EscortGroup:OptionROTPassiveDefense()
@@ -730,44 +749,35 @@ function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
self.CT1 = 0 self.CT1 = 0
self.GT1 = 0 self.GT1 = 0
self.FollowScheduler:Start() self.FollowScheduler:Start( self.FollowSchedule )
EscortGroup:MessageToClient( "Rejoining and Following at " .. Distance .. "!", 30, EscortClient ) EscortGroup:MessageToClient( "Rejoining and Following at " .. Distance .. "!", 30, EscortClient )
end end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._Flare( MenuParam ) function ESCORT:_Flare( Color, Message )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local Color = MenuParam.ParamColor
local Message = MenuParam.ParamMessage
EscortGroup:GetUnit(1):Flare( Color ) EscortGroup:GetUnit(1):Flare( Color )
EscortGroup:MessageToClient( Message, 10, EscortClient ) EscortGroup:MessageToClient( Message, 10, EscortClient )
end end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._Smoke( MenuParam ) function ESCORT:_Smoke( Color, Message )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local Color = MenuParam.ParamColor
local Message = MenuParam.ParamMessage
EscortGroup:GetUnit(1):Smoke( Color ) EscortGroup:GetUnit(1):Smoke( Color )
EscortGroup:MessageToClient( Message, 10, EscortClient ) EscortGroup:MessageToClient( Message, 10, EscortClient )
end end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._ReportNearbyTargetsNow( MenuParam ) function ESCORT:_ReportNearbyTargetsNow()
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
@@ -775,17 +785,16 @@ function ESCORT._ReportNearbyTargetsNow( MenuParam )
end end
function ESCORT._SwitchReportNearbyTargets( MenuParam ) function ESCORT:_SwitchReportNearbyTargets( ReportTargets )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
self.ReportTargets = MenuParam.ParamReportTargets self.ReportTargets = ReportTargets
if self.ReportTargets then if self.ReportTargets then
if not self.ReportTargetsScheduler then if not self.ReportTargetsScheduler then
self.ReportTargetsScheduler = SCHEDULER:New( self, self._ReportTargetsScheduler, {}, 1, 30 ) self.ReportTargetsScheduler:Schedule( self, self._ReportTargetsScheduler, {}, 1, 30 )
end end
else else
routines.removeFunction( self.ReportTargetsScheduler ) routines.removeFunction( self.ReportTargetsScheduler )
@@ -794,40 +803,31 @@ function ESCORT._SwitchReportNearbyTargets( MenuParam )
end end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._ScanTargets( MenuParam ) function ESCORT:_ScanTargets( ScanDuration )
local self = MenuParam.ParamSelf local EscortGroup = self.EscortGroup -- Wrapper.Group#GROUP
local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local ScanDuration = MenuParam.ParamScanDuration self.FollowScheduler:Stop( self.FollowSchedule )
self.FollowScheduler:Stop()
if EscortGroup:IsHelicopter() then if EscortGroup:IsHelicopter() then
SCHEDULER:New( EscortGroup, EscortGroup.PushTask, EscortGroup:PushTask(
{ EscortGroup:TaskControlled( EscortGroup:TaskControlled(
EscortGroup:TaskOrbitCircle( 200, 20 ), EscortGroup:TaskOrbitCircle( 200, 20 ),
EscortGroup:TaskCondition( nil, nil, nil, nil, ScanDuration, nil ) EscortGroup:TaskCondition( nil, nil, nil, nil, ScanDuration, nil )
) ), 1 )
},
1
)
elseif EscortGroup:IsAirPlane() then elseif EscortGroup:IsAirPlane() then
SCHEDULER:New( EscortGroup, EscortGroup.PushTask, EscortGroup:PushTask(
{ EscortGroup:TaskControlled( EscortGroup:TaskControlled(
EscortGroup:TaskOrbitCircle( 1000, 500 ), EscortGroup:TaskOrbitCircle( 1000, 500 ),
EscortGroup:TaskCondition( nil, nil, nil, nil, ScanDuration, nil ) EscortGroup:TaskCondition( nil, nil, nil, nil, ScanDuration, nil )
) ), 1 )
},
1
)
end end
EscortGroup:MessageToClient( "Scanning targets for " .. ScanDuration .. " seconds.", ScanDuration, EscortClient ) EscortGroup:MessageToClient( "Scanning targets for " .. ScanDuration .. " seconds.", ScanDuration, EscortClient )
if self.EscortMode == ESCORT.MODE.FOLLOW then if self.EscortMode == ESCORT.MODE.FOLLOW then
self.FollowScheduler:Start() self.FollowScheduler:Start( self.FollowSchedule )
end end
end end
@@ -844,124 +844,157 @@ function _Resume( EscortGroup )
end end
--- @param #MENUPARAM MenuParam --- @param #ESCORT self
function ESCORT._AttackTarget( MenuParam ) -- @param #number DetectedItemID
function ESCORT:_AttackTarget( DetectedItemID )
local self = MenuParam.ParamSelf local EscortGroup = self.EscortGroup -- Wrapper.Group#GROUP
local EscortGroup = self.EscortGroup self:E( EscortGroup )
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local AttackUnit = MenuParam.ParamUnit -- Wrapper.Unit#UNIT
self.FollowScheduler:Stop() self.FollowScheduler:Stop( self.FollowSchedule )
self:T( AttackUnit )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
EscortGroup:OptionROEOpenFire() EscortGroup:OptionROEOpenFire()
EscortGroup:OptionROTPassiveDefense() EscortGroup:OptionROTPassiveDefense()
EscortGroup:SetState( EscortGroup, "Escort", self ) EscortGroup:SetState( EscortGroup, "Escort", self )
SCHEDULER:New( EscortGroup,
EscortGroup.PushTask, local DetectedSet = self.Detection:GetDetectedSet( DetectedItemID )
{ EscortGroup:TaskCombo(
{ EscortGroup:TaskAttackUnit( AttackUnit ), local Tasks = {}
EscortGroup:TaskFunction( 1, 2, "_Resume", { "''" } )
} DetectedSet:ForEachUnit(
--- @param Wrapper.Unit#UNIT DetectedUnit
function( DetectedUnit, Tasks )
if DetectedUnit:IsAlive() then
Tasks[#Tasks+1] = EscortGroup:TaskAttackUnit( DetectedUnit )
end
end, Tasks
) )
}, 10
Tasks[#Tasks+1] = EscortGroup:TaskFunction( 1, 2, "_Resume", { "''" } )
EscortGroup:SetTask(
EscortGroup:TaskCombo(
Tasks
), 1
) )
else else
SCHEDULER:New( EscortGroup,
EscortGroup.PushTask, local DetectedSet = self.Detection:GetDetectedSet( DetectedItemID )
{ EscortGroup:TaskCombo(
{ EscortGroup:TaskFireAtPoint( AttackUnit:GetVec2(), 50 ) local Tasks = {}
}
DetectedSet:ForEachUnit(
--- @param Wrapper.Unit#UNIT DetectedUnit
function( DetectedUnit, Tasks )
if DetectedUnit:IsAlive() then
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
end
end, Tasks
) )
}, 10
EscortGroup:SetTask(
EscortGroup:TaskCombo(
Tasks
), 1
) )
end end
EscortGroup:MessageToClient( "Engaging Designated Unit!", 10, EscortClient ) EscortGroup:MessageToClient( "Engaging Designated Unit!", 10, EscortClient )
end end
--- @param #MENUPARAM MenuParam ---
function ESCORT._AssistTarget( MenuParam ) -- @param #number DetectedItemID
function ESCORT:_AssistTarget( EscortGroupAttack, DetectedItemID )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local EscortGroupAttack = MenuParam.ParamEscortGroup
local AttackUnit = MenuParam.ParamUnit -- Wrapper.Unit#UNIT
self.FollowScheduler:Stop() self.FollowScheduler:Stop( self.FollowSchedule )
self:T( AttackUnit )
if EscortGroupAttack:IsAir() then if EscortGroupAttack:IsAir() then
EscortGroupAttack:OptionROEOpenFire() EscortGroupAttack:OptionROEOpenFire()
EscortGroupAttack:OptionROTVertical() EscortGroupAttack:OptionROTVertical()
SCHDULER:New( EscortGroupAttack,
EscortGroupAttack.PushTask, local DetectedSet = self.Detection:GetDetectedSet( DetectedItemID )
{ EscortGroupAttack:TaskCombo(
{ EscortGroupAttack:TaskAttackUnit( AttackUnit ), local Tasks = {}
EscortGroupAttack:TaskOrbitCircle( 500, 350 )
} DetectedSet:ForEachUnit(
) --- @param Wrapper.Unit#UNIT DetectedUnit
}, 10 function( DetectedUnit, Tasks )
) if DetectedUnit:IsAlive() then
else Tasks[#Tasks+1] = EscortGroupAttack:TaskAttackUnit( DetectedUnit )
SCHEDULER:New( EscortGroupAttack,
EscortGroupAttack.PushTask,
{ EscortGroupAttack:TaskCombo(
{ EscortGroupAttack:TaskFireAtPoint( AttackUnit:GetVec2(), 50 )
}
)
}, 10
)
end end
end, Tasks
)
Tasks[#Tasks+1] = EscortGroupAttack:TaskOrbitCircle( 500, 350 )
EscortGroupAttack:SetTask(
EscortGroupAttack:TaskCombo(
Tasks
), 1
)
else
local DetectedSet = self.Detection:GetDetectedSet( DetectedItemID )
local Tasks = {}
DetectedSet:ForEachUnit(
--- @param Wrapper.Unit#UNIT DetectedUnit
function( DetectedUnit, Tasks )
if DetectedUnit:IsAlive() then
Tasks[#Tasks+1] = EscortGroupAttack:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
end
end, Tasks
)
EscortGroupAttack:SetTask(
EscortGroupAttack:TaskCombo(
Tasks
), 1
)
end
EscortGroupAttack:MessageToClient( "Assisting with the destroying the enemy unit!", 10, EscortClient ) EscortGroupAttack:MessageToClient( "Assisting with the destroying the enemy unit!", 10, EscortClient )
end end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._ROE( MenuParam ) function ESCORT:_ROE( EscortROEFunction, EscortROEMessage )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local EscortROEFunction = MenuParam.ParamFunction
local EscortROEMessage = MenuParam.ParamMessage
pcall( function() EscortROEFunction() end ) pcall( function() EscortROEFunction() end )
EscortGroup:MessageToClient( EscortROEMessage, 10, EscortClient ) EscortGroup:MessageToClient( EscortROEMessage, 10, EscortClient )
end end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._ROT( MenuParam ) function ESCORT:_ROT( EscortROTFunction, EscortROTMessage )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local EscortROTFunction = MenuParam.ParamFunction
local EscortROTMessage = MenuParam.ParamMessage
pcall( function() EscortROTFunction() end ) pcall( function() EscortROTFunction() end )
EscortGroup:MessageToClient( EscortROTMessage, 10, EscortClient ) EscortGroup:MessageToClient( EscortROTMessage, 10, EscortClient )
end end
--- @param #MENUPARAM MenuParam --- @param #MENUPARAM MenuParam
function ESCORT._ResumeMission( MenuParam ) function ESCORT:_ResumeMission( WayPoint )
local self = MenuParam.ParamSelf
local EscortGroup = self.EscortGroup local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient local EscortClient = self.EscortClient
local WayPoint = MenuParam.ParamWayPoint self.FollowScheduler:Stop( self.FollowSchedule )
self.FollowScheduler:Stop()
local WayPoints = EscortGroup:GetTaskRoute() local WayPoints = EscortGroup:GetTaskRoute()
self:T( WayPoint, WayPoints ) self:T( WayPoint, WayPoints )
@@ -1089,7 +1122,7 @@ function ESCORT:_FollowScheduler()
self:T( { "Client Speed, Escort Speed, Speed, FollowDistance, Time:", CS, GS, Speed, FollowDistance, Time } ) self:T( { "Client Speed, Escort Speed, Speed, FollowDistance, Time:", CS, GS, Speed, FollowDistance, Time } )
-- Now route the escort to the desired point with the desired speed. -- Now route the escort to the desired point with the desired speed.
self.EscortGroup:TaskRouteToVec3( GDV, Speed / 3.6 ) -- DCS models speed in Mps (Miles per second) self.EscortGroup:RouteToVec3( GDV, Speed / 3.6 ) -- DCS models speed in Mps (Miles per second)
end end
return true return true
@@ -1105,176 +1138,244 @@ function ESCORT:_ReportTargetsScheduler()
self:F( self.EscortGroup:GetName() ) self:F( self.EscortGroup:GetName() )
if self.EscortGroup:IsAlive() and self.EscortClient:IsAlive() then if self.EscortGroup:IsAlive() and self.EscortClient:IsAlive() then
if true then
local EscortGroupName = self.EscortGroup:GetName() local EscortGroupName = self.EscortGroup:GetName()
local EscortTargets = self.EscortGroup:GetDetectedTargets()
local ClientEscortTargets = self.EscortClient._EscortGroups[EscortGroupName].Targets
local EscortTargetMessages = ""
for EscortTargetID, EscortTarget in pairs( EscortTargets ) do
local EscortObject = EscortTarget.object
self:T( EscortObject )
if EscortObject and EscortObject:isExist() and EscortObject.id_ < 50000000 then
local EscortTargetUnit = UNIT:Find( EscortObject )
local EscortTargetUnitName = EscortTargetUnit:GetName()
-- local EscortTargetIsDetected,
-- EscortTargetIsVisible,
-- EscortTargetLastTime,
-- EscortTargetKnowType,
-- EscortTargetKnowDistance,
-- EscortTargetLastPos,
-- EscortTargetLastVelocity
-- = self.EscortGroup:IsTargetDetected( EscortObject )
--
-- self:T( { EscortTargetIsDetected,
-- EscortTargetIsVisible,
-- EscortTargetLastTime,
-- EscortTargetKnowType,
-- EscortTargetKnowDistance,
-- EscortTargetLastPos,
-- EscortTargetLastVelocity } )
local EscortTargetUnitVec3 = EscortTargetUnit:GetVec3()
local EscortVec3 = self.EscortGroup:GetVec3()
local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
( EscortTargetUnitVec3.z - EscortVec3.z )^2
) ^ 0.5 / 1000
self:T( { self.EscortGroup:GetName(), EscortTargetUnit:GetName(), Distance, EscortTarget } )
if Distance <= 15 then
if not ClientEscortTargets[EscortTargetUnitName] then
ClientEscortTargets[EscortTargetUnitName] = {}
end
ClientEscortTargets[EscortTargetUnitName].AttackUnit = EscortTargetUnit
ClientEscortTargets[EscortTargetUnitName].visible = EscortTarget.visible
ClientEscortTargets[EscortTargetUnitName].type = EscortTarget.type
ClientEscortTargets[EscortTargetUnitName].distance = EscortTarget.distance
else
if ClientEscortTargets[EscortTargetUnitName] then
ClientEscortTargets[EscortTargetUnitName] = nil
end
end
end
end
self:T( { "Sorting Targets Table:", ClientEscortTargets } )
table.sort( ClientEscortTargets, function( a, b ) return a.Distance < b.Distance end )
self:T( { "Sorted Targets Table:", ClientEscortTargets } )
-- Remove the sub menus of the Attack menu of the Escort for the EscortGroup.
self.EscortMenuAttackNearbyTargets:RemoveSubMenus() self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
if self.EscortMenuTargetAssistance then if self.EscortMenuTargetAssistance then
self.EscortMenuTargetAssistance:RemoveSubMenus() self.EscortMenuTargetAssistance:RemoveSubMenus()
end end
--for MenuIndex = 1, #self.EscortMenuAttackTargets do local DetectedItems = self.Detection:GetDetectedItems()
-- self:T( { "Remove Menu:", self.EscortMenuAttackTargets[MenuIndex] } ) self:E( DetectedItems )
-- self.EscortMenuAttackTargets[MenuIndex] = self.EscortMenuAttackTargets[MenuIndex]:Remove()
--end
local DetectedTargets = false
if ClientEscortTargets then local DetectedMsgs = {}
for ClientEscortTargetUnitName, ClientEscortTargetData in pairs( ClientEscortTargets ) do
for ClientEscortGroupName, EscortGroupData in pairs( self.EscortClient._EscortGroups ) do for ClientEscortGroupName, EscortGroupData in pairs( self.EscortClient._EscortGroups ) do
if ClientEscortTargetData and ClientEscortTargetData.AttackUnit:IsAlive() then local ClientEscortTargets = EscortGroupData.Detection
local EscortTargetMessage = "" for DetectedItemID, DetectedItem in ipairs( DetectedItems ) do
local EscortTargetCategoryName = ClientEscortTargetData.AttackUnit:GetCategoryName() self:E( { DetectedItemID, DetectedItem } )
local EscortTargetCategoryType = ClientEscortTargetData.AttackUnit:GetTypeName() -- Remove the sub menus of the Attack menu of the Escort for the EscortGroup.
if ClientEscortTargetData.type then
EscortTargetMessage = EscortTargetMessage .. EscortTargetCategoryName .. " (" .. EscortTargetCategoryType .. ") at "
else
EscortTargetMessage = EscortTargetMessage .. "Unknown target at "
end
local EscortTargetUnitVec3 = ClientEscortTargetData.AttackUnit:GetVec3() local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItemID )
local EscortVec3 = self.EscortGroup:GetVec3()
local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
( EscortTargetUnitVec3.z - EscortVec3.z )^2
) ^ 0.5 / 1000
self:T( { self.EscortGroup:GetName(), ClientEscortTargetData.AttackUnit:GetName(), Distance, ClientEscortTargetData.AttackUnit } )
if ClientEscortTargetData.visible == false then
EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " estimated km"
else
EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " km"
end
if ClientEscortTargetData.visible then
EscortTargetMessage = EscortTargetMessage .. ", visual"
end
if ClientEscortGroupName == EscortGroupName then if ClientEscortGroupName == EscortGroupName then
DetectedMsgs[#DetectedMsgs+1] = DetectedItemReportSummary
MENU_CLIENT_COMMAND:New( self.EscortClient, MENU_CLIENT_COMMAND:New( self.EscortClient,
EscortTargetMessage, DetectedItemReportSummary,
self.EscortMenuAttackNearbyTargets, self.EscortMenuAttackNearbyTargets,
ESCORT._AttackTarget, ESCORT._AttackTarget,
{ ParamSelf = self, self,
ParamUnit = ClientEscortTargetData.AttackUnit DetectedItemID
}
) )
EscortTargetMessages = EscortTargetMessages .. "\n - " .. EscortTargetMessage
else else
if self.EscortMenuTargetAssistance then if self.EscortMenuTargetAssistance then
self:T( DetectedItemReportSummary )
local MenuTargetAssistance = MENU_CLIENT:New( self.EscortClient, EscortGroupData.EscortName, self.EscortMenuTargetAssistance ) local MenuTargetAssistance = MENU_CLIENT:New( self.EscortClient, EscortGroupData.EscortName, self.EscortMenuTargetAssistance )
MENU_CLIENT_COMMAND:New( self.EscortClient, MENU_CLIENT_COMMAND:New( self.EscortClient,
EscortTargetMessage, DetectedItemReportSummary,
MenuTargetAssistance, MenuTargetAssistance,
ESCORT._AssistTarget, ESCORT._AssistTarget,
{ ParamSelf = self, self,
ParamEscortGroup = EscortGroupData.EscortGroup, EscortGroupData.EscortGroup,
ParamUnit = ClientEscortTargetData.AttackUnit DetectedItemID
}
) )
end end
end end
DetectedTargets = true
end
end
self:E( DetectedMsgs )
if DetectedTargets then
self.EscortGroup:MessageToClient( "Detected targets:\n" .. table.concat( DetectedMsgs, "\n" ), 20, self.EscortClient )
else else
ClientEscortTargetData = nil self.EscortGroup:MessageToClient( "No targets detected.", 10, self.EscortClient )
end
end
end
if EscortTargetMessages ~= "" and self.ReportTargets == true then
self.EscortGroup:MessageToClient( "Detected targets within 15 km range:" .. EscortTargetMessages:gsub("\n$",""), 20, self.EscortClient )
else
self.EscortGroup:MessageToClient( "No targets detected!", 20, self.EscortClient )
end
end
if self.EscortMenuResumeMission then
self.EscortMenuResumeMission:RemoveSubMenus()
-- if self.EscortMenuResumeWayPoints then
-- for MenuIndex = 1, #self.EscortMenuResumeWayPoints do
-- self:T( { "Remove Menu:", self.EscortMenuResumeWayPoints[MenuIndex] } )
-- self.EscortMenuResumeWayPoints[MenuIndex] = self.EscortMenuResumeWayPoints[MenuIndex]:Remove()
-- end
-- end
local TaskPoints = self:RegisterRoute()
for WayPointID, WayPoint in pairs( TaskPoints ) do
local EscortVec3 = self.EscortGroup:GetVec3()
local Distance = ( ( WayPoint.x - EscortVec3.x )^2 +
( WayPoint.y - EscortVec3.z )^2
) ^ 0.5 / 1000
MENU_CLIENT_COMMAND:New( self.EscortClient, "Waypoint " .. WayPointID .. " at " .. string.format( "%.2f", Distance ).. "km", self.EscortMenuResumeMission, ESCORT._ResumeMission, { ParamSelf = self, ParamWayPoint = WayPointID } )
end
end end
return true return true
else
-- local EscortGroupName = self.EscortGroup:GetName()
-- local EscortTargets = self.EscortGroup:GetDetectedTargets()
--
-- local ClientEscortTargets = self.EscortClient._EscortGroups[EscortGroupName].Targets
--
-- local EscortTargetMessages = ""
-- for EscortTargetID, EscortTarget in pairs( EscortTargets ) do
-- local EscortObject = EscortTarget.object
-- self:T( EscortObject )
-- if EscortObject and EscortObject:isExist() and EscortObject.id_ < 50000000 then
--
-- local EscortTargetUnit = UNIT:Find( EscortObject )
-- local EscortTargetUnitName = EscortTargetUnit:GetName()
--
--
--
-- -- local EscortTargetIsDetected,
-- -- EscortTargetIsVisible,
-- -- EscortTargetLastTime,
-- -- EscortTargetKnowType,
-- -- EscortTargetKnowDistance,
-- -- EscortTargetLastPos,
-- -- EscortTargetLastVelocity
-- -- = self.EscortGroup:IsTargetDetected( EscortObject )
-- --
-- -- self:T( { EscortTargetIsDetected,
-- -- EscortTargetIsVisible,
-- -- EscortTargetLastTime,
-- -- EscortTargetKnowType,
-- -- EscortTargetKnowDistance,
-- -- EscortTargetLastPos,
-- -- EscortTargetLastVelocity } )
--
--
-- local EscortTargetUnitVec3 = EscortTargetUnit:GetVec3()
-- local EscortVec3 = self.EscortGroup:GetVec3()
-- local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
-- ( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
-- ( EscortTargetUnitVec3.z - EscortVec3.z )^2
-- ) ^ 0.5 / 1000
--
-- self:T( { self.EscortGroup:GetName(), EscortTargetUnit:GetName(), Distance, EscortTarget } )
--
-- if Distance <= 15 then
--
-- if not ClientEscortTargets[EscortTargetUnitName] then
-- ClientEscortTargets[EscortTargetUnitName] = {}
-- end
-- ClientEscortTargets[EscortTargetUnitName].AttackUnit = EscortTargetUnit
-- ClientEscortTargets[EscortTargetUnitName].visible = EscortTarget.visible
-- ClientEscortTargets[EscortTargetUnitName].type = EscortTarget.type
-- ClientEscortTargets[EscortTargetUnitName].distance = EscortTarget.distance
-- else
-- if ClientEscortTargets[EscortTargetUnitName] then
-- ClientEscortTargets[EscortTargetUnitName] = nil
-- end
-- end
-- end
-- end
--
-- self:T( { "Sorting Targets Table:", ClientEscortTargets } )
-- table.sort( ClientEscortTargets, function( a, b ) return a.Distance < b.Distance end )
-- self:T( { "Sorted Targets Table:", ClientEscortTargets } )
--
-- -- Remove the sub menus of the Attack menu of the Escort for the EscortGroup.
-- self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
--
-- if self.EscortMenuTargetAssistance then
-- self.EscortMenuTargetAssistance:RemoveSubMenus()
-- end
--
-- --for MenuIndex = 1, #self.EscortMenuAttackTargets do
-- -- self:T( { "Remove Menu:", self.EscortMenuAttackTargets[MenuIndex] } )
-- -- self.EscortMenuAttackTargets[MenuIndex] = self.EscortMenuAttackTargets[MenuIndex]:Remove()
-- --end
--
--
-- if ClientEscortTargets then
-- for ClientEscortTargetUnitName, ClientEscortTargetData in pairs( ClientEscortTargets ) do
--
-- for ClientEscortGroupName, EscortGroupData in pairs( self.EscortClient._EscortGroups ) do
--
-- if ClientEscortTargetData and ClientEscortTargetData.AttackUnit:IsAlive() then
--
-- local EscortTargetMessage = ""
-- local EscortTargetCategoryName = ClientEscortTargetData.AttackUnit:GetCategoryName()
-- local EscortTargetCategoryType = ClientEscortTargetData.AttackUnit:GetTypeName()
-- if ClientEscortTargetData.type then
-- EscortTargetMessage = EscortTargetMessage .. EscortTargetCategoryName .. " (" .. EscortTargetCategoryType .. ") at "
-- else
-- EscortTargetMessage = EscortTargetMessage .. "Unknown target at "
-- end
--
-- local EscortTargetUnitVec3 = ClientEscortTargetData.AttackUnit:GetVec3()
-- local EscortVec3 = self.EscortGroup:GetVec3()
-- local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
-- ( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
-- ( EscortTargetUnitVec3.z - EscortVec3.z )^2
-- ) ^ 0.5 / 1000
--
-- self:T( { self.EscortGroup:GetName(), ClientEscortTargetData.AttackUnit:GetName(), Distance, ClientEscortTargetData.AttackUnit } )
-- if ClientEscortTargetData.visible == false then
-- EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " estimated km"
-- else
-- EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " km"
-- end
--
-- if ClientEscortTargetData.visible then
-- EscortTargetMessage = EscortTargetMessage .. ", visual"
-- end
--
-- if ClientEscortGroupName == EscortGroupName then
--
-- MENU_CLIENT_COMMAND:New( self.EscortClient,
-- EscortTargetMessage,
-- self.EscortMenuAttackNearbyTargets,
-- ESCORT._AttackTarget,
-- { ParamSelf = self,
-- ParamUnit = ClientEscortTargetData.AttackUnit
-- }
-- )
-- EscortTargetMessages = EscortTargetMessages .. "\n - " .. EscortTargetMessage
-- else
-- if self.EscortMenuTargetAssistance then
-- local MenuTargetAssistance = MENU_CLIENT:New( self.EscortClient, EscortGroupData.EscortName, self.EscortMenuTargetAssistance )
-- MENU_CLIENT_COMMAND:New( self.EscortClient,
-- EscortTargetMessage,
-- MenuTargetAssistance,
-- ESCORT._AssistTarget,
-- self,
-- EscortGroupData.EscortGroup,
-- ClientEscortTargetData.AttackUnit
-- )
-- end
-- end
-- else
-- ClientEscortTargetData = nil
-- end
-- end
-- end
--
-- if EscortTargetMessages ~= "" and self.ReportTargets == true then
-- self.EscortGroup:MessageToClient( "Detected targets within 15 km range:" .. EscortTargetMessages:gsub("\n$",""), 20, self.EscortClient )
-- else
-- self.EscortGroup:MessageToClient( "No targets detected!", 20, self.EscortClient )
-- end
-- end
--
-- if self.EscortMenuResumeMission then
-- self.EscortMenuResumeMission:RemoveSubMenus()
--
-- -- if self.EscortMenuResumeWayPoints then
-- -- for MenuIndex = 1, #self.EscortMenuResumeWayPoints do
-- -- self:T( { "Remove Menu:", self.EscortMenuResumeWayPoints[MenuIndex] } )
-- -- self.EscortMenuResumeWayPoints[MenuIndex] = self.EscortMenuResumeWayPoints[MenuIndex]:Remove()
-- -- end
-- -- end
--
-- local TaskPoints = self:RegisterRoute()
-- for WayPointID, WayPoint in pairs( TaskPoints ) do
-- local EscortVec3 = self.EscortGroup:GetVec3()
-- local Distance = ( ( WayPoint.x - EscortVec3.x )^2 +
-- ( WayPoint.y - EscortVec3.z )^2
-- ) ^ 0.5 / 1000
-- MENU_CLIENT_COMMAND:New( self.EscortClient, "Waypoint " .. WayPointID .. " at " .. string.format( "%.2f", Distance ).. "km", self.EscortMenuResumeMission, ESCORT._ResumeMission, { ParamSelf = self, ParamWayPoint = WayPointID } )
-- end
-- end
--
-- return true
end
end end
return false return false

View File

@@ -171,7 +171,7 @@ function MISSILETRAINER:New( Distance, Briefing )
self.Distance = Distance / 1000 self.Distance = Distance / 1000
_EVENTDISPATCHER:OnShot( self._EventShot, self ) self:HandleEvent( EVENTS.Shot )
self.DBClients = SET_CLIENT:New():FilterStart() self.DBClients = SET_CLIENT:New():FilterStart()
@@ -449,14 +449,14 @@ end
--- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME. --- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
-- @param #MISSILETRAINER self -- @param #MISSILETRAINER self
-- @param Core.Event#EVENTDATA Event -- @param Core.Event#EVENTDATA EventData
function MISSILETRAINER:_EventShot( Event ) function MISSILETRAINER:OnEventShot( EVentData )
self:F( { Event } ) self:F( { EVentData } )
local TrainerSourceDCSUnit = Event.IniDCSUnit local TrainerSourceDCSUnit = EVentData.IniDCSUnit
local TrainerSourceDCSUnitName = Event.IniDCSUnitName local TrainerSourceDCSUnitName = EVentData.IniDCSUnitName
local TrainerWeapon = Event.Weapon -- Identify the weapon fired local TrainerWeapon = EVentData.Weapon -- Identify the weapon fired
local TrainerWeaponName = Event.WeaponName -- return weapon type local TrainerWeaponName = EVentData.WeaponName -- return weapon type
self:T( "Missile Launched = " .. TrainerWeaponName ) self:T( "Missile Launched = " .. TrainerWeaponName )

View File

@@ -3,10 +3,11 @@
-- Performance: If in a DCSRTE there are a lot of moving GROUND units, then in a multi player mission, this WILL create lag if -- Performance: If in a DCSRTE there are a lot of moving GROUND units, then in a multi player mission, this WILL create lag if
-- the main DCS execution core of your CPU is fully utilized. So, this class will limit the amount of simultaneous moving GROUND units -- the main DCS execution core of your CPU is fully utilized. So, this class will limit the amount of simultaneous moving GROUND units
-- on defined intervals (currently every minute). -- on defined intervals (currently every minute).
-- @module MOVEMENT -- @module Movement
--- the MOVEMENT class --- the MOVEMENT class
-- @type -- @type MOVEMENT
-- @extends Core.Base#BASE
MOVEMENT = { MOVEMENT = {
ClassName = "MOVEMENT", ClassName = "MOVEMENT",
} }
@@ -20,7 +21,7 @@ MOVEMENT = {
-- Movement_US_Platoons = MOVEMENT:New( { 'US Tank Platoon Left', 'US Tank Platoon Middle', 'US Tank Platoon Right', 'US CH-47D Troops' }, 15 ) -- Movement_US_Platoons = MOVEMENT:New( { 'US Tank Platoon Left', 'US Tank Platoon Middle', 'US Tank Platoon Right', 'US CH-47D Troops' }, 15 )
function MOVEMENT:New( MovePrefixes, MoveMaximum ) function MOVEMENT:New( MovePrefixes, MoveMaximum )
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() ) -- #MOVEMENT
self:F( { MovePrefixes, MoveMaximum } ) self:F( { MovePrefixes, MoveMaximum } )
if type( MovePrefixes ) == 'table' then if type( MovePrefixes ) == 'table' then
@@ -33,7 +34,7 @@ function MOVEMENT:New( MovePrefixes, MoveMaximum )
self.AliveUnits = 0 -- Contains the counter how many units are currently alive self.AliveUnits = 0 -- Contains the counter how many units are currently alive
self.MoveUnits = {} -- Reflects if the Moving for this MovePrefixes is going to be scheduled or not. self.MoveUnits = {} -- Reflects if the Moving for this MovePrefixes is going to be scheduled or not.
_EVENTDISPATCHER:OnBirth( self.OnBirth, self ) self:HandleEvent( EVENTS.Birth )
-- self:AddEvent( world.event.S_EVENT_BIRTH, self.OnBirth ) -- self:AddEvent( world.event.S_EVENT_BIRTH, self.OnBirth )
-- --
@@ -60,24 +61,26 @@ end
--- Captures the birth events when new Units were spawned. --- Captures the birth events when new Units were spawned.
-- @todo This method should become obsolete. The new @{DATABASE} class will handle the collection administration. -- @todo This method should become obsolete. The new @{DATABASE} class will handle the collection administration.
function MOVEMENT:OnBirth( Event ) -- @param #MOVEMENT self
self:F( { Event } ) -- @param Core.Event#EVENTDATA self
function MOVEMENT:OnEventBirth( EventData )
self:F( { EventData } )
if timer.getTime0() < timer.getAbsTime() then -- dont need to add units spawned in at the start of the mission if mist is loaded in init line if timer.getTime0() < timer.getAbsTime() then -- dont need to add units spawned in at the start of the mission if mist is loaded in init line
if Event.IniDCSUnit then if EventData.IniDCSUnit then
self:T( "Birth object : " .. Event.IniDCSUnitName ) self:T( "Birth object : " .. EventData.IniDCSUnitName )
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then if EventData.IniDCSGroup and EventData.IniDCSGroup:isExist() then
for MovePrefixID, MovePrefix in pairs( self.MovePrefixes ) do for MovePrefixID, MovePrefix in pairs( self.MovePrefixes ) do
if string.find( Event.IniDCSUnitName, MovePrefix, 1, true ) then if string.find( EventData.IniDCSUnitName, MovePrefix, 1, true ) then
self.AliveUnits = self.AliveUnits + 1 self.AliveUnits = self.AliveUnits + 1
self.MoveUnits[Event.IniDCSUnitName] = Event.IniDCSGroupName self.MoveUnits[EventData.IniDCSUnitName] = EventData.IniDCSGroupName
self:T( self.AliveUnits ) self:T( self.AliveUnits )
end end
end end
end end
end end
_EVENTDISPATCHER:OnCrashForUnit( Event.IniDCSUnitName, self.OnDeadOrCrash, self )
_EVENTDISPATCHER:OnDeadForUnit( Event.IniDCSUnitName, self.OnDeadOrCrash, self ) EventData.IniUnit:HandleEvent( EVENTS.DEAD, self.OnDeadOrCrash )
end end
end end

View File

@@ -577,7 +577,7 @@ function SCORING:_AddPlayerFromUnit( UnitData )
"(changed " .. self.Players[PlayerName].PenaltyCoalition .. " times the coalition). 50 Penalty points added.", "(changed " .. self.Players[PlayerName].PenaltyCoalition .. " times the coalition). 50 Penalty points added.",
2 2
):ToAll() ):ToAll()
self:ScoreCSV( PlayerName, "COALITION_PENALTY", 1, -50, self.Players[PlayerName].UnitName, _SCORINGCoalition[self.Players[PlayerName].UnitCoalition], _SCORINGCategory[self.Players[PlayerName].UnitCategory], self.Players[PlayerName].UnitType, self:ScoreCSV( PlayerName, "", "COALITION_PENALTY", 1, -50, self.Players[PlayerName].UnitName, _SCORINGCoalition[self.Players[PlayerName].UnitCoalition], _SCORINGCategory[self.Players[PlayerName].UnitCategory], self.Players[PlayerName].UnitType,
UnitName, _SCORINGCoalition[UnitCoalition], _SCORINGCategory[UnitCategory], UnitData:GetTypeName() ) UnitName, _SCORINGCoalition[UnitCoalition], _SCORINGCategory[UnitCategory], UnitData:GetTypeName() )
end end
end end
@@ -633,7 +633,7 @@ function SCORING:AddGoalScore( PlayerUnit, GoalTag, Text, Score )
MESSAGE:New( Text, 30 ):ToAll() MESSAGE:New( Text, 30 ):ToAll()
self:ScoreCSV( PlayerName, "GOAL_" .. string.upper( GoalTag ), 1, Score, PlayerUnit:GetName() ) self:ScoreCSV( PlayerName, "", "GOAL_" .. string.upper( GoalTag ), 1, Score, PlayerUnit:GetName() )
end end
end end
@@ -671,7 +671,7 @@ function SCORING:_AddMissionTaskScore( Mission, PlayerUnit, Text, Score )
Score .. " task score!", Score .. " task score!",
30 ):ToAll() 30 ):ToAll()
self:ScoreCSV( PlayerName, "TASK_" .. MissionName:gsub( ' ', '_' ), 1, Score, PlayerUnit:GetName() ) self:ScoreCSV( PlayerName, "", "TASK_" .. MissionName:gsub( ' ', '_' ), 1, Score, PlayerUnit:GetName() )
end end
end end
@@ -701,7 +701,7 @@ function SCORING:_AddMissionScore( Mission, Text, Score )
Score .. " mission score!", Score .. " mission score!",
60 ):ToAll() 60 ):ToAll()
self:ScoreCSV( PlayerName, "MISSION_" .. MissionName:gsub( ' ', '_' ), 1, Score ) self:ScoreCSV( PlayerName, "", "MISSION_" .. MissionName:gsub( ' ', '_' ), 1, Score )
end end
end end
end end
@@ -882,7 +882,7 @@ function SCORING:_EventOnHit( Event )
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
end end
self:ScoreCSV( InitPlayerName, "HIT_PENALTY", 1, -25, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -25, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
else else
Player.Score = Player.Score + 1 Player.Score = Player.Score + 1
PlayerHit.Score = PlayerHit.Score + 1 PlayerHit.Score = PlayerHit.Score + 1
@@ -906,7 +906,7 @@ function SCORING:_EventOnHit( Event )
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
end end
self:ScoreCSV( InitPlayerName, "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
end end
else -- A scenery object was hit. else -- A scenery object was hit.
MESSAGE MESSAGE
@@ -915,7 +915,7 @@ function SCORING:_EventOnHit( Event )
) )
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
self:ScoreCSV( InitPlayerName, "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, "", "Scenery", TargetUnitType ) self:ScoreCSV( InitPlayerName, "", "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, "", "Scenery", TargetUnitType )
end end
end end
end end
@@ -1022,7 +1022,8 @@ function SCORING:_EventOnDeadOrCrash( Event )
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
end end
self:ScoreCSV( PlayerName, "DESTROY_PENALTY", 1, ThreatPenalty, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
self:ScoreCSV( PlayerName, TargetPlayerName, "DESTROY_PENALTY", 1, ThreatPenalty, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
else else
local ThreatLevelTarget, ThreatTypeTarget = TargetUnit:GetThreatLevel() local ThreatLevelTarget, ThreatTypeTarget = TargetUnit:GetThreatLevel()
@@ -1053,7 +1054,7 @@ function SCORING:_EventOnDeadOrCrash( Event )
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
end end
self:ScoreCSV( PlayerName, "DESTROY_SCORE", 1, ThreatScore, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) self:ScoreCSV( PlayerName, TargetPlayerName, "DESTROY_SCORE", 1, ThreatScore, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
local UnitName = TargetUnit:GetName() local UnitName = TargetUnit:GetName()
local Score = self.ScoringObjects[UnitName] local Score = self.ScoringObjects[UnitName]
@@ -1067,7 +1068,7 @@ function SCORING:_EventOnDeadOrCrash( Event )
) )
:ToAllIf( self:IfMessagesScore() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesScore() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesScore() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesScore() and self:IfMessagesToCoalition() )
self:ScoreCSV( PlayerName, "DESTROY_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) self:ScoreCSV( PlayerName, TargetPlayerName, "DESTROY_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
end end
-- Check if there are Zones where the destruction happened. -- Check if there are Zones where the destruction happened.
@@ -1085,7 +1086,7 @@ function SCORING:_EventOnDeadOrCrash( Event )
15 ) 15 )
:ToAllIf( self:IfMessagesZone() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesZone() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesZone() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesZone() and self:IfMessagesToCoalition() )
self:ScoreCSV( PlayerName, "DESTROY_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) self:ScoreCSV( PlayerName, TargetPlayerName, "DESTROY_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
end end
end end
@@ -1107,7 +1108,7 @@ function SCORING:_EventOnDeadOrCrash( Event )
) )
:ToAllIf( self:IfMessagesZone() and self:IfMessagesToAll() ) :ToAllIf( self:IfMessagesZone() and self:IfMessagesToAll() )
:ToCoalitionIf( InitCoalition, self:IfMessagesZone() and self:IfMessagesToCoalition() ) :ToCoalitionIf( InitCoalition, self:IfMessagesZone() and self:IfMessagesToCoalition() )
self:ScoreCSV( PlayerName, "DESTROY_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, "", "Scenery", TargetUnitType ) self:ScoreCSV( PlayerName, "", "DESTROY_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, "", "Scenery", TargetUnitType )
end end
end end
end end
@@ -1529,7 +1530,7 @@ function SCORING:OpenCSV( ScoringCSV )
error( "Error: Cannot open CSV file in " .. lfs.writedir() ) error( "Error: Cannot open CSV file in " .. lfs.writedir() )
end end
self.CSVFile:write( '"GameName","RunTime","Time","PlayerName","ScoreType","PlayerUnitCoaltion","PlayerUnitCategory","PlayerUnitType","PlayerUnitName","TargetUnitCoalition","TargetUnitCategory","TargetUnitType","TargetUnitName","Times","Score"\n' ) self.CSVFile:write( '"GameName","RunTime","Time","PlayerName","TargetPlayerName","ScoreType","PlayerUnitCoaltion","PlayerUnitCategory","PlayerUnitType","PlayerUnitName","TargetUnitCoalition","TargetUnitCategory","TargetUnitType","TargetUnitName","Times","Score"\n' )
self.RunTime = os.date("%y-%m-%d_%H-%M-%S") self.RunTime = os.date("%y-%m-%d_%H-%M-%S")
else else
@@ -1545,6 +1546,7 @@ end
--- Registers a score for a player. --- Registers a score for a player.
-- @param #SCORING self -- @param #SCORING self
-- @param #string PlayerName The name of the player. -- @param #string PlayerName The name of the player.
-- @param #string TargetPlayerName The name of the target player.
-- @param #string ScoreType The type of the score. -- @param #string ScoreType The type of the score.
-- @param #string ScoreTimes The amount of scores achieved. -- @param #string ScoreTimes The amount of scores achieved.
-- @param #string ScoreAmount The score given. -- @param #string ScoreAmount The score given.
@@ -1557,11 +1559,14 @@ end
-- @param #string TargetUnitCategory The category of the target unit. -- @param #string TargetUnitCategory The category of the target unit.
-- @param #string TargetUnitType The type of the target unit. -- @param #string TargetUnitType The type of the target unit.
-- @return #SCORING self -- @return #SCORING self
function SCORING:ScoreCSV( PlayerName, ScoreType, ScoreTimes, ScoreAmount, PlayerUnitName, PlayerUnitCoalition, PlayerUnitCategory, PlayerUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes, ScoreAmount, PlayerUnitName, PlayerUnitCoalition, PlayerUnitCategory, PlayerUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
--write statistic information to file --write statistic information to file
local ScoreTime = self:SecondsToClock( timer.getTime() ) local ScoreTime = self:SecondsToClock( timer.getTime() )
PlayerName = PlayerName:gsub( '"', '_' ) PlayerName = PlayerName:gsub( '"', '_' )
TargetPlayerName = TargetPlayerName or ""
TargetPlayerName = TargetPlayerName:gsub( '"', '_' )
if PlayerUnitName and PlayerUnitName ~= '' then if PlayerUnitName and PlayerUnitName ~= '' then
local PlayerUnit = Unit.getByName( PlayerUnitName ) local PlayerUnit = Unit.getByName( PlayerUnitName )
@@ -1602,6 +1607,7 @@ function SCORING:ScoreCSV( PlayerName, ScoreType, ScoreTimes, ScoreAmount, Playe
'"' .. self.RunTime .. '"' .. ',' .. '"' .. self.RunTime .. '"' .. ',' ..
'' .. ScoreTime .. '' .. ',' .. '' .. ScoreTime .. '' .. ',' ..
'"' .. PlayerName .. '"' .. ',' .. '"' .. PlayerName .. '"' .. ',' ..
'"' .. TargetPlayerName .. '"' .. ',' ..
'"' .. ScoreType .. '"' .. ',' .. '"' .. ScoreType .. '"' .. ',' ..
'"' .. PlayerUnitCoalition .. '"' .. ',' .. '"' .. PlayerUnitCoalition .. '"' .. ',' ..
'"' .. PlayerUnitCategory .. '"' .. ',' .. '"' .. PlayerUnitCategory .. '"' .. ',' ..

View File

@@ -36,25 +36,28 @@ function SEAD:New( SEADGroupPrefixes )
else else
self.SEADGroupNames[SEADGroupPrefixes] = SEADGroupPrefixes self.SEADGroupNames[SEADGroupPrefixes] = SEADGroupPrefixes
end end
_EVENTDISPATCHER:OnShot( self.EventShot, self )
self:HandleEvent( EVENTS.Shot )
return self return self
end end
--- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME. --- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
-- @see SEAD -- @see SEAD
function SEAD:EventShot( Event ) -- @param #SEAD
self:F( { Event } ) -- @param Core.Event#EVENTDATA EventData
function SEAD:OnEventShot( EventData )
self:F( { EventData } )
local SEADUnit = Event.IniDCSUnit local SEADUnit = EventData.IniDCSUnit
local SEADUnitName = Event.IniDCSUnitName local SEADUnitName = EventData.IniDCSUnitName
local SEADWeapon = Event.Weapon -- Identify the weapon fired local SEADWeapon = EventData.Weapon -- Identify the weapon fired
local SEADWeaponName = Event.WeaponName -- return weapon type local SEADWeaponName = EventData.WeaponName -- return weapon type
-- Start of the 2nd loop -- Start of the 2nd loop
self:T( "Missile Launched = " .. SEADWeaponName ) self:T( "Missile Launched = " .. SEADWeaponName )
if SEADWeaponName == "KH-58" or SEADWeaponName == "KH-25MPU" or SEADWeaponName == "AGM-88" or SEADWeaponName == "KH-31A" or SEADWeaponName == "KH-31P" then -- Check if the missile is a SEAD if SEADWeaponName == "KH-58" or SEADWeaponName == "KH-25MPU" or SEADWeaponName == "AGM-88" or SEADWeaponName == "KH-31A" or SEADWeaponName == "KH-31P" then -- Check if the missile is a SEAD
local _evade = math.random (1,100) -- random number for chance of evading action local _evade = math.random (1,100) -- random number for chance of evading action
local _targetMim = Event.Weapon:getTarget() -- Identify target local _targetMim = EventData.Weapon:getTarget() -- Identify target
local _targetMimname = Unit.getName(_targetMim) local _targetMimname = Unit.getName(_targetMim)
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon)) local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
local _targetMimgroupName = _targetMimgroup:getName() local _targetMimgroupName = _targetMimgroup:getName()

View File

@@ -44,12 +44,14 @@
-- --
-- A spawn object will behave differently based on the usage of **initialization** methods, which all start with the **Init** prefix: -- A spawn object will behave differently based on the usage of **initialization** methods, which all start with the **Init** prefix:
-- --
-- * @{#SPAWN.InitKeepUnitNames}(): Keeps the unit names as defined within the mission editor, but note that anything after a # mark is ignored, and any spaces before and after the resulting name are removed. IMPORTANT! This method MUST be the first used after :New !!!
-- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned. -- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
-- * @{#SPAWN.InitRandomizeRoute}(): Randomize the routes of spawned groups, and for air groups also optionally the height. -- * @{#SPAWN.InitRandomizeRoute}(): Randomize the routes of spawned groups, and for air groups also optionally the height.
-- * @{#SPAWN.InitRandomizeTemplate}(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined. -- * @{#SPAWN.InitRandomizeTemplate}(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
-- * @{#SPAWN.InitUnControlled}(): Spawn plane groups uncontrolled. -- * @{#SPAWN.InitUnControlled}(): Spawn plane groups uncontrolled.
-- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a batallion in an array. -- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a batallion in an array.
-- * @{#SPAWN.InitRepeat}(): Re-spawn groups when they land at the home base. Similar methods are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}. -- * @{#SPAWN.InitRepeat}(): Re-spawn groups when they land at the home base. Similar methods are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}.
-- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
-- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius. -- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius.
-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor. -- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor.
-- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Group} object. -- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Group} object.
@@ -117,6 +119,9 @@
-- --
-- Hereby the change log: -- Hereby the change log:
-- --
-- 2017-03-14: SPAWN:**InitKeepUnitNames()** added.
-- 2017-03-14: SPAWN:**InitRandomizePosition( RandomizePosition, OuterRadious, InnerRadius )** added.
--
-- 2017-02-04: SPAWN:InitUnControlled( **UnControlled** ) replaces SPAWN:InitUnControlled(). -- 2017-02-04: SPAWN:InitUnControlled( **UnControlled** ) replaces SPAWN:InitUnControlled().
-- --
-- 2017-01-24: SPAWN:**InitAIOnOff( AIOnOff )** added. -- 2017-01-24: SPAWN:**InitAIOnOff( AIOnOff )** added.
@@ -214,12 +219,14 @@ function SPAWN:New( SpawnTemplatePrefix )
self.SpawnTemplate = self._GetTemplate( self, SpawnTemplatePrefix ) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!! self.SpawnTemplate = self._GetTemplate( self, SpawnTemplatePrefix ) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!!
self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning. self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning.
self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts. self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts.
self.SpawnInitLimit = false -- By default, no InitLimit
self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time. self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time.
self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned. self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned.
self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false. self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false.
self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned. self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned.
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.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
@@ -253,12 +260,14 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
self.SpawnTemplate = self._GetTemplate( self, SpawnTemplatePrefix ) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!! self.SpawnTemplate = self._GetTemplate( self, SpawnTemplatePrefix ) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!!
self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning. self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning.
self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts. self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts.
self.SpawnInitLimit = false -- By default, no InitLimit
self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time. self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time.
self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned. self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned.
self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false. self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false.
self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned. self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned.
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.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
@@ -287,6 +296,7 @@ end
function SPAWN:InitLimit( SpawnMaxUnitsAlive, SpawnMaxGroups ) function SPAWN:InitLimit( SpawnMaxUnitsAlive, SpawnMaxGroups )
self:F( { self.SpawnTemplatePrefix, SpawnMaxUnitsAlive, SpawnMaxGroups } ) self:F( { self.SpawnTemplatePrefix, SpawnMaxUnitsAlive, SpawnMaxGroups } )
self.SpawnInitLimit = true
self.SpawnMaxUnitsAlive = SpawnMaxUnitsAlive -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time. self.SpawnMaxUnitsAlive = SpawnMaxUnitsAlive -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time.
self.SpawnMaxGroups = SpawnMaxGroups -- The maximum amount of groups that can be spawned. self.SpawnMaxGroups = SpawnMaxGroups -- The maximum amount of groups that can be spawned.
@@ -297,6 +307,20 @@ function SPAWN:InitLimit( SpawnMaxUnitsAlive, SpawnMaxGroups )
return self return self
end end
--- Keeps the unit names as defined within the mission editor,
-- but note that anything after a # mark is ignored,
-- and any spaces before and after the resulting name are removed.
-- IMPORTANT! This method MUST be the first used after :New !!!
-- @param #SPAWN self
-- @return #SPAWN self
function SPAWN:InitKeepUnitNames()
self:F( )
self.SpawnInitKeepUnitNames = true
return self
end
--- Randomizes the defined route of the SpawnTemplatePrefix group in the ME. This is very useful to define extra variation of the behaviour of groups. --- Randomizes the defined route of the SpawnTemplatePrefix group in the ME. This is very useful to define extra variation of the behaviour of groups.
-- @param #SPAWN self -- @param #SPAWN self
@@ -329,6 +353,27 @@ function SPAWN:InitRandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius,
return self return self
end end
--- Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
-- @param #SPAWN self
-- @param #boolean RandomizePosition If true, SPAWN will perform the randomization of the @{Group}s position between a given outer and inner radius.
-- @param Dcs.DCSTypes#Distance OuterRadius (optional) The outer radius in meters where the new group will be spawned.
-- @param Dcs.DCSTypes#Distance InnerRadius (optional) The inner radius in meters where the new group will NOT be spawned.
-- @return #SPAWN
function SPAWN:InitRandomizePosition( RandomizePosition, OuterRadius, InnerRadius )
self:F( { self.SpawnTemplatePrefix, RandomizePosition, OuterRadius, InnerRadius } )
self.SpawnRandomizePosition = RandomizePosition or false
self.SpawnRandomizePositionOuterRadius = OuterRadius or 0
self.SpawnRandomizePositionInnerRadius = InnerRadius or 0
for GroupID = 1, self.SpawnMaxGroups do
self:_RandomizeRoute( GroupID )
end
return self
end
--- Randomizes the UNITs that are spawned within a radius band given an Outer and Inner radius. --- Randomizes the UNITs that are spawned within a radius band given an Outer and Inner radius.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #boolean RandomizeUnits If true, SPAWN will perform the randomization of the @{UNIT}s position within the group between a given outer and inner radius. -- @param #boolean RandomizeUnits If true, SPAWN will perform the randomization of the @{UNIT}s position within the group between a given outer and inner radius.
@@ -646,6 +691,20 @@ function SPAWN:SpawnWithIndex( SpawnIndex )
local PointVec3 = POINT_VEC3:New( SpawnTemplate.route.points[1].x, SpawnTemplate.route.points[1].alt, SpawnTemplate.route.points[1].y ) local PointVec3 = POINT_VEC3:New( SpawnTemplate.route.points[1].x, SpawnTemplate.route.points[1].alt, SpawnTemplate.route.points[1].y )
self:T( { "Current point of ", self.SpawnTemplatePrefix, PointVec3 } ) self:T( { "Current point of ", self.SpawnTemplatePrefix, PointVec3 } )
-- If RandomizePosition, then Randomize the formation in the zone band, keeping the template.
if self.SpawnRandomizePosition then
local RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnRandomizePositionOuterRadius, self.SpawnRandomizePositionInnerRadius )
local CurrentX = SpawnTemplate.units[1].x
local CurrentY = SpawnTemplate.units[1].y
SpawnTemplate.x = RandomVec2.x
SpawnTemplate.y = RandomVec2.y
for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].x = SpawnTemplate.units[UnitID].x + ( RandomVec2.x - CurrentX )
SpawnTemplate.units[UnitID].y = SpawnTemplate.units[UnitID].y + ( RandomVec2.y - CurrentY )
self:T( 'SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
end
end
-- If RandomizeUnits, then Randomize the formation at the start point. -- If RandomizeUnits, then Randomize the formation at the start point.
if self.SpawnRandomizeUnits then if self.SpawnRandomizeUnits then
for UnitID = 1, #SpawnTemplate.units do for UnitID = 1, #SpawnTemplate.units do
@@ -1088,7 +1147,8 @@ end
function SPAWN:_GetPrefixFromDCSUnit( DCSUnit ) function SPAWN:_GetPrefixFromDCSUnit( DCSUnit )
self:F3( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, DCSUnit } ) self:F3( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, DCSUnit } )
local DCSUnitName = ( DCSUnit and DCSUnit:getName() ) or nil local DCSGroup = DCSUnit:getGroup()
local DCSUnitName = ( DCSGroup and DCSGroup:getName() ) or nil
if DCSUnitName then if DCSUnitName then
local SpawnPrefix = string.match( DCSUnitName, ".*#" ) local SpawnPrefix = string.match( DCSUnitName, ".*#" )
if SpawnPrefix then if SpawnPrefix then
@@ -1142,6 +1202,7 @@ function SPAWN:_GetLastIndex()
end end
--- Initalize the SpawnGroups collection. --- Initalize the SpawnGroups collection.
-- @param #SPAWN self
function SPAWN:_InitializeSpawnGroups( SpawnIndex ) function SPAWN:_InitializeSpawnGroups( SpawnIndex )
self:F3( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnIndex } ) self:F3( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnIndex } )
@@ -1245,11 +1306,20 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex )
SpawnTemplate.visible = false SpawnTemplate.visible = false
end end
if self.SpawnInitKeepUnitNames == false then
for UnitID = 1, #SpawnTemplate.units do for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].name = string.format( SpawnTemplate.name .. '-%02d', UnitID ) SpawnTemplate.units[UnitID].name = string.format( SpawnTemplate.name .. '-%02d', UnitID )
SpawnTemplate.units[UnitID].unitId = nil SpawnTemplate.units[UnitID].unitId = nil
end end
else
for UnitID = 1, #SpawnTemplate.units do
local UnitPrefix, Rest = string.match( SpawnTemplate.units[UnitID].name, "^([^#]+)#?" ):gsub( "^%s*(.-)%s*$", "%1" )
self:T( { UnitPrefix, Rest } )
SpawnTemplate.units[UnitID].name = string.format( '%s#%03d-%02d', UnitPrefix, SpawnIndex, UnitID )
SpawnTemplate.units[UnitID].unitId = nil
end
end
self:T3( { "Template:", SpawnTemplate } ) self:T3( { "Template:", SpawnTemplate } )
return SpawnTemplate return SpawnTemplate

View File

@@ -1,4 +1,5 @@
--- The main include file for the MOOSE system. --- The main include file for the MOOSE system.
-- Test of permissions
--- Core Routines --- Core Routines
Include.File( "Utilities/Routines" ) Include.File( "Utilities/Routines" )
@@ -58,7 +59,7 @@ Include.File( "Tasking/CommandCenter" )
Include.File( "Tasking/Mission" ) Include.File( "Tasking/Mission" )
Include.File( "Tasking/Task" ) Include.File( "Tasking/Task" )
Include.File( "Tasking/DetectionManager" ) Include.File( "Tasking/DetectionManager" )
Include.File( "Tasking/Task_SEAD" ) Include.File( "Tasking/Task_A2G_Dispatcher")
Include.File( "Tasking/Task_A2G" ) Include.File( "Tasking/Task_A2G" )

View File

@@ -20,7 +20,9 @@ function REPORT:New( Title )
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() )
self.Report = {} self.Report = {}
if Title then
self.Report[#self.Report+1] = Title self.Report[#self.Report+1] = Title
end
return self return self
end end
@@ -31,7 +33,7 @@ end
-- @return #REPORT -- @return #REPORT
function REPORT:Add( Text ) function REPORT:Add( Text )
self.Report[#self.Report+1] = Text self.Report[#self.Report+1] = Text
return self.Report[#self.Report+1] return self.Report[#self.Report]
end end
function REPORT:Text() function REPORT:Text()
@@ -68,9 +70,9 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
self:HandleEvent( EVENTS.Birth, self:HandleEvent( EVENTS.Birth,
--- @param #COMMANDCENTER self --- @param #COMMANDCENTER self
--- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function( self, EventData ) function( self, EventData )
self:E( { EventData } ) if EventData.IniObjectCategory == 1 then
local EventGroup = GROUP:Find( EventData.IniDCSGroup ) local EventGroup = GROUP:Find( EventData.IniDCSGroup )
if EventGroup and self:HasGroup( EventGroup ) then if EventGroup and self:HasGroup( EventGroup ) then
local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu ) local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu )
@@ -85,6 +87,7 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
Mission:JoinUnit( PlayerUnit, PlayerGroup ) Mission:JoinUnit( PlayerUnit, PlayerGroup )
Mission:ReportDetails() Mission:ReportDetails()
end end
end
end end
) )
@@ -193,17 +196,26 @@ function COMMANDCENTER:SetMenu()
self.CommandCenterMenu = self.CommandCenterMenu or MENU_COALITION:New( self.CommandCenterCoalition, "Command Center (" .. self:GetName() .. ")" ) self.CommandCenterMenu = self.CommandCenterMenu or MENU_COALITION:New( self.CommandCenterCoalition, "Command Center (" .. self:GetName() .. ")" )
local MenuTime = timer.getTime()
for MissionID, Mission in pairs( self:GetMissions() ) do for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION local Mission = Mission -- Tasking.Mission#MISSION
Mission:RemoveMenu() Mission:SetMenu( MenuTime )
end end
for MissionID, Mission in pairs( self:GetMissions() ) do for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION local Mission = Mission -- Tasking.Mission#MISSION
Mission:SetMenu() Mission:RemoveMenu( MenuTime )
end end
end end
--- Gets the commandcenter menu structure governed by the HQ command center.
-- @param #COMMANDCENTER self
-- @return Core.Menu#MENU_COALITION
function COMMANDCENTER:GetMenu()
self:F()
return self.CommandCenterMenu
end
--- Checks of the COMMANDCENTER has a GROUP. --- Checks of the COMMANDCENTER has a GROUP.
-- @param #COMMANDCENTER self -- @param #COMMANDCENTER self
@@ -224,6 +236,14 @@ function COMMANDCENTER:HasGroup( MissionGroup )
return Has return Has
end end
--- Send a CC message to the coalition of the CC.
-- @param #COMMANDCENTER self
function COMMANDCENTER:MessageToAll( Message )
self:GetPositionable():MessageToAll( Message, 20, self:GetName() )
end
--- Send a CC message to a GROUP. --- Send a CC message to a GROUP.
-- @param #COMMANDCENTER self -- @param #COMMANDCENTER self
-- @param #string Message -- @param #string Message
@@ -231,7 +251,8 @@ end
-- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown. -- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
function COMMANDCENTER:MessageToGroup( Message, TaskGroup, Name ) function COMMANDCENTER:MessageToGroup( Message, TaskGroup, Name )
local Prefix = Name and "@ Group (" .. Name .. "): " or '' local Prefix = "@ Group"
Prefix = Prefix .. ( Name and " (" .. Name .. "): " or '' )
Message = Prefix .. Message Message = Prefix .. Message
self:GetPositionable():MessageToGroup( Message , 20, TaskGroup, self:GetName() ) self:GetPositionable():MessageToGroup( Message , 20, TaskGroup, self:GetName() )
@@ -247,6 +268,7 @@ function COMMANDCENTER:MessageToCoalition( Message )
end end
--- Report the status of all MISSIONs to a GROUP. --- Report the status of all MISSIONs to a GROUP.
-- Each Mission is listed, with an indication how many Tasks are still to be completed. -- Each Mission is listed, with an indication how many Tasks are still to be completed.
-- @param #COMMANDCENTER self -- @param #COMMANDCENTER self

View File

@@ -34,23 +34,6 @@
-- ------------------------------- -- -------------------------------
-- The @{DetectionManager#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance. -- The @{DetectionManager#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
-- --
-- ===
--
-- 3) @{#DETECTION_DISPATCHER} class, extends @{#DETECTION_MANAGER}
-- ================================================================
-- The @{#DETECTION_DISPATCHER} class implements the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of FAC (groups).
-- The FAC will detect units, will group them, and will dispatch @{Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
-- Find a summary below describing for which situation a task type is created:
--
-- * **CAS Task**: Is created when there are enemy ground units within range of the FAC, while there are friendly units in the FAC perimeter.
-- * **BAI Task**: Is created when there are enemy ground units within range of the FAC, while there are NO other friendly units within the FAC perimeter.
-- * **SEAD Task**: Is created when there are enemy ground units wihtin range of the FAC, with air search radars.
--
-- Other task types will follow...
--
-- 3.1) DETECTION_DISPATCHER constructor:
-- --------------------------------------
-- The @{#DETECTION_DISPATCHER.New}() method creates a new DETECTION_DISPATCHER instance.
-- --
-- === -- ===
-- --
@@ -88,6 +71,8 @@ do -- DETECTION MANAGER
self:SetReportInterval( 30 ) self:SetReportInterval( 30 )
self:SetReportDisplayTime( 25 ) self:SetReportDisplayTime( 25 )
Detection:__Start( 5 )
return self return self
end end
@@ -250,259 +235,3 @@ do -- DETECTION_REPORTING
end end
do -- DETECTION_DISPATCHER
--- DETECTION_DISPATCHER class.
-- @type DETECTION_DISPATCHER
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @field Tasking.Mission#MISSION Mission
-- @field Wrapper.Group#GROUP CommandCenter
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
DETECTION_DISPATCHER = {
ClassName = "DETECTION_DISPATCHER",
Mission = nil,
CommandCenter = nil,
Detection = nil,
}
--- DETECTION_DISPATCHER constructor.
-- @param #DETECTION_DISPATCHER self
-- @param Set#SET_GROUP SetGroup
-- @param Functional.Detection#DETECTION_BASE Detection
-- @return #DETECTION_DISPATCHER self
function DETECTION_DISPATCHER:New( Mission, CommandCenter, SetGroup, Detection )
-- Inherits from DETECTION_MANAGER
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #DETECTION_DISPATCHER
self.Detection = Detection
self.CommandCenter = CommandCenter
self.Mission = Mission
self:Schedule( 30 )
return self
end
--- Creates a SEAD task when there are targets for it.
-- @param #DETECTION_DISPATCHER self
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
-- @return #nil If there are no targets to be set.
function DETECTION_DISPATCHER:EvaluateSEAD( DetectedArea )
self:F( { DetectedArea.AreaID } )
local DetectedSet = DetectedArea.Set
local DetectedZone = DetectedArea.Zone
-- Determine if the set has radar targets. If it does, construct a SEAD task.
local RadarCount = DetectedSet:HasSEAD()
if RadarCount > 0 then
-- Here we're doing something advanced... We're copying the DetectedSet, but making a new Set only with SEADable Radar units in it.
local TargetSetUnit = SET_UNIT:New()
TargetSetUnit:SetDatabase( DetectedSet )
TargetSetUnit:FilterHasSEAD()
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
return TargetSetUnit
end
return nil
end
--- Creates a CAS task when there are targets for it.
-- @param #DETECTION_DISPATCHER self
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Tasking.Task#TASK
function DETECTION_DISPATCHER:EvaluateCAS( DetectedArea )
self:F( { DetectedArea.AreaID } )
local DetectedSet = DetectedArea.Set
local DetectedZone = DetectedArea.Zone
-- Determine if the set has radar targets. If it does, construct a SEAD task.
local GroundUnitCount = DetectedSet:HasGroundUnits()
local FriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedArea )
if GroundUnitCount > 0 and FriendliesNearBy == true then
-- Copy the Set
local TargetSetUnit = SET_UNIT:New()
TargetSetUnit:SetDatabase( DetectedSet )
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
return TargetSetUnit
end
return nil
end
--- Creates a BAI task when there are targets for it.
-- @param #DETECTION_DISPATCHER self
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Tasking.Task#TASK
function DETECTION_DISPATCHER:EvaluateBAI( DetectedArea, FriendlyCoalition )
self:F( { DetectedArea.AreaID } )
local DetectedSet = DetectedArea.Set
local DetectedZone = DetectedArea.Zone
-- Determine if the set has radar targets. If it does, construct a SEAD task.
local GroundUnitCount = DetectedSet:HasGroundUnits()
local FriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedArea )
if GroundUnitCount > 0 and FriendliesNearBy == false then
-- Copy the Set
local TargetSetUnit = SET_UNIT:New()
TargetSetUnit:SetDatabase( DetectedSet )
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
return TargetSetUnit
end
return nil
end
--- Evaluates the removal of the Task from the Mission.
-- Can only occur when the DetectedArea is Changed AND the state of the Task is "Planned".
-- @param #DETECTION_DISPATCHER self
-- @param Tasking.Mission#MISSION Mission
-- @param Tasking.Task#TASK Task
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Tasking.Task#TASK
function DETECTION_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedArea )
if Task then
if Task:IsStatePlanned() and DetectedArea.Changed == true then
self:E( "Removing Tasking: " .. Task:GetTaskName() )
Task = Mission:RemoveTask( Task )
end
end
return Task
end
--- Assigns tasks in relation to the detected items to the @{Set#SET_GROUP}.
-- @param #DETECTION_DISPATCHER self
-- @param Functional.Detection#DETECTION_AREAS Detection The detection created by the @{Detection#DETECTION_AREAS} object.
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
function DETECTION_DISPATCHER:ProcessDetected( Detection )
self:F2()
local AreaMsg = {}
local TaskMsg = {}
local ChangeMsg = {}
local Mission = self.Mission
--- First we need to the detected targets.
for DetectedAreaID, DetectedAreaData in ipairs( Detection:GetDetectedAreas() ) do
local DetectedArea = DetectedAreaData -- Functional.Detection#DETECTION_AREAS.DetectedArea
local DetectedSet = DetectedArea.Set
local DetectedZone = DetectedArea.Zone
self:E( { "Targets in DetectedArea", DetectedArea.AreaID, DetectedSet:Count(), tostring( DetectedArea ) } )
DetectedSet:Flush()
local AreaID = DetectedArea.AreaID
-- Evaluate SEAD Tasking
local SEADTask = Mission:GetTask( "SEAD." .. AreaID )
SEADTask = self:EvaluateRemoveTask( Mission, SEADTask, DetectedArea )
if not SEADTask then
local TargetSetUnit = self:EvaluateSEAD( DetectedArea ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
SEADTask = Mission:AddTask( TASK_SEAD:New( Mission, self.SetGroup, "SEAD." .. AreaID, TargetSetUnit , DetectedZone ) )
end
end
if SEADTask and SEADTask:IsStatePlanned() then
self:E( "Planned" )
--SEADTask:SetPlannedMenu()
TaskMsg[#TaskMsg+1] = " - " .. SEADTask:GetStateString() .. " SEAD " .. AreaID .. " - " .. SEADTask.TargetSetUnit:GetUnitTypesText()
end
-- Evaluate CAS Tasking
local CASTask = Mission:GetTask( "CAS." .. AreaID )
CASTask = self:EvaluateRemoveTask( Mission, CASTask, DetectedArea )
if not CASTask then
local TargetSetUnit = self:EvaluateCAS( DetectedArea ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
CASTask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "CAS." .. AreaID, "CAS", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) )
end
end
if CASTask and CASTask:IsStatePlanned() then
--CASTask:SetPlannedMenu()
TaskMsg[#TaskMsg+1] = " - " .. CASTask:GetStateString() .. " CAS " .. AreaID .. " - " .. CASTask.TargetSetUnit:GetUnitTypesText()
end
-- Evaluate BAI Tasking
local BAITask = Mission:GetTask( "BAI." .. AreaID )
BAITask = self:EvaluateRemoveTask( Mission, BAITask, DetectedArea )
if not BAITask then
local TargetSetUnit = self:EvaluateBAI( DetectedArea, self.CommandCenter:GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
BAITask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "BAI." .. AreaID, "BAI", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) )
end
end
if BAITask and BAITask:IsStatePlanned() then
--BAITask:SetPlannedMenu()
TaskMsg[#TaskMsg+1] = " - " .. BAITask:GetStateString() .. " BAI " .. AreaID .. " - " .. BAITask.TargetSetUnit:GetUnitTypesText()
end
if #TaskMsg > 0 then
local ThreatLevel = Detection:GetTreatLevelA2G( DetectedArea )
local DetectedAreaVec3 = DetectedZone:GetVec3()
local DetectedAreaPointVec3 = POINT_VEC3:New( DetectedAreaVec3.x, DetectedAreaVec3.y, DetectedAreaVec3.z )
local DetectedAreaPointLL = DetectedAreaPointVec3:ToStringLL( 3, true )
AreaMsg[#AreaMsg+1] = string.format( " - Area #%d - %s - Threat Level [%s] (%2d)",
DetectedAreaID,
DetectedAreaPointLL,
string.rep( "", ThreatLevel ),
ThreatLevel
)
-- Loop through the changes ...
local ChangeText = Detection:GetChangeText( DetectedArea )
if ChangeText ~= "" then
ChangeMsg[#ChangeMsg+1] = string.gsub( string.gsub( ChangeText, "\n", "%1 - " ), "^.", " - %1" )
end
end
-- OK, so the tasking has been done, now delete the changes reported for the area.
Detection:AcceptChanges( DetectedArea )
end
-- TODO set menus using the HQ coordinator
Mission:GetCommandCenter():SetMenu()
if #AreaMsg > 0 then
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
self.CommandCenter:MessageToGroup(
string.format( "HQ Reporting - Target areas for mission '%s':\nAreas:\n%s\n\nTasks:\n%s\n\nChanges:\n%s ",
self.Mission:GetName(),
table.concat( AreaMsg, "\n" ),
table.concat( TaskMsg, "\n" ),
table.concat( ChangeMsg, "\n" )
), self:GetReportDisplayTime(), TaskGroup
)
end
end
end
return true
end
end

View File

@@ -12,22 +12,6 @@ MISSION = {
ClassName = "MISSION", ClassName = "MISSION",
Name = "", Name = "",
MissionStatus = "PENDING", MissionStatus = "PENDING",
_Clients = {},
TaskMenus = {},
TaskCategoryMenus = {},
TaskTypeMenus = {},
_ActiveTasks = {},
GoalFunction = nil,
MissionReportTrigger = 0,
MissionProgressTrigger = 0,
MissionReportShow = false,
MissionReportFlash = false,
MissionTimeInterval = 0,
MissionCoalition = "",
SUCCESS = 1,
FAILED = 2,
REPEAT = 3,
_GoalTasks = {}
} }
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc. --- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
@@ -45,10 +29,184 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
self:SetStartState( "Idle" ) self:SetStartState( "Idle" )
self:AddTransition( "Idle", "Start", "Ongoing" ) self:AddTransition( "Idle", "Start", "Ongoing" )
--- OnLeave Transition Handler for State Idle.
-- @function [parent=#MISSION] OnLeaveIdle
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Idle.
-- @function [parent=#MISSION] OnEnterIdle
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- OnLeave Transition Handler for State Ongoing.
-- @function [parent=#MISSION] OnLeaveOngoing
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Ongoing.
-- @function [parent=#MISSION] OnEnterOngoing
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- OnBefore Transition Handler for Event Start.
-- @function [parent=#MISSION] OnBeforeStart
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Start.
-- @function [parent=#MISSION] OnAfterStart
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Start.
-- @function [parent=#MISSION] Start
-- @param #MISSION self
--- Asynchronous Event Trigger for Event Start.
-- @function [parent=#MISSION] __Start
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "Ongoing", "Stop", "Idle" ) self:AddTransition( "Ongoing", "Stop", "Idle" )
--- OnLeave Transition Handler for State Idle.
-- @function [parent=#MISSION] OnLeaveIdle
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Idle.
-- @function [parent=#MISSION] OnEnterIdle
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- OnBefore Transition Handler for Event Stop.
-- @function [parent=#MISSION] OnBeforeStop
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Stop.
-- @function [parent=#MISSION] OnAfterStop
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Stop.
-- @function [parent=#MISSION] Stop
-- @param #MISSION self
--- Asynchronous Event Trigger for Event Stop.
-- @function [parent=#MISSION] __Stop
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "Ongoing", "Complete", "Completed" ) self:AddTransition( "Ongoing", "Complete", "Completed" )
--- OnLeave Transition Handler for State Completed.
-- @function [parent=#MISSION] OnLeaveCompleted
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Completed.
-- @function [parent=#MISSION] OnEnterCompleted
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- OnBefore Transition Handler for Event Complete.
-- @function [parent=#MISSION] OnBeforeComplete
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Complete.
-- @function [parent=#MISSION] OnAfterComplete
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Complete.
-- @function [parent=#MISSION] Complete
-- @param #MISSION self
--- Asynchronous Event Trigger for Event Complete.
-- @function [parent=#MISSION] __Complete
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "*", "Fail", "Failed" ) self:AddTransition( "*", "Fail", "Failed" )
--- OnLeave Transition Handler for State Failed.
-- @function [parent=#MISSION] OnLeaveFailed
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Failed.
-- @function [parent=#MISSION] OnEnterFailed
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- OnBefore Transition Handler for Event Fail.
-- @function [parent=#MISSION] OnBeforeFail
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Fail.
-- @function [parent=#MISSION] OnAfterFail
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Fail.
-- @function [parent=#MISSION] Fail
-- @param #MISSION self
--- Asynchronous Event Trigger for Event Fail.
-- @function [parent=#MISSION] __Fail
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } ) self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
self.CommandCenter = CommandCenter self.CommandCenter = CommandCenter
@@ -61,13 +219,17 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
self.Tasks = {} self.Tasks = {}
-- Private implementations
return self return self
end end
--- FSM function for a MISSION -- FSM function for a MISSION
-- @param #MISSION self -- @param #MISSION self
-- @param #string Event
-- @param #string From -- @param #string From
-- @param #string Event
-- @param #string To -- @param #string To
function MISSION:onbeforeComplete( From, Event, To ) function MISSION:onbeforeComplete( From, Event, To )
@@ -80,10 +242,10 @@ function MISSION:onbeforeComplete( From, Event, To )
return true -- Allow Mission completion. return true -- Allow Mission completion.
end end
--- FSM function for a MISSION -- FSM function for a MISSION
-- @param #MISSION self -- @param #MISSION self
-- @param #string Event
-- @param #string From -- @param #string From
-- @param #string Event
-- @param #string To -- @param #string To
function MISSION:onenterCompleted( From, Event, To ) function MISSION:onenterCompleted( From, Event, To )
@@ -201,23 +363,25 @@ end
--- Sets the Planned Task menu. --- Sets the Planned Task menu.
-- @param #MISSION self -- @param #MISSION self
function MISSION:SetMenu() -- @param #number MenuTime
function MISSION:SetMenu( MenuTime )
self:F() self:F()
for _, Task in pairs( self:GetTasks() ) do for _, TaskData in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK local Task = TaskData -- Tasking.Task#TASK
Task:SetMenu() Task:SetMenu( MenuTime )
end end
end end
--- Removes the Planned Task menu. --- Removes the Planned Task menu.
-- @param #MISSION self -- @param #MISSION self
function MISSION:RemoveMenu() -- @param #number MenuTime
function MISSION:RemoveMenu( MenuTime )
self:F() self:F()
for _, Task in pairs( self:GetTasks() ) do for _, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK local Task = Task -- Tasking.Task#TASK
Task:RemoveMenu() Task:RemoveMenu( MenuTime )
end end
end end
@@ -229,20 +393,6 @@ function MISSION:GetCommandCenter()
return self.CommandCenter return self.CommandCenter
end end
--- Sets the Assigned Task menu.
-- @param #MISSION self
-- @param Tasking.Task#TASK Task
-- @param #string MenuText The menu text.
-- @return #MISSION self
function MISSION:SetAssignedMenu( Task )
for _, Task in pairs( self.Tasks ) do
local Task = Task -- Tasking.Task#TASK
Task:RemoveMenu()
Task:SetAssignedMenu()
end
end
--- Removes a Task menu. --- Removes a Task menu.
-- @param #MISSION self -- @param #MISSION self
@@ -258,28 +408,18 @@ end
-- @param #MISSION self -- @param #MISSION self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @return Core.Menu#MENU_COALITION self -- @return Core.Menu#MENU_COALITION self
function MISSION:GetMissionMenu( TaskGroup ) function MISSION:GetMenu( TaskGroup )
local CommandCenter = self:GetCommandCenter() local CommandCenter = self:GetCommandCenter()
local CommandCenterMenu = CommandCenter.CommandCenterMenu local CommandCenterMenu = CommandCenter:GetMenu()
local MissionName = self:GetName() local MissionName = self:GetName()
local MissionMenu = CommandCenterMenu:GetMenu( MissionName )
local TaskGroupName = TaskGroup:GetName()
local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu )
return MissionMenu return MissionMenu
end end
--- Clears the mission menu for the coalition.
-- @param #MISSION self
-- @return #MISSION self
function MISSION:ClearMissionMenu()
self.MissionMenu:Remove()
self.MissionMenu = nil
end
--- Get the TASK identified by the TaskNumber from the Mission. This function is useful in GoalFunctions. --- Get the TASK identified by the TaskNumber from the Mission. This function is useful in GoalFunctions.
-- @param #string TaskName The Name of the @{Task} within the @{Mission}. -- @param #string TaskName The Name of the @{Task} within the @{Mission}.
-- @return Tasking.Task#TASK The Task -- @return Tasking.Task#TASK The Task
@@ -350,76 +490,44 @@ function MISSION:GetNextTaskID( Task )
return self.Tasks[TaskName].n return self.Tasks[TaskName].n
end end
--- Is the @{Mission} **Completed**.
-- @param #MISSION self
--- old stuff -- @return #boolean
--- Returns if a Mission has completed.
-- @return bool
function MISSION:IsCompleted() function MISSION:IsCompleted()
self:F() return self:Is( "Completed" )
return self.MissionStatus == "ACCOMPLISHED"
end end
--- Set a Mission to completed. --- Is the @{Mission} **Idle**.
function MISSION:Completed() -- @param #MISSION self
self:F() -- @return #boolean
self.MissionStatus = "ACCOMPLISHED" function MISSION:IsIdle()
self:StatusToClients() return self:Is( "Idle" )
end end
--- Returns if a Mission is ongoing. --- Is the @{Mission} **Ongoing**.
-- treturn bool -- @param #MISSION self
-- @return #boolean
function MISSION:IsOngoing() function MISSION:IsOngoing()
self:F() return self:Is( "Ongoing" )
return self.MissionStatus == "ONGOING"
end end
--- Set a Mission to ongoing. --- Is the @{Mission} **Failed**.
function MISSION:Ongoing() -- @param #MISSION self
self:F() -- @return #boolean
self.MissionStatus = "ONGOING"
--self:StatusToClients()
end
--- Returns if a Mission is pending.
-- treturn bool
function MISSION:IsPending()
self:F()
return self.MissionStatus == "PENDING"
end
--- Set a Mission to pending.
function MISSION:Pending()
self:F()
self.MissionStatus = "PENDING"
self:StatusToClients()
end
--- Returns if a Mission has failed.
-- treturn bool
function MISSION:IsFailed() function MISSION:IsFailed()
self:F() return self:Is( "Failed" )
return self.MissionStatus == "FAILED"
end end
--- Set a Mission to failed. --- Is the @{Mission} **Hold**.
function MISSION:Failed() -- @param #MISSION self
self:F() -- @return #boolean
self.MissionStatus = "FAILED" function MISSION:IsHold()
self:StatusToClients() return self:Is( "Hold" )
end
--- Send the status of the MISSION to all Clients.
function MISSION:StatusToClients()
self:F()
if self.MissionReportFlash then
for ClientID, Client in pairs( self._Clients ) do
Client:Message( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. '! ( ' .. self.MissionPriority .. ' mission ) ', 10, "Mission Command: Mission Status")
end
end
end end
--- Validates if the Mission has a Group
-- @param #MISSION
-- @return #boolean true if the Mission has a Group.
function MISSION:HasGroup( TaskGroup ) function MISSION:HasGroup( TaskGroup )
local Has = false local Has = false
@@ -512,107 +620,6 @@ function MISSION:ReportDetails()
return Report:Text() return Report:Text()
end end
--- Report the status of all MISSIONs to all active Clients.
function MISSION:ReportToAll()
self:F()
local AlivePlayers = ''
for ClientID, Client in pairs( self._Clients ) do
if Client:GetDCSGroup() then
if Client:GetClientGroupDCSUnit() then
if Client:GetClientGroupDCSUnit():getLife() > 0.0 then
if AlivePlayers == '' then
AlivePlayers = ' Players: ' .. Client:GetClientGroupDCSUnit():getPlayerName()
else
AlivePlayers = AlivePlayers .. ' / ' .. Client:GetClientGroupDCSUnit():getPlayerName()
end
end
end
end
end
local Tasks = self:GetTasks()
local TaskText = ""
for TaskID, TaskData in pairs( Tasks ) do
TaskText = TaskText .. " - Task " .. TaskID .. ": " .. TaskData.Name .. ": " .. TaskData:GetGoalProgress() .. "\n"
end
MESSAGE:New( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. ' ( ' .. self.MissionPriority .. ' mission )' .. AlivePlayers .. "\n" .. TaskText:gsub("\n$",""), 10, "Mission Command: Mission Report" ):ToAll()
end
--- Add a goal function to a MISSION. Goal functions are called when a @{TASK} within a mission has been completed.
-- @param function GoalFunction is the function defined by the mission designer to evaluate whether a certain goal has been reached after a @{TASK} finishes within the @{MISSION}. A GoalFunction must accept 2 parameters: Mission, Client, which contains the current MISSION object and the current CLIENT object respectively.
-- @usage
-- PatriotActivation = {
-- { "US SAM Patriot Zerti", false },
-- { "US SAM Patriot Zegduleti", false },
-- { "US SAM Patriot Gvleti", false }
-- }
--
-- function DeployPatriotTroopsGoal( Mission, Client )
--
--
-- -- Check if the cargo is all deployed for mission success.
-- for CargoID, CargoData in pairs( Mission._Cargos ) do
-- if Group.getByName( CargoData.CargoGroupName ) then
-- CargoGroup = Group.getByName( CargoData.CargoGroupName )
-- if CargoGroup then
-- -- Check if the cargo is ready to activate
-- CurrentLandingZoneID = routines.IsUnitInZones( CargoGroup:getUnits()[1], Mission:GetTask( 2 ).LandingZones ) -- The second task is the Deploytask to measure mission success upon
-- if CurrentLandingZoneID then
-- if PatriotActivation[CurrentLandingZoneID][2] == false then
-- -- Now check if this is a new Mission Task to be completed...
-- trigger.action.setGroupAIOn( Group.getByName( PatriotActivation[CurrentLandingZoneID][1] ) )
-- PatriotActivation[CurrentLandingZoneID][2] = true
-- MessageToBlue( "Mission Command: Message to all airborne units! The " .. PatriotActivation[CurrentLandingZoneID][1] .. " is armed. Our air defenses are now stronger.", 60, "BLUE/PatriotDefense" )
-- MessageToRed( "Mission Command: Our satellite systems are detecting additional NATO air defenses. To all airborne units: Take care!!!", 60, "RED/PatriotDefense" )
-- Mission:GetTask( 2 ):AddGoalCompletion( "Patriots activated", PatriotActivation[CurrentLandingZoneID][1], 1 ) -- Register Patriot activation as part of mission goal.
-- end
-- end
-- end
-- end
-- end
-- end
--
-- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Transport Troops', 'Operational', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.', 'NATO' )
-- Mission:AddGoalFunction( DeployPatriotTroopsGoal )
function MISSION:AddGoalFunction( GoalFunction )
self:F()
self.GoalFunction = GoalFunction
end
--- Register a new @{CLIENT} to participate within the mission.
-- @param CLIENT Client is the @{CLIENT} object. The object must have been instantiated with @{CLIENT:New}.
-- @return CLIENT
-- @usage
-- Add a number of Client objects to the Mission.
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 1', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 3', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 2', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 4', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
function MISSION:AddClient( Client )
self:F( { Client } )
local Valid = true
if Valid then
self._Clients[Client.ClientName] = Client
end
return Client
end
--- Find a @{CLIENT} object within the @{MISSION} by its ClientName.
-- @param CLIENT ClientName is a string defining the Client Group as defined within the ME.
-- @return CLIENT
-- @usage
-- -- Seach for Client "Bomber" within the Mission.
-- local BomberClient = Mission:FindClient( "Bomber" )
function MISSION:FindClient( ClientName )
self:F( { self._Clients[ClientName] } )
return self._Clients[ClientName]
end
--- Get all the TASKs from the Mission. This function is useful in GoalFunctions. --- Get all the TASKs from the Mission. This function is useful in GoalFunctions.
-- @return {TASK,...} Structure of TASKS with the @{TASK} number as the key. -- @return {TASK,...} Structure of TASKS with the @{TASK} number as the key.
-- @usage -- @usage
@@ -626,330 +633,3 @@ function MISSION:GetTasks()
end end
--[[
_TransportExecuteStage: Defines the different stages of Transport unload/load execution. This table is internal and is used to control the validity of Transport load/unload timing.
- _TransportExecuteStage.EXECUTING
- _TransportExecuteStage.SUCCESS
- _TransportExecuteStage.FAILED
--]]
_TransportExecuteStage = {
NONE = 0,
EXECUTING = 1,
SUCCESS = 2,
FAILED = 3
}
--- The MISSIONSCHEDULER is an OBJECT and is the main scheduler of ALL active MISSIONs registered within this scheduler. It's workings are considered internal and is automatically created when the Mission.lua file is included.
-- @type MISSIONSCHEDULER
-- @field #MISSIONSCHEDULER.MISSIONS Missions
MISSIONSCHEDULER = {
Missions = {},
MissionCount = 0,
TimeIntervalCount = 0,
TimeIntervalShow = 150,
TimeSeconds = 14400,
TimeShow = 5
}
--- @type MISSIONSCHEDULER.MISSIONS
-- @list <#MISSION> Mission
--- This is the main MISSIONSCHEDULER Scheduler function. It is considered internal and is automatically created when the Mission.lua file is included.
function MISSIONSCHEDULER.Scheduler()
-- loop through the missions in the TransportTasks
for MissionName, MissionData in pairs( MISSIONSCHEDULER.Missions ) do
local Mission = MissionData -- #MISSION
if not Mission:IsCompleted() then
-- This flag will monitor if for this mission, there are clients alive. If this flag is still false at the end of the loop, the mission status will be set to Pending (if not Failed or Completed).
local ClientsAlive = false
for ClientID, ClientData in pairs( Mission._Clients ) do
local Client = ClientData -- Wrapper.Client#CLIENT
if Client:IsAlive() then
-- There is at least one Client that is alive... So the Mission status is set to Ongoing.
ClientsAlive = true
-- If this Client was not registered as Alive before:
-- 1. We register the Client as Alive.
-- 2. We initialize the Client Tasks and make a link to the original Mission Task.
-- 3. We initialize the Cargos.
-- 4. We flag the Mission as Ongoing.
if not Client.ClientAlive then
Client.ClientAlive = true
Client.ClientBriefingShown = false
for TaskNumber, Task in pairs( Mission._Tasks ) do
-- Note that this a deepCopy. Each client must have their own Tasks with own Stages!!!
Client._Tasks[TaskNumber] = routines.utils.deepCopy( Mission._Tasks[TaskNumber] )
-- Each MissionTask must point to the original Mission.
Client._Tasks[TaskNumber].MissionTask = Mission._Tasks[TaskNumber]
Client._Tasks[TaskNumber].Cargos = Mission._Tasks[TaskNumber].Cargos
Client._Tasks[TaskNumber].LandingZones = Mission._Tasks[TaskNumber].LandingZones
end
Mission:Ongoing()
end
-- For each Client, check for each Task the state and evolve the mission.
-- This flag will indicate if the Task of the Client is Complete.
local TaskComplete = false
for TaskNumber, Task in pairs( Client._Tasks ) do
if not Task.Stage then
Task:SetStage( 1 )
end
local TransportTime = timer.getTime()
if not Task:IsDone() then
if Task:Goal() then
Task:ShowGoalProgress( Mission, Client )
end
--env.info( 'Scheduler: Mission = ' .. Mission.Name .. ' / Client = ' .. Client.ClientName .. ' / Task = ' .. Task.Name .. ' / Stage = ' .. Task.ActiveStage .. ' - ' .. Task.Stage.Name .. ' - ' .. Task.Stage.StageType )
-- Action
if Task:StageExecute() then
Task.Stage:Execute( Mission, Client, Task )
end
-- Wait until execution is finished
if Task.ExecuteStage == _TransportExecuteStage.EXECUTING then
Task.Stage:Executing( Mission, Client, Task )
end
-- Validate completion or reverse to earlier stage
if Task.Time + Task.Stage.WaitTime <= TransportTime then
Task:SetStage( Task.Stage:Validate( Mission, Client, Task ) )
end
if Task:IsDone() then
--env.info( 'Scheduler: Mission '.. Mission.Name .. ' Task ' .. Task.Name .. ' Stage ' .. Task.Stage.Name .. ' done. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
TaskComplete = true -- when a task is not yet completed, a mission cannot be completed
else
-- break only if this task is not yet done, so that future task are not yet activated.
TaskComplete = false -- when a task is not yet completed, a mission cannot be completed
--env.info( 'Scheduler: Mission "'.. Mission.Name .. '" Task "' .. Task.Name .. '" Stage "' .. Task.Stage.Name .. '" break. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
break
end
if TaskComplete then
if Mission.GoalFunction ~= nil then
Mission.GoalFunction( Mission, Client )
end
if MISSIONSCHEDULER.Scoring then
MISSIONSCHEDULER.Scoring:_AddMissionTaskScore( Client:GetClientGroupDCSUnit(), Mission.Name, 25 )
end
-- if not Mission:IsCompleted() then
-- end
end
end
end
local MissionComplete = true
for TaskNumber, Task in pairs( Mission._Tasks ) do
if Task:Goal() then
-- Task:ShowGoalProgress( Mission, Client )
if Task:IsGoalReached() then
else
MissionComplete = false
end
else
MissionComplete = false -- If there is no goal, the mission should never be ended. The goal status will be set somewhere else.
end
end
if MissionComplete then
Mission:Completed()
if MISSIONSCHEDULER.Scoring then
MISSIONSCHEDULER.Scoring:_AddMissionScore( Mission.Name, 100 )
end
else
if TaskComplete then
-- Reset for new tasking of active client
Client.ClientAlive = false -- Reset the client tasks.
end
end
else
if Client.ClientAlive then
env.info( 'Scheduler: Client "' .. Client.ClientName .. '" is inactive.' )
Client.ClientAlive = false
-- This is tricky. If we sanitize Client._Tasks before sanitizing Client._Tasks[TaskNumber].MissionTask, then the original MissionTask will be sanitized, and will be lost within the garbage collector.
-- So first sanitize Client._Tasks[TaskNumber].MissionTask, after that, sanitize only the whole _Tasks structure...
--Client._Tasks[TaskNumber].MissionTask = nil
--Client._Tasks = nil
end
end
end
-- If all Clients of this Mission are not activated, then the Mission status needs to be put back into Pending status.
-- But only if the Mission was Ongoing. In case the Mission is Completed or Failed, the Mission status may not be changed. In these cases, this will be the last run of this Mission in the Scheduler.
if ClientsAlive == false then
if Mission:IsOngoing() then
-- Mission status back to pending...
Mission:Pending()
end
end
end
Mission:StatusToClients()
if Mission:ReportTrigger() then
Mission:ReportToAll()
end
end
return true
end
--- Start the MISSIONSCHEDULER.
function MISSIONSCHEDULER.Start()
if MISSIONSCHEDULER ~= nil then
--MISSIONSCHEDULER.SchedulerId = routines.scheduleFunction( MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
MISSIONSCHEDULER.SchedulerId = SCHEDULER:New( nil, MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
end
end
--- Stop the MISSIONSCHEDULER.
function MISSIONSCHEDULER.Stop()
if MISSIONSCHEDULER.SchedulerId then
routines.removeFunction(MISSIONSCHEDULER.SchedulerId)
MISSIONSCHEDULER.SchedulerId = nil
end
end
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
-- @param Mission is the MISSION object instantiated by @{MISSION:New}.
-- @return MISSION
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
function MISSIONSCHEDULER.AddMission( Mission )
MISSIONSCHEDULER.Missions[Mission.Name] = Mission
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount + 1
-- Add an overall AI Client for the AI tasks... This AI Client will facilitate the Events in the background for each Task.
--MissionAdd:AddClient( CLIENT:Register( 'AI' ) )
return Mission
end
--- Remove a MISSION from the MISSIONSCHEDULER.
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
--
-- -- Now remove the Mission.
-- MISSIONSCHEDULER:RemoveMission( 'Russia Transport Troops SA-6' )
function MISSIONSCHEDULER.RemoveMission( MissionName )
MISSIONSCHEDULER.Missions[MissionName] = nil
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount - 1
end
--- Find a MISSION within the MISSIONSCHEDULER.
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
-- @return MISSION
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
--
-- -- Now find the Mission.
-- MissionFind = MISSIONSCHEDULER:FindMission( 'Russia Transport Troops SA-6' )
function MISSIONSCHEDULER.FindMission( MissionName )
return MISSIONSCHEDULER.Missions[MissionName]
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsShow( )
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = true
Mission.MissionReportFlash = false
end
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsFlash( TimeInterval )
local Count = 0
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = false
Mission.MissionReportFlash = true
Mission.MissionReportTrigger = timer.getTime() + Count * TimeInterval
Mission.MissionTimeInterval = MISSIONSCHEDULER.MissionCount * TimeInterval
env.info( "TimeInterval = " .. Mission.MissionTimeInterval )
Count = Count + 1
end
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsHide( Prm )
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = false
Mission.MissionReportFlash = false
end
end
--- Enables a MENU option in the communications menu under F10 to control the status of the active missions.
-- This function should be called only once when starting the MISSIONSCHEDULER.
function MISSIONSCHEDULER.ReportMenu()
local ReportMenu = SUBMENU:New( 'Status' )
local ReportMenuShow = COMMANDMENU:New( 'Show Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsShow, 0 )
local ReportMenuFlash = COMMANDMENU:New('Flash Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsFlash, 120 )
local ReportMenuHide = COMMANDMENU:New( 'Hide Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsHide, 0 )
end
--- Show the remaining mission time.
function MISSIONSCHEDULER:TimeShow()
self.TimeIntervalCount = self.TimeIntervalCount + 1
if self.TimeIntervalCount >= self.TimeTriggerShow then
local TimeMsg = string.format("%00d", ( self.TimeSeconds / 60 ) - ( timer.getTime() / 60 )) .. ' minutes left until mission reload.'
MESSAGE:New( TimeMsg, self.TimeShow, "Mission time" ):ToAll()
self.TimeIntervalCount = 0
end
end
function MISSIONSCHEDULER:Time( TimeSeconds, TimeIntervalShow, TimeShow )
self.TimeIntervalCount = 0
self.TimeSeconds = TimeSeconds
self.TimeIntervalShow = TimeIntervalShow
self.TimeShow = TimeShow
end
--- Adds a mission scoring to the game.
function MISSIONSCHEDULER:Scoring( Scoring )
self.Scoring = Scoring
end

View File

@@ -185,7 +185,6 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType )
self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New() self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New()
Mission:AddTask( self )
return self return self
end end
@@ -193,9 +192,13 @@ end
--- Get the Task FSM Process Template --- Get the Task FSM Process Template
-- @param #TASK self -- @param #TASK self
-- @return Core.Fsm#FSM_PROCESS -- @return Core.Fsm#FSM_PROCESS
function TASK:GetUnitProcess() function TASK:GetUnitProcess( TaskUnit )
if TaskUnit then
return self:GetStateMachine( TaskUnit )
else
return self.FsmTemplate return self.FsmTemplate
end
end end
--- Sets the Task FSM Process Template --- Sets the Task FSM Process Template
@@ -228,7 +231,7 @@ function TASK:JoinUnit( PlayerUnit, PlayerGroup )
-- If the PlayerGroup is not assigned to the Task, the menu needs to be set. In that case, the PlayerUnit will become the GroupPlayer leader. -- If the PlayerGroup is not assigned to the Task, the menu needs to be set. In that case, the PlayerUnit will become the GroupPlayer leader.
if self:IsStatePlanned() or self:IsStateReplanned() then if self:IsStatePlanned() or self:IsStateReplanned() then
self:SetMenuForGroup( PlayerGroup ) self:SetMenuForGroup( PlayerGroup )
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " is planning to join Task " .. self:GetName() ) --self:MessageToGroups( PlayerUnit:GetPlayerName() .. " is planning to join Task " .. self:GetName() )
end end
if self:IsStateAssigned() then if self:IsStateAssigned() then
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup ) local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
@@ -270,10 +273,11 @@ function TASK:AbortUnit( PlayerUnit )
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " aborted Task " .. self:GetName() ) self:MessageToGroups( PlayerUnit:GetPlayerName() .. " aborted Task " .. self:GetName() )
self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } ) self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } )
if #PlayerGroup:GetUnits() == 1 then if #PlayerGroup:GetUnits() == 1 then
self:UnAssignFromGroup( PlayerGroup )
PlayerGroup:SetState( PlayerGroup, "Assigned", nil ) PlayerGroup:SetState( PlayerGroup, "Assigned", nil )
self:RemoveMenuForGroup( PlayerGroup ) self:RemoveMenuForGroup( PlayerGroup )
end end
self:PlayerAborted( PlayerUnit ) self:Abort()
end end
end end
end end
@@ -339,7 +343,7 @@ end
--- Assign the @{Task}to a @{Group}. --- Assign the @{Task} to a @{Group}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK -- @return #TASK
@@ -350,7 +354,11 @@ function TASK:AssignToGroup( TaskGroup )
TaskGroup:SetState( TaskGroup, "Assigned", self ) TaskGroup:SetState( TaskGroup, "Assigned", self )
self:RemoveMenuForGroup( TaskGroup ) local Mission = self:GetMission()
local MissionMenu = Mission:GetMenu( TaskGroup )
MissionMenu:RemoveSubMenus()
--self:RemoveMenuForGroup( TaskGroup )
self:SetAssignedMenuForGroup( TaskGroup ) self:SetAssignedMenuForGroup( TaskGroup )
local TaskUnits = TaskGroup:GetUnits() local TaskUnits = TaskGroup:GetUnits()
@@ -390,6 +398,7 @@ function TASK:AssignToUnit( TaskUnit )
self:E({"Address FsmUnit", tostring( FsmUnit ) } ) self:E({"Address FsmUnit", tostring( FsmUnit ) } )
FsmUnit:SetStartState( "Planned" ) FsmUnit:SetStartState( "Planned" )
FsmUnit:Accept() -- Each Task needs to start with an Accept event to start the flow. FsmUnit:Accept() -- Each Task needs to start with an Accept event to start the flow.
return self return self
@@ -400,7 +409,7 @@ end
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK self -- @return #TASK self
function TASK:UnAssignFromUnit( TaskUnit ) function TASK:UnAssignFromUnit( TaskUnit )
self:F( TaskUnit ) self:F( TaskUnit:GetName() )
self:RemoveStateMachine( TaskUnit ) self:RemoveStateMachine( TaskUnit )
@@ -447,16 +456,24 @@ function TASK:SendBriefingToAssignedGroups()
end end
--- Assign the @{Task} from the @{Group}s. --- UnAssign the @{Task} from the @{Group}s.
-- @param #TASK self -- @param #TASK self
function TASK:UnAssignFromGroups() function TASK:UnAssignFromGroups()
self:F2() self:F2()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
self:UnAssignFromGroup( TaskGroup )
end
end
--- UnAssign the @{Task} from a @{Group}.
-- @param #TASK self
function TASK:UnAssignFromGroup( TaskGroup )
self:F2( { TaskGroup } )
TaskGroup:SetState( TaskGroup, "Assigned", nil ) TaskGroup:SetState( TaskGroup, "Assigned", nil )
self:RemoveMenuForGroup( TaskGroup ) self:RemoveAssignedMenuForGroup( TaskGroup )
local TaskUnits = TaskGroup:GetUnits() local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do for UnitID, UnitData in pairs( TaskUnits ) do
@@ -466,9 +483,10 @@ function TASK:UnAssignFromGroups()
self:UnAssignFromUnit( TaskUnit ) self:UnAssignFromUnit( TaskUnit )
end end
end end
end
end end
--- Returns if the @{Task} is assigned to the Group. --- Returns if the @{Task} is assigned to the Group.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
@@ -479,10 +497,12 @@ function TASK:IsAssignedToGroup( TaskGroup )
if self:IsStateAssigned() then if self:IsStateAssigned() then
if TaskGroup:GetState( TaskGroup, "Assigned" ) == self then if TaskGroup:GetState( TaskGroup, "Assigned" ) == self then
self:T( { "Task is assigned to:", TaskGroup:GetName() } )
return true return true
end end
end end
self:T( { "Task is not assigned to:", TaskGroup:GetName() } )
return false return false
end end
@@ -511,37 +531,36 @@ end
--- Set the menu options of the @{Task} to all the groups in the SetGroup. --- Set the menu options of the @{Task} to all the groups in the SetGroup.
-- @param #TASK self -- @param #TASK self
function TASK:SetMenu() -- @param #number MenuTime
-- @return #TASK
function TASK:SetMenu( MenuTime )
self:F() self:F()
self.SetGroup:Flush() self.SetGroup:Flush()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do for TaskGroupID, TaskGroupData in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroupData -- Wrapper.Group#GROUP
if TaskGroup:IsAlive() and TaskGroup:GetPlayerNames() then
if self:IsStatePlanned() or self:IsStateReplanned() then if self:IsStatePlanned() or self:IsStateReplanned() then
self:SetMenuForGroup( TaskGroup ) self:SetMenuForGroup( TaskGroup, MenuTime )
end
end end
end end
end end
--- Remove the menu options of the @{Task} to all the groups in the SetGroup.
-- @param #TASK self
-- @return #TASK self
function TASK:RemoveMenu()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
self:RemoveMenuForGroup( TaskGroup )
end
end
--- Set the Menu for a Group --- Set the Menu for a Group
-- @param #TASK self -- @param #TASK self
function TASK:SetMenuForGroup( TaskGroup ) -- @param #number MenuTime
-- @return #TASK
function TASK:SetMenuForGroup( TaskGroup, MenuTime )
if not self:IsAssignedToGroup( TaskGroup ) then if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
self:SetPlannedMenuForGroup( TaskGroup, self:GetTaskName() ) self:SetPlannedMenuForGroup( TaskGroup, self:GetTaskName(), MenuTime )
else else
self:SetAssignedMenuForGroup( TaskGroup ) if not self:IsAssignedToGroup( TaskGroup ) then
self:SetAssignedMenuForGroup( TaskGroup, MenuTime )
end
end end
end end
@@ -550,16 +569,24 @@ end
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @param #string MenuText The menu text. -- @param #string MenuText The menu text.
-- @param #number MenuTime
-- @return #TASK self -- @return #TASK self
function TASK:SetPlannedMenuForGroup( TaskGroup, MenuText ) function TASK:SetPlannedMenuForGroup( TaskGroup, MenuText, MenuTime )
self:E( TaskGroup:GetName() ) self:E( TaskGroup:GetName() )
local Mission = self:GetMission() local Mission = self:GetMission()
local MissionMenu = Mission:GetMissionMenu( TaskGroup ) local MissionName = Mission:GetName()
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime )
local MissionMenu = Mission:GetMenu( TaskGroup )
local TaskType = self:GetType() local TaskType = self:GetType()
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, MissionMenu ) local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, MissionMenu ):SetTime( MenuTime )
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, MenuText, TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ) local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, MenuText, TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ):SetTime( MenuTime ):SetRemoveParent( true )
return self return self
end end
@@ -567,32 +594,84 @@ end
--- Set the assigned menu options of the @{Task}. --- Set the assigned menu options of the @{Task}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @param #number MenuTime
-- @return #TASK self -- @return #TASK self
function TASK:SetAssignedMenuForGroup( TaskGroup ) function TASK:SetAssignedMenuForGroup( TaskGroup, MenuTime )
self:E( TaskGroup:GetName() ) self:E( TaskGroup:GetName() )
local Mission = self:GetMission() local Mission = self:GetMission()
local MissionMenu = Mission:GetMissionMenu( TaskGroup ) local MissionMenu = Mission:GetMenu( TaskGroup )
self:E( { MissionMenu = MissionMenu } ) self:E( { MissionMenu = MissionMenu } )
local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Task Status", MissionMenu, self.MenuTaskStatus, { self = self, TaskGroup = TaskGroup } ) local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Task Status", MissionMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime )
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Abort Task", MissionMenu, self.MenuTaskAbort, { self = self, TaskGroup = TaskGroup } ) local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Abort Task", MissionMenu, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime )
return self return self
end end
--- Remove the menu options of the @{Task} to all the groups in the SetGroup.
-- @param #TASK self
-- @param #number MenuTime
-- @return #TASK
function TASK:RemoveMenu( MenuTime )
self:F()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroup -- Wrapper.Group#GROUP
if TaskGroup:IsAlive() and TaskGroup:GetPlayerNames() then
if not self:IsAssignedToGroup( TaskGroup ) then
self:RemovePlannedMenuForGroup( TaskGroup, MenuTime )
end
end
end
end
--- Remove the menu option of the @{Task} for a @{Group}. --- Remove the menu option of the @{Task} for a @{Group}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @param #number MenuTime
-- @return #TASK self -- @return #TASK self
function TASK:RemoveMenuForGroup( TaskGroup ) function TASK:RemovePlannedMenuForGroup( TaskGroup, MenuTime )
self:F()
local Mission = self:GetMission() local Mission = self:GetMission()
local MissionName = Mission:GetName() local MissionName = Mission:GetName()
local MissionMenu = Mission:GetMissionMenu( TaskGroup ) local MissionMenu = Mission:GetMenu( TaskGroup )
MissionMenu:Remove()
if MissionMenu then
local TaskType = self:GetType()
local TypeMenu = MissionMenu:GetMenu( TaskType )
if TypeMenu then
local TaskMenu = TypeMenu:GetMenu( self:GetTaskName() )
if TaskMenu then
TaskMenu:Remove( MenuTime )
end
end
end
end
--- Remove the assigned menu option of the @{Task} for a @{Group}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @param #number MenuTime
-- @return #TASK self
function TASK:RemoveAssignedMenuForGroup( TaskGroup )
self:F()
local Mission = self:GetMission()
local MissionName = Mission:GetName()
local MissionMenu = Mission:GetMenu( TaskGroup )
if MissionMenu then
MissionMenu:RemoveSubMenus()
end
end end
function TASK.MenuAssignToGroup( MenuParam ) function TASK.MenuAssignToGroup( MenuParam )
@@ -605,18 +684,20 @@ function TASK.MenuAssignToGroup( MenuParam )
self:AssignToGroup( TaskGroup ) self:AssignToGroup( TaskGroup )
end end
function TASK.MenuTaskStatus( MenuParam ) --- Report the task status.
-- @param #TASK self
function TASK:MenuTaskStatus( TaskGroup )
local self = MenuParam.self local ReportText = self:ReportDetails()
local TaskGroup = MenuParam.TaskGroup
self:T( ReportText )
self:GetMission():GetCommandCenter():MessageToGroup( ReportText, TaskGroup )
--self:AssignToGroup( TaskGroup )
end end
function TASK.MenuTaskAbort( MenuParam ) --- Report the task status.
-- @param #TASK self
local self = MenuParam.self function TASK:MenuTaskAbort( TaskGroup )
local TaskGroup = MenuParam.TaskGroup
self:Abort() self:Abort()
end end
@@ -662,15 +743,26 @@ end
--- Add a FiniteStateMachine to @{Task} with key Task@{Unit} --- Add a FiniteStateMachine to @{Task} with key Task@{Unit}
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @return #TASK self -- @return #TASK self
function TASK:SetStateMachine( TaskUnit, Fsm ) function TASK:SetStateMachine( TaskUnit, Fsm )
self:F( { TaskUnit, self.Fsm[TaskUnit] ~= nil } ) self:F2( { TaskUnit, self.Fsm[TaskUnit] ~= nil, Fsm:GetClassNameAndID() } )
self.Fsm[TaskUnit] = Fsm self.Fsm[TaskUnit] = Fsm
return Fsm return Fsm
end end
--- Gets the FiniteStateMachine of @{Task} with key Task@{Unit}
-- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Fsm#FSM_PROCESS
function TASK:GetStateMachine( TaskUnit )
self:F2( { TaskUnit, self.Fsm[TaskUnit] ~= nil } )
return self.Fsm[TaskUnit]
end
--- Remove FiniteStateMachines from @{Task} with key Task@{Unit} --- Remove FiniteStateMachines from @{Task} with key Task@{Unit}
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
@@ -678,9 +770,15 @@ end
function TASK:RemoveStateMachine( TaskUnit ) function TASK:RemoveStateMachine( TaskUnit )
self:F( { TaskUnit, self.Fsm[TaskUnit] ~= nil } ) self:F( { TaskUnit, self.Fsm[TaskUnit] ~= nil } )
self:E( self.Fsm )
for TaskUnitT, Fsm in pairs( self.Fsm ) do
self:E( TaskUnitT )
end
self.Fsm[TaskUnit] = nil self.Fsm[TaskUnit] = nil
collectgarbage() collectgarbage()
self:T( "Garbage Collected, Processes should be finalized now ...") self:E( "Garbage Collected, Processes should be finalized now ...")
end end
--- Checks if there is a FiniteStateMachine assigned to Task@{Unit} for @{Task} --- Checks if there is a FiniteStateMachine assigned to Task@{Unit} for @{Task}
@@ -795,6 +893,32 @@ function TASK:IsStatePlanned()
return self:Is( "Planned" ) return self:Is( "Planned" )
end end
--- Sets a @{Task} to status **Aborted**.
-- @param #TASK self
function TASK:StateAborted()
self:SetState( self, "State", "Aborted" )
return self
end
--- Is the @{Task} status **Aborted**.
-- @param #TASK self
function TASK:IsStateAborted()
return self:Is( "Aborted" )
end
--- Sets a @{Task} to status **Cancelled**.
-- @param #TASK self
function TASK:StateCancelled()
self:SetState( self, "State", "Cancelled" )
return self
end
--- Is the @{Task} status **Cancelled**.
-- @param #TASK self
function TASK:IsStateCancelled()
return self:Is( "Cancelled" )
end
--- Sets a @{Task} to status **Assigned**. --- Sets a @{Task} to status **Assigned**.
-- @param #TASK self -- @param #TASK self
function TASK:StateAssigned() function TASK:StateAssigned()
@@ -875,7 +999,7 @@ function TASK:onenterSuccess( From, Event, To )
self:E( "Task Success" ) self:E( "Task Success" )
self:MessageToGroups( "Task " .. self:GetName() .. " is successful! Good job!" ) self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " is successful! Good job!" )
self:UnAssignFromGroups() self:UnAssignFromGroups()
self:GetMission():__Complete( 1 ) self:GetMission():__Complete( 1 )
@@ -1009,24 +1133,19 @@ function TASK:ReportDetails()
-- Determine the status of the Task. -- Determine the status of the Task.
local State = self:GetState() local State = self:GetState()
-- Loop each Unit active in the Task, and find Player Names. -- Loop each Unit active in the Task, and find Player Names.
local PlayerNames = {} local PlayerNames = {}
for PlayerGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do local PlayerReport = REPORT:New( " - Players:" )
local Player = PlayerGroup -- Wrapper.Group#GROUP for PlayerGroupID, PlayerGroupData in pairs( self:GetGroups():GetSet() ) do
for PlayerUnitID, PlayerUnit in pairs( PlayerGroup:GetUnits() ) do local PlayerGroup = PlayerGroupData -- Wrapper.Group#GROUP
local PlayerUnit = PlayerUnit -- Wrapper.Unit#UNIT PlayerNames = PlayerGroup:GetPlayerNames()
if PlayerUnit and PlayerUnit:IsAlive() then if PlayerNames then
local PlayerName = PlayerUnit:GetPlayerName() PlayerReport:Add( " -- Group " .. PlayerGroup:GetCallsign() .. ": " .. table.concat( PlayerNames, ", " ) )
PlayerNames[#PlayerNames+1] = PlayerName
end end
end end
local PlayerNameText = table.concat( PlayerNames, ", " )
Report:Add( "Task " .. Name .. " - State '" .. State .. "' - Players " .. PlayerNameText )
end
-- Loop each Process in the Task, and find Reporting Details. -- Loop each Process in the Task, and find Reporting Details.
Report:Add( string.format( " - Task %s\n -- State '%s'\n%s", Name, State, PlayerReport:Text() ) )
return Report:Text() return Report:Text()
end end

View File

@@ -1,28 +1,53 @@
--- (AI) (SP) (MP) Tasking for Air to Ground Processes. --- This module contains the TASK_A2G classes.
-- --
-- 1) @{#TASK_A2G} class, extends @{Task#TASK} -- # 1) @{Task_A2G#TASK_A2G} class, extends @{Task#TASK}
-- ================================================= --
-- The @{#TASK_A2G} class defines a CAS or BAI task of a @{Set} of Target Units, -- The @{#TASK_A2G} class defines Air To Ground tasks for a @{Set} of Target Units,
-- located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK}. -- based on the tasking capabilities defined in @{Task#TASK}.
-- The TASK_A2G is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses: -- The TASK_A2G is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
-- --
-- * **None**: Start of the process -- * **None**: Start of the process
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Fsm.Assign#ACT_ASSIGN_ACCEPT} is started to accept the task. -- * **Planned**: The A2G task is planned.
-- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Fsm.Route#ACT_ROUTE} is started to route the active Units in the Group to the attack zone. -- * **Assigned**: The A2G task is assigned to a @{Group#GROUP}.
-- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task. -- * **Success**: The A2G task is successfully completed.
-- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ. -- * **Failed**: The A2G task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
-- # 1) @{Task_A2G#TASK_SEAD} class, extends @{Task_A2G#TASK_A2G}
--
-- The @{#TASK_SEAD} class defines a SEAD task for a @{Set} of Target Units.
--
-- ====
--
-- # **API CHANGE HISTORY**
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
--
-- Hereby the change log:
--
-- 2017-03-09: Revised version.
-- --
-- === -- ===
-- --
-- ### Authors: FlightControl - Design and Programming -- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
-- * **[WingThor]**: Concept, Advice & Testing.
--
-- ### Authors:
--
-- * **FlightControl**: Concept, Design & Programming.
-- --
-- @module Task_A2G -- @module Task_A2G
do -- TASK_A2G do -- TASK_A2G
--- The TASK_A2G class --- The TASK_A2G class
-- @type TASK_A2G -- @type TASK_A2G
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK -- @extends Tasking.Task#TASK
TASK_A2G = { TASK_A2G = {
ClassName = "TASK_A2G", ClassName = "TASK_A2G",
@@ -33,44 +58,123 @@ do -- TASK_A2G
-- @param Tasking.Mission#MISSION Mission -- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task. -- @param #string TaskName The name of the Task.
-- @param #string TaskType BAI or CAS
-- @param Set#SET_UNIT UnitSetTargets -- @param Set#SET_UNIT UnitSetTargets
-- @param Core.Zone#ZONE_BASE TargetZone -- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @return #TASK_A2G self -- @return #TASK_A2G self
function TASK_A2G:New( Mission, SetGroup, TaskName, TaskType, TargetSetUnit, TargetZone, FACUnit ) function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) -- Tasking.Task#TASK_A2G
self:F() self:F()
self.TargetSetUnit = TargetSetUnit self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone self.TaskType = TaskType
self.FACUnit = FACUnit
local A2GUnitProcess = self:GetUnitProcess() Mission:AddTask( self )
A2GUnitProcess:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( "Attack the Area" ), { Assigned = "Route", Rejected = "Eject" } ) local Fsm = self:GetUnitProcess()
A2GUnitProcess:AddProcess ( "Assigned", "Route", ACT_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Update" } )
A2GUnitProcess:AddTransition( "Rejected", "Eject", "Planned" )
A2GUnitProcess:AddTransition( "Arrived", "Update", "Updated" )
A2GUnitProcess:AddProcess ( "Updated", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, "Attack" ), { Accounted = "Success" } )
A2GUnitProcess:AddProcess ( "Updated", "Smoke", ACT_ASSIST_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) )
--Fsm:AddProcess ( "Updated", "JTAC", PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) )
A2GUnitProcess:AddTransition( "Accounted", "Success", "Success" )
A2GUnitProcess:AddTransition( "Failed", "Fail", "Failed" )
function A2GUnitProcess:onenterUpdated( TaskUnit )
self:E( { self } ) Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "RouteToRendezVous", Rejected = "Reject" } )
self:Account()
self:Smoke() Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" )
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } )
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } )
Fsm:AddTransition( { "Arrived", "RoutingToRendezVous" }, "ArriveAtRendezVous", "ArrivedAtRendezVous" )
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "Engage", "Engaging" )
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "HoldAtRendezVous", "HoldingAtRendezVous" )
Fsm:AddProcess ( "Engaging", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, self.TaskType ), { Accounted = "Success" } )
Fsm:AddTransition( "Engaging", "RouteToTarget", "Engaging" )
Fsm:AddProcess( "Engaging", "RouteToTargetZone", ACT_ROUTE_ZONE:New(), {} )
Fsm:AddProcess( "Engaging", "RouteToTargetPoint", ACT_ROUTE_POINT:New(), {} )
Fsm:AddTransition( "Engaging", "RouteToTargets", "Engaging" )
Fsm:AddTransition( "Accounted", "DestroyedAll", "Accounted" )
Fsm:AddTransition( "Accounted", "Success", "Success" )
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
Fsm:AddTransition( "Failed", "Fail", "Failed" )
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_A2G#TASK_A2G Task
function Fsm:onafterRouteToRendezVous( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
-- Determine the first Unit from the self.RendezVousSetUnit
if Task:GetRendezVousZone( TaskUnit ) then
self:__RouteToRendezVousZone( 0.1 )
else
if Task:GetRendezVousPointVec2( TaskUnit ) then
self:__RouteToRendezVousPoint( 0.1 )
else
self:__ArriveAtRendezVous( 0.1 )
end
end
end end
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task#TASK_A2G Task
function Fsm:OnAfterArriveAtRendezVous( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
-- Determine the first Unit from the self.TargetSetUnit
self:__Engage( 0.1 )
end
--_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) --- Test
--_EVENTDISPATCHER:OnDead( self._EventDead, self ) -- @param #FSM_PROCESS self
--_EVENTDISPATCHER:OnCrash( self._EventDead, self ) -- @param Wrapper.Unit#UNIT TaskUnit
--_EVENTDISPATCHER:OnPilotDead( self._EventDead, self ) -- @param Tasking.Task#TASK_A2G Task
function Fsm:onafterEngage( TaskUnit, Task )
self:E( { self } )
self:__Account( 0.1 )
self:__RouteToTarget(0.1 )
self:__RouteToTargets( -10 )
end
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_A2G#TASK_A2G Task
function Fsm:onafterRouteToTarget( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
-- Determine the first Unit from the self.TargetSetUnit
if Task:GetTargetZone( TaskUnit ) then
self:__RouteToTargetZone( 0.1 )
else
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
if TargetUnit then
local PointVec2 = TargetUnit:GetPointVec2()
self:T( { TargetPointVec2 = PointVec2, PointVec2:GetX(), PointVec2:GetAlt(), PointVec2:GetZ() } )
Task:SetTargetPointVec2( TargetUnit:GetPointVec2(), TaskUnit )
end
self:__RouteToTargetPoint( 0.1 )
end
end
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_A2G#TASK_A2G Task
function Fsm:onafterRouteToTargets( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
if TargetUnit then
Task:SetTargetPointVec2( TargetUnit:GetPointVec2(), TaskUnit )
end
self:__RouteToTargets( -10 )
end
return self return self
end end
--- @param #TASK_A2G self --- @param #TASK_A2G self
@@ -78,7 +182,188 @@ do -- TASK_A2G
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end end
--- @param #TASK_A2G self
-- @param Core.Point#POINT_VEC2 RendezVousPointVec2 The PointVec2 object referencing to the 2D point where the RendezVous point is located on the map.
-- @param #number RendezVousRange The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2G:SetRendezVousPointVec2( RendezVousPointVec2, RendezVousRange, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
ActRouteRendezVous:SetPointVec2( RendezVousPointVec2 )
ActRouteRendezVous:SetRange( RendezVousRange )
end
--- @param #TASK_A2G self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Point#POINT_VEC2 The PointVec2 object referencing to the 2D point where the RendezVous point is located on the map.
-- @return #number The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
function TASK_A2G:GetRendezVousPointVec2( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
return ActRouteRendezVous:GetPointVec2(), ActRouteRendezVous:GetRange()
end end
--- @param #TASK_A2G self
-- @param Core.Zone#ZONE_BASE RendezVousZone The Zone object where the RendezVous is located on the map.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2G:SetRendezVousZone( RendezVousZone, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
ActRouteRendezVous:SetZone( RendezVousZone )
end
--- @param #TASK_A2G self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Zone#ZONE_BASE The Zone object where the RendezVous is located on the map.
function TASK_A2G:GetRendezVousZone( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
return ActRouteRendezVous:GetZone()
end
--- @param #TASK_A2G self
-- @param Core.Point#POINT_VEC2 TargetPointVec2 The PointVec2 object where the Target is located on the map.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2G:SetTargetPointVec2( TargetPointVec2, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
ActRouteTarget:SetPointVec2( TargetPointVec2 )
end
--- @param #TASK_A2G self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Point#POINT_VEC2 The PointVec2 object where the Target is located on the map.
function TASK_A2G:GetTargetPointVec2( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
return ActRouteTarget:GetPointVec2()
end
--- @param #TASK_A2G self
-- @param Core.Zone#ZONE_BASE TargetZone The Zone object where the Target is located on the map.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2G:SetTargetZone( TargetZone, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
ActRouteTarget:SetZone( TargetZone )
end
--- @param #TASK_A2G self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Zone#ZONE_BASE The Zone object where the Target is located on the map.
function TASK_A2G:GetTargetZone( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
return ActRouteTarget:GetZone()
end
end
do -- TASK_SEAD
--- The TASK_SEAD class
-- @type TASK_SEAD
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK
TASK_SEAD = {
ClassName = "TASK_SEAD",
}
--- Instantiates a new TASK_SEAD.
-- @param #TASK_SEAD self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets
-- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @return #TASK_SEAD self
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD" ) ) -- #TASK_SEAD
self:F()
return self
end
end
do -- TASK_BAI
--- The TASK_BAI class
-- @type TASK_BAI
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK
TASK_BAI = {
ClassName = "TASK_BAI",
}
--- Instantiates a new TASK_BAI.
-- @param #TASK_BAI self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets
-- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @return #TASK_BAI self
function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI" ) ) -- #TASK_BAI
self:F()
return self
end
end
do -- TASK_CAS
--- The TASK_CAS class
-- @type TASK_CAS
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK
TASK_CAS = {
ClassName = "TASK_CAS",
}
--- Instantiates a new TASK_CAS.
-- @param #TASK_CAS self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets
-- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @return #TASK_CAS self
function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS" ) ) -- #TASK_CAS
self:F()
return self
end
end

View File

@@ -0,0 +1,286 @@
--- **Tasking** - The TASK_A2G_DISPATCHER creates and manages player TASK_A2G tasks based on detected targets.
--
-- ===
--
-- # 1) @{#TASK_A2G_DISPATCHER} class, extends @{#DETECTION_MANAGER}
--
-- The @{#TASK_A2G_DISPATCHER} class implements the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of FAC (groups).
-- The FAC will detect units, will group them, and will dispatch @{Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
-- Find a summary below describing for which situation a task type is created:
--
-- * **CAS Task**: Is created when there are enemy ground units within range of the FAC, while there are friendly units in the FAC perimeter.
-- * **BAI Task**: Is created when there are enemy ground units within range of the FAC, while there are NO other friendly units within the FAC perimeter.
-- * **SEAD Task**: Is created when there are enemy ground units wihtin range of the FAC, with air search radars.
--
-- Other task types will follow...
--
-- 3.1) TASK_A2G_DISPATCHER constructor:
-- --------------------------------------
-- The @{#TASK_A2G_DISPATCHER.New}() method creates a new TASK_A2G_DISPATCHER instance.
--
-- ===
--
-- # **API CHANGE HISTORY**
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
--
-- Hereby the change log:
--
-- 2017-03-09: Initial class and API.
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
-- ### Authors:
--
-- * **FlightControl**: Concept, Design & Programming.
--
-- @module Task_A2G_Dispatcher
do -- TASK_A2G_DISPATCHER
--- TASK_A2G_DISPATCHER class.
-- @type TASK_A2G_DISPATCHER
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @field Tasking.Mission#MISSION Mission
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
TASK_A2G_DISPATCHER = {
ClassName = "TASK_A2G_DISPATCHER",
Mission = nil,
Detection = nil,
}
--- TASK_A2G_DISPATCHER constructor.
-- @param #TASK_A2G_DISPATCHER self
-- @param Tasking.Mission#MISSION The mission for which the task dispatching is done.
-- @param Set#SET_GROUP SetGroup The set of groups that can join the tasks within the mission.
-- @param Functional.Detection#DETECTION_BASE Detection The detection results that are used to dynamically assign new tasks to human players.
-- @return #TASK_A2G_DISPATCHER self
function TASK_A2G_DISPATCHER:New( Mission, SetGroup, Detection )
-- Inherits from DETECTION_MANAGER
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #TASK_A2G_DISPATCHER
self.Detection = Detection
self.Mission = Mission
self:Schedule( 30 )
return self
end
--- Creates a SEAD task when there are targets for it.
-- @param #TASK_A2G_DISPATCHER self
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
-- @return #nil If there are no targets to be set.
function TASK_A2G_DISPATCHER:EvaluateSEAD( DetectedItem )
self:F( { DetectedItem.ItemID } )
local DetectedSet = DetectedItem.Set
local DetectedZone = DetectedItem.Zone
-- Determine if the set has radar targets. If it does, construct a SEAD task.
local RadarCount = DetectedSet:HasSEAD()
if RadarCount > 0 then
-- Here we're doing something advanced... We're copying the DetectedSet, but making a new Set only with SEADable Radar units in it.
local TargetSetUnit = SET_UNIT:New()
TargetSetUnit:SetDatabase( DetectedSet )
TargetSetUnit:FilterHasSEAD()
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
return TargetSetUnit
end
return nil
end
--- Creates a CAS task when there are targets for it.
-- @param #TASK_A2G_DISPATCHER self
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
-- @return Tasking.Task#TASK
function TASK_A2G_DISPATCHER:EvaluateCAS( DetectedItem )
self:F( { DetectedItem.ItemID } )
local DetectedSet = DetectedItem.Set
local DetectedZone = DetectedItem.Zone
-- Determine if the set has radar targets. If it does, construct a SEAD task.
local GroundUnitCount = DetectedSet:HasGroundUnits()
local FriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedItem )
if GroundUnitCount > 0 and FriendliesNearBy == true then
-- Copy the Set
local TargetSetUnit = SET_UNIT:New()
TargetSetUnit:SetDatabase( DetectedSet )
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
return TargetSetUnit
end
return nil
end
--- Creates a BAI task when there are targets for it.
-- @param #TASK_A2G_DISPATCHER self
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
-- @return Tasking.Task#TASK
function TASK_A2G_DISPATCHER:EvaluateBAI( DetectedItem, FriendlyCoalition )
self:F( { DetectedItem.ItemID } )
local DetectedSet = DetectedItem.Set
local DetectedZone = DetectedItem.Zone
-- Determine if the set has radar targets. If it does, construct a SEAD task.
local GroundUnitCount = DetectedSet:HasGroundUnits()
local FriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedItem )
if GroundUnitCount > 0 and FriendliesNearBy == false then
-- Copy the Set
local TargetSetUnit = SET_UNIT:New()
TargetSetUnit:SetDatabase( DetectedSet )
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
return TargetSetUnit
end
return nil
end
--- Evaluates the removal of the Task from the Mission.
-- Can only occur when the DetectedItem is Changed AND the state of the Task is "Planned".
-- @param #TASK_A2G_DISPATCHER self
-- @param Tasking.Mission#MISSION Mission
-- @param Tasking.Task#TASK Task
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
-- @return Tasking.Task#TASK
function TASK_A2G_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedItem )
if Task then
if Task:IsStatePlanned() and DetectedItem.Changed == true then
self:E( "Removing Tasking: " .. Task:GetTaskName() )
Task = Mission:RemoveTask( Task )
end
end
return Task
end
--- Assigns tasks in relation to the detected items to the @{Set#SET_GROUP}.
-- @param #TASK_A2G_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Detection#DETECTION_BASE} derived object.
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
function TASK_A2G_DISPATCHER:ProcessDetected( Detection )
self:F2()
local AreaMsg = {}
local TaskMsg = {}
local ChangeMsg = {}
local Mission = self.Mission
local ReportSEAD = REPORT:New( " - SEAD Tasks:")
local ReportCAS = REPORT:New( " - CAS Tasks:")
local ReportBAI = REPORT:New( " - BAI Tasks:")
local ReportChanges = REPORT:New( " - Changes:" )
--- First we need to the detected targets.
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
local DetectedSet = DetectedItem.Set -- Functional.Detection#DETECTION_BASE.DetectedSet
local DetectedZone = DetectedItem.Zone
self:E( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
DetectedSet:Flush()
local ItemID = DetectedItem.ItemID
-- Evaluate SEAD Tasking
local SEADTask = Mission:GetTask( string.format( "SEAD.%03d", ItemID ) )
SEADTask = self:EvaluateRemoveTask( Mission, SEADTask, DetectedItem )
if not SEADTask then
local TargetSetUnit = self:EvaluateSEAD( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_SEAD:New( Mission, self.SetGroup, string.format( "SEAD.%03d", ItemID ), TargetSetUnit )
Task:SetTargetZone( DetectedZone )
SEADTask = Mission:AddTask( Task )
end
end
if SEADTask and SEADTask:IsStatePlanned() then
ReportSEAD:Add( string.format( " - %s.%02d - %s", "SEAD", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
end
-- Evaluate CAS Tasking
local CASTask = Mission:GetTask( string.format( "CAS.%03d", ItemID ) )
CASTask = self:EvaluateRemoveTask( Mission, CASTask, DetectedItem )
if not CASTask then
local TargetSetUnit = self:EvaluateCAS( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_CAS:New( Mission, self.SetGroup, string.format( "CAS.%03d", ItemID ), TargetSetUnit )
--Task:SetTargetZone( DetectedZone )
CASTask = Mission:AddTask( Task )
end
end
if CASTask and CASTask:IsStatePlanned() then
ReportCAS:Add( string.format( " - %s.%02d - %s", "CAS", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
end
-- Evaluate BAI Tasking
local BAITask = Mission:GetTask( string.format( "BAI.%03d", ItemID ) )
BAITask = self:EvaluateRemoveTask( Mission, BAITask, DetectedItem )
if not BAITask then
local TargetSetUnit = self:EvaluateBAI( DetectedItem, self.Mission:GetCommandCenter():GetPositionable():GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_BAI:New( Mission, self.SetGroup, string.format( "BAI.%03d", ItemID ), TargetSetUnit )
Task:SetTargetZone( DetectedZone )
BAITask = Mission:AddTask( Task )
end
end
if BAITask and BAITask:IsStatePlanned() then
ReportBAI:Add( string.format( " - %s.%02d - %s", "BAI", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
end
-- Loop through the changes ...
local ChangeText = Detection:GetChangeText( DetectedItem )
ReportChanges:Add( ChangeText )
-- OK, so the tasking has been done, now delete the changes reported for the area.
Detection:AcceptChanges( DetectedItem )
end
-- TODO set menus using the HQ coordinator
Mission:GetCommandCenter():SetMenu()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
Mission:GetCommandCenter():MessageToGroup(
string.format( "HQ Reporting - Planned tasks for mission '%s':\n%s\n",
self.Mission:GetName(),
string.format( "%s\n%s\n%s\n%s", ReportSEAD:Text(), ReportCAS:Text(), ReportBAI:Text(), ReportChanges:Text()
)
), TaskGroup
)
end
end
return true
end
end

View File

@@ -41,11 +41,6 @@ do -- TASK_PICKUP
local self = BASE:Inherit( self, TASK:New( Mission, AssignedSetGroup, TaskName, TaskType, "PICKUP" ) ) local self = BASE:Inherit( self, TASK:New( Mission, AssignedSetGroup, TaskName, TaskType, "PICKUP" ) )
self:F() self:F()
_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
_EVENTDISPATCHER:OnDead( self._EventDead, self )
_EVENTDISPATCHER:OnCrash( self._EventDead, self )
_EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
return self return self
end end

View File

@@ -1,78 +0,0 @@
--- This module contains the TASK_SEAD classes.
--
-- 1) @{#TASK_SEAD} class, extends @{Task#TASK}
-- =================================================
-- The @{#TASK_SEAD} class defines a SEAD task for a @{Set} of Target Units, located at a Target Zone,
-- based on the tasking capabilities defined in @{Task#TASK}.
-- The TASK_SEAD is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
--
-- * **None**: Start of the process
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Fsm.Assign#ACT_ASSIGN_ACCEPT} is started to accept the task.
-- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Fsm.Route#ACT_ROUTE} is started to route the active Units in the Group to the attack zone.
-- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task.
-- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
-- ===
--
-- ### Authors: FlightControl - Design and Programming
--
-- @module Task_SEAD
do -- TASK_SEAD
--- The TASK_SEAD class
-- @type TASK_SEAD
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK
TASK_SEAD = {
ClassName = "TASK_SEAD",
}
--- Instantiates a new TASK_SEAD.
-- @param #TASK_SEAD self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets
-- @param Core.Zone#ZONE_BASE TargetZone
-- @return #TASK_SEAD self
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, "SEAD" ) ) -- Tasking.Task_SEAD#TASK_SEAD
self:F()
self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone
local Fsm = self:GetUnitProcess()
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "Route", Rejected = "Eject" } )
Fsm:AddProcess ( "Assigned", "Route", ACT_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Update" } )
Fsm:AddTransition( "Rejected", "Eject", "Planned" )
Fsm:AddTransition( "Arrived", "Update", "Updated" )
Fsm:AddProcess ( "Updated", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, "SEAD" ), { Accounted = "Success" } )
Fsm:AddProcess ( "Updated", "Smoke", ACT_ASSIST_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) )
Fsm:AddTransition( "Accounted", "Success", "Success" )
Fsm:AddTransition( "Failed", "Fail", "Failed" )
function Fsm:onenterUpdated( TaskUnit )
self:E( { self } )
self:Account()
self:Smoke()
end
-- _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
-- _EVENTDISPATCHER:OnDead( self._EventDead, self )
-- _EVENTDISPATCHER:OnCrash( self._EventDead, self )
-- _EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
return self
end
--- @param #TASK_SEAD self
function TASK_SEAD:GetPlannedMenuText()
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end
end

View File

@@ -30,7 +30,7 @@
-- --
-- Find below a list of the **assigned task** methods: -- Find below a list of the **assigned task** methods:
-- --
-- * @{#CONTROLLABLE.TaskAttackControllable}: (AIR) Attack a Controllable. -- * @{#CONTROLLABLE.TaskAttackGroup}: (AIR) Attack a Controllable.
-- * @{#CONTROLLABLE.TaskAttackMapObject}: (AIR) Attacking the map object (building, structure, e.t.c). -- * @{#CONTROLLABLE.TaskAttackMapObject}: (AIR) Attacking the map object (building, structure, e.t.c).
-- * @{#CONTROLLABLE.TaskAttackUnit}: (AIR) Attack the Unit. -- * @{#CONTROLLABLE.TaskAttackUnit}: (AIR) Attack the Unit.
-- * @{#CONTROLLABLE.TaskBombing}: (AIR) Delivering weapon at the point on the ground. -- * @{#CONTROLLABLE.TaskBombing}: (AIR) Delivering weapon at the point on the ground.
@@ -38,7 +38,7 @@
-- * @{#CONTROLLABLE.TaskEmbarking}: (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable. -- * @{#CONTROLLABLE.TaskEmbarking}: (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable.
-- * @{#CONTROLLABLE.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location. -- * @{#CONTROLLABLE.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location.
-- * @{#CONTROLLABLE.TaskEscort}: (AIR) Escort another airborne controllable. -- * @{#CONTROLLABLE.TaskEscort}: (AIR) Escort another airborne controllable.
-- * @{#CONTROLLABLE.TaskFAC_AttackControllable}: (AIR + GROUND) The task makes the controllable/unit a FAC and orders the FAC to control the target (enemy ground controllable) destruction. -- * @{#CONTROLLABLE.TaskFAC_AttackGroup}: (AIR + GROUND) The task makes the controllable/unit a FAC and orders the FAC to control the target (enemy ground controllable) destruction.
-- * @{#CONTROLLABLE.TaskFireAtPoint}: (GROUND) Fire some or all ammunition at a VEC2 point. -- * @{#CONTROLLABLE.TaskFireAtPoint}: (GROUND) Fire some or all ammunition at a VEC2 point.
-- * @{#CONTROLLABLE.TaskFollow}: (AIR) Following another airborne controllable. -- * @{#CONTROLLABLE.TaskFollow}: (AIR) Following another airborne controllable.
-- * @{#CONTROLLABLE.TaskHold}: (GROUND) Hold ground controllable from moving. -- * @{#CONTROLLABLE.TaskHold}: (GROUND) Hold ground controllable from moving.
@@ -222,6 +222,24 @@ end
-- Tasks -- Tasks
--- Clear all tasks from the controllable.
-- @param #CONTROLLABLE self
-- @return #CONTROLLABLE
function CONTROLLABLE:ClearTasks()
self:F2()
local DCSControllable = self:GetDCSObject()
if DCSControllable then
local Controller = self:_GetController()
Controller:resetTask()
return self
end
return nil
end
--- Popping current Task from the controllable. --- Popping current Task from the controllable.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @return Wrapper.Controllable#CONTROLLABLE self -- @return Wrapper.Controllable#CONTROLLABLE self
@@ -469,13 +487,13 @@ end
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude. -- @param Dcs.DCSTypes#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude.
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackControllable" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. -- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure. -- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit )
self:F2( { self.ControllableName, AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) self:F2( { self.ControllableName, AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } )
-- AttackControllable = { -- AttackGroup = {
-- id = 'AttackControllable', -- id = 'AttackGroup',
-- params = { -- params = {
-- groupId = Group.ID, -- groupId = Group.ID,
-- weaponType = number, -- weaponType = number,
@@ -500,7 +518,7 @@ function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, At
end end
local DCSTask local DCSTask
DCSTask = { id = 'AttackControllable', DCSTask = { id = 'AttackGroup',
params = { params = {
groupId = AttackGroup:GetID(), groupId = AttackGroup:GetID(),
weaponType = WeaponType, weaponType = WeaponType,
@@ -518,48 +536,34 @@ function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, At
return DCSTask return DCSTask
end end
--- (AIR) Attack the Unit. --- (AIR) Attack the Unit.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param Wrapper.Unit#UNIT AttackUnit The unit. -- @param Wrapper.Unit#UNIT AttackUnit The UNIT.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. -- @param #boolean GroupAttack (optional) If true, all units in the group will attack the Unit when found.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. -- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackControllable" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. -- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft. -- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure. -- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, ControllableAttack ) function CONTROLLABLE:TaskAttackUnit( AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack )
self:F2( { self.ControllableName, AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, ControllableAttack } ) self:F2( { self.ControllableName, AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack } )
-- AttackUnit = {
-- id = 'AttackUnit',
-- params = {
-- unitId = Unit.ID,
-- weaponType = number,
-- expend = enum AI.Task.WeaponExpend
-- attackQty = number,
-- direction = Azimuth,
-- attackQtyLimit = boolean,
-- controllableAttack = boolean,
-- }
-- }
local DCSTask local DCSTask
DCSTask = { DCSTask = {
id = 'AttackUnit', id = 'AttackUnit',
params = { params = {
altitudeEnabled = true,
unitId = AttackUnit:GetID(), unitId = AttackUnit:GetID(),
attackQtyLimit = AttackQtyLimit or false, groupAttack = GroupAttack or false,
attackQty = AttackQty or 2, visible = Visible or false,
expend = WeaponExpend or "Auto", expend = WeaponExpend or "Auto",
altitude = 2000, directionEnabled = Direction and true or false,
directionEnabled = true, direction = Direction,
groupAttack = true, altitudeEnabled = Altitude and true or false,
--weaponType = WeaponType or 1073741822, altitude = Altitude or 30,
direction = Direction or 0, attackQtyLimit = AttackQty and true or false,
} attackQty = AttackQty,
},
} }
self:E( DCSTask ) self:E( DCSTask )
@@ -573,7 +577,7 @@ end
-- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point to deliver weapon at. -- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point to deliver weapon at.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. -- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. -- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) Desired quantity of passes. The parameter is not the same in AttackControllable and AttackUnit tasks. -- @param #number AttackQty (optional) Desired quantity of passes. The parameter is not the same in AttackGroup and AttackUnit tasks.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft. -- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure. -- @return Dcs.DCSTasking.Task#Task The DCS task structure.
@@ -1018,8 +1022,8 @@ end
function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink ) function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink )
self:F2( { self.ControllableName, AttackGroup, WeaponType, Designation, Datalink } ) self:F2( { self.ControllableName, AttackGroup, WeaponType, Designation, Datalink } )
-- FAC_AttackControllable = { -- FAC_AttackGroup = {
-- id = 'FAC_AttackControllable', -- id = 'FAC_AttackGroup',
-- params = { -- params = {
-- groupId = Group.ID, -- groupId = Group.ID,
-- weaponType = number, -- weaponType = number,
@@ -1029,7 +1033,7 @@ function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation,
-- } -- }
local DCSTask local DCSTask
DCSTask = { id = 'FAC_AttackControllable', DCSTask = { id = 'FAC_AttackGroup',
params = { params = {
groupId = AttackGroup:GetID(), groupId = AttackGroup:GetID(),
weaponType = WeaponType, weaponType = WeaponType,
@@ -1121,7 +1125,7 @@ end
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude. -- @param Dcs.DCSTypes#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude.
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackControllable" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. -- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure. -- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit )
self:F2( { self.ControllableName, AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) self:F2( { self.ControllableName, AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } )
@@ -1173,7 +1177,7 @@ function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType,
end end
--- (AIR) Attack the Unit. --- (AIR) Search and attack the Unit.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param Wrapper.Unit#UNIT EngageUnit The UNIT. -- @param Wrapper.Unit#UNIT EngageUnit The UNIT.
-- @param #number Priority (optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. -- @param #number Priority (optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
@@ -1454,7 +1458,7 @@ end
-- @param Dcs.DCSTypes#Vec3 Point The destination point in Vec3 format. -- @param Dcs.DCSTypes#Vec3 Point The destination point in Vec3 format.
-- @param #number Speed The speed to travel. -- @param #number Speed The speed to travel.
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:TaskRouteToVec2( Point, Speed ) function CONTROLLABLE:RouteToVec2( Point, Speed )
self:F2( { Point, Speed } ) self:F2( { Point, Speed } )
local ControllablePoint = self:GetUnit( 1 ):GetVec2() local ControllablePoint = self:GetUnit( 1 ):GetVec2()
@@ -1505,7 +1509,7 @@ end
-- @param Dcs.DCSTypes#Vec3 Point The destination point in Vec3 format. -- @param Dcs.DCSTypes#Vec3 Point The destination point in Vec3 format.
-- @param #number Speed The speed to travel. -- @param #number Speed The speed to travel.
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:TaskRouteToVec3( Point, Speed ) function CONTROLLABLE:RouteToVec3( Point, Speed )
self:F2( { Point, Speed } ) self:F2( { Point, Speed } )
local ControllableVec3 = self:GetUnit( 1 ):GetVec3() local ControllableVec3 = self:GetUnit( 1 ):GetVec3()
@@ -1602,7 +1606,7 @@ function CONTROLLABLE:TaskRouteToZone( Zone, Randomize, Speed, Formation )
PointFrom.x = ControllablePoint.x PointFrom.x = ControllablePoint.x
PointFrom.y = ControllablePoint.y PointFrom.y = ControllablePoint.y
PointFrom.type = "Turning Point" PointFrom.type = "Turning Point"
PointFrom.action = "Cone" PointFrom.action = Formation or "Cone"
PointFrom.speed = 20 / 1.6 PointFrom.speed = 20 / 1.6

View File

@@ -76,6 +76,9 @@
-- --
-- Hereby the change log: -- Hereby the change log:
-- --
-- 2017-03-07: GROUP:**HandleEvent( Event, EventFunction )** added.
-- 2017-03-07: GROUP:**UnHandleEvent( Event )** added.
--
-- 2017-01-24: GROUP:**SetAIOnOff( AIOnOff )** added. -- 2017-01-24: GROUP:**SetAIOnOff( AIOnOff )** added.
-- --
-- 2017-01-24: GROUP:**SetAIOn()** added. -- 2017-01-24: GROUP:**SetAIOn()** added.
@@ -110,7 +113,7 @@ GROUP = {
-- @param Dcs.DCSWrapper.Group#Group GroupName The DCS Group name -- @param Dcs.DCSWrapper.Group#Group GroupName The DCS Group name
-- @return #GROUP self -- @return #GROUP self
function GROUP:Register( GroupName ) function GROUP:Register( GroupName )
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) )
self:F2( GroupName ) self:F2( GroupName )
self.GroupName = GroupName self.GroupName = GroupName
@@ -228,7 +231,7 @@ function GROUP:GetCategory()
return nil return nil
end end
--- Returns the category name of the DCS Group. --- Returns the category name of the #GROUP.
-- @param #GROUP self -- @param #GROUP self
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship -- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
function GROUP:GetCategoryName() function GROUP:GetCategoryName()
@@ -897,4 +900,55 @@ function GROUP:OnReSpawn( ReSpawnFunction )
self.ReSpawnFunction = ReSpawnFunction self.ReSpawnFunction = ReSpawnFunction
end end
do -- Event Handling
--- Subscribe to a DCS Event.
-- @param #GROUP self
-- @param Core.Event#EVENTS Event
-- @param #function EventFunction (optional) The function to be called when the event occurs for the GROUP.
-- @return #GROUP
function GROUP:HandleEvent( Event, EventFunction )
self:EventDispatcher():OnEventForGroup( self:GetName(), EventFunction, self, Event )
return self
end
--- UnSubscribe to a DCS event.
-- @param #GROUP self
-- @param Core.Event#EVENTS Event
-- @return #GROUP
function GROUP:UnHandleEvent( Event )
self:EventDispatcher():RemoveForGroup( self:GetName(), self, Event )
return self
end
end
do -- Players
--- Get player names
-- @param #GROUP self
-- @return #table The group has players, an array of player names is returned.
-- @return #nil The group has no players
function GROUP:GetPlayerNames()
local PlayerNames = nil
local Units = self:GetUnits()
for UnitID, UnitData in pairs( Units ) do
local Unit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = Unit:GetPlayerName()
if PlayerName and PlayerName ~= "" then
PlayerNames = PlayerNames or {}
table.insert( PlayerNames, PlayerName )
end
end
self:F( PlayerNames )
return PlayerNames
end
end

View File

@@ -48,19 +48,24 @@ STATIC = {
-- As an optional parameter, a briefing text can be given also. -- As an optional parameter, a briefing text can be given also.
-- @param #STATIC self -- @param #STATIC self
-- @param #string StaticName Name of the DCS **Static** as defined within the Mission Editor. -- @param #string StaticName Name of the DCS **Static** as defined within the Mission Editor.
-- @param #boolean RaiseError Raise an error if not found.
-- @return #STATIC -- @return #STATIC
function STATIC:FindByName( StaticName ) function STATIC:FindByName( StaticName, RaiseError )
local StaticFound = _DATABASE:FindStatic( StaticName ) local StaticFound = _DATABASE:FindStatic( StaticName )
self.StaticName = StaticName self.StaticName = StaticName
if StaticFound then if StaticFound then
StaticFound:F( { StaticName } ) StaticFound:F3( { StaticName } )
return StaticFound return StaticFound
end end
if RaiseError == nil or RaiseError == true then
error( "STATIC not found for: " .. StaticName ) error( "STATIC not found for: " .. StaticName )
end
return nil
end end
function STATIC:Register( StaticName ) function STATIC:Register( StaticName )

View File

@@ -522,6 +522,31 @@ function UNIT:GetLife0()
return nil return nil
end end
--- Returns the category name of the #UNIT.
-- @param #UNIT self
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
function UNIT:GetCategoryName()
self:F3( self.UnitName )
local DCSUnit = self:GetDCSObject()
if DCSUnit then
local CategoryNames = {
[Unit.Category.AIRPLANE] = "Airplane",
[Unit.Category.HELICOPTER] = "Helicopter",
[Unit.Category.GROUND_UNIT] = "Ground Unit",
[Unit.Category.SHIP] = "Ship",
[Unit.Category.STRUCTURE] = "Structure",
}
local UnitCategory = DCSUnit:getDesc().category
self:T3( UnitCategory )
return CategoryNames[UnitCategory]
end
return nil
end
--- Returns the Unit's A2G threat level on a scale from 1 to 10 ... --- Returns the Unit's A2G threat level on a scale from 1 to 10 ...
-- The following threat levels are foreseen: -- The following threat levels are foreseen:
-- --
@@ -540,14 +565,14 @@ end
function UNIT:GetThreatLevel() function UNIT:GetThreatLevel()
local Attributes = self:GetDesc().attributes local Attributes = self:GetDesc().attributes
self:E( Attributes ) self:T( Attributes )
local ThreatLevel = 0 local ThreatLevel = 0
local ThreatText = "" local ThreatText = ""
if self:IsGround() then if self:IsGround() then
self:E( "Ground" ) self:T( "Ground" )
local ThreatLevels = { local ThreatLevels = {
"Unarmed", "Unarmed",
@@ -585,7 +610,7 @@ function UNIT:GetThreatLevel()
if self:IsAir() then if self:IsAir() then
self:E( "Air" ) self:T( "Air" )
local ThreatLevels = { local ThreatLevels = {
"Unarmed", "Unarmed",
@@ -619,7 +644,7 @@ function UNIT:GetThreatLevel()
if self:IsShip() then if self:IsShip() then
self:E( "Ship" ) self:T( "Ship" )
--["Aircraft Carriers"] = {"Heavy armed ships",}, --["Aircraft Carriers"] = {"Heavy armed ships",},
--["Cruisers"] = {"Heavy armed ships",}, --["Cruisers"] = {"Heavy armed ships",},

View File

@@ -1,4 +1,4 @@
2017-02-08 2017-02-18
- Reworked some vector functions. - Reworked some vector functions.
-- POINT_VEC3:NewFromVec2( Vec2, LandHeightAdd ) added. -- POINT_VEC3:NewFromVec2( Vec2, LandHeightAdd ) added.
@@ -7,7 +7,11 @@
-- ZONE_POLYGON_BASE:GetRandomPointVec2() added. -- ZONE_POLYGON_BASE:GetRandomPointVec2() added.
-- ZONE_POLYGON_BASE:GetRandomPointVec3() added. -- ZONE_POLYGON_BASE:GetRandomPointVec3() added.
2017-02-17
- Added ACT_ROUTE_POINT
-- Routes a controllable to a point with a defined distance.
-- Upon arrived within the engagement distance, an arrival text is shown.
2016-12-06 2016-12-06

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

0
Moose Logo/logo.txt Normal file
View File

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -97,7 +97,7 @@ COPY /b Moose.lua + %1\Tasking\CommandCenter.lua Moose.lua
COPY /b Moose.lua + %1\Tasking\Mission.lua Moose.lua COPY /b Moose.lua + %1\Tasking\Mission.lua Moose.lua
COPY /b Moose.lua + %1\Tasking\Task.lua Moose.lua COPY /b Moose.lua + %1\Tasking\Task.lua Moose.lua
COPY /b Moose.lua + %1\Tasking\DetectionManager.lua Moose.lua COPY /b Moose.lua + %1\Tasking\DetectionManager.lua Moose.lua
COPY /b Moose.lua + %1\Tasking\Task_SEAD.lua Moose.lua COPY /b Moose.lua + %1\Tasking\Task_A2G_Dispatcher.lua Moose.lua
COPY /b Moose.lua + %1\Tasking\Task_A2G.lua Moose.lua COPY /b Moose.lua + %1\Tasking\Task_A2G.lua Moose.lua
COPY /b Moose.lua + %1\Moose.lua Moose.lua COPY /b Moose.lua + %1\Moose.lua Moose.lua

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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