diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua
index 2172045f7..9b05de6c0 100644
--- a/Moose Development/Moose/AI/AI_Cargo.lua
+++ b/Moose Development/Moose/AI/AI_Cargo.lua
@@ -15,55 +15,7 @@
--
-- * AI_CARGO_GROUPED, represented by a Group of CARGO_UNITs.
--
--- # 1) @{#AI_CARGO} class, extends @{Fsm#FSM_PROCESS}
--
--- The @{#AI_CARGO} class 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.
---
--- The AI_CARGO is a state machine: it manages the different events and states of the cargo.
--- All derived classes from AI_CARGO follow the same state machine, expose the same cargo event functions, and provide the same cargo states.
---
--- ## 1.2.1) AI_CARGO Events:
---
--- * @{#AI_CARGO.Board}( ToCarrier ): Boards the cargo to a carrier.
--- * @{#AI_CARGO.Load}( ToCarrier ): Loads the cargo into a carrier, regardless of its position.
--- * @{#AI_CARGO.UnBoard}( ToPointVec2 ): UnBoard the cargo from a carrier. This will trigger a movement of the cargo to the option ToPointVec2.
--- * @{#AI_CARGO.UnLoad}( ToPointVec2 ): UnLoads the cargo from a carrier.
--- * @{#AI_CARGO.Dead}( Controllable ): The cargo is dead. The cargo process will be ended.
---
--- ## 1.2.2) AI_CARGO States:
---
--- * **UnLoaded**: The cargo is unloaded from a carrier.
--- * **Boarding**: The cargo is currently boarding (= running) into a carrier.
--- * **Loaded**: The cargo is loaded into a carrier.
--- * **UnBoarding**: The cargo is currently unboarding (=running) from a carrier.
--- * **Dead**: The cargo is dead ...
--- * **End**: The process has come to an end.
---
--- ## 1.2.3) AI_CARGO state transition methods:
---
--- State transition functions can be set **by the mission designer** customizing or improving the behaviour of the state.
--- There are 2 moments when state transition methods will be called by the state machine:
---
--- * **Leaving** the state.
--- The state transition method needs to start with the name **OnLeave + the name of the state**.
--- If the state transition method returns false, then the processing of the state transition will not be done!
--- If you want to change the behaviour of the AIControllable at this event, return false,
--- but then you'll need to specify your own logic using the AIControllable!
---
--- * **Entering** the state.
--- The state transition method needs to start with the name **OnEnter + the name of the state**.
--- These state transition methods need to provide a return value, which is specified at the function description.
---
--- # 2) #AI_CARGO_UNIT class
---
--- The AI_CARGO_UNIT class 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 AI_CARGO_UNIT objects to and from carriers.
---
--- # 5) #AI_CARGO_GROUPED class
---
--- The AI_CARGO_GROUPED class defines a cargo that is represented by a group of UNIT objects within the simulator, and can be transported by a carrier.
--- Use the event functions as described above to Load, UnLoad, Board, UnBoard the AI_CARGO_UNIT objects to and from carriers.
--
-- This module is still under construction, but is described above works already, and will keep working ...
--
@@ -200,6 +152,49 @@ do -- AI_CARGO
-- @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.
+
+ --- # AI\_CARGO class, extends @{Fsm#FSM_PROCESS}
+ --
+ -- The AI\_CARGO class 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.
+ --
+ -- The AI\_CARGO is a state machine: it manages the different events and states of the cargo.
+ -- All derived classes from AI\_CARGO follow the same state machine, expose the same cargo event functions, and provide the same cargo states.
+ --
+ -- ## AI\_CARGO Events:
+ --
+ -- * @{#AI\_CARGO.Board}( ToCarrier ): Boards the cargo to a carrier.
+ -- * @{#AI\_CARGO.Load}( ToCarrier ): Loads the cargo into a carrier, regardless of its position.
+ -- * @{#AI\_CARGO.UnBoard}( ToPointVec2 ): UnBoard the cargo from a carrier. This will trigger a movement of the cargo to the option ToPointVec2.
+ -- * @{#AI\_CARGO.UnLoad}( ToPointVec2 ): UnLoads the cargo from a carrier.
+ -- * @{#AI\_CARGO.Dead}( Controllable ): The cargo is dead. The cargo process will be ended.
+ --
+ -- ## AI\_CARGO States:
+ --
+ -- * **UnLoaded**: The cargo is unloaded from a carrier.
+ -- * **Boarding**: The cargo is currently boarding (= running) into a carrier.
+ -- * **Loaded**: The cargo is loaded into a carrier.
+ -- * **UnBoarding**: The cargo is currently unboarding (=running) from a carrier.
+ -- * **Dead**: The cargo is dead ...
+ -- * **End**: The process has come to an end.
+ --
+ -- ## AI\_CARGO state transition methods:
+ --
+ -- State transition functions can be set **by the mission designer** customizing or improving the behaviour of the state.
+ -- There are 2 moments when state transition methods will be called by the state machine:
+ --
+ -- * **Leaving** the state.
+ -- The state transition method needs to start with the name **OnLeave + the name of the state**.
+ -- If the state transition method returns false, then the processing of the state transition will not be done!
+ -- If you want to change the behaviour of the AIControllable at this event, return false,
+ -- but then you'll need to specify your own logic using the AIControllable!
+ --
+ -- * **Entering** the state.
+ -- The state transition method needs to start with the name **OnEnter + the name of the state**.
+ -- These state transition methods need to provide a return value, which is specified at the function description.
+ --
+ -- @field #AI_CARGO AI_CARGO
+ --
AI_CARGO = {
ClassName = "AI_CARGO",
Type = nil,
@@ -244,8 +239,8 @@ function AI_CARGO:New( Type, Name, Weight, ReportRadius, NearRadius )
self.Type = Type
self.Name = Name
self.Weight = Weight
- self.ReportRadius = ReportRadius
- self.NearRadius = NearRadius
+ self.ReportRadius = ReportRadius or 1000
+ self.NearRadius = NearRadius or 200
self.CargoObject = nil
self.CargoCarrier = nil
self.Representable = false
@@ -258,9 +253,39 @@ function AI_CARGO:New( Type, Name, Weight, ReportRadius, NearRadius )
CARGOS[self.Name] = self
+ self:SetEventPriority( 5 )
+
return self
end
+--- Get the name of the Cargo.
+-- @param #AI_CARGO self
+-- @return #string The name of the Cargo.
+function AI_CARGO:GetName()
+ return self.Name
+end
+
+--- Get the type of the Cargo.
+-- @param #AI_CARGO self
+-- @return #string The type of the Cargo.
+function AI_CARGO:GetType()
+ return self.Type
+end
+
+--- Check if cargo is loaded.
+-- @param #AI_CARGO self
+-- @return #boolean true if loaded
+function AI_CARGO:IsLoaded()
+ return self:Is( "Loaded" )
+end
+
+--- Check if cargo is unloaded.
+-- @param #AI_CARGO self
+-- @return #boolean true if unloaded
+function AI_CARGO:IsUnLoaded()
+ return self:Is( "UnLoaded" )
+end
+
--- Template method to spawn a new representation of the AI_CARGO in the simulator.
-- @param #AI_CARGO self
@@ -270,6 +295,46 @@ function AI_CARGO:Spawn( PointVec2 )
end
+--- Check if CargoCarrier is in the radius for the Cargo to be Loaded.
+-- @param #AI_CARGO self
+-- @param Core.Point#POINT_VEC2 PointVec2
+-- @return #boolean
+function AI_CARGO:IsInRadius( PointVec2 )
+ self:F( { PointVec2 } )
+
+ local Distance = 0
+ if self:IsLoaded() then
+ Distance = PointVec2:DistanceFromPointVec2( self.CargoCarrier:GetPointVec2() )
+ else
+ Distance = PointVec2:DistanceFromPointVec2( self.CargoObject:GetPointVec2() )
+ end
+ self:T( Distance )
+
+ if Distance <= self.ReportRadius then
+ return true
+ else
+ return false
+ end
+end
+
+
+--- Check if Cargo is the given @{Zone}.
+-- @param #AI_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 AI_CARGO:IsInZone( Zone )
+ self:F( { Zone } )
+
+ if self:IsLoaded() then
+ return Zone:IsPointVec2InZone( self.CargoCarrier:GetPointVec2() )
+ else
+ return Zone:IsPointVec2InZone( self.CargoObject:GetPointVec2() )
+ end
+
+ return nil
+
+end
+
--- Check if CargoCarrier is near the Cargo to be Loaded.
-- @param #AI_CARGO self
@@ -288,6 +353,20 @@ function AI_CARGO:IsNear( PointVec2 )
end
end
+--- Get the current PointVec2 of the cargo.
+-- @param #AI_CARGO self
+-- @return Core.Point#POINT_VEC2
+function AI_CARGO:GetPointVec2()
+ return self.CargoObject:GetPointVec2()
+end
+
+--- Get the range till cargo will board.
+-- @param #AI_CARGO self
+-- @return #number The range till cargo will board.
+function AI_CARGO:GetBoardingRange()
+ return self.ReportRadius
+end
+
end
do -- AI_CARGO_REPRESENTABLE
@@ -340,6 +419,16 @@ do -- AI_CARGO_UNIT
--- @type AI_CARGO_UNIT
-- @extends #AI_CARGO_REPRESENTABLE
+
+ --- # AI\_CARGO\_UNIT class, extends @{#AI_CARGO_REPRESENTABLE}
+ --
+ -- The AI\_CARGO\_UNIT class 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 AI\_CARGO\_UNIT objects to and from carriers.
+ --
+ -- ===
+ --
+ -- @field #AI_CARGO_UNIT AI_CARGO_UNIT
+ --
AI_CARGO_UNIT = {
ClassName = "AI_CARGO_UNIT"
}
@@ -362,6 +451,20 @@ function AI_CARGO_UNIT:New( CargoUnit, Type, Name, Weight, ReportRadius, NearRad
self:T( self.ClassName )
+ -- Cargo objects are added to the _DATABASE and SET_CARGO objects.
+ _EVENTDISPATCHER:CreateEventNewCargo( self )
+
+ return self
+end
+
+--- AI_CARGO_UNIT Destructor.
+-- @param #AI_CARGO_UNIT self
+-- @return #AI_CARGO_UNIT
+function AI_CARGO_UNIT:Destroy()
+
+ -- Cargo objects are deleted from the _DATABASE and SET_CARGO objects.
+ _EVENTDISPATCHER:CreateEventDeleteCargo( self )
+
return self
end
@@ -503,7 +606,7 @@ end
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier
-function AI_CARGO_UNIT:onenterBoarding( From, Event, To, CargoCarrier )
+function AI_CARGO_UNIT:onenterBoarding( From, Event, To, CargoCarrier, ... )
self:F( { CargoCarrier.UnitName, From, Event, To } )
local Speed = 10
@@ -535,14 +638,14 @@ end
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier
-function AI_CARGO_UNIT:onleaveBoarding( From, Event, To, CargoCarrier )
+function AI_CARGO_UNIT:onleaveBoarding( From, Event, To, CargoCarrier, ... )
self:F( { CargoCarrier.UnitName, From, Event, To } )
if self:IsNear( CargoCarrier:GetPointVec2() ) then
- self:__Load( 1, CargoCarrier )
+ self:__Load( 1, CargoCarrier, ... )
return true
else
- self:__Boarding( 1, CargoCarrier )
+ self:__Boarding( 1, CargoCarrier, ... )
end
return false
end
@@ -571,7 +674,7 @@ end
-- @param #string Event
-- @param #string From
-- @param #string To
-function AI_CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier )
+function AI_CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, ... )
self:F()
self.CargoInAir = self.CargoObject:InAir()
@@ -581,7 +684,7 @@ function AI_CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier )
-- 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
- self:Load( CargoCarrier )
+ self:Load( CargoCarrier, ... )
end
end
@@ -809,6 +912,14 @@ do -- AI_CARGO_GROUP
-- @extends AI.AI_Cargo#AI_CARGO
-- @field Set#SET_BASE CargoSet A set of cargo objects.
-- @field #string Name A string defining the name of the cargo group. The name is the unique identifier of the cargo.
+
+ --- # AI\_CARGO\_GROUP class
+ --
+ -- The AI\_CARGO\_GROUP class defines a cargo that is represented by a group of @{Unit} objects within the simulator, and can be transported by a carrier.
+ -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the AI\_CARGO\_GROUP to and from carrier.
+ --
+ -- @field #AI_CARGO_GROUP AI_CARGO_GROUP
+ --
AI_CARGO_GROUP = {
ClassName = "AI_CARGO_GROUP",
}
@@ -838,6 +949,14 @@ do -- AI_CARGO_GROUPED
--- @type AI_CARGO_GROUPED
-- @extends AI.AI_Cargo#AI_CARGO_GROUP
+
+ --- # AI\_CARGO\_GROUPED class
+ --
+ -- The AI\_CARGO\_GROUPED class defines a cargo that is represented by a group of UNIT objects within the simulator, and can be transported by a carrier.
+ -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the AI\_CARGO\_UNIT objects to and from carriers.
+ --
+ -- @field #AI_CARGO_GROUPED AI_CARGO_GROUPED
+ --
AI_CARGO_GROUPED = {
ClassName = "AI_CARGO_GROUPED",
}
diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua
index bdf743d0d..0b3a3df6c 100644
--- a/Moose Development/Moose/Core/Database.lua
+++ b/Moose Development/Moose/Core/Database.lua
@@ -6,12 +6,14 @@
-- ===================================================
-- Mission designers can use the DATABASE class to refer to:
--
+-- * STATICS
-- * UNITS
-- * GROUPS
-- * CLIENTS
--- * AIRPORTS
+-- * AIRBASES
-- * PLAYERSJOINED
-- * PLAYERS
+-- * CARGOS
--
-- On top, for internal MOOSE administration purposes, the DATBASE administers the Unit and Group TEMPLATES as defined within the Mission Editor.
--
@@ -54,6 +56,7 @@ DATABASE = {
PLAYERS = {},
PLAYERSJOINED = {},
CLIENTS = {},
+ CARGOS = {},
AIRBASES = {},
COUNTRY_ID = {},
COUNTRY_NAME = {},
@@ -85,13 +88,15 @@ local _DATABASECategory =
function DATABASE:New()
-- Inherits from BASE
- local self = BASE:Inherit( self, BASE:New() )
+ local self = BASE:Inherit( self, BASE:New() ) -- #DATABASE
self:SetEventPriority( 1 )
self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
+ self:HandleEvent( EVENTS.NewCargo )
+ self:HandleEvent( EVENTS.DeleteCargo )
-- Follow alive players and clients
self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit )
@@ -167,22 +172,24 @@ end
--- Adds a Airbase based on the Airbase Name in the DATABASE.
-- @param #DATABASE self
-function DATABASE:AddAirbase( DCSAirbaseName )
+-- @param #string AirbaseName The name of the airbase
+function DATABASE:AddAirbase( AirbaseName )
- if not self.AIRBASES[DCSAirbaseName] then
- self.AIRBASES[DCSAirbaseName] = AIRBASE:Register( DCSAirbaseName )
+ if not self.AIRBASES[AirbaseName] then
+ self.AIRBASES[AirbaseName] = AIRBASE:Register( AirbaseName )
end
end
--- Deletes a Airbase from the DATABASE based on the Airbase Name.
-- @param #DATABASE self
-function DATABASE:DeleteAirbase( DCSAirbaseName )
+-- @param #string AirbaseName The name of the airbase
+function DATABASE:DeleteAirbase( AirbaseName )
- --self.AIRBASES[DCSAirbaseName] = nil
+ self.AIRBASES[AirbaseName] = nil
end
---- Finds a AIRBASE based on the AirbaseName.
+--- Finds an AIRBASE based on the AirbaseName.
-- @param #DATABASE self
-- @param #string AirbaseName
-- @return Wrapper.Airbase#AIRBASE The found AIRBASE.
@@ -192,6 +199,35 @@ function DATABASE:FindAirbase( AirbaseName )
return AirbaseFound
end
+--- 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 Wrapper.Cargo#CARGO The found CARGO.
+function DATABASE:FindCargo( CargoName )
+
+ local CargoFound = self.CARGOS[CargoName]
+ return CargoFound
+end
+
--- Finds a CLIENT based on the ClientName.
-- @param #DATABASE self
@@ -714,7 +750,7 @@ end
--- Iterate the DATABASE and call an iterator function for each **alive** UNIT, providing the UNIT and optional parameters.
-- @param #DATABASE self
--- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the database. The function needs to accept a UNIT parameter.
+-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a UNIT parameter.
-- @return #DATABASE self
function DATABASE:ForEachUnit( IteratorFunction, FinalizeFunction, ... )
self:F2( arg )
@@ -726,7 +762,7 @@ end
--- Iterate the DATABASE and call an iterator function for each **alive** GROUP, providing the GROUP and optional parameters.
-- @param #DATABASE self
--- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the database. The function needs to accept a GROUP parameter.
+-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a GROUP parameter.
-- @return #DATABASE self
function DATABASE:ForEachGroup( IteratorFunction, ... )
self:F2( arg )
@@ -739,7 +775,7 @@ end
--- Iterate the DATABASE and call an iterator function for each **ALIVE** player, providing the player name and optional parameters.
-- @param #DATABASE self
--- @param #function IteratorFunction The function that will be called when there is an player in the database. The function needs to accept the player name.
+-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept the player name.
-- @return #DATABASE self
function DATABASE:ForEachPlayer( IteratorFunction, ... )
self:F2( arg )
@@ -752,7 +788,7 @@ end
--- Iterate the DATABASE and call an iterator function for each player who has joined the mission, providing the Unit of the player and optional parameters.
-- @param #DATABASE self
--- @param #function IteratorFunction The function that will be called when there is was a player in the database. The function needs to accept a UNIT parameter.
+-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a UNIT parameter.
-- @return #DATABASE self
function DATABASE:ForEachPlayerJoined( IteratorFunction, ... )
self:F2( arg )
@@ -764,7 +800,7 @@ end
--- Iterate the DATABASE and call an iterator function for each CLIENT, providing the CLIENT to the function and optional parameters.
-- @param #DATABASE self
--- @param #function IteratorFunction The function that will be called when there is an alive player in the database. The function needs to accept a CLIENT parameter.
+-- @param #function IteratorFunction The function that will be called object in the database. The function needs to accept a CLIENT parameter.
-- @return #DATABASE self
function DATABASE:ForEachClient( IteratorFunction, ... )
self:F2( arg )
@@ -774,6 +810,43 @@ function DATABASE:ForEachClient( IteratorFunction, ... )
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, ... )
+ self:F2( arg )
+
+ self:ForEach( IteratorFunction, arg, self.CARGOS )
+
+ return self
+end
+
+
+--- Handles the OnEventNewCargo event.
+-- @param #DATABASE self
+-- @param Core.Event#EVENTDATA EventData
+function DATABASE:OnEventNewCargo( EventData )
+ self:F2( { EventData } )
+
+ if EventData.Cargo then
+ self:AddCargo( EventData.Cargo )
+ end
+end
+
+
+--- Handles the OnEventDeleteCargo.
+-- @param #DATABASE self
+-- @param Core.Event#EVENTDATA EventData
+function DATABASE:OnEventDeleteCargo( EventData )
+ self:F2( { EventData } )
+
+ if EventData.Cargo then
+ self:DeleteCargo( EventData.Cargo.Name )
+ end
+end
+
+
--- @param #DATABASE self
function DATABASE:_RegisterTemplates()
self:F2()
diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua
index c03eac9a9..9891aa5fd 100644
--- a/Moose Development/Moose/Core/Event.lua
+++ b/Moose Development/Moose/Core/Event.lua
@@ -197,6 +197,9 @@ EVENT = {
ClassID = 0,
}
+world.event.S_EVENT_NEW_CARGO = world.event.S_EVENT_MAX + 1000
+world.event.S_EVENT_DELETE_CARGO = world.event.S_EVENT_MAX + 1001
+
--- The different types of events supported by MOOSE.
-- Use this structure to subscribe to events using the @{Base#BASE.HandleEvent}() method.
-- @type EVENTS
@@ -224,13 +227,15 @@ EVENTS = {
PlayerComment = world.event.S_EVENT_PLAYER_COMMENT,
ShootingStart = world.event.S_EVENT_SHOOTING_START,
ShootingEnd = world.event.S_EVENT_SHOOTING_END,
+ NewCargo = world.event.S_EVENT_NEW_CARGO,
+ DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
}
--- The Event structure
-- Note that at the beginning of each field description, there is an indication which field will be populated depending on the object type involved in the Event:
--
-- * A (Object.Category.)UNIT : A UNIT object type is involved in the Event.
--- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.µ
+-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.µ
--
-- @type EVENTDATA
-- @field #number id The identifier of the event.
@@ -271,6 +276,7 @@ EVENTS = {
-- @field WeaponTgtDCSUnit
+
local _EVENTMETA = {
[world.event.S_EVENT_SHOT] = {
Order = 1,
@@ -410,6 +416,16 @@ local _EVENTMETA = {
Event = "OnEventShootingEnd",
Text = "S_EVENT_SHOOTING_END"
},
+ [EVENTS.NewCargo] = {
+ Order = 1,
+ Event = "OnEventNewCargo",
+ Text = "S_EVENT_NEW_CARGO"
+ },
+ [EVENTS.DeleteCargo] = {
+ Order = 1,
+ Event = "OnEventDeleteCargo",
+ Text = "S_EVENT_DELETE_CARGO"
+ },
}
@@ -682,6 +698,39 @@ do -- OnEngineShutDown
end
+do -- Event Creation
+
+ --- 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
+
+ --- 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
+
+end
--- @param #EVENT self
-- @param #EVENTDATA Event
@@ -805,6 +854,11 @@ function EVENT:onEvent( Event )
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
end
+ if Event.cargo then
+ Event.Cargo = Event.cargo
+ Event.CargoName = Event.cargo.Name
+ end
+
local PriorityOrder = EventMeta.Order
local PriorityBegin = PriorityOrder == -1 and 5 or 1
local PriorityEnd = PriorityOrder == -1 and 1 or 5
diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua
index 2d206d453..d6e7c9caa 100644
--- a/Moose Development/Moose/Core/Set.lua
+++ b/Moose Development/Moose/Core/Set.lua
@@ -2391,3 +2391,346 @@ function SET_AIRBASE:IsIncludeObject( MAirbase )
self:T2( MAirbaseInclude )
return MAirbaseInclude
end
+
+--- @type SET_CARGO
+-- @extends Core.Set#SET_BASE
+
+--- # SET_CARGO class, extends @{Set#SET_BASE}
+--
+-- Mission designers can use the @{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 @{Set#SET_CARGO.AddCargosByName} and @{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 prefix string(s).
+-- * @{#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 self
+-- @usage
+-- -- Define a new SET_CARGO Object. The DatabaseSet will contain a reference to all Cargos.
+-- DatabaseSet = SET_CARGO:New()
+function SET_CARGO:New()
+ -- Inherits from BASE
+ local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.CARGOS ) )
+
+ self:HandleEvent( EVENTS.NewCargo )
+ self:HandleEvent( EVENTS.DeleteCargo )
+
+ 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 self
+function SET_CARGO:AddCargosByName( AddCargoNames )
+
+ 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 Wrapper.Cargo#CARGO RemoveCargoNames A single name or an array of CARGO names.
+-- @return self
+function SET_CARGO:RemoveCargosByName( RemoveCargoNames )
+
+ 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 Wrapper.Cargo#CARGO The found Cargo.
+function SET_CARGO:FindCargo( CargoName )
+
+ 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
+function SET_CARGO:FilterCoalitions( Coalitions )
+ if not self.Filter.Coalitions then
+ self.Filter.Coalitions = {}
+ end
+ if type( Coalitions ) ~= "table" then
+ Coalitions = { Coalitions }
+ end
+ for CoalitionID, Coalition in pairs( Coalitions ) do
+ self.Filter.Coalitions[Coalition] = Coalition
+ end
+ return self
+end
+
+--- 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 )
+ 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 )
+ 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 of defined cargo prefixes.
+-- All the cargos starting with the given prefixes will be included within the set.
+-- @param #SET_CARGO self
+-- @param #string Prefixes The prefix of which the cargo name starts with.
+-- @return #SET_CARGO self
+function SET_CARGO:FilterPrefixes( Prefixes )
+ 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()
+
+ if _DATABASE then
+ self:_FilterStart()
+ end
+
+ 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 )
+ 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 )
+ self:F3( { Event } )
+
+ return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
+end
+
+--- Iterate the SET_CARGO and call an interator 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, ... )
+ self:F2( arg )
+
+ self:ForEach( IteratorFunction, arg, self.Set )
+
+ return self
+end
+
+--- Iterate the SET_CARGO while identifying the nearest @{Cargo#CARGO} from a @{Point#POINT_VEC2}.
+-- @param #SET_CARGO self
+-- @param Core.Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest @{Cargo#CARGO}.
+-- @return Wrapper.Cargo#CARGO The closest @{Cargo#CARGO}.
+function SET_CARGO:FindNearestCargoFromPointVec2( PointVec2 )
+ self:F2( PointVec2 )
+
+ local NearestCargo = self:FindNearestObjectFromPointVec2( PointVec2 )
+ return NearestCargo
+end
+
+
+
+---
+-- @param #SET_CARGO self
+-- @param AI.AI_Cargo#AI_CARGO MCargo
+-- @return #SET_CARGO self
+function SET_CARGO:IsIncludeObject( MCargo )
+ 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:T3( { "Coalition:", CargoCoalitionID, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
+ if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == CargoCoalitionID then
+ MCargoCoalition = true
+ end
+ end
+ self:T( { "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:T3( { "Type:", MCargo:GetType(), TypeName } )
+ if TypeName == MCargo:GetType() then
+ MCargoType = true
+ end
+ end
+ self:T( { "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:T3( { "Prefix:", string.find( MCargo.Name, CargoPrefix, 1 ), CargoPrefix } )
+ if string.find( MCargo.Name, CargoPrefix, 1 ) then
+ MCargoPrefix = true
+ end
+ end
+ self:T( { "Evaluated Prefix", MCargoPrefix } )
+ MCargoInclude = MCargoInclude and MCargoPrefix
+ end
+ end
+
+ self:T2( 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 )
+
+ 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 )
+ self:F3( { EventData } )
+
+ if EventData.Cargo then
+ local Cargo = _DATABASE:FindCargo( EventData.Cargo.Name )
+ if Cargo and Cargo.Name then
+ self:Remove( Cargo.Name )
+ end
+ end
+end
+
diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua
index 8456729a8..d7c00ae39 100644
--- a/Moose Development/Moose/Core/Zone.lua
+++ b/Moose Development/Moose/Core/Zone.lua
@@ -73,41 +73,41 @@
-- @extends Core.Base#BASE
---- # 1) ZONE_BASE class, extends @{Base#BASE}
+--- # ZONE_BASE class, extends @{Base#BASE}
--
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
--
--- ## 1.1) Each zone has a name:
+-- ## Each zone has a name:
--
-- * @{#ZONE_BASE.GetName}(): Returns the name of the zone.
--
--- ## 1.2) Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}:
+-- ## Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}:
--
-- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a Vec2 is within the zone.
-- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a Vec3 is within the zone.
--
--- ## 1.3) A zone has a probability factor that can be set to randomize a selection between zones:
+-- ## A zone has a probability factor that can be set to randomize a selection between zones:
--
-- * @{#ZONE_BASE.SetRandomizeProbability}(): Set the randomization probability of a zone to be selected, taking a value between 0 and 1 ( 0 = 0%, 1 = 100% )
-- * @{#ZONE_BASE.GetRandomizeProbability}(): Get the randomization probability of a zone to be selected, passing a value between 0 and 1 ( 0 = 0%, 1 = 100% )
-- * @{#ZONE_BASE.GetZoneMaybe}(): Get the zone taking into account the randomization probability. nil is returned if this zone is not a candidate.
--
--- ## 1.4) A zone manages Vectors:
+-- ## A zone manages Vectors:
--
-- * @{#ZONE_BASE.GetVec2}(): Returns the @{DCSTypes#Vec2} coordinate of the zone.
-- * @{#ZONE_BASE.GetRandomVec2}(): Define a random @{DCSTypes#Vec2} within the zone.
--
--- ## 1.5) A zone has a bounding square:
+-- ## A zone has a bounding square:
--
-- * @{#ZONE_BASE.GetBoundingSquare}(): Get the outer most bounding square of the zone.
--
--- ## 1.6) A zone can be marked:
+-- ## A zone can be marked:
--
-- * @{#ZONE_BASE.SmokeZone}(): Smokes the zone boundaries in a color.
-- * @{#ZONE_BASE.FlareZone}(): Flares the zone boundaries in a color.
--
--- ===
-- @field #ZONE_BASE ZONE_BASE
+--
ZONE_BASE = {
ClassName = "ZONE_BASE",
ZoneName = "",
@@ -144,20 +144,21 @@ function ZONE_BASE:GetName()
return self.ZoneName
end
---- Returns if a location is within the zone.
+
+--- Returns if a Vec2 is within the zone.
-- @param #ZONE_BASE self
--- @param Dcs.DCSTypes#Vec2 Vec2 The location to test.
--- @return #boolean true if the location is within the zone.
+-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 to test.
+-- @return #boolean true if the Vec2 is within the zone.
function ZONE_BASE:IsVec2InZone( Vec2 )
self:F2( Vec2 )
return false
end
---- Returns if a point is within the zone.
+--- Returns if a Vec3 is within the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Vec3 Vec3 The point to test.
--- @return #boolean true if the point is within the zone.
+-- @return #boolean true if the Vec3 is within the zone.
function ZONE_BASE:IsVec3InZone( Vec3 )
self:F2( Vec3 )
@@ -166,6 +167,31 @@ function ZONE_BASE:IsVec3InZone( Vec3 )
return InZone
end
+--- Returns if a PointVec2 is within the zone.
+-- @param #ZONE_BASE self
+-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to test.
+-- @return #boolean true if the PointVec2 is within the zone.
+function ZONE_BASE:IsPointVec2InZone( PointVec2 )
+ self:F2( PointVec2 )
+
+ local InZone = self:IsVec2InZone( PointVec2:GetVec2() )
+
+ return InZone
+end
+
+--- Returns if a PointVec3 is within the zone.
+-- @param #ZONE_BASE self
+-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 to test.
+-- @return #boolean true if the PointVec3 is within the zone.
+function ZONE_BASE:IsPointVec3InZone( PointVec3 )
+ self:F2( PointVec3 )
+
+ local InZone = self:IsPointVec2InZone( PointVec3 )
+
+ return InZone
+end
+
+
--- Returns the @{DCSTypes#Vec2} coordinate of the zone.
-- @param #ZONE_BASE self
-- @return #nil.
@@ -310,29 +336,29 @@ end
-- @type ZONE_RADIUS
-- @field Dcs.DCSTypes#Vec2 Vec2 The current location of the zone.
-- @field Dcs.DCSTypes#Distance Radius The radius of the zone.
--- @extends Core.Zone#ZONE_BASE
+-- @extends #ZONE_BASE
---- # 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE}
+--- # ZONE_RADIUS class, extends @{Zone#ZONE_BASE}
--
-- The ZONE_RADIUS class defined by a zone name, a location and a radius.
-- This class implements the inherited functions from Core.Zone#ZONE_BASE taking into account the own zone format and properties.
--
--- ## 2.1) @{Zone#ZONE_RADIUS} constructor
+-- ## ZONE_RADIUS constructor
--
-- * @{#ZONE_RADIUS.New}(): Constructor.
--
--- ## 2.2) Manage the radius of the zone
+-- ## Manage the radius of the zone
--
-- * @{#ZONE_RADIUS.SetRadius}(): Sets the radius of the zone.
-- * @{#ZONE_RADIUS.GetRadius}(): Returns the radius of the zone.
--
--- ## 2.3) Manage the location of the zone
+-- ## Manage the location of the zone
--
-- * @{#ZONE_RADIUS.SetVec2}(): Sets the @{DCSTypes#Vec2} of the zone.
-- * @{#ZONE_RADIUS.GetVec2}(): Returns the @{DCSTypes#Vec2} of the zone.
-- * @{#ZONE_RADIUS.GetVec3}(): Returns the @{DCSTypes#Vec3} of the zone, taking an additional height parameter.
--
--- ## 2.4) Zone point randomization
+-- ## Zone point randomization
--
-- Various functions exist to find random points within the zone.
--
@@ -340,8 +366,6 @@ end
-- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Point#POINT_VEC2} object representing a random 2D point in the zone.
-- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight.
--
--- ===
---
-- @field #ZONE_RADIUS ZONE_RADIUS
--
ZONE_RADIUS = {
@@ -616,16 +640,14 @@ end
--- @type ZONE
--- @extends Core.Zone#ZONE_RADIUS
+-- @extends #ZONE_RADIUS
---- # 3) ZONE class, extends @{Zone#ZONE_RADIUS}
+--- # ZONE class, extends @{Zone#ZONE_RADIUS}
--
-- The ZONE class, defined by the zone name as defined within the Mission Editor.
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
--
--- ===
---
-- @field #ZONE ZONE
--
ZONE = {
@@ -655,18 +677,15 @@ function ZONE:New( ZoneName )
end
---- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius.
--- @type ZONE_UNIT
+--- @type ZONE_UNIT
-- @field Wrapper.Unit#UNIT ZoneUNIT
-- @extends Core.Zone#ZONE_RADIUS
---- # 4) #ZONE_UNIT class, extends @{Zone#ZONE_RADIUS}
+--- # ZONE_UNIT class, extends @{Zone#ZONE_RADIUS}
--
-- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius.
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
--
--- ===
---
-- @field #ZONE_UNIT ZONE_UNIT
--
ZONE_UNIT = {
@@ -751,16 +770,14 @@ end
--- @type ZONE_GROUP
-- @field Wrapper.Group#GROUP ZoneGROUP
--- @extends Core.Zone#ZONE_RADIUS
+-- @extends #ZONE_RADIUS
---- # 5) #ZONE_GROUP class, extends @{Zone#ZONE_RADIUS}
+--- # ZONE_GROUP class, extends @{Zone#ZONE_RADIUS}
--
-- The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius. The current leader of the group defines the center of the zone.
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
--
--- ===
---
-- @field #ZONE_GROUP ZONE_GROUP
--
ZONE_GROUP = {
@@ -818,16 +835,16 @@ end
--- @type ZONE_POLYGON_BASE
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}.
--- @extends Core.Zone#ZONE_BASE
+-- @extends #ZONE_BASE
---- # 6) ZONE_POLYGON_BASE class, extends @{Zone#ZONE_BASE}
+--- # ZONE_POLYGON_BASE class, extends @{Zone#ZONE_BASE}
--
-- The ZONE_POLYGON_BASE class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
--
--- ## 6.1) Zone point randomization
+-- ## Zone point randomization
--
-- Various functions exist to find random points within the zone.
--
@@ -835,8 +852,6 @@ end
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Point#POINT_VEC2} object representing a random 2D point within the zone.
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
--
--- ===
---
-- @field #ZONE_POLYGON_BASE ZONE_POLYGON_BASE
--
ZONE_POLYGON_BASE = {
@@ -870,6 +885,17 @@ function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
return self
end
+--- Returns the center location of the polygon.
+-- @param #ZONE_GROUP self
+-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Group} location.
+function ZONE_POLYGON_BASE:GetVec2()
+ self:F( self.ZoneName )
+
+ local Bounds = self:GetBoundingSquare()
+
+ return { x = ( Bounds.x2 + Bounds.x1 ) / 2, y = ( Bounds.y2 + Bounds.y1 ) / 2 }
+end
+
--- Flush polygon coordinates as a table in DCS.log.
-- @param #ZONE_POLYGON_BASE self
-- @return #ZONE_POLYGON_BASE self
@@ -1073,16 +1099,14 @@ end
--- @type ZONE_POLYGON
--- @extends Core.Zone#ZONE_POLYGON_BASE
+-- @extends #ZONE_POLYGON_BASE
---- # 7) ZONE_POLYGON class, extends @{Zone#ZONE_POLYGON_BASE}
+--- # ZONE_POLYGON class, extends @{Zone#ZONE_POLYGON_BASE}
--
-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
--
--- ===
---
-- @field #ZONE_POLYGON ZONE_POLYGON
--
ZONE_POLYGON = {
diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua
index cca24bef8..5195ff310 100644
--- a/Moose Development/Moose/Moose.lua
+++ b/Moose Development/Moose/Moose.lua
@@ -1,3 +1,70 @@
+--- The main include file for the MOOSE system.
+-- Test of permissions
+
+--- Core Routines
+Include.File( "Utilities/Routines" )
+Include.File( "Utilities/Utils" )
+
+--- Core Classes
+Include.File( "Core/Base" )
+Include.File( "Core/Scheduler" )
+Include.File( "Core/ScheduleDispatcher")
+Include.File( "Core/Event" )
+Include.File( "Core/Menu" )
+Include.File( "Core/Zone" )
+Include.File( "Core/Database" )
+Include.File( "Core/Set" )
+Include.File( "Core/Point" )
+Include.File( "Core/Message" )
+Include.File( "Core/Fsm" )
+Include.File( "Core/Radio" )
+
+--- Wrapper Classes
+Include.File( "Wrapper/Object" )
+Include.File( "Wrapper/Identifiable" )
+Include.File( "Wrapper/Positionable" )
+Include.File( "Wrapper/Controllable" )
+Include.File( "Wrapper/Group" )
+Include.File( "Wrapper/Unit" )
+Include.File( "Wrapper/Client" )
+Include.File( "Wrapper/Static" )
+Include.File( "Wrapper/Airbase" )
+Include.File( "Wrapper/Scenery" )
+
+--- Functional Classes
+Include.File( "Functional/Scoring" )
+Include.File( "Functional/CleanUp" )
+Include.File( "Functional/Spawn" )
+Include.File( "Functional/Movement" )
+Include.File( "Functional/Sead" )
+Include.File( "Functional/Escort" )
+Include.File( "Functional/MissileTrainer" )
+Include.File( "Functional/AirbasePolice" )
+Include.File( "Functional/Detection" )
+
+--- AI Classes
+Include.File( "AI/AI_Balancer" )
+Include.File( "AI/AI_Patrol" )
+Include.File( "AI/AI_Cap" )
+Include.File( "AI/AI_Cas" )
+Include.File( "AI/AI_Cargo" )
+
+--- Actions
+Include.File( "Actions/Act_Assign" )
+Include.File( "Actions/Act_Route" )
+Include.File( "Actions/Act_Account" )
+Include.File( "Actions/Act_Assist" )
+
+--- Task Handling Classes
+Include.File( "Tasking/CommandCenter" )
+Include.File( "Tasking/Mission" )
+Include.File( "Tasking/Task" )
+Include.File( "Tasking/DetectionManager" )
+Include.File( "Tasking/Task_A2G_Dispatcher")
+Include.File( "Tasking/Task_A2G" )
+Include.File( "Tasking/Task_CARGO" )
+
+
-- The order of the declarations is important here. Don't touch it.
--- Declare the event dispatcher based on the EVENT class
@@ -7,7 +74,7 @@ _EVENTDISPATCHER = EVENT:New() -- Core.Event#EVENT
_SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.Timer#SCHEDULEDISPATCHER
--- Declare the main database object, which is used internally by the MOOSE classes.
-_DATABASE = DATABASE:New() -- Database#DATABASE
+_DATABASE = DATABASE:New() -- Core.Database#DATABASE
diff --git a/Moose Development/Moose/Tasking/Task_CARGO.lua b/Moose Development/Moose/Tasking/Task_CARGO.lua
new file mode 100644
index 000000000..44d3523d9
--- /dev/null
+++ b/Moose Development/Moose/Tasking/Task_CARGO.lua
@@ -0,0 +1,575 @@
+--- **Tasking (Release 2.1)** -- The TASK_CARGO models tasks for players to transport @{Cargo}.
+--
+-- 
+--
+-- ====
+--
+-- Cargo are units or cargo objects within DCS world that allow to be transported or sling loaded by other units.
+-- The CARGO class, as part of the moose core, is able to Board, Load, UnBoard and UnLoad from Carrier units.
+-- This collection of classes in this module define tasks for human players to handle cargo objects.
+-- Cargo can be transported, picked-up, deployed and sling-loaded from and to other places.
+--
+-- The following classes are important to consider:
+--
+-- * @{#TASK_CARGO_TRANSPORT}: Defines a task for a human player to transport a set of cargo between various zones.
+--
+-- ==
+--
+-- # **API CHANGE HISTORY**
+--
+-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
+--
+-- * **Added** parts are expressed in bold type face.
+-- * _Removed_ parts are expressed in italic type face.
+--
+-- Hereby the change log:
+--
+-- 2017-03-09: Revised version.
+--
+-- ===
+--
+-- # **AUTHORS and CONTRIBUTIONS**
+--
+-- ### Contributions:
+--
+-- ### Authors:
+--
+-- * **FlightControl**: Concept, Design & Programming.
+--
+-- @module Task_CARGO
+
+do -- TASK_CARGO
+
+ --- @type TASK_CARGO
+ -- @extends Tasking.Task#TASK
+
+ ---
+ -- # TASK_CARGO class, extends @{Task#TASK}
+ --
+ -- The TASK_CARGO class defines @{Cargo} transport tasks,
+ -- based on the tasking capabilities defined in @{Task#TASK}.
+ -- The TASK_CARGO is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
+ --
+ -- * **None**: Start of the process.
+ -- * **Planned**: The cargo task is planned.
+ -- * **Assigned**: The cargo task is assigned to a @{Group#GROUP}.
+ -- * **Success**: The cargo task is successfully completed.
+ -- * **Failed**: The cargo task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
+ --
+ -- # 1.1) Set the scoring of achievements in a cargo task.
+ --
+ -- Scoring or penalties can be given in the following circumstances:
+ --
+ -- ===
+ --
+ -- @field #TASK_CARGO TASK_CARGO
+ --
+ TASK_CARGO = {
+ ClassName = "TASK_CARGO",
+ }
+
+ --- Instantiates a new TASK_CARGO.
+ -- @param #TASK_CARGO self
+ -- @param Tasking.Mission#MISSION Mission
+ -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
+ -- @param #string TaskName The name of the Task.
+ -- @param Core.Set#SET_CARGO SetCargo The scope of the cargo to be transported.
+ -- @param #string TaskType The type of Cargo task.
+ -- @return #TASK_CARGO self
+ function TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, TaskType )
+ local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) -- #TASK_CARGO
+ self:F( {Mission, SetGroup, TaskName, SetCargo, TaskType})
+
+ self.SetCargo = SetCargo
+ self.TaskType = TaskType
+
+ self.DeployZones = {} -- setmetatable( {}, { __mode = "v" } ) -- weak table on value
+
+ Mission:AddTask( self )
+
+ local Fsm = self:GetUnitProcess()
+
+
+ Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "SelectAction", Rejected = "Reject" } )
+
+ Fsm:AddTransition( "*", "SelectAction", "WaitingForCommand" )
+
+ Fsm:AddTransition( "WaitingForCommand", "RouteToPickup", "RoutingToPickup" )
+ Fsm:AddProcess ( "RoutingToPickup", "RouteToPickupPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtPickup" } )
+ Fsm:AddTransition( "Arrived", "ArriveAtPickup", "ArrivedAtPickup" )
+
+ Fsm:AddTransition( "WaitingForCommand", "RouteToDeploy", "RoutingToDeploy" )
+ Fsm:AddProcess ( "RoutingToDeploy", "RouteToDeployZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtDeploy" } )
+ Fsm:AddTransition( "Arrived", "ArriveAtDeploy", "ArrivedAtDeploy" )
+
+ Fsm:AddTransition( { "ArrivedAtPickup", "ArrivedAtDeploy" }, "Land", "Landing" )
+ Fsm:AddTransition( "Landing", "Landed", "Landed" )
+
+ Fsm:AddTransition( "WaitingForCommand", "PrepareBoarding", "AwaitBoarding" )
+ Fsm:AddTransition( "AwaitBoarding", "Board", "Boarding" )
+ Fsm:AddTransition( "Boarding", "Boarded", "Boarded" )
+
+ Fsm:AddTransition( "WaitingForCommand", "PrepareUnBoarding", "AwaitUnBoarding" )
+ Fsm:AddTransition( "AwaitUnBoarding", "UnBoard", "UnBoarding" )
+ Fsm:AddTransition( "UnBoarding", "UnBoarded", "UnBoarded" )
+
+
+ Fsm:AddTransition( "Deployed", "Success", "Success" )
+ Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
+ Fsm:AddTransition( "Failed", "Fail", "Failed" )
+
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnEnterWaitingForCommand( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ TaskUnit.Menu = MENU_GROUP:New( TaskUnit:GetGroup(), Task:GetName() .. " @ " .. TaskUnit:GetName() )
+
+ Task.SetCargo:ForEachCargo(
+
+ --- @param AI.AI_Cargo#AI_CARGO Cargo
+ function( Cargo )
+ if Cargo:IsUnLoaded() then
+ if Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
+ MENU_GROUP_COMMAND:New(
+ TaskUnit:GetGroup(),
+ "Pickup cargo " .. Cargo.Name,
+ TaskUnit.Menu,
+ self.MenuBoardCargo,
+ self,
+ Cargo
+ )
+ else
+ MENU_GROUP_COMMAND:New(
+ TaskUnit:GetGroup(),
+ "Route to cargo " .. Cargo.Name,
+ TaskUnit.Menu,
+ self.MenuRouteToPickup,
+ self,
+ Cargo
+ )
+ end
+ end
+
+ if Cargo:IsLoaded() then
+ for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do
+ if Cargo:IsInZone( DeployZone ) then
+ MENU_GROUP_COMMAND:New(
+ TaskUnit:GetGroup(),
+ "Deploy cargo " .. Cargo.Name,
+ TaskUnit.Menu,
+ self.MenuUnBoardCargo,
+ self,
+ Cargo
+ )
+ else
+ MENU_GROUP_COMMAND:New(
+ TaskUnit:GetGroup(),
+ "Route to deploy zone " .. DeployZoneName,
+ TaskUnit.Menu,
+ self.MenuRouteToDeploy,
+ self,
+ DeployZone
+ )
+ end
+ end
+ end
+
+ end
+ )
+ end
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnLeaveWaitingForCommand( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ TaskUnit.Menu:Remove()
+ end
+
+ function Fsm:MenuBoardCargo( Cargo )
+ self:__PrepareBoarding( 1.0, Cargo )
+ end
+
+ function Fsm:MenuUnBoardCargo( Cargo )
+ self:__PrepareUnBoarding( 1.0, Cargo )
+ end
+
+ function Fsm:MenuRouteToPickup( Cargo )
+ self:__RouteToPickup( 1.0, Cargo )
+ end
+
+ function Fsm:MenuRouteToDeploy( DeployZone )
+ self:__RouteToDeploy( 1.0, DeployZone )
+ end
+
+ --- Route to Cargo
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:onafterRouteToPickup( TaskUnit, Task, From, Event, To, Cargo )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+
+ self.Cargo = Cargo
+ Task:SetCargoPickup( self.Cargo, TaskUnit )
+ self:__RouteToPickupPoint( 0.1 )
+ end
+
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:onafterArriveAtPickup( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ if TaskUnit:IsAir() then
+ self:__Land( -0.1 )
+ else
+ self:__SelectAction( -0.1 )
+ end
+ end
+
+
+ --- Route to DeployZone
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ function Fsm:onafterRouteToDeploy( TaskUnit, Task, From, Event, To, DeployZone )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+
+ self.DeployZone = DeployZone
+ Task:SetDeployZone( self.DeployZone, TaskUnit )
+ self:__RouteToDeployZone( 0.1 )
+ end
+
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:onafterArriveAtDeploy( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ if TaskUnit:IsAir() then
+ self:__Land( -0.1 )
+ else
+ self:__SelectAction( -0.1 )
+ end
+ end
+
+
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnAfterLand( TaskUnit, Task, From, Event, To )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
+ if TaskUnit:InAir() then
+ Task:GetMission():GetCommandCenter():MessageToGroup( "Land", TaskUnit:GetGroup(), "Land" )
+ self:__Land( -10 )
+ else
+ Task:GetMission():GetCommandCenter():MessageToGroup( "Landed ...", TaskUnit:GetGroup(), "Land" )
+ self:__Landed( -0.1 )
+ end
+ else
+ self:__ArriveAtCargo( -0.1 )
+ end
+ end
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnAfterLanded( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
+ if TaskUnit:InAir() then
+ self:__Land( -0.1 )
+ else
+ Task:GetMission():GetCommandCenter():MessageToGroup( "Preparing to board in 10 seconds ...", TaskUnit:GetGroup(), "Boarding" )
+ self:__PrepareBoarding( -10 )
+ end
+ else
+ self:__ArriveAtCargo( -0.1 )
+ end
+ end
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnAfterPrepareBoarding( TaskUnit, Task, From, Event, To, Cargo )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ self.Cargo = Cargo
+ if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
+ if TaskUnit:InAir() then
+ self:__Land( -0.1 )
+ else
+ self:__Board( -0.1 )
+ end
+ else
+ self:__ArriveAtCargo( -0.1 )
+ end
+ end
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnAfterBoard( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ function self.Cargo:OnEnterLoaded( From, Event, To, TaskUnit, TaskProcess )
+
+ self:E({From, Event, To, TaskUnit, TaskProcess })
+
+ TaskProcess:__Boarded( 0.1 )
+
+ end
+
+
+ if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
+ if TaskUnit:InAir() then
+ self:__Land( -0.1 )
+ else
+ Task:GetMission():GetCommandCenter():MessageToGroup( "Boarding ...", TaskUnit:GetGroup(), "Boarding" )
+ self.Cargo:Board( TaskUnit, self )
+ end
+ else
+ self:__ArriveAtCargo( -0.1 )
+ end
+ end
+
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnAfterBoarded( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ Task:GetMission():GetCommandCenter():MessageToGroup( "Boarded ...", TaskUnit:GetGroup(), "Boarding" )
+ self:__SelectAction( 1 )
+ end
+
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnAfterPrepareUnBoarding( TaskUnit, Task, From, Event, To, Cargo, DeployZone )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ self.DeployZone = DeployZone
+ self.Cargo:__UnBoard( -0.1, DeployZone )
+ end
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnAfterUnBoard( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ function self.Cargo:OnEnterUnLoaded( From, Event, To, TaskUnit, TaskProcess )
+
+ self:E({From, Event, To, TaskUnit, TaskProcess })
+
+ TaskProcess:__UnBoarded( 0.1 )
+
+ end
+
+ Task:GetMission():GetCommandCenter():MessageToGroup( "UnBoarding ...", TaskUnit:GetGroup(), "UnBoarding" )
+ self.Cargo:__UnBoard( -0.1, self.DeployZone )
+ end
+
+
+ ---
+ -- @param #FSM_PROCESS self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @param Tasking.Task_CARGO#TASK_CARGO Task
+ function Fsm:OnAfterUnBoarded( TaskUnit, Task )
+ self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
+
+ Task:GetMission():GetCommandCenter():MessageToGroup( "UnBoarded ...", TaskUnit:GetGroup(), "UnBoarding" )
+ self:__SelectAction( 1 )
+ end
+
+
+ return self
+
+ end
+
+ --- @param #TASK_CARGO self
+ function TASK_CARGO:GetPlannedMenuText()
+ return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
+ end
+
+
+ --- @param #TASK_CARGO self
+ -- @param AI.AI_Cargo#AI_CARGO Cargo The cargo.
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return #TASK_CARGO
+ function TASK_CARGO:SetCargoPickup( Cargo, TaskUnit )
+
+ self:F({Cargo, TaskUnit})
+ local ProcessUnit = self:GetUnitProcess( TaskUnit )
+
+ local ActRouteCargo = ProcessUnit:GetProcess( "RoutingToPickup", "RouteToPickupPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
+ ActRouteCargo:SetPointVec2( Cargo:GetPointVec2() )
+ ActRouteCargo:SetRange( Cargo:GetBoardingRange() )
+ return self
+ end
+
+
+ --- @param #TASK_CARGO self
+ -- @param Core.Zone#ZONE DeployZone
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return #TASK_CARGO
+ function TASK_CARGO:SetDeployZone( DeployZone, TaskUnit )
+
+ local ProcessUnit = self:GetUnitProcess( TaskUnit )
+
+ local ActRouteDeployZone = ProcessUnit:GetProcess( "RoutingToDeploy", "RouteToDeployZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
+ ActRouteDeployZone:SetZone( DeployZone )
+ return self
+ end
+
+
+ --- @param #TASK_CARGO self
+ -- @param Core.Zone#ZONE DeployZone
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return #TASK_CARGO
+ function TASK_CARGO:AddDeployZone( DeployZone, TaskUnit )
+
+ self.DeployZones[DeployZone:GetName()] = DeployZone
+
+ return self
+ end
+
+ --- @param #TASK_CARGO self
+ -- @param Core.Zone#ZONE DeployZone
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return #TASK_CARGO
+ function TASK_CARGO:RemoveDeployZone( DeployZone, TaskUnit )
+
+ self.DeployZones[DeployZone:GetName()] = nil
+
+ return self
+ end
+
+ --- @param #TASK_CARGO self
+ -- @param @list DeployZones
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return #TASK_CARGO
+ function TASK_CARGO:SetDeployZones( DeployZones, TaskUnit )
+
+ for DeployZoneID, DeployZone in pairs( DeployZones ) do
+ self.DeployZones[DeployZone:GetName()] = DeployZone
+ end
+
+ return self
+ end
+
+
+
+ --- @param #TASK_CARGO self
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return Core.Zone#ZONE_BASE The Zone object where the Target is located on the map.
+ function TASK_CARGO:GetTargetZone( TaskUnit )
+
+ local ProcessUnit = self:GetUnitProcess( TaskUnit )
+
+ local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
+ return ActRouteTarget:GetZone()
+ end
+
+ --- Set a score when a target in scope of the A2G attack, has been destroyed .
+ -- @param #TASK_CARGO self
+ -- @param #string Text The text to display to the player, when the target has been destroyed.
+ -- @param #number Score The score in points.
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return #TASK_CARGO
+ function TASK_CARGO:SetScoreOnDestroy( Text, Score, TaskUnit )
+ self:F( { Text, Score, TaskUnit } )
+
+ local ProcessUnit = self:GetUnitProcess( TaskUnit )
+
+ ProcessUnit:AddScoreProcess( "Engaging", "Account", "Account", Text, Score )
+
+ return self
+ end
+
+ --- Set a score when all the targets in scope of the A2G attack, have been destroyed.
+ -- @param #TASK_CARGO self
+ -- @param #string Text The text to display to the player, when all targets hav been destroyed.
+ -- @param #number Score The score in points.
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return #TASK_CARGO
+ function TASK_CARGO:SetScoreOnSuccess( Text, Score, TaskUnit )
+ self:F( { Text, Score, TaskUnit } )
+
+ local ProcessUnit = self:GetUnitProcess( TaskUnit )
+
+ ProcessUnit:AddScore( "Success", Text, Score )
+
+ return self
+ end
+
+ --- Set a penalty when the A2G attack has failed.
+ -- @param #TASK_CARGO self
+ -- @param #string Text The text to display to the player, when the A2G attack has failed.
+ -- @param #number Penalty The penalty in points.
+ -- @param Wrapper.Unit#UNIT TaskUnit
+ -- @return #TASK_CARGO
+ function TASK_CARGO:SetPenaltyOnFailed( Text, Penalty, TaskUnit )
+ self:F( { Text, Score, TaskUnit } )
+
+ local ProcessUnit = self:GetUnitProcess( TaskUnit )
+
+ ProcessUnit:AddScore( "Failed", Text, Penalty )
+
+ return self
+ end
+
+
+end
+
+
+do -- TASK_CARGO_TRANSPORT
+
+ --- The TASK_CARGO_TRANSPORT class
+ -- @type TASK_CARGO_TRANSPORT
+ -- @extends #TASK_CARGO
+ TASK_CARGO_TRANSPORT = {
+ ClassName = "TASK_CARGO_TRANSPORT",
+ }
+
+ --- Instantiates a new TASK_CARGO_TRANSPORT.
+ -- @param #TASK_CARGO_TRANSPORT self
+ -- @param Tasking.Mission#MISSION Mission
+ -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
+ -- @param #string TaskName The name of the Task.
+ -- @param Core.Set#SET_CARGO SetCargo The scope of the cargo to be transported.
+ -- @return #TASK_CARGO_TRANSPORT self
+ function TASK_CARGO_TRANSPORT:New( Mission, SetGroup, TaskName, SetCargo )
+ local self = BASE:Inherit( self, TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, "Transport" ) ) -- #TASK_CARGO_TRANSPORT
+ self:F()
+
+ return self
+ end
+
+end
+
diff --git a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
new file mode 100644
index 000000000..3b2b611ed
--- /dev/null
+++ b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
@@ -0,0 +1,31 @@
+env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
+env.info( 'Moose Generation Timestamp: 20170328_0728' )
+
+local base = _G
+
+Include = {}
+
+Include.File = function( IncludeFile )
+ if not Include.Files[ IncludeFile ] then
+ Include.Files[IncludeFile] = IncludeFile
+ env.info( "Include:" .. IncludeFile .. " from " .. Include.ProgramPath )
+ local f = assert( base.loadfile( Include.ProgramPath .. IncludeFile .. ".lua" ) )
+ if f == nil then
+ error ("Could not load MOOSE file " .. IncludeFile .. ".lua" )
+ else
+ env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.ProgramPath )
+ return f()
+ end
+ end
+end
+
+Include.ProgramPath = "Scripts/Moose/"
+
+env.info( "Include.ProgramPath = " .. Include.ProgramPath)
+
+Include.Files = {}
+
+Include.File( "Moose" )
+
+BASE:TraceOnOff( true )
+env.info( '*** MOOSE INCLUDE END *** ' )
diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua
index 4e7356543..e69de29bb 100644
--- a/Moose Mission Setup/Moose.lua
+++ b/Moose Mission Setup/Moose.lua
@@ -1,75 +0,0 @@
-env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
-env.info( 'Moose Generation Timestamp: 20170412_0926' )
-
-local base = _G
-
-__Moose = {}
-
-__Moose.Include = function( IncludeFile )
- if not __Moose.Includes[ IncludeFile ] then
- __Moose.Includes[IncludeFile] = IncludeFile
- local f = assert( base.loadfile( __Moose.ProgramPath .. IncludeFile ) )
- if f == nil then
- error ("Moose: Could not load Moose file " .. IncludeFile )
- else
- env.info( "Moose: " .. IncludeFile .. " dynamically loaded from " .. __Moose.ProgramPath )
- return f()
- end
- end
-end
-
-__Moose.ProgramPath = "Scripts/Moose/"
-
-__Moose.Includes = {}
-__Moose.Include( 'Utilities/Routines.lua' )
-__Moose.Include( 'Utilities/Utils.lua' )
-__Moose.Include( 'Core/Base.lua' )
-__Moose.Include( 'Core/Scheduler.lua' )
-__Moose.Include( 'Core/ScheduleDispatcher.lua' )
-__Moose.Include( 'Core/Event.lua' )
-__Moose.Include( 'Core/Menu.lua' )
-__Moose.Include( 'Core/Zone.lua' )
-__Moose.Include( 'Core/Database.lua' )
-__Moose.Include( 'Core/Set.lua' )
-__Moose.Include( 'Core/Point.lua' )
-__Moose.Include( 'Core/Message.lua' )
-__Moose.Include( 'Core/Fsm.lua' )
-__Moose.Include( 'Core/Radio.lua' )
-__Moose.Include( 'Core/SpawnStatic.lua' )
-__Moose.Include( 'Wrapper/Object.lua' )
-__Moose.Include( 'Wrapper/Identifiable.lua' )
-__Moose.Include( 'Wrapper/Positionable.lua' )
-__Moose.Include( 'Wrapper/Controllable.lua' )
-__Moose.Include( 'Wrapper/Group.lua' )
-__Moose.Include( 'Wrapper/Unit.lua' )
-__Moose.Include( 'Wrapper/Client.lua' )
-__Moose.Include( 'Wrapper/Static.lua' )
-__Moose.Include( 'Wrapper/Airbase.lua' )
-__Moose.Include( 'Wrapper/Scenery.lua' )
-__Moose.Include( 'Functional/Scoring.lua' )
-__Moose.Include( 'Functional/CleanUp.lua' )
-__Moose.Include( 'Functional/Spawn.lua' )
-__Moose.Include( 'Functional/Movement.lua' )
-__Moose.Include( 'Functional/Sead.lua' )
-__Moose.Include( 'Functional/Escort.lua' )
-__Moose.Include( 'Functional/MissileTrainer.lua' )
-__Moose.Include( 'Functional/AirbasePolice.lua' )
-__Moose.Include( 'Functional/Detection.lua' )
-__Moose.Include( 'AI/AI_Balancer.lua' )
-__Moose.Include( 'AI/AI_Patrol.lua' )
-__Moose.Include( 'AI/AI_Cap.lua' )
-__Moose.Include( 'AI/AI_Cas.lua' )
-__Moose.Include( 'AI/AI_Cargo.lua' )
-__Moose.Include( 'Actions/Act_Assign.lua' )
-__Moose.Include( 'Actions/Act_Route.lua' )
-__Moose.Include( 'Actions/Act_Account.lua' )
-__Moose.Include( 'Actions/Act_Assist.lua' )
-__Moose.Include( 'Tasking/CommandCenter.lua' )
-__Moose.Include( 'Tasking/Mission.lua' )
-__Moose.Include( 'Tasking/Task.lua' )
-__Moose.Include( 'Tasking/DetectionManager.lua' )
-__Moose.Include( 'Tasking/Task_A2G_Dispatcher.lua' )
-__Moose.Include( 'Tasking/Task_A2G.lua' )
-__Moose.Include( 'Moose.lua' )
-BASE:TraceOnOff( true )
-env.info( '*** MOOSE INCLUDE END *** ' )
diff --git a/docs/Documentation/AI_Balancer.html b/docs/Documentation/AI_Balancer.html
index 15193880f..f8b0437fc 100644
--- a/docs/Documentation/AI_Balancer.html
+++ b/docs/Documentation/AI_Balancer.html
@@ -80,6 +80,7 @@
The #AI_CARGO class 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.
-
-
The AICARGO is a state machine: it manages the different events and states of the cargo.
-All derived classes from AICARGO follow the same state machine, expose the same cargo event functions, and provide the same cargo states.
-
-
1.2.1) AI_CARGO Events:
-
-
-
AI_CARGO.Board( ToCarrier ): Boards the cargo to a carrier.
-
AI_CARGO.Load( ToCarrier ): Loads the cargo into a carrier, regardless of its position.
-
AI_CARGO.UnBoard( ToPointVec2 ): UnBoard the cargo from a carrier. This will trigger a movement of the cargo to the option ToPointVec2.
-
AI_CARGO.UnLoad( ToPointVec2 ): UnLoads the cargo from a carrier.
-
AI_CARGO.Dead( Controllable ): The cargo is dead. The cargo process will be ended.
-
-
-
1.2.2) AI_CARGO States:
-
-
-
UnLoaded: The cargo is unloaded from a carrier.
-
Boarding: The cargo is currently boarding (= running) into a carrier.
-
Loaded: The cargo is loaded into a carrier.
-
UnBoarding: The cargo is currently unboarding (=running) from a carrier.
-
Dead: The cargo is dead ...
-
End: The process has come to an end.
-
-
-
1.2.3) AI_CARGO state transition methods:
-
-
State transition functions can be set by the mission designer customizing or improving the behaviour of the state.
-There are 2 moments when state transition methods will be called by the state machine:
-
-
-
Leaving the state.
- The state transition method needs to start with the name OnLeave + the name of the state.
- If the state transition method returns false, then the processing of the state transition will not be done!
- If you want to change the behaviour of the AIControllable at this event, return false,
- but then you'll need to specify your own logic using the AIControllable!
-
Entering the state.
- The state transition method needs to start with the name OnEnter + the name of the state.
- These state transition methods need to provide a return value, which is specified at the function description.
-
-
-
2) #AICARGOUNIT class
-
-
The AICARGOUNIT class 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 AICARGOUNIT objects to and from carriers.
-
-
5) #AICARGOGROUPED class
-
-
The AICARGOGROUPED class defines a cargo that is represented by a group of UNIT objects within the simulator, and can be transported by a carrier.
-Use the event functions as described above to Load, UnLoad, Board, UnBoard the AICARGOUNIT objects to and from carriers.
This module is still under construction, but is described above works already, and will keep working ...
@@ -179,19 +127,25 @@ Use the event functions as described above to Load, UnLoad, Board, UnBoard the A
The AI_CARGO class 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.
+
+
The AI_CARGO is a state machine: it manages the different events and states of the cargo.
+All derived classes from AI_CARGO follow the same state machine, expose the same cargo event functions, and provide the same cargo states.
#AI( ToCarrier ): Loads the cargo into a carrier, regardless of its position.
+
#AI( ToPointVec2 ): UnBoard the cargo from a carrier. This will trigger a movement of the cargo to the option ToPointVec2.
+
#AI( ToPointVec2 ): UnLoads the cargo from a carrier.
+
#AI( Controllable ): The cargo is dead. The cargo process will be ended.
+
+
+
AI_CARGO States:
+
+
+
UnLoaded: The cargo is unloaded from a carrier.
+
Boarding: The cargo is currently boarding (= running) into a carrier.
+
Loaded: The cargo is loaded into a carrier.
+
UnBoarding: The cargo is currently unboarding (=running) from a carrier.
+
Dead: The cargo is dead ...
+
End: The process has come to an end.
+
+
+
AI_CARGO state transition methods:
+
+
State transition functions can be set by the mission designer customizing or improving the behaviour of the state.
+There are 2 moments when state transition methods will be called by the state machine:
+
+
+
Leaving the state.
+ The state transition method needs to start with the name OnLeave + the name of the state.
+ If the state transition method returns false, then the processing of the state transition will not be done!
+ If you want to change the behaviour of the AIControllable at this event, return false,
+ but then you'll need to specify your own logic using the AIControllable!
+
Entering the state.
+ The state transition method needs to start with the name OnEnter + the name of the state.
+ These state transition methods need to provide a return value, which is specified at the function description.
+
@@ -700,6 +732,12 @@ Use the event functions as described above to Load, UnLoad, Board, UnBoard the A
+
AI_CARGO_GROUP class
+
+
The AI_CARGO_GROUP class defines a cargo that is represented by a group of Unit objects within the simulator, and can be transported by a carrier.
+
+
+
Use the event functions as described above to Load, UnLoad, Board, UnBoard the AI_CARGO_GROUP to and from carrier.
@@ -714,6 +752,12 @@ Use the event functions as described above to Load, UnLoad, Board, UnBoard the A
+
AI_CARGO_GROUPED class
+
+
The AI_CARGO_GROUPED class defines a cargo that is represented by a group of UNIT objects within the simulator, and can be transported by a carrier.
+
+
+
Use the event functions as described above to Load, UnLoad, Board, UnBoard the AI_CARGO_UNIT objects to and from carriers.
@@ -756,6 +800,14 @@ Use the event functions as described above to Load, UnLoad, Board, UnBoard the A
#function IteratorFunction :
-The function that will be called when there is an alive player in the database. The function needs to accept a CLIENT parameter.
+The function that will be called object in the database. The function needs to accept a CLIENT parameter.
@@ -1026,7 +1194,7 @@ self
#function IteratorFunction :
-The function that will be called when there is an alive GROUP in the database. The function needs to accept a GROUP parameter.
+The function that will be called for each object in the database. The function needs to accept a GROUP parameter.
@@ -1058,7 +1226,7 @@ self
#function IteratorFunction :
-The function that will be called when there is an player in the database. The function needs to accept the player name.
+The function that will be called for each object in the database. The function needs to accept the player name.
@@ -1090,7 +1258,7 @@ self
#function IteratorFunction :
-The function that will be called when there is was a player in the database. The function needs to accept a UNIT parameter.
+The function that will be called for each object in the database. The function needs to accept a UNIT parameter.
@@ -1122,7 +1290,7 @@ self
#function IteratorFunction :
-The function that will be called when there is an alive UNIT in the database. The function needs to accept a UNIT parameter.
+The function that will be called for each object in the database. The function needs to accept a UNIT parameter.
@@ -1415,6 +1583,48 @@ self
-- Define a new DATABASE Object. This DBObject will contain a reference to all Group and Unit Templates defined within the ME and the DCSRTE.
DBObject = DATABASE:New()
Core - EVENT models DCS event dispatching using a publish-subscribe model.
-
-
-
-
-
-
-
-
1) Event Handling Overview
-
-
-
-
Within a running mission, various DCS events occur. Units are dynamically created, crash, die, shoot stuff, get hit etc.
-This module provides a mechanism to dispatch those events occuring within your running mission, to the different objects orchestrating your mission.
-
-
-
-
Objects can subscribe to different events. The Event dispatcher will publish the received DCS events to the subscribed MOOSE objects, in a specified order.
-In this way, the subscribed MOOSE objects are kept in sync with your evolving running mission.
-
-
1.1) Event Dispatching
-
-
-
-
The _EVENTDISPATCHER object is automatically created within MOOSE,
-and handles the dispatching of DCS Events occurring
-in the simulator to the subscribed objects
-in the correct processing order.
-
-
-
-
There are 5 levels of kind of objects that the _EVENTDISPATCHER services:
-
-
-
_DATABASE object: The core of the MOOSE objects. Any object that is created, deleted or updated, is done in this database.
-
SET_ derived classes: Subsets of the _DATABASE object. These subsets are updated by the _EVENTDISPATCHER as the second priority.
-
UNIT objects: UNIT objects can subscribe to DCS events. Each DCS event will be directly published to teh subscribed UNIT object.
-
GROUP objects: GROUP objects can subscribe to DCS events. Each DCS event will be directly published to the subscribed GROUP object.
-
Any other object: Various other objects can subscribe to DCS events. Each DCS event triggered will be published to each subscribed object.
-
-
-
-
-
For most DCS events, the above order of updating will be followed.
-
-
-
-
But for some DCS events, the publishing order is reversed. This is due to the fact that objects need to be erased instead of added.
-
-
1.2) Event Handling
-
-
-
-
The actual event subscribing and handling is not facilitated through the _EVENTDISPATCHER, but it is done through the BASE class, UNIT class and GROUP class.
-The _EVENTDISPATCHER is a component that is quietly working in the background of MOOSE.
-
-
-
-
The BASE class provides methods to catch DCS Events. These are events that are triggered from within the DCS simulator,
-and handled through lua scripting. MOOSE provides an encapsulation to handle these events more efficiently.
-
-
1.2.1 Subscribe / Unsubscribe to DCS Events
-
-
At first, the mission designer will need to Subscribe to a specific DCS event for the class.
-So, when the DCS event occurs, the class will be notified of that event.
-There are two functions which you use to subscribe to or unsubscribe from an event.
Note that for a UNIT, the event will be handled for that UNIT only!
-Note that for a GROUP, the event will be handled for all the UNITs in that GROUP only!
-
-
For all objects of other classes, the subscribed events will be handled for all UNITs within the Mission!
-So if a UNIT within the mission has the subscribed event for that object,
-then the object event handler will receive the event for that UNIT!
-
-
1.3.2 Event Handling of DCS Events
-
-
Once the class is subscribed to the event, an Event Handling method on the object or class needs to be written that will be called
-when the DCS event occurs. The Event Handling method receives an Event#EVENTDATA structure, which contains a lot of information
-about the event that occurred.
-
-
Find below an example of the prototype how to write an event handling function for two units:
-
-
local Tank1 = UNIT:FindByName( "Tank A" )
- local Tank2 = UNIT:FindByName( "Tank B" )
-
- -- Here we subscribe to the Dead events. So, if one of these tanks dies, the Tank1 or Tank2 objects will be notified.
- Tank1:HandleEvent( EVENTS.Dead )
- Tank2:HandleEvent( EVENTS.Dead )
-
- --- This function is an Event Handling function that will be called when Tank1 is Dead.
- -- @param Wrapper.Unit#UNIT self
- -- @param Core.Event#EVENTDATA EventData
- function Tank1:OnEventDead( EventData )
-
- self:SmokeGreen()
- end
-
- --- This function is an Event Handling function that will be called when Tank2 is Dead.
- -- @param Wrapper.Unit#UNIT self
- -- @param Core.Event#EVENTDATA EventData
- function Tank2:OnEventDead( EventData )
-
- self:SmokeBlue()
- end
-
-
-
1.3.3 Event Handling methods that are automatically called upon subscribed DCS events
-
-
-
-
The following list outlines which EVENTS item in the structure corresponds to which Event Handling method.
-Always ensure that your event handling methods align with the events being subscribed to, or nothing will be executed.
-
-
2) EVENTS type
-
-
The EVENTS structure contains names for all the different DCS events that objects can subscribe to using the
-Base#BASE.HandleEvent() method.
-
-
3) EVENTDATA type
-
-
The Event#EVENTDATA structure contains all the fields that are populated with event information before
-an Event Handler method is being called by the event dispatcher.
-The Event Handler received the EVENTDATA object as a parameter, and can be used to investigate further the different events.
-There are basically 4 main categories of information stored in the EVENTDATA structure:
-
-
-
Initiator Unit data: Several fields documenting the initiator unit related to the event.
-
Target Unit data: Several fields documenting the target unit related to the event.
-
Weapon data: Certain events populate weapon information.
-
Place data: Certain events populate place information.
-
-
--- This function is an Event Handling function that will be called when Tank1 is Dead.
- -- EventData is an EVENTDATA structure.
- -- We use the EventData.IniUnit to smoke the tank Green.
- -- @param Wrapper.Unit#UNIT self
- -- @param Core.Event#EVENTDATA EventData
- function Tank1:OnEventDead( EventData )
-
-
EventData.IniUnit:SmokeGreen()
- end
-
-
-
-
Find below an overview which events populate which information categories:
-
-
-
-
IMPORTANT NOTE: Some events can involve not just UNIT objects, but also STATIC objects!!!
-In that case the initiator or target unit fields will refer to a STATIC object!
-In case a STATIC object is involved, the documentation indicates which fields will and won't not be populated.
-The fields IniObjectCategory and TgtObjectCategory contain the indicator which kind of object is involved in the event.
-You can use the enumerator Object.Category.UNIT and Object.Category.STATIC to check on IniObjectCategory and TgtObjectCategory.
-Example code snippet:
-
-
if Event.IniObjectCategory == Object.Category.UNIT then
- ...
- end
- if Event.IniObjectCategory == Object.Category.STATIC then
- ...
- end
-
-
-
When a static object is involved in the event, the Group and Player fields won't be populated.
-
-
-
-
API CHANGE HISTORY
-
-
The underlying change log documents the API changes. Please read this carefully. The following notation is used:
Set a new listener for an SEVENTX event independent from a unit or a weapon.
-
-
Parameters
-
-
-
-
#function EventFunction :
-The function to be called when the event occurs for the unit.
-
-
-
-
-
Core.Base#BASE EventClass :
-The self instance of the class for which the event is captured. When the event happens, the event process will be called in this class provided.
The Event structure
-Note that at the beginning of each field description, there is an indication which field will be populated depending on the object type involved in the Event:
-
-
-
A (Object.Category.)UNIT : A UNIT object type is involved in the Event.
-
-
-
-
-
A (Object.Category.)STATIC : A STATIC object type is involved in the Event.µ
-
@@ -942,6 +1065,72 @@ The default "time interval" is after 0.001 seconds.
You can set the "yield interval", and the "time interval". (See above).
+
+
+
Once the filters have been defined and the SETCARGO has been built, you can iterate the SETCARGO with the available iterator methods.
+The iterator methods will walk the SETCARGO set, and call for each cargo within the set a function that you provide.
+The following iterator methods are currently available within the SETCARGO:
Iterate the SET_CARGO and call an interator function for each CARGO, providing the CARGO and optional parameters.
+
+
Parameters
+
+
+
+
#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.
Tasking (Release 2.1) -- The TASK_CARGO models tasks for players to transport Cargo.
+
+
+
+
+
+
+
+
Cargo are units or cargo objects within DCS world that allow to be transported or sling loaded by other units.
+The CARGO class, as part of the moose core, is able to Board, Load, UnBoard and UnLoad from Carrier units.
+This collection of classes in this module define tasks for human players to handle cargo objects.
+Cargo can be transported, picked-up, deployed and sling-loaded from and to other places.
+
+
The following classes are important to consider:
+
+
+
#TASKCARGOTRANSPORT: Defines a task for a human player to transport a set of cargo between various zones.
+
+
+
==
+
+
API CHANGE HISTORY
+
+
The underlying change log documents the API changes. Please read this carefully. The following notation is used:
The ZONE_GROUP class defines by a zone around a Group#GROUP with a radius.
@@ -727,8 +743,6 @@
The current leader of the group defines the center of the zone.
This class implements the inherited functions from Zone#ZONE_RADIUS taking into account the own zone format and properties.
-
-
@@ -742,15 +756,13 @@ This class implements the inherited functions from Zone#ZONEPOLYGONBASE
+
The ZONEPOLYGONBASE class defined by a sequence of Group#GROUP waypoints within the Mission Editor, forming a polygon.
@@ -772,7 +784,7 @@ This class implements the inherited functions from Zone#ZONE_RADIUS taking into account the own zone format and properties.
This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
-
6.1) Zone point randomization
+
Zone point randomization
Various functions exist to find random points within the zone.
@@ -782,8 +794,6 @@ This class is an abstract BASE class for derived classes, and is not meant to be