diff --git a/Moose Development/Moose/Cargo/Cargo.lua b/Moose Development/Moose/Cargo/Cargo.lua deleted file mode 100644 index 57068feda..000000000 --- a/Moose Development/Moose/Cargo/Cargo.lua +++ /dev/null @@ -1,1401 +0,0 @@ ---- **Cargo** - Management of CARGO logistics, that can be transported from and to transportation carriers. --- --- === --- --- ![Banner Image](..\Images\deprecated.png) --- --- # 1) MOOSE Cargo System. --- --- #### Those who have used the mission editor, know that the DCS mission editor provides cargo facilities. --- However, these are merely static objects. Wouldn't it be nice if cargo could bring a new dynamism into your --- simulations? Where various objects of various types could be treated also as cargo? --- --- This is what MOOSE brings to you, a complete new cargo object model that used the cargo capabilities of --- DCS world, but enhances it. --- --- MOOSE Cargo introduces also a new concept, called a "carrier". These can be: --- --- - Helicopters --- - Planes --- - Ground Vehicles --- - Ships --- --- With the MOOSE Cargo system, you can: --- --- - Take full control of the cargo as objects within your script (see below). --- - Board/Unboard infantry into carriers. Also other objects can be boarded, like mortars. --- - Load/Unload dcs world cargo objects into carriers. --- - Load/Unload other static objects into carriers (like tires etc). --- - Slingload cargo objects. --- - Board units one by one... --- --- # 2) MOOSE Cargo Objects. --- --- In order to make use of the MOOSE cargo system, you need to **declare** the DCS objects as MOOSE cargo objects! --- --- This sounds complicated, but it is actually quite simple. --- --- See here an example: --- --- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 ) --- --- The above code declares a MOOSE cargo object called `EngineerCargoGroup`. --- It actually just refers to an infantry group created within the sim called `"Engineers"`. --- The infantry group now becomes controlled by the MOOSE cargo object `EngineerCargoGroup`. --- A MOOSE cargo object also has properties, like the type of cargo, the logical name, and the reporting range. --- --- There are 4 types of MOOSE cargo objects possible, each represented by its own class: --- --- - @{Cargo.CargoGroup#CARGO_GROUP}: A MOOSE cargo that is represented by a DCS world GROUP object. --- - @{Cargo.CargoCrate#CARGO_CRATE}: A MOOSE cargo that is represented by a DCS world cargo object (static object). --- - @{Cargo.CargoUnit#CARGO_UNIT}: A MOOSE cargo that is represented by a DCS world unit object or static object. --- - @{Cargo.CargoSlingload#CARGO_SLINGLOAD}: A MOOSE cargo that is represented by a DCS world cargo object (static object), that can be slingloaded. --- --- Note that a CARGO crate is not meant to be slingloaded (it can, but it is not **meant** to be handled like that. --- Instead, a CARGO_CRATE is able to load itself into the bays of a carrier. --- --- Each of these MOOSE cargo objects behave in its own way, and have methods to be handled. --- --- local InfantryGroup = GROUP:FindByName( "Infantry" ) --- local InfantryCargo = CARGO_GROUP:New( InfantryGroup, "Engineers", "Infantry Engineers", 2000 ) --- local CargoCarrier = UNIT:FindByName( "Carrier" ) --- -- This call will make the Cargo run to the CargoCarrier. --- -- Upon arrival at the CargoCarrier, the Cargo will be Loaded into the Carrier. --- -- This process is now fully automated. --- InfantryCargo:Board( CargoCarrier, 25 ) --- --- The above would create a MOOSE cargo object called `InfantryCargo`, and using that object, --- you can board the cargo into the carrier `CargoCarrier`. --- Simple, isn't it? Told you, and this is only the beginning. --- --- The boarding, unboarding, loading, unloading of cargo is however something that is not meant to be coded manually by mission designers. --- It would be too low-level and not end-user friendly to deal with cargo handling complexity. --- Things can become really complex if you want to make cargo being handled and behave in multiple scenarios. --- --- # 3) Cargo Handling Classes, the main engines for mission designers! --- --- For this reason, the MOOSE Cargo System is heavily used by 3 important **cargo handling class hierarchies** within MOOSE, --- that make cargo come "alive" within your mission in a full automatic manner! --- --- ## 3.1) AI Cargo handlers. --- --- - @{AI.AI_Cargo_APC} will create for you the capability to make an APC group handle cargo. --- - @{AI.AI_Cargo_Helicopter} will create for you the capability to make a Helicopter group handle cargo. --- --- --- ## 3.2) AI Cargo transportation dispatchers. --- --- There are also dispatchers that make AI work together to transport cargo automatically!!! --- --- - @{AI.AI_Cargo_Dispatcher_APC} derived classes will create for your dynamic cargo handlers controlled by AI ground vehicle groups (APCs) to transport cargo between sites. --- - @{AI.AI_Cargo_Dispatcher_Helicopter} derived classes will create for your dynamic cargo handlers controlled by AI helicopter groups to transport cargo between sites. --- --- ## 3.3) Cargo transportation tasking. --- --- And there is cargo transportation tasking for human players. --- --- - @{Tasking.Task_CARGO} derived classes will create for you cargo transportation tasks, that allow human players to interact with MOOSE cargo objects to complete tasks. --- --- Please refer to the documentation reflected within these modules to understand the detailed capabilities. --- --- # 4) Cargo SETs. --- --- To make life a bit more easy, MOOSE cargo objects can be grouped into a @{Core.Set#SET_CARGO}. --- This is a collection of MOOSE cargo objects. --- --- This would work as follows: --- --- -- Define the cargo set. --- local CargoSetWorkmaterials = SET_CARGO:New():FilterTypes( "Workmaterials" ):FilterStart() --- --- -- Now add cargo the cargo set. --- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 ) --- local ConcreteCargo = CARGO_SLINGLOAD:New( STATIC:FindByName( "Concrete" ), "Workmaterials", "Concrete", 150, 50 ) --- local CrateCargo = CARGO_CRATE:New( STATIC:FindByName( "Crate" ), "Workmaterials", "Crate", 150, 50 ) --- local EnginesCargo = CARGO_CRATE:New( STATIC:FindByName( "Engines" ), "Workmaterials", "Engines", 150, 50 ) --- local MetalCargo = CARGO_CRATE:New( STATIC:FindByName( "Metal" ), "Workmaterials", "Metal", 150, 50 ) --- --- This is a very powerful concept! --- Instead of having to deal with multiple MOOSE cargo objects yourself, the cargo set capability will group cargo objects into one set. --- The key is the **cargo type** name given at each cargo declaration! --- In the above example, the cargo type name is `"Workmaterials"`. Each cargo object declared is given that type name. (the 2nd parameter). --- What happens now is that the cargo set `CargoSetWorkmaterials` will be added with each cargo object **dynamically** when the cargo object is created. --- In other words, the cargo set `CargoSetWorkmaterials` will incorporate any `"Workmaterials"` dynamically into its set. --- --- The cargo sets are extremely important for the AI cargo transportation dispatchers and the cargo transporation tasking. --- --- # 5) Declare cargo directly in the mission editor! --- --- But I am not finished! There is something more, that is even more great! --- Imagine the mission designers having to code all these lines every time it wants to embed cargo within a mission. --- --- -- Now add cargo the cargo set. --- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 ) --- local ConcreteCargo = CARGO_SLINGLOAD:New( STATIC:FindByName( "Concrete" ), "Workmaterials", "Concrete", 150, 50 ) --- local CrateCargo = CARGO_CRATE:New( STATIC:FindByName( "Crate" ), "Workmaterials", "Crate", 150, 50 ) --- local EnginesCargo = CARGO_CRATE:New( STATIC:FindByName( "Engines" ), "Workmaterials", "Engines", 150, 50 ) --- local MetalCargo = CARGO_CRATE:New( STATIC:FindByName( "Metal" ), "Workmaterials", "Metal", 150, 50 ) --- --- This would be extremely tiring and a huge overload. --- However, the MOOSE framework allows to declare MOOSE cargo objects within the mission editor!!! --- --- So, at mission startup, MOOSE will search for objects following a special naming convention, and will **create** for you **dynamically --- cargo objects** at **mission start**!!! -- These cargo objects can then be automatically incorporated within cargo set(s)!!! --- In other words, your mission will be reduced to about a few lines of code, providing you with a full dynamic cargo handling mission! --- --- ## 5.1) Use \#CARGO tags in the mission editor: --- --- MOOSE can create automatically cargo objects, if the name of the cargo contains the **\#CARGO** tag. --- When a mission starts, MOOSE will scan all group and static objects it found for the presence of the \#CARGO tag. --- When found, MOOSE will declare the object as cargo (create in the background a CARGO_ object, like CARGO_GROUP, CARGO_CRATE or CARGO_SLINGLOAD. --- The creation of these CARGO_ objects will allow to be filtered and automatically added in SET_CARGO objects. --- In other words, with very minimal code as explained in the above code section, you are able to create vast amounts of cargo objects just from within the editor. --- --- What I talk about is this: --- --- -- BEFORE THIS SCRIPT STARTS, MOOSE WILL ALREADY HAVE SCANNED FOR OBJECTS WITH THE #CARGO TAG IN THE NAME. --- -- FOR EACH OF THESE OBJECT, MOOSE WILL HAVE CREATED CARGO_ OBJECTS LIKE CARGO_GROUP, CARGO_CRATE AND CARGO_SLINGLOAD. --- --- HQ = GROUP:FindByName( "HQ", "Bravo" ) --- --- CommandCenter = COMMANDCENTER --- :New( HQ, "Lima" ) --- --- Mission = MISSION --- :New( CommandCenter, "Operation Cargo Fun", "Tactical", "Transport Cargo", coalition.side.RED ) --- --- TransportGroups = SET_GROUP:New():FilterCoalitions( "blue" ):FilterPrefixes( "Transport" ):FilterStart() --- --- TaskDispatcher = TASK_CARGO_DISPATCHER:New( Mission, TransportGroups ) --- --- -- This is the most important now. You setup a new SET_CARGO filtering the relevant type. --- -- The actual cargo objects are now created by MOOSE in the background. --- -- Each cargo is setup in the Mission Editor using the #CARGO tag in the group name. --- -- This allows a truly dynamic setup. --- local CargoSetWorkmaterials = SET_CARGO:New():FilterTypes( "Workmaterials" ):FilterStart() --- --- local WorkplaceTask = TaskDispatcher:AddTransportTask( "Build a Workplace", CargoSetWorkmaterials, "Transport the workers, engineers and the equipment near the Workplace." ) --- TaskDispatcher:SetTransportDeployZone( WorkplaceTask, ZONE:New( "Workplace" ) ) --- --- The above code example has the `CargoSetWorkmaterials`, which is a SET_CARGO collection and will include the CARGO_ objects of the type "Workmaterials". --- And there is NO cargo object actually declared within the script! However, if you would open the mission, there would be hundreds of cargo objects... --- --- The \#CARGO tag even allows for several options to be specified, which are important to learn. --- --- ## 5.2) The \#CARGO tag to create CARGO_GROUP objects: --- --- You can also use the \#CARGO tag on **group** objects of the mission editor. --- --- For example, the following #CARGO naming in the **group name** of the object, will create a CARGO_GROUP object when the mission starts. --- --- `Infantry #CARGO(T=Workmaterials,RR=500,NR=25)` --- --- This will create a CARGO_GROUP object: --- --- * with the group name `Infantry #CARGO` --- * is of type `Workmaterials` --- * will report when a carrier is within 500 meters --- * will board to carriers when the carrier is within 500 meters from the cargo object --- * will disappear when the cargo is within 25 meters from the carrier during boarding --- --- So the overall syntax of the #CARGO naming tag and arguments are: --- --- `GroupName #CARGO(T=CargoTypeName,RR=Range,NR=Range)` --- --- * **T=** Provide a text that contains the type name of the cargo object. This type name can be used to filter cargo within a SET_CARGO object. --- * **RR=** Provide the minimal range in meters when the report to the carrier, and board to the carrier. --- Note that this option is optional, so can be omitted. The default value of the RR is 250 meters. --- * **NR=** Provide the maximum range in meters when the cargo units will be boarded within the carrier during boarding. --- Note that this option is optional, so can be omitted. The default value of the RR is 10 meters. --- --- ## 5.2) The \#CARGO tag to create CARGO_CRATE or CARGO_SLINGLOAD objects: --- --- You can also use the \#CARGO tag on **static** objects, including **static cargo** objects of the mission editor. --- --- For example, the following #CARGO naming in the **static name** of the object, will create a CARGO_CRATE object when the mission starts. --- --- `Static #CARGO(T=Workmaterials,C=CRATE,RR=500,NR=25)` --- --- This will create a CARGO_CRATE object: --- --- * with the group name `Static #CARGO` --- * is of type `Workmaterials` --- * is of category `CRATE` (as opposed to `SLING`) --- * will report when a carrier is within 500 meters --- * will board to carriers when the carrier is within 500 meters from the cargo object --- * will disappear when the cargo is within 25 meters from the carrier during boarding --- --- So the overall syntax of the #CARGO naming tag and arguments are: --- --- `StaticName #CARGO(T=CargoTypeName,C=Category,RR=Range,NR=Range)` --- --- * **T=** Provide a text that contains the type name of the cargo object. This type name can be used to filter cargo within a SET_CARGO object. --- * **C=** Provide either `CRATE` or `SLING` to have this static created as a CARGO_CRATE or CARGO_SLINGLOAD respectively. --- * **RR=** Provide the minimal range in meters when the report to the carrier, and board to the carrier. --- Note that this option is optional, so can be omitted. The default value of the RR is 250 meters. --- * **NR=** Provide the maximum range in meters when the cargo units will be boarded within the carrier during boarding. --- Note that this option is optional, so can be omitted. The default value of the RR is 10 meters. --- --- # Developer Note --- --- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE --- Therefore, this class is considered to be deprecated --- --- === --- --- ### Author: **FlightControl** --- ### Contributions: --- --- === --- --- @module Cargo.Cargo --- @image Cargo.JPG - --- Events - --- Board - ---- Boards the cargo to a Carrier. The event will create a movement (= running or driving) of the cargo to the Carrier. --- The cargo must be in the **UnLoaded** state. --- @function [parent=#CARGO] Board --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE ToCarrier The Carrier that will hold the cargo. --- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision). - ---- Boards the cargo to a Carrier. The event will create a movement (= running or driving) of the cargo to the Carrier. --- The cargo must be in the **UnLoaded** state. --- @function [parent=#CARGO] __Board --- @param #CARGO self --- @param #number DelaySeconds The amount of seconds to delay the action. --- @param Wrapper.Controllable#CONTROLLABLE ToCarrier The Carrier that will hold the cargo. --- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision). - - --- UnBoard - ---- UnBoards the cargo to a Carrier. The event will create a movement (= running or driving) of the cargo from the Carrier. --- The cargo must be in the **Loaded** state. --- @function [parent=#CARGO] UnBoard --- @param #CARGO self --- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location. - ---- UnBoards the cargo to a Carrier. The event will create a movement (= running or driving) of the cargo from the Carrier. --- The cargo must be in the **Loaded** state. --- @function [parent=#CARGO] __UnBoard --- @param #CARGO self --- @param #number DelaySeconds The amount of seconds to delay the action. --- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location. - - --- Load - ---- Loads the cargo to a Carrier. The event will load the cargo into the Carrier regardless of its position. There will be no movement simulated of the cargo loading. --- The cargo must be in the **UnLoaded** state. --- @function [parent=#CARGO] Load --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE ToCarrier The Carrier that will hold the cargo. - ---- Loads the cargo to a Carrier. The event will load the cargo into the Carrier regardless of its position. There will be no movement simulated of the cargo loading. --- The cargo must be in the **UnLoaded** state. --- @function [parent=#CARGO] __Load --- @param #CARGO self --- @param #number DelaySeconds The amount of seconds to delay the action. --- @param Wrapper.Controllable#CONTROLLABLE ToCarrier The Carrier that will hold the cargo. - - --- UnLoad - ---- UnLoads the cargo to a Carrier. The event will unload the cargo from the Carrier. There will be no movement simulated of the cargo loading. --- The cargo must be in the **Loaded** state. --- @function [parent=#CARGO] UnLoad --- @param #CARGO self --- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location. - ---- UnLoads the cargo to a Carrier. The event will unload the cargo from the Carrier. There will be no movement simulated of the cargo loading. --- The cargo must be in the **Loaded** state. --- @function [parent=#CARGO] __UnLoad --- @param #CARGO self --- @param #number DelaySeconds The amount of seconds to delay the action. --- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location. - --- State Transition Functions - --- UnLoaded - ---- @function [parent=#CARGO] OnLeaveUnLoaded --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE Controllable --- @return #boolean - ---- @function [parent=#CARGO] OnEnterUnLoaded --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE Controllable - --- Loaded - ---- @function [parent=#CARGO] OnLeaveLoaded --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE Controllable --- @return #boolean - ---- @function [parent=#CARGO] OnEnterLoaded --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE Controllable - --- Boarding - ---- @function [parent=#CARGO] OnLeaveBoarding --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE Controllable --- @return #boolean - ---- @function [parent=#CARGO] OnEnterBoarding --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE Controllable --- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision). - --- UnBoarding - ---- @function [parent=#CARGO] OnLeaveUnBoarding --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE Controllable --- @return #boolean - ---- @function [parent=#CARGO] OnEnterUnBoarding --- @param #CARGO self --- @param Wrapper.Controllable#CONTROLLABLE Controllable - - --- TODO: Find all Carrier objects and make the type of the Carriers Wrapper.Unit#UNIT in the documentation. - -CARGOS = {} - -do -- CARGO - - --- @type CARGO - -- @extends Core.Fsm#FSM_PROCESS - -- @field #string Type A string defining the type of the cargo. eg. Engineers, Equipment, Screwdrivers. - -- @field #string Name A string defining the name of the cargo. The name is the unique identifier of the cargo. - -- @field #number Weight A number defining the weight of the cargo. The weight is expressed in kg. - -- @field #number NearRadius (optional) A number defining the radius in meters when the cargo is near to a Carrier, so that it can be loaded. - -- @field Wrapper.Unit#UNIT CargoObject The alive DCS object representing the cargo. This value can be nil, meaning, that the cargo is not represented anywhere... - -- @field Wrapper.Client#CLIENT CargoCarrier The alive DCS object carrying the cargo. This value can be nil, meaning, that the cargo is not contained anywhere... - -- @field #boolean Slingloadable This flag defines if the cargo can be slingloaded. - -- @field #boolean Moveable This flag defines if the cargo is moveable. - -- @field #boolean Representable This flag defines if the cargo can be represented by a DCS Unit. - -- @field #boolean Containable This flag defines if the cargo can be contained within a DCS Unit. - - --- Defines the core functions that defines a cargo object within MOOSE. - -- - -- A cargo is a **logical object** defined that is available for transport, and has a life status within a simulation. - -- - -- CARGO is not meant to be used directly by mission designers, but provides a base class for **concrete cargo implementation classes** to handle: - -- - -- * Cargo **group objects**, implemented by the @{Cargo.CargoGroup#CARGO_GROUP} class. - -- * Cargo **Unit objects**, implemented by the @{Cargo.CargoUnit#CARGO_UNIT} class. - -- * Cargo **Crate objects**, implemented by the @{Cargo.CargoCrate#CARGO_CRATE} class. - -- * Cargo **Sling Load objects**, implemented by the @{Cargo.CargoSlingload#CARGO_SLINGLOAD} class. - -- - -- The above cargo classes are used by the AI\_CARGO\_ classes to allow AI groups to transport cargo: - -- - -- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC#AI_CARGO_APC} class. - -- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter#AI_CARGO_HELICOPTER} class. - -- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane#AI_CARGO_AIRPLANE} class. - -- * AI Ships is planned. - -- - -- The above cargo classes are also used by the TASK\_CARGO\_ classes to allow human players to transport cargo as part of a tasking: - -- - -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players. - -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players. - -- - -- - -- The CARGO is a state machine: it manages the different events and states of the cargo. - -- All derived classes from CARGO follow the same state machine, expose the same cargo event functions, and provide the same cargo states. - -- - -- ## CARGO Events: - -- - -- * @{#CARGO.Board}( ToCarrier ): Boards the cargo to a carrier. - -- * @{#CARGO.Load}( ToCarrier ): Loads the cargo into a carrier, regardless of its position. - -- * @{#CARGO.UnBoard}( ToPointVec2 ): UnBoard the cargo from a carrier. This will trigger a movement of the cargo to the option ToPointVec2. - -- * @{#CARGO.UnLoad}( ToPointVec2 ): UnLoads the cargo from a carrier. - -- * @{#CARGO.Destroyed}( Controllable ): The cargo is dead. The cargo process will be ended. - -- - -- @field #CARGO - CARGO = { - ClassName = "CARGO", - Type = nil, - Name = nil, - Weight = nil, - CargoObject = nil, - CargoCarrier = nil, - Representable = false, - Slingloadable = false, - Moveable = false, - Containable = false, - Reported = {}, - } - - -- @type CARGO.CargoObjects - -- @map < #string, Wrapper.Positionable#POSITIONABLE > The alive POSITIONABLE objects representing the the cargo. - - --- CARGO Constructor. This class is an abstract class and should not be instantiated. - -- @param #CARGO self - -- @param #string Type - -- @param #string Name - -- @param #number Weight - -- @param #number LoadRadius (optional) - -- @param #number NearRadius (optional) - -- @return #CARGO - function CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) --R2.1 - - local self = BASE:Inherit( self, FSM:New() ) -- #CARGO - self:T( { Type, Name, Weight, LoadRadius, NearRadius } ) - - self:SetStartState( "UnLoaded" ) - self:AddTransition( { "UnLoaded", "Boarding" }, "Board", "Boarding" ) - self:AddTransition( "Boarding" , "Boarding", "Boarding" ) - self:AddTransition( "Boarding", "CancelBoarding", "UnLoaded" ) - self:AddTransition( "Boarding", "Load", "Loaded" ) - self:AddTransition( "UnLoaded", "Load", "Loaded" ) - self:AddTransition( "Loaded", "UnBoard", "UnBoarding" ) - self:AddTransition( "UnBoarding", "UnBoarding", "UnBoarding" ) - self:AddTransition( "UnBoarding", "UnLoad", "UnLoaded" ) - self:AddTransition( "Loaded", "UnLoad", "UnLoaded" ) - self:AddTransition( "*", "Damaged", "Damaged" ) - self:AddTransition( "*", "Destroyed", "Destroyed" ) - self:AddTransition( "*", "Respawn", "UnLoaded" ) - self:AddTransition( "*", "Reset", "UnLoaded" ) - - self.Type = Type - self.Name = Name - self.Weight = Weight or 0 - self.CargoObject = nil -- Wrapper.Group#GROUP - self.CargoCarrier = nil -- Wrapper.Client#CLIENT - self.Representable = false - self.Slingloadable = false - self.Moveable = false - self.Containable = false - - self.CargoLimit = 0 - - self.LoadRadius = LoadRadius or 500 - --self.NearRadius = NearRadius or 25 - - self:SetDeployed( false ) - - self.CargoScheduler = SCHEDULER:New() - - CARGOS[self.Name] = self - - return self - end - - --- Find a CARGO in the _DATABASE. - -- @param #CARGO self - -- @param #string CargoName The Cargo Name. - -- @return #CARGO self - function CARGO:FindByName( CargoName ) - - local CargoFound = _DATABASE:FindCargo( CargoName ) - return CargoFound - end - - --- Get the x position of the cargo. - -- @param #CARGO self - -- @return #number - function CARGO:GetX() - if self:IsLoaded() then - return self.CargoCarrier:GetCoordinate().x - else - return self.CargoObject:GetCoordinate().x - end - end - - --- Get the y position of the cargo. - -- @param #CARGO self - -- @return #number - function CARGO:GetY() - if self:IsLoaded() then - return self.CargoCarrier:GetCoordinate().z - else - return self.CargoObject:GetCoordinate().z - end - end - - --- Get the heading of the cargo. - -- @param #CARGO self - -- @return #number - function CARGO:GetHeading() - if self:IsLoaded() then - return self.CargoCarrier:GetHeading() - else - return self.CargoObject:GetHeading() - end - end - - --- Check if the cargo can be Slingloaded. - -- @param #CARGO self - function CARGO:CanSlingload() - return false - end - - --- Check if the cargo can be Boarded. - -- @param #CARGO self - function CARGO:CanBoard() - return true - end - - --- Check if the cargo can be Unboarded. - -- @param #CARGO self - function CARGO:CanUnboard() - return true - end - - --- Check if the cargo can be Loaded. - -- @param #CARGO self - function CARGO:CanLoad() - return true - end - - --- Check if the cargo can be Unloaded. - -- @param #CARGO self - function CARGO:CanUnload() - return true - end - - --- Destroy the cargo. - -- @param #CARGO self - function CARGO:Destroy() - if self.CargoObject then - self.CargoObject:Destroy() - end - self:Destroyed() - end - - --- Get the name of the Cargo. - -- @param #CARGO self - -- @return #string The name of the Cargo. - function CARGO:GetName() --R2.1 - return self.Name - end - - --- Get the current active object representing or being the Cargo. - -- @param #CARGO self - -- @return Wrapper.Positionable#POSITIONABLE The object representing or being the Cargo. - function CARGO:GetObject() - if self:IsLoaded() then - return self.CargoCarrier - else - return self.CargoObject - end - end - - --- Get the object name of the Cargo. - -- @param #CARGO self - -- @return #string The object name of the Cargo. - function CARGO:GetObjectName() --R2.1 - if self:IsLoaded() then - return self.CargoCarrier:GetName() - else - return self.CargoObject:GetName() - end - end - - --- Get the amount of Cargo. - -- @param #CARGO self - -- @return #number The amount of Cargo. - function CARGO:GetCount() - return 1 - end - - --- Get the type of the Cargo. - -- @param #CARGO self - -- @return #string The type of the Cargo. - function CARGO:GetType() - return self.Type - end - - --- Get the transportation method of the Cargo. - -- @param #CARGO self - -- @return #string The transportation method of the Cargo. - function CARGO:GetTransportationMethod() - return self.TransportationMethod - end - - --- Get the coalition of the Cargo. - -- @param #CARGO self - -- @return Coalition - function CARGO:GetCoalition() - if self:IsLoaded() then - return self.CargoCarrier:GetCoalition() - else - return self.CargoObject:GetCoalition() - end - end - - --- Get the current coordinates of the Cargo. - -- @param #CARGO self - -- @return Core.Point#COORDINATE The coordinates of the Cargo. - function CARGO:GetCoordinate() - return self.CargoObject:GetCoordinate() - end - - --- Check if cargo is destroyed. - -- @param #CARGO self - -- @return #boolean true if destroyed - function CARGO:IsDestroyed() - return self:Is( "Destroyed" ) - end - - --- Check if cargo is loaded. - -- @param #CARGO self - -- @return #boolean true if loaded - function CARGO:IsLoaded() - return self:Is( "Loaded" ) - end - - --- Check if cargo is loaded. - -- @param #CARGO self - -- @param Wrapper.Unit#UNIT Carrier - -- @return #boolean true if loaded - function CARGO:IsLoadedInCarrier( Carrier ) - return self.CargoCarrier and self.CargoCarrier:GetName() == Carrier:GetName() - end - - --- Check if cargo is unloaded. - -- @param #CARGO self - -- @return #boolean true if unloaded - function CARGO:IsUnLoaded() - return self:Is( "UnLoaded" ) - end - - --- Check if cargo is boarding. - -- @param #CARGO self - -- @return #boolean true if boarding - function CARGO:IsBoarding() - return self:Is( "Boarding" ) - end - - --- Check if cargo is unboarding. - -- @param #CARGO self - -- @return #boolean true if unboarding - function CARGO:IsUnboarding() - return self:Is( "UnBoarding" ) - end - - --- Check if cargo is alive. - -- @param #CARGO self - -- @return #boolean true if unloaded - function CARGO:IsAlive() - - if self:IsLoaded() then - return self.CargoCarrier:IsAlive() - else - return self.CargoObject:IsAlive() - end - end - - --- Set the cargo as deployed. - -- @param #CARGO self - -- @param #boolean Deployed true if the cargo is to be deployed. false or nil otherwise. - function CARGO:SetDeployed( Deployed ) - self.Deployed = Deployed - end - - --- Is the cargo deployed - -- @param #CARGO self - -- @return #boolean - function CARGO:IsDeployed() - return self.Deployed - end - - --- Template method to spawn a new representation of the CARGO in the simulator. - -- @param #CARGO self - -- @return #CARGO - function CARGO:Spawn( PointVec2 ) - self:T() - - end - - --- Signal a flare at the position of the CARGO. - -- @param #CARGO self - -- @param Utilities.Utils#FLARECOLOR FlareColor - function CARGO:Flare( FlareColor ) - if self:IsUnLoaded() then - trigger.action.signalFlare( self.CargoObject:GetVec3(), FlareColor , 0 ) - end - end - - --- Signal a white flare at the position of the CARGO. - -- @param #CARGO self - function CARGO:FlareWhite() - self:Flare( trigger.flareColor.White ) - end - - --- Signal a yellow flare at the position of the CARGO. - -- @param #CARGO self - function CARGO:FlareYellow() - self:Flare( trigger.flareColor.Yellow ) - end - - --- Signal a green flare at the position of the CARGO. - -- @param #CARGO self - function CARGO:FlareGreen() - self:Flare( trigger.flareColor.Green ) - end - - --- Signal a red flare at the position of the CARGO. - -- @param #CARGO self - function CARGO:FlareRed() - self:Flare( trigger.flareColor.Red ) - end - - --- Smoke the CARGO. - -- @param #CARGO self - -- @param Utilities.Utils#SMOKECOLOR SmokeColor The color of the smoke. - -- @param #number Radius The radius of randomization around the center of the Cargo. - function CARGO:Smoke( SmokeColor, Radius ) - if self:IsUnLoaded() then - if Radius then - trigger.action.smoke( self.CargoObject:GetRandomVec3( Radius ), SmokeColor ) - else - trigger.action.smoke( self.CargoObject:GetVec3(), SmokeColor ) - end - end - end - - --- Smoke the CARGO Green. - -- @param #CARGO self - function CARGO:SmokeGreen() - self:Smoke( trigger.smokeColor.Green, Range ) - end - - --- Smoke the CARGO Red. - -- @param #CARGO self - function CARGO:SmokeRed() - self:Smoke( trigger.smokeColor.Red, Range ) - end - - --- Smoke the CARGO White. - -- @param #CARGO self - function CARGO:SmokeWhite() - self:Smoke( trigger.smokeColor.White, Range ) - end - - --- Smoke the CARGO Orange. - -- @param #CARGO self - function CARGO:SmokeOrange() - self:Smoke( trigger.smokeColor.Orange, Range ) - end - - --- Smoke the CARGO Blue. - -- @param #CARGO self - function CARGO:SmokeBlue() - self:Smoke( trigger.smokeColor.Blue, Range ) - end - - --- Set the Load radius, which is the radius till when the Cargo can be loaded. - -- @param #CARGO self - -- @param #number LoadRadius The radius till Cargo can be loaded. - -- @return #CARGO - function CARGO:SetLoadRadius( LoadRadius ) - self.LoadRadius = LoadRadius or 150 - end - - --- Get the Load radius, which is the radius till when the Cargo can be loaded. - -- @param #CARGO self - -- @return #number The radius till Cargo can be loaded. - function CARGO:GetLoadRadius() - return self.LoadRadius - end - - --- Check if Cargo is in the LoadRadius for the Cargo to be Boarded or Loaded. - -- @param #CARGO self - -- @param Core.Point#COORDINATE Coordinate - -- @return #boolean true if the CargoGroup is within the loading radius. - function CARGO:IsInLoadRadius( Coordinate ) - self:T( { Coordinate, LoadRadius = self.LoadRadius } ) - - local Distance = 0 - if self:IsUnLoaded() then - local CargoCoordinate = self.CargoObject:GetCoordinate() - Distance = Coordinate:Get2DDistance( CargoCoordinate ) - self:T( Distance ) - if Distance <= self.LoadRadius then - return true - end - end - - return false - end - - --- Check if the Cargo can report itself to be Boarded or Loaded. - -- @param #CARGO self - -- @param Core.Point#COORDINATE Coordinate - -- @return #boolean true if the Cargo can report itself. - function CARGO:IsInReportRadius( Coordinate ) - self:T( { Coordinate } ) - - local Distance = 0 - if self:IsUnLoaded() then - Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() ) - self:T( Distance ) - if Distance <= self.LoadRadius then - return true - end - end - - return false - end - - - --- Check if CargoCarrier is near the coordinate within NearRadius. - -- @param #CARGO self - -- @param Core.Point#COORDINATE Coordinate - -- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision). - -- @return #boolean - function CARGO:IsNear( Coordinate, NearRadius ) - --self:T( { PointVec2 = PointVec2, NearRadius = NearRadius } ) - - if self.CargoObject:IsAlive() then - --local Distance = PointVec2:Get2DDistance( self.CargoObject:GetPointVec2() ) - --self:T( { CargoObjectName = self.CargoObject:GetName() } ) - --self:T( { CargoObjectVec2 = self.CargoObject:GetVec2() } ) - --self:T( { PointVec2 = PointVec2:GetVec2() } ) - local Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() ) - --self:T( { Distance = Distance, NearRadius = NearRadius or "nil" } ) - - if Distance <= NearRadius then - --self:T( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = true } ) - return true - end - end - - --self:T( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = false } ) - return false - end - - --- Check if Cargo is the given @{Core.Zone}. - -- @param #CARGO self - -- @param Core.Zone#ZONE_BASE Zone - -- @return #boolean **true** if cargo is in the Zone, **false** if cargo is not in the Zone. - function CARGO:IsInZone( Zone ) - --self:T( { Zone } ) - - if self:IsLoaded() then - return Zone:IsPointVec2InZone( self.CargoCarrier:GetPointVec2() ) - else - --self:T( { Size = self.CargoObject:GetSize(), Units = self.CargoObject:GetUnits() } ) - if self.CargoObject:GetSize() ~= 0 then - return Zone:IsPointVec2InZone( self.CargoObject:GetPointVec2() ) - else - return false - end - end - - return nil - - end - - --- Get the current PointVec2 of the cargo. - -- @param #CARGO self - -- @return Core.Point#COORDINATE - function CARGO:GetPointVec2() - return self.CargoObject:GetPointVec2() - end - - --- Get the current Coordinate of the cargo. - -- @param #CARGO self - -- @return Core.Point#COORDINATE - function CARGO:GetCoordinate() - return self.CargoObject:GetCoordinate() - end - - --- Get the weight of the cargo. - -- @param #CARGO self - -- @return #number Weight The weight in kg. - function CARGO:GetWeight() - return self.Weight - end - - --- Set the weight of the cargo. - -- @param #CARGO self - -- @param #number Weight The weight in kg. - -- @return #CARGO - function CARGO:SetWeight( Weight ) - self.Weight = Weight - return self - end - - --- Get the volume of the cargo. - -- @param #CARGO self - -- @return #number Volume The volume in kg. - function CARGO:GetVolume() - return self.Volume - end - - --- Set the volume of the cargo. - -- @param #CARGO self - -- @param #number Volume The volume in kg. - -- @return #CARGO - function CARGO:SetVolume( Volume ) - self.Volume = Volume - return self - end - - --- Send a CC message to a @{Wrapper.Group}. - -- @param #CARGO self - -- @param #string Message - -- @param Wrapper.Group#GROUP CarrierGroup The Carrier Group. - -- @param #string Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown. - function CARGO:MessageToGroup( Message, CarrierGroup, Name ) - - MESSAGE:New( Message, 20, "Cargo " .. self:GetName() ):ToGroup( CarrierGroup ) - - end - - --- Report to a Carrier Group. - -- @param #CARGO self - -- @param #string Action The string describing the action for the cargo. - -- @param Wrapper.Group#GROUP CarrierGroup The Carrier Group to send the report to. - -- @return #CARGO - function CARGO:Report( ReportText, Action, CarrierGroup ) - - if not self.Reported[CarrierGroup] or not self.Reported[CarrierGroup][Action] then - self.Reported[CarrierGroup] = {} - self.Reported[CarrierGroup][Action] = true - self:MessageToGroup( ReportText, CarrierGroup ) - if self.ReportFlareColor then - if not self.Reported[CarrierGroup]["Flaring"] then - self:Flare( self.ReportFlareColor ) - self.Reported[CarrierGroup]["Flaring"] = true - end - end - if self.ReportSmokeColor then - if not self.Reported[CarrierGroup]["Smoking"] then - self:Smoke( self.ReportSmokeColor ) - self.Reported[CarrierGroup]["Smoking"] = true - end - end - end - end - - --- Report to a Carrier Group with a Flaring signal. - -- @param #CARGO self - -- @param Utilities.Utils#UTILS.FlareColor FlareColor the color of the flare. - -- @return #CARGO - function CARGO:ReportFlare( FlareColor ) - - self.ReportFlareColor = FlareColor - end - - --- Report to a Carrier Group with a Smoking signal. - -- @param #CARGO self - -- @param Utilities.Utils#UTILS.SmokeColor SmokeColor the color of the smoke. - -- @return #CARGO - function CARGO:ReportSmoke( SmokeColor ) - - self.ReportSmokeColor = SmokeColor - end - - --- Reset the reporting for a Carrier Group. - -- @param #CARGO self - -- @param #string Action The string describing the action for the cargo. - -- @param Wrapper.Group#GROUP CarrierGroup The Carrier Group to send the report to. - -- @return #CARGO - function CARGO:ReportReset( Action, CarrierGroup ) - - self.Reported[CarrierGroup][Action] = nil - end - - --- Reset all the reporting for a Carrier Group. - -- @param #CARGO self - -- @param Wrapper.Group#GROUP CarrierGroup The Carrier Group to send the report to. - -- @return #CARGO - function CARGO:ReportResetAll( CarrierGroup ) - - self.Reported[CarrierGroup] = nil - end - - --- Respawn the cargo when destroyed - -- @param #CARGO self - -- @param #boolean RespawnDestroyed - function CARGO:RespawnOnDestroyed( RespawnDestroyed ) - - if RespawnDestroyed then - self.onenterDestroyed = function( self ) - self:Respawn() - end - else - self.onenterDestroyed = nil - end - - end - -end -- CARGO - -do -- CARGO_REPRESENTABLE - - -- @type CARGO_REPRESENTABLE - -- @extends #CARGO - -- @field test - - --- Models CARGO that is representable by a Unit. - -- @field #CARGO_REPRESENTABLE CARGO_REPRESENTABLE - CARGO_REPRESENTABLE = { - ClassName = "CARGO_REPRESENTABLE" - } - - --- CARGO_REPRESENTABLE Constructor. - -- @param #CARGO_REPRESENTABLE self - -- @param Wrapper.Positionable#POSITIONABLE CargoObject The cargo object. - -- @param #string Type Type name - -- @param #string Name Name. - -- @param #number LoadRadius (optional) Radius in meters. - -- @param #number NearRadius (optional) Radius in meters when the cargo is loaded into the carrier. - -- @return #CARGO_REPRESENTABLE - function CARGO_REPRESENTABLE:New( CargoObject, Type, Name, LoadRadius, NearRadius ) - - -- Inherit CARGO. - local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE - self:T( { Type, Name, LoadRadius, NearRadius } ) - - -- Descriptors. - local Desc=CargoObject:GetDesc() - self:T({Desc=Desc}) - - -- Weight. - local Weight = math.random( 80, 120 ) - - -- Adjust weight.. - if Desc then - if Desc.typeName == "2B11 mortar" then - Weight = 210 - else - Weight = Desc.massEmpty - end - end - - -- Set weight. - self:SetWeight( Weight ) - - return self - end - - --- CARGO_REPRESENTABLE Destructor. - -- @param #CARGO_REPRESENTABLE self - -- @return #CARGO_REPRESENTABLE - function CARGO_REPRESENTABLE:Destroy() - - -- Cargo objects are deleted from the _DATABASE and SET_CARGO objects. - self:T( { CargoName = self:GetName() } ) - --_EVENTDISPATCHER:CreateEventDeleteCargo( self ) - - return self - end - - --- Route a cargo unit to a PointVec2. - -- @param #CARGO_REPRESENTABLE self - -- @param Core.Point#COORDINATE ToPointVec2 - -- @param #number Speed - -- @return #CARGO_REPRESENTABLE - function CARGO_REPRESENTABLE:RouteTo( ToPointVec2, Speed ) - self:F2( ToPointVec2 ) - - local Points = {} - - local PointStartVec2 = self.CargoObject:GetPointVec2() - - Points[#Points+1] = PointStartVec2:WaypointGround( Speed ) - Points[#Points+1] = ToPointVec2:WaypointGround( Speed ) - - local TaskRoute = self.CargoObject:TaskRoute( Points ) - self.CargoObject:SetTask( TaskRoute, 2 ) - return self - end - - --- Send a message to a @{Wrapper.Group} through a communication channel near the cargo. - -- @param #CARGO_REPRESENTABLE self - -- @param #string Message - -- @param Wrapper.Group#GROUP TaskGroup - -- @param #string Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown. - function CARGO_REPRESENTABLE:MessageToGroup( Message, TaskGroup, Name ) - - local CoordinateZone = ZONE_RADIUS:New( "Zone" , self:GetCoordinate():GetVec2(), 500 ) - CoordinateZone:Scan( { Object.Category.UNIT } ) - for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do - local NearUnit = UNIT:Find( DCSUnit ) - self:T({NearUnit=NearUnit}) - local NearUnitCoalition = NearUnit:GetCoalition() - local CargoCoalition = self:GetCoalition() - if NearUnitCoalition == CargoCoalition then - local Attributes = NearUnit:GetDesc() - self:T({Desc=Attributes}) - if NearUnit:HasAttribute( "Trucks" ) then - MESSAGE:New( Message, 20, NearUnit:GetCallsign() .. " reporting - Cargo " .. self:GetName() ):ToGroup( TaskGroup ) - break - end - end - end - - end - -end -- CARGO_REPRESENTABLE - -do -- CARGO_REPORTABLE - - -- @type CARGO_REPORTABLE - -- @extends #CARGO - CARGO_REPORTABLE = { - ClassName = "CARGO_REPORTABLE" - } - - --- CARGO_REPORTABLE Constructor. - -- @param #CARGO_REPORTABLE self - -- @param #string Type - -- @param #string Name - -- @param #number Weight - -- @param #number LoadRadius (optional) - -- @param #number NearRadius (optional) - -- @return #CARGO_REPORTABLE - function CARGO_REPORTABLE:New( Type, Name, Weight, LoadRadius, NearRadius ) - local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_REPORTABLE - self:T( { Type, Name, Weight, LoadRadius, NearRadius } ) - - return self - end - - --- Send a CC message to a @{Wrapper.Group}. - -- @param #CARGO_REPORTABLE self - -- @param #string Message - -- @param Wrapper.Group#GROUP TaskGroup - -- @param #string Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown. - function CARGO_REPORTABLE:MessageToGroup( Message, TaskGroup, Name ) - - MESSAGE:New( Message, 20, "Cargo " .. self:GetName() .. " reporting" ):ToGroup( TaskGroup ) - - end - -end - -do -- CARGO_PACKAGE - - -- @type CARGO_PACKAGE - -- @extends #CARGO_REPRESENTABLE - CARGO_PACKAGE = { - ClassName = "CARGO_PACKAGE" - } - ---- CARGO_PACKAGE Constructor. --- @param #CARGO_PACKAGE self --- @param Wrapper.Unit#UNIT CargoCarrier The UNIT carrying the package. --- @param #string Type --- @param #string Name --- @param #number Weight --- @param #number LoadRadius (optional) --- @param #number NearRadius (optional) --- @return #CARGO_PACKAGE -function CARGO_PACKAGE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius ) - local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_PACKAGE - self:T( { Type, Name, Weight, LoadRadius, NearRadius } ) - - self:T( CargoCarrier ) - self.CargoCarrier = CargoCarrier - - return self -end - ---- Board Event. --- @param #CARGO_PACKAGE self --- @param #string Event --- @param #string From --- @param #string To --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #number Speed --- @param #number BoardDistance --- @param #number Angle -function CARGO_PACKAGE:onafterOnBoard( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle ) - self:T() - - self.CargoInAir = self.CargoCarrier:InAir() - - self:T( self.CargoInAir ) - - -- Only move the CargoCarrier to the New CargoCarrier when the New CargoCarrier is not in the air. - if not self.CargoInAir then - - local Points = {} - - local StartPointVec2 = self.CargoCarrier:GetPointVec2() - local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - self:T( { CargoCarrierHeading, CargoDeployHeading } ) - local CargoDeployPointVec2 = CargoCarrier:GetPointVec2():Translate( BoardDistance, CargoDeployHeading ) - - Points[#Points+1] = StartPointVec2:WaypointGround( Speed ) - Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed ) - - local TaskRoute = self.CargoCarrier:TaskRoute( Points ) - self.CargoCarrier:SetTask( TaskRoute, 1 ) - end - - self:Boarded( CargoCarrier, Speed, BoardDistance, LoadDistance, Angle ) - -end - ---- Check if CargoCarrier is near the Cargo to be Loaded. --- @param #CARGO_PACKAGE self --- @param Wrapper.Unit#UNIT CargoCarrier --- @return #boolean -function CARGO_PACKAGE:IsNear( CargoCarrier ) - self:T() - - local CargoCarrierPoint = CargoCarrier:GetCoordinate() - - local Distance = CargoCarrierPoint:Get2DDistance( self.CargoCarrier:GetCoordinate() ) - self:T( Distance ) - - if Distance <= self.NearRadius then - return true - else - return false - end -end - ---- Boarded Event. --- @param #CARGO_PACKAGE self --- @param #string Event --- @param #string From --- @param #string To --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #number Speed --- @param #number BoardDistance --- @param #number LoadDistance --- @param #number Angle -function CARGO_PACKAGE:onafterOnBoarded( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle ) - self:T() - - if self:IsNear( CargoCarrier ) then - self:__Load( 1, CargoCarrier, Speed, LoadDistance, Angle ) - else - self:__Boarded( 1, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle ) - end -end - ---- UnBoard Event. --- @param #CARGO_PACKAGE self --- @param #string Event --- @param #string From --- @param #string To --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #number Speed --- @param #number UnLoadDistance --- @param #number UnBoardDistance --- @param #number Radius --- @param #number Angle -function CARGO_PACKAGE:onafterUnBoard( From, Event, To, CargoCarrier, Speed, UnLoadDistance, UnBoardDistance, Radius, Angle ) - self:T() - - self.CargoInAir = self.CargoCarrier:InAir() - - self:T( self.CargoInAir ) - - -- Only unboard the cargo when the carrier is not in the air. - -- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea). - if not self.CargoInAir then - - self:_Next( self.FsmP.UnLoad, UnLoadDistance, Angle ) - - local Points = {} - - local StartPointVec2 = CargoCarrier:GetPointVec2() - local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - self:T( { CargoCarrierHeading, CargoDeployHeading } ) - local CargoDeployPointVec2 = StartPointVec2:Translate( UnBoardDistance, CargoDeployHeading ) - - Points[#Points+1] = StartPointVec2:WaypointGround( Speed ) - Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed ) - - local TaskRoute = CargoCarrier:TaskRoute( Points ) - CargoCarrier:SetTask( TaskRoute, 1 ) - end - - self:__UnBoarded( 1 , CargoCarrier, Speed ) - -end - ---- UnBoarded Event. --- @param #CARGO_PACKAGE self --- @param #string Event --- @param #string From --- @param #string To --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #number Speed -function CARGO_PACKAGE:onafterUnBoarded( From, Event, To, CargoCarrier, Speed ) - self:T() - - if self:IsNear( CargoCarrier ) then - self:__UnLoad( 1, CargoCarrier, Speed ) - else - self:__UnBoarded( 1, CargoCarrier, Speed ) - end -end - ---- Load Event. --- @param #CARGO_PACKAGE self --- @param #string Event --- @param #string From --- @param #string To --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #number Speed --- @param #number LoadDistance --- @param #number Angle -function CARGO_PACKAGE:onafterLoad( From, Event, To, CargoCarrier, Speed, LoadDistance, Angle ) - self:T() - - self.CargoCarrier = CargoCarrier - - local StartPointVec2 = self.CargoCarrier:GetPointVec2() - local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - local CargoDeployPointVec2 = StartPointVec2:Translate( LoadDistance, CargoDeployHeading ) - - local Points = {} - Points[#Points+1] = StartPointVec2:WaypointGround( Speed ) - Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed ) - - local TaskRoute = self.CargoCarrier:TaskRoute( Points ) - self.CargoCarrier:SetTask( TaskRoute, 1 ) - -end - ---- UnLoad Event. --- @param #CARGO_PACKAGE self --- @param #string Event --- @param #string From --- @param #string To --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #number Speed --- @param #number Distance --- @param #number Angle -function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Distance, Angle ) - self:T() - - local StartPointVec2 = self.CargoCarrier:GetPointVec2() - local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - local CargoDeployPointVec2 = StartPointVec2:Translate( Distance, CargoDeployHeading ) - - self.CargoCarrier = CargoCarrier - - local Points = {} - Points[#Points+1] = StartPointVec2:WaypointGround( Speed ) - Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed ) - - local TaskRoute = self.CargoCarrier:TaskRoute( Points ) - self.CargoCarrier:SetTask( TaskRoute, 1 ) - -end - -end diff --git a/Moose Development/Moose/Cargo/CargoCrate.lua b/Moose Development/Moose/Cargo/CargoCrate.lua deleted file mode 100644 index b9dcb2761..000000000 --- a/Moose Development/Moose/Cargo/CargoCrate.lua +++ /dev/null @@ -1,340 +0,0 @@ ---- **Cargo** - Management of single cargo crates, which are based on a STATIC object. --- --- === --- --- ### [Demo Missions]() --- --- ### [YouTube Playlist]() --- --- === --- --- ### Author: **FlightControl** --- ### Contributions: --- --- === --- --- @module Cargo.CargoCrate --- @image Cargo_Crates.JPG - -do -- CARGO_CRATE - - --- Models the behaviour of cargo crates, which can be slingloaded and boarded on helicopters. - -- @type CARGO_CRATE - -- @extends Cargo.Cargo#CARGO_REPRESENTABLE - - --- - -- ![Banner Image](..\Images\deprecated.png) - -- - --- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier. - -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers. - -- - -- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo: - -- - -- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC} module. - -- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter} module. - -- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane} module. - -- * AI Ships is planned. - -- - -- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking: - -- - -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players. - -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players. - -- - -- # Developer Note - -- - -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE - -- Therefore, this class is considered to be deprecated - -- - -- === - -- - -- @field #CARGO_CRATE - CARGO_CRATE = { - ClassName = "CARGO_CRATE" - } - - --- CARGO_CRATE Constructor. - -- @param #CARGO_CRATE self - -- @param Wrapper.Static#STATIC CargoStatic - -- @param #string Type - -- @param #string Name - -- @param #number LoadRadius (optional) - -- @param #number NearRadius (optional) - -- @return #CARGO_CRATE - function CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius ) - local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_CRATE - self:T( { Type, Name, NearRadius } ) - - self.CargoObject = CargoStatic -- Wrapper.Static#STATIC - - -- Cargo objects are added to the _DATABASE and SET_CARGO objects. - _EVENTDISPATCHER:CreateEventNewCargo( self ) - - self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead ) - self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead ) - --self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCargoDead ) - self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead ) - - self:SetEventPriority( 4 ) - - self.NearRadius = NearRadius or 25 - - return self - end - - -- @param #CARGO_CRATE self - -- @param Core.Event#EVENTDATA EventData - function CARGO_CRATE:OnEventCargoDead( EventData ) - - local Destroyed = false - - if self:IsDestroyed() or self:IsUnLoaded() or self:IsBoarding() then - if self.CargoObject:GetName() == EventData.IniUnitName then - if not self.NoDestroy then - Destroyed = true - end - end - else - if self:IsLoaded() then - local CarrierName = self.CargoCarrier:GetName() - if CarrierName == EventData.IniDCSUnitName then - MESSAGE:New( "Cargo is lost from carrier " .. CarrierName, 15 ):ToAll() - Destroyed = true - self.CargoCarrier:ClearCargo() - end - end - end - - if Destroyed then - self:I( { "Cargo crate destroyed: " .. self.CargoObject:GetName() } ) - self:Destroyed() - end - - end - - - --- Enter UnLoaded State. - -- @param #CARGO_CRATE self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Core.Point#COORDINATE - function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 ) - --self:T( { ToPointVec2, From, Event, To } ) - - local Angle = 180 - local Speed = 10 - local Distance = 10 - - if From == "Loaded" then - local StartCoordinate = self.CargoCarrier:GetCoordinate() - local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - local CargoDeployCoord = StartCoordinate:Translate( Distance, CargoDeployHeading ) - - ToPointVec2 = ToPointVec2 or COORDINATE:NewFromVec2( { x= CargoDeployCoord.x, y = CargoDeployCoord.z } ) - - -- Respawn the group... - if self.CargoObject then - self.CargoObject:ReSpawnAt( ToPointVec2, 0 ) - self.CargoCarrier = nil - end - - end - - if self.OnUnLoadedCallBack then - self.OnUnLoadedCallBack( self, unpack( self.OnUnLoadedParameters ) ) - self.OnUnLoadedCallBack = nil - end - - end - - - --- Loaded State. - -- @param #CARGO_CRATE self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Wrapper.Unit#UNIT CargoCarrier - function CARGO_CRATE:onenterLoaded( From, Event, To, CargoCarrier ) - --self:T( { From, Event, To, CargoCarrier } ) - - self.CargoCarrier = CargoCarrier - - -- Only destroy the CargoObject is if there is a CargoObject (packages don't have CargoObjects). - if self.CargoObject then - self:T("Destroying") - self.NoDestroy = true - self.CargoObject:Destroy( false ) -- Do not generate a remove unit event, because we want to keep the template for later respawn in the database. - --local Coordinate = self.CargoObject:GetCoordinate():GetRandomCoordinateInRadius( 50, 20 ) - --self.CargoObject:ReSpawnAt( Coordinate, 0 ) - end - end - - --- Check if the cargo can be Boarded. - -- @param #CARGO_CRATE self - function CARGO_CRATE:CanBoard() - return false - end - - --- Check if the cargo can be Unboarded. - -- @param #CARGO_CRATE self - function CARGO_CRATE:CanUnboard() - return false - end - - --- Check if the cargo can be sling loaded. - -- @param #CARGO_CRATE self - function CARGO_CRATE:CanSlingload() - return false - end - - --- Check if Cargo Crate is in the radius for the Cargo to be reported. - -- @param #CARGO_CRATE self - -- @param Core.Point#COORDINATE Coordinate - -- @return #boolean true if the Cargo Crate is within the report radius. - function CARGO_CRATE:IsInReportRadius( Coordinate ) - --self:T( { Coordinate, LoadRadius = self.LoadRadius } ) - - local Distance = 0 - if self:IsUnLoaded() then - Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() ) - --self:T( Distance ) - if Distance <= self.LoadRadius then - return true - end - end - - return false - end - - - --- Check if Cargo Crate is in the radius for the Cargo to be Boarded or Loaded. - -- @param #CARGO_CRATE self - -- @param Core.Point#Coordinate Coordinate - -- @return #boolean true if the Cargo Crate is within the loading radius. - function CARGO_CRATE:IsInLoadRadius( Coordinate ) - --self:T( { Coordinate, LoadRadius = self.NearRadius } ) - - local Distance = 0 - if self:IsUnLoaded() then - Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() ) - --self:T( Distance ) - if Distance <= self.NearRadius then - return true - end - end - - return false - end - - - - --- Get the current Coordinate of the CargoGroup. - -- @param #CARGO_CRATE self - -- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup. - -- @return #nil There is no valid Cargo in the CargoGroup. - function CARGO_CRATE:GetCoordinate() - --self:T() - - return self.CargoObject:GetCoordinate() - end - - --- Check if the CargoGroup is alive. - -- @param #CARGO_CRATE self - -- @return #boolean true if the CargoGroup is alive. - -- @return #boolean false if the CargoGroup is dead. - function CARGO_CRATE:IsAlive() - - local Alive = true - - -- When the Cargo is Loaded, the Cargo is in the CargoCarrier, so we check if the CargoCarrier is alive. - -- When the Cargo is not Loaded, the Cargo is the CargoObject, so we check if the CargoObject is alive. - if self:IsLoaded() then - Alive = Alive == true and self.CargoCarrier:IsAlive() - else - Alive = Alive == true and self.CargoObject:IsAlive() - end - - return Alive - - end - - - --- Route Cargo to Coordinate and randomize locations. - -- @param #CARGO_CRATE self - -- @param Core.Point#COORDINATE Coordinate - function CARGO_CRATE:RouteTo( Coordinate ) - self:T( {Coordinate = Coordinate } ) - - end - - - --- Check if Cargo is near to the Carrier. - -- The Cargo is near to the Carrier within NearRadius. - -- @param #CARGO_CRATE self - -- @param Wrapper.Group#GROUP CargoCarrier - -- @param #number NearRadius - -- @return #boolean The Cargo is near to the Carrier. - -- @return #nil The Cargo is not near to the Carrier. - function CARGO_CRATE:IsNear( CargoCarrier, NearRadius ) - self:T( {NearRadius = NearRadius } ) - - return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) - end - - --- Respawn the CargoGroup. - -- @param #CARGO_CRATE self - function CARGO_CRATE:Respawn() - - self:T( { "Respawning crate " .. self:GetName() } ) - - - -- Respawn the group... - if self.CargoObject then - self.CargoObject:ReSpawn() -- A cargo destroy crates a DEAD event. - self:__Reset( -0.1 ) - end - - - end - - - --- Respawn the CargoGroup. - -- @param #CARGO_CRATE self - function CARGO_CRATE:onafterReset() - - self:T( { "Reset crate " .. self:GetName() } ) - - - -- Respawn the group... - if self.CargoObject then - self:SetDeployed( false ) - self:SetStartState( "UnLoaded" ) - self.CargoCarrier = nil - -- Cargo objects are added to the _DATABASE and SET_CARGO objects. - _EVENTDISPATCHER:CreateEventNewCargo( self ) - end - - - end - - --- Get the transportation method of the Cargo. - -- @param #CARGO_CRATE self - -- @return #string The transportation method of the Cargo. - function CARGO_CRATE:GetTransportationMethod() - if self:IsLoaded() then - return "for unloading" - else - if self:IsUnLoaded() then - return "for loading" - else - if self:IsDeployed() then - return "delivered" - end - end - end - return "" - end - -end - diff --git a/Moose Development/Moose/Cargo/CargoGroup.lua b/Moose Development/Moose/Cargo/CargoGroup.lua deleted file mode 100644 index b756f456c..000000000 --- a/Moose Development/Moose/Cargo/CargoGroup.lua +++ /dev/null @@ -1,777 +0,0 @@ ---- **Cargo** - Management of grouped cargo logistics, which are based on a GROUP object. --- --- === --- --- ### [Demo Missions]() --- --- ### [YouTube Playlist]() --- --- === --- --- ### Author: **FlightControl** --- ### Contributions: --- --- === --- --- @module Cargo.CargoGroup --- @image Cargo_Groups.JPG - - -do -- CARGO_GROUP - - --- @type CARGO_GROUP - -- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects. - -- @field #string GroupName The name of the CargoGroup. - -- @field Wrapper.Group#GROUÜ CargoCarrier The carrier group. - -- @extends Cargo.Cargo#CARGO_REPORTABLE - - --- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator. - -- - -- ![Banner Image](..\Images\deprecated.png) - -- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers. - -- - -- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo: - -- - -- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC} module. - -- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter} module. - -- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane} module. - -- * AI Ships is planned. - -- - -- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking: - -- - -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players. - -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players. - -- - -- # Developer Note - -- - -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE - -- Therefore, this class is considered to be deprecated - -- - -- @field #CARGO_GROUP CARGO_GROUP - -- - CARGO_GROUP = { - ClassName = "CARGO_GROUP", - } - - --- CARGO_GROUP constructor. - -- This make a new CARGO_GROUP from a @{Wrapper.Group} object. - -- It will "ungroup" the group object within the sim, and will create a @{Core.Set} of individual Unit objects. - -- @param #CARGO_GROUP self - -- @param Wrapper.Group#GROUP CargoGroup Group to be transported as cargo. - -- @param #string Type Cargo type, e.g. "Infantry". This is the type used in SET_CARGO:New():FilterTypes("Infantry") to define the valid cargo groups of the set. - -- @param #string Name A user defined name of the cargo group. This name CAN be the same as the group object but can also have a different name. This name MUST be unique! - -- @param #number LoadRadius (optional) Distance in meters until which a cargo is loaded into the carrier. Cargo outside this radius has to be routed by other means to within the radius to be loaded. - -- @param #number NearRadius (optional) Once the units are within this radius of the carrier, they are actually loaded, i.e. disappear from the scene. - -- @return #CARGO_GROUP Cargo group object. - function CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius, NearRadius ) - - -- Inherit CAROG_REPORTABLE - local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_GROUP - self:T( { Type, Name, LoadRadius } ) - - self.CargoSet = SET_CARGO:New() - self.CargoGroup = CargoGroup - self.Grouped = true - self.CargoUnitTemplate = {} - - self.NearRadius = NearRadius - - self:SetDeployed( false ) - - local WeightGroup = 0 - local VolumeGroup = 0 - - self.CargoGroup:Destroy() -- destroy and generate a unit removal event, so that the database gets cleaned, and the linked sets get properly cleaned. - - local GroupName = CargoGroup:GetName() - self.CargoName = Name - self.CargoTemplate = UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ) ) - - -- Deactivate late activation. - self.CargoTemplate.lateActivation=false - - self.GroupTemplate = UTILS.DeepCopy( self.CargoTemplate ) - self.GroupTemplate.name = self.CargoName .. "#CARGO" - self.GroupTemplate.groupId = nil - - self.GroupTemplate.units = {} - - for UnitID, UnitTemplate in pairs( self.CargoTemplate.units ) do - UnitTemplate.name = UnitTemplate.name .. "#CARGO" - local CargoUnitName = UnitTemplate.name - self.CargoUnitTemplate[CargoUnitName] = UnitTemplate - - self.GroupTemplate.units[#self.GroupTemplate.units+1] = self.CargoUnitTemplate[CargoUnitName] - self.GroupTemplate.units[#self.GroupTemplate.units].unitId = nil - - -- And we register the spawned unit as part of the CargoSet. - local Unit = UNIT:Register( CargoUnitName ) - - end - - -- Then we register the new group in the database - self.CargoGroup = GROUP:NewTemplate( self.GroupTemplate, self.GroupTemplate.CoalitionID, self.GroupTemplate.CategoryID, self.GroupTemplate.CountryID ) - - -- Now we spawn the new group based on the template created. - self.CargoObject = _DATABASE:Spawn( self.GroupTemplate ) - - for CargoUnitID, CargoUnit in pairs( self.CargoObject:GetUnits() ) do - - - local CargoUnitName = CargoUnit:GetName() - - local Cargo = CARGO_UNIT:New( CargoUnit, Type, CargoUnitName, LoadRadius, NearRadius ) - self.CargoSet:Add( CargoUnitName, Cargo ) - - WeightGroup = WeightGroup + Cargo:GetWeight() - - end - - self:SetWeight( WeightGroup ) - - self:T( { "Weight Cargo", WeightGroup } ) - - -- Cargo objects are added to the _DATABASE and SET_CARGO objects. - _EVENTDISPATCHER:CreateEventNewCargo( self ) - - self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead ) - self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead ) - --self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCargoDead ) - self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead ) - - self:SetEventPriority( 4 ) - - return self - end - - - --- Respawn the CargoGroup. - -- @param #CARGO_GROUP self - function CARGO_GROUP:Respawn() - - self:T( { "Respawning" } ) - - for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do - local Cargo = CargoData -- Cargo.Cargo#CARGO - Cargo:Destroy() -- Destroy the cargo and generate a remove unit event to update the sets. - Cargo:SetStartState( "UnLoaded" ) - end - - -- Now we spawn the new group based on the template created. - _DATABASE:Spawn( self.GroupTemplate ) - - for CargoUnitID, CargoUnit in pairs( self.CargoObject:GetUnits() ) do - - local CargoUnitName = CargoUnit:GetName() - - local Cargo = CARGO_UNIT:New( CargoUnit, self.Type, CargoUnitName, self.LoadRadius ) - self.CargoSet:Add( CargoUnitName, Cargo ) - - end - - self:SetDeployed( false ) - self:SetStartState( "UnLoaded" ) - - end - - --- Ungroup the cargo group into individual groups with one unit. - -- This is required because by default a group will move in formation and this is really an issue for group control. - -- Therefore this method is made to be able to ungroup a group. - -- This works for ground only groups. - -- @param #CARGO_GROUP self - function CARGO_GROUP:Ungroup() - - if self.Grouped == true then - - self.Grouped = false - - self.CargoGroup:Destroy() - - for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do - local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT - - if CargoUnit:IsUnLoaded() then - local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate ) - --local GroupName = env.getValueDictByKey( GroupTemplate.name ) - - -- We create a new group object with one unit... - -- First we prepare the template... - GroupTemplate.name = self.CargoName .. "#CARGO#" .. CargoUnitName - GroupTemplate.groupId = nil - - if CargoUnit:IsUnLoaded() then - GroupTemplate.units = {} - GroupTemplate.units[1] = self.CargoUnitTemplate[CargoUnitName] - GroupTemplate.units[#GroupTemplate.units].unitId = nil - GroupTemplate.units[#GroupTemplate.units].x = CargoUnit:GetX() - GroupTemplate.units[#GroupTemplate.units].y = CargoUnit:GetY() - GroupTemplate.units[#GroupTemplate.units].heading = CargoUnit:GetHeading() - end - - - -- Then we register the new group in the database - local CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID) - - -- Now we spawn the new group based on the template created. - _DATABASE:Spawn( GroupTemplate ) - end - end - - self.CargoObject = nil - end - - - end - - --- Regroup the cargo group into one group with multiple unit. - -- This is required because by default a group will move in formation and this is really an issue for group control. - -- Therefore this method is made to be able to regroup a group. - -- This works for ground only groups. - -- @param #CARGO_GROUP self - function CARGO_GROUP:Regroup() - - self:T("Regroup") - - if self.Grouped == false then - - self.Grouped = true - - local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate ) - GroupTemplate.name = self.CargoName .. "#CARGO" - GroupTemplate.groupId = nil - GroupTemplate.units = {} - - for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do - local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT - - self:T( { CargoUnit:GetName(), UnLoaded = CargoUnit:IsUnLoaded() } ) - - if CargoUnit:IsUnLoaded() then - - CargoUnit.CargoObject:Destroy() - - GroupTemplate.units[#GroupTemplate.units+1] = self.CargoUnitTemplate[CargoUnitName] - GroupTemplate.units[#GroupTemplate.units].unitId = nil - GroupTemplate.units[#GroupTemplate.units].x = CargoUnit:GetX() - GroupTemplate.units[#GroupTemplate.units].y = CargoUnit:GetY() - GroupTemplate.units[#GroupTemplate.units].heading = CargoUnit:GetHeading() - end - end - - -- Then we register the new group in the database - self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID ) - - self:T( { "Regroup", GroupTemplate } ) - - -- Now we spawn the new group based on the template created. - self.CargoObject = _DATABASE:Spawn( GroupTemplate ) - end - - end - - - --- @param #CARGO_GROUP self - -- @param Core.Event#EVENTDATA EventData - function CARGO_GROUP:OnEventCargoDead( EventData ) - - self:T(EventData) - - local Destroyed = false - - if self:IsDestroyed() or self:IsUnLoaded() or self:IsBoarding() or self:IsUnboarding() then - Destroyed = true - for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do - local Cargo = CargoData -- Cargo.Cargo#CARGO - if Cargo:IsAlive() then - Destroyed = false - else - Cargo:Destroyed() - end - end - else - local CarrierName = self.CargoCarrier:GetName() - if CarrierName == EventData.IniDCSUnitName then - MESSAGE:New( "Cargo is lost from carrier " .. CarrierName, 15 ):ToAll() - Destroyed = true - self.CargoCarrier:ClearCargo() - end - end - - if Destroyed then - self:Destroyed() - self:T( { "Cargo group destroyed" } ) - end - - end - - --- After Board Event. - -- @param #CARGO_GROUP self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Wrapper.Unit#UNIT CargoCarrier - -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. - function CARGO_GROUP:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... ) - self:T( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } ) - - NearRadius = NearRadius or self.NearRadius - - -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo, ... ) - self:T( { "Board Unit", Cargo:GetName( ), Cargo:IsDestroyed(), Cargo.CargoObject:IsAlive() } ) - local CargoGroup = Cargo.CargoObject --Wrapper.Group#GROUP - CargoGroup:OptionAlarmStateGreen() - Cargo:__Board( 1, CargoCarrier, NearRadius, ... ) - end, ... - ) - - self:__Boarding( -1, CargoCarrier, NearRadius, ... ) - - end - - --- Enter Loaded State. - -- @param #CARGO_GROUP self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Wrapper.Unit#UNIT CargoCarrier - function CARGO_GROUP:onafterLoad( From, Event, To, CargoCarrier, ... ) - --self:T( { From, Event, To, CargoCarrier, ...} ) - - if From == "UnLoaded" then - -- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier. - for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do - if not Cargo:IsDestroyed() then - Cargo:Load( CargoCarrier ) - end - end - end - - --self.CargoObject:Destroy() - self.CargoCarrier = CargoCarrier - self.CargoCarrier:AddCargo( self ) - - end - - --- Leave Boarding State. - -- @param #CARGO_GROUP self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Wrapper.Unit#UNIT CargoCarrier - -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. - function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) - --self:T( { CargoCarrier.UnitName, From, Event, To } ) - - local Boarded = true - local Cancelled = false - local Dead = true - - self.CargoSet:Flush() - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do - --self:T( { Cargo:GetName(), Cargo.current } ) - - - if not Cargo:is( "Loaded" ) - and (not Cargo:is( "Destroyed" )) then -- If one or more units of a group defined as CARGO_GROUP died, the CARGO_GROUP:Board() command does not trigger the CARGO_GRUOP:OnEnterLoaded() function. - Boarded = false - end - - if Cargo:is( "UnLoaded" ) then - Cancelled = true - end - - if not Cargo:is( "Destroyed" ) then - Dead = false - end - - end - - if not Dead then - - if not Cancelled then - if not Boarded then - self:__Boarding( -5, CargoCarrier, NearRadius, ... ) - else - self:T("Group Cargo is loaded") - self:__Load( 1, CargoCarrier, ... ) - end - else - self:__CancelBoarding( 1, CargoCarrier, NearRadius, ... ) - end - else - self:__Destroyed( 1, CargoCarrier, NearRadius, ... ) - end - - end - - --- Enter UnBoarding State. - -- @param #CARGO_GROUP self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Core.Point#COORDINATE ToPointVec2 - -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. - function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... ) - self:T( {From, Event, To, ToPointVec2, NearRadius } ) - - NearRadius = NearRadius or 25 - - local Timer = 1 - - if From == "Loaded" then - - if self.CargoObject then - self.CargoObject:Destroy() - end - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - --- @param Cargo.Cargo#CARGO Cargo - function( Cargo, NearRadius ) - if not Cargo:IsDestroyed() then - local ToVec=nil - if ToPointVec2==nil then - ToVec=self.CargoCarrier:GetPointVec2():GetRandomPointVec2InRadius(2*NearRadius, NearRadius) - else - ToVec=ToPointVec2 - end - Cargo:__UnBoard( Timer, ToVec, NearRadius ) - Timer = Timer + 1 - end - end, { NearRadius } - ) - - - self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) - end - - end - - --- Leave UnBoarding State. - -- @param #CARGO_GROUP self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Core.Point#COORDINATE ToPointVec2 - -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. - function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) - --self:T( { From, Event, To, ToPointVec2, NearRadius } ) - - --local NearRadius = NearRadius or 25 - - local Angle = 180 - local Speed = 10 - local Distance = 5 - - if From == "UnBoarding" then - local UnBoarded = true - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do - self:T( { Cargo:GetName(), Cargo.current } ) - if not Cargo:is( "UnLoaded" ) and not Cargo:IsDestroyed() then - UnBoarded = false - end - end - - if UnBoarded then - self:__UnLoad( 1, ToPointVec2, ... ) - else - self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) - end - - return false - end - - end - - --- Enter UnLoaded State. - -- @param #CARGO_GROUP self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Core.Point#COORDINATE ToPointVec2 - function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... ) - --self:T( { From, Event, To, ToPointVec2 } ) - - if From == "Loaded" then - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo ) - --Cargo:UnLoad( ToPointVec2 ) - local RandomVec2=nil - if ToPointVec2 then - RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(20, 10) - end - Cargo:UnBoard( RandomVec2 ) - end - ) - - end - - self.CargoCarrier:RemoveCargo( self ) - self.CargoCarrier = nil - - end - - - --- Get the current Coordinate of the CargoGroup. - -- @param #CARGO_GROUP self - -- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup. - -- @return #nil There is no valid Cargo in the CargoGroup. - function CARGO_GROUP:GetCoordinate() - local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO - - if Cargo then - return Cargo.CargoObject:GetCoordinate() - end - - return nil - end - - --- Get the x position of the cargo. - -- @param #CARGO_GROUP self - -- @return #number - function CARGO:GetX() - - local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO - - if Cargo then - return Cargo:GetCoordinate().x - end - - return nil - end - - --- Get the y position of the cargo. - -- @param #CARGO_GROUP self - -- @return #number - function CARGO:GetY() - - local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO - - if Cargo then - return Cargo:GetCoordinate().z - end - - return nil - end - - - - --- Check if the CargoGroup is alive. - -- @param #CARGO_GROUP self - -- @return #boolean true if the CargoGroup is alive. - -- @return #boolean false if the CargoGroup is dead. - function CARGO_GROUP:IsAlive() - - local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO - return Cargo ~= nil - - end - - - --- Get the first alive Cargo Unit of the Cargo Group. - -- @param #CARGO_GROUP self - -- @return #CARGO_GROUP - function CARGO_GROUP:GetFirstAlive() - - local CargoFirstAlive = nil - - for _, Cargo in pairs( self.CargoSet:GetSet() ) do - if not Cargo:IsDestroyed() then - CargoFirstAlive = Cargo - break - end - end - return CargoFirstAlive - end - - - --- Get the amount of cargo units in the group. - -- @param #CARGO_GROUP self - -- @return #CARGO_GROUP - function CARGO_GROUP:GetCount() - return self.CargoSet:Count() - end - - - --- Get the underlying GROUP object from the CARGO_GROUP. - -- @param #CARGO_GROUP self - -- @return #CARGO_GROUP - function CARGO_GROUP:GetGroup( Cargo ) - local Cargo = Cargo or self:GetFirstAlive() -- Cargo.Cargo#CARGO - return Cargo.CargoObject:GetGroup() - end - - - --- Route Cargo to Coordinate and randomize locations. - -- @param #CARGO_GROUP self - -- @param Core.Point#COORDINATE Coordinate - function CARGO_GROUP:RouteTo( Coordinate ) - --self:T( {Coordinate = Coordinate } ) - - -- For each Cargo within the CargoSet, route each object to the Coordinate - self.CargoSet:ForEach( - function( Cargo ) - Cargo.CargoObject:RouteGroundTo( Coordinate, 10, "vee", 0 ) - end - ) - - end - - --- Check if Cargo is near to the Carrier. - -- The Cargo is near to the Carrier if the first unit of the Cargo Group is within NearRadius. - -- @param #CARGO_GROUP self - -- @param Wrapper.Group#GROUP CargoCarrier - -- @param #number NearRadius - -- @return #boolean The Cargo is near to the Carrier or #nil if the Cargo is not near to the Carrier. - function CARGO_GROUP:IsNear( CargoCarrier, NearRadius ) - self:T( {NearRadius = NearRadius } ) - - for _, Cargo in pairs( self.CargoSet:GetSet() ) do - local Cargo = Cargo -- Cargo.Cargo#CARGO - if Cargo:IsAlive() then - if Cargo:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) then - self:T( "Near" ) - return true - end - end - end - - return nil - end - - --- Check if Cargo Group is in the radius for the Cargo to be Boarded. - -- @param #CARGO_GROUP self - -- @param Core.Point#COORDINATE Coordinate - -- @return #boolean true if the Cargo Group is within the load radius. - function CARGO_GROUP:IsInLoadRadius( Coordinate ) - --self:T( { Coordinate } ) - - local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO - - if Cargo then - local Distance = 0 - local CargoCoordinate - if Cargo:IsLoaded() then - CargoCoordinate = Cargo.CargoCarrier:GetCoordinate() - else - CargoCoordinate = Cargo.CargoObject:GetCoordinate() - end - - -- FF check if coordinate could be obtained. This was commented out for some (unknown) reason. But the check seems valid! - if CargoCoordinate then - Distance = Coordinate:Get2DDistance( CargoCoordinate ) - else - return false - end - - self:T( { Distance = Distance, LoadRadius = self.LoadRadius } ) - if Distance <= self.LoadRadius then - return true - else - return false - end - end - - return nil - - end - - - --- Check if Cargo Group is in the report radius. - -- @param #CARGO_GROUP self - -- @param Core.Point#Coordinate Coordinate - -- @return #boolean true if the Cargo Group is within the report radius. - function CARGO_GROUP:IsInReportRadius( Coordinate ) - --self:T( { Coordinate } ) - - local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO - - if Cargo then - self:T( { Cargo } ) - local Distance = 0 - if Cargo:IsUnLoaded() then - Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() ) - --self:T( Distance ) - if Distance <= self.LoadRadius then - return true - end - end - end - - return nil - - end - - - --- Signal a flare at the position of the CargoGroup. - -- @param #CARGO_GROUP self - -- @param Utilities.Utils#FLARECOLOR FlareColor - function CARGO_GROUP:Flare( FlareColor ) - - local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO - if Cargo then - Cargo:Flare( FlareColor ) - end - end - - --- Smoke the CargoGroup. - -- @param #CARGO_GROUP self - -- @param Utilities.Utils#SMOKECOLOR SmokeColor The color of the smoke. - -- @param #number Radius The radius of randomization around the center of the first element of the CargoGroup. - function CARGO_GROUP:Smoke( SmokeColor, Radius ) - - local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO - - if Cargo then - Cargo:Smoke( SmokeColor, Radius ) - end - end - - --- Check if the first element of the CargoGroup is the given @{Core.Zone}. - -- @param #CARGO_GROUP self - -- @param Core.Zone#ZONE_BASE Zone - -- @return #boolean **true** if the first element of the CargoGroup is in the Zone - -- @return #boolean **false** if there is no element of the CargoGroup in the Zone. - function CARGO_GROUP:IsInZone( Zone ) - --self:T( { Zone } ) - - local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO - - if Cargo then - return Cargo:IsInZone( Zone ) - end - - return nil - - end - - --- Get the transportation method of the Cargo. - -- @param #CARGO_GROUP self - -- @return #string The transportation method of the Cargo. - function CARGO_GROUP:GetTransportationMethod() - if self:IsLoaded() then - return "for unboarding" - else - if self:IsUnLoaded() then - return "for boarding" - else - if self:IsDeployed() then - return "delivered" - end - end - end - return "" - end - - - -end -- CARGO_GROUP - diff --git a/Moose Development/Moose/Cargo/CargoSlingload.lua b/Moose Development/Moose/Cargo/CargoSlingload.lua deleted file mode 100644 index 90209e8c0..000000000 --- a/Moose Development/Moose/Cargo/CargoSlingload.lua +++ /dev/null @@ -1,277 +0,0 @@ ---- **Cargo** - Management of single cargo crates, which are based on a STATIC object. The cargo can only be slingloaded. --- --- === --- --- ### [Demo Missions]() --- --- ### [YouTube Playlist]() --- --- === --- --- ### Author: **FlightControl** --- ### Contributions: --- --- === --- --- @module Cargo.CargoSlingload --- @image Cargo_Slingload.JPG - - -do -- CARGO_SLINGLOAD - - --- Models the behaviour of cargo crates, which can only be slingloaded. - -- @type CARGO_SLINGLOAD - -- @extends Cargo.Cargo#CARGO_REPRESENTABLE - - --- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier. - -- - -- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking: - -- - -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players. - -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players. - -- - -- # Developer Note - -- - -- ![Banner Image](..\Images\deprecated.png) - -- - -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE - -- Therefore, this class is considered to be deprecated - -- - -- === - -- - -- @field #CARGO_SLINGLOAD - CARGO_SLINGLOAD = { - ClassName = "CARGO_SLINGLOAD" - } - - --- CARGO_SLINGLOAD Constructor. - -- @param #CARGO_SLINGLOAD self - -- @param Wrapper.Static#STATIC CargoStatic - -- @param #string Type - -- @param #string Name - -- @param #number LoadRadius (optional) - -- @param #number NearRadius (optional) - -- @return #CARGO_SLINGLOAD - function CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius ) - local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_SLINGLOAD - self:T( { Type, Name, NearRadius } ) - - self.CargoObject = CargoStatic - - -- Cargo objects are added to the _DATABASE and SET_CARGO objects. - _EVENTDISPATCHER:CreateEventNewCargo( self ) - - self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead ) - self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead ) - --self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCargoDead ) - self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead ) - - self:SetEventPriority( 4 ) - - self.NearRadius = NearRadius or 25 - - return self - end - - - -- @param #CARGO_SLINGLOAD self - -- @param Core.Event#EVENTDATA EventData - function CARGO_SLINGLOAD:OnEventCargoDead( EventData ) - - local Destroyed = false - - if self:IsDestroyed() or self:IsUnLoaded() then - if self.CargoObject:GetName() == EventData.IniUnitName then - if not self.NoDestroy then - Destroyed = true - end - end - end - - if Destroyed then - self:I( { "Cargo crate destroyed: " .. self.CargoObject:GetName() } ) - self:Destroyed() - end - - end - - - --- Check if the cargo can be Slingloaded. - -- @param #CARGO_SLINGLOAD self - function CARGO_SLINGLOAD:CanSlingload() - return true - end - - --- Check if the cargo can be Boarded. - -- @param #CARGO_SLINGLOAD self - function CARGO_SLINGLOAD:CanBoard() - return false - end - - --- Check if the cargo can be Unboarded. - -- @param #CARGO_SLINGLOAD self - function CARGO_SLINGLOAD:CanUnboard() - return false - end - - --- Check if the cargo can be Loaded. - -- @param #CARGO_SLINGLOAD self - function CARGO_SLINGLOAD:CanLoad() - return false - end - - --- Check if the cargo can be Unloaded. - -- @param #CARGO_SLINGLOAD self - function CARGO_SLINGLOAD:CanUnload() - return false - end - - - --- Check if Cargo Crate is in the radius for the Cargo to be reported. - -- @param #CARGO_SLINGLOAD self - -- @param Core.Point#COORDINATE Coordinate - -- @return #boolean true if the Cargo Crate is within the report radius. - function CARGO_SLINGLOAD:IsInReportRadius( Coordinate ) - --self:T( { Coordinate, LoadRadius = self.LoadRadius } ) - - local Distance = 0 - if self:IsUnLoaded() then - Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() ) - if Distance <= self.LoadRadius then - return true - end - end - - return false - end - - - --- Check if Cargo Slingload is in the radius for the Cargo to be Boarded or Loaded. - -- @param #CARGO_SLINGLOAD self - -- @param Core.Point#COORDINATE Coordinate - -- @return #boolean true if the Cargo Slingload is within the loading radius. - function CARGO_SLINGLOAD:IsInLoadRadius( Coordinate ) - --self:T( { Coordinate } ) - - local Distance = 0 - if self:IsUnLoaded() then - Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() ) - if Distance <= self.NearRadius then - return true - end - end - - return false - end - - - - --- Get the current Coordinate of the CargoGroup. - -- @param #CARGO_SLINGLOAD self - -- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup. - -- @return #nil There is no valid Cargo in the CargoGroup. - function CARGO_SLINGLOAD:GetCoordinate() - --self:T() - - return self.CargoObject:GetCoordinate() - end - - --- Check if the CargoGroup is alive. - -- @param #CARGO_SLINGLOAD self - -- @return #boolean true if the CargoGroup is alive. - -- @return #boolean false if the CargoGroup is dead. - function CARGO_SLINGLOAD:IsAlive() - - local Alive = true - - -- When the Cargo is Loaded, the Cargo is in the CargoCarrier, so we check if the CargoCarrier is alive. - -- When the Cargo is not Loaded, the Cargo is the CargoObject, so we check if the CargoObject is alive. - if self:IsLoaded() then - Alive = Alive == true and self.CargoCarrier:IsAlive() - else - Alive = Alive == true and self.CargoObject:IsAlive() - end - - return Alive - - end - - - --- Route Cargo to Coordinate and randomize locations. - -- @param #CARGO_SLINGLOAD self - -- @param Core.Point#COORDINATE Coordinate - function CARGO_SLINGLOAD:RouteTo( Coordinate ) - --self:T( {Coordinate = Coordinate } ) - - end - - - --- Check if Cargo is near to the Carrier. - -- The Cargo is near to the Carrier within NearRadius. - -- @param #CARGO_SLINGLOAD self - -- @param Wrapper.Group#GROUP CargoCarrier - -- @param #number NearRadius - -- @return #boolean The Cargo is near to the Carrier. - -- @return #nil The Cargo is not near to the Carrier. - function CARGO_SLINGLOAD:IsNear( CargoCarrier, NearRadius ) - --self:T( {NearRadius = NearRadius } ) - - return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) - end - - - --- Respawn the CargoGroup. - -- @param #CARGO_SLINGLOAD self - function CARGO_SLINGLOAD:Respawn() - - --self:T( { "Respawning slingload " .. self:GetName() } ) - - - -- Respawn the group... - if self.CargoObject then - self.CargoObject:ReSpawn() -- A cargo destroy crates a DEAD event. - self:__Reset( -0.1 ) - end - - - end - - - --- Respawn the CargoGroup. - -- @param #CARGO_SLINGLOAD self - function CARGO_SLINGLOAD:onafterReset() - - --self:T( { "Reset slingload " .. self:GetName() } ) - - - -- Respawn the group... - if self.CargoObject then - self:SetDeployed( false ) - self:SetStartState( "UnLoaded" ) - self.CargoCarrier = nil - -- Cargo objects are added to the _DATABASE and SET_CARGO objects. - _EVENTDISPATCHER:CreateEventNewCargo( self ) - end - - - end - - --- Get the transportation method of the Cargo. - -- @param #CARGO_SLINGLOAD self - -- @return #string The transportation method of the Cargo. - function CARGO_SLINGLOAD:GetTransportationMethod() - if self:IsLoaded() then - return "for sling loading" - else - if self:IsUnLoaded() then - return "for sling loading" - else - if self:IsDeployed() then - return "delivered" - end - end - end - return "" - end - -end diff --git a/Moose Development/Moose/Cargo/CargoUnit.lua b/Moose Development/Moose/Cargo/CargoUnit.lua deleted file mode 100644 index bc504d003..000000000 --- a/Moose Development/Moose/Cargo/CargoUnit.lua +++ /dev/null @@ -1,397 +0,0 @@ ---- **Cargo** - Management of single cargo logistics, which are based on a UNIT object. --- --- === --- --- ### [Demo Missions]() --- --- ### [YouTube Playlist]() --- --- === --- --- ### Author: **FlightControl** --- ### Contributions: --- --- === --- --- @module Cargo.CargoUnit --- @image Cargo_Units.JPG - -do -- CARGO_UNIT - - --- Models CARGO in the form of units, which can be boarded, unboarded, loaded, unloaded. - -- @type CARGO_UNIT - -- @extends Cargo.Cargo#CARGO_REPRESENTABLE - - --- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier. - -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO_UNIT objects to and from carriers. - -- Note that ground forces behave in a group, and thus, act in formation, regardless if one unit is commanded to move. - -- - -- This class is used in CARGO_GROUP, and is not meant to be used by mission designers individually. - -- - -- # Developer Note - -- - -- ![Banner Image](..\Images\deprecated.png) - -- - -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE - -- Therefore, this class is considered to be deprecated - -- - -- === - -- - -- @field #CARGO_UNIT CARGO_UNIT - -- - CARGO_UNIT = { - ClassName = "CARGO_UNIT" - } - - --- CARGO_UNIT Constructor. - -- @param #CARGO_UNIT self - -- @param Wrapper.Unit#UNIT CargoUnit - -- @param #string Type - -- @param #string Name - -- @param #number Weight - -- @param #number LoadRadius (optional) - -- @param #number NearRadius (optional) - -- @return #CARGO_UNIT - function CARGO_UNIT:New( CargoUnit, Type, Name, LoadRadius, NearRadius ) - - -- Inherit CARGO_REPRESENTABLE. - local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoUnit, Type, Name, LoadRadius, NearRadius ) ) -- #CARGO_UNIT - - -- Debug info. - self:T({Type=Type, Name=Name, LoadRadius=LoadRadius, NearRadius=NearRadius}) - - -- Set cargo object. - self.CargoObject = CargoUnit - - -- Set event prio. - self:SetEventPriority( 5 ) - - return self - end - - --- Enter UnBoarding State. - -- @param #CARGO_UNIT self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Core.Point#COORDINATE ToPointVec2 - -- @param #number NearRadius (optional) Defaut 25 m. - function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius ) - self:T( { From, Event, To, ToPointVec2, NearRadius } ) - - local Angle = 180 - local Speed = 60 - local DeployDistance = 9 - local RouteDistance = 60 - - if From == "Loaded" then - - if not self:IsDestroyed() then - - local CargoCarrier = self.CargoCarrier -- Wrapper.Controllable#CONTROLLABLE - - if CargoCarrier:IsAlive() then - - local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2() - local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - - - local CargoRoutePointVec2 = CargoCarrierPointVec2:Translate( RouteDistance, CargoDeployHeading ) - - - -- if there is no ToPointVec2 given, then use the CargoRoutePointVec2 - local FromDirectionVec3 = CargoCarrierPointVec2:GetDirectionVec3( ToPointVec2 or CargoRoutePointVec2 ) - local FromAngle = CargoCarrierPointVec2:GetAngleDegrees(FromDirectionVec3) - local FromPointVec2 = CargoCarrierPointVec2:Translate( DeployDistance, FromAngle ) - --local CargoDeployPointVec2 = CargoCarrierPointVec2:GetRandomCoordinateInRadius( 10, 5 ) - - ToPointVec2 = ToPointVec2 or CargoCarrierPointVec2:GetRandomCoordinateInRadius( NearRadius, DeployDistance ) - - -- Respawn the group... - if self.CargoObject then - if CargoCarrier:IsShip() then - -- If CargoCarrier is a ship, we don't want to spawn the units in the water next to the boat. Use destination coord instead. - self.CargoObject:ReSpawnAt( ToPointVec2, CargoDeployHeading ) - else - self.CargoObject:ReSpawnAt( FromPointVec2, CargoDeployHeading ) - end - self:T( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } ) - self.CargoCarrier = nil - - local Points = {} - - -- From - Points[#Points+1] = FromPointVec2:WaypointGround( Speed, "Vee" ) - - -- To - Points[#Points+1] = ToPointVec2:WaypointGround( Speed, "Vee" ) - - local TaskRoute = self.CargoObject:TaskRoute( Points ) - self.CargoObject:SetTask( TaskRoute, 1 ) - - - self:__UnBoarding( 1, ToPointVec2, NearRadius ) - end - else - -- the Carrier is dead. This cargo is dead too! - self:Destroyed() - end - end - end - - end - - --- Leave UnBoarding State. - -- @param #CARGO_UNIT self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Core.Point#COORDINATE ToPointVec2 - -- @param #number NearRadius (optional) Defaut 100 m. - function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius ) - self:T( { From, Event, To, ToPointVec2, NearRadius } ) - - local Angle = 180 - local Speed = 10 - local Distance = 5 - - if From == "UnBoarding" then - --if self:IsNear( ToPointVec2, NearRadius ) then - return true - --else - - --self:__UnBoarding( 1, ToPointVec2, NearRadius ) - --end - --return false - end - - end - - --- UnBoard Event. - -- @param #CARGO_UNIT self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Core.Point#COORDINATE ToPointVec2 - -- @param #number NearRadius (optional) Defaut 100 m. - function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius ) - self:T( { From, Event, To, ToPointVec2, NearRadius } ) - - self.CargoInAir = self.CargoObject:InAir() - - self:T( self.CargoInAir ) - - -- Only unboard the cargo when the carrier is not in the air. - -- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea). - if not self.CargoInAir then - - end - - self:__UnLoad( 1, ToPointVec2, NearRadius ) - - end - - - - --- Enter UnLoaded State. - -- @param #CARGO_UNIT self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Core.Point#COORDINATE - function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 ) - self:T( { ToPointVec2, From, Event, To } ) - - local Angle = 180 - local Speed = 10 - local Distance = 5 - - if From == "Loaded" then - local StartPointVec2 = self.CargoCarrier:GetPointVec2() - local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - local CargoDeployCoord = StartPointVec2:Translate( Distance, CargoDeployHeading ) - - ToPointVec2 = ToPointVec2 or COORDINATE:New( CargoDeployCoord.x, CargoDeployCoord.z ) - - -- Respawn the group... - if self.CargoObject then - self.CargoObject:ReSpawnAt( ToPointVec2, 0 ) - self.CargoCarrier = nil - end - - end - - if self.OnUnLoadedCallBack then - self.OnUnLoadedCallBack( self, unpack( self.OnUnLoadedParameters ) ) - self.OnUnLoadedCallBack = nil - end - - end - - --- Board Event. - -- @param #CARGO_UNIT self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Wrapper.Group#GROUP CargoCarrier - -- @param #number NearRadius - function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... ) - self:T( { From, Event, To, CargoCarrier, NearRadius = NearRadius } ) - - self.CargoInAir = self.CargoObject:InAir() - - local Desc = self.CargoObject:GetDesc() - local MaxSpeed = Desc.speedMaxOffRoad - local TypeName = Desc.typeName - - --self:T({Unit=self.CargoObject:GetName()}) - - -- A cargo unit can only be boarded if it is not dead - - -- Only move the group to the carrier when the cargo is not in the air - -- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea). - if not self.CargoInAir then - -- If NearRadius is given, then use the given NearRadius, otherwise calculate the NearRadius - -- based upon the Carrier bounding radius, which is calculated from the bounding rectangle on the Y axis. - local NearRadius = NearRadius or CargoCarrier:GetBoundingRadius() + 5 - if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then - self:Load( CargoCarrier, NearRadius, ... ) - else - if MaxSpeed and MaxSpeed == 0 or TypeName and TypeName == "Stinger comm" then - self:Load( CargoCarrier, NearRadius, ... ) - else - - local Speed = 90 - local Angle = 180 - local Distance = 0 - - local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2() - local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - local CargoDeployPointVec2 = CargoCarrierPointVec2:Translate( Distance, CargoDeployHeading ) - - -- Set the CargoObject to state Green to ensure it is boarding! - self.CargoObject:OptionAlarmStateGreen() - - local Points = {} - - local PointStartVec2 = self.CargoObject:GetPointVec2() - - Points[#Points+1] = PointStartVec2:WaypointGround( Speed ) - Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed ) - - local TaskRoute = self.CargoObject:TaskRoute( Points ) - self.CargoObject:SetTask( TaskRoute, 2 ) - self:__Boarding( -5, CargoCarrier, NearRadius, ... ) - self.RunCount = 0 - end - end - end - end - - - --- Boarding Event. - -- @param #CARGO_UNIT self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Wrapper.Client#CLIENT CargoCarrier - -- @param #number NearRadius Default 25 m. - function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) - self:T( { From, Event, To, CargoCarrier:GetName(), NearRadius = NearRadius } ) - - self:T( { IsAlive=self.CargoObject:IsAlive() } ) - - if CargoCarrier and CargoCarrier:IsAlive() then -- and self.CargoObject and self.CargoObject:IsAlive() then - if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then - local NearRadius = NearRadius or CargoCarrier:GetBoundingRadius( NearRadius ) + 5 - if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then - self:__Load( -1, CargoCarrier, ... ) - else - if self:IsNear( CargoCarrier:GetPointVec2(), 20 ) then - self:__Boarding( -1, CargoCarrier, NearRadius, ... ) - self.RunCount = self.RunCount + 1 - else - self:__Boarding( -2, CargoCarrier, NearRadius, ... ) - self.RunCount = self.RunCount + 2 - end - if self.RunCount >= 40 then - self.RunCount = 0 - local Speed = 90 - local Angle = 180 - local Distance = 0 - - --self:T({Unit=self.CargoObject:GetName()}) - - local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2() - local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees. - local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) - local CargoDeployPointVec2 = CargoCarrierPointVec2:Translate( Distance, CargoDeployHeading ) - - -- Set the CargoObject to state Green to ensure it is boarding! - self.CargoObject:OptionAlarmStateGreen() - - local Points = {} - - local PointStartVec2 = self.CargoObject:GetPointVec2() - - Points[#Points+1] = PointStartVec2:WaypointGround( Speed, "Off road" ) - Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed, "Off road" ) - - local TaskRoute = self.CargoObject:TaskRoute( Points ) - self.CargoObject:SetTask( TaskRoute, 0.2 ) - end - end - else - self.CargoObject:MessageToGroup( "Cancelling Boarding... Get back on the ground!", 5, CargoCarrier:GetGroup(), self:GetName() ) - self:CancelBoarding( CargoCarrier, NearRadius, ... ) - self.CargoObject:SetCommand( self.CargoObject:CommandStopRoute( true ) ) - end - else - self:T("Something is wrong") - end - - end - - - --- Loaded State. - -- @param #CARGO_UNIT self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Wrapper.Unit#UNIT CargoCarrier - function CARGO_UNIT:onenterLoaded( From, Event, To, CargoCarrier ) - self:T( { From, Event, To, CargoCarrier } ) - - self.CargoCarrier = CargoCarrier - - --self:T({Unit=self.CargoObject:GetName()}) - - -- Only destroy the CargoObject if there is a CargoObject (packages don't have CargoObjects). - if self.CargoObject then - self.CargoObject:Destroy( false ) - --self.CargoObject:ReSpawnAt( COORDINATE:NewFromVec2( {x=0,y=0} ), 0 ) - end - end - - --- Get the transportation method of the Cargo. - -- @param #CARGO_UNIT self - -- @return #string The transportation method of the Cargo. - function CARGO_UNIT:GetTransportationMethod() - if self:IsLoaded() then - return "for unboarding" - else - if self:IsUnLoaded() then - return "for boarding" - else - if self:IsDeployed() then - return "delivered" - end - end - end - return "" - end - -end -- CARGO_UNIT diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 040969abb..7ee178f08 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -54,7 +54,6 @@ -- * AIRBASES -- * PLAYERSJOINED -- * PLAYERS --- * CARGOS -- * STORAGES (DCS warehouses) -- * DYNAMICCARGO -- @@ -81,7 +80,6 @@ DATABASE = { PLAYERSJOINED = {}, PLAYERUNITS = {}, CLIENTS = {}, - CARGOS = {}, AIRBASES = {}, COUNTRY_ID = {}, COUNTRY_NAME = {}, @@ -746,102 +744,6 @@ do -- OpsZone end -- OpsZone -do -- cargo - - --- Adds a Cargo based on the Cargo Name in the DATABASE. - -- @param #DATABASE self - -- @param #string CargoName The name of the airbase - function DATABASE:AddCargo( Cargo ) - - if not self.CARGOS[Cargo.Name] then - self.CARGOS[Cargo.Name] = Cargo - end - end - - - --- Deletes a Cargo from the DATABASE based on the Cargo Name. - -- @param #DATABASE self - -- @param #string CargoName The name of the airbase - function DATABASE:DeleteCargo( CargoName ) - - self.CARGOS[CargoName] = nil - end - - --- Finds an CARGO based on the CargoName. - -- @param #DATABASE self - -- @param #string CargoName - -- @return Cargo.Cargo#CARGO The found CARGO. - function DATABASE:FindCargo( CargoName ) - - local CargoFound = self.CARGOS[CargoName] - return CargoFound - end - - --- Checks if the Template name has a #CARGO tag. - -- If yes, the group is a cargo. - -- @param #DATABASE self - -- @param #string TemplateName - -- @return #boolean - function DATABASE:IsCargo( TemplateName ) - - TemplateName = env.getValueDictByKey( TemplateName ) - - local Cargo = TemplateName:match( "#(CARGO)" ) - - return Cargo and Cargo == "CARGO" - end - - --- Private method that registers new Static Templates within the DATABASE Object. - -- @param #DATABASE self - -- @return #DATABASE self - function DATABASE:_RegisterCargos() - - local Groups = UTILS.DeepCopy( self.GROUPS ) -- This is a very important statement. CARGO_GROUP:New creates a new _DATABASE.GROUP entry, which will confuse the loop. I searched 4 hours on this to find the bug! - - for CargoGroupName, CargoGroup in pairs( Groups ) do - if self:IsCargo( CargoGroupName ) then - local CargoInfo = CargoGroupName:match("#CARGO(.*)") - local CargoParam = CargoInfo and CargoInfo:match( "%((.*)%)") - local CargoName1 = CargoGroupName:match("(.*)#CARGO%(.*%)") - local CargoName2 = CargoGroupName:match(".*#CARGO%(.*%)(.*)") - local CargoName = CargoName1 .. ( CargoName2 or "" ) - local Type = CargoParam and CargoParam:match( "T=([%a%d ]+),?") - local Name = CargoParam and CargoParam:match( "N=([%a%d]+),?") or CargoName - local LoadRadius = CargoParam and tonumber( CargoParam:match( "RR=([%a%d]+),?") ) - local NearRadius = CargoParam and tonumber( CargoParam:match( "NR=([%a%d]+),?") ) - - self:I({"Register CargoGroup:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius}) - CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius, NearRadius ) - end - end - - for CargoStaticName, CargoStatic in pairs( self.STATICS ) do - if self:IsCargo( CargoStaticName ) then - local CargoInfo = CargoStaticName:match("#CARGO(.*)") - local CargoParam = CargoInfo and CargoInfo:match( "%((.*)%)") - local CargoName = CargoStaticName:match("(.*)#CARGO") - local Type = CargoParam and CargoParam:match( "T=([%a%d ]+),?") - local Category = CargoParam and CargoParam:match( "C=([%a%d ]+),?") - local Name = CargoParam and CargoParam:match( "N=([%a%d]+),?") or CargoName - local LoadRadius = CargoParam and tonumber( CargoParam:match( "RR=([%a%d]+),?") ) - local NearRadius = CargoParam and tonumber( CargoParam:match( "NR=([%a%d]+),?") ) - - if Category == "SLING" then - self:I({"Register CargoSlingload:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius}) - CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius ) - else - if Category == "CRATE" then - self:I({"Register CargoCrate:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius}) - CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius ) - end - end - end - end - - end - -end -- cargo - --- Finds a CLIENT based on the ClientName. -- @param #DATABASE self -- @param #string ClientName - Note this is the UNIT name of the client! @@ -2050,19 +1952,6 @@ function DATABASE:ForEachClient( IteratorFunction, FinalizeFunction, ... ) return self end ---- Iterate the DATABASE and call an iterator function for each CARGO, providing the CARGO object to the function and optional parameters. --- @param #DATABASE self --- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a CLIENT parameter. --- @return #DATABASE self -function DATABASE:ForEachCargo( IteratorFunction, FinalizeFunction, ... ) - self:F2( arg ) - - self:ForEach( IteratorFunction, FinalizeFunction, arg, self.CARGOS ) - - return self -end - - --- Handles the OnEventNewCargo event. -- @param #DATABASE self -- @param Core.Event#EVENTDATA EventData diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index 7a9e22e46..e97b78d37 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -187,19 +187,17 @@ EVENT = { CreateMarkCoordinateOnEvent = false, } -world.event.S_EVENT_NEW_CARGO = world.event.S_EVENT_MAX + 1000 -world.event.S_EVENT_DELETE_CARGO = world.event.S_EVENT_MAX + 1001 -world.event.S_EVENT_NEW_ZONE = world.event.S_EVENT_MAX + 1002 -world.event.S_EVENT_DELETE_ZONE = world.event.S_EVENT_MAX + 1003 -world.event.S_EVENT_NEW_ZONE_GOAL = world.event.S_EVENT_MAX + 1004 -world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005 -world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006 -world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007 +world.event.S_EVENT_NEW_ZONE = world.event.S_EVENT_MAX + 1000 +world.event.S_EVENT_DELETE_ZONE = world.event.S_EVENT_MAX + 1001 +world.event.S_EVENT_NEW_ZONE_GOAL = world.event.S_EVENT_MAX + 1002 +world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1003 +world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1004 +world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1005 -- dynamic cargo -world.event.S_EVENT_NEW_DYNAMIC_CARGO = world.event.S_EVENT_MAX + 1008 -world.event.S_EVENT_DYNAMIC_CARGO_LOADED = world.event.S_EVENT_MAX + 1009 -world.event.S_EVENT_DYNAMIC_CARGO_UNLOADED = world.event.S_EVENT_MAX + 1010 -world.event.S_EVENT_DYNAMIC_CARGO_REMOVED = world.event.S_EVENT_MAX + 1011 +world.event.S_EVENT_NEW_DYNAMIC_CARGO = world.event.S_EVENT_MAX + 1006 +world.event.S_EVENT_DYNAMIC_CARGO_LOADED = world.event.S_EVENT_MAX + 1007 +world.event.S_EVENT_DYNAMIC_CARGO_UNLOADED = world.event.S_EVENT_MAX + 1008 +world.event.S_EVENT_DYNAMIC_CARGO_REMOVED = world.event.S_EVENT_MAX + 1009 --- The different types of events supported by MOOSE. @@ -234,8 +232,6 @@ EVENTS = { MarkChange = world.event.S_EVENT_MARK_CHANGE, MarkRemoved = world.event.S_EVENT_MARK_REMOVED, -- Moose Events - NewCargo = world.event.S_EVENT_NEW_CARGO, - DeleteCargo = world.event.S_EVENT_DELETE_CARGO, NewZone = world.event.S_EVENT_NEW_ZONE, DeleteZone = world.event.S_EVENT_DELETE_ZONE, NewZoneGoal = world.event.S_EVENT_NEW_ZONE_GOAL, @@ -512,16 +508,6 @@ local _EVENTMETA = { Event = "OnEventMarkRemoved", Text = "S_EVENT_MARK_REMOVED" }, - [EVENTS.NewCargo] = { - Order = 1, - Event = "OnEventNewCargo", - Text = "S_EVENT_NEW_CARGO" - }, - [EVENTS.DeleteCargo] = { - Order = 1, - Event = "OnEventDeleteCargo", - Text = "S_EVENT_DELETE_CARGO" - }, [EVENTS.NewZone] = { Order = 1, Event = "OnEventNewZone", @@ -1068,38 +1054,6 @@ end do -- Event Creation - -- TODO Remove old Cargo event - --- Creation of a New Cargo Event. - -- @param #EVENT self - -- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created. - function EVENT:CreateEventNewCargo( Cargo ) - self:F( { Cargo } ) - - local Event = { - id = EVENTS.NewCargo, - time = timer.getTime(), - cargo = Cargo, - } - - world.onEvent( Event ) - end - - -- TODO Remove old Cargo event - --- Creation of a Cargo Deletion Event. - -- @param #EVENT self - -- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created. - function EVENT:CreateEventDeleteCargo( Cargo ) - self:F( { Cargo } ) - - local Event = { - id = EVENTS.DeleteCargo, - time = timer.getTime(), - cargo = Cargo, - } - - world.onEvent( Event ) - end - --- Creation of a New Zone Event. -- @param #EVENT self -- @param Core.Zone#ZONE_BASE Zone The Zone created. @@ -1368,7 +1322,6 @@ function EVENT:onEvent( Event ) Event.IniDynamicCargoName = Event.IniUnitName Event.IniPlayerName = string.match(Event.IniUnitName,"^(.+)|%d%d:%d%d|PKG%d+") else - --Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName ) Event.IniUnit = STATIC:FindByName( Event.IniDCSUnitName, false ) end Event.IniCoalition = Event.IniDCSUnit:getCoalition() @@ -1540,12 +1493,6 @@ function EVENT:onEvent( Event ) Event.MarkGroupID = Event.groupID end - -- Cargo object. - if Event.cargo then - Event.Cargo = Event.cargo - Event.CargoName = Event.cargo.Name - end - -- Dynamic cargo Object if Event.dynamiccargo then Event.IniDynamicCargo = Event.dynamiccargo @@ -1707,15 +1654,6 @@ function EVENT:onEvent( Event ) end end - -- When cargo was deleted, it may probably be because of an S_EVENT_DEAD. - -- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call. - -- And this is a problem because it will remove all entries from the SET_CARGOs. - -- To prevent this from happening, the Cargo object has a flag NoDestroy. - -- When true, the SET_CARGO won't Remove the Cargo object from the set. - -- But we need to switch that flag off after the event handlers have been called. - if Event.id == EVENTS.DeleteCargo then - Event.Cargo.NoDestroy = nil - end else self:T( { EventMeta.Text, Event } ) end diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index ee2b0c6ce..8d4a3189c 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -3725,25 +3725,6 @@ do -- COORDINATE local ModeA2A = nil - --[[ - if Task then - if Task:IsInstanceOf( TASK_A2A ) then - ModeA2A = true - else - if Task:IsInstanceOf( TASK_A2G ) then - ModeA2A = false - else - if Task:IsInstanceOf( TASK_CARGO ) then - ModeA2A = false - end - if Task:IsInstanceOf( TASK_CAPTURE_ZONE ) then - ModeA2A = false - end - end - end - end - --]] - if ModeA2A == nil then local IsAir = Controllable and ( Controllable:IsAirPlane() or Controllable:IsHelicopter() ) or false if IsAir then diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 27ec6c0e0..0d567c472 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -24,7 +24,6 @@ -- * @{#SET_STATIC}: Defines a collection of @{Wrapper.Static}s filtered by filter criteria. -- * @{#SET_CLIENT}: Defines a collection of @{Wrapper.Client}s filtered by filter criteria. -- * @{#SET_AIRBASE}: Defines a collection of @{Wrapper.Airbase}s filtered by filter criteria. --- * @{#SET_CARGO}: Defines a collection of @{Cargo.Cargo}s filtered by filter criteria. -- * @{#SET_ZONE}: Defines a collection of @{Core.Zone}s filtered by filter criteria. -- * @{#SET_SCENERY}: Defines a collection of @{Wrapper.Scenery}s added via a filtered @{#SET_ZONE}. -- * @{#SET_DYNAMICCARGO}: Defines a collection of @{Wrapper.DynamicCargo}s filtered by filter criteria. @@ -5781,431 +5780,6 @@ do -- SET_AIRBASE end -do -- SET_CARGO - - --- - -- @type SET_CARGO - -- @extends Core.Set#SET_BASE - - --- Mission designers can use the @{Core.Set#SET_CARGO} class to build sets of cargos optionally belonging to certain: - -- - -- * Coalitions - -- * Types - -- * Name or Prefix - -- - -- ## SET_CARGO constructor - -- - -- Create a new SET_CARGO object with the @{#SET_CARGO.New} method: - -- - -- * @{#SET_CARGO.New}: Creates a new SET_CARGO object. - -- - -- ## Add or Remove CARGOs from SET_CARGO - -- - -- CARGOs can be added and removed using the @{Core.Set#SET_CARGO.AddCargosByName} and @{Core.Set#SET_CARGO.RemoveCargosByName} respectively. - -- These methods take a single CARGO name or an array of CARGO names to be added or removed from SET_CARGO. - -- - -- ## SET_CARGO filter criteria - -- - -- You can set filter criteria to automatically maintain the SET_CARGO contents. - -- Filter criteria are defined by: - -- - -- * @{#SET_CARGO.FilterCoalitions}: Builds the SET_CARGO with the cargos belonging to the coalition(s). - -- * @{#SET_CARGO.FilterPrefixes}: Builds the SET_CARGO with the cargos containing the same string(s). **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results. - -- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching) - -- * @{#SET_CARGO.FilterTypes}: Builds the SET_CARGO with the cargos belonging to the cargo type(s). - -- * @{#SET_CARGO.FilterCountries}: Builds the SET_CARGO with the cargos belonging to the country(ies). - -- - -- Once the filter criteria have been set for the SET_CARGO, you can start filtering using: - -- - -- * @{#SET_CARGO.FilterStart}: Starts the filtering of the cargos within the SET_CARGO. - -- - -- ## SET_CARGO iterators - -- - -- Once the filters have been defined and the SET_CARGO has been built, you can iterate the SET_CARGO with the available iterator methods. - -- The iterator methods will walk the SET_CARGO set, and call for each cargo within the set a function that you provide. - -- The following iterator methods are currently available within the SET_CARGO: - -- - -- * @{#SET_CARGO.ForEachCargo}: Calls a function for each cargo it finds within the SET_CARGO. - -- - -- @field #SET_CARGO SET_CARGO - SET_CARGO = { - ClassName = "SET_CARGO", - Cargos = {}, - Filter = { - Coalitions = nil, - Types = nil, - Countries = nil, - ClientPrefixes = nil, - }, - FilterMeta = { - Coalitions = { - red = coalition.side.RED, - blue = coalition.side.BLUE, - neutral = coalition.side.NEUTRAL, - }, - }, - } - - --- Creates a new SET_CARGO object, building a set of cargos belonging to a coalitions and categories. - -- @param #SET_CARGO self - -- @return #SET_CARGO - -- @usage - -- -- Define a new SET_CARGO Object. The DatabaseSet will contain a reference to all Cargos. - -- DatabaseSet = SET_CARGO:New() - function SET_CARGO:New() -- R2.1 - -- Inherits from BASE - local self = BASE:Inherit(self, SET_BASE:New(_DATABASE.CARGOS)) -- #SET_CARGO - - return self - end - - --- Add CARGO to SET_CARGO. - -- @param Core.Set#SET_CARGO self - -- @param Cargo.Cargo#CARGO Cargo A single cargo. - -- @return Core.Set#SET_CARGO self - function SET_CARGO:AddCargo(Cargo) -- R2.4 - - self:Add(Cargo:GetName(), Cargo) - - return self - end - - --- Add CARGOs to SET_CARGO. - -- @param Core.Set#SET_CARGO self - -- @param #string AddCargoNames A single name or an array of CARGO names. - -- @return Core.Set#SET_CARGO self - function SET_CARGO:AddCargosByName(AddCargoNames) -- R2.1 - - local AddCargoNamesArray = (type(AddCargoNames) == "table") and AddCargoNames or { AddCargoNames } - - for AddCargoID, AddCargoName in pairs(AddCargoNamesArray) do - self:Add(AddCargoName, CARGO:FindByName(AddCargoName)) - end - - return self - end - - --- Remove CARGOs from SET_CARGO. - -- @param Core.Set#SET_CARGO self - -- @param Cargo.Cargo#CARGO RemoveCargoNames A single name or an array of CARGO names. - -- @return Core.Set#SET_CARGO self - function SET_CARGO:RemoveCargosByName(RemoveCargoNames) -- R2.1 - - local RemoveCargoNamesArray = (type(RemoveCargoNames) == "table") and RemoveCargoNames or { RemoveCargoNames } - - for RemoveCargoID, RemoveCargoName in pairs(RemoveCargoNamesArray) do - self:Remove(RemoveCargoName.CargoName) - end - - return self - end - - --- Finds a Cargo based on the Cargo Name. - -- @param #SET_CARGO self - -- @param #string CargoName - -- @return Cargo.Cargo#CARGO The found Cargo. - function SET_CARGO:FindCargo(CargoName) -- R2.1 - - local CargoFound = self.Set[CargoName] - return CargoFound - end - - --- Builds a set of cargos of coalitions. - -- Possible current coalitions are red, blue and neutral. - -- @param #SET_CARGO self - -- @param #string Coalitions Can take the following values: "red", "blue", "neutral". - -- @return #SET_CARGO self - - --- Builds a set of cargos of defined cargo types. - -- Possible current types are those types known within DCS world. - -- @param #SET_CARGO self - -- @param #string Types Can take those type strings known within DCS world. - -- @return #SET_CARGO self - function SET_CARGO:FilterTypes(Types) -- R2.1 - if not self.Filter.Types then - self.Filter.Types = {} - end - if type(Types) ~= "table" then - Types = { Types } - end - for TypeID, Type in pairs(Types) do - self.Filter.Types[Type] = Type - end - return self - end - - --- Builds a set of cargos of defined countries. - -- Possible current countries are those known within DCS world. - -- @param #SET_CARGO self - -- @param #string Countries Can take those country strings known within DCS world. - -- @return #SET_CARGO self - function SET_CARGO:FilterCountries(Countries) -- R2.1 - if not self.Filter.Countries then - self.Filter.Countries = {} - end - if type(Countries) ~= "table" then - Countries = { Countries } - end - for CountryID, Country in pairs(Countries) do - self.Filter.Countries[Country] = Country - end - return self - end - - --- Builds a set of CARGOs that contain a given string in their name. - -- **Attention!** Bad naming convention as this **does not** filter only **prefixes** but all cargos that **contain** the string. - -- @param #SET_CARGO self - -- @param #string Prefixes The string pattern(s) that need to be in the cargo name. Can also be passed as a `#table` of strings. - -- @return #SET_CARGO self - function SET_CARGO:FilterPrefixes(Prefixes) -- R2.1 - if not self.Filter.CargoPrefixes then - self.Filter.CargoPrefixes = {} - end - if type(Prefixes) ~= "table" then - Prefixes = { Prefixes } - end - for PrefixID, Prefix in pairs(Prefixes) do - self.Filter.CargoPrefixes[Prefix] = Prefix - end - return self - end - - --- Starts the filtering. - -- @param #SET_CARGO self - -- @return #SET_CARGO self - function SET_CARGO:FilterStart() -- R2.1 - - if _DATABASE then - self:_FilterStart() - self:HandleEvent(EVENTS.NewCargo) - self:HandleEvent(EVENTS.DeleteCargo) - end - - return self - end - - --- Stops the filtering for the defined collection. - -- @param #SET_CARGO self - -- @return #SET_CARGO self - function SET_CARGO:FilterStop() - - self:UnHandleEvent(EVENTS.NewCargo) - self:UnHandleEvent(EVENTS.DeleteCargo) - - return self - end - - --- Handles the Database to check on an event (birth) that the Object was added in the Database. - -- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event! - -- @param #SET_CARGO self - -- @param Core.Event#EVENTDATA Event - -- @return #string The name of the CARGO - -- @return #table The CARGO - function SET_CARGO:AddInDatabase(Event) -- R2.1 - --self:F3({ Event }) - - return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] - end - - --- Handles the Database to check on any event that Object exists in the Database. - -- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa! - -- @param #SET_CARGO self - -- @param Core.Event#EVENTDATA Event - -- @return #string The name of the CARGO - -- @return #table The CARGO - function SET_CARGO:FindInDatabase(Event) -- R2.1 - --self:F3({ Event }) - - return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] - end - - --- Iterate the SET_CARGO and call an iterator function for each CARGO, providing the CARGO and optional parameters. - -- @param #SET_CARGO self - -- @param #function IteratorFunction The function that will be called when there is an alive CARGO in the SET_CARGO. The function needs to accept a CARGO parameter. - -- @return #SET_CARGO self - function SET_CARGO:ForEachCargo(IteratorFunction, ...) -- R2.1 - --self:F2(arg) - - self:ForEach(IteratorFunction, arg, self:GetSet()) - - return self - end - - --- Iterate the SET_CARGO while identifying the nearest @{Cargo.Cargo#CARGO} from a @{Core.Point#COORDINATE}. - -- @param #SET_CARGO self - -- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest @{Cargo.Cargo#CARGO}. - -- @return Cargo.Cargo#CARGO The closest @{Cargo.Cargo#CARGO}. - function SET_CARGO:FindNearestCargoFromPointVec2(Coordinate) -- R2.1 - --self:F2(Coordinate) - - local NearestCargo = self:FindNearestObjectFromPointVec2(Coordinate) - return NearestCargo - end - - --- - -- @param #SET_CARGO self - function SET_CARGO:FirstCargoWithState(State) - - local FirstCargo = nil - - for CargoName, Cargo in pairs(self.Set) do - if Cargo:Is(State) then - FirstCargo = Cargo - break - end - end - - return FirstCargo - end - - --- - -- @param #SET_CARGO self - function SET_CARGO:FirstCargoWithStateAndNotDeployed(State) - - local FirstCargo = nil - - for CargoName, Cargo in pairs(self.Set) do - if Cargo:Is(State) and not Cargo:IsDeployed() then - FirstCargo = Cargo - break - end - end - - return FirstCargo - end - - --- Iterate the SET_CARGO while identifying the first @{Cargo.Cargo#CARGO} that is UnLoaded. - -- @param #SET_CARGO self - -- @return Cargo.Cargo#CARGO The first @{Cargo.Cargo#CARGO}. - function SET_CARGO:FirstCargoUnLoaded() - local FirstCargo = self:FirstCargoWithState("UnLoaded") - return FirstCargo - end - - --- Iterate the SET_CARGO while identifying the first @{Cargo.Cargo#CARGO} that is UnLoaded and not Deployed. - -- @param #SET_CARGO self - -- @return Cargo.Cargo#CARGO The first @{Cargo.Cargo#CARGO}. - function SET_CARGO:FirstCargoUnLoadedAndNotDeployed() - local FirstCargo = self:FirstCargoWithStateAndNotDeployed("UnLoaded") - return FirstCargo - end - - --- Iterate the SET_CARGO while identifying the first @{Cargo.Cargo#CARGO} that is Loaded. - -- @param #SET_CARGO self - -- @return Cargo.Cargo#CARGO The first @{Cargo.Cargo#CARGO}. - function SET_CARGO:FirstCargoLoaded() - local FirstCargo = self:FirstCargoWithState("Loaded") - return FirstCargo - end - - --- Iterate the SET_CARGO while identifying the first @{Cargo.Cargo#CARGO} that is Deployed. - -- @param #SET_CARGO self - -- @return Cargo.Cargo#CARGO The first @{Cargo.Cargo#CARGO}. - function SET_CARGO:FirstCargoDeployed() - local FirstCargo = self:FirstCargoWithState("Deployed") - return FirstCargo - end - - --- - -- @param #SET_CARGO self - -- @param AI.AI_Cargo#AI_CARGO MCargo - -- @return #SET_CARGO self - function SET_CARGO:IsIncludeObject(MCargo) -- R2.1 - --self:F2(MCargo) - - local MCargoInclude = true - - if MCargo then - local MCargoName = MCargo:GetName() - - if self.Filter.Coalitions then - local MCargoCoalition = false - for CoalitionID, CoalitionName in pairs(self.Filter.Coalitions) do - local CargoCoalitionID = MCargo:GetCoalition() - --self:T(3({ "Coalition:", CargoCoalitionID, self.FilterMeta.Coalitions[CoalitionName], CoalitionName }) - if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == CargoCoalitionID then - MCargoCoalition = true - end - end - --self:F({ "Evaluated Coalition", MCargoCoalition }) - MCargoInclude = MCargoInclude and MCargoCoalition - end - - if self.Filter.Types then - local MCargoType = false - for TypeID, TypeName in pairs(self.Filter.Types) do - --self:T(3({ "Type:", MCargo:GetType(), TypeName }) - if TypeName == MCargo:GetType() then - MCargoType = true - end - end - --self:F({ "Evaluated Type", MCargoType }) - MCargoInclude = MCargoInclude and MCargoType - end - - if self.Filter.CargoPrefixes then - local MCargoPrefix = false - for CargoPrefixId, CargoPrefix in pairs(self.Filter.CargoPrefixes) do - --self:T(3({ "Prefix:", string.find(MCargo.Name, CargoPrefix, 1), CargoPrefix }) - if string.find(MCargo.Name, CargoPrefix, 1) then - MCargoPrefix = true - end - end - --self:F({ "Evaluated Prefix", MCargoPrefix }) - MCargoInclude = MCargoInclude and MCargoPrefix - end - end - - if self.Filter.Functions and MCargoInclude then - local MClientFunc = self:_EvalFilterFunctions(MCargo) - MCargoInclude = MCargoInclude and MClientFunc - end - - --self:T(2(MCargoInclude) - return MCargoInclude - end - - --- Handles the OnEventNewCargo event for the Set. - -- @param #SET_CARGO self - -- @param Core.Event#EVENTDATA EventData - function SET_CARGO:OnEventNewCargo(EventData) -- R2.1 - - --self:F({ "New Cargo", EventData }) - - if EventData.Cargo then - if EventData.Cargo and self:IsIncludeObject(EventData.Cargo) then - self:Add(EventData.Cargo.Name, EventData.Cargo) - end - end - end - - --- Handles the OnDead or OnCrash event for alive units set. - -- @param #SET_CARGO self - -- @param Core.Event#EVENTDATA EventData - function SET_CARGO:OnEventDeleteCargo(EventData) -- R2.1 - --self:F3({ EventData }) - - if EventData.Cargo then - local Cargo = _DATABASE:FindCargo(EventData.Cargo.Name) - if Cargo and Cargo.Name then - - -- When cargo was deleted, it may probably be because of an S_EVENT_DEAD. - -- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call. - -- And this is a problem because it will remove all entries from the SET_CARGOs. - -- To prevent this from happening, the Cargo object has a flag NoDestroy. - -- When true, the SET_CARGO won't Remove the Cargo object from the set. - -- This flag is switched off after the event handlers have been called in the EVENT class. - --self:F({ CargoNoDestroy = Cargo.NoDestroy }) - if Cargo.NoDestroy then - else - self:Remove(Cargo.Name) - end - end - end - end - -end - do -- SET_ZONE --- @@ -6547,14 +6121,6 @@ do -- SET_ZONE if EventData.Zone then local Zone = _DATABASE:FindZone(EventData.Zone.ZoneName) if Zone and Zone.ZoneName then - - -- When cargo was deleted, it may probably be because of an S_EVENT_DEAD. - -- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call. - -- And this is a problem because it will remove all entries from the SET_ZONEs. - -- To prevent this from happening, the Zone object has a flag NoDestroy. - -- When true, the SET_ZONE won't Remove the Zone object from the set. - -- This flag is switched off after the event handlers have been called in the EVENT class. - --self:F({ ZoneNoDestroy = Zone.NoDestroy }) if Zone.NoDestroy then else self:Remove(Zone.ZoneName) @@ -7069,14 +6635,6 @@ do -- SET_ZONE_GOAL if EventData.ZoneGoal then local Zone = _DATABASE:FindZone(EventData.ZoneGoal.ZoneName) if Zone and Zone.ZoneName then - - -- When cargo was deleted, it may probably be because of an S_EVENT_DEAD. - -- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call. - -- And this is a problem because it will remove all entries from the SET_ZONE_GOALs. - -- To prevent this from happening, the Zone object has a flag NoDestroy. - -- When true, the SET_ZONE_GOAL won't Remove the Zone object from the set. - -- This flag is switched off after the event handlers have been called in the EVENT class. - --self:F({ ZoneNoDestroy = Zone.NoDestroy }) if Zone.NoDestroy then else self:Remove(Zone.ZoneName) @@ -7465,14 +7023,6 @@ do -- SET_OPSZONE if EventData.ZoneGoal then local Zone = _DATABASE:FindZone(EventData.ZoneGoal.ZoneName) if Zone and Zone.ZoneName then - - -- When cargo was deleted, it may probably be because of an S_EVENT_DEAD. - -- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call. - -- And this is a problem because it will remove all entries from the SET_OPSZONEs. - -- To prevent this from happening, the Zone object has a flag NoDestroy. - -- When true, the SET_OPSZONE won't Remove the Zone object from the set. - -- This flag is switched off after the event handlers have been called in the EVENT class. - --self:F({ ZoneNoDestroy = Zone.NoDestroy }) if Zone.NoDestroy then else self:Remove(Zone.ZoneName) diff --git a/Moose Development/Moose/Functional/Artillery.lua b/Moose Development/Moose/Functional/Artillery.lua index 669fde4e0..9e68aafa6 100644 --- a/Moose Development/Moose/Functional/Artillery.lua +++ b/Moose Development/Moose/Functional/Artillery.lua @@ -511,24 +511,6 @@ -- -- Start ARTY process. -- normandy:Start() -- --- ### Transportation as Cargo --- This example demonstates how an ARTY group can be transported to another location as cargo. --- -- Define a group as CARGO_GROUP --- CargoGroupMortars=CARGO_GROUP:New(GROUP:FindByName("Mortars"), "Mortars", "Mortar Platoon Alpha", 100 , 10) --- --- -- Define the mortar CARGO GROUP as ARTY object --- mortars=ARTY:NewFromCargoGroup(CargoGroupMortars, "Mortar Platoon Alpha") --- --- -- Start ARTY process --- mortars:Start() --- --- -- Setup AI cargo dispatcher for e.g. helos --- SetHeloCarriers = SET_GROUP:New():FilterPrefixes("CH-47D"):FilterStart() --- SetCargoMortars = SET_CARGO:New():FilterTypes("Mortars"):FilterStart() --- SetZoneDepoly = SET_ZONE:New():FilterPrefixes("Deploy"):FilterStart() --- CargoHelo=AI_CARGO_DISPATCHER_HELICOPTER:New(SetHeloCarriers, SetCargoMortars, SetZoneDepoly) --- CargoHelo:Start() --- The ARTY group will be transported and resume its normal operation after it has been deployed. New targets can be assigned at any time also during the transportation process. -- -- @field #ARTY ARTY={ @@ -1230,37 +1212,6 @@ function ARTY:New(group, alias) return self end ---- Creates a new ARTY object from a MOOSE CARGO_GROUP object. --- @param #ARTY self --- @param Cargo.CargoGroup#CARGO_GROUP cargogroup The CARGO GROUP object for which artillery tasks should be assigned. --- @param alias (Optional) Alias name the group will be calling itself when sending messages. Default is the group name. --- @return #ARTY ARTY object or nil if group does not exist or is not a ground or naval group. -function ARTY:NewFromCargoGroup(cargogroup, alias) - - if cargogroup then - BASE:T(string.format("ARTY script version %s. Added CARGO group %s.", ARTY.version, cargogroup:GetName())) - else - BASE:E("ERROR: Requested ARTY CARGO GROUP does not exist! (Has to be a MOOSE CARGO(!) group.)") - return nil - end - - -- Get group belonging to the cargo group. - local group=cargogroup:GetObject() - - -- Create ARTY object. - local arty=ARTY:New(group,alias) - - -- Set iscargo flag. - arty.iscargo=true - - -- Set cargo group object. - arty.cargogroup=cargogroup - - return arty -end - - - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- User Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Functional/ZoneGoalCargo.lua b/Moose Development/Moose/Functional/ZoneGoalCargo.lua deleted file mode 100644 index 10b91e12f..000000000 --- a/Moose Development/Moose/Functional/ZoneGoalCargo.lua +++ /dev/null @@ -1,458 +0,0 @@ ---- **Functional** - 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. --- --- # Developer Note --- --- ![Banner Image](..\Images\deprecated.png) --- --- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE --- Therefore, this class is considered to be deprecated --- --- === --- --- ### Author: **FlightControl** --- --- === --- --- @module Functional.ZoneGoalCargo --- @image MOOSE.JPG - -do -- ZoneGoal - - -- @type ZONE_GOAL_CARGO - -- @extends Functional.ZoneGoal#ZONE_GOAL - - - --- 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. - -- - -- ## 1. ZONE_GOAL_CARGO constructor - -- - -- * @{#ZONE_GOAL_CARGO.New}(): Creates a new ZONE_GOAL_CARGO object. - -- - -- ## 2. ZONE_GOAL_CARGO is a finite state machine (FSM). - -- - -- ### 2.1 ZONE_GOAL_CARGO States - -- - -- * **Deployed**: The Zone has been captured by an other coalition. - -- * **Airborne**: The Zone is currently intruded by an other coalition. There are units of the owning coalition and an other coalition in the Zone. - -- * **Loaded**: 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. - -- - -- ### 2.2 ZONE_GOAL_CARGO Events - -- - -- * **Capture**: The Zone has been captured by an other 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. - -- - -- ### 2.3 ZONE_GOAL_CARGO State Machine - -- - -- @field #ZONE_GOAL_CARGO - ZONE_GOAL_CARGO = { - ClassName = "ZONE_GOAL_CARGO", - } - - -- @field #table ZONE_GOAL_CARGO.States - ZONE_GOAL_CARGO.States = {} - - --- ZONE_GOAL_CARGO Constructor. - -- @param #ZONE_GOAL_CARGO self - -- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved. - -- @param #number Coalition The initial coalition owning the zone. - -- @return #ZONE_GOAL_CARGO - function ZONE_GOAL_CARGO:New( Zone, Coalition ) - - local self = BASE:Inherit( self, ZONE_GOAL:New( Zone ) ) -- #ZONE_GOAL_CARGO - self:F( { Zone = Zone, Coalition = Coalition } ) - - self:SetCoalition( Coalition ) - - do - - --- Captured State Handler OnLeave for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnLeaveCaptured - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - -- @return #boolean - - --- Captured State Handler OnEnter for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnEnterCaptured - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - - end - - - do - - --- Attacked State Handler OnLeave for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnLeaveAttacked - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - -- @return #boolean - - --- Attacked State Handler OnEnter for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnEnterAttacked - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - - end - - do - - --- Guarded State Handler OnLeave for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnLeaveGuarded - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - -- @return #boolean - - --- Guarded State Handler OnEnter for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnEnterGuarded - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - - end - - - do - - --- Empty State Handler OnLeave for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnLeaveEmpty - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - -- @return #boolean - - --- Empty State Handler OnEnter for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnEnterEmpty - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - - end - - self:AddTransition( "*", "Guard", "Guarded" ) - - --- Guard Handler OnBefore for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnBeforeGuard - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - -- @return #boolean - - --- Guard Handler OnAfter for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnAfterGuard - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - - --- Guard Trigger for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] Guard - -- @param #ZONE_GOAL_CARGO self - - --- Guard Asynchronous Trigger for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] __Guard - -- @param #ZONE_GOAL_CARGO self - -- @param #number Delay - - self:AddTransition( "*", "Empty", "Empty" ) - - --- Empty Handler OnBefore for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnBeforeEmpty - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - -- @return #boolean - - --- Empty Handler OnAfter for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnAfterEmpty - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - - --- Empty Trigger for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] Empty - -- @param #ZONE_GOAL_CARGO self - - --- Empty Asynchronous Trigger for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] __Empty - -- @param #ZONE_GOAL_CARGO self - -- @param #number Delay - - - self:AddTransition( { "Guarded", "Empty" }, "Attack", "Attacked" ) - - --- Attack Handler OnBefore for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnBeforeAttack - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - -- @return #boolean - - --- Attack Handler OnAfter for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnAfterAttack - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - - --- Attack Trigger for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] Attack - -- @param #ZONE_GOAL_CARGO self - - --- Attack Asynchronous Trigger for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] __Attack - -- @param #ZONE_GOAL_CARGO self - -- @param #number Delay - - self:AddTransition( { "Guarded", "Attacked", "Empty" }, "Capture", "Captured" ) - - --- Capture Handler OnBefore for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnBeforeCapture - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - -- @return #boolean - - --- Capture Handler OnAfter for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] OnAfterCapture - -- @param #ZONE_GOAL_CARGO self - -- @param #string From - -- @param #string Event - -- @param #string To - - --- Capture Trigger for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] Capture - -- @param #ZONE_GOAL_CARGO self - - --- Capture Asynchronous Trigger for ZONE_GOAL_CARGO - -- @function [parent=#ZONE_GOAL_CARGO] __Capture - -- @param #ZONE_GOAL_CARGO self - -- @param #number Delay - - return self - end - - - --- Set the owning coalition of the zone. - -- @param #ZONE_GOAL_CARGO self - -- @param #number Coalition - function ZONE_GOAL_CARGO:SetCoalition( Coalition ) - self.Coalition = Coalition - end - - - --- Get the owning coalition of the zone. - -- @param #ZONE_GOAL_CARGO self - -- @return #number Coalition. - function ZONE_GOAL_CARGO:GetCoalition() - return self.Coalition - end - - - --- Get the owning coalition name of the zone. - -- @param #ZONE_GOAL_CARGO self - -- @return #string Coalition name. - function ZONE_GOAL_CARGO:GetCoalitionName() - - if self.Coalition == coalition.side.BLUE then - return "Blue" - end - - if self.Coalition == coalition.side.RED then - return "Red" - end - - if self.Coalition == coalition.side.NEUTRAL then - return "Neutral" - end - - return "" - end - - - function ZONE_GOAL_CARGO:IsGuarded() - - local IsGuarded = self.Zone:IsAllInZoneOfCoalition( self.Coalition ) - self:F( { IsGuarded = IsGuarded } ) - return IsGuarded - end - - - function ZONE_GOAL_CARGO:IsEmpty() - - local IsEmpty = self.Zone:IsNoneInZone() - self:F( { IsEmpty = IsEmpty } ) - return IsEmpty - end - - - function ZONE_GOAL_CARGO:IsCaptured() - - local IsCaptured = self.Zone:IsAllInZoneOfOtherCoalition( self.Coalition ) - self:F( { IsCaptured = IsCaptured } ) - return IsCaptured - end - - - function ZONE_GOAL_CARGO:IsAttacked() - - local IsAttacked = self.Zone:IsSomeInZoneOfCoalition( self.Coalition ) - self:F( { IsAttacked = IsAttacked } ) - return IsAttacked - end - - - - --- Mark. - -- @param #ZONE_GOAL_CARGO self - function ZONE_GOAL_CARGO:Mark() - - local Coord = self.Zone:GetCoordinate() - local ZoneName = self:GetZoneName() - local State = self:GetState() - - if self.MarkRed and self.MarkBlue then - self:F( { MarkRed = self.MarkRed, MarkBlue = self.MarkBlue } ) - Coord:RemoveMark( self.MarkRed ) - Coord:RemoveMark( self.MarkBlue ) - end - - if self.Coalition == coalition.side.BLUE then - self.MarkBlue = Coord:MarkToCoalitionBlue( "Guard Zone: " .. ZoneName .. "\nStatus: " .. State ) - self.MarkRed = Coord:MarkToCoalitionRed( "Capture Zone: " .. ZoneName .. "\nStatus: " .. State ) - else - self.MarkRed = Coord:MarkToCoalitionRed( "Guard Zone: " .. ZoneName .. "\nStatus: " .. State ) - self.MarkBlue = Coord:MarkToCoalitionBlue( "Capture Zone: " .. ZoneName .. "\nStatus: " .. State ) - end - end - - --- Bound. - -- @param #ZONE_GOAL_CARGO self - function ZONE_GOAL_CARGO:onenterGuarded() - - --self:GetParent( self ):onenterGuarded() - - if self.Coalition == coalition.side.BLUE then - --elf.ProtectZone:BoundZone( 12, country.id.USA ) - else - --self.ProtectZone:BoundZone( 12, country.id.RUSSIA ) - end - - self:Mark() - - end - - function ZONE_GOAL_CARGO:onenterCaptured() - - --self:GetParent( self ):onenterCaptured() - - local NewCoalition = self.Zone:GetCoalition() - self:F( { NewCoalition = NewCoalition } ) - self:SetCoalition( NewCoalition ) - - self:Mark() - end - - - function ZONE_GOAL_CARGO:onenterEmpty() - - --self:GetParent( self ):onenterEmpty() - - self:Mark() - end - - - function ZONE_GOAL_CARGO:onenterAttacked() - - --self:GetParent( self ):onenterAttacked() - - self:Mark() - end - - - --- When started, check the Coalition status. - -- @param #ZONE_GOAL_CARGO self - function ZONE_GOAL_CARGO:onafterGuard() - - --self:F({BASE:GetParent( self )}) - --BASE:GetParent( self ).onafterGuard( self ) - - if not self.SmokeScheduler then - self.SmokeScheduler = self:ScheduleRepeat( 1, 1, 0.1, nil, self.StatusSmoke, self ) - end - if not self.ScheduleStatusZone then - self.ScheduleStatusZone = self:ScheduleRepeat( 15, 15, 0.1, nil, self.StatusZone, self ) - end - end - - - function ZONE_GOAL_CARGO:IsCaptured() - - local IsCaptured = self.Zone:IsAllInZoneOfOtherCoalition( self.Coalition ) - self:F( { IsCaptured = IsCaptured } ) - return IsCaptured - end - - - function ZONE_GOAL_CARGO:IsAttacked() - - local IsAttacked = self.Zone:IsSomeInZoneOfCoalition( self.Coalition ) - self:F( { IsAttacked = IsAttacked } ) - return IsAttacked - end - - --- Check status Coalition ownership. - -- @param #ZONE_GOAL_CARGO self - function ZONE_GOAL_CARGO:StatusZone() - - local State = self:GetState() - self:F( { State = self:GetState() } ) - - self.Zone:Scan() - - if State ~= "Guarded" and self:IsGuarded() then - self:Guard() - end - - if State ~= "Empty" and self:IsEmpty() then - self:Empty() - end - - if State ~= "Attacked" and self:IsAttacked() then - self:Attack() - end - - if State ~= "Captured" and self:IsCaptured() then - self:Capture() - end - - end - -end - diff --git a/Moose Development/Moose/Globals.lua b/Moose Development/Moose/Globals.lua index 5108254d1..d5f7ef941 100644 --- a/Moose Development/Moose/Globals.lua +++ b/Moose Development/Moose/Globals.lua @@ -13,9 +13,6 @@ _DATABASE = DATABASE:New() -- Core.Database#DATABASE _SETTINGS = SETTINGS:Set() -- Core.Settings#SETTINGS _SETTINGS:SetPlayerMenuOn() ---- Register cargos. -_DATABASE:_RegisterCargos() - --- Register zones. _DATABASE:_RegisterZones() _DATABASE:_RegisterAirbases() diff --git a/Moose Development/Moose/Modules.lua b/Moose Development/Moose/Modules.lua index b6ff32ab9..489d0421a 100644 --- a/Moose Development/Moose/Modules.lua +++ b/Moose Development/Moose/Modules.lua @@ -50,11 +50,6 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Net.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Storage.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/DynamicCargo.lua' ) -__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/Cargo.lua' ) -__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoUnit.lua' ) -__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoSlingload.lua' ) -__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoCrate.lua' ) -__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoGroup.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Scoring.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/CleanUp.lua' ) @@ -80,7 +75,6 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Shorad.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/AICSAR.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/AmmoTruck.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Autolase.lua' ) -__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ZoneGoalCargo.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Tiresias.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Stratego.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua') diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index d39f0bb30..cb1a18225 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -148,7 +148,7 @@ function CLIENT:FindByName( ClientName, ClientBriefing, Error ) end end ---- Transport defines that the Client is a Transport. Transports show cargo. +--- Register a client. -- @param #CLIENT self -- @param #string ClientName Name of the client unit. -- @return #CLIENT self @@ -507,37 +507,6 @@ function CLIENT:GetClientGroupDCSUnit() end end - ---- Evaluates if the CLIENT is a transport. --- @param #CLIENT self --- @return #boolean true is a transport. -function CLIENT:IsTransport() - self:F() - return self.ClientTransport -end - ---- Shows the @{AI.AI_Cargo#CARGO} contained within the CLIENT to the player as a message. --- The @{AI.AI_Cargo#CARGO} is shown using the @{Core.Message#MESSAGE} distribution system. --- @param #CLIENT self -function CLIENT:ShowCargo() - self:F() - - local CargoMsg = "" - - for CargoName, Cargo in pairs( CARGOS ) do - if self == Cargo:IsLoadedInClient() then - CargoMsg = CargoMsg .. Cargo.CargoName .. " Type:" .. Cargo.CargoType .. " Weight: " .. Cargo.CargoWeight .. "\n" - end - end - - if CargoMsg == "" then - CargoMsg = "empty" - end - - self:Message( CargoMsg, 15, "Co-Pilot: Cargo Status", 30 ) - -end - --- The main message driver for the CLIENT. -- This function displays various messages to the Player logged into the CLIENT through the DCS World Messaging system. -- @param #CLIENT self