diff --git a/Moose Development/Moose/AI/AI_A2A.lua b/Moose Development/Moose/AI/AI_A2A.lua index aee68be5c..1309b52bc 100644 --- a/Moose Development/Moose/AI/AI_A2A.lua +++ b/Moose Development/Moose/AI/AI_A2A.lua @@ -1,14 +1,12 @@ ---- **AI** -- **AI A2A Air Patrolling or Staging.** +--- **AI** -- (R2.2) - Models the process of air operations for airplanes. -- --- ==== +-- This is a class used in the @{AI_A2A_Dispatcher}. -- --- ### Author: **Sven Van de Velde (FlightControl)** --- ### Contributions: +-- === -- --- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) --- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Testing and API concept review. +-- ### Author: **FlightControl** -- --- ==== +-- === -- -- @module AI_A2A diff --git a/Moose Development/Moose/AI/AI_A2A_Cap.lua b/Moose Development/Moose/AI/AI_A2A_Cap.lua index a38ac5b58..9b90b489e 100644 --- a/Moose Development/Moose/AI/AI_A2A_Cap.lua +++ b/Moose Development/Moose/AI/AI_A2A_Cap.lua @@ -1,28 +1,12 @@ ---- **AI** -- **Execute Combat Air Patrol (CAP).** +--- **AI** -- (R2.2) - Models the process of Combat Air Patrol (CAP) for airplanes. +-- +-- This is a class used in the @{AI_A2A_Dispatcher}. -- --- ![Banner Image](..\Presentations\AI_CAP\Dia1.JPG) --- -- === -- --- AI CAP classes makes AI Groups execute a Combat Air Patrol. +-- ### Author: **FlightControl** -- --- There are the following types of CAP classes defined: --- --- * @{#AI_A2A_CAP}: Perform a CAP in a zone. --- --- ==== --- --- ### Author: **Sven Van de Velde (FlightControl)** --- --- ### Contributions: --- --- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. --- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. --- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. --- * **[Whisper](http://forums.eagle.ru/member.php?u=3829): Testing. --- * **[Delta99](https://forums.eagle.ru/member.php?u=125166): Testing. --- --- ==== +-- === -- -- @module AI_A2A_Cap diff --git a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua index f5875f571..39e81634a 100644 --- a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua @@ -1,8 +1,10 @@ ---- **AI** - The AI_A2A_DISPATCHER creates an automatic A2A defense system based on an EWR network targets and coordinating CAP and GCI. +--- **AI** - (R2.2) - Manages the process of an automatic A2A defense system based on an EWR network targets and coordinating CAP and GCI. +-- +-- === -- -- ![Banner Image](..\Presentations\AI_A2A_DISPATCHER\Dia1.JPG) -- --- ==== +-- === -- -- # QUICK START GUIDE -- @@ -150,7 +152,7 @@ -- -- === -- --- ### Authors: **Sven Van de Velde (FlightControl)** rework of GCICAP + introduction of new concepts (squadrons). +-- ### Authors: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons). -- ### Authors: **Stonehouse**, **SNAFU** in terms of the advice, documentation, and the original GCICAP script. -- -- @module AI_A2A_Dispatcher @@ -169,13 +171,13 @@ do -- AI_A2A_DISPATCHER -- -- The @{#AI_A2A_DISPATCHER} class is designed to create an automatic air defence system for a coalition. -- - -- ==== + -- === -- -- # Demo Missions -- -- ### [AI\_A2A\_DISPATCHER Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/release-2-2-pre/AID%20-%20AI%20Dispatching) -- - -- ==== + -- === -- -- # YouTube Channel -- @@ -3178,7 +3180,7 @@ do -- The AI_A2A_GCICAP class is designed to create an automatic air defence system for a coalition setting up GCI and CAP air defenses. -- The class derives from @{AI#AI_A2A_DISPATCHER} and thus, all the methods that are defined in the @{AI#AI_A2A_DISPATCHER} class, can be used also in AI\_A2A\_GCICAP. -- - -- ==== + -- === -- -- # Demo Missions -- @@ -3188,7 +3190,7 @@ do -- -- ### [AI\_A2A\_GCICAP for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching) -- - -- ==== + -- === -- -- # YouTube Channel -- @@ -3218,7 +3220,7 @@ do -- -- In short it is a plug in very flexible and configurable air defence module for DCS World. -- - -- ==== + -- === -- -- # The following actions need to be followed when using AI\_A2A\_GCICAP in your mission: -- diff --git a/Moose Development/Moose/AI/AI_A2A_Gci.lua b/Moose Development/Moose/AI/AI_A2A_Gci.lua index ac868630f..e714fcfe6 100644 --- a/Moose Development/Moose/AI/AI_A2A_Gci.lua +++ b/Moose Development/Moose/AI/AI_A2A_Gci.lua @@ -1,28 +1,16 @@ ---- **AI** -- **Execute Ground Controlled Interception (GCI).** +--- **AI** -- (R2.2) - Models the process of Ground Controlled Interception (GCI) for airplanes. -- --- ![Banner Image](..\Presentations\AI_GCI\Dia1.JPG) +-- This is a class used in the @{AI_A2A_Dispatcher}. -- -- === -- --- AI A2A_INTEREPT class makes AI Groups execute an Intercept. +-- ### Author: **FlightControl** -- --- There are the following types of GCI classes defined: --- --- * @{#AI_A2A_GCI}: Perform a GCI in a zone. --- --- ==== --- --- ### Author: **Sven Van de Velde (FlightControl)** --- --- ### Contributions: --- --- ==== +-- === -- -- @module AI_A2A_GCI ---BASE:TraceClass("AI_A2A_GCI") - --- @type AI_A2A_GCI -- @extends AI.AI_A2A#AI_A2A diff --git a/Moose Development/Moose/AI/AI_A2A_Patrol.lua b/Moose Development/Moose/AI/AI_A2A_Patrol.lua index a6620b68b..927c5fd32 100644 --- a/Moose Development/Moose/AI/AI_A2A_Patrol.lua +++ b/Moose Development/Moose/AI/AI_A2A_Patrol.lua @@ -1,40 +1,12 @@ ---- **AI** -- **Air Patrolling or Staging.** +--- **AI** -- (R2.2) - Models the process of air patrol of airplanes. -- --- ![Banner Image](..\Presentations\AI_PATROL\Dia1.JPG) +-- This is a class used in the @{AI_A2A_Dispatcher}. -- -- === -- --- AI PATROL classes makes AI Groups execute an Patrol. +-- ### Author: **FlightControl** -- --- There are the following types of PATROL classes defined: --- --- * @{#AI_A2A_PATROL}: Perform a PATROL in a zone. --- --- ==== --- --- # Demo Missions --- --- ### [AI_PATROL Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/PAT%20-%20Patrolling) --- --- ### [AI_PATROL Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/PAT%20-%20Patrolling) --- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) --- --- ==== --- --- # YouTube Channel --- --- ### [AI_PATROL YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl35HvYZKA6G22WMt7iI3zky) --- --- ==== --- --- ### Author: **Sven Van de Velde (FlightControl)** --- ### Contributions: --- --- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) --- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Testing and API concept review. --- --- ==== +-- === -- -- @module AI_A2A_Patrol diff --git a/Moose Development/Moose/AI/AI_BAI.lua b/Moose Development/Moose/AI/AI_BAI.lua index 426bfea04..ccb0603bc 100644 --- a/Moose Development/Moose/AI/AI_BAI.lua +++ b/Moose Development/Moose/AI/AI_BAI.lua @@ -1,40 +1,25 @@ ---- **AI** -- **Provide Battlefield Air Interdiction (bombing).** +--- **AI** -- (R2.1) - Manages the independent process of Battlefield Air Interdiction (bombing) for airplanes. +-- +-- === -- -- ![Banner Image](..\Presentations\AI_BAI\Dia1.JPG) -- -- === -- --- AI_BAI classes makes AI Controllables execute bombing tasks. +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/BAI%20-%20Battlefield%20Air%20Interdiction) -- --- There are the following types of BAI classes defined: +-- === -- --- * @{#AI_BAI_ZONE}: Perform a BAI in a zone. --- --- ==== +-- ### [YouTube Playlist]() -- --- # Demo Missions --- --- ### [AI_BAI Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/BOMB%20-%20Close%20Air%20Support) --- --- ### [AI_BAI Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/BOMB%20-%20Close%20Air%20Support) --- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) --- --- ==== --- --- # YouTube Channel --- --- ### [AI_BAI YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3JBO1WDqqpyYRRmIkR2ir2) --- --- ==== --- --- ### Author: **Sven Van de Velde (FlightControl)** +-- === -- +-- ### Author: **FlightControl** -- ### Contributions: -- -- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. -- --- ==== +-- === -- -- @module AI_Bai diff --git a/Moose Development/Moose/AI/AI_Balancer.lua b/Moose Development/Moose/AI/AI_Balancer.lua index b20f3d32a..cb784e571 100644 --- a/Moose Development/Moose/AI/AI_Balancer.lua +++ b/Moose Development/Moose/AI/AI_Balancer.lua @@ -1,33 +1,25 @@ ---- **AI** -- **AI Balancing will replace in multi player missions --- non-occupied human slots with AI groups, in order to provide an engaging simulation environment, --- even when there are hardly any players in the mission.** +--- **AI** -- (2.1) - Balance player slots with AI to create an engaging simulation environment, independent of the amount of players. +-- +-- === -- -- ![Banner Image](..\Presentations\AI_Balancer\Dia1.JPG) --- --- ==== -- --- # Demo Missions +-- === -- --- ### [AI_BALANCER Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/AIB%20-%20AI%20Balancing) +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/AIB%20-%20AI%20Balancing) -- --- ### [AI_BALANCER Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AIB%20-%20AI%20Balancing) --- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) +-- === -- --- ==== +-- ### [YouTube Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl2CJVIrL1TdAumuVS8n64B7) -- --- # YouTube Channel +-- === -- --- ### [AI_BALANCER YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl2CJVIrL1TdAumuVS8n64B7) --- --- ==== --- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- -- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) -- --- ==== +-- === -- -- @module AI_Balancer diff --git a/Moose Development/Moose/AI/AI_CAP.lua b/Moose Development/Moose/AI/AI_CAP.lua index 58b8e3191..8dc70fd40 100644 --- a/Moose Development/Moose/AI/AI_CAP.lua +++ b/Moose Development/Moose/AI/AI_CAP.lua @@ -1,35 +1,20 @@ ---- **AI** -- **Execute Combat Air Patrol (CAP).** +--- **AI** -- (R2.1) - Manages the independent process of Combat Air Patrol (CAP) for airplanes. +-- +-- === -- -- ![Banner Image](..\Presentations\AI_CAP\Dia1.JPG) -- -- === -- --- AI CAP classes makes AI Controllables execute a Combat Air Patrol. +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAP%20-%20Combat%20Air%20Patrol) -- --- There are the following types of CAP classes defined: +-- === -- --- * @{#AI_CAP_ZONE}: Perform a CAP in a zone. --- --- ==== +-- ### [YouTube Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1YCyPxJgoZn-CfhwyeW65L) -- --- # Demo Missions --- --- ### [AI_CAP Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAP%20-%20Combat%20Air%20Patrol) --- --- ### [AI_CAP Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAP%20-%20Combat%20Air%20Patrol) --- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) --- --- ==== --- --- # YouTube Channel --- --- ### [AI_CAP YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1YCyPxJgoZn-CfhwyeW65L) --- --- ==== --- --- ### Author: **Sven Van de Velde (FlightControl)** +-- === -- +-- ### Author: **FlightControl** -- ### Contributions: -- -- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. @@ -38,7 +23,7 @@ -- * **[Whisper](http://forums.eagle.ru/member.php?u=3829): Testing. -- * **[Delta99](https://forums.eagle.ru/member.php?u=125166): Testing. -- --- ==== +-- === -- -- @module AI_Cap diff --git a/Moose Development/Moose/AI/AI_CAS.lua b/Moose Development/Moose/AI/AI_CAS.lua index 3f3a88a19..2450d02ff 100644 --- a/Moose Development/Moose/AI/AI_CAS.lua +++ b/Moose Development/Moose/AI/AI_CAS.lua @@ -1,43 +1,27 @@ ---- **AI** -- **Provide Close Air Support to friendly ground troops.** +--- **AI** -- (R2.1) - Manages the independent process of Close Air Support for airplanes. +-- +-- === -- -- ![Banner Image](..\Presentations\AI_CAS\Dia1.JPG) -- -- === -- --- AI CAS classes makes AI Controllables execute a Close Air Support. +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAS%20-%20Close%20Air%20Support) -- --- There are the following types of CAS classes defined: +-- === -- --- * @{#AI_CAS_ZONE}: Perform a CAS in a zone. --- --- ==== +-- ### [YouTube Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3JBO1WDqqpyYRRmIkR2ir2) -- --- # Demo Missions --- --- ### [AI_CAS Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAS%20-%20Close%20Air%20Support) --- --- ### [AI_CAS Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAS%20-%20Close%20Air%20Support) --- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) --- --- ==== --- --- # YouTube Channel --- --- ### [AI_CAS YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3JBO1WDqqpyYRRmIkR2ir2) --- --- ==== --- --- --- ### Author: **Sven Van de Velde (FlightControl)** +-- === -- +-- ### Author: **FlightControl** -- ### Contributions: -- -- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. -- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. -- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. -- --- ==== +-- === -- -- @module AI_Cas diff --git a/Moose Development/Moose/AI/AI_Formation.lua b/Moose Development/Moose/AI/AI_Formation.lua index 3b2012710..d5801927d 100644 --- a/Moose Development/Moose/AI/AI_Formation.lua +++ b/Moose Development/Moose/AI/AI_Formation.lua @@ -1,4 +1,6 @@ ---- **AI** -- Build large **formations** of AI @{Group}s flying together. +--- **AI** -- (R2.2) - Build large airborne formations of aircraft. +-- +-- === -- -- ![Banner Image](..\Presentations\AI_FORMATION\Dia1.JPG) -- @@ -28,29 +30,20 @@ -- -- * @{#AI_FORMATION}: Create a formation from several @{GROUP}s. -- --- ==== +-- === -- --- # Demo Missions --- --- ### [AI_FORMATION Demo Missions source code]() --- --- ### [AI_FORMATION Demo Missions, only for beta testers]() --- --- ### [ALL Demo Missions pack of the last release]() --- --- ==== --- --- # YouTube Channel --- ---- ### [AI_FORMATION YouTube Channel]() +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/FOR%20-%20Formation) -- -- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### [YouTube Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0bFIJ9jIdYM22uaWmIN4oz) -- +-- === +-- +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module AI_Formation diff --git a/Moose Development/Moose/AI/AI_Patrol.lua b/Moose Development/Moose/AI/AI_Patrol.lua index fe3474b0d..4cc6e7d6e 100644 --- a/Moose Development/Moose/AI/AI_Patrol.lua +++ b/Moose Development/Moose/AI/AI_Patrol.lua @@ -1,4 +1,6 @@ ---- **AI** -- **Air Patrolling or Staging.** +--- **AI** -- (R2.1) - Manages the independent process of Air Patrol for airplanes. +-- +-- === -- -- ![Banner Image](..\Presentations\AI_PATROL\Dia1.JPG) -- @@ -10,31 +12,23 @@ -- -- * @{#AI_PATROL_ZONE}: Perform a PATROL in a zone. -- --- ==== +-- === -- --- # Demo Missions +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/PAT%20-%20Patrolling) -- --- ### [AI_PATROL Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/PAT%20-%20Patrolling) +-- === -- --- ### [AI_PATROL Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/PAT%20-%20Patrolling) --- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) +-- ### [YouTube Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl35HvYZKA6G22WMt7iI3zky) -- --- ==== +-- === -- --- # YouTube Channel --- --- ### [AI_PATROL YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl35HvYZKA6G22WMt7iI3zky) --- --- ==== --- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- -- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) -- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Testing and API concept review. -- --- ==== +-- === -- -- @module AI_Patrol diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index 00b2dabc4..f642d79b1 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -4,10 +4,10 @@ -- -- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Base @@ -1083,6 +1083,34 @@ function BASE:E( Arguments ) end +--- Log an information which will be traced always. Can be anywhere within the function logic. +-- @param #BASE self +-- @param Arguments A #table or any field. +function BASE:I( Arguments ) + + if BASE.Debug then + local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" ) + local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" ) + + local Function = "function" + if DebugInfoCurrent.name then + Function = DebugInfoCurrent.name + end + + local LineCurrent = DebugInfoCurrent.currentline + local LineFrom = -1 + if DebugInfoFrom then + LineFrom = DebugInfoFrom.currentline + end + + env.info( string.format( "%6d(%6d)/%1s:%20s%05d.%s(%s)" , LineCurrent, LineFrom, "I", self.ClassName, self.ClassID, Function, routines.utils.oneLineSerialize( Arguments ) ) ) + else + env.info( string.format( "%1s:%20s%05d(%s)" , "I", self.ClassName, self.ClassID, routines.utils.oneLineSerialize( Arguments ) ) ) + end + +end + + --- old stuff diff --git a/Moose Development/Moose/Core/Cargo.lua b/Moose Development/Moose/Core/Cargo.lua index de62c73e2..991669931 100644 --- a/Moose Development/Moose/Core/Cargo.lua +++ b/Moose Development/Moose/Core/Cargo.lua @@ -11,7 +11,7 @@ -- -- This module is still under construction, but is described above works already, and will keep working ... -- --- ==== +-- === -- -- # Demo Missions -- @@ -21,18 +21,18 @@ -- -- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- --- ==== +-- === -- -- # YouTube Channel -- -- ### [CARGO YouTube Channel](https://www.youtube.com/watch?v=tM00lTlkpYs&list=PL7ZUrU4zZUl2zUTuKrLW5RsO9zLMqUtbf) -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Cargo diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index f99726349..d90e01284 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -1,11 +1,11 @@ --- **Core** -- DATABASE manages the database of mission objects. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Database diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index 3e55977da..1907c3a4c 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -159,10 +159,10 @@ -- -- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Event diff --git a/Moose Development/Moose/Core/Fsm.lua b/Moose Development/Moose/Core/Fsm.lua index d107fc903..0c49c79e3 100644 --- a/Moose Development/Moose/Core/Fsm.lua +++ b/Moose Development/Moose/Core/Fsm.lua @@ -56,13 +56,13 @@ -- * @{#FSM_SET}: Models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here -- for multiple objects or the position of the state machine in the process. -- --- ==== +-- === -- -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Fsm diff --git a/Moose Development/Moose/Core/Goal.lua b/Moose Development/Moose/Core/Goal.lua index 6b2a98b3c..ff6976877 100644 --- a/Moose Development/Moose/Core/Goal.lua +++ b/Moose Development/Moose/Core/Goal.lua @@ -1,14 +1,14 @@ --- **Core (WIP)** -- Base class to allow the modeling of processes to achieve Goals. -- --- ==== +-- === -- -- GOAL models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- --- ==== +-- === -- -- @module Goal diff --git a/Moose Development/Moose/Core/Menu.lua b/Moose Development/Moose/Core/Menu.lua index 87439acb4..9bb30be21 100644 --- a/Moose Development/Moose/Core/Menu.lua +++ b/Moose Development/Moose/Core/Menu.lua @@ -25,10 +25,10 @@ -- -- === --- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Menu diff --git a/Moose Development/Moose/Core/Message.lua b/Moose Development/Moose/Core/Message.lua index 5d3450616..11a1e19dc 100644 --- a/Moose Development/Moose/Core/Message.lua +++ b/Moose Development/Moose/Core/Message.lua @@ -39,12 +39,12 @@ -- * To all players using @{Message#MESSAGE.ToAllIf}(). -- * To a coalition using @{Message#MESSAGE.ToCoalitionIf}(). -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @field #MESSAGE MESSAGE = { diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 3fdfea1c5..e56ff64aa 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -2,7 +2,7 @@ -- -- ![Banner Image](..\Presentations\POINT\Dia1.JPG) -- --- ==== +-- === -- -- # Demo Missions -- @@ -12,7 +12,7 @@ -- -- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- --- ==== +-- === -- -- # YouTube Channel -- diff --git a/Moose Development/Moose/Core/Scheduler.lua b/Moose Development/Moose/Core/Scheduler.lua index 4b712d215..e576aa2aa 100644 --- a/Moose Development/Moose/Core/Scheduler.lua +++ b/Moose Development/Moose/Core/Scheduler.lua @@ -21,13 +21,13 @@ -- -- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- --- ==== +-- === -- -- # YouTube Channel -- -- ### [SCHEDULER YouTube Channel (none)]() -- --- ==== +-- === -- -- ### Contributions: -- diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index b4e7a95a4..71df11f1c 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -23,12 +23,12 @@ -- * Validate the presence of objects in the SET. -- * Trigger events when objects in the SET change a zone presence. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Set @@ -604,15 +604,16 @@ end --- Flushes the current SET_BASE contents in the log ... (for debugging reasons). -- @param #SET_BASE self +-- @param Core.Base#BASE MasterObject (optional) The master object as a reference. -- @return #string A string with the names of the objects. -function SET_BASE:Flush() +function SET_BASE:Flush( MasterObject ) self:F3() local ObjectNames = "" for ObjectName, Object in pairs( self.Set ) do ObjectNames = ObjectNames .. ObjectName .. ", " end - self:E( { "Objects in Set:", ObjectNames } ) + self:I( { MasterObject = MasterObject:GetClassNameAndID(), "Objects in Set:", ObjectNames } ) return ObjectNames end diff --git a/Moose Development/Moose/Core/Settings.lua b/Moose Development/Moose/Core/Settings.lua index 85498104d..8b8a2c601 100644 --- a/Moose Development/Moose/Core/Settings.lua +++ b/Moose Development/Moose/Core/Settings.lua @@ -2,7 +2,7 @@ -- -- ![Banner Image](..\Presentations\SETTINGS\Dia1.JPG) -- --- ==== +-- === -- -- The documentation of the SETTINGS class can be found further in this document. -- diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index eef24926a..5342a6e92 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -2,43 +2,27 @@ -- -- ![Banner Image](..\Presentations\SPAWN\SPAWN.JPG) -- --- ==== +-- === -- -- The documentation of the SPAWN class can be found further in this document. -- --- ==== +-- === -- --- # Demo Missions --- --- ### [SPAWN Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SPA%20-%20Spawning) --- --- ### [SPAWN Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPA%20-%20Spawning) --- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) --- --- ==== --- --- # YouTube Channel --- --- ### [SPAWN YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL) +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SPA%20-%20Spawning) -- -- === -- --- # **AUTHORS and CONTRIBUTIONS** +-- ### [YouTube Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL) -- --- ### Contributions: +-- === -- --- * **Aaron**: Posed the idea for Group position randomization at SpawnInZone and make the Unit randomization separate from the Group randomization. --- * [**Entropy**](https://forums.eagle.ru/member.php?u=111471), **Afinegan**: Came up with the requirement for AIOnOff(). +-- ### Author: **FlightControl** +-- ### Contributions: A lot of people within this community! -- --- ### Authors: --- --- * **FlightControl**: Design & Programming +-- === -- -- @module Spawn -----BASE:TraceClass("SPAWN") - --- SPAWN Class -- @type SPAWN diff --git a/Moose Development/Moose/Core/SpawnStatic.lua b/Moose Development/Moose/Core/SpawnStatic.lua index 533c51e1f..92a816257 100644 --- a/Moose Development/Moose/Core/SpawnStatic.lua +++ b/Moose Development/Moose/Core/SpawnStatic.lua @@ -2,11 +2,11 @@ -- -- ![Banner Image](..\Presentations\SPAWNSTATIC\Dia1.JPG) -- --- ==== +-- === -- -- SPAWNSTATIC spawns static structures in your missions dynamically. See below the SPAWNSTATIC class documentation. -- --- ==== +-- === -- -- # Demo Missions -- @@ -16,18 +16,18 @@ -- -- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- --- ==== +-- === -- -- # YouTube Channel -- -- ### [SPAWNSTATIC YouTube Channel]() -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module SpawnStatic diff --git a/Moose Development/Moose/Core/Spot.lua b/Moose Development/Moose/Core/Spot.lua index 38ed1d583..10edb6cee 100644 --- a/Moose Development/Moose/Core/Spot.lua +++ b/Moose Development/Moose/Core/Spot.lua @@ -2,7 +2,7 @@ -- -- ![Banner Image](..\Presentations\SPOT\Dia1.JPG) -- --- ==== +-- === -- -- SPOT implements the DCS Spot class functionality, but adds additional luxury to be able to: -- @@ -11,7 +11,7 @@ -- * Provide a @{Unit} as a target, instead of a point. -- * Implement a status machine, LaseOn, LaseOff. -- --- ==== +-- === -- -- # Demo Missions -- @@ -21,22 +21,22 @@ -- -- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- --- ==== +-- === -- -- # YouTube Channel -- -- ### [SPOT YouTube Channel]() -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- -- * [**Ciribob**](https://forums.eagle.ru/member.php?u=112175): Showing the way how to lase targets + how laser codes work!!! Explained the autolase script. -- * [**EasyEB**](https://forums.eagle.ru/member.php?u=112055): Ideas and Beta Testing -- * [**Wingthor**](https://forums.eagle.ru/member.php?u=123698): Beta Testing -- --- ==== +-- === -- -- @module Spot diff --git a/Moose Development/Moose/Core/UserFlag.lua b/Moose Development/Moose/Core/UserFlag.lua index 3c11718da..05fc7b29e 100644 --- a/Moose Development/Moose/Core/UserFlag.lua +++ b/Moose Development/Moose/Core/UserFlag.lua @@ -1,14 +1,14 @@ --- **Core (WIP)** -- Manage user flags. -- --- ==== +-- === -- -- Management of DCS User Flags. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- --- ==== +-- === -- -- @module UserFlag diff --git a/Moose Development/Moose/Core/UserSound.lua b/Moose Development/Moose/Core/UserSound.lua index ff1c316c8..808b78a5f 100644 --- a/Moose Development/Moose/Core/UserSound.lua +++ b/Moose Development/Moose/Core/UserSound.lua @@ -1,14 +1,14 @@ --- **Core (WIP)** -- Manage user sound. -- --- ==== +-- === -- -- Management of DCS User Sound. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- --- ==== +-- === -- -- @module UserSound diff --git a/Moose Development/Moose/Core/Velocity.lua b/Moose Development/Moose/Core/Velocity.lua index 964d67577..88d047126 100644 --- a/Moose Development/Moose/Core/Velocity.lua +++ b/Moose Development/Moose/Core/Velocity.lua @@ -2,10 +2,10 @@ -- -- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Velocity diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 618d49ec5..72317d2ba 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -2,7 +2,7 @@ -- -- ![Banner Image](..\Presentations\ZONE\Dia1.JPG) -- --- ==== +-- === -- -- There are essentially two core functions that zones accomodate: -- @@ -27,12 +27,12 @@ -- * @{#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius. -- * @{#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module Zone diff --git a/Moose Development/Moose/Functional/CleanUp.lua b/Moose Development/Moose/Functional/CleanUp.lua index 50c3851f1..016bb10ef 100644 --- a/Moose Development/Moose/Functional/CleanUp.lua +++ b/Moose Development/Moose/Functional/CleanUp.lua @@ -2,10 +2,10 @@ -- -- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: -- --- ==== +-- === -- -- @module CleanUp diff --git a/Moose Development/Moose/Functional/Designate.lua b/Moose Development/Moose/Functional/Designate.lua index e8322dc26..19e09d6ab 100644 --- a/Moose Development/Moose/Functional/Designate.lua +++ b/Moose Development/Moose/Functional/Designate.lua @@ -795,7 +795,7 @@ do -- DESIGNATE -- ok, we added one item to the designate scope. self.AttackSet:ForEachGroupAlive( function( AttackGroup ) - local DetectionText = self.Detection:DetectedItemReportSummary( DesignateIndex, AttackGroup ):Text( ", " ) + local DetectionText = self.Detection:DetectedItemReportSummary( DetectedItem, AttackGroup ):Text( ", " ) self.CC:GetPositionable():MessageToGroup( "Targets detected at \n" .. DetectionText, 10, AttackGroup, self.DesignateName ) end ) @@ -900,7 +900,7 @@ do -- DESIGNATE -- @return #DESIGNATE function DESIGNATE:SetDesignateMenu() - self.AttackSet:Flush() + self.AttackSet:Flush( self ) self.AttackSet:ForEachGroupAlive( diff --git a/Moose Development/Moose/Functional/Detection.lua b/Moose Development/Moose/Functional/Detection.lua index bc738e2f7..7484bbd98 100644 --- a/Moose Development/Moose/Functional/Detection.lua +++ b/Moose Development/Moose/Functional/Detection.lua @@ -9,7 +9,7 @@ -- -- Find the DETECTION classes documentation further in this document in the globals section. -- --- ==== +-- === -- -- # Demo Missions -- @@ -19,13 +19,13 @@ -- -- ### [ALL Demo Missions pack of the Latest Release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- --- ==== +-- === -- -- # YouTube Channel -- -- ### [DETECTION YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3Cf5jpI6BS0sBOVWK__tji) -- --- ==== +-- === -- -- ### Contributions: -- diff --git a/Moose Development/Moose/Functional/Escort.lua b/Moose Development/Moose/Functional/Escort.lua index c9b150a92..6fcddbe7c 100644 --- a/Moose Development/Moose/Functional/Escort.lua +++ b/Moose Development/Moose/Functional/Escort.lua @@ -1,9 +1,9 @@ --- **Functional** -- Taking the lead of AI escorting your flight. -- --- ==== +-- === -- -- @{#ESCORT} class --- ================ +-- === -- The @{#ESCORT} class allows you to interact with escorting AI on your flight and take the lead. -- Each escorting group can be commanded with a whole set of radio commands (radio menu in your flight, and then F10). -- @@ -11,7 +11,7 @@ -- Ships and Ground troops will have a more limited set, but they can provide support through the bombing of targets designated by the other escorts. -- -- RADIO MENUs that can be created: --- ================================ +-- === -- Find a summary below of the current available commands: -- -- Navigation ...: @@ -79,13 +79,13 @@ -- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission. -- -- ESCORT construction methods. --- ============================ +-- === -- Create a new SPAWN object with the @{#ESCORT.New} method: -- -- * @{#ESCORT.New}: Creates a new ESCORT object from a @{Group#GROUP} for a @{Client#CLIENT}, with an optional briefing text. -- -- ESCORT initialization methods. --- ============================== +-- === -- 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. diff --git a/Moose Development/Moose/Functional/MissileTrainer.lua b/Moose Development/Moose/Functional/MissileTrainer.lua index fd3357855..7659b3c8a 100644 --- a/Moose Development/Moose/Functional/MissileTrainer.lua +++ b/Moose Development/Moose/Functional/MissileTrainer.lua @@ -3,7 +3,7 @@ -- === -- -- 1) @{MissileTrainer#MISSILETRAINER} class, extends @{Base#BASE} --- =============================================================== +-- === -- The @{#MISSILETRAINER} class uses the DCS world messaging system to be alerted of any missiles fired, and when a missile would hit your aircraft, -- the class will destroy the missile within a certain range, to avoid damage to your aircraft. -- It suports the following functionality: @@ -71,7 +71,7 @@ -- === -- -- CREDITS --- ======= +-- === -- **Stuka (Danny)** Who you can search on the Eagle Dynamics Forums. -- Working together with Danny has resulted in the MISSILETRAINER class. -- Danny has shared his ideas and together we made a design. diff --git a/Moose Development/Moose/Functional/Movement.lua b/Moose Development/Moose/Functional/Movement.lua index 69317c9e5..a5d4d7058 100644 --- a/Moose Development/Moose/Functional/Movement.lua +++ b/Moose Development/Moose/Functional/Movement.lua @@ -1,6 +1,6 @@ --- **Functional** -- Limit the MOVEMENT of simulaneous moving ground vehicles. -- --- ==== +-- === -- -- Limit the simultaneous movement of Groups within a running Mission. -- This module is defined to improve the performance in missions, and to bring additional realism for GROUND vehicles. diff --git a/Moose Development/Moose/Functional/Protect.lua b/Moose Development/Moose/Functional/Protect.lua index 6fe73e54a..f0f2ef260 100644 --- a/Moose Development/Moose/Functional/Protect.lua +++ b/Moose Development/Moose/Functional/Protect.lua @@ -2,10 +2,10 @@ -- -- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- ### Contributions: **MillerTime** -- --- ==== +-- === -- -- @module Protect diff --git a/Moose Development/Moose/Functional/RAT.lua b/Moose Development/Moose/Functional/RAT.lua index b73c53820..04da94f98 100644 --- a/Moose Development/Moose/Functional/RAT.lua +++ b/Moose Development/Moose/Functional/RAT.lua @@ -1,9 +1,11 @@ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- **Functional** - Create random airtraffic in your missions. --- +--- **Functional** - (R2.2) - Create random airtraffic in your missions. +-- +-- === +-- -- ![Banner Image](..\Presentations\RAT\RAT.png) -- --- ==== +-- === -- -- The aim of the RAT class is to fill the empty DCS world with randomized air traffic and bring more life to your airports. -- @@ -36,14 +38,14 @@ -- -- More of the documentation include some simple examples can be found further down this page. -- --- ==== +-- === -- -- # Demo Missions -- -- ### [RAT Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/Release/RAT%20-%20Random%20Air%20Traffic) -- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- --- ==== +-- === -- -- # YouTube Channel -- @@ -56,7 +58,7 @@ -- -- ### Contributions: **Sven van de Velde ([FlightControl](https://forums.eagle.ru/member.php?u=89536))** -- --- ==== +-- === -- @module Rat ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua new file mode 100644 index 000000000..5108d13e8 --- /dev/null +++ b/Moose Development/Moose/Functional/Range.lua @@ -0,0 +1,1909 @@ +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +--- **Functional** - (R2.3) - Range Practice. +-- +-- === +-- +-- ![Banner Image](..\Presentations\RANGE\RANGE_Main.png) +-- +-- === +-- +-- The RANGE class enables easy set up of bombing and strafing ranges within DCS World. +-- +-- Implementation is based on the [Simple Range Script](https://forums.eagle.ru/showthread.php?t=157991) by [Ciribob](https://forums.eagle.ru/member.php?u=112175), which itself was motivated +-- by a script by SNAFU [see here](https://forums.eagle.ru/showthread.php?t=109174). +-- +-- ## Features +-- +-- * Bomb and rocket impact point from closest range target is measured and distance reported to the player. +-- * Number of hits on strafing passes are counted. +-- * Results of all bombing and strafing runs are stored and top 10 results can be displayed. +-- * Range targets can be marked by smoke. +-- * Range can be illuminated by illumination bombs for night practices. +-- * Rocket or bomb impact points can be marked by smoke. +-- * Direct hits on targets can trigger flares. +-- * Smoke and flare colors can be adjusted for each player via radio menu. +-- * Range information and weather report at the range can be reported via radio menu. +-- +-- More information and examples can be found below. +-- +-- === +-- +-- # Demo Missions +-- +-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) +-- +-- === +-- +-- # YouTube Channel +-- +-- ### [MOOSE YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL) +-- +-- === +-- +-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** +-- +-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536), [Ciribob](https://forums.eagle.ru/member.php?u=112175) +-- +-- === +-- @module Range + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +--- RANGE class +-- @type RANGE +-- @field #string ClassName Name of the Class. +-- @field #boolean Debug If true, debug info is send as messages on the screen. +-- @field #string rangename Name of the range. +-- @field Core.Point#COORDINATE location Coordinate of the range. +-- @field #number rangeradius Radius of range defining its total size for e.g. smoking bomb impact points. Default 10 km. +-- @field #table strafeTargets Table of strafing targets. +-- @field #table bombingTargets Table of targets to bomb. +-- @field #number nbombtargets Number of bombing targets. +-- @field #number nstrafetargets Number of strafing targets. +-- @field #table MenuAddedTo Table for monitoring which players already got an F10 menu. +-- @field #table planes Table for administration. +-- @field #table strafeStatus Table containing the current strafing target a player as assigned to. +-- @field #table strafePlayerResults Table containing the strafing results of each player. +-- @field #table bombPlayerResults Table containing the bombing results of each player. +-- @field #table PlayerSettings Indiviual player settings. +-- @field #number dtBombtrack Time step [sec] used for tracking released bomb/rocket positions. Default 0.005 seconds. +-- @field #number Tmsg Time [sec] messages to players are displayed. Default 30 sec. +-- @field #number strafemaxalt Maximum altitude above ground for registering for a strafe run. Default is 914 m = 3000 ft. +-- @field #number ndisplayresult Number of (player) results that a displayed. Default is 10. +-- @field Utilities.Utils#SMOKECOLOR BombSmokeColor Color id used for smoking bomb targets. +-- @field Utilities.Utils#SMOKECOLOR StrafeSmokeColor Color id used to smoke strafe targets. +-- @field Utilities.Utils#SMOKECOLOR StrafePitSmokeColor Color id used to smoke strafe pit approach boxes. +-- @field #number illuminationminalt Minimum altitude AGL in meters at which illumination bombs are fired. Default is 500 m. +-- @field #number illuminationmaxalt Maximum altitude AGL in meters at which illumination bombs are fired. Default is 1000 m. +-- @field #number scorebombdistance Distance from closest target up to which bomb hits are counted. Default 1000 m. +-- @field #number TdelaySmoke Time delay in seconds between impact of bomb and starting the smoke. Default 3 seconds. +-- @field #boolean eventmoose If true, events are handled by MOOSE. If false, events are handled directly by DCS eventhandler. Default true. +-- @extends Core.Base#BASE + +---# RANGE class, extends @{Base#BASE} +-- The RANGE class enables a mission designer to easily set up practice ranges in DCS. A new RANGE object can be created with the @{#RANGE.New}(rangename) contructor. +-- The parameter "rangename" defindes the name of the range. It has to be unique since this is also the name displayed in the radio menu. +-- +-- Generally, a range consits of strafe pits and bombing targets. For strafe pits the number of hits for each pass is counted and tabulated. +-- For bombing targets, the distance from the impact point of the bomb or rocket to the closest range target is measured and tabulated. +-- Each player can display his best results via a function in the radio menu or see the best best results from all players. +-- +-- When all targets have been defined in the script, the range is started by the @{#RANGE.Start}() command. +-- +-- **IMPORTANT** +-- +-- Due to a DCS bug, it is not possible to directly monitor when a player enters a plane. So in a mission with client slots, it is vital that +-- a player first enters as spector and **after that** jumps into the slot of his aircraft! +-- If that is not done, the script is not started correctly. This can be checked by looking at the radio menues. If the mission was entered correctly, +-- there should be an "On the Range" menu items in the "F10. Other..." menu. +-- +-- ## Strafe Pits +-- Each strafe pit can consist of multiple targets. Often one findes two or three strafe targets next to each other. +-- +-- A strafe pit can be added to the range by the @{#RANGE.AddStrafepit}(unitnames, boxlength, boxwidth, heading, inverseheading, goodpass, foulline) function. +-- +-- The first parameter defines the target. This has to be given as a lua table which contains the unit names of the targets as defined in the mission editor. +-- +-- In order to perform a valid pass on the strafe pit, the pilot has to begin his run from the correct direction. Therefore, an "approach box" is defined in front +-- of the strafe targets. The parameters "boxlength" and "boxwidth" define the size of the box while the parameter "heading" defines its direction. +-- If the parameter heading is passed as **nil**, the heading is automatically taken from the heading of the first target unit as defined in the ME. +-- The parameter "inverseheading" turns the heading around by 180 degrees. This is sometimes useful, since the default heading of strafe target units point in the +-- wrong/opposite direction. +-- +-- The parameter "goodpass" defines the number of hits a pilot has to achive during a run to be judges as a good pass. +-- +-- The last parameter "foulline" sets the distance from the pit targets to the foul line. Hit from closer than this line are not counted. +-- +-- Finally, a valid approach has to be performed below a certain maximum altitude. The default is 914 meters (3000 ft) AGL. This is a parameter valid for all +-- strafing pits of the range and can be adjusted by the @{#RANGE.SetMaxStrafeAlt}(maxalt) function. +-- +-- ## Bombing targets +-- One ore multiple bombing targets can be added to the range by the @{#RANGE.AddBombingTargets}(unitnames goodhitrange,static) function. +-- +-- The first parameter "unitnames" has to be a lua table, which contains the names of the units as defined in the mission editor. +-- +-- The parameter "goodhitrange" specifies the radius around the target. If a bomb or rocket falls at a distance smaller than this number, the hit is considered to be "good". +-- +-- The final (optional) parameter "static" can be enabled (set to true) if static bomb targets are used rather than alive units. +-- +-- ## Fine Tuning +-- Many range parameters have good default values. However, the mission designer can change these settings easily with the supplied user functions: +-- +-- * @{#RANGE.SetMaxStrafeAlt}() sets the max altitude for valid strafing runs. +-- * @{#RANGE.SetMessageTimeDuration}() sets the duration how long (most) messages are displayed. +-- * @{#RANGE.SetDisplayedMaxPlayerResults}() sets the number of results displayed. +-- * @{#RANGE.SetRangeRadius}() defines the total range area. +-- * @{#RANGE.SetBombTargetSmokeColor}() sets the color used to smoke bombing targets. +-- * @{#RANGE.SetStrafeTargetSmokeColor}() sets the color used to smoke strafe targets. +-- * @{#RANGE.SetStrafePitSmokeColor}() sets the color used to smoke strafe pit approach boxes. +-- * @{#RANGE.SetSmokeTimeDelay}() sets the time delay between smoking bomb/rocket impact points after impact. +-- +-- ## Radio Menu +-- Each range gets a radio menu with various submenus where each player can adjust his individual settings or request information about the range or his scores. +-- +-- The main range menu can be found at "F10. Other..." --> "Fxx. On the Range..." --> "F1. Your Range Name...". +-- +-- The range menu contains the following submenues: +-- +-- * "F1. Mark Targets": Various ways to mark targets. +-- * "F2. My Settings": Player specific settings. +-- * "F3. Stats" Player: statistics and scores. +-- * "Range Information": Information about the range, such as bearing and range. Also range and player specific settings are displayed. +-- * "Weather Report": Temperatur, wind and QFE pressure information is provided. +-- +-- ## Examples +-- +-- ### Goldwater Range +-- This example shows hot to set up the Barry M. Goldwater range. It consists of two strafe pits each has two targets plus three bombing targets. +-- +-- -- Strafe pits. Each pit can consist of multiple targets. Here we have two pits and each of the pits has two targets. These are names of the corresponding units defined in the ME. +-- local strafepit_left={"GWR Strafe Pit Left 1", "GWR Strafe Pit Left 2"} +-- local strafepit_right={"GWR Strafe Pit Right 1", "GWR Strafe Pit Right 2"} +-- +-- -- Table of bombing target names. Again these are the names of the corresponding units as defined in the ME. +-- local bombtargets={"GWR Bomb Target Circle Left", "GWR Bomb Target Circle Right", "GWR Bomb Target Hard"} +-- +-- -- Create a range object. +-- local GoldwaterRange=RANGE:New("Goldwater Range") +-- +-- -- Distance between foul line and strafe target. Note that this could also be done manually by simply measuring the distance between the target and the foul line in the ME. +-- local strafe=UNIT:FindByName("GWR Strafe Pit Left 1") +-- local foul=UNIT:FindByName("GWR Foul Line Left") +-- local fouldist=strafe:GetCoordinate():Get2DDistance(foul:GetCoordinate()) +-- +-- -- Add strafe pits. Each pit (left and right) consists of two targets. +-- GoldwaterRange:AddStrafePit(strafepit_left, 3000, 300, nil, true, 20, fouldist) +-- GoldwaterRange:AddStrafePit(strafepit_right, 3000, 300, nil, true, 20, fouldist) +-- +-- -- Add bombing targets. A good hit is if the bomb falls less then 50 m from the target. +-- GoldwaterRange:AddBombingTargets(bombtargets, 50) +-- +-- -- Start range. +-- GoldwaterRange:Start() +-- +-- +-- +-- @field #RANGE +RANGE={ + ClassName = "RANGE", + Debug=false, + rangename=nil, + location=nil, + rangeradius=10000, + strafeTargets={}, + bombingTargets={}, + nbombtargets=0, + nstrafetargets=0, + MenuAddedTo = {}, + planes = {}, + strafeStatus = {}, + strafePlayerResults = {}, + bombPlayerResults = {}, + PlayerSettings = {}, + dtBombtrack=0.005, + Tmsg=30, + strafemaxalt=914, + ndisplayresult=10, + BombSmokeColor=SMOKECOLOR.Red, + StrafeSmokeColor=SMOKECOLOR.Green, + StrafePitSmokeColor=SMOKECOLOR.White, + illuminationminalt=500, + illuminationmaxalt=1000, + scorebombdistance=1000, + TdelaySmoke=3.0, + eventmoose=true, +} + +--- Some ID to identify who we are in output of the DCS.log file. +-- @field #string id +RANGE.id="RANGE | " + +--- Range script version. +-- @field #number version +RANGE.version="1.0.0" + +--TODO list +--TODO: Add statics for strafe pits. +--DONE: Convert env.info() to self:T() +--DONE: Add user functions. +--DONE: Rename private functions, i.e. start with _functionname. +--DONE: number of displayed results variable. +--DONE: Add tire option for strafe pits. ==> No really feasible since tires are very small and cannot be seen. +--DONE: Check that menu texts are short enough to be correctly displayed in VR. + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- RANGE contructor. Creates a new RANGE object. +-- @param #RANGE self +-- @param #string rangename Name of the range. Has to be unique. Will we used to create F10 menu items etc. +-- @return #RANGE RANGE object. +function RANGE:New(rangename) + BASE:F({rangename=rangename}) + + -- Inherit BASE. + local self=BASE:Inherit(self, BASE:New()) -- #RANGE + + -- Get range name. + self.rangename=rangename or "Practice Range" + + -- Debug info. + local text=string.format("RANGE script version %s. Creating new RANGE object. Range name: %s.", RANGE.version, self.rangename) + self:E(RANGE.id..text) + MESSAGE:New(text, 10):ToAllIf(self.Debug) + + -- Return object. + return self +end + +--- Initializes number of targets and location of the range. Starts the event handlers. +-- @param #RANGE self +function RANGE:Start() + self:F() + + -- Location/coordinate of range. + local _location=nil + + -- Count bomb targets. + local _count=0 + for _,_target in pairs(self.bombingTargets) do + _count=_count+1 + --_target.name + if _location==nil then + _location=_target.point --Core.Point#COORDINATE + end + end + self.nbombtargets=_count + + -- Count strafing targets. + _count=0 + for _,_target in pairs(self.strafeTargets) do + _count=_count+1 + for _,_unit in pairs(_target.targets) do + if _location==nil then + _location=_unit:GetCoordinate() + end + end + end + self.nstrafetargets=_count + + -- Location of the range. We simply take the first unit/target we find. + self.location=_location + + if self.location==nil then + local text=string.format("ERROR! No range location found. Number of strafe targets = %d. Number of bomb targets = %d.", self.rangename, self.nstrafetargets, self.nbombtargets) + self:E(RANGE.id..text) + return nil + end + + -- Starting range. + local text=string.format("Starting RANGE %s. Number of strafe targets = %d. Number of bomb targets = %d.", self.rangename, self.nstrafetargets, self.nbombtargets) + self:E(RANGE.id..text) + MESSAGE:New(text,10):ToAllIf(self.Debug) + + -- Event handling. + if self.eventmoose then + -- Events are handled my MOOSE. + self:T(RANGE.id.."Events are handled by MOOSE.") + self:HandleEvent(EVENTS.Birth, self._OnBirth) + self:HandleEvent(EVENTS.Hit, self._OnHit) + self:HandleEvent(EVENTS.Shot, self._OnShot) + else + -- Events are handled directly by DCS. + self:T(RANGE.id.."Events are handled directly by DCS.") + world.addEventHandler(self) + end + +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- User Functions + +--- Set maximal strafing altitude. Player entering a strafe pit above that altitude are not registered for a valid pass. +-- @param #RANGE self +-- @param #number maxalt Maximum altitude AGL in meters. Default is 914 m= 3000 ft. +function RANGE:SetMaxStrafeAlt(maxalt) + self.strafemaxalt=maxalt or 914 +end + +--- Set time interval for tracking bombs. A smaller time step increases accuracy but needs more CPU time. +-- @param #RANGE self +-- @param #number dt Time interval in seconds. Default is 0.005 s. +function RANGE:SetBombtrackTimestep(dt) + self.dtBombtrack=dt or 0.005 +end + +--- Set time how long (most) messages are displayed. +-- @param #RANGE self +-- @param #number time Time in seconds. Default is 30 s. +function RANGE:SetMessageTimeDuration(time) + self.Tmsg=time or 30 +end + +--- Set max number of player results that are displayed. +-- @param #RANGE self +-- @param #number nmax Number of results. Default is 10. +function RANGE:SetDisplayedMaxPlayerResults(nmax) + self.ndisplayresult=nmax or 10 +end + +--- Set range radius. Defines the area in which e.g. bomb impacts are smoked. +-- @param #RANGE self +-- @param #number radius Radius in km. Default 10 km. +function RANGE:SetRangeRadius(radius) + self.rangeradius=radius*1000 or 10000 +end + +--- Set smoke color for marking bomb targets. By default bomb targets are marked by red smoke. +-- @param #RANGE self +-- @param Utilities.Utils#SMOKECOLOR colorid Color id. Default SMOKECOLOR.Red. +function RANGE:SetBombTargetSmokeColor(colorid) + self.BombSmokeColor=colorid or SMOKECOLOR.Red +end + +--- Set smoke color for marking strafe targets. By default strafe targets are marked by green smoke. +-- @param #RANGE self +-- @param Utilities.Utils#SMOKECOLOR colorid Color id. Default SMOKECOLOR.Green. +function RANGE:SetStrafeTargetSmokeColor(colorid) + self.StrafeSmokeColor=colorid or SMOKECOLOR.Green +end + +--- Set smoke color for marking strafe pit approach boxes. By default strafe pit boxes are marked by white smoke. +-- @param #RANGE self +-- @param Utilities.Utils#SMOKECOLOR colorid Color id. Default SMOKECOLOR.White. +function RANGE:SetStrafePitSmokeColor(colorid) + self.StrafePitSmokeColor=colorid or SMOKECOLOR.White +end + +--- Set time delay between bomb impact and starting to smoke the impact point. +-- @param #RANGE self +-- @param #number delay Time delay in seconds. Default is 3 seconds. +function RANGE:SetSmokeTimeDelay(delay) + self.TdelaySmoke=delay or 3.0 +end + +--- Enable debug modus. +-- @param #RANGE self +function RANGE:DebugON() + self.Debug=true +end + +--- Disable debug modus. +-- @param #RANGE self +function RANGE:DebugOFF() + self.Debug=false +end + + +--- Add new strafe pit. For a strafe pit, hits from guns are counted. One pit can consist of several units. +-- Note, an approach is only valid, if the player enters via a zone in front of the pit, which defined by boxlength and boxheading. +-- Furthermore, the player must not be too high and fly in the direction of the pit to make a valid target apporoach. +-- @param #RANGE self +-- @param #table unitnames Table of unit names defining the strafe targets. The first target in the list determines the approach zone (heading and box). +-- @param #number boxlength (Optional) Length of the approach box in meters. Default is 3000 m. +-- @param #number boxwidth (Optional) Width of the approach box in meters. Default is 300 m. +-- @param #number heading (Optional) Approach heading in Degrees. Default is heading of the unit as defined in the mission editor. +-- @param #boolean inverseheading (Optional) Take inverse heading (heading --> heading - 180 Degrees). Default is false. +-- @param #number goodpass (Optional) Number of hits for a "good" strafing pass. Default is 20. +-- @param #number foulline (Optional) Foul line distance. Hits from closer than this distance are not counted. Default 610 m = 2000 ft. Set to 0 for no foul line. +function RANGE:AddStrafePit(unitnames, boxlength, boxwidth, heading, inverseheading, goodpass, foulline) + self:F({unitnames=unitnames, boxlength=boxlength, boxwidth=boxwidth, heading=heading, inverseheading=inverseheading, goodpass=goodpass, foulline=foulline}) + + -- Create table if necessary. + if type(unitnames) ~= "table" then + unitnames={unitnames} + end + + -- Make targets + local _targets={} + local center=nil --Wrapper.Unit#UNIT + local ntargets=0 + + for _i,_name in ipairs(unitnames) do + + self:T(RANGE.id..string.format("Adding strafe target #%d %s", _i, _name)) + local unit=UNIT:FindByName(_name) + + if unit then + table.insert(_targets, unit) + -- Define center as the first unit we find + if center==nil then + center=unit + end + ntargets=ntargets+1 + else + local text=string.format("ERROR! Could not find strafe target with name %s.", _name) + self:E(RANGE.id..text) + MESSAGE:New(text, 10):ToAllIf(self.Debug) + end + + end + + -- Approach box dimensions. + local l=boxlength or 3000 + local w=(boxwidth or 300)/2 + + -- Heading: either manually entered or automatically taken from unit heading. + local heading=heading or center:GetHeading() + + -- Invert the heading since some units point in the "wrong" direction. In particular the strafe pit from 476th range objects. + if inverseheading ~= nil then + if inverseheading then + heading=heading-180 + end + end + if heading<0 then + heading=heading+360 + end + if heading>360 then + heading=heading-360 + end + + -- Number of hits called a "good" pass. + local goodpass=goodpass or 20 + + -- Foule line distance. + local foulline=foulline or 610 + + -- Coordinate of the range. + local Ccenter=center:GetCoordinate() + + -- Name of the target defined as its unit name. + local _name=center:GetName() + + -- Points defining the approach area. + local p={} + p[#p+1]=Ccenter:Translate( w, heading+90) + p[#p+1]= p[#p]:Translate( l, heading) + p[#p+1]= p[#p]:Translate(2*w, heading-90) + p[#p+1]= p[#p]:Translate( -l, heading) + + local pv2={} + for i,p in ipairs(p) do + pv2[i]={x=p.x, y=p.z} + end + + -- Create polygon zone. + local _polygon=ZONE_POLYGON_BASE:New(_name, pv2) + + -- Create tires + --_polygon:BoundZone() + + -- Add zone to table. + table.insert(self.strafeTargets, {name=_name, polygon=_polygon, goodPass=goodpass, targets=_targets, foulline=foulline, smokepoints=p, heading=heading}) + + -- Debug info + local text=string.format("Adding new strafe target %s with %d targets: heading = %03d, box_L = %.1f, box_W = %.1f, goodpass = %d, foul line = %.1f", _name, ntargets, heading, boxlength, boxwidth, goodpass, foulline) + self:T(RANGE.id..text) + MESSAGE:New(text, 5):ToAllIf(self.Debug) +end + +--- Add bombing target(s) to range. +-- @param #RANGE self +-- @param #table unitnames Table containing the unit names acting as bomb targets. +-- @param #number goodhitrange (Optional) Max distance from target unit (in meters) which is considered as a good hit. Default is 25 m. +-- @param #boolean static (Optional) Target is static. Default false. +function RANGE:AddBombingTargets(unitnames, goodhitrange, static) + self:F({unitnames=unitnames, goodhitrange=goodhitrange, static=static}) + + -- Create a table if necessary. + if type(unitnames) ~= "table" then + unitnames={unitnames} + end + + if static == nil or static == false then + static=false + else + static=true + end + + -- Default range is 25 m. + goodhitrange=goodhitrange or 25 + + for _,name in pairs(unitnames) do + local _unit + local _static + + if static then + + -- Add static object. Workaround since cargo objects are not yet in database because DCS function does not add those. + local _DCSstatic=StaticObject.getByName(name) + if _DCSstatic and _DCSstatic:isExist() then + self:T(RANGE.id..string.format("Adding DCS static to database. Name = %s.", name)) + _DATABASE:AddStatic(name) + else + self:E(RANGE.id..string.format("ERROR! DCS static DOES NOT exist! Name = %s.", name)) + end + + -- Now we can find it... + _static=STATIC:FindByName(name) + if _static then + self:AddBombingTargetUnit(_static, goodhitrange) + self:T(RANGE.id..string.format("Adding static bombing target %s with hit range %d.", name, goodhitrange)) + else + self:E(RANGE.id..string.format("ERROR! Cound not find static bombing target %s.", name)) + end + + else + + _unit=UNIT:FindByName(name) + if _unit then + self:AddBombingTargetUnit(_unit, goodhitrange) + self:T(RANGE.id..string.format("Adding bombing target %s with hit range %d.", name, goodhitrange)) + else + self:E(RANGE.id..string.fromat("ERROR! Could not find bombing target %s.", name)) + end + + end + + end +end + +--- Add a unit as bombing target. +-- @param #RANGE self +-- @param Wrapper.Unit#UNIT unit Unit of the strafe target. +-- @param #number goodhitrange Max distance from unit which is considered as a good hit. +function RANGE:AddBombingTargetUnit(unit, goodhitrange) + self:F({unit=unit, goodhitrange=goodhitrange}) + + local coord=unit:GetCoordinate() + local name=unit:GetName() + + -- Default range is 25 m. + goodhitrange=goodhitrange or 25 + + -- Create a zone around the unit. + local Vec2=coord:GetVec2() + local Rzone=ZONE_RADIUS:New(name, Vec2, goodhitrange) + + -- Insert target to table. + table.insert(self.bombingTargets, {name=name, point=coord, zone=Rzone, target=unit, goodhitrange=goodhitrange}) +end + + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Event Handling + +--- General event handler. +-- @param #RANGE self +-- @param #table Event DCS event table. +function RANGE:onEvent(Event) + self:F3(Event) + + if Event == nil or Event.initiator == nil or Unit.getByName(Event.initiator:getName()) == nil then + return true + end + + local DCSiniunit = Event.initiator + local DCStgtunit = Event.target + local DCSweapon = Event.weapon + + local EventData={} + local _playerunit=nil + local _playername=nil + + if Event.initiator then + EventData.IniUnitName = Event.initiator:getName() + EventData.IniDCSGroup = Event.initiator:getGroup() + EventData.IniGroupName = Event.initiator:getGroup():getName() + -- Get player unit and name. This returns nil,nil if the event was not fired by a player unit. And these are the only events we are interested in. + _playerunit, _playername = self:_GetPlayerUnitAndName(EventData.IniUnitName) + end + + if Event.target then + EventData.TgtUnitName = Event.target:getName() + EventData.TgtDCSGroup = Event.target:getGroup() + EventData.TgtGroupName = Event.target:getGroup():getName() + EventData.TgtGroup = GROUP:FindByName(EventData.TgtGroupName) + EventData.TgtUnit = UNIT:FindByName(EventData.TgtUnitName) + end + + if Event.weapon then + EventData.Weapon = Event.weapon + EventData.weapon = Event.weapon + EventData.WeaponTypeName = Event.weapon:getTypeName() + end + + -- Event info. + self:T3(RANGE.id..string.format("EVENT: Event in onEvent with ID = %s", tostring(Event.id))) + self:T3(RANGE.id..string.format("EVENT: Ini unit = %s" , tostring(EventData.IniUnitName))) + self:T3(RANGE.id..string.format("EVENT: Ini group = %s" , tostring(EventData.IniGroupName))) + self:T3(RANGE.id..string.format("EVENT: Ini player = %s" , tostring(_playername))) + self:T3(RANGE.id..string.format("EVENT: Tgt unit = %s" , tostring(EventData.TgtUnitName))) + self:T3(RANGE.id..string.format("EVENT: Tgt group = %s" , tostring(EventData.IniGroupName))) + self:T3(RANGE.id..string.format("EVENT: Wpn type = %s" , tostring(EventData.WeapoinTypeName))) + + -- Call event Birth function. + if Event.id==world.event.S_EVENT_BIRTH and _playername then + self:_OnBirth(EventData) + end + + -- Call event Shot function. + if Event.id==world.event.S_EVENT_SHOT and _playername and Event.weapon then + self:_OnShot(EventData) + end + + -- Call event Hit function. + if Event.id==world.event.S_EVENT_HIT and _playername and DCStgtunit then + self:_OnHit(EventData) + end + +end + + +--- Range event handler for event birth. +-- @param #RANGE self +-- @param Core.Event#EVENTDATA EventData +function RANGE:_OnBirth(EventData) + self:F({eventbirth = EventData}) + + local _unitName=EventData.IniUnitName + local _unit, _playername=self:_GetPlayerUnitAndName(_unitName) + + self:T3(RANGE.id.."BIRTH: unit = "..tostring(EventData.IniUnitName)) + self:T3(RANGE.id.."BIRTH: group = "..tostring(EventData.IniGroupName)) + self:T3(RANGE.id.."BIRTH: player = "..tostring(_playername)) + + if _unit and _playername then + + local _uid=_unit:GetID() + local _group=_unit:GetGroup() + local _gid=_group:GetID() + local _callsign=_unit:GetCallsign() + + -- Debug output. + local text=string.format("Player %s, callsign %s entered unit %s (UID %d) of group %s (GID %d)", _playername, _callsign, _unitName, _uid, _group:GetName(), _gid) + self:T(RANGE.id..text) + MESSAGE:New(text, 5):ToAllIf(self.Debug) + + -- Reset current strafe status. + self.strafeStatus[_uid] = nil + + -- Add Menu commands. + self:_AddF10Commands(_unitName) + + -- By default, some bomb impact points and do not flare each hit on target. + self.PlayerSettings[_playername]={} + self.PlayerSettings[_playername].smokebombimpact=true + self.PlayerSettings[_playername].flaredirecthits=false + self.PlayerSettings[_playername].smokecolor=SMOKECOLOR.Blue + self.PlayerSettings[_playername].flarecolor=FLARECOLOR.Red + self.PlayerSettings[_playername].delaysmoke=true + + -- Start check in zone timer. + if self.planes[_uid] ~= true then + SCHEDULER:New(nil, self._CheckInZone, {self, EventData.IniUnitName}, 1, 1) + self.planes[_uid] = true + end + + end +end + +--- Range event handler for event hit. +-- @param #RANGE self +-- @param Core.Event#EVENTDATA EventData +function RANGE:_OnHit(EventData) + self:F({eventhit = EventData}) + + -- Player info + local _unitName = EventData.IniUnitName + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + local _unitID = _unit:GetID() + + -- Target + local target = EventData.TgtUnit + local targetname = EventData.TgtUnitName + + -- Debug info. + self:T3(RANGE.id.."HIT: Ini unit = "..tostring(EventData.IniUnitName)) + self:T3(RANGE.id.."HIT: Ini group = "..tostring(EventData.IniGroupName)) + self:T3(RANGE.id.."HIT: Tgt target = "..tostring(EventData.TgtUnitName)) + self:T3(RANGE.id.."HIT: Tgt group = "..tostring(EventData.TgtGroupName)) + + -- Current strafe target of player. + local _currentTarget = self.strafeStatus[_unitID] + + -- Player has rolled in on a strafing target. + if _currentTarget then + + local playerPos = _unit:GetCoordinate() + local targetPos = target:GetCoordinate() + + -- Loop over valid targets for this run. + for _,_target in pairs(_currentTarget.zone.targets) do + + -- Check the the target is the same that was actually hit. + if _target:GetName() == targetname then + + -- Get distance between player and target. + local dist=playerPos:Get2DDistance(targetPos) + + if dist > _currentTarget.zone.foulline then + -- Increase hit counter of this run. + _currentTarget.hits = _currentTarget.hits + 1 + + -- Flare target. + if _unit and _playername and self.PlayerSettings[_playername].flaredirecthits then + targetPos:Flare(self.PlayerSettings[_playername].flarecolor) + end + else + -- Too close to the target. + if _currentTarget.pastfoulline==false and _unit and _playername then + local _d=_currentTarget.zone.foulline + local text=string.format("%s, Invalid hit!\nYou already passed foul line distance of %d m for target %s.", self:_myname(_unitName), _d, targetname) + self:_DisplayMessageToGroup(_unit, text, 10) + self:T2(RANGE.id..text) + _currentTarget.pastfoulline=true + end + end + + end + end + end + + -- Bombing Targets + for _,_target in pairs(self.bombingTargets) do + + -- Check if one of the bomb targets was hit. + if _target.name == targetname then + + if _unit and _playername then + + local playerPos = _unit:GetCoordinate() + local targetPos = target:GetCoordinate() + + -- Message to player. + --local text=string.format("%s, direct hit on target %s.", self:_myname(_unitName), targetname) + --self:DisplayMessageToGroup(_unit, text, 10, true) + + -- Flare target. + if self.PlayerSettings[_playername].flaredirecthits then + targetPos:Flare(self.PlayerSettings[_playername].flarecolor) + end + + end + end + end +end + +--- Range event handler for event shot (when a unit releases a rocket or bomb (but not a fast firing gun). +-- @param #RANGE self +-- @param Core.Event#EVENTDATA EventData +function RANGE:_OnShot(EventData) + self:F({eventshot = EventData}) + + -- Weapon data. + local _weapon = EventData.Weapon:getTypeName() -- should be the same as Event.WeaponTypeName + local _weaponStrArray = self:_split(_weapon,"%.") + local _weaponName = _weaponStrArray[#_weaponStrArray] + + -- Debug info. + self:T3(RANGE.id.."EVENT SHOT: Ini unit = "..EventData.IniUnitName) + self:T3(RANGE.id.."EVENT SHOT: Ini group = "..EventData.IniGroupName) + self:T3(RANGE.id.."EVENT SHOT: Weapon type = ".._weapon) + self:T3(RANGE.id.."EVENT SHOT: Weapon name = ".._weaponName) + + -- Monitor only bombs and rockets. + if (string.match(_weapon, "weapons.bombs") or string.match(_weapon, "weapons.nurs")) then + + -- Weapon + local _ordnance = EventData.weapon + + -- Tracking info and init of last bomb position. + self:T(RANGE.id..string.format("Tracking %s - %s.", _weapon, _ordnance:getName())) + + -- Init bomb position. + local _lastBombPos = {x=0,y=0,z=0} + + -- Get unit name. + local _unitName = EventData.IniUnitName + + -- Function monitoring the position of a bomb until impact. + local function trackBomb(_previousPos) + + -- Get player unit and name. + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + local _callsign=self:_myname(_unitName) + + if _unit and _playername then + + -- When the pcall returns a failure the weapon has hit. + local _status,_bombPos = pcall( + function() + return _ordnance:getPoint() + end) + + if _status then + + -- Still in the air. Remember this position. + _lastBombPos = {x = _bombPos.x, y = _bombPos.y, z= _bombPos.z } + + -- Check again in 0.005 seconds. + return timer.getTime() + self.dtBombtrack + + else + + -- Bomb did hit the ground. + -- Get closet target to last position. + local _closetTarget = nil + local _distance = nil + local _hitquality = "POOR" + + -- Coordinate of impact point. + local impactcoord=COORDINATE:NewFromVec3(_lastBombPos) + + -- Distance from range. We dont want to smoke targets outside of the range. + local impactdist=impactcoord:Get2DDistance(self.location) + + -- Smoke impact point of bomb. + if self.PlayerSettings[_playername].smokebombimpact and impactdist b.hits end + table.sort(_results,_sort) + + -- Prepare message of best results. + local _bestMsg = "" + local _count = 1 + + -- Loop over results + for _,_result in pairs(_results) do + + -- Message text. + _message = _message..string.format("\n[%d] Hits %d - %s - %s", _count, _result.hits, _result.zone.name, _result.text) + + -- Best result. + if _bestMsg == "" then + _bestMsg = string.format("Hits %d - %s - %s", _result.hits, _result.zone.name, _result.text) + end + + -- 10 runs + if _count == self.ndisplayresult then + break + end + + -- Increase counter + _count = _count+1 + end + + -- Message text. + _message = _message .."\n\nBEST: ".._bestMsg + end + + -- Send message to group. + self:_DisplayMessageToGroup(_unit, _message, nil, true) + end +end + +--- Display top 10 strafing results of all players. +-- @param #RANGE self +-- @param #string _unitName Name fo the player unit. +function RANGE:_DisplayStrafePitResults(_unitName) + self:F(_unitName) + + -- Get player unit and name. + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + + -- Check if we have a unit which is a player. + if _unit and _playername then + + -- Results table. + local _playerResults = {} + + -- Message text. + local _message = string.format("Strafe Pit Results - Top %d Players:\n", self.ndisplayresult) + + -- Loop over player results. + for _playerName,_results in pairs(self.strafePlayerResults) do + + -- Get the best result of the player. + local _best = nil + for _,_result in pairs(_results) do + if _best == nil or _result.hits > _best.hits then + _best = _result + end + end + + -- Add best result to table. + if _best ~= nil then + local text=string.format("%s: Hits %i - %s - %s", _playerName, _best.hits, _best.zone.name, _best.text) + table.insert(_playerResults,{msg = text, hits = _best.hits}) + end + + end + + --Sort list! + local _sort = function( a,b ) return a.hits > b.hits end + table.sort(_playerResults,_sort) + + -- Add top 10 results. + for _i = 1, math.min(#_playerResults, self.ndisplayresult) do + _message = _message..string.format("\n[%d] %s", _i, _playerResults[_i].msg) + end + + -- In case there are no scores yet. + if #_playerResults<1 then + _message = _message.."No player scored yet." + end + + -- Send message. + self:_DisplayMessageToGroup(_unit, _message, nil, true) + end +end + +--- Display top 10 bombing run results of specific player. +-- @param #RANGE self +-- @param #string _unitName Name of the player unit. +function RANGE:_DisplayMyBombingResults(_unitName) + self:F(_unitName) + + -- Get player unit and name. + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + + if _unit and _playername then + + -- Init message. + local _message = string.format("My Top %d Bombing Results:\n", self.ndisplayresult) + + -- Results from player. + local _results = self.bombPlayerResults[_playername] + + -- No score so far. + if _results == nil then + _message = _playername..": No Score yet." + else + + -- Sort results wrt to distance. + local _sort = function( a,b ) return a.distance < b.distance end + table.sort(_results,_sort) + + -- Loop over results. + local _bestMsg = "" + local _count = 1 + for _,_result in pairs(_results) do + + -- Message with name, weapon and distance. + _message = _message.."\n"..string.format("[%d] %d m - %s - %s - %s hit", _count, _result.distance, _result.name, _result.weapon, _result.quality) + + -- Store best/first result. + if _bestMsg == "" then + _bestMsg = string.format("%d m - %s - %s - %s hit",_result.distance,_result.name,_result.weapon, _result.quality) + end + + -- Best 10 runs only. + if _count == self.ndisplayresult then + break + end + + -- Increase counter. + _count = _count+1 + end + + -- Message. + _message = _message .."\n\nBEST: ".._bestMsg + end + + -- Send message. + self:_DisplayMessageToGroup(_unit, _message, nil, true) + end +end + +--- Display best bombing results of top 10 players. +-- @param #RANGE self +-- @param #string _unitName Name of player unit. +function RANGE:_DisplayBombingResults(_unitName) + self:F(_unitName) + + -- Results table. + local _playerResults = {} + + -- Get player unit and name. + local _unit, _player = self:_GetPlayerUnitAndName(_unitName) + + -- Check if we have a unit with a player. + if _unit and _player then + + -- Message header. + local _message = string.format("Bombing Results - Top %d Players:\n", self.ndisplayresult) + + -- Loop over players. + for _playerName,_results in pairs(self.bombPlayerResults) do + + -- Find best result of player. + local _best = nil + for _,_result in pairs(_results) do + if _best == nil or _result.distance < _best.distance then + _best = _result + end + end + + -- Put best result of player into table. + if _best ~= nil then + local bestres=string.format("%s: %d m - %s - %s - %s hit", _playerName, _best.distance, _best.name, _best.weapon, _best.quality) + table.insert(_playerResults, {msg = bestres, distance = _best.distance}) + end + + end + + -- Sort list of player results. + local _sort = function( a,b ) return a.distance < b.distance end + table.sort(_playerResults,_sort) + + -- Loop over player results. + for _i = 1, math.min(#_playerResults, self.ndisplayresult) do + _message = _message..string.format("\n[%d] %s", _i, _playerResults[_i].msg) + end + + -- In case there are no scores yet. + if #_playerResults<1 then + _message = _message.."No player scored yet." + end + + -- Send message. + self:_DisplayMessageToGroup(_unit, _message, nil, true) + end +end + +--- Report information like bearing and range from player unit to range. +-- @param #RANGE self +-- @param #string _unitname Name of the player unit. +function RANGE:_DisplayRangeInfo(_unitname) + self:F(_unitname) + + -- Get player unit and player name. + local unit, playername = self:_GetPlayerUnitAndName(_unitname) + + -- Check if we have a player. + if unit and playername then + + -- Message text. + local text="" + + -- Current coordinates. + local coord=unit:GetCoordinate() + + if self.location then + + -- Direction vector from current position (coord) to target (position). + local position=self.location --Core.Point#COORDINATE + local rangealt=position:GetLandHeight() + local vec3=coord:GetDirectionVec3(position) + local angle=coord:GetAngleDegrees(vec3) + local range=coord:Get2DDistance(position) + + -- Bearing string. + local Bs=string.format('%03d°', angle) + + local texthit + if self.PlayerSettings[playername].flaredirecthits then + texthit=string.format("Flare direct hits: ON (flare color %s)\n", self:_flarecolor2text(self.PlayerSettings[playername].flarecolor)) + else + texthit=string.format("Flare direct hits: OFF\n") + end + local textbomb + if self.PlayerSettings[playername].smokebombimpact then + textbomb=string.format("Smoke bomb impact points: ON (smoke color %s)\n", self:_smokecolor2text(self.PlayerSettings[playername].smokecolor)) + else + textbomb=string.format("Smoke bomb impact points: OFF\n") + end + local textdelay + if self.PlayerSettings[playername].delaysmoke then + textdelay=string.format("Smoke bomb delay: ON (delay %.1f seconds)", self.TdelaySmoke) + else + textdelay=string.format("Smoke bomb delay: OFF") + end + + -- Player unit settings. + local settings=_DATABASE:GetPlayerSettings(playername) or _SETTINGS --Core.Settings#SETTINGS + local trange=string.format("%.1f km", range/1000) + local trangealt=string.format("%d m", rangealt) + local tstrafemaxalt=string.format("%d m", self.strafemaxalt) + if settings:IsImperial() then + trange=string.format("%.1f NM", UTILS.MetersToNM(range)) + trangealt=string.format("%d feet", UTILS.MetersToFeet(rangealt)) + tstrafemaxalt=string.format("%d feet", UTILS.MetersToFeet(self.strafemaxalt)) + end + + -- Message. + text=text..string.format("Information on %s:\n", self.rangename) + text=text..string.format("-------------------------------------------------------\n") + text=text..string.format("Bearing %s, Range %s\n", Bs, trange) + text=text..string.format("Altitude ASL: %s\n", trangealt) + text=text..string.format("Max strafing alt AGL: %s\n", tstrafemaxalt) + text=text..string.format("# of strafe targets: %d\n", self.nstrafetargets) + text=text..string.format("# of bomb targets: %d\n", self.nbombtargets) + text=text..texthit + text=text..textbomb + text=text..textdelay + + -- Send message to player group. + self:_DisplayMessageToGroup(unit, text, nil, true) + + -- Debug output. + self:T2(RANGE.id..text) + end + end +end + +--- Report weather conditions at range. Temperature, QFE pressure and wind data. +-- @param #RANGE self +-- @param #string _unitname Name of the player unit. +function RANGE:_DisplayRangeWeather(_unitname) + self:F(_unitname) + + -- Get player unit and player name. + local unit, playername = self:_GetPlayerUnitAndName(_unitname) + + -- Check if we have a player. + if unit and playername then + + -- Message text. + local text="" + + -- Current coordinates. + local coord=unit:GetCoordinate() + + if self.location then + + -- Get atmospheric data at range location. + local position=self.location --Core.Point#COORDINATE + local T=position:GetTemperature() + local P=position:GetPressure() + local Wd,Ws=position:GetWind() + + -- Get Beaufort wind scale. + local Bn,Bd=UTILS.BeaufortScale(Ws) + + local WD=string.format('%03d°', Wd) + local Ts=string.format("%d°C",T) + + local hPa2inHg=0.0295299830714 + local hPa2mmHg=0.7500615613030 + + local settings=_DATABASE:GetPlayerSettings(playername) or _SETTINGS --Core.Settings#SETTINGS + local tT=string.format("%d°C",T) + local tW=string.format("%.1f m/s", Ws) + local tP=string.format("%.1f mmHg", P*hPa2mmHg) + if settings:IsImperial() then + tT=string.format("%d°F", UTILS.CelciusToFarenheit(T)) + tW=string.format("%.1f knots", UTILS.MpsToKnots(Ws)) + tP=string.format("%.2f inHg", P*hPa2inHg) + end + + + -- Message text. + text=text..string.format("Weather Report at %s:\n", self.rangename) + text=text..string.format("--------------------------------------------------\n") + text=text..string.format("Temperature %s\n", tT) + text=text..string.format("Wind from %s at %s (%s)\n", WD, tW, Bd) + text=text..string.format("QFE %.1f hPa = %s", P, tP) + else + text=string.format("No range location defined for range %s.", self.rangename) + end + + -- Send message to player group. + self:_DisplayMessageToGroup(unit, text, nil, true) + + -- Debug output. + self:T2(RANGE.id..text) + else + self:T(RANGE.id..string.format("ERROR! Could not find player unit in RangeInfo! Name = %s", _unitname)) + end +end + +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Timer Functions + +--- Check if player is inside a strafing zone. If he is, we start looking for hits. If he was and left the zone again, the result is stored. +-- @param #RANGE self +-- @param #string _unitName Name of player unit. +function RANGE:_CheckInZone(_unitName) + self:F(_unitName) + + -- Get player unit and name. + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + + if _unit and _playername then + + -- Current position of player unit. + local _unitID = _unit:GetID() + + -- Currently strafing? (strafeStatus is nil if not) + local _currentStrafeRun = self.strafeStatus[_unitID] + + if _currentStrafeRun then -- player has already registered for a strafing run. + + -- Get the current approach zone and check if player is inside. + local zone=_currentStrafeRun.zone.polygon --Core.Zone#ZONE_POLYGON_BASE + + local unitheading = _unit:GetHeading() + local pitheading = _currentStrafeRun.zone.heading - 180 + local deltaheading = unitheading-pitheading + local towardspit = math.abs(deltaheading)<=90 or math.abs(deltaheading-360)<=90 + local unitalt=_unit:GetHeight()-_unit:GetCoordinate():GetLandHeight() + + -- Check if unit is inside zone and below max height AGL. + local unitinzone=_unit:IsInZone(zone) and unitalt <= self.strafemaxalt and towardspit + + -- Debug output + local text=string.format("Checking stil in zone. Unit = %s, player = %s in zone = %s. alt = %d, delta heading = %d", _unitName, _playername, tostring(unitinzone), unitalt, deltaheading) + self:T(RANGE.id..text) + + -- Check if player is in strafe zone and below max alt. + if unitinzone then + + -- Still in zone, keep counting hits. Increase counter. + _currentStrafeRun.time = _currentStrafeRun.time+1 + + else + + -- Increase counter + _currentStrafeRun.time = _currentStrafeRun.time+1 + + if _currentStrafeRun.time <= 3 then + + -- Reset current run. + self.strafeStatus[_unitID] = nil + + -- Message text. + local _msg = string.format("%s left strafing zone %s too quickly. No Score.", _playername, _currentStrafeRun.zone.name) + + -- Send message. + self:_DisplayMessageToGroup(_unit, _msg, nil, true) + + else + + -- Result. + local _result = self.strafeStatus[_unitID] + + -- Judge this pass. Text is displayed on summary. + if _result.hits >= _result.zone.goodPass*2 then + _result.text = "EXCELLENT PASS" + elseif _result.hits >= _result.zone.goodPass then + _result.text = "GOOD PASS" + elseif _result.hits >= _result.zone.goodPass/2 then + _result.text = "INEFFECTIVE PASS" + else + _result.text = "POOR PASS" + end + + -- Message text. + local _text=string.format("%s, %s with %d hits on target %s.", self:_myname(_unitName), _result.text, _result.hits, _result.zone.name) + + -- Send message. + self:_DisplayMessageToGroup(_unit, _text) + + -- Set strafe status to nil. + self.strafeStatus[_unitID] = nil + + -- Save stats so the player can retrieve them. + local _stats = self.strafePlayerResults[_playername] or {} + table.insert(_stats, _result) + self.strafePlayerResults[_playername] = _stats + end + + end + + else + + -- Check to see if we're in any of the strafing zones (first time). + for _,_targetZone in pairs(self.strafeTargets) do + + -- Get the current approach zone and check if player is inside. + local zonenname=_targetZone.name + local zone=_targetZone.polygon --Core.Zone#ZONE_POLYGON_BASE + + -- Check if player is in zone and below max alt and flying towards the target. + local unitheading = _unit:GetHeading() + local pitheading = _targetZone.heading - 180 + local deltaheading = unitheading-pitheading + local towardspit = math.abs(deltaheading)<=90 or math.abs(deltaheading-360)<=90 + local unitalt =_unit:GetHeight()-_unit:GetCoordinate():GetLandHeight() + + -- Check if unit is inside zone and below max height AGL. + local unitinzone=_unit:IsInZone(zone) and unitalt <= self.strafemaxalt and towardspit + + -- Debug info. + local text=string.format("Checking zone %s. Unit = %s, player = %s in zone = %s. alt = %d, delta heading = %d", _targetZone.name, _unitName, _playername, tostring(unitinzone), unitalt, deltaheading) + self:T(RANGE.id..text) + + -- Player is inside zone. + if unitinzone then + + -- Init strafe status for this player. + self.strafeStatus[_unitID] = {hits = 0, zone = _targetZone, time = 1, pastfoulline=false } + + -- Rolling in! + local _msg=string.format("%s, rolling in on strafe pit %s.", self:_myname(_unitName), _targetZone.name) + + -- Send message. + self:_DisplayMessageToGroup(_unit, _msg, 10, true) + + -- We found our player. Skip remaining checks. + break + + end -- unit in zone check + + end -- loop over zones + end + end + +end + +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Menu Functions + +--- Add menu commands for player. +-- @param #RANGE self +-- @param #string _unitName Name of player unit. +function RANGE:_AddF10Commands(_unitName) + self:F(_unitName) + + -- Get player unit and name. + local _unit, playername = self:_GetPlayerUnitAndName(_unitName) + + -- Check for player unit. + if _unit and playername then + + -- Get group and ID. + local group=_unit:GetGroup() + local _gid=group:GetID() + + if group and _gid then + + if not self.MenuAddedTo[_gid] then + + -- Enable switch so we don't do this twice. + self.MenuAddedTo[_gid] = true + + -- Main F10 menu: F10/On the Range + local _rootPath = missionCommands.addSubMenuForGroup(_gid, "On the Range") + local _rangePath = missionCommands.addSubMenuForGroup(_gid, self.rangename, _rootPath) + local _statsPath = missionCommands.addSubMenuForGroup(_gid, "Statistics", _rangePath) + local _markPath = missionCommands.addSubMenuForGroup(_gid, "Mark Targets", _rangePath) + local _settingsPath = missionCommands.addSubMenuForGroup(_gid, "My Settings", _rangePath) + -- F10/On the Range/My Settings/ + local _mysmokePath = missionCommands.addSubMenuForGroup(_gid, "Smoke Color", _settingsPath) + local _myflarePath = missionCommands.addSubMenuForGroup(_gid, "Flare Color", _settingsPath) + + + --TODO: Convert to MOOSE menu. + -- F10/On the Range/Mark Targets/ + missionCommands.addCommandForGroup(_gid, "Mark On Map", _markPath, self._MarkTargetsOnMap, self, _unitName) + missionCommands.addCommandForGroup(_gid, "Illuminate Range", _markPath, self._IlluminateBombTargets, self, _unitName) + missionCommands.addCommandForGroup(_gid, "Smoke Strafe Pits", _markPath, self._SmokeStrafeTargetBoxes, self, _unitName) + missionCommands.addCommandForGroup(_gid, "Smoke Strafe Tgts", _markPath, self._SmokeStrafeTargets, self, _unitName) + missionCommands.addCommandForGroup(_gid, "Smoke Bomb Tgts", _markPath, self._SmokeBombTargets, self, _unitName) + -- F10/On the Range/Stats/ + missionCommands.addCommandForGroup(_gid, "All Strafe Results", _statsPath, self._DisplayStrafePitResults, self, _unitName) + missionCommands.addCommandForGroup(_gid, "All Bombing Results", _statsPath, self._DisplayBombingResults, self, _unitName) + missionCommands.addCommandForGroup(_gid, "My Strafe Results", _statsPath, self._DisplayMyStrafePitResults, self, _unitName) + missionCommands.addCommandForGroup(_gid, "My Bomb Results", _statsPath, self._DisplayMyBombingResults, self, _unitName) + missionCommands.addCommandForGroup(_gid, "Reset All Stats", _statsPath, self._ResetRangeStats, self, _unitName) + -- F10/On the Range/My Settings/Smoke Color/ + missionCommands.addCommandForGroup(_gid, "Blue Smoke", _mysmokePath, self._playersmokecolor, self, _unitName, SMOKECOLOR.Blue) + missionCommands.addCommandForGroup(_gid, "Green Smoke", _mysmokePath, self._playersmokecolor, self, _unitName, SMOKECOLOR.Green) + missionCommands.addCommandForGroup(_gid, "Orange Smoke", _mysmokePath, self._playersmokecolor, self, _unitName, SMOKECOLOR.Orange) + missionCommands.addCommandForGroup(_gid, "Red Smoke", _mysmokePath, self._playersmokecolor, self, _unitName, SMOKECOLOR.Red) + missionCommands.addCommandForGroup(_gid, "White Smoke", _mysmokePath, self._playersmokecolor, self, _unitName, SMOKECOLOR.White) + -- F10/On the Range/My Settings/Flare Color/ + missionCommands.addCommandForGroup(_gid, "Green Flares", _myflarePath, self._playerflarecolor, self, _unitName, FLARECOLOR.Green) + missionCommands.addCommandForGroup(_gid, "Red Flares", _myflarePath, self._playerflarecolor, self, _unitName, FLARECOLOR.Red) + missionCommands.addCommandForGroup(_gid, "White Flares", _myflarePath, self._playerflarecolor, self, _unitName, FLARECOLOR.White) + missionCommands.addCommandForGroup(_gid, "Yellow Flares", _myflarePath, self._playerflarecolor, self, _unitName, FLARECOLOR.Yellow) + -- F10/On the Range/My Settings/ + missionCommands.addCommandForGroup(_gid, "Smoke Delay On/Off", _settingsPath, self._SmokeBombDelayOnOff, self, _unitName) + missionCommands.addCommandForGroup(_gid, "Smoke Impact On/Off", _settingsPath, self._SmokeBombImpactOnOff, self, _unitName) + missionCommands.addCommandForGroup(_gid, "Flare Hits On/Off", _settingsPath, self._FlareDirectHitsOnOff, self, _unitName) + -- F10/On the Range/ + missionCommands.addCommandForGroup(_gid, "Range Information", _rangePath, self._DisplayRangeInfo, self, _unitName) + missionCommands.addCommandForGroup(_gid, "Weather Report", _rangePath, self._DisplayRangeWeather, self, _unitName) + end + else + self:T(RANGE.id.."Could not find group or group ID in AddF10Menu() function. Unit name: ".._unitName) + end + else + self:T(RANGE.id.."Player unit does not exist in AddF10Menu() function. Unit name: ".._unitName) + end + +end + +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Helper Functions + +--- Mark targets on F10 map. +-- @param #RANGE self +-- @param #string _unitName Name of the player unit. +function RANGE:_MarkTargetsOnMap(_unitName) + self:F(_unitName) + + -- Get group. + local group=UNIT:FindByName(_unitName):GetGroup() + + if group then + + -- Mark bomb targets. + for _,_target in pairs(self.bombingTargets) do + local coord=_target.point --Core.Point#COORDINATE + coord:MarkToGroup("Bomb target ".._target.name, group) + end + + -- Mark strafe targets. + for _,_strafepit in pairs(self.strafeTargets) do + for _,_target in pairs(_strafepit.targets) do + local coord=_target:GetCoordinate() --Core.Point#COORDINATE + coord:MarkToGroup("Strafe target ".._target:GetName(), group) + end + end + + if _unitName then + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + local text=string.format("%s, %s, range targets are now marked on F10 map.", self.rangename, _playername) + self:_DisplayMessageToGroup(_unit, text, 5) + end + + end +end + +--- Illuminate targets. Fires illumination bombs at one random bomb and one random strafe target at a random altitude between 400 and 800 m. +-- @param #RANGE self +-- @param #string _unitName (Optional) Name of the player unit. +function RANGE:_IlluminateBombTargets(_unitName) + self:F(_unitName) + + -- All bombing target coordinates. + local bomb={} + + for _,_target in pairs(self.bombingTargets) do + local coord=_target.point --Core.Point#COORDINATE + table.insert(bomb, coord) + end + + if #bomb>0 then + local coord=bomb[math.random(#bomb)] --Core.Point#COORDINATE + local c=COORDINATE:New(coord.x,coord.y+math.random(self.illuminationminalt,self.illuminationmaxalt),coord.z) + c:IlluminationBomb() + end + + -- All strafe target coordinates. + local strafe={} + + for _,_strafepit in pairs(self.strafeTargets) do + for _,_target in pairs(_strafepit.targets) do + local coord=_target:GetCoordinate() --Core.Point#COORDINATE + table.insert(strafe, coord) + end + end + + -- Pick a random strafe target. + if #strafe>0 then + local coord=strafe[math.random(#strafe)] --Core.Point#COORDINATE + local c=COORDINATE:New(coord.x,coord.y+math.random(self.illuminationminalt,self.illuminationmaxalt),coord.z) + c:IlluminationBomb() + end + + if _unitName then + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + local text=string.format("%s, %s, range targets are illuminated.", self.rangename, _playername) + self:_DisplayMessageToGroup(_unit, text, 5) + end +end + +--- Reset player statistics. +-- @param #RANGE self +-- @param #string _unitName Name of the player unit. +function RANGE:_ResetRangeStats(_unitName) + self:F(_unitName) + + -- Get player unit and name. + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + + if _unit and _playername then + self.strafePlayerResults[_playername] = nil + self.bombPlayerResults[_playername] = nil + local text=string.format("%s, %s, your range stats were cleared.", self.rangename, _playername) + self:DisplayMessageToGroup(_unit, text, 5) + end +end + +--- Display message to group. +-- @param #RANGE self +-- @param Wrapper.Unit#UNIT _unit Player unit. +-- @param #string _text Message text. +-- @param #number _time Duration how long the message is displayed. +-- @param #boolean _clear Clear up old messages. +function RANGE:_DisplayMessageToGroup(_unit, _text, _time, _clear) + self:F({unit=_unit, text=_text, time=_time, clear=_clear}) + + _time=_time or self.Tmsg + if _clear==nil then + _clear=false + end + + -- Group ID. + local _gid=_unit:GetGroup():GetID() + + if _gid then + if _clear == true then + trigger.action.outTextForGroup(_gid, _text, _time, _clear) + else + trigger.action.outTextForGroup(_gid, _text, _time) + end + end + +end + +--- Toggle status of smoking bomb impact points. +-- @param #RANGE self +-- @param #string unitname Name of the player unit. +function RANGE:_SmokeBombImpactOnOff(unitname) + self:F(unitname) + + local unit, playername = self:_GetPlayerUnitAndName(unitname) + if unit and playername then + local text + if self.PlayerSettings[playername].smokebombimpact==true then + self.PlayerSettings[playername].smokebombimpact=false + text=string.format("%s, %s, smoking impact points of bombs is now OFF.", self.rangename, playername) + else + self.PlayerSettigs[playername].smokebombimpact=true + text=string.format("%s, %s, smoking impact points of bombs is now ON.", self.rangename, playername) + end + self:_DisplayMessageToGroup(unit, text, 5) + end + +end + +--- Toggle status of time delay for smoking bomb impact points +-- @param #RANGE self +-- @param #string unitname Name of the player unit. +function RANGE:_SmokeBombDelayOnOff(unitname) + self:F(unitname) + + local unit, playername = self:_GetPlayerUnitAndName(unitname) + if unit and playername then + local text + if self.PlayerSettings[playername].delaysmoke==true then + self.PlayerSettings[playername].delaysmoke=false + text=string.format("%s, %s, delayed smoke of bombs is now OFF.", self.rangename, playername) + else + self.PlayerSettigs[playername].delaysmoke=true + text=string.format("%s, %s, delayed smoke of bombs is now ON.", self.rangename, playername) + end + self:_DisplayMessageToGroup(unit, text, 5) + end + +end + +--- Toggle status of flaring direct hits of range targets. +-- @param #RANGE self +-- @param #string unitname Name of the player unit. +function RANGE:_FlareDirectHitsOnOff(unitname) + self:F(unitname) + + local unit, playername = self:_GetPlayerUnitAndName(unitname) + if unit and playername then + local text + if self.PlayerSettings[playername].flaredirecthits==true then + self.PlayerSettings[playername].flaredirecthits=false + text=string.format("%s, %s, flaring direct hits is now OFF.", self.rangename, playername) + else + self.PlayerSettings[playername].flaredirecthits=true + text=string.format("%s, %s, flaring direct hits is now ON.", self.rangename, playername) + end + self:_DisplayMessageToGroup(unit, text, 5) + end + +end + +--- Mark bombing targets with smoke. +-- @param #RANGE self +-- @param #string unitname Name of the player unit. +function RANGE:_SmokeBombTargets(unitname) + self:F(unitname) + + for _,_target in pairs(self.bombingTargets) do + local coord = _target.point --Core.Point#COORDINATE + coord:Smoke(self.BombSmokeColor) + end + + if unitname then + local unit, playername = self:_GetPlayerUnitAndName(unitname) + local text=string.format("%s, %s, bombing targets are now marked with %s smoke.", self.rangename, playername, self:_smokecolor2text(self.BombSmokeColor)) + self:_DisplayMessageToGroup(unit, text, 5) + end + +end + +--- Mark strafing targets with smoke. +-- @param #RANGE self +-- @param #string unitname Name of the player unit. +function RANGE:_SmokeStrafeTargets(unitname) + self:F(unitname) + + for _,_target in pairs(self.strafeTargets) do + for _,_unit in pairs(_target.targets) do + local coord = _unit:GetCoordinate() --Core.Point#COORDINATE + coord:Smoke(self.StrafeSmokeColor) + end + end + + if unitname then + local unit, playername = self:_GetPlayerUnitAndName(unitname) + local text=string.format("%s, %s, strafing tragets are now marked with %s smoke.", self.rangename, playername, self:_smokecolor2text(self.StrafeSmokeColor)) + self:_DisplayMessageToGroup(unit, text, 5) + end + +end + +--- Mark approach boxes of strafe targets with smoke. +-- @param #RANGE self +-- @param #string unitname Name of the player unit. +function RANGE:_SmokeStrafeTargetBoxes(unitname) + self:F(unitname) + + for _,_target in pairs(self.strafeTargets) do + local zone=_target.polygon --Core.Zone#ZONE + zone:SmokeZone(self.StrafePitSmokeColor) + for _,_point in pairs(_target.smokepoints) do + _point:SmokeOrange() --Corners are smoked orange. + end + end + + if unitname then + local unit, playername = self:_GetPlayerUnitAndName(unitname) + local text=string.format("%s, %s, strafing pit approach boxes are now marked with %s smoke.", self.rangename, playername, self:_smokecolor2text(self.StrafePitSmokeColor)) + self:_DisplayMessageToGroup(unit, text, 5) + end + +end + +--- Sets the smoke color used to smoke players bomb impact points. +-- @param #RANGE self +-- @param #string _unitName Name of the player unit. +-- @param Utilities.Utils#SMOKECOLOR color ID of the smoke color. +function RANGE:_playersmokecolor(_unitName, color) + self:F({unitname=_unitName, color=color}) + + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + if _unit and _playername then + self.PlayerSettings[_playername].smokecolor=color + local text=string.format("%s, %s, your bomb impacts are now smoked in %s.", self.rangename, _playername, self:_smokecolor2text(color)) + self:_DisplayMessageToGroup(_unit, text, 5) + end + +end + +--- Sets the flare color used when player makes a direct hit on target. +-- @param #RANGE self +-- @param #string _unitName Name of the player unit. +-- @param Utilities.Utils#FLARECOLOR color ID of flare color. +function RANGE:_playerflarecolor(_unitName, color) + self:F({unitname=_unitName, color=color}) + + local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) + if _unit and _playername then + self.PlayerSettings[_playername].flarecolor=color + local text=string.format("%s, %s, your direct hits are now flared in %s.", self.rangename, _playername, self:_flarecolor2text(color)) + self:_DisplayMessageToGroup(_unit, text, 5) + end + +end + +--- Converts a smoke color id to text. E.g. SMOKECOLOR.Blue --> "blue". +-- @param #RANGE self +-- @param Utilities.Utils#SMOKECOLOR color Color Id. +-- @return #string Color text. +function RANGE:_smokecolor2text(color) + self:F(color) + + local txt="" + if color==SMOKECOLOR.Blue then + txt="blue" + elseif color==SMOKECOLOR.Green then + txt="green" + elseif color==SMOKECOLOR.Orange then + txt="orange" + elseif color==SMOKECOLOR.Red then + txt="red" + elseif color==SMOKECOLOR.White then + txt="white" + else + txt=string.format("unkown color (%s)", tostring(color)) + end + + return txt +end + +--- Sets the flare color used to flare players direct target hits. +-- @param #RANGE self +-- @param Utilities.Utils#FLARECOLOR color Color Id. +-- @return #string Color text. +function RANGE:_flarecolor2text(color) + self:F(color) + + local txt="" + if color==FLARECOLOR.Green then + txt="green" + elseif color==FLARECOLOR.Red then + txt="red" + elseif color==FLARECOLOR.White then + txt="white" + elseif color==FLARECOLOR.Yellow then + txt="yellow" + else + txt=string.format("unkown color (%s)", tostring(color)) + end + + return txt +end + +--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned. +-- @param #RANGE self +-- @param #string _unitName Name of the player unit. +-- @return Wrapper.Unit#UNIT Unit of player. +-- @return #string Name of the player. +-- @return nil If player does not exist. +function RANGE:_GetPlayerUnitAndName(_unitName) + self:F(_unitName) + + if _unitName ~= nil then + local DCSunit=Unit.getByName(_unitName) + local playername=DCSunit:getPlayerName() + local unit=UNIT:Find(DCSunit) + + self:T({DCSunit=DCSunit, unit=unit, playername=playername}) + if DCSunit and unit and playername then + return unit, playername + end + end + + return nil,nil +end + +--- Returns a string which consits of this callsign and the player name. +-- @param #RANGE self +-- @param #string unitname Name of the player unit. +function RANGE:_myname(unitname) + self:F(unitname) + + local unit=UNIT:FindByName(unitname) + local pname=unit:GetPlayerName() + local csign=unit:GetCallsign() + + return string.format("%s (%s)", csign, pname) +end + +--- http://stackoverflow.com/questions/1426954/split-string-in-lua +-- @param #RANGE self +-- @param #string str Sting to split. +-- @param #string sep Speparator for split. +-- @return #table Split text. +function RANGE:_split(str, sep) + self:F({str=str, sep=sep}) + + local result = {} + local regex = ("([^%s]+)"):format(sep) + for each in str:gmatch(regex) do + table.insert(result, each) + end + + return result +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Functional/Scoring.lua b/Moose Development/Moose/Functional/Scoring.lua index ed233a409..cab7839ae 100644 --- a/Moose Development/Moose/Functional/Scoring.lua +++ b/Moose Development/Moose/Functional/Scoring.lua @@ -1,5 +1,6 @@ ---- **Functional** -- **Administer the SCORING of player achievements, --- and create a CSV file logging the scoring events for use at team or squadron websites.** +--- **Functional** -- (R2.0) - Administer the scoring of player achievements, and create a CSV file logging the scoring events for use at team or squadron websites. +-- +-- === -- -- ![Banner Image](..\Presentations\SCORING\Dia1.JPG) -- @@ -178,7 +179,7 @@ -- * @{#SCORING.SetMessagesToCoalition}(): Configure to send messages to only those players within the same coalition as the player. -- -- --- ==== +-- === -- -- # **API CHANGE HISTORY** -- diff --git a/Moose Development/Moose/Functional/Sead.lua b/Moose Development/Moose/Functional/Sead.lua index cd176650f..f1a18b8df 100644 --- a/Moose Development/Moose/Functional/Sead.lua +++ b/Moose Development/Moose/Functional/Sead.lua @@ -1,6 +1,6 @@ --- **Functional** -- Provides defensive behaviour to a set of SAM sites within a running Mission. -- --- ==== +-- === -- -- @module Sead diff --git a/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua b/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua index b776cc4bb..b0d6d6912 100644 --- a/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua +++ b/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua @@ -1,15 +1,25 @@ ---- **Functional** -- (WIP R2.3) Models the process to capture a Zone for a Coalition, which is guarded by another Coalition. +--- **Functional** -- (R2.3) Models the process to zone guarding and capturing. -- --- ==== +-- === -- -- ![Banner Image](..\Presentations\ZONE_CAPTURE_COALITION\Dia1.JPG) -- -- === -- --- ### Contributions: **Millertime**: Concept --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAZ%20-%20Capture Zones) -- --- ==== +-- - CAZ-000 - Capture Zone: Demonstrates the basic concept of capturing a zone. +-- +-- === +-- +-- ### [YouTube Playlist](https://www.youtube.com/watch?v=0m6K6Yxa-os&list=PL7ZUrU4zZUl0qqJsfa8DPvZWDY-OyDumE) +-- +-- === +-- +-- ### Author: **FlightControl** +-- ### Contributions: **Millertime** - Concept +-- +-- === -- -- @module ZoneCaptureCoalition @@ -22,26 +32,48 @@ do -- ZONE_CAPTURE_COALITION --- # ZONE\_CAPTURE\_COALITION class, extends @{ZoneGoalCoalition#ZONE_GOAL_COALITION} -- -- Models the process to capture a Zone for a Coalition, which is guarded by another Coalition. + -- This is a powerful concept that allows to create very dynamic missions based on the different state transitions of various zones. -- -- --- -- -- ![Banner Image](..\Presentations\ZONE_CAPTURE_COALITION\Dia1.JPG) -- -- --- + -- + -- # 0. Player Experience + -- + -- ![States](..\Presentations\ZONE_CAPTURE_COALITION\Dia3.JPG) -- - -- The Zone is initially **Guarded** by the __owning coalition__, which is the coalition that initially occupies the zone with units of its coalition. + -- The above models the possible state transitions between the **Guarded**, **Attacked**, **Empty** and **Captured** states. + -- A zone has an __owning coalition__, that means that at a specific point in time, a zone can be owned by the red or blue coalition. + -- + -- The Zone can be in the state **Guarded** by the __owning coalition__, which is the coalition that initially occupies the zone with units of its coalition. -- Once units of an other coalition are entering the Zone, the state will change to **Attacked**. As long as these units remain in the zone, the state keeps set to Attacked. -- When all units are destroyed in the Zone, the state will change to **Empty**, which expresses that the Zone is empty, and can be captured. -- When units of the other coalition are in the Zone, and no other units of the owning coalition is in the Zone, the Zone is captured, and its state will change to **Captured**. -- - -- Event handlers can be defined by the mission designer to action on the state transitions. + -- The zone needs to be monitored regularly for the presence of units to interprete the correct state transition required. + -- This monitoring process MUST be started using the @{#ZONE_CAPTURE_COALITION.Start}() method. + -- Otherwise no monitoring will be active and the zone will stay in the current state forever. + -- See further in chapter 3.3 for more information about this. -- -- ## 1. ZONE\_CAPTURE\_COALITION constructor -- -- * @{#ZONE_CAPTURE_COALITION.New}(): Creates a new ZONE\_CAPTURE\_COALITION object. + -- + -- In order to use ZONE\_CAPTURE\_COALITION, you need to: + -- + -- - Create a @{Zone} object from one of the ZONE\_ classes. Note that ZONE\_POLYGON\_ classes are not yet functional. The only functional ZONE\_ classses are those derived from a ZONE\_RADIUS. + -- + -- ![New](..\Presentations\ZONE_CAPTURE_COALITION\Dia5.JPG) + -- + -- Ensure that during the life cycle of the ZONE\_CAPTURE\_COALITION object, the object keeps alive. + -- It is best to declare the object globally within your script. -- -- ## 2. ZONE\_CAPTURE\_COALITION is a finite state machine (FSM). -- + -- ![States](..\Presentations\ZONE_CAPTURE_COALITION\Dia4.JPG) + -- -- ### 2.1 ZONE\_CAPTURE\_COALITION States -- -- * **Captured**: The Zone has been captured by an other coalition. @@ -55,7 +87,225 @@ do -- ZONE_CAPTURE_COALITION -- * **Attack**: The Zone is currently intruded by an other coalition. There are units of the owning coalition and an other coalition in the Zone. -- * **Guard**: The Zone is guarded by the owning coalition. There is no other unit of an other coalition in the Zone. -- * **Empty**: The Zone is empty. There is not valid unit in the Zone. + -- + -- ## 3. "Script It" + -- + -- ZONE\_CAPTURE\_COALITION allows to take action on the various state transitions and add your custom code and logic. + -- + -- ### 3.1. Take action using state- and event handlers. + -- + -- ![States](..\Presentations\ZONE_CAPTURE_COALITION\Dia6.JPG) + -- + -- The most important to understand is how states and events can be tailored. + -- Carefully study the diagram and the explanations. + -- + -- **State Handlers** capture the moment: + -- + -- - On Leave from the old state. Return false to cancel the transition. + -- - On Enter to the new state. + -- + -- **Event Handlers** capture the moment: + -- + -- - On Before the event is triggered. Return false to cancel the transition. + -- - On After the event is triggered. + -- + -- + -- + -- ![States](..\Presentations\ZONE_CAPTURE_COALITION\Dia7.JPG) + -- + -- Each handler can receive optionally 3 parameters: + -- + -- - **From**: A string containing the From State. + -- - **Event**: A string containing the Event. + -- - **To**: A string containing the To State. -- + -- The mission designer can use these values to alter the logic. + -- For example: + -- + -- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self + -- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To ) + -- if From ~= "Empty" then + -- -- Display a message + -- end + -- end + -- + -- This code checks that when the __Guarded__ state has been reached, that if the **From** state was __Empty__, then display a message. + -- + -- ### 3.2. Example Event Handler. + -- + -- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self + -- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To ) + -- if From ~= To then + -- local Coalition = self:GetCoalition() + -- self:E( { Coalition = Coalition } ) + -- if Coalition == coalition.side.BLUE then + -- ZoneCaptureCoalition:Smoke( SMOKECOLOR.Blue ) + -- US_CC:MessageTypeToCoalition( string.format( "%s is under protection of the USA", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- RU_CC:MessageTypeToCoalition( string.format( "%s is under protection of the USA", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- else + -- ZoneCaptureCoalition:Smoke( SMOKECOLOR.Red ) + -- RU_CC:MessageTypeToCoalition( string.format( "%s is under protection of Russia", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- US_CC:MessageTypeToCoalition( string.format( "%s is under protection of Russia", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- end + -- end + -- end + -- + -- ### 3.3. Stop and Start the zone monitoring process. + -- + -- At regular intervals, the state of the zone needs to be monitored. + -- The zone needs to be scanned for the presence of units within the zone boundaries. + -- Depending on the owning coalition of the zone and the presence of units (of the owning and/or other coalition(s)), the zone will transition to another state. + -- + -- However, ... this scanning process is rather CPU intensive. Imagine you have 10 of these capture zone objects setup within your mission. + -- That would mean that your mission would check 10 capture zones simultaneously, each checking for the presence of units. + -- It would be highly **CPU inefficient**, as some of these zones are not required to be monitored (yet). + -- + -- Therefore, the mission designer is given 2 methods that allow to take control of the CPU utilization efficiency: + -- + -- - @{#ZONE_CAPTURE_COALITION.Start()}(): This starts the monitoring process. + -- - @{#ZONE_CAPTURE_COALITION.Stop()}(): This stops the monitoring process. + -- + -- ### IMPORTANT + -- + -- **Each capture zone object must have the monitoring process started specifically. + -- The monitoring process is NOT started by default!!!** + -- + -- + -- ## 4. Full Example + -- + -- The following annotated code shows a real example of how ZONE\_CAPTURE\_COALITION can be applied. + -- + -- The concept is simple. + -- + -- The USA (US), blue coalition, needs to capture the Russian (RU), red coalition, zone, which is near groom lake. + -- + -- A capture zone has been setup that guards the presence of the troops. + -- Troops are guarded by red forces. Blue is required to destroy the red forces and capture the zones. + -- + -- At first, we setup the Command Centers + -- + -- do + -- + -- RU_CC = COMMANDCENTER:New( GROUP:FindByName( "REDHQ" ), "Russia HQ" ) + -- US_CC = COMMANDCENTER:New( GROUP:FindByName( "BLUEHQ" ), "USA HQ" ) + -- + -- end + -- + -- Next, we define the mission, and add some scoring to it. + -- + -- do -- Missions + -- + -- US_Mission_EchoBay = MISSION:New( US_CC, "Echo Bay", "Primary", + -- "Welcome trainee. The airport Groom Lake in Echo Bay needs to be captured.\n" .. + -- "There are five random capture zones located at the airbase.\n" .. + -- "Move to one of the capture zones, destroy the fuel tanks in the capture zone, " .. + -- "and occupy each capture zone with a platoon.\n " .. + -- "Your orders are to hold position until all capture zones are taken.\n" .. + -- "Use the map (F10) for a clear indication of the location of each capture zone.\n" .. + -- "Note that heavy resistance can be expected at the airbase!\n" .. + -- "Mission 'Echo Bay' is complete when all five capture zones are taken, and held for at least 5 minutes!" + -- , coalition.side.RED ) + -- + -- US_Mission_EchoBay:Start() + -- + -- end + -- + -- + -- Now the real work starts. + -- We define a **CaptureZone** object, which is a ZONE object. + -- Within the mission, a trigger zone is created with the name __CaptureZone__, with the defined radius within the mission editor. + -- + -- CaptureZone = ZONE:New( "CaptureZone" ) + -- + -- Next, we define the **ZoneCaptureCoalition** object, as explained above. + -- + -- ZoneCaptureCoalition = ZONE_CAPTURE_COALITION:New( CaptureZone, coalition.side.RED ) + -- + -- Of course, we want to let the **ZoneCaptureCoalition** object do something when the state transitions. + -- Do accomodate this, it is very simple, as explained above. + -- We use **Event Handlers** to tailor the logic. + -- + -- Here we place an Event Handler at the Guarded event. So when the **Guarded** event is triggered, then this method is called! + -- With the variables **From**, **Event**, **To**. Each of these variables containing a string. + -- + -- We check if the previous state wasn't Guarded also. + -- If not, we retrieve the owning Coalition of the **ZoneCaptureCoalition**, using `self:GetCoalition()`. + -- So **Coalition** will contain the current owning coalition of the zone. + -- + -- Depending on the zone ownership, different messages are sent. + -- Note the methods `ZoneCaptureCoalition:GetZoneName()`. + -- + -- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self + -- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To ) + -- if From ~= To then + -- local Coalition = self:GetCoalition() + -- self:E( { Coalition = Coalition } ) + -- if Coalition == coalition.side.BLUE then + -- ZoneCaptureCoalition:Smoke( SMOKECOLOR.Blue ) + -- US_CC:MessageTypeToCoalition( string.format( "%s is under protection of the USA", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- RU_CC:MessageTypeToCoalition( string.format( "%s is under protection of the USA", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- else + -- ZoneCaptureCoalition:Smoke( SMOKECOLOR.Red ) + -- RU_CC:MessageTypeToCoalition( string.format( "%s is under protection of Russia", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- US_CC:MessageTypeToCoalition( string.format( "%s is under protection of Russia", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- end + -- end + -- end + -- + -- As you can see, not a rocket science. + -- Next is the Event Handler when the **Empty** state transition is triggered. + -- Now we smoke the ZoneCaptureCoalition with a green color, using `self:Smoke( SMOKECOLOR.Green )`. + -- + -- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self + -- function ZoneCaptureCoalition:OnEnterEmpty() + -- self:Smoke( SMOKECOLOR.Green ) + -- US_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- RU_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- end + -- + -- The next Event Handlers speak for itself. + -- When the zone is Attacked, we smoke the zone white and send some messages to each coalition. + -- + -- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self + -- function ZoneCaptureCoalition:OnEnterAttacked() + -- ZoneCaptureCoalition:Smoke( SMOKECOLOR.White ) + -- local Coalition = self:GetCoalition() + -- self:E({Coalition = Coalition}) + -- if Coalition == coalition.side.BLUE then + -- US_CC:MessageTypeToCoalition( string.format( "%s is under attack by Russia", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- RU_CC:MessageTypeToCoalition( string.format( "We are attacking %s", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- else + -- RU_CC:MessageTypeToCoalition( string.format( "%s is under attack by the USA", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- US_CC:MessageTypeToCoalition( string.format( "We are attacking %s", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- end + -- end + -- + -- When the zone is Captured, we send some victory or loss messages to the correct coalition. + -- And we add some score. + -- + -- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self + -- function ZoneCaptureCoalition:OnEnterCaptured() + -- local Coalition = self:GetCoalition() + -- self:E({Coalition = Coalition}) + -- if Coalition == coalition.side.BLUE then + -- RU_CC:MessageTypeToCoalition( string.format( "%s is captured by the USA, we lost it!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- US_CC:MessageTypeToCoalition( string.format( "We captured %s, Excellent job!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- else + -- US_CC:MessageTypeToCoalition( string.format( "%s is captured by Russia, we lost it!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- RU_CC:MessageTypeToCoalition( string.format( "We captured %s, Excellent job!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- end + -- + -- self:__Guard( 30 ) + -- end + -- + -- And this call is the most important of all! + -- In the context of the mission, we need to start the zone capture monitoring process. + -- Or nothing will be monitored and the zone won't change states. + -- We start the monitoring after 5 seconds, and will repeat every 30 seconds a check. + -- + -- ZoneCaptureCoalition:Start( 5, 30 ) + -- + -- -- @field #ZONE_CAPTURE_COALITION ZONE_CAPTURE_COALITION = { ClassName = "ZONE_CAPTURE_COALITION", @@ -265,10 +515,6 @@ do -- ZONE_CAPTURE_COALITION -- @param #ZONE_CAPTURE_COALITION self -- @param #number Delay - if not self.ScheduleStatusZone then - self.ScheduleStatusZone = self:ScheduleRepeat( 15, 15, 0.1, nil, self.StatusZone, self ) - end - return self end @@ -437,6 +683,81 @@ do -- ZONE_CAPTURE_COALITION end end + + --- Starts the zone capturing monitoring process. + -- This process can be CPU intensive, ensure that you specify reasonable time intervals for the monitoring process. + -- Note that the monitoring process is NOT started automatically during the `:New()` constructor. + -- It is advised that the zone monitoring process is only started when the monitoring is of relevance in context of the current mission goals. + -- When the zone is of no relevance, it is advised NOT to start the monitoring process, or to stop the monitoring process to save CPU resources. + -- Therefore, the mission designer will need to use the `:Start()` method within his script to start the monitoring process specifically. + -- @param #ZONE_CAPTURE_COALITION self + -- @param #number StartInterval (optional) Specifies the start time interval in seconds when the zone state will be checked for the first time. + -- @param #number RepeatInterval (optional) Specifies the repeat time interval in seconds when the zone state will be checked repeatedly. + -- @usage + -- + -- -- Setup the zone. + -- CaptureZone = ZONE:New( "CaptureZone" ) + -- ZoneCaptureCoalition = ZONE_CAPTURE_COALITION:New( CaptureZone, coalition.side.RED ) + -- + -- -- This starts the monitoring process within 15 seconds, repeating every 15 seconds. + -- ZoneCaptureCoalition:Start() + -- + -- -- This starts the monitoring process immediately, but repeats every 30 seconds. + -- ZoneCaptureCoalition:Start( 0, 30 ) + -- + function ZONE_CAPTURE_COALITION:Start( StartInterval, RepeatInterval ) + + StartInterval = StartInterval or 15 + RepeatInterval = RepeatInterval or 15 + + if self.ScheduleStatusZone then + self:ScheduleStop( self.ScheduleStatusZone ) + end + self.ScheduleStatusZone = self:ScheduleRepeat( StartInterval, RepeatInterval, 0.1, nil, self.StatusZone, self ) + end + + + --- Stops the zone capturing monitoring process. + -- When the zone capturing monitor process is stopped, there won't be any changes anymore in the state and the owning coalition of the zone. + -- This method becomes really useful when the zone is of no relevance anymore within a long lasting mission. + -- In this case, it is advised to stop the monitoring process, not to consume unnecessary the CPU intensive scanning of units presence within the zone. + -- @param #ZONE_CAPTURE_COALITION self + -- @usage + -- -- Setup the zone. + -- CaptureZone = ZONE:New( "CaptureZone" ) + -- ZoneCaptureCoalition = ZONE_CAPTURE_COALITION:New( CaptureZone, coalition.side.RED ) + -- + -- -- This starts the monitoring process within 15 seconds, repeating every 15 seconds. + -- ZoneCaptureCoalition:Start() + -- + -- -- When the zone capturing is of no relevance anymore, stop the monitoring! + -- ZoneCaptureCoalition:Stop() + -- + -- @usage + -- -- For example, one could stop the monitoring when the zone was captured! + -- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self + -- function ZoneCaptureCoalition:OnEnterCaptured() + -- local Coalition = self:GetCoalition() + -- self:E({Coalition = Coalition}) + -- if Coalition == coalition.side.BLUE then + -- RU_CC:MessageTypeToCoalition( string.format( "%s is captured by the USA, we lost it!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- US_CC:MessageTypeToCoalition( string.format( "We captured %s, Excellent job!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- else + -- US_CC:MessageTypeToCoalition( string.format( "%s is captured by Russia, we lost it!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- RU_CC:MessageTypeToCoalition( string.format( "We captured %s, Excellent job!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information ) + -- end + -- + -- self:AddScore( "Captured", "Zone captured: Extra points granted.", 200 ) + -- + -- self:Stop() + -- end + -- + function ZONE_CAPTURE_COALITION:Stop() + + if self.ScheduleStatusZone then + self:ScheduleStop( self.ScheduleStatusZone ) + end + end end diff --git a/Moose Development/Moose/Functional/ZoneGoal.lua b/Moose Development/Moose/Functional/ZoneGoal.lua index 436b00db8..5bca12a4e 100644 --- a/Moose Development/Moose/Functional/ZoneGoal.lua +++ b/Moose Development/Moose/Functional/ZoneGoal.lua @@ -1,15 +1,15 @@ --- **Functional (WIP)** -- Base class that models processes to achieve goals involving a Zone. -- --- ==== +-- === -- -- ZONE_GOAL models processes that have a Goal with a defined achievement involving a Zone. -- Derived classes implement the ways how the achievements can be realized. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- --- ==== +-- === -- -- @module ZoneGoal diff --git a/Moose Development/Moose/Functional/ZoneGoalCargo.lua b/Moose Development/Moose/Functional/ZoneGoalCargo.lua index 3fc0d5e8b..e5ea44310 100644 --- a/Moose Development/Moose/Functional/ZoneGoalCargo.lua +++ b/Moose Development/Moose/Functional/ZoneGoalCargo.lua @@ -1,15 +1,15 @@ --- **Functional (WIP)** -- Base class that models processes to achieve goals involving a Zone and Cargo. -- --- ==== +-- === -- -- ZONE_GOAL_CARGO models processes that have a Goal with a defined achievement involving a Zone and Cargo. -- Derived classes implement the ways how the achievements can be realized. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- --- ==== +-- === -- -- @module ZoneGoalCargo diff --git a/Moose Development/Moose/Functional/ZoneGoalCoalition.lua b/Moose Development/Moose/Functional/ZoneGoalCoalition.lua index 0b31b8494..91c7df0dc 100644 --- a/Moose Development/Moose/Functional/ZoneGoalCoalition.lua +++ b/Moose Development/Moose/Functional/ZoneGoalCoalition.lua @@ -1,15 +1,15 @@ --- **Functional (WIP)** -- Base class that models processes to achieve goals involving a Zone for a Coalition. -- --- ==== +-- === -- -- ZONE_GOAL_COALITION models processes that have a Goal with a defined achievement involving a Zone for a Coalition. -- Derived classes implement the ways how the achievements can be realized. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- --- ==== +-- === -- -- @module ZoneGoalCoalition diff --git a/Moose Development/Moose/Tasking/CommandCenter.lua b/Moose Development/Moose/Tasking/CommandCenter.lua index d949f4763..2aa6317a6 100644 --- a/Moose Development/Moose/Tasking/CommandCenter.lua +++ b/Moose Development/Moose/Tasking/CommandCenter.lua @@ -3,11 +3,11 @@ -- -- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module CommandCenter diff --git a/Moose Development/Moose/Tasking/DetectionManager.lua b/Moose Development/Moose/Tasking/DetectionManager.lua index e2816dbba..6252dc0a4 100644 --- a/Moose Development/Moose/Tasking/DetectionManager.lua +++ b/Moose Development/Moose/Tasking/DetectionManager.lua @@ -3,7 +3,7 @@ -- === -- -- 1) @{DetectionManager#DETECTION_MANAGER} class, extends @{Fsm#FSM} --- ==================================================================== +-- === -- The @{DetectionManager#DETECTION_MANAGER} class defines the core functions to report detected objects to groups. -- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour. -- @@ -27,7 +27,7 @@ -- === -- -- 2) @{DetectionManager#DETECTION_REPORTING} class, extends @{DetectionManager#DETECTION_MANAGER} --- ========================================================================================= +-- === -- The @{DetectionManager#DETECTION_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{DetectionManager#DETECTION_MANAGER} class. -- -- 2.1) DETECTION_REPORTING constructor: diff --git a/Moose Development/Moose/Tasking/Mission.lua b/Moose Development/Moose/Tasking/Mission.lua index 897180d16..44de4ee3f 100644 --- a/Moose Development/Moose/Tasking/Mission.lua +++ b/Moose Development/Moose/Tasking/Mission.lua @@ -1,8 +1,8 @@ --- **Tasking** -- A MISSION is the main owner of a Mission orchestration within MOOSE. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- @@ -46,6 +46,7 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi self.MissionCoalition = MissionCoalition self.Tasks = {} + self.TaskNumber = 0 self.PlayerNames = {} -- These are the players that achieved progress in the mission. self:SetStartState( "IDLE" ) @@ -307,7 +308,7 @@ end -- @param Wrapper.Group#GROUP PlayerGroup The GROUP of the player joining the Mission. -- @return #boolean true if Unit is part of a Task in the Mission. function MISSION:JoinUnit( PlayerUnit, PlayerGroup ) - self:E( { Mission = self:GetName(), PlayerUnit = PlayerUnit, PlayerGroup = PlayerGroup } ) + self:I( { Mission = self:GetName(), PlayerUnit = PlayerUnit, PlayerGroup = PlayerGroup } ) local PlayerUnitAdded = false @@ -459,7 +460,7 @@ do -- Group Assignment local MissionGroupName = MissionGroup:GetName() self.AssignedGroups[MissionGroupName] = MissionGroup - self:E( string.format( "Mission %s is assigned to %s", MissionName, MissionGroupName ) ) + self:I( string.format( "Mission %s is assigned to %s", MissionName, MissionGroupName ) ) return self end @@ -568,6 +569,18 @@ function MISSION:GetTask( TaskName ) end +--- Return the next @{Task} ID to be completed within the @{Mission}. +-- @param #MISSION self +-- @param Tasking.Task#TASK Task is the @{Task} object. +-- @return Tasking.Task#TASK The task added. +function MISSION:GetNextTaskID( Task ) + + self.TaskNumber = self.TaskNumber + 1 + + return self.TaskNumber +end + + --- Register a @{Task} to be completed within the @{Mission}. -- Note that there can be multiple @{Task}s registered to be completed. -- Each Task can be set a certain Goals. The Mission will not be completed until all Goals are reached. @@ -577,9 +590,7 @@ end function MISSION:AddTask( Task ) local TaskName = Task:GetTaskName() - self:E( { "==> Adding TASK ", MissionName = self:GetName(), TaskName = TaskName } ) - - self.Tasks[TaskName] = self.Tasks[TaskName] or { n = 0 } + self:I( { "==> Adding TASK ", MissionName = self:GetName(), TaskName = TaskName } ) self.Tasks[TaskName] = Task @@ -588,6 +599,7 @@ function MISSION:AddTask( Task ) return Task end + --- Removes a @{Task} to be completed within the @{Mission}. -- Note that there can be multiple @{Task}s registered to be completed. -- Each Task can be set a certain Goals. The Mission will not be completed until all Goals are reached. @@ -597,7 +609,7 @@ end function MISSION:RemoveTask( Task ) local TaskName = Task:GetTaskName() - self:E( { "<== Removing TASK ", MissionName = self:GetName(), TaskName = TaskName } ) + self:I( { "<== Removing TASK ", MissionName = self:GetName(), TaskName = TaskName } ) self:F( TaskName ) self.Tasks[TaskName] = self.Tasks[TaskName] or { n = 0 } @@ -613,21 +625,6 @@ function MISSION:RemoveTask( Task ) return nil end ---- Return the next @{Task} ID to be completed within the @{Mission}. --- @param #MISSION self --- @param Tasking.Task#TASK Task is the @{Task} object. --- @return Tasking.Task#TASK The task added. -function MISSION:GetNextTaskID( Task ) - - local TaskName = Task:GetTaskName() - self:F( TaskName ) - self.Tasks[TaskName] = self.Tasks[TaskName] or { n = 0 } - - self.Tasks[TaskName].n = self.Tasks[TaskName].n + 1 - - return self.Tasks[TaskName].n -end - --- Is the @{Mission} **COMPLETED**. -- @param #MISSION self -- @return #boolean diff --git a/Moose Development/Moose/Tasking/Task.lua b/Moose Development/Moose/Tasking/Task.lua index 22a02fe82..7f8841095 100644 --- a/Moose Development/Moose/Tasking/Task.lua +++ b/Moose Development/Moose/Tasking/Task.lua @@ -1,12 +1,12 @@ --- **Tasking** -- This module contains the TASK class, the main engine to run human taskings. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Task diff --git a/Moose Development/Moose/Tasking/TaskInfo.lua b/Moose Development/Moose/Tasking/TaskInfo.lua index df0160747..bf75bcf5a 100644 --- a/Moose Development/Moose/Tasking/TaskInfo.lua +++ b/Moose Development/Moose/Tasking/TaskInfo.lua @@ -1,12 +1,12 @@ --- **Tasking** -- Controls the information of a Task. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module TaskInfo diff --git a/Moose Development/Moose/Tasking/TaskZoneCapture.lua b/Moose Development/Moose/Tasking/TaskZoneCapture.lua index e897e0e2e..fd5934dfd 100644 --- a/Moose Development/Moose/Tasking/TaskZoneCapture.lua +++ b/Moose Development/Moose/Tasking/TaskZoneCapture.lua @@ -1,12 +1,12 @@ --- **Tasking** - The TASK_Protect models tasks for players to protect or capture specific zones. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: MillerTime -- --- ==== +-- === -- -- @module TaskZoneCapture diff --git a/Moose Development/Moose/Tasking/Task_A2A.lua b/Moose Development/Moose/Tasking/Task_A2A.lua index cd6f74022..4db992c40 100644 --- a/Moose Development/Moose/Tasking/Task_A2A.lua +++ b/Moose Development/Moose/Tasking/Task_A2A.lua @@ -1,12 +1,12 @@ --- **Tasking** - The TASK_A2A models tasks for players in Air to Air engagements. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Task_A2A diff --git a/Moose Development/Moose/Tasking/Task_A2A_Dispatcher.lua b/Moose Development/Moose/Tasking/Task_A2A_Dispatcher.lua index ce227ce24..18d48e9e4 100644 --- a/Moose Development/Moose/Tasking/Task_A2A_Dispatcher.lua +++ b/Moose Development/Moose/Tasking/Task_A2A_Dispatcher.lua @@ -2,13 +2,13 @@ -- -- The @{#TASK_A2A_DISPATCHER} classes implement the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of EWR installation groups. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Task_A2A_Dispatcher diff --git a/Moose Development/Moose/Tasking/Task_A2G.lua b/Moose Development/Moose/Tasking/Task_A2G.lua index c9737759a..6ecb4ce78 100644 --- a/Moose Development/Moose/Tasking/Task_A2G.lua +++ b/Moose Development/Moose/Tasking/Task_A2G.lua @@ -1,12 +1,12 @@ --- **Tasking** - The TASK_A2G models tasks for players in Air to Ground engagements. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Task_A2G diff --git a/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua b/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua index 45749b2b9..d47aa8b95 100644 --- a/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua +++ b/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua @@ -1,18 +1,18 @@ --- **Tasking** - The TASK\_A2G\_DISPATCHER dispatches A2G Tasks to Players based on enemy location detection. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Task_A2G_Dispatcher do -- TASK_A2G_DISPATCHER - --- TASK_A2G_DISPATCHER class. + --- 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. @@ -367,20 +367,20 @@ do -- TASK_A2G_DISPATCHER -- - Overview reports, which are providing the essential information. It provides an overview of a greater thing, and may take a bit of time to read. -- - Detailed reports, which provide with very detailed information. It takes a bit longer to read those reports, so the display of those could be a bit longer. -- - -- # 2. TASK_A2G_DISPATCHER constructor + -- # 2. TASK\_A2G\_DISPATCHER constructor -- - -- The @{#TASK_A2G_DISPATCHER.New}() method creates a new TASK_A2G_DISPATCHER instance. + -- The @{#TASK_A2G_DISPATCHER.New}() method creates a new TASK\_A2G\_DISPATCHER instance. -- -- # 3. Usage -- -- To use the TASK\_A2G\_DISPATCHER class, you need: -- - -- - A @{CommandCenter} object. - -- - A @{Mission} object. - -- - A @{Detection} object. - -- - A @{Task_A2G_Dispatcher} object. - -- - A @{Set} of @{Group} objects that will detect the emeny. - -- - A @{Set} ob @{Group} objects that will attack the enemy. + -- - A @{CommandCenter} object. The master communication channel. + -- - A @{Mission} object. Each task belongs to a Mission. + -- - A @{Detection} object. There are several detection grouping methods to choose from. + -- - A @{Task_A2G_Dispatcher} object. The master A2G task dispatcher. + -- - A @{Set} of @{Group} objects that will detect the emeny, the RecceSet. This is attached to the @{Detection} object. + -- - A @{Set} ob @{Group} objects that will attack the enemy, the AttackSet. This is attached to the @{Task_A2G_Dispatcher} object. -- -- Below an example mission declaration that is defines a Task A2G Dispatcher object. -- diff --git a/Moose Development/Moose/Tasking/Task_CARGO.lua b/Moose Development/Moose/Tasking/Task_CARGO.lua index a138e2a0f..7d11cae8d 100644 --- a/Moose Development/Moose/Tasking/Task_CARGO.lua +++ b/Moose Development/Moose/Tasking/Task_CARGO.lua @@ -2,7 +2,7 @@ -- -- ![Banner Image](..\Presentations\TASK_CARGO\Dia1.JPG) -- --- ==== +-- === -- -- The Moose framework provides various CARGO classes that allow DCS phisical or logical objects to be transported or sling loaded by Carriers. -- The CARGO_ classes, as part of the moose core, are able to Board, Load, UnBoard and UnLoad cargo between Carrier units. @@ -14,13 +14,13 @@ -- -- * @{#TASK_CARGO_TRANSPORT}: Defines a task for a human player to transport a set of cargo between various zones. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Task_Cargo diff --git a/Moose Development/Moose/Tasking/Task_Pickup.lua b/Moose Development/Moose/Tasking/Task_Pickup.lua index 0e1b103c5..459f9f4a2 100644 --- a/Moose Development/Moose/Tasking/Task_Pickup.lua +++ b/Moose Development/Moose/Tasking/Task_Pickup.lua @@ -1,7 +1,7 @@ --- This module contains the TASK_PICKUP classes. -- -- 1) @{#TASK_PICKUP} class, extends @{Task#TASK} --- =================================================== +-- === -- The @{#TASK_PICKUP} class defines a pickup task of a @{Set} of @{CARGO} objects defined within the mission. -- based on the tasking capabilities defined in @{Task#TASK}. -- The TASK_PICKUP is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses: diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 13ee83ab1..e6db9284c 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -1,8 +1,8 @@ --- **Wrapper** -- AIRBASE is a wrapper class to handle the DCS Airbase objects. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 3b20fb754..71e2066cb 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -1,8 +1,8 @@ --- **Wrapper** -- CLIENT wraps DCS Unit objects acting as a __Client__ or __Player__ within a mission. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 90e11151d..fe3d1378d 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -1,8 +1,8 @@ --- **Wrapper** -- CONTROLLABLE is an intermediate class wrapping Group and Unit classes "controllers". -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index 5c9e48b87..f46c2701b 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -13,15 +13,15 @@ -- -- See the detailed documentation on the GROUP class. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- -- * [**Entropy**](https://forums.eagle.ru/member.php?u=111471), **Afinegan**: Came up with the requirement for AIOnOff(). -- --- ==== +-- === -- -- @module Group diff --git a/Moose Development/Moose/Wrapper/Identifiable.lua b/Moose Development/Moose/Wrapper/Identifiable.lua index fe14a8b9d..baa83eedb 100644 --- a/Moose Development/Moose/Wrapper/Identifiable.lua +++ b/Moose Development/Moose/Wrapper/Identifiable.lua @@ -1,12 +1,12 @@ --- **Wrapper** -- IDENTIFIABLE is an intermediate class wrapping DCS Object class derived Objects. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Identifiable diff --git a/Moose Development/Moose/Wrapper/Object.lua b/Moose Development/Moose/Wrapper/Object.lua index a8fcdfe0c..fc3c11126 100644 --- a/Moose Development/Moose/Wrapper/Object.lua +++ b/Moose Development/Moose/Wrapper/Object.lua @@ -1,8 +1,8 @@ --- **Wrapper** -- OBJECT wraps the DCS Object derived objects. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index f901be0e2..5a7f064c4 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -1,12 +1,12 @@ --- **Wrapper** -- POSITIONABLE wraps DCS classes that are "positionable". -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Positionable diff --git a/Moose Development/Moose/Wrapper/Scenery.lua b/Moose Development/Moose/Wrapper/Scenery.lua index d0d5215dd..e999917b1 100644 --- a/Moose Development/Moose/Wrapper/Scenery.lua +++ b/Moose Development/Moose/Wrapper/Scenery.lua @@ -1,12 +1,12 @@ --- **Wrapper** -- SCENERY models scenery within the DCS simulator. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Scenery diff --git a/Moose Development/Moose/Wrapper/Static.lua b/Moose Development/Moose/Wrapper/Static.lua index 1a76a869a..28e7c364b 100644 --- a/Moose Development/Moose/Wrapper/Static.lua +++ b/Moose Development/Moose/Wrapper/Static.lua @@ -1,12 +1,12 @@ --- **Wrapper** -- STATIC wraps the DCS StaticObject class. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Static diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 76f4567ab..26d30ed91 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -9,13 +9,13 @@ -- * Handle local Unit Controller. -- * Manage the "state" of the DCS Unit. -- --- ==== +-- === -- --- ### Author: **Sven Van de Velde (FlightControl)** +-- ### Author: **FlightControl** -- -- ### Contributions: -- --- ==== +-- === -- -- @module Unit diff --git a/Moose Setup/Moose.files b/Moose Setup/Moose.files index 938e9e1ed..1e575f0f2 100644 --- a/Moose Setup/Moose.files +++ b/Moose Setup/Moose.files @@ -45,6 +45,7 @@ Functional/ATC_Ground.lua Functional/Detection.lua Functional/Designate.lua Functional/RAT.lua +Functional/Range.lua Functional/ZoneGoal.lua Functional/ZoneGoalCoalition.lua Functional/ZoneCaptureCoalition.lua