Merge pull request #171 from FlightControl-Master/MOOSE-RELEASE-2

MOOSE-RELEASE
This commit is contained in:
Sven Van de Velde 2016-12-17 22:09:00 +01:00 committed by GitHub
commit 4c904309f6
396 changed files with 59757 additions and 84603 deletions

View File

@ -0,0 +1,256 @@
--- This module contains the AI_BALANCER class.
--
-- ===
--
-- 1) @{AI.AI_Balancer#AI_BALANCER} class, extends @{Core.Fsm#FSM_SET}
-- ===================================================================================
-- The @{AI.AI_Balancer#AI_BALANCER} class monitors and manages as many AI GROUPS as there are
-- CLIENTS in a SET_CLIENT collection not occupied by players.
-- The AI_BALANCER class manages internally a collection of AI management objects, which govern the behaviour
-- of the underlying AI GROUPS.
--
-- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM)
-- and calls for each event the state transition methods providing the internal @{Core.Fsm#FSM_SET.Set} object containing the
-- SET_GROUP and additional event parameters provided during the event.
--
-- 1.1) AI_BALANCER construction method
-- ---------------------------------------
-- Create a new AI_BALANCER object with the @{#AI_BALANCER.New} method:
--
-- * @{#AI_BALANCER.New}: Creates a new AI_BALANCER object.
--
-- 1.2)
-- ----
-- * Add
-- * Remove
--
-- 1.2) AI_BALANCER returns AI to Airbases
-- ------------------------------------------
-- You can configure to have the AI to return to:
--
-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the home @{Wrapper.Airbase#AIRBASE}.
-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}.
-- --
-- ===
--
-- **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:
--
-- 2016-08-17: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval )
--
-- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called!
-- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
--
-- ===
--
-- AUTHORS and CONTRIBUTIONS
-- =========================
--
-- ### Contributions:
--
-- * **Dutch_Baron (James)**: Who you can search on the Eagle Dynamics Forums.
-- Working together with James has resulted in the creation of the AI_BALANCER class.
-- James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-)
--
-- * **SNAFU**:
-- Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE.
-- None of the script code has been used however within the new AI_BALANCER moose class.
--
-- ### Authors:
--
-- * FlightControl: Framework Design & Programming
--
-- @module AI_Balancer
--- AI_BALANCER class
-- @type AI_BALANCER
-- @field Core.Set#SET_CLIENT SetClient
-- @extends Core.Fsm#FSM_SET
AI_BALANCER = {
ClassName = "AI_BALANCER",
PatrolZones = {},
AIGroups = {},
}
--- Creates a new AI_BALANCER object
-- @param #AI_BALANCER self
-- @param Core.Set#SET_CLIENT SetClient A SET\_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player).
-- @param Functional.Spawn#SPAWN SpawnAI The default Spawn object to spawn new AI Groups when needed.
-- @return #AI_BALANCER
-- @usage
-- -- Define a new AI_BALANCER Object.
function AI_BALANCER:New( SetClient, SpawnAI )
-- Inherits from BASE
local self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- Core.Fsm#FSM_SET
self:SetStartState( "None" )
self:AddTransition( "*", "Start", "Monitoring" )
self:AddTransition( "*", "Monitor", "Monitoring" )
self:AddTransition( "*", "Spawn", "Spawning" )
self:AddTransition( "Spawning", "Spawned", "Spawned" )
self:AddTransition( "*", "Destroy", "Destroying" )
self:AddTransition( "*", "Return", "Returning" )
self:AddTransition( "*", "End", "End" )
self:AddTransition( "*", "Dead", "End" )
self.SetClient = SetClient
self.SpawnAI = SpawnAI
self.ToNearestAirbase = false
self.ToHomeAirbase = false
self:__Start( 1 )
return self
end
--- Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}.
-- @param #AI_BALANCER self
-- @param Dcs.DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
-- @param Core.Set#SET_AIRBASE ReturnAirbaseSet The SET of @{Core.Set#SET_AIRBASE}s to evaluate where to return to.
function AI_BALANCER:ReturnToNearestAirbases( ReturnTresholdRange, ReturnAirbaseSet )
self.ToNearestAirbase = true
self.ReturnTresholdRange = ReturnTresholdRange
self.ReturnAirbaseSet = ReturnAirbaseSet
end
--- Returns the AI to the home @{Wrapper.Airbase#AIRBASE}.
-- @param #AI_BALANCER self
-- @param Dcs.DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
function AI_BALANCER:ReturnToHomeAirbase( ReturnTresholdRange )
self.ToHomeAirbase = true
self.ReturnTresholdRange = ReturnTresholdRange
end
--- @param #AI_BALANCER self
-- @param Core.Set#SET_GROUP SetGroup
-- @param #string ClientName
-- @param Wrapper.Group#GROUP AIGroup
function AI_BALANCER:onenterSpawning( SetGroup, Event, From, To, ClientName )
-- OK, Spawn a new group from the default SpawnAI object provided.
local AIGroup = self.SpawnAI:Spawn()
AIGroup:E( "Spawning new AIGroup" )
--TODO: need to rework UnitName thing ...
SetGroup:Add( ClientName, AIGroup )
-- Fire the Spawned event. The first parameter is the AIGroup just Spawned.
-- Mission designers can catch this event to bind further actions to the AIGroup.
self:Spawned( AIGroup )
end
--- @param #AI_BALANCER self
-- @param Core.Set#SET_GROUP SetGroup
-- @param Wrapper.Group#GROUP AIGroup
function AI_BALANCER:onenterDestroying( SetGroup, Event, From, To, AIGroup )
AIGroup:Destroy()
end
--- @param #AI_BALANCER self
-- @param Core.Set#SET_GROUP SetGroup
-- @param Wrapper.Group#GROUP AIGroup
function AI_BALANCER:onenterReturning( SetGroup, Event, From, To, AIGroup )
local AIGroupTemplate = AIGroup:GetTemplate()
if self.ToHomeAirbase == true then
local WayPointCount = #AIGroupTemplate.route.points
local SwitchWayPointCommand = AIGroup:CommandSwitchWayPoint( 1, WayPointCount, 1 )
AIGroup:SetCommand( SwitchWayPointCommand )
AIGroup:MessageToRed( "Returning to home base ...", 30 )
else
-- Okay, we need to send this Group back to the nearest base of the Coalition of the AI.
--TODO: i need to rework the POINT_VEC2 thing.
local PointVec2 = POINT_VEC2:New( AIGroup:GetVec2().x, AIGroup:GetVec2().y )
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
self:T( ClosestAirbase.AirbaseName )
AIGroup:MessageToRed( "Returning to " .. ClosestAirbase:GetName().. " ...", 30 )
local RTBRoute = AIGroup:RouteReturnToAirbase( ClosestAirbase )
AIGroupTemplate.route = RTBRoute
AIGroup:Respawn( AIGroupTemplate )
end
end
--- @param #AI_BALANCER self
function AI_BALANCER:onenterMonitoring( SetGroup )
self.SetClient:ForEachClient(
--- @param Wrapper.Client#CLIENT Client
function( Client )
self:E(Client.ClientName)
local AIGroup = self.Set:Get( Client.UnitName ) -- Wrapper.Group#GROUP
if Client:IsAlive() then
if AIGroup and AIGroup:IsAlive() == true then
if self.ToNearestAirbase == false and self.ToHomeAirbase == false then
self:Destroy( AIGroup )
else
-- We test if there is no other CLIENT within the self.ReturnTresholdRange of the first unit of the AI group.
-- If there is a CLIENT, the AI stays engaged and will not return.
-- If there is no CLIENT within the self.ReturnTresholdRange, then the unit will return to the Airbase return method selected.
local PlayerInRange = { Value = false }
local RangeZone = ZONE_RADIUS:New( 'RangeZone', AIGroup:GetVec2(), self.ReturnTresholdRange )
self:E( RangeZone )
_DATABASE:ForEachPlayer(
--- @param Wrapper.Unit#UNIT RangeTestUnit
function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange )
self:E( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } )
if RangeTestUnit:IsInZone( RangeZone ) == true then
self:E( "in zone" )
if RangeTestUnit:GetCoalition() ~= AIGroup:GetCoalition() then
self:E( "in range" )
PlayerInRange.Value = true
end
end
end,
--- @param Core.Zone#ZONE_RADIUS RangeZone
-- @param Wrapper.Group#GROUP AIGroup
function( RangeZone, AIGroup, PlayerInRange )
if PlayerInRange.Value == false then
self:Return( AIGroup )
end
end
, RangeZone, AIGroup, PlayerInRange
)
end
self.Set:Remove( Client.UnitName )
end
else
if not AIGroup or not AIGroup:IsAlive() == true then
self:E("client not alive")
self:Spawn( Client.UnitName )
self:E("text after spawn")
end
end
return true
end
)
self:__Monitor( 10 )
end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
--- (AI) (FSM) Make AI patrol routes or zones.
--
-- ===
--
-- 1) @{#AI_PATROLZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE}
-- ================================================================
-- The @{#AI_PATROLZONE} class implements the core functions to patrol a @{Zone} by an AIR @{Controllable} @{Group}.
-- The patrol algorithm works that for each airplane patrolling, upon arrival at the patrol zone,
-- a random point is selected as the route point within the 3D space, within the given boundary limits.
-- The airplane will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
-- Upon arrival at the random 3D point, a new 3D random point will be selected within the patrol zone using the given limits.
-- This cycle will continue until a fuel treshold has been reached by the airplane.
-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
--
-- 1.1) AI_PATROLZONE constructor:
-- ----------------------------
--
-- * @{#AI_PATROLZONE.New}(): Creates a new AI_PATROLZONE object.
--
-- 1.2) AI_PATROLZONE state machine:
-- ----------------------------------
-- The AI_PATROLZONE is a state machine: it manages the different events and states of the AIControllable it is controlling.
--
-- ### 1.2.1) AI_PATROLZONE Events:
--
-- * @{#AI_PATROLZONE.Route}( AIControllable ): A new 3D route point is selected and the AIControllable will fly towards that point with the given speed.
-- * @{#AI_PATROLZONE.Patrol}( AIControllable ): The AIControllable reports it is patrolling. This event is called every 30 seconds.
-- * @{#AI_PATROLZONE.RTB}( AIControllable ): The AIControllable will report return to base.
-- * @{#AI_PATROLZONE.End}( AIControllable ): The end of the AI_PATROLZONE process.
-- * @{#AI_PATROLZONE.Dead}( AIControllable ): The AIControllable is dead. The AI_PATROLZONE process will be ended.
--
-- ### 1.2.2) AI_PATROLZONE States:
--
-- * **Route**: A new 3D route point is selected and the AIControllable will fly towards that point with the given speed.
-- * **Patrol**: The AIControllable is patrolling. This state is set every 30 seconds, so every 30 seconds, a state transition method can be used.
-- * **RTB**: The AIControllable reports it wants to return to the base.
-- * **Dead**: The AIControllable is dead ...
-- * **End**: The process has come to an end.
--
-- ### 1.2.3) AI_PATROLZONE 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:
--
-- * **Before** the state transition.
-- The state transition method needs to start with the name **OnBefore + 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!
--
-- * **After** the state transition.
-- The state transition method needs to start with the name **OnAfter + the name of the state**.
-- These state transition methods need to provide a return value, which is specified at the function description.
--
-- An example how to manage a state transition for an AI_PATROLZONE object **Patrol** for the state **RTB**:
--
-- local PatrolZoneGroup = GROUP:FindByName( "Patrol Zone" )
-- local PatrolZone = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup )
--
-- local PatrolSpawn = SPAWN:New( "Patrol Group" )
-- local PatrolGroup = PatrolSpawn:Spawn()
--
-- local Patrol = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 300, 600 )
-- Patrol:SetControllable( PatrolGroup )
-- Patrol:ManageFuel( 0.2, 60 )
--
-- **OnBefore**RTB( AIGroup ) will be called by the AI_PATROLZONE object when the AIGroup reports RTB, but **before** the RTB default action is processed by the AI_PATROLZONE object.
--
-- --- State transition function for the AI_PATROLZONE **Patrol** object
-- -- @param #AI_PATROLZONE self
-- -- @param Wrapper.Controllable#CONTROLLABLE AIGroup
-- -- @return #boolean If false is returned, then the OnAfter state transition method will not be called.
-- function Patrol:OnBeforeRTB( AIGroup )
-- AIGroup:MessageToRed( "Returning to base", 20 )
-- end
--
-- **OnAfter**RTB( AIGroup ) will be called by the AI_PATROLZONE object when the AIGroup reports RTB, but **after** the RTB default action was processed by the AI_PATROLZONE object.
--
-- --- State transition function for the AI_PATROLZONE **Patrol** object
-- -- @param #AI_PATROLZONE self
-- -- @param Wrapper.Controllable#CONTROLLABLE AIGroup
-- -- @return #Wrapper.Controllable#CONTROLLABLE The new AIGroup object that is set to be patrolling the zone.
-- function Patrol:OnAfterRTB( AIGroup )
-- return PatrolSpawn:Spawn()
-- end
--
-- 1.3) Manage the AI_PATROLZONE parameters:
-- ------------------------------------------
-- The following methods are available to modify the parameters of a AI_PATROLZONE object:
--
-- * @{#AI_PATROLZONE.SetControllable}(): Set the AIControllable.
-- * @{#AI_PATROLZONE.GetControllable}(): Get the AIControllable.
-- * @{#AI_PATROLZONE.SetSpeed}(): Set the patrol speed of the AI, for the next patrol.
-- * @{#AI_PATROLZONE.SetAltitude}(): Set altitude of the AI, for the next patrol.
--
-- 1.3) Manage the out of fuel in the AI_PATROLZONE:
-- ----------------------------------------------
-- When the AIControllable is out of fuel, it is required that a new AIControllable is started, before the old AIControllable can return to the home base.
-- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated.
-- When the fuel treshold is reached, the AIControllable will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROLZONE.
-- Once the time is finished, the old AIControllable will return to the base.
-- Use the method @{#AI_PATROLZONE.ManageFuel}() to have this proces in place.
--
-- ====
--
-- **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:
--
-- 2016-09-01: Initial class and API.
--
-- ===
--
-- AUTHORS and CONTRIBUTIONS
-- =========================
--
-- ### Contributions:
--
-- * **DutchBaron**: Testing.
-- * **Pikey**: Testing and API concept review.
--
-- ### Authors:
--
-- * **FlightControl**: Design & Programming.
--
--
-- @module Patrol
-- State Transition Functions
--- OnBefore State Transition Function
-- @function [parent=#AI_PATROLZONE] OnBeforeRoute
-- @param #AI_PATROLZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable
-- @return #boolean
--- OnAfter State Transition Function
-- @function [parent=#AI_PATROLZONE] OnAfterRoute
-- @param #AI_PATROLZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable
--- AI_PATROLZONE class
-- @type AI_PATROLZONE
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
-- @field Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @field Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @field Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @field Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
-- @field Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
-- @extends Core.Fsm#FSM_CONTROLLABLE
AI_PATROLZONE = {
ClassName = "AI_PATROLZONE",
}
--- Creates a new AI_PATROLZONE object
-- @param #AI_PATROLZONE self
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
-- @return #AI_PATROLZONE self
-- @usage
-- -- Define a new AI_PATROLZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
-- PatrolZone = ZONE:New( 'PatrolZone' )
-- PatrolSpawn = SPAWN:New( 'Patrol Group' )
-- PatrolArea = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 600, 900 )
function AI_PATROLZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed )
-- Inherits from BASE
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- Core.Fsm#FSM_CONTROLLABLE
self:SetStartState( "None" )
self:AddTransition( "*", "Start", "Route" )
self:AddTransition( "*", "Route", "Route" )
self:AddTransition( { "Patrol", "Route" }, "Patrol", "Patrol" )
self:AddTransition( "Patrol", "RTB", "RTB" )
self:AddTransition( "*", "End", "End" )
self:AddTransition( "*", "Dead", "End" )
self.PatrolZone = PatrolZone
self.PatrolFloorAltitude = PatrolFloorAltitude
self.PatrolCeilingAltitude = PatrolCeilingAltitude
self.PatrolMinSpeed = PatrolMinSpeed
self.PatrolMaxSpeed = PatrolMaxSpeed
return self
end
--- Sets (modifies) the minimum and maximum speed of the patrol.
-- @param #AI_PATROLZONE self
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
-- @return #AI_PATROLZONE self
function AI_PATROLZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
self.PatrolMinSpeed = PatrolMinSpeed
self.PatrolMaxSpeed = PatrolMaxSpeed
end
--- Sets the floor and ceiling altitude of the patrol.
-- @param #AI_PATROLZONE self
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @return #AI_PATROLZONE self
function AI_PATROLZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )
self.PatrolFloorAltitude = PatrolFloorAltitude
self.PatrolCeilingAltitude = PatrolCeilingAltitude
end
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
function _NewPatrolRoute( AIControllable )
AIControllable:T( "NewPatrolRoute" )
local PatrolZone = AIControllable:GetState( AIControllable, "PatrolZone" ) -- PatrolCore.Zone#AI_PATROLZONE
PatrolZone:__Route( 1 )
end
--- When the AIControllable is out of fuel, it is required that a new AIControllable is started, before the old AIControllable can return to the home base.
-- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated.
-- When the fuel treshold is reached, the AIControllable will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROLZONE.
-- Once the time is finished, the old AIControllable will return to the base.
-- @param #AI_PATROLZONE self
-- @param #number PatrolFuelTresholdPercentage The treshold in percentage (between 0 and 1) when the AIControllable is considered to get out of fuel.
-- @param #number PatrolOutOfFuelOrbitTime The amount of seconds the out of fuel AIControllable will orbit before returning to the base.
-- @return #AI_PATROLZONE self
function AI_PATROLZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime )
self.PatrolManageFuel = true
self.PatrolFuelTresholdPercentage = PatrolFuelTresholdPercentage
self.PatrolOutOfFuelOrbitTime = PatrolOutOfFuelOrbitTime
return self
end
--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings.
-- @param #AI_PATROLZONE self
-- @return #AI_PATROLZONE self
function AI_PATROLZONE:onenterRoute()
self:F2()
local PatrolRoute = {}
if self.Controllable:IsAlive() then
--- Determine if the AIControllable is within the PatrolZone.
-- If not, make a waypoint within the to that the AIControllable will fly at maximum speed to that point.
-- --- Calculate the current route point.
-- local CurrentVec2 = self.Controllable:GetVec2()
-- local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
-- local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
-- local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
-- POINT_VEC3.RoutePointAltType.BARO,
-- POINT_VEC3.RoutePointType.TurningPoint,
-- POINT_VEC3.RoutePointAction.TurningPoint,
-- ToPatrolZoneSpeed,
-- true
-- )
--
-- PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint
self:T2( PatrolRoute )
if self.Controllable:IsNotInZone( self.PatrolZone ) then
--- Find a random 2D point in PatrolZone.
local ToPatrolZoneVec2 = self.PatrolZone:GetRandomVec2()
self:T2( ToPatrolZoneVec2 )
--- Define Speed and Altitude.
local ToPatrolZoneAltitude = math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
self:T2( ToPatrolZoneSpeed )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToPatrolZonePointVec3 = POINT_VEC3:New( ToPatrolZoneVec2.x, ToPatrolZoneAltitude, ToPatrolZoneVec2.y )
--- Create a route point of type air.
local ToPatrolZoneRoutePoint = ToPatrolZonePointVec3:RoutePointAir(
POINT_VEC3.RoutePointAltType.BARO,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
ToPatrolZoneSpeed,
true
)
PatrolRoute[#PatrolRoute+1] = ToPatrolZoneRoutePoint
end
--- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
--- Find a random 2D point in PatrolZone.
local ToTargetVec2 = self.PatrolZone:GetRandomVec2()
self:T2( ToTargetVec2 )
--- Define Speed and Altitude.
local ToTargetAltitude = math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude )
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
--- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir(
POINT_VEC3.RoutePointAltType.BARO,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
ToTargetSpeed,
true
)
--ToTargetPointVec3:SmokeRed()
PatrolRoute[#PatrolRoute+1] = ToTargetRoutePoint
--- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
self.Controllable:WayPointInitialize( PatrolRoute )
--- Do a trick, link the NewPatrolRoute function of the PATROLGROUP object to the AIControllable in a temporary variable ...
self.Controllable:SetState( self.Controllable, "PatrolZone", self )
self.Controllable:WayPointFunction( #PatrolRoute, 1, "_NewPatrolRoute" )
--- NOW ACT_ROUTE THE GROUP!
self.Controllable:WayPointExecute( 1 )
self:__Patrol( 30 )
end
end
--- @param #AI_PATROLZONE self
function AI_PATROLZONE:onenterPatrol()
self:F2()
if self.Controllable and self.Controllable:IsAlive() then
local Fuel = self.Controllable:GetUnit(1):GetFuel()
if Fuel < self.PatrolFuelTresholdPercentage then
local OldAIControllable = self.Controllable
local AIControllableTemplate = self.Controllable:GetTemplate()
local OrbitTask = OldAIControllable:TaskOrbitCircle( math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ), self.PatrolMinSpeed )
local TimedOrbitTask = OldAIControllable:TaskControlled( OrbitTask, OldAIControllable:TaskCondition(nil,nil,nil,nil,self.PatrolOutOfFuelOrbitTime,nil ) )
OldAIControllable:SetTask( TimedOrbitTask, 10 )
self:RTB()
else
self:__Patrol( 30 ) -- Execute the Patrol event after 30 seconds.
end
end
end

View File

@ -0,0 +1,266 @@
--- (SP) (MP) (FSM) Account for (Detect, count and report) DCS events occuring on DCS objects (units).
--
-- ===
--
-- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS}
--
-- ## ACT_ACCOUNT state machine:
--
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
-- All derived classes from this class will start with the class name, followed by a \_. See the relevant derived class descriptions below.
-- Each derived class follows exactly the same process, using the same events and following the same state transitions,
-- but will have **different implementation behaviour** upon each event or state transition.
--
-- ### ACT_ACCOUNT **Events**:
--
-- These are the events defined in this class:
--
-- * **Start**: The process is started. The process will go into the Report state.
-- * **Event**: A relevant event has occured that needs to be accounted for. The process will go into the Account state.
-- * **Report**: The process is reporting to the player the accounting status of the DCS events.
-- * **More**: There are more DCS events that need to be accounted for. The process will go back into the Report state.
-- * **NoMore**: There are no more DCS events that need to be accounted for. The process will go into the Success state.
--
-- ### ACT_ACCOUNT **Event methods**:
--
-- Event methods are available (dynamically allocated by the state machine), that accomodate for state transitions occurring in the process.
-- There are two types of event methods, which you can use to influence the normal mechanisms in the state machine:
--
-- * **Immediate**: The event method has exactly the name of the event.
-- * **Delayed**: The event method starts with a __ + the name of the event. The first parameter of the event method is a number value, expressing the delay in seconds when the event will be executed.
--
-- ### ACT_ACCOUNT **States**:
--
-- * **Assigned**: The player is assigned to the task. This is the initialization state for the process.
-- * **Waiting**: the process is waiting for a DCS event to occur within the simulator. This state is set automatically.
-- * **Report**: The process is Reporting to the players in the group of the unit. This state is set automatically every 30 seconds.
-- * **Account**: The relevant DCS event has occurred, and is accounted for.
-- * **Success (*)**: All DCS events were accounted for.
-- * **Failed (*)**: The process has failed.
--
-- (*) End states of the process.
--
-- ### ACT_ACCOUNT 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:
--
-- * **Before** the state transition.
-- The state transition method needs to start with the name **OnBefore + 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!
--
-- * **After** the state transition.
-- The state transition method needs to start with the name **OnAfter + the name of the state**.
-- These state transition methods need to provide a return value, which is specified at the function description.
--
-- # 1) @{#ACT_ACCOUNT_DEADS} FSM class, extends @{Fsm.Account#ACT_ACCOUNT}
--
-- The ACT_ACCOUNT_DEADS class accounts (detects, counts and reports) successful kills of DCS units.
-- The process is given a @{Set} of units that will be tracked upon successful destruction.
-- The process will end after each target has been successfully destroyed.
-- Each successful dead will trigger an Account state transition that can be scored, modified or administered.
--
--
-- ## ACT_ACCOUNT_DEADS constructor:
--
-- * @{#ACT_ACCOUNT_DEADS.New}(): Creates a new ACT_ACCOUNT_DEADS object.
--
-- ===
--
-- @module Account
do -- ACT_ACCOUNT
--- ACT_ACCOUNT class
-- @type ACT_ACCOUNT
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Core.Fsm#FSM_PROCESS
ACT_ACCOUNT = {
ClassName = "ACT_ACCOUNT",
TargetSetUnit = nil,
}
--- Creates a new DESTROY process.
-- @param #ACT_ACCOUNT self
-- @return #ACT_ACCOUNT
function ACT_ACCOUNT:New()
-- Inherits from BASE
local self = BASE:Inherit( self, FSM_PROCESS:New() ) -- Core.Fsm#FSM_PROCESS
self:AddTransition( "Assigned", "Start", "Waiting")
self:AddTransition( "*", "Wait", "Waiting")
self:AddTransition( "*", "Report", "Report")
self:AddTransition( "*", "Event", "Account")
self:AddTransition( "Account", "More", "Wait")
self:AddTransition( "Account", "NoMore", "Accounted")
self:AddTransition( "*", "Fail", "Failed")
self:AddEndState( "Accounted" )
self:AddEndState( "Failed" )
self:SetStartState( "Assigned" )
return self
end
--- Process Events
--- StateMachine callback function
-- @param #ACT_ACCOUNT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ACCOUNT:onafterStart( ProcessUnit, Event, From, To )
self:EventOnDead( self.onfuncEventDead )
self:__Wait( 1 )
end
--- StateMachine callback function
-- @param #ACT_ACCOUNT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ACCOUNT:onenterWaiting( ProcessUnit, Event, From, To )
if self.DisplayCount >= self.DisplayInterval then
self:Report()
self.DisplayCount = 1
else
self.DisplayCount = self.DisplayCount + 1
end
return true -- Process always the event.
end
--- StateMachine callback function
-- @param #ACT_ACCOUNT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ACCOUNT:onafterEvent( ProcessUnit, Event, From, To, Event )
self:__NoMore( 1 )
end
end -- ACT_ACCOUNT
do -- ACT_ACCOUNT_DEADS
--- ACT_ACCOUNT_DEADS class
-- @type ACT_ACCOUNT_DEADS
-- @field Set#SET_UNIT TargetSetUnit
-- @extends #ACT_ACCOUNT
ACT_ACCOUNT_DEADS = {
ClassName = "ACT_ACCOUNT_DEADS",
TargetSetUnit = nil,
}
--- Creates a new DESTROY process.
-- @param #ACT_ACCOUNT_DEADS self
-- @param Set#SET_UNIT TargetSetUnit
-- @param #string TaskName
function ACT_ACCOUNT_DEADS:New( TargetSetUnit, TaskName )
-- Inherits from BASE
local self = BASE:Inherit( self, ACT_ACCOUNT:New() ) -- #ACT_ACCOUNT_DEADS
self.TargetSetUnit = TargetSetUnit
self.TaskName = TaskName
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
self.DisplayCategory = "HQ" -- Targets is the default display category
return self
end
function ACT_ACCOUNT_DEADS:Init( FsmAccount )
self.TargetSetUnit = FsmAccount.TargetSetUnit
self.TaskName = FsmAccount.TaskName
end
function ACT_ACCOUNT_DEADS:_Destructor()
self:E("_Destructor")
self:EventRemoveAll()
end
--- Process Events
--- StateMachine callback function
-- @param #ACT_ACCOUNT_DEADS self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ACCOUNT_DEADS:onenterReport( ProcessUnit, Event, From, To )
self:E( { ProcessUnit, Event, From, To } )
self:Message( "Your group with assigned " .. self.TaskName .. " task has " .. self.TargetSetUnit:GetUnitTypesText() .. " targets left to be destroyed." )
end
--- StateMachine callback function
-- @param #ACT_ACCOUNT_DEADS self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ACCOUNT_DEADS:onenterAccount( ProcessUnit, Event, From, To, EventData )
self:T( { ProcessUnit, EventData, Event, From, To } )
self:T({self.Controllable})
self.TargetSetUnit:Flush()
if self.TargetSetUnit:FindUnit( EventData.IniUnitName ) then
local TaskGroup = ProcessUnit:GetGroup()
self.TargetSetUnit:RemoveUnitsByName( EventData.IniUnitName )
self:Message( "You hit a target. Your group with assigned " .. self.TaskName .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed." )
end
end
--- StateMachine callback function
-- @param #ACT_ACCOUNT_DEADS self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ACCOUNT_DEADS:onafterEvent( ProcessUnit, Event, From, To, EventData )
if self.TargetSetUnit:Count() > 0 then
self:__More( 1 )
else
self:__NoMore( 1 )
end
end
--- DCS Events
--- @param #ACT_ACCOUNT_DEADS self
-- @param Event#EVENTDATA EventData
function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData )
self:T( { "EventDead", EventData } )
if EventData.IniDCSUnit then
self:__Event( 1, EventData )
end
end
end -- ACT_ACCOUNT DEADS

View File

@ -0,0 +1,293 @@
--- (SP) (MP) (FSM) Accept or reject process for player (task) assignments.
--
-- ===
--
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
--
-- ## ACT_ASSIGN state machine:
--
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
-- All derived classes from this class will start with the class name, followed by a \_. See the relevant derived class descriptions below.
-- Each derived class follows exactly the same process, using the same events and following the same state transitions,
-- but will have **different implementation behaviour** upon each event or state transition.
--
-- ### ACT_ASSIGN **Events**:
--
-- These are the events defined in this class:
--
-- * **Start**: Start the tasking acceptance process.
-- * **Assign**: Assign the task.
-- * **Reject**: Reject the task..
--
-- ### ACT_ASSIGN **Event methods**:
--
-- Event methods are available (dynamically allocated by the state machine), that accomodate for state transitions occurring in the process.
-- There are two types of event methods, which you can use to influence the normal mechanisms in the state machine:
--
-- * **Immediate**: The event method has exactly the name of the event.
-- * **Delayed**: The event method starts with a __ + the name of the event. The first parameter of the event method is a number value, expressing the delay in seconds when the event will be executed.
--
-- ### ACT_ASSIGN **States**:
--
-- * **UnAssigned**: The player has not accepted the task.
-- * **Assigned (*)**: The player has accepted the task.
-- * **Rejected (*)**: The player has not accepted the task.
-- * **Waiting**: The process is awaiting player feedback.
-- * **Failed (*)**: The process has failed.
--
-- (*) End states of the process.
--
-- ### ACT_ASSIGN 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:
--
-- * **Before** the state transition.
-- The state transition method needs to start with the name **OnBefore + 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!
--
-- * **After** the state transition.
-- The state transition method needs to start with the name **OnAfter + the name of the state**.
-- These state transition methods need to provide a return value, which is specified at the function description.
--
-- ===
--
-- # 1) @{#ACT_ASSIGN_ACCEPT} class, extends @{Fsm.Assign#ACT_ASSIGN}
--
-- The ACT_ASSIGN_ACCEPT class accepts by default a task for a player. No player intervention is allowed to reject the task.
--
-- ## 1.1) ACT_ASSIGN_ACCEPT constructor:
--
-- * @{#ACT_ASSIGN_ACCEPT.New}(): Creates a new ACT_ASSIGN_ACCEPT object.
--
-- ===
--
-- # 2) @{#ACT_ASSIGN_MENU_ACCEPT} class, extends @{Fsm.Assign#ACT_ASSIGN}
--
-- The ACT_ASSIGN_MENU_ACCEPT class accepts a task when the player accepts the task through an added menu option.
-- This assignment type is useful to conditionally allow the player to choose whether or not he would accept the task.
-- The assignment type also allows to reject the task.
--
-- ## 2.1) ACT_ASSIGN_MENU_ACCEPT constructor:
-- -----------------------------------------
--
-- * @{#ACT_ASSIGN_MENU_ACCEPT.New}(): Creates a new ACT_ASSIGN_MENU_ACCEPT object.
--
-- ===
--
-- @module Assign
do -- ACT_ASSIGN
--- ACT_ASSIGN class
-- @type ACT_ASSIGN
-- @field Tasking.Task#TASK Task
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Zone#ZONE_BASE TargetZone
-- @extends Core.Fsm#FSM_PROCESS
ACT_ASSIGN = {
ClassName = "ACT_ASSIGN",
}
--- Creates a new task assignment state machine. The process will accept the task by default, no player intervention accepted.
-- @param #ACT_ASSIGN self
-- @return #ACT_ASSIGN The task acceptance process.
function ACT_ASSIGN:New()
-- Inherits from BASE
local self = BASE:Inherit( self, FSM_PROCESS:New( "ACT_ASSIGN" ) ) -- Core.Fsm#FSM_PROCESS
self:AddTransition( "UnAssigned", "Start", "Waiting" )
self:AddTransition( "Waiting", "Assign", "Assigned" )
self:AddTransition( "Waiting", "Reject", "Rejected" )
self:AddTransition( "*", "Fail", "Failed" )
self:AddEndState( "Assigned" )
self:AddEndState( "Rejected" )
self:AddEndState( "Failed" )
self:SetStartState( "UnAssigned" )
return self
end
end -- ACT_ASSIGN
do -- ACT_ASSIGN_ACCEPT
--- ACT_ASSIGN_ACCEPT class
-- @type ACT_ASSIGN_ACCEPT
-- @field Tasking.Task#TASK Task
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Zone#ZONE_BASE TargetZone
-- @extends #ACT_ASSIGN
ACT_ASSIGN_ACCEPT = {
ClassName = "ACT_ASSIGN_ACCEPT",
}
--- Creates a new task assignment state machine. The process will accept the task by default, no player intervention accepted.
-- @param #ACT_ASSIGN_ACCEPT self
-- @param #string TaskBriefing
function ACT_ASSIGN_ACCEPT:New( TaskBriefing )
local self = BASE:Inherit( self, ACT_ASSIGN:New() ) -- #ACT_ASSIGN_ACCEPT
self.TaskBriefing = TaskBriefing
return self
end
function ACT_ASSIGN_ACCEPT:Init( FsmAssign )
self.TaskBriefing = FsmAssign.TaskBriefing
end
--- StateMachine callback function
-- @param #ACT_ASSIGN_ACCEPT self
-- @param Wrapper.Unit#UNIT ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIGN_ACCEPT:onafterStart( ProcessUnit, Event, From, To )
self:E( { ProcessUnit, Event, From, To } )
self:__Assign( 1 )
end
--- StateMachine callback function
-- @param #ACT_ASSIGN_ACCEPT self
-- @param Wrapper.Unit#UNIT ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIGN_ACCEPT:onenterAssigned( ProcessUnit, Event, From, To )
env.info( "in here" )
self:E( { ProcessUnit, Event, From, To } )
local ProcessGroup = ProcessUnit:GetGroup()
self:Message( "You are assigned to the task " .. self.Task:GetName() )
self.Task:Assign()
end
end -- ACT_ASSIGN_ACCEPT
do -- ACT_ASSIGN_MENU_ACCEPT
--- ACT_ASSIGN_MENU_ACCEPT class
-- @type ACT_ASSIGN_MENU_ACCEPT
-- @field Tasking.Task#TASK Task
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Zone#ZONE_BASE TargetZone
-- @extends #ACT_ASSIGN
ACT_ASSIGN_MENU_ACCEPT = {
ClassName = "ACT_ASSIGN_MENU_ACCEPT",
}
--- Init.
-- @param #ACT_ASSIGN_MENU_ACCEPT self
-- @param #string TaskName
-- @param #string TaskBriefing
-- @return #ACT_ASSIGN_MENU_ACCEPT self
function ACT_ASSIGN_MENU_ACCEPT:New( TaskName, TaskBriefing )
-- Inherits from BASE
local self = BASE:Inherit( self, ACT_ASSIGN:New() ) -- #ACT_ASSIGN_MENU_ACCEPT
self.TaskName = TaskName
self.TaskBriefing = TaskBriefing
return self
end
function ACT_ASSIGN_MENU_ACCEPT:Init( FsmAssign )
self.TaskName = FsmAssign.TaskName
self.TaskBriefing = FsmAssign.TaskBriefing
end
--- Creates a new task assignment state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #ACT_ASSIGN_MENU_ACCEPT self
-- @param #string TaskName
-- @param #string TaskBriefing
-- @return #ACT_ASSIGN_MENU_ACCEPT self
function ACT_ASSIGN_MENU_ACCEPT:Init( TaskName, TaskBriefing )
self.TaskBriefing = TaskBriefing
self.TaskName = TaskName
return self
end
--- StateMachine callback function
-- @param #ACT_ASSIGN_MENU_ACCEPT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIGN_MENU_ACCEPT:onafterStart( ProcessUnit, Event, From, To )
self:E( { ProcessUnit, Event, From, To } )
self:Message( "Access the radio menu to accept the task. You have 30 seconds or the assignment will be cancelled." )
local ProcessGroup = ProcessUnit:GetGroup()
self.Menu = MENU_GROUP:New( ProcessGroup, "Task " .. self.TaskName .. " acceptance" )
self.MenuAcceptTask = MENU_GROUP_COMMAND:New( ProcessGroup, "Accept task " .. self.TaskName, self.Menu, self.MenuAssign, self )
self.MenuRejectTask = MENU_GROUP_COMMAND:New( ProcessGroup, "Reject task " .. self.TaskName, self.Menu, self.MenuReject, self )
end
--- Menu function.
-- @param #ACT_ASSIGN_MENU_ACCEPT self
function ACT_ASSIGN_MENU_ACCEPT:MenuAssign()
self:E( )
self:__Assign( 1 )
end
--- Menu function.
-- @param #ACT_ASSIGN_MENU_ACCEPT self
function ACT_ASSIGN_MENU_ACCEPT:MenuReject()
self:E( )
self:__Reject( 1 )
end
--- StateMachine callback function
-- @param #ACT_ASSIGN_MENU_ACCEPT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIGN_MENU_ACCEPT:onafterAssign( ProcessUnit, Event, From, To )
self:E( { ProcessUnit.UnitNameEvent, From, To } )
self.Menu:Remove()
end
--- StateMachine callback function
-- @param #ACT_ASSIGN_MENU_ACCEPT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIGN_MENU_ACCEPT:onafterReject( ProcessUnit, Event, From, To )
self:E( { ProcessUnit.UnitName, Event, From, To } )
self.Menu:Remove()
--TODO: need to resolve this problem ... it has to do with the events ...
--self.Task:UnAssignFromUnit( ProcessUnit )needs to become a callback funtion call upon the event
ProcessUnit:Destroy()
end
end -- ACT_ASSIGN_MENU_ACCEPT

View File

@ -0,0 +1,206 @@
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
--
-- ===
--
-- # @{#ACT_ASSIST} FSM class, extends @{Core.Fsm#FSM_PROCESS}
--
-- ## ACT_ASSIST state machine:
--
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
-- All derived classes from this class will start with the class name, followed by a \_. See the relevant derived class descriptions below.
-- Each derived class follows exactly the same process, using the same events and following the same state transitions,
-- but will have **different implementation behaviour** upon each event or state transition.
--
-- ### ACT_ASSIST **Events**:
--
-- These are the events defined in this class:
--
-- * **Start**: The process is started.
-- * **Next**: The process is smoking the targets in the given zone.
--
-- ### ACT_ASSIST **Event methods**:
--
-- Event methods are available (dynamically allocated by the state machine), that accomodate for state transitions occurring in the process.
-- There are two types of event methods, which you can use to influence the normal mechanisms in the state machine:
--
-- * **Immediate**: The event method has exactly the name of the event.
-- * **Delayed**: The event method starts with a __ + the name of the event. The first parameter of the event method is a number value, expressing the delay in seconds when the event will be executed.
--
-- ### ACT_ASSIST **States**:
--
-- * **None**: The controllable did not receive route commands.
-- * **AwaitSmoke (*)**: The process is awaiting to smoke the targets in the zone.
-- * **Smoking (*)**: The process is smoking the targets in the zone.
-- * **Failed (*)**: The process has failed.
--
-- (*) End states of the process.
--
-- ### ACT_ASSIST 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:
--
-- * **Before** the state transition.
-- The state transition method needs to start with the name **OnBefore + 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!
--
-- * **After** the state transition.
-- The state transition method needs to start with the name **OnAfter + the name of the state**.
-- These state transition methods need to provide a return value, which is specified at the function description.
--
-- ===
--
-- # 1) @{#ACT_ASSIST_SMOKE_TARGETS_ZONE} class, extends @{Fsm.Route#ACT_ASSIST}
--
-- The ACT_ASSIST_SMOKE_TARGETS_ZONE class implements the core functions to smoke targets in a @{Zone}.
-- The targets are smoked within a certain range around each target, simulating a realistic smoking behaviour.
-- At random intervals, a new target is smoked.
--
-- # 1.1) ACT_ASSIST_SMOKE_TARGETS_ZONE constructor:
--
-- * @{#ACT_ASSIST_SMOKE_TARGETS_ZONE.New}(): Creates a new ACT_ASSIST_SMOKE_TARGETS_ZONE object.
--
-- ===
--
-- @module Smoke
do -- ACT_ASSIST
--- ACT_ASSIST class
-- @type ACT_ASSIST
-- @extends Core.Fsm#FSM_PROCESS
ACT_ASSIST = {
ClassName = "ACT_ASSIST",
}
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #ACT_ASSIST self
-- @return #ACT_ASSIST
function ACT_ASSIST:New()
-- Inherits from BASE
local self = BASE:Inherit( self, FSM_PROCESS:New( "ACT_ASSIST" ) ) -- Core.Fsm#FSM_PROCESS
self:AddTransition( "None", "Start", "AwaitSmoke" )
self:AddTransition( "AwaitSmoke", "Next", "Smoking" )
self:AddTransition( "Smoking", "Next", "AwaitSmoke" )
self:AddTransition( "*", "Stop", "Success" )
self:AddTransition( "*", "Fail", "Failed" )
self:AddEndState( "Failed" )
self:AddEndState( "Success" )
self:SetStartState( "None" )
return self
end
--- Task Events
--- StateMachine callback function
-- @param #ACT_ASSIST self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIST:onafterStart( ProcessUnit, Event, From, To )
local ProcessGroup = ProcessUnit:GetGroup()
local MissionMenu = self:GetMission():GetMissionMenu( ProcessGroup )
local function MenuSmoke( MenuParam )
self:E( MenuParam )
local self = MenuParam.self
local SmokeColor = MenuParam.SmokeColor
self.SmokeColor = SmokeColor
self:__Next( 1 )
end
self.Menu = MENU_GROUP:New( ProcessGroup, "Target acquisition", MissionMenu )
self.MenuSmokeBlue = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop blue smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Blue } )
self.MenuSmokeGreen = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop green smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Green } )
self.MenuSmokeOrange = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop Orange smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Orange } )
self.MenuSmokeRed = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop Red smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Red } )
self.MenuSmokeWhite = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop White smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.White } )
end
end
do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
--- ACT_ASSIST_SMOKE_TARGETS_ZONE class
-- @type ACT_ASSIST_SMOKE_TARGETS_ZONE
-- @field Set#SET_UNIT TargetSetUnit
-- @field Core.Zone#ZONE_BASE TargetZone
-- @extends #ACT_ASSIST
ACT_ASSIST_SMOKE_TARGETS_ZONE = {
ClassName = "ACT_ASSIST_SMOKE_TARGETS_ZONE",
}
-- function ACT_ASSIST_SMOKE_TARGETS_ZONE:_Destructor()
-- self:E("_Destructor")
--
-- self.Menu:Remove()
-- self:EventRemoveAll()
-- end
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self
-- @param Set#SET_UNIT TargetSetUnit
-- @param Core.Zone#ZONE_BASE TargetZone
function ACT_ASSIST_SMOKE_TARGETS_ZONE:New( TargetSetUnit, TargetZone )
local self = BASE:Inherit( self, ACT_ASSIST:New() ) -- #ACT_ASSIST
self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone
return self
end
function ACT_ASSIST_SMOKE_TARGETS_ZONE:Init( FsmSmoke )
self.TargetSetUnit = FsmSmoke.TargetSetUnit
self.TargetZone = FsmSmoke.TargetZone
end
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self
-- @param Set#SET_UNIT TargetSetUnit
-- @param Core.Zone#ZONE_BASE TargetZone
-- @return #ACT_ASSIST_SMOKE_TARGETS_ZONE self
function ACT_ASSIST_SMOKE_TARGETS_ZONE:Init( TargetSetUnit, TargetZone )
self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone
return self
end
--- StateMachine callback function
-- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIST_SMOKE_TARGETS_ZONE:onenterSmoking( ProcessUnit, Event, From, To )
self.TargetSetUnit:ForEachUnit(
--- @param Wrapper.Unit#UNIT SmokeUnit
function( SmokeUnit )
if math.random( 1, ( 100 * self.TargetSetUnit:Count() ) / 4 ) <= 100 then
SCHEDULER:New( self,
function()
if SmokeUnit:IsAlive() then
SmokeUnit:Smoke( self.SmokeColor, 150 )
end
end, {}, math.random( 10, 60 )
)
end
end
)
end
end

View File

@ -2,9 +2,9 @@
--- PROCESS_JTAC class
-- @type PROCESS_JTAC
-- @field Unit#UNIT ProcessUnit
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Process#PROCESS
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Core.Fsm#FSM_PROCESS
PROCESS_JTAC = {
ClassName = "PROCESS_JTAC",
Fsm = {},
@ -14,10 +14,10 @@ PROCESS_JTAC = {
--- Creates a new DESTROY process.
-- @param #PROCESS_JTAC self
-- @param Task#TASK Task
-- @param Unit#UNIT ProcessUnit
-- @param Set#SET_UNIT TargetSetUnit
-- @param Unit#UNIT FACUnit
-- @param Tasking.Task#TASK Task
-- @param Wrapper.Unit#UNIT ProcessUnit
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param Wrapper.Unit#UNIT FACUnit
-- @return #PROCESS_JTAC self
function PROCESS_JTAC:New( Task, ProcessUnit, TargetSetUnit, FACUnit )
@ -34,7 +34,7 @@ function PROCESS_JTAC:New( Task, ProcessUnit, TargetSetUnit, FACUnit )
self.DisplayCategory = "HQ" -- Targets is the default display category
self.Fsm = STATEMACHINE_PROCESS:New( self, {
self.Fsm = FSM_PROCESS:New( self, {
initial = 'Assigned',
events = {
{ name = 'Start', from = 'Assigned', to = 'CreatedMenu' },
@ -66,7 +66,7 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -77,7 +77,7 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -123,7 +123,7 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -131,7 +131,7 @@ function PROCESS_JTAC:OnJTACMenuAwait( Fsm, Event, From, To )
if self.DisplayCount >= self.DisplayInterval then
local TaskJTAC = self.Task -- Task#TASK_JTAC
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
TaskJTAC.Spots = TaskJTAC.Spots or {}
for TargetUnitName, SpotData in pairs( TaskJTAC.Spots) do
local TargetUnit = UNIT:FindByName( TargetUnitName )
@ -147,16 +147,16 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Unit#UNIT TargetUnit
-- @param Wrapper.Unit#UNIT TargetUnit
function PROCESS_JTAC:OnJTACMenuSpot( Fsm, Event, From, To, TargetUnit )
local TargetUnitName = TargetUnit:GetName()
local TaskJTAC = self.Task -- Task#TASK_JTAC
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
TaskJTAC.Spots = TaskJTAC.Spots or {}
TaskJTAC.Spots[TargetUnitName] = TaskJTAC.Spots[TargetUnitName] or {}
@ -174,16 +174,16 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Unit#UNIT TargetUnit
-- @param Wrapper.Unit#UNIT TargetUnit
function PROCESS_JTAC:OnJTACMenuCancel( Fsm, Event, From, To, TargetUnit )
local TargetUnitName = TargetUnit:GetName()
local TaskJTAC = self.Task -- Task#TASK_JTAC
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
TaskJTAC.Spots = TaskJTAC.Spots or {}
if TaskJTAC.Spots[TargetUnitName] then

View File

@ -2,9 +2,9 @@
--- PROCESS_PICKUP class
-- @type PROCESS_PICKUP
-- @field Unit#UNIT ProcessUnit
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Process#PROCESS
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Core.Fsm#FSM_PROCESS
PROCESS_PICKUP = {
ClassName = "PROCESS_PICKUP",
Fsm = {},
@ -14,9 +14,9 @@ PROCESS_PICKUP = {
--- Creates a new DESTROY process.
-- @param #PROCESS_PICKUP self
-- @param Task#TASK Task
-- @param Unit#UNIT ProcessUnit
-- @param Set#SET_UNIT TargetSetUnit
-- @param Tasking.Task#TASK Task
-- @param Wrapper.Unit#UNIT ProcessUnit
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @return #PROCESS_PICKUP self
function PROCESS_PICKUP:New( Task, ProcessName, ProcessUnit )
@ -29,7 +29,7 @@ function PROCESS_PICKUP:New( Task, ProcessName, ProcessUnit )
self.DisplayTime = 10 -- 10 seconds is the default
self.DisplayCategory = "HQ" -- Targets is the default display category
self.Fsm = STATEMACHINE_PROCESS:New( self, {
self.Fsm = FSM_PROCESS:New( self, {
initial = 'Assigned',
events = {
{ name = 'Start', from = 'Assigned', to = 'Navigating' },
@ -57,7 +57,7 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -68,7 +68,7 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -89,11 +89,11 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function PROCESS_PICKUP:OnHitTarget( Fsm, Event, From, To, Event )
@ -115,7 +115,7 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -126,11 +126,11 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA DCSEvent
-- @param Core.Event#EVENTDATA DCSEvent
function PROCESS_PICKUP:OnKilled( Fsm, Event, From, To )
self:NextEvent( Fsm.Restart )
@ -139,7 +139,7 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -151,7 +151,7 @@ end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -162,7 +162,7 @@ end
--- DCS Events
--- @param #PROCESS_PICKUP self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function PROCESS_PICKUP:EventDead( Event )
if Event.IniDCSUnit then

View File

@ -0,0 +1,249 @@
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
--
-- ===
--
-- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS}
--
-- ## ACT_ROUTE state machine:
--
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
-- All derived classes from this class will start with the class name, followed by a \_. See the relevant derived class descriptions below.
-- Each derived class follows exactly the same process, using the same events and following the same state transitions,
-- but will have **different implementation behaviour** upon each event or state transition.
--
-- ### ACT_ROUTE **Events**:
--
-- These are the events defined in this class:
--
-- * **Start**: The process is started. The process will go into the Report state.
-- * **Report**: The process is reporting to the player the route to be followed.
-- * **Route**: The process is routing the controllable.
-- * **Pause**: The process is pausing the route of the controllable.
-- * **Arrive**: The controllable has arrived at a route point.
-- * **More**: There are more route points that need to be followed. The process will go back into the Report state.
-- * **NoMore**: There are no more route points that need to be followed. The process will go into the Success state.
--
-- ### ACT_ROUTE **Event methods**:
--
-- Event methods are available (dynamically allocated by the state machine), that accomodate for state transitions occurring in the process.
-- There are two types of event methods, which you can use to influence the normal mechanisms in the state machine:
--
-- * **Immediate**: The event method has exactly the name of the event.
-- * **Delayed**: The event method starts with a __ + the name of the event. The first parameter of the event method is a number value, expressing the delay in seconds when the event will be executed.
--
-- ### ACT_ROUTE **States**:
--
-- * **None**: The controllable did not receive route commands.
-- * **Arrived (*)**: The controllable has arrived at a route point.
-- * **Aborted (*)**: The controllable has aborted the route path.
-- * **Routing**: The controllable is understay to the route point.
-- * **Pausing**: The process is pausing the routing. AI air will go into hover, AI ground will stop moving. Players can fly around.
-- * **Success (*)**: All route points were reached.
-- * **Failed (*)**: The process has failed.
--
-- (*) End states of the process.
--
-- ### ACT_ROUTE 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:
--
-- * **Before** the state transition.
-- The state transition method needs to start with the name **OnBefore + 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!
--
-- * **After** the state transition.
-- The state transition method needs to start with the name **OnAfter + the name of the state**.
-- These state transition methods need to provide a return value, which is specified at the function description.
--
-- ===
--
-- # 1) @{#ACT_ROUTE_ZONE} class, extends @{Fsm.Route#ACT_ROUTE}
--
-- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Controllable} player @{Unit} to a @{Zone}.
-- The player receives on perioding times messages with the coordinates of the route to follow.
-- Upon arrival at the zone, a confirmation of arrival is sent, and the process will be ended.
--
-- # 1.1) ACT_ROUTE_ZONE constructor:
--
-- * @{#ACT_ROUTE_ZONE.New}(): Creates a new ACT_ROUTE_ZONE object.
--
-- ===
--
-- @module Route
do -- ACT_ROUTE
--- ACT_ROUTE class
-- @type ACT_ROUTE
-- @field Tasking.Task#TASK TASK
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Zone#ZONE_BASE TargetZone
-- @extends Core.Fsm#FSM_PROCESS
ACT_ROUTE = {
ClassName = "ACT_ROUTE",
}
--- Creates a new routing state machine. The process will route a CLIENT to a ZONE until the CLIENT is within that ZONE.
-- @param #ACT_ROUTE self
-- @return #ACT_ROUTE self
function ACT_ROUTE:New()
-- Inherits from BASE
local self = BASE:Inherit( self, FSM_PROCESS:New( "ACT_ROUTE" ) ) -- Core.Fsm#FSM_PROCESS
self:AddTransition( "None", "Start", "Routing" )
self:AddTransition( "*", "Report", "Reporting" )
self:AddTransition( "*", "Route", "Routing" )
self:AddTransition( "Routing", "Pause", "Pausing" )
self:AddTransition( "*", "Abort", "Aborted" )
self:AddTransition( "Routing", "Arrive", "Arrived" )
self:AddTransition( "Arrived", "Success", "Success" )
self:AddTransition( "*", "Fail", "Failed" )
self:AddTransition( "", "", "" )
self:AddTransition( "", "", "" )
self:AddEndState( "Arrived" )
self:AddEndState( "Failed" )
self:SetStartState( "None" )
return self
end
--- Task Events
--- StateMachine callback function
-- @param #ACT_ROUTE self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ROUTE:onafterStart( ProcessUnit, Event, From, To )
self:__Route( 1 )
end
--- Check if the controllable has arrived.
-- @param #ACT_ROUTE self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @return #boolean
function ACT_ROUTE:onfuncHasArrived( ProcessUnit )
return false
end
--- StateMachine callback function
-- @param #ACT_ROUTE self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ROUTE:onbeforeRoute( ProcessUnit, Event, From, To )
if ProcessUnit:IsAlive() then
local HasArrived = self:onfuncHasArrived( ProcessUnit ) -- Polymorphic
if self.DisplayCount >= self.DisplayInterval then
self:T( { HasArrived = HasArrived } )
if not HasArrived then
self:__Report( 1 )
end
self.DisplayCount = 1
else
self.DisplayCount = self.DisplayCount + 1
end
self:T( { DisplayCount = self.DisplayCount } )
if HasArrived then
self:__Arrive( 1 )
else
self:__Route( 1 )
end
return HasArrived -- if false, then the event will not be executed...
end
return false
end
end -- ACT_ROUTE
do -- ACT_ROUTE_ZONE
--- ACT_ROUTE_ZONE class
-- @type ACT_ROUTE_ZONE
-- @field Tasking.Task#TASK TASK
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Zone#ZONE_BASE TargetZone
-- @extends #ACT_ROUTE
ACT_ROUTE_ZONE = {
ClassName = "ACT_ROUTE_ZONE",
}
--- Creates a new routing state machine. The task will route a controllable to a ZONE until the controllable is within that ZONE.
-- @param #ACT_ROUTE_ZONE self
-- @param Core.Zone#ZONE_BASE TargetZone
function ACT_ROUTE_ZONE:New( TargetZone )
local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_ZONE
self.TargetZone = TargetZone
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
return self
end
function ACT_ROUTE_ZONE:Init( FsmRoute )
self.TargetZone = FsmRoute.TargetZone
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
end
--- Method override to check if the controllable has arrived.
-- @param #ACT_ROUTE self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @return #boolean
function ACT_ROUTE_ZONE:onfuncHasArrived( ProcessUnit )
if ProcessUnit:IsInZone( self.TargetZone ) then
local RouteText = "You have arrived within the zone."
self:Message( RouteText )
end
return ProcessUnit:IsInZone( self.TargetZone )
end
--- Task Events
--- StateMachine callback function
-- @param #ACT_ROUTE_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ROUTE_ZONE:onenterReporting( ProcessUnit, Event, From, To )
local ZoneVec2 = self.TargetZone:GetVec2()
local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y )
local TaskUnitVec2 = ProcessUnit:GetVec2()
local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y )
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target."
self:Message( RouteText )
end
end -- ACT_ROUTE_ZONE

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@
--
-- 1.1) BASE constructor
-- ---------------------
-- Any class derived from BASE, must use the @{Base#BASE.New) constructor within the @{Base#BASE.Inherit) method.
-- See an example at the @{Base#BASE.New} method how this is done.
-- Any class derived from BASE, must use the @{Core.Base#BASE.New) constructor within the @{Core.Base#BASE.Inherit) method.
-- See an example at the @{Core.Base#BASE.New} method how this is done.
--
-- 1.2) BASE Trace functionality
-- -----------------------------
@ -90,24 +90,6 @@ FORMATION = {
--- The base constructor. This is the top top class of all classed defined within the MOOSE.
-- Any new class needs to be derived from this class for proper inheritance.
-- @param #BASE self
-- @return #BASE The new instance of the BASE class.
-- @usage
-- -- This declares the constructor of the class TASK, inheriting from BASE.
-- --- TASK constructor
-- -- @param #TASK self
-- -- @param Parameter The parameter of the New constructor.
-- -- @return #TASK self
-- function TASK:New( Parameter )
--
-- local self = BASE:Inherit( self, BASE:New() )
--
-- self.Variable = Parameter
--
-- return self
-- end
-- @todo need to investigate if the deepCopy is really needed... Don't think so.
function BASE:New()
local self = routines.utils.deepCopy( self ) -- Create a new self instance
@ -116,9 +98,40 @@ function BASE:New()
self.__index = self
_ClassID = _ClassID + 1
self.ClassID = _ClassID
return self
end
function BASE:_Destructor()
--self:E("_Destructor")
--self:EventRemoveAll()
end
function BASE:_SetDestructor()
-- TODO: Okay, this is really technical...
-- When you set a proxy to a table to catch __gc, weak tables don't behave like weak...
-- Therefore, I am parking this logic until I've properly discussed all this with the community.
--[[
local proxy = newproxy(true)
local proxyMeta = getmetatable(proxy)
proxyMeta.__gc = function ()
env.info("In __gc for " .. self:GetClassNameAndID() )
if self._Destructor then
self:_Destructor()
end
end
-- keep the userdata from newproxy reachable until the object
-- table is about to be garbage-collected - then the __gc hook
-- will be invoked and the destructor called
rawset( self, '__proxy', proxy )
--]]
end
--- This is the worker method to inherit from a parent class.
-- @param #BASE self
-- @param Child is the Child class that inherits.
@ -131,6 +144,8 @@ function BASE:Inherit( Child, Parent )
if Child ~= nil then
setmetatable( Child, Parent )
Child.__index = Child
Child:_SetDestructor()
end
--self:T( 'Inherited from ' .. Parent.ClassName )
return Child
@ -170,7 +185,7 @@ end
--- Set a new listener for the class.
-- @param self
-- @param DCSTypes#Event Event
-- @param Dcs.DCSTypes#Event Event
-- @param #function EventFunction
-- @return #BASE
function BASE:AddEvent( Event, EventFunction )
@ -186,12 +201,278 @@ end
--- Returns the event dispatcher
-- @param #BASE self
-- @return Event#EVENT
-- @return Core.Event#EVENT
function BASE:Event()
return _EVENTDISPATCHER
end
--- Remove all subscribed events
-- @param #BASE self
-- @return #BASE
function BASE:EventRemoveAll()
_EVENTDISPATCHER:RemoveAll( self )
return self
end
--- Subscribe to a S_EVENT_SHOT event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnShot( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_SHOT )
return self
end
--- Subscribe to a S_EVENT_HIT event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnHit( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_HIT )
return self
end
--- Subscribe to a S_EVENT_TAKEOFF event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnTakeOff( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_TAKEOFF )
return self
end
--- Subscribe to a S_EVENT_LAND event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnLand( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_LAND )
return self
end
--- Subscribe to a S_EVENT_CRASH event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnCrash( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_CRASH )
return self
end
--- Subscribe to a S_EVENT_EJECTION event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnEjection( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_EJECTION )
return self
end
--- Subscribe to a S_EVENT_REFUELING event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnRefueling( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_REFUELING )
return self
end
--- Subscribe to a S_EVENT_DEAD event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnDead( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_DEAD )
return self
end
--- Subscribe to a S_EVENT_PILOT_DEAD event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnPilotDead( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_PILOT_DEAD )
return self
end
--- Subscribe to a S_EVENT_BASE_CAPTURED event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnBaseCaptured( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_BASE_CAPTURED )
return self
end
--- Subscribe to a S_EVENT_MISSION_START event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnMissionStart( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_MISSION_START )
return self
end
--- Subscribe to a S_EVENT_MISSION_END event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnPlayerMissionEnd( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_MISSION_END )
return self
end
--- Subscribe to a S_EVENT_TOOK_CONTROL event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnTookControl( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_TOOK_CONTROL )
return self
end
--- Subscribe to a S_EVENT_REFUELING_STOP event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnRefuelingStop( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_REFUELING_STOP )
return self
end
--- Subscribe to a S_EVENT_BIRTH event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnBirth( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_BIRTH )
return self
end
--- Subscribe to a S_EVENT_HUMAN_FAILURE event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnHumanFailure( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_HUMAN_FAILURE )
return self
end
--- Subscribe to a S_EVENT_ENGINE_STARTUP event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnEngineStartup( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_ENGINE_STARTUP )
return self
end
--- Subscribe to a S_EVENT_ENGINE_SHUTDOWN event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnEngineShutdown( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_ENGINE_SHUTDOWN )
return self
end
--- Subscribe to a S_EVENT_PLAYER_ENTER_UNIT event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnPlayerEnterUnit( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_PLAYER_ENTER_UNIT )
return self
end
--- Subscribe to a S_EVENT_PLAYER_LEAVE_UNIT event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnPlayerLeaveUnit( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
return self
end
--- Subscribe to a S_EVENT_PLAYER_COMMENT event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnPlayerComment( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_PLAYER_COMMENT )
return self
end
--- Subscribe to a S_EVENT_SHOOTING_START event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnShootingStart( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_SHOOTING_START )
return self
end
--- Subscribe to a S_EVENT_SHOOTING_END event.
-- @param #BASE self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @return #BASE
function BASE:EventOnShootingEnd( EventFunction )
_EVENTDISPATCHER:OnEventGeneric( EventFunction, self, world.event.S_EVENT_SHOOTING_END )
return self
end
@ -268,8 +549,8 @@ local BaseEventCodes = {
--- Creation of a Birth Event.
-- @param #BASE self
-- @param DCSTypes#Time EventTime The time stamp of the event.
-- @param DCSObject#Object Initiator The initiating object of the event.
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event.
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event.
-- @param #string IniUnitName The initiating unit name.
-- @param place
-- @param subplace
@ -290,8 +571,8 @@ end
--- Creation of a Crash Event.
-- @param #BASE self
-- @param DCSTypes#Time EventTime The time stamp of the event.
-- @param DCSObject#Object Initiator The initiating object of the event.
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event.
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event.
function BASE:CreateEventCrash( EventTime, Initiator )
self:F( { EventTime, Initiator } )
@ -304,10 +585,10 @@ function BASE:CreateEventCrash( EventTime, Initiator )
world.onEvent( Event )
end
-- TODO: Complete DCSTypes#Event structure.
-- TODO: Complete Dcs.DCSTypes#Event structure.
--- The main event handling function... This function captures all events generated for the class.
-- @param #BASE self
-- @param DCSTypes#Event event
-- @param Dcs.DCSTypes#Event event
function BASE:onEvent(event)
--self:F( { BaseEventCodes[event.id], event } )
@ -350,7 +631,7 @@ function BASE:GetState( Object, StateName )
local ClassNameAndID = Object:GetClassNameAndID()
if self.States[ClassNameAndID] then
local State = self.States[ClassNameAndID][StateName]
local State = self.States[ClassNameAndID][StateName] or false
self:T2( { ClassNameAndID, StateName, State } )
return State
end

View File

@ -2,7 +2,7 @@
--
-- ====
--
-- 1) @{Database#DATABASE} class, extends @{Base#BASE}
-- 1) @{Core.Database#DATABASE} class, extends @{Core.Base#BASE}
-- ===================================================
-- Mission designers can use the DATABASE class to refer to:
--
@ -38,7 +38,7 @@
--- DATABASE class
-- @type DATABASE
-- @extends Base#BASE
-- @extends Core.Base#BASE
DATABASE = {
ClassName = "DATABASE",
Templates = {
@ -106,7 +106,7 @@ end
--- Finds a Unit based on the Unit Name.
-- @param #DATABASE self
-- @param #string UnitName
-- @return Unit#UNIT The found Unit.
-- @return Wrapper.Unit#UNIT The found Unit.
function DATABASE:FindUnit( UnitName )
local UnitFound = self.UNITS[UnitName]
@ -154,7 +154,7 @@ end
--- Finds a STATIC based on the StaticName.
-- @param #DATABASE self
-- @param #string StaticName
-- @return Static#STATIC The found STATIC.
-- @return Wrapper.Static#STATIC The found STATIC.
function DATABASE:FindStatic( StaticName )
local StaticFound = self.STATICS[StaticName]
@ -181,7 +181,7 @@ end
--- Finds a AIRBASE based on the AirbaseName.
-- @param #DATABASE self
-- @param #string AirbaseName
-- @return Airbase#AIRBASE The found AIRBASE.
-- @return Wrapper.Airbase#AIRBASE The found AIRBASE.
function DATABASE:FindAirbase( AirbaseName )
local AirbaseFound = self.AIRBASES[AirbaseName]
@ -192,7 +192,7 @@ end
--- Finds a CLIENT based on the ClientName.
-- @param #DATABASE self
-- @param #string ClientName
-- @return Client#CLIENT The found CLIENT.
-- @return Wrapper.Client#CLIENT The found CLIENT.
function DATABASE:FindClient( ClientName )
local ClientFound = self.CLIENTS[ClientName]
@ -215,7 +215,7 @@ end
--- Finds a GROUP based on the GroupName.
-- @param #DATABASE self
-- @param #string GroupName
-- @return Group#GROUP The found GROUP.
-- @return Wrapper.Group#GROUP The found GROUP.
function DATABASE:FindGroup( GroupName )
local GroupFound = self.GROUPS[GroupName]
@ -535,7 +535,7 @@ end
--- Handles the OnBirth event for the alive units set.
-- @param #DATABASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnBirth( Event )
self:F2( { Event } )
@ -549,7 +549,7 @@ end
--- Handles the OnDead or OnCrash event for alive units set.
-- @param #DATABASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnDeadOrCrash( Event )
self:F2( { Event } )
@ -564,7 +564,7 @@ end
--- Handles the OnPlayerEnterUnit event to fill the active players table (with the unit filter applied).
-- @param #DATABASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnPlayerEnterUnit( Event )
self:F2( { Event } )
@ -579,7 +579,7 @@ end
--- Handles the OnPlayerLeaveUnit event to clean the active players table.
-- @param #DATABASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnPlayerLeaveUnit( Event )
self:F2( { Event } )

View File

@ -1,6 +1,19 @@
--- The EVENT class models an efficient event handling process between other classes and its units, weapons.
--- This module contains the EVENT class.
--
-- ===
--
-- Takes care of EVENT dispatching between DCS events and event handling functions defined in MOOSE classes.
--
-- ===
--
-- The above menus classes **are derived** from 2 main **abstract** classes defined within the MOOSE framework (so don't use these):
--
-- ===
--
-- ### Contributions: -
-- ### Authors: FlightControl : Design & Programming
--
-- @module Event
-- @author FlightControl
--- The EVENT structure
-- @type EVENT
@ -45,13 +58,13 @@ local _EVENTCODES = {
-- @field weapon
-- @field IniDCSUnit
-- @field IniDCSUnitName
-- @field Unit#UNIT IniUnit
-- @field Wrapper.Unit#UNIT IniUnit
-- @field #string IniUnitName
-- @field IniDCSGroup
-- @field IniDCSGroupName
-- @field TgtDCSUnit
-- @field TgtDCSUnitName
-- @field Unit#UNIT TgtUnit
-- @field Wrapper.Unit#UNIT TgtUnit
-- @field #string TgtUnitName
-- @field TgtDCSGroup
-- @field TgtDCSGroupName
@ -80,45 +93,62 @@ end
--- Initializes the Events structure for the event
-- @param #EVENT self
-- @param DCSWorld#world.event EventID
-- @param #string EventClass
-- @param Dcs.DCSWorld#world.event EventID
-- @param Core.Base#BASE EventClass
-- @return #EVENT.Events
function EVENT:Init( EventID, EventClass )
self:F3( { _EVENTCODES[EventID], EventClass } )
if not self.Events[EventID] then
self.Events[EventID] = {}
if not self.Events[EventID] then
-- Create a WEAK table to ensure that the garbage collector is cleaning the event links when the object usage is cleaned.
self.Events[EventID] = setmetatable( {}, { __mode = "k" } )
end
if not self.Events[EventID][EventClass] then
self.Events[EventID][EventClass] = {}
self.Events[EventID][EventClass] = setmetatable( {}, { __mode = "k" } )
end
return self.Events[EventID][EventClass]
end
--- Removes an Events entry
-- @param #EVENT self
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param DCSWorld#world.event EventID
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID
-- @return #EVENT.Events
function EVENT:Remove( EventSelf, EventID )
self:F3( { EventSelf, _EVENTCODES[EventID] } )
function EVENT:Remove( EventClass, EventID )
self:F3( { EventClass, _EVENTCODES[EventID] } )
local EventClass = EventSelf:GetClassNameAndID()
local EventClass = EventClass
self.Events[EventID][EventClass] = nil
end
--- Clears all event subscriptions for a @{Core.Base#BASE} derived object.
-- @param #EVENT self
-- @param Core.Base#BASE EventObject
function EVENT:RemoveAll( EventObject )
self:F3( { EventObject:GetClassNameAndID() } )
local EventClass = EventObject:GetClassNameAndID()
for EventID, EventData in pairs( self.Events ) do
self.Events[EventID][EventClass] = nil
end
end
--- Create an OnDead event handler for a group
-- @param #EVENT self
-- @param #table EventTemplate
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param EventSelf The self instance of the class for which the event is.
-- @param EventClass The instance of the class for which the event is.
-- @param #function OnEventFunction
-- @return #EVENT
function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, OnEventFunction )
function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventClass, OnEventFunction )
self:F2( EventTemplate.name )
for EventUnitID, EventUnit in pairs( EventTemplate.units ) do
OnEventFunction( self, EventUnit.name, EventFunction, EventSelf )
OnEventFunction( self, EventUnit.name, EventFunction, EventClass )
end
return self
end
@ -126,15 +156,15 @@ end
--- Set a new listener for an S_EVENT_X event independent from a unit or a weapon.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is captured. When the event happens, the event process will be called in this class provided.
-- @param EventID
-- @return #EVENT
function EVENT:OnEventGeneric( EventFunction, EventSelf, EventID )
function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
self:F2( { EventID } )
local Event = self:Init( EventID, EventSelf:GetClassNameAndID() )
local Event = self:Init( EventID, EventClass )
Event.EventFunction = EventFunction
Event.EventSelf = EventSelf
Event.EventClass = EventClass
return self
end
@ -143,19 +173,19 @@ end
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param EventID
-- @return #EVENT
function EVENT:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, EventID )
function EVENT:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, EventID )
self:F2( EventDCSUnitName )
local Event = self:Init( EventID, EventSelf:GetClassNameAndID() )
local Event = self:Init( EventID, EventClass )
if not Event.IniUnit then
Event.IniUnit = {}
end
Event.IniUnit[EventDCSUnitName] = {}
Event.IniUnit[EventDCSUnitName].EventFunction = EventFunction
Event.IniUnit[EventDCSUnitName].EventSelf = EventSelf
Event.IniUnit[EventDCSUnitName].EventClass = EventClass
return self
end
@ -163,14 +193,14 @@ do -- OnBirth
--- Create an OnBirth event handler for a group
-- @param #EVENT self
-- @param Group#GROUP EventGroup
-- @param Wrapper.Group#GROUP EventGroup
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param EventSelf The self instance of the class for which the event is.
-- @param EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventSelf )
function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnBirthForUnit )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnBirthForUnit )
return self
end
@ -178,12 +208,12 @@ do -- OnBirth
--- Set a new listener for an S_EVENT_BIRTH event, and registers the unit born.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnBirth( EventFunction, EventSelf )
function EVENT:OnBirth( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_BIRTH )
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_BIRTH )
return self
end
@ -192,24 +222,24 @@ do -- OnBirth
-- @param #EVENT self
-- @param #string EventDCSUnitName The id of the unit for the event to be handled.
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnBirthForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnBirthForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_BIRTH )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_BIRTH )
return self
end
--- Stop listening to S_EVENT_BIRTH event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnBirthRemove( EventSelf )
function EVENT:OnBirthRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_BIRTH )
self:Remove( EventClass, world.event.S_EVENT_BIRTH )
return self
end
@ -221,14 +251,14 @@ do -- OnCrash
--- Create an OnCrash event handler for a group
-- @param #EVENT self
-- @param Group#GROUP EventGroup
-- @param Wrapper.Group#GROUP EventGroup
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param EventSelf The self instance of the class for which the event is.
-- @param EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventSelf )
function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnCrashForUnit )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnCrashForUnit )
return self
end
@ -236,12 +266,12 @@ do -- OnCrash
--- Set a new listener for an S_EVENT_CRASH event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnCrash( EventFunction, EventSelf )
function EVENT:OnCrash( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_CRASH )
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_CRASH )
return self
end
@ -250,24 +280,24 @@ do -- OnCrash
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnCrashForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnCrashForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_CRASH )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_CRASH )
return self
end
--- Stop listening to S_EVENT_CRASH event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnCrashRemove( EventSelf )
function EVENT:OnCrashRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_CRASH )
self:Remove( EventClass, world.event.S_EVENT_CRASH )
return self
end
@ -278,14 +308,14 @@ do -- OnDead
--- Create an OnDead event handler for a group
-- @param #EVENT self
-- @param Group#GROUP EventGroup
-- @param Wrapper.Group#GROUP EventGroup
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param EventSelf The self instance of the class for which the event is.
-- @param EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventSelf )
function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnDeadForUnit )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnDeadForUnit )
return self
end
@ -293,12 +323,12 @@ do -- OnDead
--- Set a new listener for an S_EVENT_DEAD event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnDead( EventFunction, EventSelf )
function EVENT:OnDead( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_DEAD )
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_DEAD )
return self
end
@ -308,24 +338,24 @@ do -- OnDead
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnDeadForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnDeadForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_DEAD )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_DEAD )
return self
end
--- Stop listening to S_EVENT_DEAD event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnDeadRemove( EventSelf )
function EVENT:OnDeadRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_DEAD )
self:Remove( EventClass, world.event.S_EVENT_DEAD )
return self
end
@ -338,12 +368,12 @@ do -- OnPilotDead
--- Set a new listener for an S_EVENT_PILOT_DEAD event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnPilotDead( EventFunction, EventSelf )
function EVENT:OnPilotDead( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_PILOT_DEAD )
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PILOT_DEAD )
return self
end
@ -352,24 +382,24 @@ do -- OnPilotDead
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnPilotDeadForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnPilotDeadForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_PILOT_DEAD )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_PILOT_DEAD )
return self
end
--- Stop listening to S_EVENT_PILOT_DEAD event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnPilotDeadRemove( EventSelf )
function EVENT:OnPilotDeadRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_PILOT_DEAD )
self:Remove( EventClass, world.event.S_EVENT_PILOT_DEAD )
return self
end
@ -381,12 +411,12 @@ do -- OnLand
-- @param #EVENT self
-- @param #table EventTemplate
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param EventSelf The self instance of the class for which the event is.
-- @param EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventSelf )
function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnLandForUnit )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnLandForUnit )
return self
end
@ -395,24 +425,24 @@ do -- OnLand
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnLandForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnLandForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_LAND )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_LAND )
return self
end
--- Stop listening to S_EVENT_LAND event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnLandRemove( EventSelf )
function EVENT:OnLandRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_LAND )
self:Remove( EventClass, world.event.S_EVENT_LAND )
return self
end
@ -425,12 +455,12 @@ do -- OnTakeOff
-- @param #EVENT self
-- @param #table EventTemplate
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param EventSelf The self instance of the class for which the event is.
-- @param EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventSelf )
function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnTakeOffForUnit )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnTakeOffForUnit )
return self
end
@ -439,24 +469,24 @@ do -- OnTakeOff
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnTakeOffForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnTakeOffForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_TAKEOFF )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_TAKEOFF )
return self
end
--- Stop listening to S_EVENT_TAKEOFF event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnTakeOffRemove( EventSelf )
function EVENT:OnTakeOffRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_TAKEOFF )
self:Remove( EventClass, world.event.S_EVENT_TAKEOFF )
return self
end
@ -470,12 +500,12 @@ do -- OnEngineShutDown
-- @param #EVENT self
-- @param #table EventTemplate
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param EventSelf The self instance of the class for which the event is.
-- @param EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventSelf )
function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventClass )
self:F2( EventTemplate.name )
self:OnEventForTemplate( EventTemplate, EventFunction, EventSelf, self.OnEngineShutDownForUnit )
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnEngineShutDownForUnit )
return self
end
@ -484,24 +514,24 @@ do -- OnEngineShutDown
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnEngineShutDownForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnEngineShutDownForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_ENGINE_SHUTDOWN )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_ENGINE_SHUTDOWN )
return self
end
--- Stop listening to S_EVENT_ENGINE_SHUTDOWN event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnEngineShutDownRemove( EventSelf )
function EVENT:OnEngineShutDownRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_ENGINE_SHUTDOWN )
self:Remove( EventClass, world.event.S_EVENT_ENGINE_SHUTDOWN )
return self
end
@ -514,24 +544,24 @@ do -- OnEngineStartUp
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnEngineStartUpForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnEngineStartUpForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_ENGINE_STARTUP )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_ENGINE_STARTUP )
return self
end
--- Stop listening to S_EVENT_ENGINE_STARTUP event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnEngineStartUpRemove( EventSelf )
function EVENT:OnEngineStartUpRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_ENGINE_STARTUP )
self:Remove( EventClass, world.event.S_EVENT_ENGINE_STARTUP )
return self
end
@ -542,12 +572,12 @@ do -- OnShot
--- Set a new listener for an S_EVENT_SHOT event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnShot( EventFunction, EventSelf )
function EVENT:OnShot( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_SHOT )
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_SHOT )
return self
end
@ -556,24 +586,24 @@ do -- OnShot
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnShotForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnShotForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_SHOT )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_SHOT )
return self
end
--- Stop listening to S_EVENT_SHOT event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnShotRemove( EventSelf )
function EVENT:OnShotRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_SHOT )
self:Remove( EventClass, world.event.S_EVENT_SHOT )
return self
end
@ -586,12 +616,12 @@ do -- OnHit
--- Set a new listener for an S_EVENT_HIT event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnHit( EventFunction, EventSelf )
function EVENT:OnHit( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_HIT )
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_HIT )
return self
end
@ -600,24 +630,24 @@ do -- OnHit
-- @param #EVENT self
-- @param #string EventDCSUnitName
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnHitForUnit( EventDCSUnitName, EventFunction, EventSelf )
function EVENT:OnHitForUnit( EventDCSUnitName, EventFunction, EventClass )
self:F2( EventDCSUnitName )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventSelf, world.event.S_EVENT_HIT )
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_HIT )
return self
end
--- Stop listening to S_EVENT_HIT event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnHitRemove( EventSelf )
function EVENT:OnHitRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_HIT )
self:Remove( EventClass, world.event.S_EVENT_HIT )
return self
end
@ -629,24 +659,24 @@ do -- OnPlayerEnterUnit
--- Set a new listener for an S_EVENT_PLAYER_ENTER_UNIT event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnPlayerEnterUnit( EventFunction, EventSelf )
function EVENT:OnPlayerEnterUnit( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_PLAYER_ENTER_UNIT )
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PLAYER_ENTER_UNIT )
return self
end
--- Stop listening to S_EVENT_PLAYER_ENTER_UNIT event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnPlayerEnterRemove( EventSelf )
function EVENT:OnPlayerEnterRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_PLAYER_ENTER_UNIT )
self:Remove( EventClass, world.event.S_EVENT_PLAYER_ENTER_UNIT )
return self
end
@ -657,24 +687,24 @@ do -- OnPlayerLeaveUnit
--- Set a new listener for an S_EVENT_PLAYER_LEAVE_UNIT event.
-- @param #EVENT self
-- @param #function EventFunction The function to be called when the event occurs for the unit.
-- @param Base#BASE EventSelf The self instance of the class for which the event is.
-- @param Base#BASE EventClass The self instance of the class for which the event is.
-- @return #EVENT
function EVENT:OnPlayerLeaveUnit( EventFunction, EventSelf )
function EVENT:OnPlayerLeaveUnit( EventFunction, EventClass )
self:F2()
self:OnEventGeneric( EventFunction, EventSelf, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
return self
end
--- Stop listening to S_EVENT_PLAYER_LEAVE_UNIT event.
-- @param #EVENT self
-- @param Base#BASE EventSelf
-- @param Base#BASE EventClass
-- @return #EVENT
function EVENT:OnPlayerLeaveRemove( EventSelf )
function EVENT:OnPlayerLeaveRemove( EventClass )
self:F2()
self:Remove( EventSelf, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
self:Remove( EventClass, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
return self
end
@ -694,6 +724,10 @@ function EVENT:onEvent( Event )
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = UNIT:FindByName( Event.IniDCSUnitName )
if not Event.IniUnit then
-- Unit can be a CLIENT. Most likely this will be the case ...
Event.IniUnit = CLIENT:FindByName( Event.IniDCSUnitName, '', true )
end
Event.IniDCSGroupName = ""
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
@ -717,16 +751,21 @@ function EVENT:onEvent( Event )
Event.WeaponName = Event.Weapon:getTypeName()
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
end
self:E( { _EVENTCODES[Event.id], Event.initiator, Event.IniDCSUnitName, Event.target, Event.TgtDCSUnitName, Event.weapon, Event.WeaponName } )
for ClassName, EventData in pairs( self.Events[Event.id] ) do
self:E( { _EVENTCODES[Event.id], Event, Event.IniDCSUnitName, Event.TgtDCSUnitName } )
-- Okay, we got the event from DCS. Now loop the self.Events[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
for EventClass, EventData in pairs( self.Events[Event.id] ) do
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
if Event.IniDCSUnitName and EventData.IniUnit and EventData.IniUnit[Event.IniDCSUnitName] then
self:T( { "Calling event function for class ", ClassName, " unit ", Event.IniUnitName } )
EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventSelf, Event )
self:T( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName } )
EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event )
else
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
if Event.IniDCSUnit and not EventData.IniUnit then
if ClassName == EventData.EventSelf:GetClassNameAndID() then
self:T( { "Calling event function for class ", ClassName } )
EventData.EventFunction( EventData.EventSelf, Event )
if EventClass == EventData.EventClass then
self:T( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID() } )
EventData.EventFunction( EventData.EventClass, Event )
end
end
end

View File

@ -0,0 +1,729 @@
--- This module contains the FSM class.
-- This development is based on a state machine implementation made by Conroy Kyle.
-- The state machine can be found here: https://github.com/kyleconroy/lua-state-machine
--
-- I've taken the development and enhanced it to make the state machine hierarchical...
-- It is a fantastic development, this module.
--
-- ===
--
-- 1) @{Workflow#FSM} class, extends @{Core.Base#BASE}
-- ==============================================
--
-- 1.1) Add or remove objects from the FSM
-- --------------------------------------------
-- @module Fsm
-- @author FlightControl
do -- FSM
--- FSM class
-- @type FSM
-- @extends Core.Base#BASE
FSM = {
ClassName = "FSM",
}
--- Creates a new FSM object.
-- @param #FSM self
-- @return #FSM
function FSM:New( FsmT )
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() )
self.options = options or {}
self.options.subs = self.options.subs or {}
self.current = self.options.initial or 'none'
self.Events = {}
self.subs = {}
self.endstates = {}
self.Scores = {}
self._StartState = "none"
self._Transitions = {}
self._Processes = {}
self._EndStates = {}
self._Scores = {}
self.CallScheduler = SCHEDULER:New( self )
return self
end
function FSM:SetStartState( State )
self._StartState = State
self.current = State
end
function FSM:GetStartState()
return self._StartState or {}
end
function FSM:AddTransition( From, Event, To )
local Transition = {}
Transition.From = From
Transition.Event = Event
Transition.To = To
self:E( Transition )
self._Transitions[Transition] = Transition
self:_eventmap( self.Events, Transition )
end
function FSM:GetTransitions()
return self._Transitions or {}
end
--- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Controllable} by the task.
-- @return Core.Fsm#FSM_PROCESS
function FSM:AddProcess( From, Event, Process, ReturnEvents )
self:E( { From, Event, Process, ReturnEvents } )
local Sub = {}
Sub.From = From
Sub.Event = Event
Sub.fsm = Process
Sub.StartEvent = "Start"
Sub.ReturnEvents = ReturnEvents
self._Processes[Sub] = Sub
self:_submap( self.subs, Sub, nil )
self:AddTransition( From, Event, From )
return Process
end
function FSM:GetProcesses()
return self._Processes or {}
end
function FSM:GetProcess( From, Event )
for ProcessID, Process in pairs( self:GetProcesses() ) do
if Process.From == From and Process.Event == Event then
self:E( Process )
return Process.fsm
end
end
error( "Sub-Process from state " .. From .. " with event " .. Event .. " not found!" )
end
function FSM:AddEndState( State )
self._EndStates[State] = State
self.endstates[State] = State
end
function FSM:GetEndStates()
return self._EndStates or {}
end
--- Adds a score for the FSM to be achieved.
-- @param #FSM self
-- @param #string State is the state of the process when the score needs to be given. (See the relevant state descriptions of the process).
-- @param #string ScoreText is a text describing the score that is given according the status.
-- @param #number Score is a number providing the score of the status.
-- @return #FSM self
function FSM:AddScore( State, ScoreText, Score )
self:F2( { State, ScoreText, Score } )
self._Scores[State] = self._Scores[State] or {}
self._Scores[State].ScoreText = ScoreText
self._Scores[State].Score = Score
return self
end
--- Adds a score for the FSM_PROCESS to be achieved.
-- @param #FSM self
-- @param #string From is the From State of the main process.
-- @param #string Event is the Event of the main process.
-- @param #string State is the state of the process when the score needs to be given. (See the relevant state descriptions of the process).
-- @param #string ScoreText is a text describing the score that is given according the status.
-- @param #number Score is a number providing the score of the status.
-- @return #FSM self
function FSM:AddScoreProcess( From, Event, State, ScoreText, Score )
self:F2( { Event, State, ScoreText, Score } )
local Process = self:GetProcess( From, Event )
self:E( { Process = Process._Name, Scores = Process._Scores, State = State, ScoreText = ScoreText, Score = Score } )
Process._Scores[State] = Process._Scores[State] or {}
Process._Scores[State].ScoreText = ScoreText
Process._Scores[State].Score = Score
return Process
end
function FSM:GetScores()
return self._Scores or {}
end
function FSM:GetSubs()
return self.options.subs
end
function FSM:LoadCallBacks( CallBackTable )
for name, callback in pairs( CallBackTable or {} ) do
self[name] = callback
end
end
function FSM:_eventmap( Events, EventStructure )
local Event = EventStructure.Event
local __Event = "__" .. EventStructure.Event
self[Event] = self[Event] or self:_create_transition(Event)
self[__Event] = self[__Event] or self:_delayed_transition(Event)
self:T( "Added methods: " .. Event .. ", " .. __Event )
Events[Event] = self.Events[Event] or { map = {} }
self:_add_to_map( Events[Event].map, EventStructure )
end
function FSM:_submap( subs, sub, name )
self:F( { sub = sub, name = name } )
subs[sub.From] = subs[sub.From] or {}
subs[sub.From][sub.Event] = subs[sub.From][sub.Event] or {}
-- Make the reference table weak.
-- setmetatable( subs[sub.From][sub.Event], { __mode = "k" } )
subs[sub.From][sub.Event][sub] = {}
subs[sub.From][sub.Event][sub].fsm = sub.fsm
subs[sub.From][sub.Event][sub].StartEvent = sub.StartEvent
subs[sub.From][sub.Event][sub].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
subs[sub.From][sub.Event][sub].name = name
subs[sub.From][sub.Event][sub].fsmparent = self
end
function FSM:_call_handler(handler, params)
if self[handler] then
self:E( "Calling " .. handler )
return self[handler]( self, unpack(params) )
end
end
function FSM._handler( self, EventName, ... )
self:E( { EventName, ... } )
local can, to = self:can( EventName )
self:E( { EventName, self.current, can, to } )
local ReturnValues = nil
if can then
local from = self.current
local params = { EventName, from, to, ... }
if self:_call_handler("onbefore" .. EventName, params) == false
or self:_call_handler("onleave" .. from, params) == false then
return false
end
self.current = to
local execute = true
local subtable = self:_gosub( from, EventName )
for _, sub in pairs( subtable ) do
--if sub.nextevent then
-- self:F2( "nextevent = " .. sub.nextevent )
-- self[sub.nextevent]( self )
--end
self:E( "calling sub start event: " .. sub.StartEvent )
sub.fsm.fsmparent = self
sub.fsm.ReturnEvents = sub.ReturnEvents
sub.fsm[sub.StartEvent]( sub.fsm )
execute = true
end
local fsmparent, Event = self:_isendstate( to )
if fsmparent and Event then
self:F2( { "end state: ", fsmparent, Event } )
self:_call_handler("onenter" .. to, params)
self:_call_handler("onafter" .. EventName, params)
self:_call_handler("onstatechange", params)
fsmparent[Event]( fsmparent )
execute = false
end
if execute then
-- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute!
if from ~= to then
self:T3( { onenter = "onenter" .. to, callback = self["onenter" .. to] } )
self:_call_handler("onenter" .. to, params)
end
self:T3( { On = "OnBefore" .. to, callback = self["OnBefore" .. to] } )
if ( self:_call_handler("OnBefore" .. to, params ) ~= false ) then
self:T3( { onafter = "onafter" .. EventName, callback = self["onafter" .. EventName] } )
self:_call_handler("onafter" .. EventName, params)
self:T3( { On = "OnAfter" .. to, callback = self["OnAfter" .. to] } )
ReturnValues = self:_call_handler("OnAfter" .. to, params )
end
self:_call_handler("onstatechange", params)
end
return ReturnValues
end
return nil
end
function FSM:_delayed_transition( EventName )
self:E( { EventName = EventName } )
return function( self, DelaySeconds, ... )
self:T( "Delayed Event: " .. EventName )
local CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1 )
self:T( { CallID = CallID } )
end
end
function FSM:_create_transition( EventName )
self:E( { Event = EventName } )
return function( self, ... ) return self._handler( self, EventName , ... ) end
end
function FSM:_gosub( ParentFrom, ParentEvent )
local fsmtable = {}
if self.subs[ParentFrom] and self.subs[ParentFrom][ParentEvent] then
self:E( { ParentFrom, ParentEvent, self.subs[ParentFrom], self.subs[ParentFrom][ParentEvent] } )
return self.subs[ParentFrom][ParentEvent]
else
return {}
end
end
function FSM:_isendstate( Current )
local FSMParent = self.fsmparent
if FSMParent and self.endstates[Current] then
self:E( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } )
FSMParent.current = Current
local ParentFrom = FSMParent.current
self:E( ParentFrom )
self:E( self.ReturnEvents )
local Event = self.ReturnEvents[Current]
self:E( { ParentFrom, Event, self.ReturnEvents } )
if Event then
return FSMParent, Event
else
self:E( { "Could not find parent event name for state ", ParentFrom } )
end
end
return nil
end
function FSM:_add_to_map( Map, Event )
self:F3( { Map, Event } )
if type(Event.From) == 'string' then
Map[Event.From] = Event.To
else
for _, From in ipairs(Event.From) do
Map[From] = Event.To
end
end
self:T3( { Map, Event } )
end
function FSM:GetState()
return self.current
end
function FSM:Is( State )
return self.current == State
end
function FSM:is(state)
return self.current == state
end
function FSM:can(e)
self:E( { e, self.Events, self.Events[e] } )
local Event = self.Events[e]
self:F3( { self.current, Event } )
local To = Event and Event.map[self.current] or Event.map['*']
return To ~= nil, To
end
function FSM:cannot(e)
return not self:can(e)
end
end
do -- FSM_CONTROLLABLE
--- FSM_CONTROLLABLE class
-- @type FSM_CONTROLLABLE
-- @field Wrapper.Controllable#CONTROLLABLE Controllable
-- @extends Core.Fsm#FSM
FSM_CONTROLLABLE = {
ClassName = "FSM_CONTROLLABLE",
}
--- Creates a new FSM_CONTROLLABLE object.
-- @param #FSM_CONTROLLABLE self
-- @param #table FSMT Finite State Machine Table
-- @param Wrapper.Controllable#CONTROLLABLE Controllable (optional) The CONTROLLABLE object that the FSM_CONTROLLABLE governs.
-- @return #FSM_CONTROLLABLE
function FSM_CONTROLLABLE:New( FSMT, Controllable )
-- Inherits from BASE
local self = BASE:Inherit( self, FSM:New( FSMT ) ) -- Core.Fsm#FSM_CONTROLLABLE
if Controllable then
self:SetControllable( Controllable )
end
return self
end
--- Sets the CONTROLLABLE object that the FSM_CONTROLLABLE governs.
-- @param #FSM_CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE FSMControllable
-- @return #FSM_CONTROLLABLE
function FSM_CONTROLLABLE:SetControllable( FSMControllable )
self:F( FSMControllable )
self.Controllable = FSMControllable
end
--- Gets the CONTROLLABLE object that the FSM_CONTROLLABLE governs.
-- @param #FSM_CONTROLLABLE self
-- @return Wrapper.Controllable#CONTROLLABLE
function FSM_CONTROLLABLE:GetControllable()
return self.Controllable
end
function FSM_CONTROLLABLE:_call_handler( handler, params )
local ErrorHandler = function( errmsg )
env.info( "Error in SCHEDULER function:" .. errmsg )
if debug ~= nil then
env.info( debug.traceback() )
end
return errmsg
end
if self[handler] then
self:E( "Calling " .. handler )
return xpcall( function() return self[handler]( self, self.Controllable, unpack( params ) ) end, ErrorHandler )
--return self[handler]( self, self.Controllable, unpack( params ) )
end
end
end
do -- FSM_PROCESS
--- FSM_PROCESS class
-- @type FSM_PROCESS
-- @field Tasking.Task#TASK Task
-- @extends Core.Fsm#FSM_CONTROLLABLE
FSM_PROCESS = {
ClassName = "FSM_PROCESS",
}
--- Creates a new FSM_PROCESS object.
-- @param #FSM_PROCESS self
-- @return #FSM_PROCESS
function FSM_PROCESS:New( Controllable, Task )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- Core.Fsm#FSM_PROCESS
self:F( Controllable, Task )
self:Assign( Controllable, Task )
return self
end
function FSM_PROCESS:Init( FsmProcess )
self:E( "No Initialisation" )
end
--- Creates a new FSM_PROCESS object based on this FSM_PROCESS.
-- @param #FSM_PROCESS self
-- @return #FSM_PROCESS
function FSM_PROCESS:Copy( Controllable, Task )
self:E( { self:GetClassNameAndID() } )
local NewFsm = self:New( Controllable, Task ) -- Core.Fsm#FSM_PROCESS
NewFsm:Assign( Controllable, Task )
-- Polymorphic call to initialize the new FSM_PROCESS based on self FSM_PROCESS
NewFsm:Init( self )
-- Set Start State
NewFsm:SetStartState( self:GetStartState() )
-- Copy Transitions
for TransitionID, Transition in pairs( self:GetTransitions() ) do
NewFsm:AddTransition( Transition.From, Transition.Event, Transition.To )
end
-- Copy Processes
for ProcessID, Process in pairs( self:GetProcesses() ) do
self:E( { Process} )
local FsmProcess = NewFsm:AddProcess( Process.From, Process.Event, Process.fsm:Copy( Controllable, Task ), Process.ReturnEvents )
end
-- Copy End States
for EndStateID, EndState in pairs( self:GetEndStates() ) do
self:E( EndState )
NewFsm:AddEndState( EndState )
end
-- Copy the score tables
for ScoreID, Score in pairs( self:GetScores() ) do
self:E( Score )
NewFsm:AddScore( ScoreID, Score.ScoreText, Score.Score )
end
return NewFsm
end
--- Sets the task of the process.
-- @param #FSM_PROCESS self
-- @param Tasking.Task#TASK Task
-- @return #FSM_PROCESS
function FSM_PROCESS:SetTask( Task )
self.Task = Task
return self
end
--- Gets the task of the process.
-- @param #FSM_PROCESS self
-- @return Tasking.Task#TASK
function FSM_PROCESS:GetTask()
return self.Task
end
--- Gets the mission of the process.
-- @param #FSM_PROCESS self
-- @return Tasking.Mission#MISSION
function FSM_PROCESS:GetMission()
return self.Task.Mission
end
--- Gets the mission of the process.
-- @param #FSM_PROCESS self
-- @return Tasking.CommandCenter#COMMANDCENTER
function FSM_PROCESS:GetCommandCenter()
return self:GetTask():GetMission():GetCommandCenter()
end
--- Send a message of the @{Task} to the Group of the Unit.
-- @param #FSM_PROCESS self
function FSM_PROCESS:Message( Message )
self:F( { Message = Message } )
local CC = self:GetCommandCenter()
local TaskGroup = self.Controllable:GetGroup()
CC:MessageToGroup( Message, TaskGroup )
end
--- Assign the process to a @{Unit} and activate the process.
-- @param #FSM_PROCESS self
-- @param Task.Tasking#TASK Task
-- @param Wrapper.Unit#UNIT ProcessUnit
-- @return #FSM_PROCESS self
function FSM_PROCESS:Assign( ProcessUnit, Task )
self:E( { Task, ProcessUnit } )
self:SetControllable( ProcessUnit )
self:SetTask( Task )
--self.ProcessGroup = ProcessUnit:GetGroup()
return self
end
--- Adds a score for the FSM_PROCESS to be achieved.
-- @param #FSM_PROCESS self
-- @param #string State is the state of the process when the score needs to be given. (See the relevant state descriptions of the process).
-- @param #string ScoreText is a text describing the score that is given according the status.
-- @param #number Score is a number providing the score of the status.
-- @return #FSM_PROCESS self
function FSM_PROCESS:AddScore( State, ScoreText, Score )
self:F2( { State, ScoreText, Score } )
self.Scores[State] = self.Scores[State] or {}
self.Scores[State].ScoreText = ScoreText
self.Scores[State].Score = Score
return self
end
function FSM_PROCESS:onenterAssigned( ProcessUnit )
self:E( "Assign" )
self.Task:Assign()
end
function FSM_PROCESS:onenterFailed( ProcessUnit )
self:E( "Failed" )
self.Task:Fail()
end
function FSM_PROCESS:onenterSuccess( ProcessUnit )
self:E( "Success" )
self.Task:Success()
end
--- StateMachine callback function for a FSM_PROCESS
-- @param #FSM_PROCESS self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function FSM_PROCESS:onstatechange( ProcessUnit, Event, From, To, Dummy )
self:E( { ProcessUnit, Event, From, To, Dummy, self:IsTrace() } )
if self:IsTrace() then
MESSAGE:New( "@ Process " .. self:GetClassNameAndID() .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll()
end
self:E( self.Scores[To] )
-- TODO: This needs to be reworked with a callback functions allocated within Task, and set within the mission script from the Task Objects...
if self.Scores[To] then
local Task = self.Task
local Scoring = Task:GetScoring()
if Scoring then
Scoring:_AddMissionTaskScore( Task.Mission, ProcessUnit, self.Scores[To].ScoreText, self.Scores[To].Score )
end
end
end
end
do -- FSM_TASK
--- FSM_TASK class
-- @type FSM_TASK
-- @field Tasking.Task#TASK Task
-- @extends Core.Fsm#FSM
FSM_TASK = {
ClassName = "FSM_TASK",
}
--- Creates a new FSM_TASK object.
-- @param #FSM_TASK self
-- @param #table FSMT
-- @param Tasking.Task#TASK Task
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #FSM_TASK
function FSM_TASK:New( FSMT )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New( FSMT ) ) -- Core.Fsm#FSM_TASK
self["onstatechange"] = self.OnStateChange
return self
end
function FSM_TASK:_call_handler( handler, params )
if self[handler] then
self:E( "Calling " .. handler )
return self[handler]( self, unpack( params ) )
end
end
end -- FSM_TASK
do -- FSM_SET
--- FSM_SET class
-- @type FSM_SET
-- @field Core.Set#SET_BASE Set
-- @extends Core.Fsm#FSM
FSM_SET = {
ClassName = "FSM_SET",
}
--- Creates a new FSM_SET object.
-- @param #FSM_SET self
-- @param #table FSMT Finite State Machine Table
-- @param Set_SET_BASE FSMSet (optional) The Set object that the FSM_SET governs.
-- @return #FSM_SET
function FSM_SET:New( FSMSet )
-- Inherits from BASE
local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM_SET
if FSMSet then
self:Set( FSMSet )
end
return self
end
--- Sets the SET_BASE object that the FSM_SET governs.
-- @param #FSM_SET self
-- @param Core.Set#SET_BASE FSMSet
-- @return #FSM_SET
function FSM_SET:Set( FSMSet )
self:F( FSMSet )
self.Set = FSMSet
end
--- Gets the SET_BASE object that the FSM_SET governs.
-- @param #FSM_SET self
-- @return Core.Set#SET_BASE
function FSM_SET:Get()
return self.Controllable
end
function FSM_SET:_call_handler( handler, params )
if self[handler] then
self:E( "Calling " .. handler )
return self[handler]( self, self.Set, unpack( params ) )
end
end
end -- FSM_SET

View File

@ -15,17 +15,17 @@
--
-- ### To manage **main menus**, the classes begin with **MENU_**:
--
-- * @{Menu#MENU_MISSION}: Manages main menus for whole mission file.
-- * @{Menu#MENU_COALITION}: Manages main menus for whole coalition.
-- * @{Menu#MENU_GROUP}: Manages main menus for GROUPs.
-- * @{Menu#MENU_CLIENT}: Manages main menus for CLIENTs. This manages menus for units with the skill level "Client".
-- * @{Core.Menu#MENU_MISSION}: Manages main menus for whole mission file.
-- * @{Core.Menu#MENU_COALITION}: Manages main menus for whole coalition.
-- * @{Core.Menu#MENU_GROUP}: Manages main menus for GROUPs.
-- * @{Core.Menu#MENU_CLIENT}: Manages main menus for CLIENTs. This manages menus for units with the skill level "Client".
--
-- ### To manage **command menus**, which are menus that allow the player to issue **functions**, the classes begin with **MENU_COMMAND_**:
--
-- * @{Menu#MENU_MISSION_COMMAND}: Manages command menus for whole mission file.
-- * @{Menu#MENU_COALITION_COMMAND}: Manages command menus for whole coalition.
-- * @{Menu#MENU_GROUP_COMMAND}: Manages command menus for GROUPs.
-- * @{Menu#MENU_CLIENT_COMMAND}: Manages command menus for CLIENTs. This manages menus for units with the skill level "Client".
-- * @{Core.Menu#MENU_MISSION_COMMAND}: Manages command menus for whole mission file.
-- * @{Core.Menu#MENU_COALITION_COMMAND}: Manages command menus for whole coalition.
-- * @{Core.Menu#MENU_GROUP_COMMAND}: Manages command menus for GROUPs.
-- * @{Core.Menu#MENU_CLIENT_COMMAND}: Manages command menus for CLIENTs. This manages menus for units with the skill level "Client".
--
-- ===
--
@ -37,11 +37,11 @@
-- These are simply abstract base classes defining a couple of fields that are used by the
-- derived MENU_ classes to manage menus.
--
-- 1.1) @{Menu#MENU_BASE} class, extends @{Base#BASE}
-- 1.1) @{Core.Menu#MENU_BASE} class, extends @{Core.Base#BASE}
-- --------------------------------------------------
-- The @{#MENU_BASE} class defines the main MENU class where other MENU classes are derived from.
--
-- 1.2) @{Menu#MENU_COMMAND_BASE} class, extends @{Base#BASE}
-- 1.2) @{Core.Menu#MENU_COMMAND_BASE} class, extends @{Core.Base#BASE}
-- ----------------------------------------------------------
-- The @{#MENU_COMMAND_BASE} class defines the main MENU class where other MENU COMMAND_ classes are derived from, in order to set commands.
--
@ -53,15 +53,15 @@
-- ======================
-- The underlying classes manage the menus for a complete mission file.
--
-- 2.1) @{Menu#MENU_MISSION} class, extends @{Menu#MENU_BASE}
-- 2.1) @{Menu#MENU_MISSION} class, extends @{Core.Menu#MENU_BASE}
-- ---------------------------------------------------------
-- The @{Menu#MENU_MISSION} class manages the main menus for a complete mission.
-- The @{Core.Menu#MENU_MISSION} class manages the main menus for a complete mission.
-- You can add menus with the @{#MENU_MISSION.New} method, which constructs a MENU_MISSION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION.Remove}.
--
-- 2.2) @{Menu#MENU_MISSION_COMMAND} class, extends @{Menu#MENU_COMMAND_BASE}
-- 2.2) @{Menu#MENU_MISSION_COMMAND} class, extends @{Core.Menu#MENU_COMMAND_BASE}
-- -------------------------------------------------------------------------
-- The @{Menu#MENU_MISSION_COMMAND} class manages the command menus for a complete mission, which allow players to execute functions during mission execution.
-- The @{Core.Menu#MENU_MISSION_COMMAND} class manages the command menus for a complete mission, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_MISSION_COMMAND.New} method, which constructs a MENU_MISSION_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION_COMMAND.Remove}.
--
@ -71,15 +71,15 @@
-- =========================
-- The underlying classes manage the menus for whole coalitions.
--
-- 3.1) @{Menu#MENU_COALITION} class, extends @{Menu#MENU_BASE}
-- 3.1) @{Menu#MENU_COALITION} class, extends @{Core.Menu#MENU_BASE}
-- ------------------------------------------------------------
-- The @{Menu#MENU_COALITION} class manages the main menus for coalitions.
-- The @{Core.Menu#MENU_COALITION} class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_COALITION.New} method, which constructs a MENU_COALITION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION.Remove}.
--
-- 3.2) @{Menu#MENU_COALITION_COMMAND} class, extends @{Menu#MENU_COMMAND_BASE}
-- 3.2) @{Menu#MENU_COALITION_COMMAND} class, extends @{Core.Menu#MENU_COMMAND_BASE}
-- ----------------------------------------------------------------------------
-- The @{Menu#MENU_COALITION_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- The @{Core.Menu#MENU_COALITION_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_COALITION_COMMAND.New} method, which constructs a MENU_COALITION_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION_COMMAND.Remove}.
--
@ -89,15 +89,15 @@
-- =====================
-- The underlying classes manage the menus for groups. Note that groups can be inactive, alive or can be destroyed.
--
-- 4.1) @{Menu#MENU_GROUP} class, extends @{Menu#MENU_BASE}
-- 4.1) @{Menu#MENU_GROUP} class, extends @{Core.Menu#MENU_BASE}
-- --------------------------------------------------------
-- The @{Menu#MENU_GROUP} class manages the main menus for coalitions.
-- The @{Core.Menu#MENU_GROUP} class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}.
--
-- 4.2) @{Menu#MENU_GROUP_COMMAND} class, extends @{Menu#MENU_COMMAND_BASE}
-- 4.2) @{Menu#MENU_GROUP_COMMAND} class, extends @{Core.Menu#MENU_COMMAND_BASE}
-- ------------------------------------------------------------------------
-- The @{Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- The @{Core.Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_GROUP_COMMAND.New} method, which constructs a MENU_GROUP_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND.Remove}.
--
@ -107,15 +107,15 @@
-- ======================
-- The underlying classes manage the menus for units with skill level client or player.
--
-- 5.1) @{Menu#MENU_CLIENT} class, extends @{Menu#MENU_BASE}
-- 5.1) @{Menu#MENU_CLIENT} class, extends @{Core.Menu#MENU_BASE}
-- ---------------------------------------------------------
-- The @{Menu#MENU_CLIENT} class manages the main menus for coalitions.
-- The @{Core.Menu#MENU_CLIENT} class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_CLIENT.New} method, which constructs a MENU_CLIENT object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_CLIENT.Remove}.
--
-- 5.2) @{Menu#MENU_CLIENT_COMMAND} class, extends @{Menu#MENU_COMMAND_BASE}
-- 5.2) @{Menu#MENU_CLIENT_COMMAND} class, extends @{Core.Menu#MENU_COMMAND_BASE}
-- -------------------------------------------------------------------------
-- The @{Menu#MENU_CLIENT_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- The @{Core.Menu#MENU_CLIENT_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_CLIENT_COMMAND.New} method, which constructs a MENU_CLIENT_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_CLIENT_COMMAND.Remove}.
--
@ -351,7 +351,7 @@ do -- MENU_COALITION
--- MENU_COALITION constructor. Creates a new MENU_COALITION object and creates the menu for a complete coalition.
-- @param #MENU_COALITION self
-- @param DCSCoalition#coalition.side Coalition The coalition owning the menu.
-- @param Dcs.DCSCoalition#coalition.side Coalition The coalition owning the menu.
-- @param #string MenuText The text for the menu.
-- @param #table ParentMenu The parent menu. This parameter can be ignored if you want the menu to be located at the perent menu of DCS world (under F10 other).
-- @return #MENU_COALITION self
@ -420,7 +420,7 @@ do -- MENU_COALITION_COMMAND
--- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters.
-- @param #MENU_COALITION_COMMAND self
-- @param DCSCoalition#coalition.side Coalition The coalition owning the menu.
-- @param Dcs.DCSCoalition#coalition.side Coalition The coalition owning the menu.
-- @param #string MenuText The text for the menu.
-- @param Menu#MENU_COALITION ParentMenu The parent menu.
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
@ -493,7 +493,7 @@ do -- MENU_CLIENT
-- MenuStatus[MenuClientName]:Remove()
-- end
--
-- --- @param Client#CLIENT MenuClient
-- --- @param Wrapper.Client#CLIENT MenuClient
-- local function AddStatusMenu( MenuClient )
-- local MenuClientName = MenuClient:GetName()
-- -- This would create a menu for the red coalition under the MenuCoalitionRed menu object.
@ -526,7 +526,7 @@ do -- MENU_CLIENT
--- MENU_CLIENT constructor. Creates a new radio menu item for a client.
-- @param #MENU_CLIENT self
-- @param Client#CLIENT Client The Client owning the menu.
-- @param Wrapper.Client#CLIENT Client The Client owning the menu.
-- @param #string MenuText The text for the menu.
-- @param #table ParentMenu The parent menu.
-- @return #MENU_CLIENT self
@ -618,7 +618,7 @@ do -- MENU_CLIENT
--- MENU_CLIENT_COMMAND constructor. Creates a new radio command item for a client, which can invoke a function with parameters.
-- @param #MENU_CLIENT_COMMAND self
-- @param Client#CLIENT Client The Client owning the menu.
-- @param Wrapper.Client#CLIENT Client The Client owning the menu.
-- @param #string MenuText The text for the menu.
-- @param #MENU_BASE ParentMenu The parent menu.
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
@ -719,7 +719,7 @@ do
-- MenuStatus[MenuGroupName]:Remove()
-- end
--
-- --- @param Group#GROUP MenuGroup
-- --- @param Wrapper.Group#GROUP MenuGroup
-- local function AddStatusMenu( MenuGroup )
-- local MenuGroupName = MenuGroup:GetName()
-- -- This would create a menu for the red coalition under the MenuCoalitionRed menu object.
@ -753,51 +753,41 @@ do
--- MENU_GROUP constructor. Creates a new radio menu item for a group.
-- @param #MENU_GROUP self
-- @param Group#GROUP MenuGroup The Group owning the menu.
-- @param Wrapper.Group#GROUP MenuGroup The Group owning the menu.
-- @param #string MenuText The text for the menu.
-- @param #table ParentMenu The parent menu.
-- @return #MENU_GROUP self
function MENU_GROUP:New( MenuGroup, MenuText, ParentMenu )
-- Arrange meta tables
local MenuParentPath = {}
if ParentMenu ~= nil then
MenuParentPath = ParentMenu.MenuPath
end
local self = BASE:Inherit( self, MENU_BASE:New( MenuText, MenuParentPath ) )
self:F( { MenuGroup, MenuText, ParentMenu } )
self.MenuGroup = MenuGroup
self.MenuGroupID = MenuGroup:GetID()
self.MenuParentPath = MenuParentPath
self.MenuText = MenuText
self.ParentMenu = ParentMenu
-- Determine if the menu was not already created and already visible at the group.
-- If it is visible, then return the cached self, otherwise, create self and cache it.
self.Menus = {}
if not _MENUGROUPS[self.MenuGroupID] then
_MENUGROUPS[self.MenuGroupID] = {}
MenuGroup._Menus = MenuGroup._Menus or {}
local Path = ( ParentMenu and ( table.concat( ParentMenu.MenuPath or {}, "@" ) .. "@" .. MenuText ) ) or MenuText
if MenuGroup._Menus[Path] then
self = MenuGroup._Menus[Path]
else
self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
MenuGroup._Menus[Path] = self
self.Menus = {}
self.MenuGroup = MenuGroup
self.Path = Path
self.MenuGroupID = MenuGroup:GetID()
self.MenuText = MenuText
self.ParentMenu = ParentMenu
self:T( { "Adding Menu ", MenuText, self.MenuParentPath } )
self.MenuPath = missionCommands.addSubMenuForGroup( self.MenuGroupID, MenuText, self.MenuParentPath )
if ParentMenu and ParentMenu.Menus then
ParentMenu.Menus[self.MenuPath] = self
end
end
local MenuPath = _MENUGROUPS[self.MenuGroupID]
self:T( { MenuGroup:GetName(), MenuPath[table.concat(MenuParentPath)], MenuParentPath, MenuText } )
local MenuPathID = table.concat(MenuParentPath) .. "/" .. MenuText
if MenuPath[MenuPathID] then
missionCommands.removeItemForGroup( self.MenuGroupID, MenuPath[MenuPathID] )
end
self:T( { "Adding for MenuPath ", MenuText, MenuParentPath } )
self.MenuPath = missionCommands.addSubMenuForGroup( self.MenuGroupID, MenuText, MenuParentPath )
MenuPath[MenuPathID] = self.MenuPath
self:T( { self.MenuGroupID, self.MenuPath } )
if ParentMenu and ParentMenu.Menus then
ParentMenu.Menus[self.MenuPath] = self
end
self:F( { MenuGroup:GetName(), MenuText, ParentMenu.MenuPath } )
return self
end
@ -817,23 +807,20 @@ do
-- @param #MENU_GROUP self
-- @return #nil
function MENU_GROUP:Remove()
self:F( self.MenuPath )
self:F( { self.MenuGroupID, self.MenuPath } )
self:RemoveSubMenus()
if not _MENUGROUPS[self.MenuGroupID] then
_MENUGROUPS[self.MenuGroupID] = {}
end
if self.MenuGroup._Menus[self.Path] then
self = self.MenuGroup._Menus[self.Path]
local MenuPath = _MENUGROUPS[self.MenuGroupID]
if MenuPath[table.concat(self.MenuParentPath) .. "/" .. self.MenuText] then
MenuPath[table.concat(self.MenuParentPath) .. "/" .. self.MenuText] = nil
end
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
if self.ParentMenu then
self.ParentMenu.Menus[self.MenuPath] = nil
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
if self.ParentMenu then
self.ParentMenu.Menus[self.MenuPath] = nil
end
self:E( self.MenuGroup._Menus[self.Path] )
self.MenuGroup._Menus[self.Path] = nil
self = nil
end
return nil
end
@ -848,7 +835,7 @@ do
--- Creates a new radio command item for a group
-- @param #MENU_GROUP_COMMAND self
-- @param Group#GROUP MenuGroup The Group owning the menu.
-- @param Wrapper.Group#GROUP MenuGroup The Group owning the menu.
-- @param MenuText The text for the menu.
-- @param ParentMenu The parent menu.
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
@ -856,32 +843,30 @@ do
-- @return Menu#MENU_GROUP_COMMAND self
function MENU_GROUP_COMMAND:New( MenuGroup, MenuText, ParentMenu, CommandMenuFunction, ... )
local self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
self.MenuGroup = MenuGroup
self.MenuGroupID = MenuGroup:GetID()
self.MenuText = MenuText
self.ParentMenu = ParentMenu
if not _MENUGROUPS[self.MenuGroupID] then
_MENUGROUPS[self.MenuGroupID] = {}
MenuGroup._Menus = MenuGroup._Menus or {}
local Path = ( ParentMenu and ( table.concat( ParentMenu.MenuPath or {}, "@" ) .. "@" .. MenuText ) ) or MenuText
if MenuGroup._Menus[Path] then
self = MenuGroup._Menus[Path]
else
self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
MenuGroup._Menus[Path] = self
self.Path = Path
self.MenuGroup = MenuGroup
self.MenuGroupID = MenuGroup:GetID()
self.MenuText = MenuText
self.ParentMenu = ParentMenu
self:T( { "Adding Command Menu ", MenuText, self.MenuParentPath } )
self.MenuPath = missionCommands.addCommandForGroup( self.MenuGroupID, MenuText, self.MenuParentPath, self.MenuCallHandler, arg )
if ParentMenu and ParentMenu.Menus then
ParentMenu.Menus[self.MenuPath] = self
end
end
local MenuPath = _MENUGROUPS[self.MenuGroupID]
self:T( { MenuGroup:GetName(), MenuPath[table.concat(self.MenuParentPath)], self.MenuParentPath, MenuText, CommandMenuFunction, arg } )
local MenuPathID = table.concat(self.MenuParentPath) .. "/" .. MenuText
if MenuPath[MenuPathID] then
missionCommands.removeItemForGroup( self.MenuGroupID, MenuPath[MenuPathID] )
end
self:T( { "Adding for MenuPath ", MenuText, self.MenuParentPath } )
self.MenuPath = missionCommands.addCommandForGroup( self.MenuGroupID, MenuText, self.MenuParentPath, self.MenuCallHandler, arg )
MenuPath[MenuPathID] = self.MenuPath
ParentMenu.Menus[self.MenuPath] = self
self:F( { MenuGroup:GetName(), MenuText, ParentMenu.MenuPath } )
return self
end
@ -889,21 +874,18 @@ do
-- @param #MENU_GROUP_COMMAND self
-- @return #nil
function MENU_GROUP_COMMAND:Remove()
self:F( self.MenuPath )
if not _MENUGROUPS[self.MenuGroupID] then
_MENUGROUPS[self.MenuGroupID] = {}
end
local MenuPath = _MENUGROUPS[self.MenuGroupID]
self:F( { self.MenuGroupID, self.MenuPath } )
if self.MenuGroup._Menus[self.Path] then
self = self.MenuGroup._Menus[self.Path]
if MenuPath[table.concat(self.MenuParentPath) .. "/" .. self.MenuText] then
MenuPath[table.concat(self.MenuParentPath) .. "/" .. self.MenuText] = nil
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
self.ParentMenu.Menus[self.MenuPath] = nil
self:E( self.MenuGroup._Menus[self.Path] )
self.MenuGroup._Menus[self.Path] = nil
self = nil
end
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
self.ParentMenu.Menus[self.MenuPath] = nil
return nil
end

View File

@ -1,6 +1,6 @@
--- This module contains the MESSAGE class.
--
-- 1) @{Message#MESSAGE} class, extends @{Base#BASE}
-- 1) @{Core.Message#MESSAGE} class, extends @{Core.Base#BASE}
-- =================================================
-- Message System to display Messages to Clients, Coalitions or All.
-- Messages are shown on the display panel for an amount of seconds, and will then disappear.
@ -8,23 +8,23 @@
--
-- 1.1) MESSAGE construction methods
-- ---------------------------------
-- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
-- Messages are created with @{Core.Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
-- To send messages, you need to use the To functions.
--
-- 1.2) Send messages with MESSAGE To methods
-- ------------------------------------------
-- Messages are sent to:
--
-- * Clients with @{Message#MESSAGE.ToClient}.
-- * Coalitions with @{Message#MESSAGE.ToCoalition}.
-- * All Players with @{Message#MESSAGE.ToAll}.
-- * Clients with @{Core.Message#MESSAGE.ToClient}.
-- * Coalitions with @{Core.Message#MESSAGE.ToCoalition}.
-- * All Players with @{Core.Message#MESSAGE.ToAll}.
--
-- @module Message
-- @author FlightControl
--- The MESSAGE class
-- @type MESSAGE
-- @extends Base#BASE
-- @extends Core.Base#BASE
MESSAGE = {
ClassName = "MESSAGE",
MessageCategory = 0,
@ -54,7 +54,11 @@ function MESSAGE:New( MessageText, MessageDuration, MessageCategory )
-- When no MessageCategory is given, we don't show it as a title...
if MessageCategory and MessageCategory ~= "" then
self.MessageCategory = MessageCategory .. ": "
if MessageCategory:sub(-1) ~= "\n" then
self.MessageCategory = MessageCategory .. ": "
else
self.MessageCategory = MessageCategory:sub( 1, -2 ) .. ":\n"
end
else
self.MessageCategory = ""
end
@ -72,7 +76,7 @@ end
--- Sends a MESSAGE to a Client Group. Note that the Group needs to be defined within the ME with the skillset "Client" or "Player".
-- @param #MESSAGE self
-- @param Client#CLIENT Client is the Group of the Client.
-- @param Wrapper.Client#CLIENT Client is the Group of the Client.
-- @return #MESSAGE
-- @usage
-- -- Send the 2 messages created with the @{New} method to the Client Group.
@ -104,7 +108,7 @@ end
--- Sends a MESSAGE to a Group.
-- @param #MESSAGE self
-- @param Group#GROUP Group is the Group.
-- @param Wrapper.Group#GROUP Group is the Group.
-- @return #MESSAGE
function MESSAGE:ToGroup( Group )
self:F( Group.GroupName )

View File

@ -1,59 +1,74 @@
--- This module contains the POINT classes.
--
-- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE}
-- ===============================================
-- The @{Point#POINT_VEC3} class defines a 3D point in the simulator.
-- 1) @{Core.Point#POINT_VEC3} class, extends @{Core.Base#BASE}
-- ==================================================
-- The @{Core.Point#POINT_VEC3} class defines a 3D point in the simulator.
--
-- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts.
-- In order to keep the credibility of the the author, I want to emphasize that the of the MIST framework was created by Grimes, who you can find on the Eagle Dynamics Forums.
--
-- 1.1) POINT_VEC3 constructor
-- ---------------------------
--
-- A new POINT instance can be created with:
-- A new POINT_VEC3 instance can be created with:
--
-- * @{#POINT_VEC3.New}(): a 3D point.
-- * @{#POINT_VEC3.NewFromVec3}(): a 3D point created from a @{Dcs.DCSTypes#Vec3}.
--
--
-- 2) @{Point#POINT_VEC2} class, extends @{Point#POINT_VEC3}
-- 2) @{Core.Point#POINT_VEC2} class, extends @{Core.Point#POINT_VEC3}
-- =========================================================
-- The @{Point#POINT_VEC2} class defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
-- The @{Core.Point#POINT_VEC2} class defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
--
-- 2.1) POINT_VEC2 constructor
-- ---------------------------
--
-- A new POINT instance can be created with:
-- A new POINT_VEC2 instance can be created with:
--
-- * @{#POINT_VEC2.New}(): a 2D point.
-- * @{#POINT_VEC2.New}(): a 2D point, taking an additional height parameter.
-- * @{#POINT_VEC2.NewFromVec2}(): a 2D point created from a @{Dcs.DCSTypes#Vec2}.
--
-- ===
--
-- **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:
--
-- 2016-08-12: POINT_VEC3:**Translate( Distance, Angle )** added.
--
-- 2016-08-06: Made PointVec3 and Vec3, PointVec2 and Vec2 terminology used in the code consistent.
--
-- * Replaced method _Point_Vec3() to **Vec3**() where the code manages a Vec3. Replaced all references to the method.
-- * Replaced method _Point_Vec2() to **Vec2**() where the code manages a Vec2. Replaced all references to the method.
-- * Replaced method Random_Point_Vec3() to **RandomVec3**() where the code manages a Vec3. Replaced all references to the method.
-- .
-- ===
--
-- ### Authors:
--
-- * FlightControl : Design & Programming
--
-- ### Contributions:
--
-- @module Point
-- @author FlightControl
--- The POINT_VEC3 class
-- @type POINT_VEC3
-- @extends Base#BASE
-- @extends Core.Base#BASE
-- @field #number x The x coordinate in 3D space.
-- @field #number y The y coordinate in 3D space.
-- @field #number z The z coordiante in 3D space.
-- @field #POINT_VEC3.SmokeColor SmokeColor
-- @field #POINT_VEC3.FlareColor FlareColor
-- @field Utilities.Utils#SMOKECOLOR SmokeColor
-- @field Utilities.Utils#FLARECOLOR FlareColor
-- @field #POINT_VEC3.RoutePointAltType RoutePointAltType
-- @field #POINT_VEC3.RoutePointType RoutePointType
-- @field #POINT_VEC3.RoutePointAction RoutePointAction
POINT_VEC3 = {
ClassName = "POINT_VEC3",
SmokeColor = {
Green = trigger.smokeColor.Green,
Red = trigger.smokeColor.Red,
White = trigger.smokeColor.White,
Orange = trigger.smokeColor.Orange,
Blue = trigger.smokeColor.Blue
},
FlareColor = {
Green = trigger.flareColor.Green,
Red = trigger.flareColor.Red,
White = trigger.flareColor.White,
Yellow = trigger.flareColor.Yellow
},
Metric = true,
RoutePointAltType = {
BARO = "BARO",
@ -66,81 +81,70 @@ POINT_VEC3 = {
},
}
--- SmokeColor
-- @type POINT_VEC3.SmokeColor
-- @field Green
-- @field Red
-- @field White
-- @field Orange
-- @field Blue
--- FlareColor
-- @type POINT_VEC3.FlareColor
-- @field Green
-- @field Red
-- @field White
-- @field Yellow
--- The POINT_VEC2 class
-- @type POINT_VEC2
-- @extends #POINT_VEC3
-- @field Dcs.DCSTypes#Distance x The x coordinate in meters.
-- @field Dcs.DCSTypes#Distance y the y coordinate in meters.
POINT_VEC2 = {
ClassName = "POINT_VEC2",
}
do -- POINT_VEC3
--- RoutePoint AltTypes
-- @type POINT_VEC3.RoutePointAltType
-- @field BARO "BARO"
--- RoutePoint Types
-- @type POINT_VEC3.RoutePointType
-- @field TurningPoint "Turning Point"
--- RoutePoint Actions
-- @type POINT_VEC3.RoutePointAction
-- @field TurningPoint "Turning Point"
-- Constructor.
--- Create a new POINT_VEC3 object.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North.
-- @param DCSTypes#Distance y The y coordinate of the Vec3 point, pointing Upwards.
-- @param DCSTypes#Distance z The z coordinate of the Vec3 point, pointing to the Right.
-- @return Point#POINT_VEC3 self
-- @param Dcs.DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North.
-- @param Dcs.DCSTypes#Distance y The y coordinate of the Vec3 point, pointing Upwards.
-- @param Dcs.DCSTypes#Distance z The z coordinate of the Vec3 point, pointing to the Right.
-- @return Core.Point#POINT_VEC3 self
function POINT_VEC3:New( x, y, z )
local self = BASE:Inherit( self, BASE:New() )
self.x = x
self.y = y
self.z = z
return self
end
--- Create a new POINT_VEC3 object from Vec3 coordinates.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Vec3 Vec3 The Vec3 point.
-- @return Point#POINT_VEC3 self
-- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#POINT_VEC3 self
function POINT_VEC3:NewFromVec3( Vec3 )
return self:New( Vec3.x, Vec3.y, Vec3.z )
self = self:New( Vec3.x, Vec3.y, Vec3.z )
self:F2( self )
return self
end
--- Return the coordinates of the POINT_VEC3 in Vec3 format.
-- @param #POINT_VEC3 self
-- @return DCSTypes#Vec3 The Vec3 coodinate.
-- @return Dcs.DCSTypes#Vec3 The Vec3 coodinate.
function POINT_VEC3:GetVec3()
return { x = self.x, y = self.y, z = self.z }
end
--- Return the coordinates of the POINT_VEC3 in Vec2 format.
-- @param #POINT_VEC3 self
-- @return DCSTypes#Vec2 The Vec2 coodinate.
-- @return Dcs.DCSTypes#Vec2 The Vec2 coodinate.
function POINT_VEC3:GetVec2()
return { x = self.x, y = self.z }
end
@ -187,9 +191,9 @@ end
--- Return a random Vec2 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Distance OuterRadius
-- @param DCSTypes#Distance InnerRadius
-- @return DCSTypes#Vec2 Vec2
-- @param Dcs.DCSTypes#Distance OuterRadius
-- @param Dcs.DCSTypes#Distance InnerRadius
-- @return Dcs.DCSTypes#Vec2 Vec2
function POINT_VEC3:GetRandomVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } )
@ -218,8 +222,8 @@ end
--- Return a random POINT_VEC2 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Distance OuterRadius
-- @param DCSTypes#Distance InnerRadius
-- @param Dcs.DCSTypes#Distance OuterRadius
-- @param Dcs.DCSTypes#Distance InnerRadius
-- @return #POINT_VEC2
function POINT_VEC3:GetRandomPointVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } )
@ -229,9 +233,9 @@ end
--- Return a random Vec3 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Distance OuterRadius
-- @param DCSTypes#Distance InnerRadius
-- @return DCSTypes#Vec3 Vec3
-- @param Dcs.DCSTypes#Distance OuterRadius
-- @param Dcs.DCSTypes#Distance InnerRadius
-- @return Dcs.DCSTypes#Vec3 Vec3
function POINT_VEC3:GetRandomVec3InRadius( OuterRadius, InnerRadius )
local RandomVec2 = self:GetRandomVec2InRadius( OuterRadius, InnerRadius )
@ -243,8 +247,8 @@ end
--- Return a random POINT_VEC3 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Distance OuterRadius
-- @param DCSTypes#Distance InnerRadius
-- @param Dcs.DCSTypes#Distance OuterRadius
-- @param Dcs.DCSTypes#Distance InnerRadius
-- @return #POINT_VEC3
function POINT_VEC3:GetRandomPointVec3InRadius( OuterRadius, InnerRadius )
@ -255,7 +259,7 @@ end
--- Return a direction vector Vec3 from POINT_VEC3 to the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #POINT_VEC3 TargetPointVec3 The target POINT_VEC3.
-- @return DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @return Dcs.DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format.
function POINT_VEC3:GetDirectionVec3( TargetPointVec3 )
return { x = TargetPointVec3:GetX() - self:GetX(), y = TargetPointVec3:GetY() - self:GetY(), z = TargetPointVec3:GetZ() - self:GetZ() }
end
@ -273,7 +277,7 @@ end
--- Return a direction in radians from the POINT_VEC3 using a direction vector in Vec3 format.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @param Dcs.DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @return #number DirectionRadians The direction in radians.
function POINT_VEC3:GetDirectionRadians( DirectionVec3 )
local DirectionRadians = math.atan2( DirectionVec3.z, DirectionVec3.x )
@ -287,7 +291,7 @@ end
--- Return the 2D distance in meters between the target POINT_VEC3 and the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #POINT_VEC3 TargetPointVec3 The target POINT_VEC3.
-- @return DCSTypes#Distance Distance The distance in meters.
-- @return Dcs.DCSTypes#Distance Distance The distance in meters.
function POINT_VEC3:Get2DDistance( TargetPointVec3 )
local TargetVec3 = TargetPointVec3:GetVec3()
local SourceVec3 = self:GetVec3()
@ -297,7 +301,7 @@ end
--- Return the 3D distance in meters between the target POINT_VEC3 and the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #POINT_VEC3 TargetPointVec3 The target POINT_VEC3.
-- @return DCSTypes#Distance Distance The distance in meters.
-- @return Dcs.DCSTypes#Distance Distance The distance in meters.
function POINT_VEC3:Get3DDistance( TargetPointVec3 )
local TargetVec3 = TargetPointVec3:GetVec3()
local SourceVec3 = self:GetVec3()
@ -373,6 +377,20 @@ function POINT_VEC3:IsMetric()
return self.Metric
end
--- Add a Distance in meters from the POINT_VEC3 horizontal plane, with the given angle, and calculate the new POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param Dcs.DCSTypes#Distance Distance The Distance to be added in meters.
-- @param Dcs.DCSTypes#Angle Angle The Angle in degrees.
-- @return #POINT_VEC3 The new calculated POINT_VEC3.
function POINT_VEC3:Translate( Distance, Angle )
local SX = self:GetX()
local SZ = self:GetZ()
local Radians = Angle / 180 * math.pi
local TX = Distance * math.cos( Radians ) + SX
local TZ = Distance * math.sin( Radians ) + SZ
return POINT_VEC3:New( TX, self:GetY(), TZ )
end
@ -381,7 +399,7 @@ end
-- @param #POINT_VEC3.RoutePointAltType AltType The altitude type.
-- @param #POINT_VEC3.RoutePointType Type The route point type.
-- @param #POINT_VEC3.RoutePointAction Action The route point action.
-- @param DCSTypes#Speed Speed Airspeed in km/h.
-- @param Dcs.DCSTypes#Speed Speed Airspeed in km/h.
-- @param #boolean SpeedLocked true means the speed is locked.
-- @return #table The route point.
function POINT_VEC3:RoutePointAir( AltType, Type, Action, Speed, SpeedLocked )
@ -422,7 +440,7 @@ end
--- Build an ground type route point.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Speed Speed Speed in km/h.
-- @param Dcs.DCSTypes#Speed Speed Speed in km/h.
-- @param #POINT_VEC3.RoutePointAction Formation The route point Formation.
-- @return #table The route point.
function POINT_VEC3:RoutePointGround( Speed, Formation )
@ -462,7 +480,7 @@ end
--- Smokes the point in a color.
-- @param #POINT_VEC3 self
-- @param Point#POINT_VEC3.SmokeColor SmokeColor
-- @param Utilities.Utils#SMOKECOLOR SmokeColor
function POINT_VEC3:Smoke( SmokeColor )
self:F2( { SmokeColor } )
trigger.action.smoke( self:GetVec3(), SmokeColor )
@ -472,41 +490,41 @@ end
-- @param #POINT_VEC3 self
function POINT_VEC3:SmokeGreen()
self:F2()
self:Smoke( POINT_VEC3.SmokeColor.Green )
self:Smoke( SMOKECOLOR.Green )
end
--- Smoke the POINT_VEC3 Red.
-- @param #POINT_VEC3 self
function POINT_VEC3:SmokeRed()
self:F2()
self:Smoke( POINT_VEC3.SmokeColor.Red )
self:Smoke( SMOKECOLOR.Red )
end
--- Smoke the POINT_VEC3 White.
-- @param #POINT_VEC3 self
function POINT_VEC3:SmokeWhite()
self:F2()
self:Smoke( POINT_VEC3.SmokeColor.White )
self:Smoke( SMOKECOLOR.White )
end
--- Smoke the POINT_VEC3 Orange.
-- @param #POINT_VEC3 self
function POINT_VEC3:SmokeOrange()
self:F2()
self:Smoke( POINT_VEC3.SmokeColor.Orange )
self:Smoke( SMOKECOLOR.Orange )
end
--- Smoke the POINT_VEC3 Blue.
-- @param #POINT_VEC3 self
function POINT_VEC3:SmokeBlue()
self:F2()
self:Smoke( POINT_VEC3.SmokeColor.Blue )
self:Smoke( SMOKECOLOR.Blue )
end
--- Flares the point in a color.
-- @param #POINT_VEC3 self
-- @param Point#POINT_VEC3.FlareColor
-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
-- @param Utilities.Utils#FLARECOLOR FlareColor
-- @param Dcs.DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
function POINT_VEC3:Flare( FlareColor, Azimuth )
self:F2( { FlareColor } )
trigger.action.signalFlare( self:GetVec3(), FlareColor, Azimuth and Azimuth or 0 )
@ -514,51 +532,47 @@ end
--- Flare the POINT_VEC3 White.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
-- @param Dcs.DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
function POINT_VEC3:FlareWhite( Azimuth )
self:F2( Azimuth )
self:Flare( POINT_VEC3.FlareColor.White, Azimuth )
self:Flare( FLARECOLOR.White, Azimuth )
end
--- Flare the POINT_VEC3 Yellow.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
-- @param Dcs.DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
function POINT_VEC3:FlareYellow( Azimuth )
self:F2( Azimuth )
self:Flare( POINT_VEC3.FlareColor.Yellow, Azimuth )
self:Flare( FLARECOLOR.Yellow, Azimuth )
end
--- Flare the POINT_VEC3 Green.
-- @param #POINT_VEC3 self
-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
-- @param Dcs.DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
function POINT_VEC3:FlareGreen( Azimuth )
self:F2( Azimuth )
self:Flare( POINT_VEC3.FlareColor.Green, Azimuth )
self:Flare( FLARECOLOR.Green, Azimuth )
end
--- Flare the POINT_VEC3 Red.
-- @param #POINT_VEC3 self
function POINT_VEC3:FlareRed( Azimuth )
self:F2( Azimuth )
self:Flare( POINT_VEC3.FlareColor.Red, Azimuth )
self:Flare( FLARECOLOR.Red, Azimuth )
end
end
--- The POINT_VEC2 class
-- @type POINT_VEC2
-- @extends Point#POINT_VEC3
-- @field #number x The x coordinate in 2D space.
-- @field #number y the y coordinate in 2D space.
POINT_VEC2 = {
ClassName = "POINT_VEC2",
}
do -- POINT_VEC2
--- Create a new POINT_VEC2 object.
--- POINT_VEC2 constructor.
-- @param #POINT_VEC2 self
-- @param DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North.
-- @param DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right.
-- @param DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height.
-- @return Point#POINT_VEC2
-- @param Dcs.DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North.
-- @param Dcs.DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right.
-- @param Dcs.DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height.
-- @return Core.Point#POINT_VEC2
function POINT_VEC2:New( x, y, LandHeightAdd )
local LandHeight = land.getHeight( { ["x"] = x, ["y"] = y } )
@ -566,15 +580,16 @@ function POINT_VEC2:New( x, y, LandHeightAdd )
LandHeightAdd = LandHeightAdd or 0
LandHeight = LandHeight + LandHeightAdd
local self = BASE:Inherit( self, POINT_VEC3:New( x, LandHeight, y ) )
self = BASE:Inherit( self, POINT_VEC3:New( x, LandHeight, y ) )
self:F2( self )
return self
end
--- Create a new POINT_VEC2 object from Vec2 coordinates.
-- @param #POINT_VEC2 self
-- @param DCSTypes#Vec2 Vec2 The Vec2 point.
-- @return Point#POINT_VEC2 self
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 point.
-- @return Core.Point#POINT_VEC2 self
function POINT_VEC2:NewFromVec2( Vec2, LandHeightAdd )
local LandHeight = land.getHeight( Vec2 )
@ -582,16 +597,16 @@ function POINT_VEC2:NewFromVec2( Vec2, LandHeightAdd )
LandHeightAdd = LandHeightAdd or 0
LandHeight = LandHeight + LandHeightAdd
local self = BASE:Inherit( self, POINT_VEC3:New( Vec2.x, LandHeight, Vec2.y ) )
self:F2( { Vec2.x, Vec2.y, LandHeightAdd } )
self = BASE:Inherit( self, POINT_VEC3:New( Vec2.x, LandHeight, Vec2.y ) )
self:F2( self )
return self
end
--- Create a new POINT_VEC2 object from Vec3 coordinates.
-- @param #POINT_VEC2 self
-- @param DCSTypes#Vec3 Vec3 The Vec3 point.
-- @return Point#POINT_VEC2 self
-- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#POINT_VEC2 self
function POINT_VEC2:NewFromVec3( Vec3 )
local self = BASE:Inherit( self, BASE:New() )
@ -599,8 +614,8 @@ function POINT_VEC2:NewFromVec3( Vec3 )
local LandHeight = land.getHeight( Vec2 )
local self = BASE:Inherit( self, POINT_VEC3:New( Vec2.x, LandHeight, Vec2.y ) )
self:F2( { Vec2.x, LandHeight, Vec2.y } )
self = BASE:Inherit( self, POINT_VEC3:New( Vec2.x, LandHeight, Vec2.y ) )
self:F2( self )
return self
end
@ -643,7 +658,7 @@ end
--- Calculate the distance from a reference @{#POINT_VEC2}.
-- @param #POINT_VEC2 self
-- @param #POINT_VEC2 PointVec2Reference The reference @{#POINT_VEC2}.
-- @return DCSTypes#Distance The distance from the reference @{#POINT_VEC2} in meters.
-- @return Dcs.DCSTypes#Distance The distance from the reference @{#POINT_VEC2} in meters.
function POINT_VEC2:DistanceFromPointVec2( PointVec2Reference )
self:F2( PointVec2Reference )
@ -653,10 +668,10 @@ function POINT_VEC2:DistanceFromPointVec2( PointVec2Reference )
return Distance
end
--- Calculate the distance from a reference @{DCSTypes#Vec2}.
--- Calculate the distance from a reference @{Dcs.DCSTypes#Vec2}.
-- @param #POINT_VEC2 self
-- @param DCSTypes#Vec2 Vec2Reference The reference @{DCSTypes#Vec2}.
-- @return DCSTypes#Distance The distance from the reference @{DCSTypes#Vec2} in meters.
-- @param Dcs.DCSTypes#Vec2 Vec2Reference The reference @{Dcs.DCSTypes#Vec2}.
-- @return Dcs.DCSTypes#Distance The distance from the reference @{Dcs.DCSTypes#Vec2} in meters.
function POINT_VEC2:DistanceFromVec2( Vec2Reference )
self:F2( Vec2Reference )
@ -676,8 +691,8 @@ end
--- Add a Distance in meters from the POINT_VEC2 orthonormal plane, with the given angle, and calculate the new POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param DCSTypes#Distance Distance The Distance to be added in meters.
-- @param DCSTypes#Angle Angle The Angle in degrees.
-- @param Dcs.DCSTypes#Distance Distance The Distance to be added in meters.
-- @param Dcs.DCSTypes#Angle Angle The Angle in degrees.
-- @return #POINT_VEC2 The new calculated POINT_VEC2.
function POINT_VEC2:Translate( Distance, Angle )
local SX = self:GetX()
@ -689,5 +704,6 @@ function POINT_VEC2:Translate( Distance, Angle )
return POINT_VEC2:New( TX, TY )
end
end

View File

@ -0,0 +1,210 @@
--- This module defines the SCHEDULEDISPATCHER class, which is used by a central object called _SCHEDULEDISPATCHER.
--
-- ===
--
-- Takes care of the creation and dispatching of scheduled functions for SCHEDULER objects.
--
-- This class is tricky and needs some thorought explanation.
-- SCHEDULE classes are used to schedule functions for objects, or as persistent objects.
-- The SCHEDULEDISPATCHER class ensures that:
--
-- - Scheduled functions are planned according the SCHEDULER object parameters.
-- - Scheduled functions are repeated when requested, according the SCHEDULER object parameters.
-- - Scheduled functions are automatically removed when the schedule is finished, according the SCHEDULER object parameters.
--
-- The SCHEDULEDISPATCHER class will manage SCHEDULER object in memory during garbage collection:
-- - When a SCHEDULER object is not attached to another object (that is, it's first :Schedule() parameter is nil), then the SCHEDULER
-- object is _persistent_ within memory.
-- - When a SCHEDULER object *is* attached to another object, then the SCHEDULER object is _not persistent_ within memory after a garbage collection!
-- The none persistency of SCHEDULERS attached to objects is required to allow SCHEDULER objects to be garbage collectged, when the parent object is also desroyed or nillified and garbage collected.
-- Even when there are pending timer scheduled functions to be executed for the SCHEDULER object,
-- these will not be executed anymore when the SCHEDULER object has been destroyed.
--
-- The SCHEDULEDISPATCHER allows multiple scheduled functions to be planned and executed for one SCHEDULER object.
-- The SCHEDULER object therefore keeps a table of "CallID's", which are returned after each planning of a new scheduled function by the SCHEDULEDISPATCHER.
-- The SCHEDULER object plans new scheduled functions through the @{Core.Scheduler#SCHEDULER.Schedule}() method.
-- The Schedule() method returns the CallID that is the reference ID for each planned schedule.
--
-- ===
--
-- ===
--
-- ### Contributions: -
-- ### Authors: FlightControl : Design & Programming
--
-- @module ScheduleDispatcher
--- The SCHEDULEDISPATCHER structure
-- @type SCHEDULEDISPATCHER
SCHEDULEDISPATCHER = {
ClassName = "SCHEDULEDISPATCHER",
CallID = 0,
}
function SCHEDULEDISPATCHER:New()
local self = BASE:Inherit( self, BASE:New() )
self:F3()
return self
end
--- Add a Schedule to the ScheduleDispatcher.
-- The development of this method was really tidy.
-- It is constructed as such that a garbage collection is executed on the weak tables, when the Scheduler is nillified.
-- Nothing of this code should be modified without testing it thoroughly.
-- @param #SCHEDULEDISPATCHER self
-- @param Core.Scheduler#SCHEDULER Scheduler
function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop )
self:F2( { Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop } )
self.CallID = self.CallID + 1
-- Initialize the ObjectSchedulers array, which is a weakly coupled table.
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
self.PersistentSchedulers = self.PersistentSchedulers or {}
-- Initialize the ObjectSchedulers array, which is a weakly coupled table.
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } )
if Scheduler.SchedulerObject then
self.ObjectSchedulers[self.CallID] = Scheduler
self:T3( { self.CallID, self.ObjectSchedulers[self.CallID] } )
else
self.PersistentSchedulers[self.CallID] = Scheduler
self:T3( { self.CallID, self.PersistentSchedulers[self.CallID] } )
end
self.Schedule = self.Schedule or setmetatable( {}, { __mode = "k" } )
self.Schedule[Scheduler] = {}
self.Schedule[Scheduler][self.CallID] = {}
self.Schedule[Scheduler][self.CallID].Function = ScheduleFunction
self.Schedule[Scheduler][self.CallID].Arguments = ScheduleArguments
self.Schedule[Scheduler][self.CallID].StartTime = timer.getTime() + ( Start or 0 )
self.Schedule[Scheduler][self.CallID].Start = Start + .001
self.Schedule[Scheduler][self.CallID].Repeat = Repeat
self.Schedule[Scheduler][self.CallID].Randomize = Randomize
self.Schedule[Scheduler][self.CallID].Stop = Stop
self:T3( self.Schedule[Scheduler][self.CallID] )
self.Schedule[Scheduler][self.CallID].CallHandler = function( CallID )
self:F2( CallID )
local ErrorHandler = function( errmsg )
env.info( "Error in timer function: " .. errmsg )
if debug ~= nil then
env.info( debug.traceback() )
end
return errmsg
end
local Scheduler = self.ObjectSchedulers[CallID]
if not Scheduler then
Scheduler = self.PersistentSchedulers[CallID]
end
self:T3( { Scheduler = Scheduler } )
if Scheduler then
local Schedule = self.Schedule[Scheduler][CallID]
self:T3( { Schedule = Schedule } )
local ScheduleObject = Scheduler.SchedulerObject
--local ScheduleObjectName = Scheduler.SchedulerObject:GetNameAndClassID()
local ScheduleFunction = Schedule.Function
local ScheduleArguments = Schedule.Arguments
local Start = Schedule.Start
local Repeat = Schedule.Repeat or 0
local Randomize = Schedule.Randomize or 0
local Stop = Schedule.Stop or 0
local ScheduleID = Schedule.ScheduleID
local Status, Result
if ScheduleObject then
local function Timer()
return ScheduleFunction( ScheduleObject, unpack( ScheduleArguments ) )
end
Status, Result = xpcall( Timer, ErrorHandler )
else
local function Timer()
return ScheduleFunction( unpack( ScheduleArguments ) )
end
Status, Result = xpcall( Timer, ErrorHandler )
end
local CurrentTime = timer.getTime()
local StartTime = CurrentTime + Start
if Status and (( Result == nil ) or ( Result and Result ~= false ) ) then
if Repeat ~= 0 and ( Stop == 0 ) or ( Stop ~= 0 and CurrentTime <= StartTime + Stop ) then
local ScheduleTime =
CurrentTime +
Repeat +
math.random(
- ( Randomize * Repeat / 2 ),
( Randomize * Repeat / 2 )
) +
0.01
self:T3( { Repeat = CallID, CurrentTime, ScheduleTime, ScheduleArguments } )
return ScheduleTime -- returns the next time the function needs to be called.
else
self:Stop( Scheduler, CallID )
end
else
self:Stop( Scheduler, CallID )
end
else
--self:E( "Scheduled obscolete call for CallID: " .. CallID )
end
return nil
end
self:Start( Scheduler, self.CallID )
return self.CallID
end
function SCHEDULEDISPATCHER:RemoveSchedule( Scheduler, CallID )
self:F2( { Remove = CallID, Scheduler = Scheduler } )
if CallID then
self:Stop( Scheduler, CallID )
self.Schedule[Scheduler][CallID] = nil
end
end
function SCHEDULEDISPATCHER:Start( Scheduler, CallID )
self:F2( { Start = CallID, Scheduler = Scheduler } )
if CallID then
local Schedule = self.Schedule[Scheduler]
Schedule[CallID].ScheduleID = timer.scheduleFunction(
Schedule[CallID].CallHandler,
CallID,
timer.getTime() + Schedule[CallID].Start
)
else
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
self:Start( Scheduler, CallID ) -- Recursive
end
end
end
function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
self:F2( { Stop = CallID, Scheduler = Scheduler } )
if CallID then
local Schedule = self.Schedule[Scheduler]
timer.removeFunction( Schedule[CallID].ScheduleID )
else
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
self:Stop( Scheduler, CallID ) -- Recursive
end
end
end

View File

@ -0,0 +1,157 @@
--- This module contains the SCHEDULER class.
--
-- # 1) @{Core.Scheduler#SCHEDULER} class, extends @{Core.Base#BASE}
--
-- The @{Core.Scheduler#SCHEDULER} class creates schedule.
--
-- ## 1.1) SCHEDULER constructor
--
-- The SCHEDULER class is quite easy to use, but note that the New constructor has variable parameters:
--
-- * @{Core.Scheduler#SCHEDULER.New}( nil ): Setup a new SCHEDULER object, which is persistently executed after garbage collection.
-- * @{Core.Scheduler#SCHEDULER.New}( Object ): Setup a new SCHEDULER object, which is linked to the Object. When the Object is nillified or destroyed, the SCHEDULER object will also be destroyed and stopped after garbage collection.
-- * @{Core.Scheduler#SCHEDULER.New}( nil, Function, FunctionArguments, Start, ... ): Setup a new persistent SCHEDULER object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
-- * @{Core.Scheduler#SCHEDULER.New}( Object, Function, FunctionArguments, Start, ... ): Setup a new SCHEDULER object, linked to Object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
--
-- ## 1.2) SCHEDULER timer stopping and (re-)starting.
--
-- The SCHEDULER can be stopped and restarted with the following methods:
--
-- * @{Core.Scheduler#SCHEDULER.Start}(): (Re-)Start the schedules within the SCHEDULER object. If a CallID is provided to :Start(), only the schedule referenced by CallID will be (re-)started.
-- * @{Core.Scheduler#SCHEDULER.Stop}(): Stop the schedules within the SCHEDULER object. If a CallID is provided to :Stop(), then only the schedule referenced by CallID will be stopped.
--
-- ## 1.3) Create a new schedule
--
-- With @{Core.Scheduler#SCHEDULER.Schedule}() a new time event can be scheduled. This function is used by the :New() constructor when a new schedule is planned.
--
-- ===
--
-- ### Contributions:
--
-- * FlightControl : Concept & Testing
--
-- ### Authors:
--
-- * FlightControl : Design & Programming
--
-- ### Test Missions:
--
-- * SCH - Scheduler
--
-- ===
--
-- @module Scheduler
--- The SCHEDULER class
-- @type SCHEDULER
-- @field #number ScheduleID the ID of the scheduler.
-- @extends Core.Base#BASE
SCHEDULER = {
ClassName = "SCHEDULER",
Schedules = {},
}
--- SCHEDULER constructor.
-- @param #SCHEDULER self
-- @param #table SchedulerObject Specified for which Moose object the timer is setup. If a value of nil is provided, a scheduler will be setup without an object reference.
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
-- @param #table SchedulerArguments Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
-- @param #number Repeat Specifies the interval in seconds when the scheduler will call the event function.
-- @param #number RandomizeFactor Specifies a randomization factor between 0 and 1 to randomize the Repeat.
-- @param #number Stop Specifies the amount of seconds when the scheduler will be stopped.
-- @return #SCHEDULER self
-- @return #number The ScheduleID of the planned schedule.
function SCHEDULER:New( SchedulerObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop )
local self = BASE:Inherit( self, BASE:New() )
self:F2( { Start, Repeat, RandomizeFactor, Stop } )
local ScheduleID = nil
if SchedulerFunction then
ScheduleID = self:Schedule( SchedulerObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop )
end
return self, ScheduleID
end
--function SCHEDULER:_Destructor()
-- --self:E("_Destructor")
--
-- _SCHEDULEDISPATCHER:RemoveSchedule( self.CallID )
--end
--- Schedule a new time event. Note that the schedule will only take place if the scheduler is *started*. Even for a single schedule event, the scheduler needs to be started also.
-- @param #SCHEDULER self
-- @param #table SchedulerObject Specified for which Moose object the timer is setup. If a value of nil is provided, a scheduler will be setup without an object reference.
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
-- @param #table SchedulerArguments Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
-- @param #number Repeat Specifies the interval in seconds when the scheduler will call the event function.
-- @param #number RandomizeFactor Specifies a randomization factor between 0 and 1 to randomize the Repeat.
-- @param #number Stop Specifies the amount of seconds when the scheduler will be stopped.
-- @return #number The ScheduleID of the planned schedule.
function SCHEDULER:Schedule( SchedulerObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop )
self:F2( { Start, Repeat, RandomizeFactor, Stop } )
self:T3( { SchedulerArguments } )
self.SchedulerObject = SchedulerObject
local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule(
self,
SchedulerFunction,
SchedulerArguments,
Start,
Repeat,
RandomizeFactor,
Stop
)
self.Schedules[#self.Schedules+1] = ScheduleID
return ScheduleID
end
--- (Re-)Starts the schedules or a specific schedule if a valid ScheduleID is provided.
-- @param #SCHEDULER self
-- @param #number ScheduleID (optional) The ScheduleID of the planned (repeating) schedule.
function SCHEDULER:Start( ScheduleID )
self:F3( { ScheduleID } )
_SCHEDULEDISPATCHER:Start( self, ScheduleID )
end
--- Stops the schedules or a specific schedule if a valid ScheduleID is provided.
-- @param #SCHEDULER self
-- @param #number ScheduleID (optional) The ScheduleID of the planned (repeating) schedule.
function SCHEDULER:Stop( ScheduleID )
self:F3( { ScheduleID } )
_SCHEDULEDISPATCHER:Stop( self, ScheduleID )
end
--- Removes a specific schedule if a valid ScheduleID is provided.
-- @param #SCHEDULER self
-- @param #number ScheduleID (optional) The ScheduleID of the planned (repeating) schedule.
function SCHEDULER:Remove( ScheduleID )
self:F3( { ScheduleID } )
_SCHEDULEDISPATCHER:Remove( self, ScheduleID )
end

View File

@ -2,9 +2,9 @@
--
-- ===
--
-- 1) @{Set#SET_BASE} class, extends @{Base#BASE}
-- 1) @{Core.Set#SET_BASE} class, extends @{Core.Base#BASE}
-- ==============================================
-- The @{Set#SET_BASE} class defines the core functions that define a collection of objects.
-- The @{Core.Set#SET_BASE} class defines the core functions that define a collection of objects.
-- A SET provides iterators to iterate the SET, but will **temporarily** yield the ForEach interator loop at defined **"intervals"** to the mail simulator loop.
-- In this way, large loops can be done while not blocking the simulator main processing loop.
-- The default **"yield interval"** is after 10 objects processed.
@ -12,18 +12,18 @@
--
-- 1.1) Add or remove objects from the SET
-- ---------------------------------------
-- Some key core functions are @{Set#SET_BASE.Add} and @{Set#SET_BASE.Remove} to add or remove objects from the SET in your logic.
-- Some key core functions are @{Core.Set#SET_BASE.Add} and @{Core.Set#SET_BASE.Remove} to add or remove objects from the SET in your logic.
--
-- 1.2) Define the SET iterator **"yield interval"** and the **"time interval"**
-- -----------------------------------------------------------------------------
-- Modify the iterator intervals with the @{Set#SET_BASE.SetInteratorIntervals} method.
-- Modify the iterator intervals with the @{Core.Set#SET_BASE.SetInteratorIntervals} method.
-- You can set the **"yield interval"**, and the **"time interval"**. (See above).
--
-- ===
--
-- 2) @{Set#SET_GROUP} class, extends @{Set#SET_BASE}
-- 2) @{Core.Set#SET_GROUP} class, extends @{Core.Set#SET_BASE}
-- ==================================================
-- Mission designers can use the @{Set#SET_GROUP} class to build sets of groups belonging to certain:
-- Mission designers can use the @{Core.Set#SET_GROUP} class to build sets of groups belonging to certain:
--
-- * Coalitions
-- * Categories
@ -38,7 +38,7 @@
--
-- 2.2) Add or Remove GROUP(s) from SET_GROUP:
-- -------------------------------------------
-- GROUPS can be added and removed using the @{Set#SET_GROUP.AddGroupsByName} and @{Set#SET_GROUP.RemoveGroupsByName} respectively.
-- GROUPS can be added and removed using the @{Core.Set#SET_GROUP.AddGroupsByName} and @{Core.Set#SET_GROUP.RemoveGroupsByName} respectively.
-- These methods take a single GROUP name or an array of GROUP names to be added or removed from SET_GROUP.
--
-- 2.3) SET_GROUP filter criteria:
@ -57,7 +57,7 @@
--
-- Planned filter criteria within development are (so these are not yet available):
--
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Zone#ZONE}.
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Core.Zone#ZONE}.
--
-- 2.4) SET_GROUP iterators:
-- -------------------------
@ -72,9 +72,9 @@
--
-- ====
--
-- 3) @{Set#SET_UNIT} class, extends @{Set#SET_BASE}
-- 3) @{Core.Set#SET_UNIT} class, extends @{Core.Set#SET_BASE}
-- ===================================================
-- Mission designers can use the @{Set#SET_UNIT} class to build sets of units belonging to certain:
-- Mission designers can use the @{Core.Set#SET_UNIT} class to build sets of units belonging to certain:
--
-- * Coalitions
-- * Categories
@ -90,7 +90,7 @@
--
-- 3.2) Add or Remove UNIT(s) from SET_UNIT:
-- -----------------------------------------
-- UNITs can be added and removed using the @{Set#SET_UNIT.AddUnitsByName} and @{Set#SET_UNIT.RemoveUnitsByName} respectively.
-- UNITs can be added and removed using the @{Core.Set#SET_UNIT.AddUnitsByName} and @{Core.Set#SET_UNIT.RemoveUnitsByName} respectively.
-- These methods take a single UNIT name or an array of UNIT names to be added or removed from SET_UNIT.
--
-- 3.3) SET_UNIT filter criteria:
@ -110,7 +110,7 @@
--
-- Planned filter criteria within development are (so these are not yet available):
--
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Zone#ZONE}.
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Core.Zone#ZONE}.
--
-- 3.4) SET_UNIT iterators:
-- ------------------------
@ -130,9 +130,9 @@
--
-- ===
--
-- 4) @{Set#SET_CLIENT} class, extends @{Set#SET_BASE}
-- 4) @{Core.Set#SET_CLIENT} class, extends @{Core.Set#SET_BASE}
-- ===================================================
-- Mission designers can use the @{Set#SET_CLIENT} class to build sets of units belonging to certain:
-- Mission designers can use the @{Core.Set#SET_CLIENT} class to build sets of units belonging to certain:
--
-- * Coalitions
-- * Categories
@ -148,7 +148,7 @@
--
-- 4.2) Add or Remove CLIENT(s) from SET_CLIENT:
-- -----------------------------------------
-- CLIENTs can be added and removed using the @{Set#SET_CLIENT.AddClientsByName} and @{Set#SET_CLIENT.RemoveClientsByName} respectively.
-- CLIENTs can be added and removed using the @{Core.Set#SET_CLIENT.AddClientsByName} and @{Core.Set#SET_CLIENT.RemoveClientsByName} respectively.
-- These methods take a single CLIENT name or an array of CLIENT names to be added or removed from SET_CLIENT.
--
-- 4.3) SET_CLIENT filter criteria:
@ -168,7 +168,7 @@
--
-- Planned filter criteria within development are (so these are not yet available):
--
-- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Zone#ZONE}.
-- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Core.Zone#ZONE}.
--
-- 4.4) SET_CLIENT iterators:
-- ------------------------
@ -180,9 +180,9 @@
--
-- ====
--
-- 5) @{Set#SET_AIRBASE} class, extends @{Set#SET_BASE}
-- 5) @{Core.Set#SET_AIRBASE} class, extends @{Core.Set#SET_BASE}
-- ====================================================
-- Mission designers can use the @{Set#SET_AIRBASE} class to build sets of airbases optionally belonging to certain:
-- Mission designers can use the @{Core.Set#SET_AIRBASE} class to build sets of airbases optionally belonging to certain:
--
-- * Coalitions
--
@ -194,7 +194,7 @@
--
-- 5.2) Add or Remove AIRBASEs from SET_AIRBASE
-- --------------------------------------------
-- AIRBASEs can be added and removed using the @{Set#SET_AIRBASE.AddAirbasesByName} and @{Set#SET_AIRBASE.RemoveAirbasesByName} respectively.
-- AIRBASEs can be added and removed using the @{Core.Set#SET_AIRBASE.AddAirbasesByName} and @{Core.Set#SET_AIRBASE.RemoveAirbasesByName} respectively.
-- These methods take a single AIRBASE name or an array of AIRBASE names to be added or removed from SET_AIRBASE.
--
-- 5.3) SET_AIRBASE filter criteria
@ -218,13 +218,12 @@
--
-- ====
--
-- ### Contributions:
--
-- * Mechanist : Concept & Testing
--
-- ### Authors:
--
-- * FlightControl : Design & Programming
--
-- ### Contributions:
--
--
-- @module Set
@ -234,7 +233,7 @@
-- @field #table Filter
-- @field #table Set
-- @field #table List
-- @extends Base#BASE
-- @extends Core.Base#BASE
SET_BASE = {
ClassName = "SET_BASE",
Filter = {},
@ -265,10 +264,10 @@ function SET_BASE:New( Database )
return self
end
--- Finds an @{Base#BASE} object based on the object Name.
--- Finds an @{Core.Base#BASE} object based on the object Name.
-- @param #SET_BASE self
-- @param #string ObjectName
-- @return Base#BASE The Object found.
-- @return Core.Base#BASE The Object found.
function SET_BASE:_Find( ObjectName )
local ObjectFound = self.Set[ObjectName]
@ -285,11 +284,11 @@ function SET_BASE:GetSet()
return self.Set
end
--- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using the Object Name as the index.
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using a given ObjectName as the index.
-- @param #SET_BASE self
-- @param #string ObjectName
-- @param Base#BASE Object
-- @return Base#BASE The added BASE Object.
-- @param Core.Base#BASE Object
-- @return Core.Base#BASE The added BASE Object.
function SET_BASE:Add( ObjectName, Object )
self:F2( ObjectName )
@ -311,7 +310,22 @@ function SET_BASE:Add( ObjectName, Object )
end
--- Removes a @{Base#BASE} object from the @{Set#SET_BASE} and derived classes, based on the Object Name.
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using the Object Name as the index.
-- @param #SET_BASE self
-- @param Wrapper.Object#OBJECT Object
-- @return Core.Base#BASE The added BASE Object.
function SET_BASE:AddObject( Object )
self:F2( Object.ObjectName )
self:T( Object.UnitName )
self:T( Object.ObjectName )
self:Add( Object.ObjectName, Object )
end
--- Removes a @{Core.Base#BASE} object from the @{Core.Set#SET_BASE} and derived classes, based on the Object Name.
-- @param #SET_BASE self
-- @param #string ObjectName
function SET_BASE:Remove( ObjectName )
@ -350,7 +364,22 @@ function SET_BASE:Remove( ObjectName )
end
--- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes.
--- Gets a @{Core.Base#BASE} object from the @{Core.Set#SET_BASE} and derived classes, based on the Object Name.
-- @param #SET_BASE self
-- @param #string ObjectName
-- @return Core.Base#BASE
function SET_BASE:Get( ObjectName )
self:F( ObjectName )
local t = self.Set[ObjectName]
self:T3( { ObjectName, t } )
return t
end
--- Retrieves the amount of objects in the @{Core.Set#SET_BASE} and derived classes.
-- @param #SET_BASE self
-- @return #number Count
function SET_BASE:Count()
@ -443,10 +472,10 @@ function SET_BASE:FilterStop()
return self
end
--- Iterate the SET_BASE while identifying the nearest object from a @{Point#POINT_VEC2}.
--- Iterate the SET_BASE while identifying the nearest object from a @{Core.Point#POINT_VEC2}.
-- @param #SET_BASE self
-- @param Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest object in the set.
-- @return Base#BASE The closest object.
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest object in the set.
-- @return Core.Base#BASE The closest object.
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
self:F2( PointVec2 )
@ -497,7 +526,7 @@ end
--- Handles the OnBirth event for the Set.
-- @param #SET_BASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function SET_BASE:_EventOnBirth( Event )
self:F3( { Event } )
@ -513,7 +542,7 @@ end
--- Handles the OnDead or OnCrash event for alive units set.
-- @param #SET_BASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function SET_BASE:_EventOnDeadOrCrash( Event )
self:F3( { Event } )
@ -527,7 +556,7 @@ end
--- Handles the OnPlayerEnterUnit event to fill the active players table (with the unit filter applied).
-- @param #SET_BASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function SET_BASE:_EventOnPlayerEnterUnit( Event )
self:F3( { Event } )
@ -543,7 +572,7 @@ end
--- Handles the OnPlayerLeaveUnit event to clean the active players table.
-- @param #SET_BASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function SET_BASE:_EventOnPlayerLeaveUnit( Event )
self:F3( { Event } )
@ -576,6 +605,9 @@ end
function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArguments )
self:F3( arg )
Set = Set or self:GetSet()
arg = arg or {}
local function CoRoutine()
local Count = 0
for ObjectID, ObjectData in pairs( Set ) do
@ -688,7 +720,7 @@ end
--- SET_GROUP class
-- @type SET_GROUP
-- @extends Set#SET_BASE
-- @extends #SET_BASE
SET_GROUP = {
ClassName = "SET_GROUP",
Filter = {
@ -729,7 +761,7 @@ function SET_GROUP:New()
end
--- Add GROUP(s) to SET_GROUP.
-- @param Set#SET_GROUP self
-- @param Core.Set#SET_GROUP self
-- @param #string AddGroupNames A single name or an array of GROUP names.
-- @return self
function SET_GROUP:AddGroupsByName( AddGroupNames )
@ -744,8 +776,8 @@ function SET_GROUP:AddGroupsByName( AddGroupNames )
end
--- Remove GROUP(s) from SET_GROUP.
-- @param Set#SET_GROUP self
-- @param Group#GROUP RemoveGroupNames A single name or an array of GROUP names.
-- @param Core.Set#SET_GROUP self
-- @param Wrapper.Group#GROUP RemoveGroupNames A single name or an array of GROUP names.
-- @return self
function SET_GROUP:RemoveGroupsByName( RemoveGroupNames )
@ -764,7 +796,7 @@ end
--- Finds a Group based on the Group Name.
-- @param #SET_GROUP self
-- @param #string GroupName
-- @return Group#GROUP The found Group.
-- @return Wrapper.Group#GROUP The found Group.
function SET_GROUP:FindGroup( GroupName )
local GroupFound = self.Set[GroupName]
@ -865,7 +897,7 @@ 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_GROUP self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the GROUP
-- @return #table The GROUP
function SET_GROUP:AddInDatabase( Event )
@ -882,7 +914,7 @@ 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_GROUP self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the GROUP
-- @return #table The GROUP
function SET_GROUP:FindInDatabase( Event )
@ -905,15 +937,15 @@ end
--- Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence completely in a @{Zone}, providing the GROUP and optional parameters to the called function.
-- @param #SET_GROUP self
-- @param Zone#ZONE ZoneObject The Zone to be tested for.
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the SET_GROUP. The function needs to accept a GROUP parameter.
-- @return #SET_GROUP self
function SET_GROUP:ForEachGroupCompletelyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Group#GROUP GroupObject
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Group#GROUP GroupObject
function( ZoneObject, GroupObject )
if GroupObject:IsCompletelyInZone( ZoneObject ) then
return true
@ -927,15 +959,15 @@ end
--- Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence partly in a @{Zone}, providing the GROUP and optional parameters to the called function.
-- @param #SET_GROUP self
-- @param Zone#ZONE ZoneObject The Zone to be tested for.
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the SET_GROUP. The function needs to accept a GROUP parameter.
-- @return #SET_GROUP self
function SET_GROUP:ForEachGroupPartlyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Group#GROUP GroupObject
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Group#GROUP GroupObject
function( ZoneObject, GroupObject )
if GroupObject:IsPartlyInZone( ZoneObject ) then
return true
@ -949,15 +981,15 @@ end
--- Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence not in a @{Zone}, providing the GROUP and optional parameters to the called function.
-- @param #SET_GROUP self
-- @param Zone#ZONE ZoneObject The Zone to be tested for.
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the SET_GROUP. The function needs to accept a GROUP parameter.
-- @return #SET_GROUP self
function SET_GROUP:ForEachGroupNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Group#GROUP GroupObject
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Group#GROUP GroupObject
function( ZoneObject, GroupObject )
if GroupObject:IsNotInZone( ZoneObject ) then
return true
@ -998,7 +1030,7 @@ end
---
-- @param #SET_GROUP self
-- @param Group#GROUP MooseGroup
-- @param Wrapper.Group#GROUP MooseGroup
-- @return #SET_GROUP self
function SET_GROUP:IsIncludeObject( MooseGroup )
self:F2( MooseGroup )
@ -1054,7 +1086,7 @@ end
--- SET_UNIT class
-- @type SET_UNIT
-- @extends Set#SET_BASE
-- @extends Core.Set#SET_BASE
SET_UNIT = {
ClassName = "SET_UNIT",
Units = {},
@ -1126,8 +1158,8 @@ function SET_UNIT:AddUnitsByName( AddUnitNames )
end
--- Remove UNIT(s) from SET_UNIT.
-- @param Set#SET_UNIT self
-- @param Unit#UNIT RemoveUnitNames A single name or an array of UNIT names.
-- @param Core.Set#SET_UNIT self
-- @param Wrapper.Unit#UNIT RemoveUnitNames A single name or an array of UNIT names.
-- @return self
function SET_UNIT:RemoveUnitsByName( RemoveUnitNames )
@ -1144,7 +1176,7 @@ end
--- Finds a Unit based on the Unit Name.
-- @param #SET_UNIT self
-- @param #string UnitName
-- @return Unit#UNIT The found Unit.
-- @return Wrapper.Unit#UNIT The found Unit.
function SET_UNIT:FindUnit( UnitName )
local UnitFound = self.Set[UnitName]
@ -1290,7 +1322,7 @@ 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_UNIT self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the UNIT
-- @return #table The UNIT
function SET_UNIT:AddInDatabase( Event )
@ -1307,7 +1339,7 @@ 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_UNIT self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the UNIT
-- @return #table The UNIT
function SET_UNIT:FindInDatabase( Event )
@ -1331,15 +1363,15 @@ end
--- Iterate the SET_UNIT and call an iterator function for each **alive** UNIT presence completely in a @{Zone}, providing the UNIT and optional parameters to the called function.
-- @param #SET_UNIT self
-- @param Zone#ZONE ZoneObject The Zone to be tested for.
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
function SET_UNIT:ForEachUnitCompletelyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Unit#UNIT UnitObject
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsCompletelyInZone( ZoneObject ) then
return true
@ -1353,15 +1385,15 @@ end
--- Iterate the SET_UNIT and call an iterator function for each **alive** UNIT presence not in a @{Zone}, providing the UNIT and optional parameters to the called function.
-- @param #SET_UNIT self
-- @param Zone#ZONE ZoneObject The Zone to be tested for.
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
function SET_UNIT:ForEachUnitNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Unit#UNIT UnitObject
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsNotInZone( ZoneObject ) then
return true
@ -1383,7 +1415,7 @@ function SET_UNIT:GetUnitTypes()
local UnitTypes = {}
for UnitID, UnitData in pairs( self:GetSet() ) do
local TextUnit = UnitData -- Unit#UNIT
local TextUnit = UnitData -- Wrapper.Unit#UNIT
if TextUnit:IsAlive() then
local UnitType = TextUnit:GetTypeName()
@ -1428,7 +1460,7 @@ function SET_UNIT:GetUnitThreatLevels()
local UnitThreatLevels = {}
for UnitID, UnitData in pairs( self:GetSet() ) do
local ThreatUnit = UnitData -- Unit#UNIT
local ThreatUnit = UnitData -- Wrapper.Unit#UNIT
if ThreatUnit:IsAlive() then
local UnitThreatLevel, UnitThreatLevelText = ThreatUnit:GetThreatLevel()
local ThreatUnitName = ThreatUnit:GetName()
@ -1445,14 +1477,14 @@ end
--- Returns if the @{Set} has targets having a radar (of a given type).
-- @param #SET_UNIT self
-- @param DCSUnit#Unit.RadarType RadarType
-- @param Dcs.DCSWrapper.Unit#Unit.RadarType RadarType
-- @return #number The amount of radars in the Set with the given type
function SET_UNIT:HasRadar( RadarType )
self:F2( RadarType )
local RadarCount = 0
for UnitID, UnitData in pairs( self:GetSet()) do
local UnitSensorTest = UnitData -- Unit#UNIT
local UnitSensorTest = UnitData -- Wrapper.Unit#UNIT
local HasSensors
if RadarType then
HasSensors = UnitSensorTest:HasSensors( Unit.SensorType.RADAR, RadarType )
@ -1476,7 +1508,7 @@ function SET_UNIT:HasSEAD()
local SEADCount = 0
for UnitID, UnitData in pairs( self:GetSet()) do
local UnitSEAD = UnitData -- Unit#UNIT
local UnitSEAD = UnitData -- Wrapper.Unit#UNIT
if UnitSEAD:IsAlive() then
local UnitSEADAttributes = UnitSEAD:GetDesc().attributes
@ -1500,7 +1532,7 @@ function SET_UNIT:HasGroundUnits()
local GroundUnitCount = 0
for UnitID, UnitData in pairs( self:GetSet()) do
local UnitTest = UnitData -- Unit#UNIT
local UnitTest = UnitData -- Wrapper.Unit#UNIT
if UnitTest:IsGround() then
GroundUnitCount = GroundUnitCount + 1
end
@ -1517,7 +1549,7 @@ function SET_UNIT:HasFriendlyUnits( FriendlyCoalition )
local FriendlyUnitCount = 0
for UnitID, UnitData in pairs( self:GetSet()) do
local UnitTest = UnitData -- Unit#UNIT
local UnitTest = UnitData -- Wrapper.Unit#UNIT
if UnitTest:IsFriendly( FriendlyCoalition ) then
FriendlyUnitCount = FriendlyUnitCount + 1
end
@ -1556,7 +1588,7 @@ end
---
-- @param #SET_UNIT self
-- @param Unit#UNIT MUnit
-- @param Wrapper.Unit#UNIT MUnit
-- @return #SET_UNIT self
function SET_UNIT:IsIncludeObject( MUnit )
self:F2( MUnit )
@ -1649,7 +1681,7 @@ end
--- SET_CLIENT class
-- @type SET_CLIENT
-- @extends Set#SET_BASE
-- @extends Core.Set#SET_BASE
SET_CLIENT = {
ClassName = "SET_CLIENT",
Clients = {},
@ -1691,7 +1723,7 @@ function SET_CLIENT:New()
end
--- Add CLIENT(s) to SET_CLIENT.
-- @param Set#SET_CLIENT self
-- @param Core.Set#SET_CLIENT self
-- @param #string AddClientNames A single name or an array of CLIENT names.
-- @return self
function SET_CLIENT:AddClientsByName( AddClientNames )
@ -1706,8 +1738,8 @@ function SET_CLIENT:AddClientsByName( AddClientNames )
end
--- Remove CLIENT(s) from SET_CLIENT.
-- @param Set#SET_CLIENT self
-- @param Client#CLIENT RemoveClientNames A single name or an array of CLIENT names.
-- @param Core.Set#SET_CLIENT self
-- @param Wrapper.Client#CLIENT RemoveClientNames A single name or an array of CLIENT names.
-- @return self
function SET_CLIENT:RemoveClientsByName( RemoveClientNames )
@ -1724,7 +1756,7 @@ end
--- Finds a Client based on the Client Name.
-- @param #SET_CLIENT self
-- @param #string ClientName
-- @return Client#CLIENT The found Client.
-- @return Wrapper.Client#CLIENT The found Client.
function SET_CLIENT:FindClient( ClientName )
local ClientFound = self.Set[ClientName]
@ -1845,7 +1877,7 @@ 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_CLIENT self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the CLIENT
-- @return #table The CLIENT
function SET_CLIENT:AddInDatabase( Event )
@ -1857,7 +1889,7 @@ 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_CLIENT self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the CLIENT
-- @return #table The CLIENT
function SET_CLIENT:FindInDatabase( Event )
@ -1880,15 +1912,15 @@ end
--- Iterate the SET_CLIENT and call an iterator function for each **alive** CLIENT presence completely in a @{Zone}, providing the CLIENT and optional parameters to the called function.
-- @param #SET_CLIENT self
-- @param Zone#ZONE ZoneObject The Zone to be tested for.
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
-- @return #SET_CLIENT self
function SET_CLIENT:ForEachClientInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Client#CLIENT ClientObject
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Client#CLIENT ClientObject
function( ZoneObject, ClientObject )
if ClientObject:IsInZone( ZoneObject ) then
return true
@ -1902,15 +1934,15 @@ end
--- Iterate the SET_CLIENT and call an iterator function for each **alive** CLIENT presence not in a @{Zone}, providing the CLIENT and optional parameters to the called function.
-- @param #SET_CLIENT self
-- @param Zone#ZONE ZoneObject The Zone to be tested for.
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
-- @return #SET_CLIENT self
function SET_CLIENT:ForEachClientNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Client#CLIENT ClientObject
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Client#CLIENT ClientObject
function( ZoneObject, ClientObject )
if ClientObject:IsNotInZone( ZoneObject ) then
return true
@ -1924,7 +1956,7 @@ end
---
-- @param #SET_CLIENT self
-- @param Client#CLIENT MClient
-- @param Wrapper.Client#CLIENT MClient
-- @return #SET_CLIENT self
function SET_CLIENT:IsIncludeObject( MClient )
self:F2( MClient )
@ -2006,7 +2038,7 @@ end
--- SET_AIRBASE class
-- @type SET_AIRBASE
-- @extends Set#SET_BASE
-- @extends Core.Set#SET_BASE
SET_AIRBASE = {
ClassName = "SET_AIRBASE",
Airbases = {},
@ -2042,7 +2074,7 @@ function SET_AIRBASE:New()
end
--- Add AIRBASEs to SET_AIRBASE.
-- @param Set#SET_AIRBASE self
-- @param Core.Set#SET_AIRBASE self
-- @param #string AddAirbaseNames A single name or an array of AIRBASE names.
-- @return self
function SET_AIRBASE:AddAirbasesByName( AddAirbaseNames )
@ -2057,8 +2089,8 @@ function SET_AIRBASE:AddAirbasesByName( AddAirbaseNames )
end
--- Remove AIRBASEs from SET_AIRBASE.
-- @param Set#SET_AIRBASE self
-- @param Airbase#AIRBASE RemoveAirbaseNames A single name or an array of AIRBASE names.
-- @param Core.Set#SET_AIRBASE self
-- @param Wrapper.Airbase#AIRBASE RemoveAirbaseNames A single name or an array of AIRBASE names.
-- @return self
function SET_AIRBASE:RemoveAirbasesByName( RemoveAirbaseNames )
@ -2075,7 +2107,7 @@ end
--- Finds a Airbase based on the Airbase Name.
-- @param #SET_AIRBASE self
-- @param #string AirbaseName
-- @return Airbase#AIRBASE The found Airbase.
-- @return Wrapper.Airbase#AIRBASE The found Airbase.
function SET_AIRBASE:FindAirbase( AirbaseName )
local AirbaseFound = self.Set[AirbaseName]
@ -2137,7 +2169,7 @@ 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_AIRBASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the AIRBASE
-- @return #table The AIRBASE
function SET_AIRBASE:AddInDatabase( Event )
@ -2149,7 +2181,7 @@ 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_AIRBASE self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the AIRBASE
-- @return #table The AIRBASE
function SET_AIRBASE:FindInDatabase( Event )
@ -2170,10 +2202,10 @@ function SET_AIRBASE:ForEachAirbase( IteratorFunction, ... )
return self
end
--- Iterate the SET_AIRBASE while identifying the nearest @{Airbase#AIRBASE} from a @{Point#POINT_VEC2}.
--- Iterate the SET_AIRBASE while identifying the nearest @{Wrapper.Airbase#AIRBASE} from a @{Core.Point#POINT_VEC2}.
-- @param #SET_AIRBASE self
-- @param Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest @{Airbase#AIRBASE}.
-- @return Airbase#AIRBASE The closest @{Airbase#AIRBASE}.
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest @{Wrapper.Airbase#AIRBASE}.
-- @return Wrapper.Airbase#AIRBASE The closest @{Wrapper.Airbase#AIRBASE}.
function SET_AIRBASE:FindNearestAirbaseFromPointVec2( PointVec2 )
self:F2( PointVec2 )
@ -2185,7 +2217,7 @@ end
---
-- @param #SET_AIRBASE self
-- @param Airbase#AIRBASE MAirbase
-- @param Wrapper.Airbase#AIRBASE MAirbase
-- @return #SET_AIRBASE self
function SET_AIRBASE:IsIncludeObject( MAirbase )
self:F2( MAirbase )

View File

@ -1,4 +1,4 @@
--- This module contains the ZONE classes, inherited from @{Zone#ZONE_BASE}.
--- This module contains the ZONE classes, inherited from @{Core.Zone#ZONE_BASE}.
-- There are essentially two core functions that zones accomodate:
--
-- * Test if an object is within the zone boundaries.
@ -7,7 +7,7 @@
-- The object classes are using the zone classes to test the zone boundaries, which can take various forms:
--
-- * Test if completely within the zone.
-- * Test if partly within the zone (for @{Group#GROUP} objects).
-- * Test if partly within the zone (for @{Wrapper.Group#GROUP} objects).
-- * Test if not in the zone.
-- * Distance to the nearest intersecting point of the zone.
-- * Distance to the center of the zone.
@ -15,53 +15,125 @@
--
-- Each of these ZONE classes have a zone name, and specific parameters defining the zone type:
--
-- * @{Zone#ZONE_BASE}: The ZONE_BASE class defining the base for all other zone classes.
-- * @{Zone#ZONE_RADIUS}: The ZONE_RADIUS class defined by a zone name, a location and a radius.
-- * @{Zone#ZONE}: The ZONE class, defined by the zone name as defined within the Mission Editor.
-- * @{Zone#ZONE_UNIT}: The ZONE_UNIT class defines by a zone around a @{Unit#UNIT} with a radius.
-- * @{Zone#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius.
-- * @{Zone#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
--
-- Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}:
--
-- * @{#ZONE_BASE.IsPointVec2InZone}: Returns if a location is within the zone.
-- * @{#ZONE_BASE.IsPointVec3InZone}: Returns if a point is within the zone.
-- * @{Core.Zone#ZONE_BASE}: The ZONE_BASE class defining the base for all other zone classes.
-- * @{Core.Zone#ZONE_RADIUS}: The ZONE_RADIUS class defined by a zone name, a location and a radius.
-- * @{Core.Zone#ZONE}: The ZONE class, defined by the zone name as defined within the Mission Editor.
-- * @{Core.Zone#ZONE_UNIT}: The ZONE_UNIT class defines by a zone around a @{Wrapper.Unit#UNIT} with a radius.
-- * @{Core.Zone#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius.
-- * @{Core.Zone#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
--
-- ===
--
-- 1) @{Zone#ZONE_BASE} class, extends @{Base#BASE}
-- 1) @{Core.Zone#ZONE_BASE} class, extends @{Core.Base#BASE}
-- ================================================
-- The ZONE_BASE class defining the base for all other zone classes.
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
--
-- ### 1.1) Each zone has a name:
--
-- * @{#ZONE_BASE.GetName}(): Returns the name of the zone.
--
-- ### 1.2) Each zone implements two polymorphic functions defined in @{Core.Zone#ZONE_BASE}:
--
-- * @{#ZONE_BASE.IsPointVec2InZone}(): Returns if a @{Core.Point#POINT_VEC2} is within the zone.
-- * @{#ZONE_BASE.IsPointVec3InZone}(): Returns if a @{Core.Point#POINT_VEC3} is within the zone.
--
-- ### 1.3) 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:
--
-- * @{#ZONE_BASE.GetVec2}(): Returns the @{Dcs.DCSTypes#Vec2} coordinate of the zone.
-- * @{#ZONE_BASE.GetRandomVec2}(): Define a random @{Dcs.DCSTypes#Vec2} within the zone.
--
-- ### 1.5) 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:
--
-- * @{#ZONE_BASE.SmokeZone}(): Smokes the zone boundaries in a color.
-- * @{#ZONE_BASE.FlareZone}(): Flares the zone boundaries in a color.
--
-- ===
--
-- 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE}
-- 2) @{Core.Zone#ZONE_RADIUS} class, extends @{Core.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) @{Core.Zone#ZONE_RADIUS} constructor:
--
-- * @{#ZONE_BASE.New}(): Constructor.
--
-- ### 2.2) Manage the radius of the zone:
--
-- * @{#ZONE_BASE.SetRadius}(): Sets the radius of the zone.
-- * @{#ZONE_BASE.GetRadius}(): Returns the radius of the zone.
--
-- ### 2.3) Manage the location of the zone:
--
-- * @{#ZONE_BASE.SetVec2}(): Sets the @{Dcs.DCSTypes#Vec2} of the zone.
-- * @{#ZONE_BASE.GetVec2}(): Returns the @{Dcs.DCSTypes#Vec2} of the zone.
-- * @{#ZONE_BASE.GetVec3}(): Returns the @{Dcs.DCSTypes#Vec3} of the zone, taking an additional height parameter.
--
-- ===
--
-- 3) @{Zone#ZONE} class, extends @{Zone#ZONE_RADIUS}
-- 3) @{Core.Zone#ZONE} class, extends @{Core.Zone#ZONE_RADIUS}
-- ==========================================
-- The ZONE class, defined by the zone name as defined within the Mission Editor.
-- This class implements the inherited functions from {Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
--
-- ===
--
-- 4) @{Zone#ZONE_UNIT} class, extends @{Zone#ZONE_RADIUS}
-- 4) @{Core.Zone#ZONE_UNIT} class, extends @{Core.Zone#ZONE_RADIUS}
-- =======================================================
-- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius.
-- The ZONE_UNIT class defined by a zone around a @{Wrapper.Unit#UNIT} with a radius.
-- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
--
-- ===
--
-- 5) @{Zone#ZONE_GROUP} class, extends @{Zone#ZONE_RADIUS}
-- 5) @{Core.Zone#ZONE_GROUP} class, extends @{Core.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.
-- The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius. The current leader of the group defines the center of the zone.
-- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
--
-- ===
--
-- 6) @{Zone#ZONE_POLYGON} class, extends @{Zone#ZONE_BASE}
-- 6) @{Core.Zone#ZONE_POLYGON_BASE} class, extends @{Core.Zone#ZONE_BASE}
-- ========================================================
-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- The ZONE_POLYGON_BASE class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- This class implements the inherited functions from @{Core.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.
--
-- ===
--
-- 7) @{Core.Zone#ZONE_POLYGON} class, extends @{Core.Zone#ZONE_POLYGON_BASE}
-- ================================================================
-- The ZONE_POLYGON class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
--
-- ====
--
-- **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:
--
-- 2016-08-15: ZONE_BASE:**GetName()** added.
--
-- 2016-08-15: ZONE_BASE:**SetZoneProbability( ZoneProbability )** added.
--
-- 2016-08-15: ZONE_BASE:**GetZoneProbability()** added.
--
-- 2016-08-15: ZONE_BASE:**GetZoneMaybe()** added.
--
-- ===
--
@ -72,18 +144,21 @@
--- The ZONE_BASE class
-- @type ZONE_BASE
-- @field #string ZoneName Name of the zone.
-- @extends Base#BASE
-- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
-- @extends Core.Base#BASE
ZONE_BASE = {
ClassName = "ZONE_BASE",
ZoneName = "",
ZoneProbability = 1,
}
--- The ZONE_BASE.BoundingSquare
-- @type ZONE_BASE.BoundingSquare
-- @field DCSTypes#Distance x1 The lower x coordinate (left down)
-- @field DCSTypes#Distance y1 The lower y coordinate (left down)
-- @field DCSTypes#Distance x2 The higher x coordinate (right up)
-- @field DCSTypes#Distance y2 The higher y coordinate (right up)
-- @field Dcs.DCSTypes#Distance x1 The lower x coordinate (left down)
-- @field Dcs.DCSTypes#Distance y1 The lower y coordinate (left down)
-- @field Dcs.DCSTypes#Distance x2 The higher x coordinate (right up)
-- @field Dcs.DCSTypes#Distance y2 The higher y coordinate (right up)
--- ZONE_BASE constructor
@ -99,9 +174,17 @@ function ZONE_BASE:New( ZoneName )
return self
end
--- Returns the name of the zone.
-- @param #ZONE_BASE self
-- @return #string The name of the zone.
function ZONE_BASE:GetName()
self:F2()
return self.ZoneName
end
--- Returns if a location is within the zone.
-- @param #ZONE_BASE self
-- @param DCSTypes#Vec2 Vec2 The location to test.
-- @param Dcs.DCSTypes#Vec2 Vec2 The location to test.
-- @return #boolean true if the location is within the zone.
function ZONE_BASE:IsPointVec2InZone( Vec2 )
self:F2( Vec2 )
@ -111,7 +194,7 @@ end
--- Returns if a point is within the zone.
-- @param #ZONE_BASE self
-- @param DCSTypes#Vec3 Vec3 The point to test.
-- @param Dcs.DCSTypes#Vec3 Vec3 The point to test.
-- @return #boolean true if the point is within the zone.
function ZONE_BASE:IsPointVec3InZone( Vec3 )
self:F2( Vec3 )
@ -121,7 +204,7 @@ function ZONE_BASE:IsPointVec3InZone( Vec3 )
return InZone
end
--- Returns the Vec2 coordinate of the zone.
--- Returns the @{Dcs.DCSTypes#Vec2} coordinate of the zone.
-- @param #ZONE_BASE self
-- @return #nil.
function ZONE_BASE:GetVec2()
@ -129,9 +212,9 @@ function ZONE_BASE:GetVec2()
return nil
end
--- Define a random @{DCSTypes#Vec2} within the zone.
--- Define a random @{Dcs.DCSTypes#Vec2} within the zone.
-- @param #ZONE_BASE self
-- @return #nil The Vec2 coordinates.
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinates.
function ZONE_BASE:GetRandomVec2()
return nil
end
@ -147,27 +230,61 @@ end
--- Smokes the zone boundaries in a color.
-- @param #ZONE_BASE self
-- @param SmokeColor The smoke color.
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
function ZONE_BASE:SmokeZone( SmokeColor )
self:F2( SmokeColor )
end
--- Set the randomization probability of a zone to be selected.
-- @param #ZONE_BASE self
-- @param ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
function ZONE_BASE:SetZoneProbability( ZoneProbability )
self:F2( ZoneProbability )
self.ZoneProbability = ZoneProbability or 1
return self
end
--- Get the randomization probability of a zone to be selected.
-- @param #ZONE_BASE self
-- @return #number A value between 0 and 1. 0 = 0% and 1 = 100% probability.
function ZONE_BASE:GetZoneProbability()
self:F2()
return self.ZoneProbability
end
--- Get the zone taking into account the randomization probability of a zone to be selected.
-- @param #ZONE_BASE self
-- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor.
-- @return #nil The zone is not selected taking into account the randomization probability factor.
function ZONE_BASE:GetZoneMaybe()
self:F2()
local Randomization = math.random()
if Randomization <= self.ZoneProbability then
return self
else
return nil
end
end
--- The ZONE_RADIUS class, defined by a zone name, a location and a radius.
-- @type ZONE_RADIUS
-- @field DCSTypes#Vec2 Vec2 The current location of the zone.
-- @field DCSTypes#Distance Radius The radius of the zone.
-- @extends Zone#ZONE_BASE
-- @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
ZONE_RADIUS = {
ClassName="ZONE_RADIUS",
}
--- Constructor of ZONE_RADIUS, taking the zone name, the zone location and a radius.
--- Constructor of @{#ZONE_RADIUS}, taking the zone name, the zone location and a radius.
-- @param #ZONE_RADIUS self
-- @param #string ZoneName Name of the zone.
-- @param DCSTypes#Vec2 Vec2 The location of the zone.
-- @param DCSTypes#Distance Radius The radius of the zone.
-- @param Dcs.DCSTypes#Vec2 Vec2 The location of the zone.
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
-- @return #ZONE_RADIUS self
function ZONE_RADIUS:New( ZoneName, Vec2, Radius )
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) )
@ -181,7 +298,7 @@ end
--- Smokes the zone boundaries in a color.
-- @param #ZONE_RADIUS self
-- @param #POINT_VEC3.SmokeColor SmokeColor The smoke color.
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
-- @param #number Points (optional) The amount of points in the circle.
-- @return #ZONE_RADIUS self
function ZONE_RADIUS:SmokeZone( SmokeColor, Points )
@ -208,9 +325,9 @@ end
--- Flares the zone boundaries in a color.
-- @param #ZONE_RADIUS self
-- @param #POINT_VEC3.FlareColor FlareColor The flare color.
-- @param Utilities.Utils#FLARECOLOR FlareColor The flare color.
-- @param #number Points (optional) The amount of points in the circle.
-- @param DCSTypes#Azimuth Azimuth (optional) Azimuth The azimuth of the flare.
-- @param Dcs.DCSTypes#Azimuth Azimuth (optional) Azimuth The azimuth of the flare.
-- @return #ZONE_RADIUS self
function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth )
self:F2( { FlareColor, Azimuth } )
@ -235,7 +352,7 @@ end
--- Returns the radius of the zone.
-- @param #ZONE_RADIUS self
-- @return DCSTypes#Distance The radius of the zone.
-- @return Dcs.DCSTypes#Distance The radius of the zone.
function ZONE_RADIUS:GetRadius()
self:F2( self.ZoneName )
@ -246,8 +363,8 @@ end
--- Sets the radius of the zone.
-- @param #ZONE_RADIUS self
-- @param DCSTypes#Distance Radius The radius of the zone.
-- @return DCSTypes#Distance The radius of the zone.
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
-- @return Dcs.DCSTypes#Distance The radius of the zone.
function ZONE_RADIUS:SetRadius( Radius )
self:F2( self.ZoneName )
@ -257,9 +374,9 @@ function ZONE_RADIUS:SetRadius( Radius )
return self.Radius
end
--- Returns the location of the zone.
--- Returns the @{Dcs.DCSTypes#Vec2} of the zone.
-- @param #ZONE_RADIUS self
-- @return DCSTypes#Vec2 The location of the zone.
-- @return Dcs.DCSTypes#Vec2 The location of the zone.
function ZONE_RADIUS:GetVec2()
self:F2( self.ZoneName )
@ -268,11 +385,11 @@ function ZONE_RADIUS:GetVec2()
return self.Vec2
end
--- Sets the location of the zone.
--- Sets the @{Dcs.DCSTypes#Vec2} of the zone.
-- @param #ZONE_RADIUS self
-- @param DCSTypes#Vec2 Vec2 The new location of the zone.
-- @return DCSTypes#Vec2 The new location of the zone.
function ZONE_RADIUS:SetPointVec2( Vec2 )
-- @param Dcs.DCSTypes#Vec2 Vec2 The new location of the zone.
-- @return Dcs.DCSTypes#Vec2 The new location of the zone.
function ZONE_RADIUS:SetVec2( Vec2 )
self:F2( self.ZoneName )
self.Vec2 = Vec2
@ -282,10 +399,10 @@ function ZONE_RADIUS:SetPointVec2( Vec2 )
return self.Vec2
end
--- Returns the @{DCSTypes#Vec3} of the ZONE_RADIUS.
--- Returns the @{Dcs.DCSTypes#Vec3} of the ZONE_RADIUS.
-- @param #ZONE_RADIUS self
-- @param DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return DCSTypes#Vec3 The point of the zone.
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Dcs.DCSTypes#Vec3 The point of the zone.
function ZONE_RADIUS:GetVec3( Height )
self:F2( { self.ZoneName, Height } )
@ -302,7 +419,7 @@ end
--- Returns if a location is within the zone.
-- @param #ZONE_RADIUS self
-- @param DCSTypes#Vec2 Vec2 The location to test.
-- @param Dcs.DCSTypes#Vec2 Vec2 The location to test.
-- @return #boolean true if the location is within the zone.
function ZONE_RADIUS:IsPointVec2InZone( Vec2 )
self:F2( Vec2 )
@ -320,7 +437,7 @@ end
--- Returns if a point is within the zone.
-- @param #ZONE_RADIUS self
-- @param DCSTypes#Vec3 Vec3 The point to test.
-- @param Dcs.DCSTypes#Vec3 Vec3 The point to test.
-- @return #boolean true if the point is within the zone.
function ZONE_RADIUS:IsPointVec3InZone( Vec3 )
self:F2( Vec3 )
@ -332,7 +449,7 @@ end
--- Returns a random location within the zone.
-- @param #ZONE_RADIUS self
-- @return DCSTypes#Vec2 The random location within the zone.
-- @return Dcs.DCSTypes#Vec2 The random location within the zone.
function ZONE_RADIUS:GetRandomVec2()
self:F( self.ZoneName )
@ -352,7 +469,7 @@ end
--- The ZONE class, defined by the zone name as defined within the Mission Editor. The location and the radius are automatically collected from the mission settings.
-- @type ZONE
-- @extends Zone#ZONE_RADIUS
-- @extends Core.Zone#ZONE_RADIUS
ZONE = {
ClassName="ZONE",
}
@ -380,10 +497,10 @@ function ZONE:New( ZoneName )
end
--- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius.
--- The ZONE_UNIT class defined by a zone around a @{Wrapper.Unit#UNIT} with a radius.
-- @type ZONE_UNIT
-- @field Unit#UNIT ZoneUNIT
-- @extends Zone#ZONE_RADIUS
-- @field Wrapper.Unit#UNIT ZoneUNIT
-- @extends Core.Zone#ZONE_RADIUS
ZONE_UNIT = {
ClassName="ZONE_UNIT",
}
@ -391,8 +508,8 @@ ZONE_UNIT = {
--- Constructor to create a ZONE_UNIT instance, taking the zone name, a zone unit and a radius.
-- @param #ZONE_UNIT self
-- @param #string ZoneName Name of the zone.
-- @param Unit#UNIT ZoneUNIT The unit as the center of the zone.
-- @param DCSTypes#Distance Radius The radius of the zone.
-- @param Wrapper.Unit#UNIT ZoneUNIT The unit as the center of the zone.
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
-- @return #ZONE_UNIT self
function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius )
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetVec2(), Radius ) )
@ -405,9 +522,9 @@ function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius )
end
--- Returns the current location of the @{Unit#UNIT}.
--- Returns the current location of the @{Wrapper.Unit#UNIT}.
-- @param #ZONE_UNIT self
-- @return DCSTypes#Vec2 The location of the zone based on the @{Unit#UNIT}location.
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Wrapper.Unit#UNIT}location.
function ZONE_UNIT:GetVec2()
self:F( self.ZoneName )
@ -426,29 +543,30 @@ end
--- Returns a random location within the zone.
-- @param #ZONE_UNIT self
-- @return DCSTypes#Vec2 The random location within the zone.
-- @return Dcs.DCSTypes#Vec2 The random location within the zone.
function ZONE_UNIT:GetRandomVec2()
self:F( self.ZoneName )
local Point = {}
local PointVec2 = self.ZoneUNIT:GetPointVec2()
if not PointVec2 then
PointVec2 = self.LastVec2
local RandomVec2 = {}
local Vec2 = self.ZoneUNIT:GetVec2()
if not Vec2 then
Vec2 = self.LastVec2
end
local angle = math.random() * math.pi*2;
Point.x = PointVec2.x + math.cos( angle ) * math.random() * self:GetRadius();
Point.y = PointVec2.y + math.sin( angle ) * math.random() * self:GetRadius();
RandomVec2.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius();
RandomVec2.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius();
self:T( { Point } )
self:T( { RandomVec2 } )
return Point
return RandomVec2
end
--- Returns the @{DCSTypes#Vec3} of the ZONE_UNIT.
--- Returns the @{Dcs.DCSTypes#Vec3} of the ZONE_UNIT.
-- @param #ZONE_UNIT self
-- @param DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return DCSTypes#Vec3 The point of the zone.
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Dcs.DCSTypes#Vec3 The point of the zone.
function ZONE_UNIT:GetVec3( Height )
self:F2( self.ZoneName )
@ -465,17 +583,17 @@ end
--- The ZONE_GROUP class defined by a zone around a @{Group}, taking the average center point of all the units within the Group, with a radius.
-- @type ZONE_GROUP
-- @field Group#GROUP ZoneGROUP
-- @extends Zone#ZONE_RADIUS
-- @field Wrapper.Group#GROUP ZoneGROUP
-- @extends Core.Zone#ZONE_RADIUS
ZONE_GROUP = {
ClassName="ZONE_GROUP",
}
--- Constructor to create a ZONE_GROUP instance, taking the zone name, a zone @{Group#GROUP} and a radius.
--- Constructor to create a ZONE_GROUP instance, taking the zone name, a zone @{Wrapper.Group#GROUP} and a radius.
-- @param #ZONE_GROUP self
-- @param #string ZoneName Name of the zone.
-- @param Group#GROUP ZoneGROUP The @{Group} as the center of the zone.
-- @param DCSTypes#Distance Radius The radius of the zone.
-- @param Wrapper.Group#GROUP ZoneGROUP The @{Group} as the center of the zone.
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
-- @return #ZONE_GROUP self
function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius )
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) )
@ -489,7 +607,7 @@ end
--- Returns the current location of the @{Group}.
-- @param #ZONE_GROUP self
-- @return DCSTypes#Vec2 The location of the zone based on the @{Group} location.
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Group} location.
function ZONE_GROUP:GetVec2()
self:F( self.ZoneName )
@ -502,7 +620,7 @@ end
--- Returns a random location within the zone of the @{Group}.
-- @param #ZONE_GROUP self
-- @return DCSTypes#Vec2 The random location of the zone based on the @{Group} location.
-- @return Dcs.DCSTypes#Vec2 The random location of the zone based on the @{Group} location.
function ZONE_GROUP:GetRandomVec2()
self:F( self.ZoneName )
@ -522,23 +640,23 @@ end
-- Polygons
--- The ZONE_POLYGON_BASE class defined by an array of @{DCSTypes#Vec2}, forming a polygon.
--- The ZONE_POLYGON_BASE class defined by an array of @{Dcs.DCSTypes#Vec2}, forming a polygon.
-- @type ZONE_POLYGON_BASE
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}.
-- @extends Zone#ZONE_BASE
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{Dcs.DCSTypes#Vec2}.
-- @extends Core.Zone#ZONE_BASE
ZONE_POLYGON_BASE = {
ClassName="ZONE_POLYGON_BASE",
}
--- A points array.
-- @type ZONE_POLYGON_BASE.ListVec2
-- @list <DCSTypes#Vec2>
-- @list <Dcs.DCSTypes#Vec2>
--- Constructor to create a ZONE_POLYGON_BASE instance, taking the zone name and an array of @{DCSTypes#Vec2}, forming a polygon.
-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected.
--- Constructor to create a ZONE_POLYGON_BASE instance, taking the zone name and an array of @{Dcs.DCSTypes#Vec2}, forming a polygon.
-- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected.
-- @param #ZONE_POLYGON_BASE self
-- @param #string ZoneName Name of the zone.
-- @param #ZONE_POLYGON_BASE.ListVec2 PointsArray An array of @{DCSTypes#Vec2}, forming a polygon..
-- @param #ZONE_POLYGON_BASE.ListVec2 PointsArray An array of @{Dcs.DCSTypes#Vec2}, forming a polygon..
-- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) )
@ -571,7 +689,7 @@ end
--- Smokes the zone boundaries in a color.
-- @param #ZONE_POLYGON_BASE self
-- @param #POINT_VEC3.SmokeColor SmokeColor The smoke color.
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
-- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:SmokeZone( SmokeColor )
self:F2( SmokeColor )
@ -607,7 +725,7 @@ end
--- Returns if a location is within the zone.
-- Source learned and taken from: https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
-- @param #ZONE_POLYGON_BASE self
-- @param DCSTypes#Vec2 Vec2 The location to test.
-- @param Dcs.DCSTypes#Vec2 Vec2 The location to test.
-- @return #boolean true if the location is within the zone.
function ZONE_POLYGON_BASE:IsPointVec2InZone( Vec2 )
self:F2( Vec2 )
@ -635,9 +753,9 @@ function ZONE_POLYGON_BASE:IsPointVec2InZone( Vec2 )
return InPolygon
end
--- Define a random @{DCSTypes#Vec2} within the zone.
--- Define a random @{Dcs.DCSTypes#Vec2} within the zone.
-- @param #ZONE_POLYGON_BASE self
-- @return DCSTypes#Vec2 The Vec2 coordinate.
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinate.
function ZONE_POLYGON_BASE:GetRandomVec2()
self:F2()
@ -687,18 +805,18 @@ end
--- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
--- The ZONE_POLYGON class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- @type ZONE_POLYGON
-- @extends Zone#ZONE_POLYGON_BASE
-- @extends Core.Zone#ZONE_POLYGON_BASE
ZONE_POLYGON = {
ClassName="ZONE_POLYGON",
}
--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the name of the @{Group#GROUP} defined within the Mission Editor.
-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON.
--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the name of the @{Wrapper.Group#GROUP} defined within the Mission Editor.
-- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON.
-- @param #ZONE_POLYGON self
-- @param #string ZoneName Name of the zone.
-- @param Group#GROUP ZoneGroup The GROUP waypoints as defined within the Mission Editor define the polygon shape.
-- @param Wrapper.Group#GROUP ZoneGroup The GROUP waypoints as defined within the Mission Editor define the polygon shape.
-- @return #ZONE_POLYGON self
function ZONE_POLYGON:New( ZoneName, ZoneGroup )

View File

@ -4,7 +4,7 @@
--- Represents airbases: airdromes, helipads and ships with flying decks or landing pads.
-- @type Airbase
-- @extends DCSCoalitionObject#CoalitionObject
-- @extends Dcs.DCSCoalitionWrapper.Object#CoalitionObject
-- @field #Airbase.ID ID Identifier of an airbase. It assigned to an airbase by the Mission Editor automatically. This identifier is used in AI tasks to refer an airbase that exists (spawned and not dead) or not.
-- @field #Airbase.Category Category enum contains identifiers of airbase categories.
-- @field #Airbase.Desc Desc Airbase descriptor. Airdromes are unique and their types are unique, but helipads and ships are not always unique and may have the same type.
@ -33,7 +33,7 @@
--- Returns Unit that is corresponded to the airbase. Works only for ships.
-- @function [parent=#Airbase] getUnit
-- @param self
-- @return Unit#Unit
-- @return Wrapper.Unit#Unit
--- Returns identifier of the airbase.
-- @function [parent=#Airbase] getID

View File

@ -2,7 +2,7 @@
-- @module DCSCoalitionObject
--- @type CoalitionObject
-- @extends DCSObject#Object
-- @extends Dcs.DCSWrapper.Object#Object
--- @type coalition
-- @field #coalition.side side
@ -17,7 +17,7 @@ coalition = {} --#coalition
--- Returns coalition of the object.
-- @function [parent=#CoalitionObject] getCoalition
-- @param #CoalitionObject self
-- @return DCSTypes#coalition.side
-- @return Dcs.DCSTypes#coalition.side
--- Returns object country.
-- @function [parent=#CoalitionObject] getCountry

View File

@ -78,7 +78,7 @@
--- Detected target.
-- @type DetectedTarget
-- @field Object#Object object The target
-- @field Wrapper.Object#Object object The target
-- @field #boolean visible The target is visible
-- @field #boolean type The target type is known
-- @field #boolean distance Distance to the target is known
@ -87,7 +87,7 @@
--- Checks if the target is detected or not. If one or more detection method is specified the function will return true if the target is detected by at least one of these methods. If no detection methods are specified the function will return true if the target is detected by any method.
-- @function [parent=#Controller] isTargetDetected
-- @param self
-- @param Object#Object target Target to check
-- @param Wrapper.Object#Object target Target to check
-- @param #Controller.Detection detection Controller.Detection detection1, Controller.Detection detection2, ... Controller.Detection detectionN
-- @return #boolean detected True if the target is detected.
-- @return #boolean visible Has effect only if detected is true. True if the target is visible now.
@ -107,7 +107,7 @@
--- Know a target.
-- @function [parent=#Controller] knowTarget
-- @param self
-- @param Object#Object object The target.
-- @param Wrapper.Object#Object object The target.
-- @param #boolean type Target type is known.
-- @param #boolean distance Distance to target is known.

View File

@ -41,7 +41,7 @@
--- Returns the coalition of the group.
-- @function [parent=#Group] getCoalition
-- @param #Group self
-- @return DCSCoalitionObject#coalition.side
-- @return Dcs.DCSCoalitionWrapper.Object#coalition.side
--- Returns the group's name. This is the same name assigned to the group in Mission Editor.
-- @function [parent=#Group] getName
@ -57,7 +57,7 @@
-- @function [parent=#Group] getUnit
-- @param #Group self
-- @param #number unitNumber
-- @return DCSUnit#Unit
-- @return Dcs.DCSWrapper.Unit#Unit
--- Returns current size of the group. If some of the units will be destroyed, As units are destroyed the size of the group will be changed.
-- @function [parent=#Group] getSize
@ -72,7 +72,7 @@
--- Returns array of the units present in the group now. Destroyed units will not be enlisted at all.
-- @function [parent=#Group] getUnits
-- @param #Group self
-- @return #list<DCSUnit#Unit> array of Units
-- @return #list<Dcs.DCSWrapper.Unit#Unit> array of Units
--- Returns controller of the group.
-- @function [parent=#Group] getController

View File

@ -4,7 +4,7 @@
-------------------------------------------------------------------------------
-- @module StaticObject
-- @extends CoalitionObject#CoalitionObject
-- @extends CoalitionWrapper.Object#CoalitionObject
--- Represents static object added in the Mission Editor.
-- @type StaticObject
@ -13,7 +13,7 @@
--- StaticObject descriptor. Airdromes are unique and their types are unique, but helipads and ships are not always unique and may have the same type.
-- @type StaticObject.Desc
-- @extends Unit#Unit.Desc
-- @extends Wrapper.Unit#Unit.Desc
--- Returns static object by its name. If no static object found nil will be returned.
-- @function [parent=#StaticObject] getByName

View File

@ -2,7 +2,7 @@
-- @module DCSUnit
--- @type Unit
-- @extends DCSCoalitionObject#CoalitionObject
-- @extends Dcs.DCSCoalitionWrapper.Object#CoalitionObject
-- @field ID Identifier of an unit. It assigned to an unit by the Mission Editor automatically.
-- @field #Unit.Category Category
-- @field #Unit.RefuelingSystem RefuelingSystem
@ -57,14 +57,14 @@
--- A unit descriptor.
-- @type Unit.Desc
-- @extends Object#Object.Desc
-- @extends Wrapper.Object#Object.Desc
-- @field #Unit.Category category Unit Category
-- @field #Mass massEmpty mass of empty unit
-- @field #number speedMax istance / Time, --maximal velocity
--- An aircraft descriptor.
-- @type Unit.DescAircraft
-- @extends Unit#Unit.Desc
-- @extends Wrapper.Unit#Unit.Desc
-- @field #Mass fuelMassMax maximal inner fuel mass
-- @field #Distance range Operational range
-- @field #Distance Hmax Ceiling
@ -75,18 +75,18 @@
--- An airplane descriptor.
-- @type Unit.DescAirplane
-- @extends Unit#Unit.DescAircraft
-- @extends Wrapper.Unit#Unit.DescAircraft
-- @field #number speedMax0 Distance / Time maximal TAS at ground level
-- @field #number speedMax10K Distance / Time maximal TAS at altitude of 10 km
--- A helicopter descriptor.
-- @type Unit.DescHelicopter
-- @extends Unit#Unit.DescAircraft
-- @extends Wrapper.Unit#Unit.DescAircraft
-- @field #Distance HmaxStat static ceiling
--- A vehicle descriptor.
-- @type Unit.DescVehicle
-- @extends Unit#Unit.Desc
-- @extends Wrapper.Unit#Unit.Desc
-- @field #Angle maxSlopeAngle maximal slope angle
-- @field #boolean riverCrossing can the vehicle cross a rivers
@ -106,12 +106,12 @@
--- An optic sensor.
-- @type Unit.Optic
-- @extends Unit#Unit.Sensor
-- @extends Wrapper.Unit#Unit.Sensor
-- @field #Unit.OpticType opticType
--- A radar.
-- @type Unit.Radar
-- @extends Unit#Unit.Sensor
-- @extends Wrapper.Unit#Unit.Sensor
-- @field #Distance detectionDistanceRBM detection distance for RCS=1m^2 in real-beam mapping mode, nil if radar doesn't support surface/land search
-- @field #Distance detectionDistanceHRM detection distance for RCS=1m^2 in high-resolution mapping mode, nil if radar has no HRM
-- @field #Unit.Radar.detectionDistanceAir detectionDistanceAir detection distance for RCS=1m^2 airborne target, nil if radar doesn't support air search
@ -129,7 +129,7 @@
-- @field #Distance tailOn
--- An IRST.
-- @type Unit#Unit.IRST
-- @type Wrapper.Unit#Unit.IRST
-- @extends Unit.Sensor
-- @field #Distance detectionDistanceIdle detection of tail-on target with heat signature = 1 in upper hemisphere, engines are in idle
-- @field #Distance detectionDistanceMaximal ..., engines are in maximal mode
@ -137,7 +137,7 @@
--- An RWR.
-- @type Unit.RWR
-- @extends Unit#Unit.Sensor
-- @extends Wrapper.Unit#Unit.Sensor
--- table that stores all unit sensors.
-- TODO @type Sensors
@ -178,7 +178,7 @@
--- Returns the unit's group if it exist and nil otherwise
-- @function [parent=#Unit] getGroup
-- @param #Unit self
-- @return DCSGroup#Group
-- @return Dcs.DCSWrapper.Group#Group
--- Returns the unit's callsign - the localized string.
-- @function [parent=#Unit] getCallsign
@ -230,7 +230,7 @@
-- Second value is the object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
-- @function [parent=#Unit] getRadar
-- @param #Unit self
-- @return #boolean, Object#Object
-- @return #boolean, Wrapper.Object#Object
--- Returns unit descriptor. Descriptor type depends on unit category.
-- @function [parent=#Unit] getDesc

View File

@ -15,7 +15,7 @@
--- Returns altitude MSL of the point.
-- @function [parent=#land] getHeight
-- @param #Vec2 point point on the ground.
-- @return DCSTypes#Distance
-- @return Dcs.DCSTypes#Distance
--- returns surface type at the given point.
-- @function [parent=#land] getSurfaceType

View File

@ -2,9 +2,9 @@
--
-- ===
--
-- 1) @{AirbasePolice#AIRBASEPOLICE_BASE} class, extends @{Base#BASE}
-- 1) @{Functional.AirbasePolice#AIRBASEPOLICE_BASE} class, extends @{Core.Base#BASE}
-- ==================================================================
-- The @{AirbasePolice#AIRBASEPOLICE_BASE} class provides the main methods to monitor CLIENT behaviour at airbases.
-- The @{Functional.AirbasePolice#AIRBASEPOLICE_BASE} class provides the main methods to monitor CLIENT behaviour at airbases.
-- CLIENTS should not be allowed to:
--
-- * Don't taxi faster than 40 km/h.
@ -12,7 +12,7 @@
-- * Avoid to hit other planes on the airbase.
-- * Obey ground control orders.
--
-- 2) @{AirbasePolice#AIRBASEPOLICE_CAUCASUS} class, extends @{AirbasePolice#AIRBASEPOLICE_BASE}
-- 2) @{Functional.AirbasePolice#AIRBASEPOLICE_CAUCASUS} class, extends @{Functional.AirbasePolice#AIRBASEPOLICE_BASE}
-- =============================================================================================
-- All the airbases on the caucasus map can be monitored using this class.
-- If you want to monitor specific airbases, you need to use the @{#AIRBASEPOLICE_BASE.Monitor}() method, which takes a table or airbase names.
@ -39,7 +39,7 @@
-- * TbilisiLochini
-- * Vaziani
--
-- 3) @{AirbasePolice#AIRBASEPOLICE_NEVADA} class, extends @{AirbasePolice#AIRBASEPOLICE_BASE}
-- 3) @{Functional.AirbasePolice#AIRBASEPOLICE_NEVADA} class, extends @{Functional.AirbasePolice#AIRBASEPOLICE_BASE}
-- =============================================================================================
-- All the airbases on the NEVADA map can be monitored using this class.
-- If you want to monitor specific airbases, you need to use the @{#AIRBASEPOLICE_BASE.Monitor}() method, which takes a table or airbase names.
@ -59,8 +59,8 @@
--- @type AIRBASEPOLICE_BASE
-- @field Set#SET_CLIENT SetClient
-- @extends Base#BASE
-- @field Core.Set#SET_CLIENT SetClient
-- @extends Core.Base#BASE
AIRBASEPOLICE_BASE = {
ClassName = "AIRBASEPOLICE_BASE",
@ -85,21 +85,21 @@ function AIRBASEPOLICE_BASE:New( SetClient, Airbases )
self.Airbases = Airbases
for AirbaseID, Airbase in pairs( self.Airbases ) do
Airbase.ZoneBoundary = ZONE_POLYGON_BASE:New( "Boundary", Airbase.PointsBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
Airbase.ZoneBoundary = ZONE_POLYGON_BASE:New( "Boundary", Airbase.PointsBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
for PointsRunwayID, PointsRunway in pairs( Airbase.PointsRunways ) do
Airbase.ZoneRunways[PointsRunwayID] = ZONE_POLYGON_BASE:New( "Runway " .. PointsRunwayID, PointsRunway ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
Airbase.ZoneRunways[PointsRunwayID] = ZONE_POLYGON_BASE:New( "Runway " .. PointsRunwayID, PointsRunway ):SmokeZone(SMOKECOLOR.Red):Flush()
end
end
-- -- Template
-- local TemplateBoundary = GROUP:FindByName( "Template Boundary" )
-- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local TemplateRunway1 = GROUP:FindByName( "Template Runway 1" )
-- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
self.SetClient:ForEachClient(
--- @param Client#CLIENT Client
--- @param Wrapper.Client#CLIENT Client
function( Client )
Client:SetState( self, "Speeding", false )
Client:SetState( self, "Warnings", 0)
@ -141,7 +141,7 @@ function AIRBASEPOLICE_BASE:_AirbaseMonitor()
self.SetClient:ForEachClientInZone( Airbase.ZoneBoundary,
--- @param Client#CLIENT Client
--- @param Wrapper.Client#CLIENT Client
function( Client )
self:E( Client.UnitName )
@ -219,7 +219,7 @@ end
--- @type AIRBASEPOLICE_CAUCASUS
-- @field Set#SET_CLIENT SetClient
-- @field Core.Set#SET_CLIENT SetClient
-- @extends #AIRBASEPOLICE_BASE
AIRBASEPOLICE_CAUCASUS = {
@ -749,197 +749,197 @@ function AIRBASEPOLICE_CAUCASUS:New( SetClient )
-- -- AnapaVityazevo
-- local AnapaVityazevoBoundary = GROUP:FindByName( "AnapaVityazevo Boundary" )
-- self.Airbases.AnapaVityazevo.ZoneBoundary = ZONE_POLYGON:New( "AnapaVityazevo Boundary", AnapaVityazevoBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.AnapaVityazevo.ZoneBoundary = ZONE_POLYGON:New( "AnapaVityazevo Boundary", AnapaVityazevoBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local AnapaVityazevoRunway1 = GROUP:FindByName( "AnapaVityazevo Runway 1" )
-- self.Airbases.AnapaVityazevo.ZoneRunways[1] = ZONE_POLYGON:New( "AnapaVityazevo Runway 1", AnapaVityazevoRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.AnapaVityazevo.ZoneRunways[1] = ZONE_POLYGON:New( "AnapaVityazevo Runway 1", AnapaVityazevoRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Batumi
-- local BatumiBoundary = GROUP:FindByName( "Batumi Boundary" )
-- self.Airbases.Batumi.ZoneBoundary = ZONE_POLYGON:New( "Batumi Boundary", BatumiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Batumi.ZoneBoundary = ZONE_POLYGON:New( "Batumi Boundary", BatumiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local BatumiRunway1 = GROUP:FindByName( "Batumi Runway 1" )
-- self.Airbases.Batumi.ZoneRunways[1] = ZONE_POLYGON:New( "Batumi Runway 1", BatumiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Batumi.ZoneRunways[1] = ZONE_POLYGON:New( "Batumi Runway 1", BatumiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Beslan
-- local BeslanBoundary = GROUP:FindByName( "Beslan Boundary" )
-- self.Airbases.Beslan.ZoneBoundary = ZONE_POLYGON:New( "Beslan Boundary", BeslanBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Beslan.ZoneBoundary = ZONE_POLYGON:New( "Beslan Boundary", BeslanBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local BeslanRunway1 = GROUP:FindByName( "Beslan Runway 1" )
-- self.Airbases.Beslan.ZoneRunways[1] = ZONE_POLYGON:New( "Beslan Runway 1", BeslanRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Beslan.ZoneRunways[1] = ZONE_POLYGON:New( "Beslan Runway 1", BeslanRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Gelendzhik
-- local GelendzhikBoundary = GROUP:FindByName( "Gelendzhik Boundary" )
-- self.Airbases.Gelendzhik.ZoneBoundary = ZONE_POLYGON:New( "Gelendzhik Boundary", GelendzhikBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Gelendzhik.ZoneBoundary = ZONE_POLYGON:New( "Gelendzhik Boundary", GelendzhikBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local GelendzhikRunway1 = GROUP:FindByName( "Gelendzhik Runway 1" )
-- self.Airbases.Gelendzhik.ZoneRunways[1] = ZONE_POLYGON:New( "Gelendzhik Runway 1", GelendzhikRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Gelendzhik.ZoneRunways[1] = ZONE_POLYGON:New( "Gelendzhik Runway 1", GelendzhikRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Gudauta
-- local GudautaBoundary = GROUP:FindByName( "Gudauta Boundary" )
-- self.Airbases.Gudauta.ZoneBoundary = ZONE_POLYGON:New( "Gudauta Boundary", GudautaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Gudauta.ZoneBoundary = ZONE_POLYGON:New( "Gudauta Boundary", GudautaBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local GudautaRunway1 = GROUP:FindByName( "Gudauta Runway 1" )
-- self.Airbases.Gudauta.ZoneRunways[1] = ZONE_POLYGON:New( "Gudauta Runway 1", GudautaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Gudauta.ZoneRunways[1] = ZONE_POLYGON:New( "Gudauta Runway 1", GudautaRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Kobuleti
-- local KobuletiBoundary = GROUP:FindByName( "Kobuleti Boundary" )
-- self.Airbases.Kobuleti.ZoneBoundary = ZONE_POLYGON:New( "Kobuleti Boundary", KobuletiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Kobuleti.ZoneBoundary = ZONE_POLYGON:New( "Kobuleti Boundary", KobuletiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local KobuletiRunway1 = GROUP:FindByName( "Kobuleti Runway 1" )
-- self.Airbases.Kobuleti.ZoneRunways[1] = ZONE_POLYGON:New( "Kobuleti Runway 1", KobuletiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Kobuleti.ZoneRunways[1] = ZONE_POLYGON:New( "Kobuleti Runway 1", KobuletiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- KrasnodarCenter
-- local KrasnodarCenterBoundary = GROUP:FindByName( "KrasnodarCenter Boundary" )
-- self.Airbases.KrasnodarCenter.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarCenter Boundary", KrasnodarCenterBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.KrasnodarCenter.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarCenter Boundary", KrasnodarCenterBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local KrasnodarCenterRunway1 = GROUP:FindByName( "KrasnodarCenter Runway 1" )
-- self.Airbases.KrasnodarCenter.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarCenter Runway 1", KrasnodarCenterRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.KrasnodarCenter.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarCenter Runway 1", KrasnodarCenterRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- KrasnodarPashkovsky
-- local KrasnodarPashkovskyBoundary = GROUP:FindByName( "KrasnodarPashkovsky Boundary" )
-- self.Airbases.KrasnodarPashkovsky.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarPashkovsky Boundary", KrasnodarPashkovskyBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.KrasnodarPashkovsky.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarPashkovsky Boundary", KrasnodarPashkovskyBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local KrasnodarPashkovskyRunway1 = GROUP:FindByName( "KrasnodarPashkovsky Runway 1" )
-- self.Airbases.KrasnodarPashkovsky.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 1", KrasnodarPashkovskyRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.KrasnodarPashkovsky.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 1", KrasnodarPashkovskyRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
-- local KrasnodarPashkovskyRunway2 = GROUP:FindByName( "KrasnodarPashkovsky Runway 2" )
-- self.Airbases.KrasnodarPashkovsky.ZoneRunways[2] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 2", KrasnodarPashkovskyRunway2 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.KrasnodarPashkovsky.ZoneRunways[2] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 2", KrasnodarPashkovskyRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Krymsk
-- local KrymskBoundary = GROUP:FindByName( "Krymsk Boundary" )
-- self.Airbases.Krymsk.ZoneBoundary = ZONE_POLYGON:New( "Krymsk Boundary", KrymskBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Krymsk.ZoneBoundary = ZONE_POLYGON:New( "Krymsk Boundary", KrymskBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local KrymskRunway1 = GROUP:FindByName( "Krymsk Runway 1" )
-- self.Airbases.Krymsk.ZoneRunways[1] = ZONE_POLYGON:New( "Krymsk Runway 1", KrymskRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Krymsk.ZoneRunways[1] = ZONE_POLYGON:New( "Krymsk Runway 1", KrymskRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Kutaisi
-- local KutaisiBoundary = GROUP:FindByName( "Kutaisi Boundary" )
-- self.Airbases.Kutaisi.ZoneBoundary = ZONE_POLYGON:New( "Kutaisi Boundary", KutaisiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Kutaisi.ZoneBoundary = ZONE_POLYGON:New( "Kutaisi Boundary", KutaisiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local KutaisiRunway1 = GROUP:FindByName( "Kutaisi Runway 1" )
-- self.Airbases.Kutaisi.ZoneRunways[1] = ZONE_POLYGON:New( "Kutaisi Runway 1", KutaisiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Kutaisi.ZoneRunways[1] = ZONE_POLYGON:New( "Kutaisi Runway 1", KutaisiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- MaykopKhanskaya
-- local MaykopKhanskayaBoundary = GROUP:FindByName( "MaykopKhanskaya Boundary" )
-- self.Airbases.MaykopKhanskaya.ZoneBoundary = ZONE_POLYGON:New( "MaykopKhanskaya Boundary", MaykopKhanskayaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.MaykopKhanskaya.ZoneBoundary = ZONE_POLYGON:New( "MaykopKhanskaya Boundary", MaykopKhanskayaBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local MaykopKhanskayaRunway1 = GROUP:FindByName( "MaykopKhanskaya Runway 1" )
-- self.Airbases.MaykopKhanskaya.ZoneRunways[1] = ZONE_POLYGON:New( "MaykopKhanskaya Runway 1", MaykopKhanskayaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.MaykopKhanskaya.ZoneRunways[1] = ZONE_POLYGON:New( "MaykopKhanskaya Runway 1", MaykopKhanskayaRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- MineralnyeVody
-- local MineralnyeVodyBoundary = GROUP:FindByName( "MineralnyeVody Boundary" )
-- self.Airbases.MineralnyeVody.ZoneBoundary = ZONE_POLYGON:New( "MineralnyeVody Boundary", MineralnyeVodyBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.MineralnyeVody.ZoneBoundary = ZONE_POLYGON:New( "MineralnyeVody Boundary", MineralnyeVodyBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local MineralnyeVodyRunway1 = GROUP:FindByName( "MineralnyeVody Runway 1" )
-- self.Airbases.MineralnyeVody.ZoneRunways[1] = ZONE_POLYGON:New( "MineralnyeVody Runway 1", MineralnyeVodyRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.MineralnyeVody.ZoneRunways[1] = ZONE_POLYGON:New( "MineralnyeVody Runway 1", MineralnyeVodyRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Mozdok
-- local MozdokBoundary = GROUP:FindByName( "Mozdok Boundary" )
-- self.Airbases.Mozdok.ZoneBoundary = ZONE_POLYGON:New( "Mozdok Boundary", MozdokBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Mozdok.ZoneBoundary = ZONE_POLYGON:New( "Mozdok Boundary", MozdokBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local MozdokRunway1 = GROUP:FindByName( "Mozdok Runway 1" )
-- self.Airbases.Mozdok.ZoneRunways[1] = ZONE_POLYGON:New( "Mozdok Runway 1", MozdokRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Mozdok.ZoneRunways[1] = ZONE_POLYGON:New( "Mozdok Runway 1", MozdokRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Nalchik
-- local NalchikBoundary = GROUP:FindByName( "Nalchik Boundary" )
-- self.Airbases.Nalchik.ZoneBoundary = ZONE_POLYGON:New( "Nalchik Boundary", NalchikBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Nalchik.ZoneBoundary = ZONE_POLYGON:New( "Nalchik Boundary", NalchikBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local NalchikRunway1 = GROUP:FindByName( "Nalchik Runway 1" )
-- self.Airbases.Nalchik.ZoneRunways[1] = ZONE_POLYGON:New( "Nalchik Runway 1", NalchikRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Nalchik.ZoneRunways[1] = ZONE_POLYGON:New( "Nalchik Runway 1", NalchikRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Novorossiysk
-- local NovorossiyskBoundary = GROUP:FindByName( "Novorossiysk Boundary" )
-- self.Airbases.Novorossiysk.ZoneBoundary = ZONE_POLYGON:New( "Novorossiysk Boundary", NovorossiyskBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Novorossiysk.ZoneBoundary = ZONE_POLYGON:New( "Novorossiysk Boundary", NovorossiyskBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local NovorossiyskRunway1 = GROUP:FindByName( "Novorossiysk Runway 1" )
-- self.Airbases.Novorossiysk.ZoneRunways[1] = ZONE_POLYGON:New( "Novorossiysk Runway 1", NovorossiyskRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Novorossiysk.ZoneRunways[1] = ZONE_POLYGON:New( "Novorossiysk Runway 1", NovorossiyskRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- SenakiKolkhi
-- local SenakiKolkhiBoundary = GROUP:FindByName( "SenakiKolkhi Boundary" )
-- self.Airbases.SenakiKolkhi.ZoneBoundary = ZONE_POLYGON:New( "SenakiKolkhi Boundary", SenakiKolkhiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.SenakiKolkhi.ZoneBoundary = ZONE_POLYGON:New( "SenakiKolkhi Boundary", SenakiKolkhiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local SenakiKolkhiRunway1 = GROUP:FindByName( "SenakiKolkhi Runway 1" )
-- self.Airbases.SenakiKolkhi.ZoneRunways[1] = ZONE_POLYGON:New( "SenakiKolkhi Runway 1", SenakiKolkhiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.SenakiKolkhi.ZoneRunways[1] = ZONE_POLYGON:New( "SenakiKolkhi Runway 1", SenakiKolkhiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- SochiAdler
-- local SochiAdlerBoundary = GROUP:FindByName( "SochiAdler Boundary" )
-- self.Airbases.SochiAdler.ZoneBoundary = ZONE_POLYGON:New( "SochiAdler Boundary", SochiAdlerBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.SochiAdler.ZoneBoundary = ZONE_POLYGON:New( "SochiAdler Boundary", SochiAdlerBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local SochiAdlerRunway1 = GROUP:FindByName( "SochiAdler Runway 1" )
-- self.Airbases.SochiAdler.ZoneRunways[1] = ZONE_POLYGON:New( "SochiAdler Runway 1", SochiAdlerRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.SochiAdler.ZoneRunways[1] = ZONE_POLYGON:New( "SochiAdler Runway 1", SochiAdlerRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
-- local SochiAdlerRunway2 = GROUP:FindByName( "SochiAdler Runway 2" )
-- self.Airbases.SochiAdler.ZoneRunways[2] = ZONE_POLYGON:New( "SochiAdler Runway 2", SochiAdlerRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.SochiAdler.ZoneRunways[2] = ZONE_POLYGON:New( "SochiAdler Runway 2", SochiAdlerRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Soganlug
-- local SoganlugBoundary = GROUP:FindByName( "Soganlug Boundary" )
-- self.Airbases.Soganlug.ZoneBoundary = ZONE_POLYGON:New( "Soganlug Boundary", SoganlugBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Soganlug.ZoneBoundary = ZONE_POLYGON:New( "Soganlug Boundary", SoganlugBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local SoganlugRunway1 = GROUP:FindByName( "Soganlug Runway 1" )
-- self.Airbases.Soganlug.ZoneRunways[1] = ZONE_POLYGON:New( "Soganlug Runway 1", SoganlugRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Soganlug.ZoneRunways[1] = ZONE_POLYGON:New( "Soganlug Runway 1", SoganlugRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- SukhumiBabushara
-- local SukhumiBabusharaBoundary = GROUP:FindByName( "SukhumiBabushara Boundary" )
-- self.Airbases.SukhumiBabushara.ZoneBoundary = ZONE_POLYGON:New( "SukhumiBabushara Boundary", SukhumiBabusharaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.SukhumiBabushara.ZoneBoundary = ZONE_POLYGON:New( "SukhumiBabushara Boundary", SukhumiBabusharaBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local SukhumiBabusharaRunway1 = GROUP:FindByName( "SukhumiBabushara Runway 1" )
-- self.Airbases.SukhumiBabushara.ZoneRunways[1] = ZONE_POLYGON:New( "SukhumiBabushara Runway 1", SukhumiBabusharaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.SukhumiBabushara.ZoneRunways[1] = ZONE_POLYGON:New( "SukhumiBabushara Runway 1", SukhumiBabusharaRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- TbilisiLochini
-- local TbilisiLochiniBoundary = GROUP:FindByName( "TbilisiLochini Boundary" )
-- self.Airbases.TbilisiLochini.ZoneBoundary = ZONE_POLYGON:New( "TbilisiLochini Boundary", TbilisiLochiniBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.TbilisiLochini.ZoneBoundary = ZONE_POLYGON:New( "TbilisiLochini Boundary", TbilisiLochiniBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local TbilisiLochiniRunway1 = GROUP:FindByName( "TbilisiLochini Runway 1" )
-- self.Airbases.TbilisiLochini.ZoneRunways[1] = ZONE_POLYGON:New( "TbilisiLochini Runway 1", TbilisiLochiniRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.TbilisiLochini.ZoneRunways[1] = ZONE_POLYGON:New( "TbilisiLochini Runway 1", TbilisiLochiniRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- local TbilisiLochiniRunway2 = GROUP:FindByName( "TbilisiLochini Runway 2" )
-- self.Airbases.TbilisiLochini.ZoneRunways[2] = ZONE_POLYGON:New( "TbilisiLochini Runway 2", TbilisiLochiniRunway2 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.TbilisiLochini.ZoneRunways[2] = ZONE_POLYGON:New( "TbilisiLochini Runway 2", TbilisiLochiniRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
-- -- Vaziani
-- local VazianiBoundary = GROUP:FindByName( "Vaziani Boundary" )
-- self.Airbases.Vaziani.ZoneBoundary = ZONE_POLYGON:New( "Vaziani Boundary", VazianiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Vaziani.ZoneBoundary = ZONE_POLYGON:New( "Vaziani Boundary", VazianiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local VazianiRunway1 = GROUP:FindByName( "Vaziani Runway 1" )
-- self.Airbases.Vaziani.ZoneRunways[1] = ZONE_POLYGON:New( "Vaziani Runway 1", VazianiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Vaziani.ZoneRunways[1] = ZONE_POLYGON:New( "Vaziani Runway 1", VazianiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
--
--
@ -947,10 +947,10 @@ function AIRBASEPOLICE_CAUCASUS:New( SetClient )
-- Template
-- local TemplateBoundary = GROUP:FindByName( "Template Boundary" )
-- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local TemplateRunway1 = GROUP:FindByName( "Template Runway 1" )
-- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
return self
@ -960,7 +960,7 @@ end
--- @type AIRBASEPOLICE_NEVADA
-- @extends AirbasePolice#AIRBASEPOLICE_BASE
-- @extends Functional.AirbasePolice#AIRBASEPOLICE_BASE
AIRBASEPOLICE_NEVADA = {
ClassName = "AIRBASEPOLICE_NEVADA",
Airbases = {
@ -1143,49 +1143,49 @@ function AIRBASEPOLICE_NEVADA:New( SetClient )
-- -- Nellis
-- local NellisBoundary = GROUP:FindByName( "Nellis Boundary" )
-- self.Airbases.Nellis.ZoneBoundary = ZONE_POLYGON:New( "Nellis Boundary", NellisBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Nellis.ZoneBoundary = ZONE_POLYGON:New( "Nellis Boundary", NellisBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local NellisRunway1 = GROUP:FindByName( "Nellis Runway 1" )
-- self.Airbases.Nellis.ZoneRunways[1] = ZONE_POLYGON:New( "Nellis Runway 1", NellisRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Nellis.ZoneRunways[1] = ZONE_POLYGON:New( "Nellis Runway 1", NellisRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- local NellisRunway2 = GROUP:FindByName( "Nellis Runway 2" )
-- self.Airbases.Nellis.ZoneRunways[2] = ZONE_POLYGON:New( "Nellis Runway 2", NellisRunway2 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Nellis.ZoneRunways[2] = ZONE_POLYGON:New( "Nellis Runway 2", NellisRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- -- McCarran
-- local McCarranBoundary = GROUP:FindByName( "McCarran Boundary" )
-- self.Airbases.McCarran.ZoneBoundary = ZONE_POLYGON:New( "McCarran Boundary", McCarranBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.McCarran.ZoneBoundary = ZONE_POLYGON:New( "McCarran Boundary", McCarranBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local McCarranRunway1 = GROUP:FindByName( "McCarran Runway 1" )
-- self.Airbases.McCarran.ZoneRunways[1] = ZONE_POLYGON:New( "McCarran Runway 1", McCarranRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.McCarran.ZoneRunways[1] = ZONE_POLYGON:New( "McCarran Runway 1", McCarranRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- local McCarranRunway2 = GROUP:FindByName( "McCarran Runway 2" )
-- self.Airbases.McCarran.ZoneRunways[2] = ZONE_POLYGON:New( "McCarran Runway 2", McCarranRunway2 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.McCarran.ZoneRunways[2] = ZONE_POLYGON:New( "McCarran Runway 2", McCarranRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- local McCarranRunway3 = GROUP:FindByName( "McCarran Runway 3" )
-- self.Airbases.McCarran.ZoneRunways[3] = ZONE_POLYGON:New( "McCarran Runway 3", McCarranRunway3 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.McCarran.ZoneRunways[3] = ZONE_POLYGON:New( "McCarran Runway 3", McCarranRunway3 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- local McCarranRunway4 = GROUP:FindByName( "McCarran Runway 4" )
-- self.Airbases.McCarran.ZoneRunways[4] = ZONE_POLYGON:New( "McCarran Runway 4", McCarranRunway4 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.McCarran.ZoneRunways[4] = ZONE_POLYGON:New( "McCarran Runway 4", McCarranRunway4 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- -- Creech
-- local CreechBoundary = GROUP:FindByName( "Creech Boundary" )
-- self.Airbases.Creech.ZoneBoundary = ZONE_POLYGON:New( "Creech Boundary", CreechBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.Creech.ZoneBoundary = ZONE_POLYGON:New( "Creech Boundary", CreechBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local CreechRunway1 = GROUP:FindByName( "Creech Runway 1" )
-- self.Airbases.Creech.ZoneRunways[1] = ZONE_POLYGON:New( "Creech Runway 1", CreechRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Creech.ZoneRunways[1] = ZONE_POLYGON:New( "Creech Runway 1", CreechRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- local CreechRunway2 = GROUP:FindByName( "Creech Runway 2" )
-- self.Airbases.Creech.ZoneRunways[2] = ZONE_POLYGON:New( "Creech Runway 2", CreechRunway2 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.Creech.ZoneRunways[2] = ZONE_POLYGON:New( "Creech Runway 2", CreechRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- -- Groom Lake
-- local GroomLakeBoundary = GROUP:FindByName( "GroomLake Boundary" )
-- self.Airbases.GroomLake.ZoneBoundary = ZONE_POLYGON:New( "GroomLake Boundary", GroomLakeBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush()
-- self.Airbases.GroomLake.ZoneBoundary = ZONE_POLYGON:New( "GroomLake Boundary", GroomLakeBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
--
-- local GroomLakeRunway1 = GROUP:FindByName( "GroomLake Runway 1" )
-- self.Airbases.GroomLake.ZoneRunways[1] = ZONE_POLYGON:New( "GroomLake Runway 1", GroomLakeRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.GroomLake.ZoneRunways[1] = ZONE_POLYGON:New( "GroomLake Runway 1", GroomLakeRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
--
-- local GroomLakeRunway2 = GROUP:FindByName( "GroomLake Runway 2" )
-- self.Airbases.GroomLake.ZoneRunways[2] = ZONE_POLYGON:New( "GroomLake Runway 2", GroomLakeRunway2 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush()
-- self.Airbases.GroomLake.ZoneRunways[2] = ZONE_POLYGON:New( "GroomLake Runway 2", GroomLakeRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
end

View File

@ -10,7 +10,7 @@
--- The CLEANUP class.
-- @type CLEANUP
-- @extends Base#BASE
-- @extends Core.Base#BASE
CLEANUP = {
ClassName = "CLEANUP",
ZoneNames = {},
@ -51,7 +51,7 @@ end
--- Destroys a group from the simulator, but checks first if it is still existing!
-- @param #CLEANUP self
-- @param DCSGroup#Group GroupObject The object to be destroyed.
-- @param Dcs.DCSWrapper.Group#Group GroupObject The object to be destroyed.
-- @param #string CleanUpGroupName The groupname...
function CLEANUP:_DestroyGroup( GroupObject, CleanUpGroupName )
self:F( { GroupObject, CleanUpGroupName } )
@ -62,9 +62,9 @@ function CLEANUP:_DestroyGroup( GroupObject, CleanUpGroupName )
end
end
--- Destroys a @{DCSUnit#Unit} from the simulator, but checks first if it is still existing!
--- Destroys a @{Dcs.DCSWrapper.Unit#Unit} from the simulator, but checks first if it is still existing!
-- @param #CLEANUP self
-- @param DCSUnit#Unit CleanUpUnit The object to be destroyed.
-- @param Dcs.DCSWrapper.Unit#Unit CleanUpUnit The object to be destroyed.
-- @param #string CleanUpUnitName The Unit name ...
function CLEANUP:_DestroyUnit( CleanUpUnit, CleanUpUnitName )
self:F( { CleanUpUnit, CleanUpUnitName } )
@ -89,10 +89,10 @@ function CLEANUP:_DestroyUnit( CleanUpUnit, CleanUpUnitName )
end
end
-- TODO check DCSTypes#Weapon
-- TODO check Dcs.DCSTypes#Weapon
--- Destroys a missile from the simulator, but checks first if it is still existing!
-- @param #CLEANUP self
-- @param DCSTypes#Weapon MissileObject
-- @param Dcs.DCSTypes#Weapon MissileObject
function CLEANUP:_DestroyMissile( MissileObject )
self:F( { MissileObject } )
@ -134,7 +134,7 @@ end
--- Detects if a crash event occurs.
-- Crashed units go into a CleanUpList for removal.
-- @param #CLEANUP self
-- @param DCSTypes#Event event
-- @param Dcs.DCSTypes#Event event
function CLEANUP:_EventCrash( Event )
self:F( { Event } )
@ -157,7 +157,7 @@ end
--- Detects if a unit shoots a missile.
-- If this occurs within one of the zones, then the weapon used must be destroyed.
-- @param #CLEANUP self
-- @param DCSTypes#Event event
-- @param Dcs.DCSTypes#Event event
function CLEANUP:_EventShot( Event )
self:F( { Event } )
@ -174,7 +174,7 @@ end
--- Detects if the Unit has an S_EVENT_HIT within the given ZoneNames. If this is the case, destroy the unit.
-- @param #CLEANUP self
-- @param DCSTypes#Event event
-- @param Dcs.DCSTypes#Event event
function CLEANUP:_EventHitCleanUp( Event )
self:F( { Event } )
@ -199,7 +199,7 @@ function CLEANUP:_EventHitCleanUp( Event )
end
end
--- Add the @{DCSUnit#Unit} to the CleanUpList for CleanUp.
--- Add the @{Dcs.DCSWrapper.Unit#Unit} to the CleanUpList for CleanUp.
function CLEANUP:_AddForCleanUp( CleanUpUnit, CleanUpUnitName )
self:F( { CleanUpUnit, CleanUpUnitName } )
@ -217,7 +217,7 @@ end
--- Detects if the Unit has an S_EVENT_ENGINE_SHUTDOWN or an S_EVENT_HIT within the given ZoneNames. If this is the case, add the Group to the CLEANUP List.
-- @param #CLEANUP self
-- @param DCSTypes#Event event
-- @param Dcs.DCSTypes#Event event
function CLEANUP:_EventAddForCleanUp( Event )
if Event.IniDCSUnit then

View File

@ -2,14 +2,14 @@
--
-- ===
--
-- 1) @{Detection#DETECTION_BASE} class, extends @{Base#BASE}
-- 1) @{Functional.Detection#DETECTION_BASE} class, extends @{Core.Base#BASE}
-- ==========================================================
-- The @{Detection#DETECTION_BASE} class defines the core functions to administer detected objects.
-- The @{Detection#DETECTION_BASE} class will detect objects within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s).
-- The @{Functional.Detection#DETECTION_BASE} class defines the core functions to administer detected objects.
-- The @{Functional.Detection#DETECTION_BASE} class will detect objects within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s).
--
-- 1.1) DETECTION_BASE constructor
-- -------------------------------
-- Construct a new DETECTION_BASE instance using the @{Detection#DETECTION_BASE.New}() method.
-- Construct a new DETECTION_BASE instance using the @{Functional.Detection#DETECTION_BASE.New}() method.
--
-- 1.2) DETECTION_BASE initialization
-- ----------------------------------
@ -20,46 +20,46 @@
--
-- Use the following functions to report the objects it detected using the methods Visual, Optical, Radar, IRST, RWR, DLINK:
--
-- * @{Detection#DETECTION_BASE.InitDetectVisual}(): Detected using Visual.
-- * @{Detection#DETECTION_BASE.InitDetectOptical}(): Detected using Optical.
-- * @{Detection#DETECTION_BASE.InitDetectRadar}(): Detected using Radar.
-- * @{Detection#DETECTION_BASE.InitDetectIRST}(): Detected using IRST.
-- * @{Detection#DETECTION_BASE.InitDetectRWR}(): Detected using RWR.
-- * @{Detection#DETECTION_BASE.InitDetectDLINK}(): Detected using DLINK.
-- * @{Functional.Detection#DETECTION_BASE.InitDetectVisual}(): Detected using Visual.
-- * @{Functional.Detection#DETECTION_BASE.InitDetectOptical}(): Detected using Optical.
-- * @{Functional.Detection#DETECTION_BASE.InitDetectRadar}(): Detected using Radar.
-- * @{Functional.Detection#DETECTION_BASE.InitDetectIRST}(): Detected using IRST.
-- * @{Functional.Detection#DETECTION_BASE.InitDetectRWR}(): Detected using RWR.
-- * @{Functional.Detection#DETECTION_BASE.InitDetectDLINK}(): Detected using DLINK.
--
-- 1.3) Obtain objects detected by DETECTION_BASE
-- ----------------------------------------------
-- DETECTION_BASE builds @{Set}s of objects detected. These @{Set#SET_BASE}s can be retrieved using the method @{Detection#DETECTION_BASE.GetDetectedSets}().
-- The method will return a list (table) of @{Set#SET_BASE} objects.
-- DETECTION_BASE builds @{Set}s of objects detected. These @{Core.Set#SET_BASE}s can be retrieved using the method @{Functional.Detection#DETECTION_BASE.GetDetectedSets}().
-- The method will return a list (table) of @{Core.Set#SET_BASE} objects.
--
-- ===
--
-- 2) @{Detection#DETECTION_AREAS} class, extends @{Detection#DETECTION_BASE}
-- 2) @{Functional.Detection#DETECTION_AREAS} class, extends @{Functional.Detection#DETECTION_BASE}
-- ===============================================================================
-- The @{Detection#DETECTION_AREAS} class will detect units within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s),
-- and will build a list (table) of @{Set#SET_UNIT}s containing the @{Unit#UNIT}s detected.
-- The @{Functional.Detection#DETECTION_AREAS} class will detect units within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s),
-- and will build a list (table) of @{Core.Set#SET_UNIT}s containing the @{Wrapper.Unit#UNIT}s detected.
-- The class is group the detected units within zones given a DetectedZoneRange parameter.
-- A set with multiple detected zones will be created as there are groups of units detected.
--
-- 2.1) Retrieve the Detected Unit sets and Detected Zones
-- -------------------------------------------------------
-- The DetectedUnitSets methods are implemented in @{Detection#DECTECTION_BASE} and the DetectedZones methods is implemented in @{Detection#DETECTION_AREAS}.
-- The DetectedUnitSets methods are implemented in @{Functional.Detection#DECTECTION_BASE} and the DetectedZones methods is implemented in @{Functional.Detection#DETECTION_AREAS}.
--
-- Retrieve the DetectedUnitSets with the method @{Detection#DETECTION_BASE.GetDetectedSets}(). A table will be return of @{Set#SET_UNIT}s.
-- To understand the amount of sets created, use the method @{Detection#DETECTION_BASE.GetDetectedSetCount}().
-- If you want to obtain a specific set from the DetectedSets, use the method @{Detection#DETECTION_BASE.GetDetectedSet}() with a given index.
-- Retrieve the DetectedUnitSets with the method @{Functional.Detection#DETECTION_BASE.GetDetectedSets}(). A table will be return of @{Core.Set#SET_UNIT}s.
-- To understand the amount of sets created, use the method @{Functional.Detection#DETECTION_BASE.GetDetectedSetCount}().
-- If you want to obtain a specific set from the DetectedSets, use the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}() with a given index.
--
-- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Detection#DETECTION_BASE.GetDetectionZones}().
-- To understand the amount of zones created, use the method @{Detection#DETECTION_BASE.GetDetectionZoneCount}().
-- If you want to obtain a specific zone from the DetectedZones, use the method @{Detection#DETECTION_BASE.GetDetectionZone}() with a given index.
-- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZones}().
-- To understand the amount of zones created, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZoneCount}().
-- If you want to obtain a specific zone from the DetectedZones, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZone}() with a given index.
--
-- 1.4) Flare or Smoke detected units
-- ----------------------------------
-- Use the methods @{Detection#DETECTION_AREAS.FlareDetectedUnits}() or @{Detection#DETECTION_AREAS.SmokeDetectedUnits}() to flare or smoke the detected units when a new detection has taken place.
-- Use the methods @{Functional.Detection#DETECTION_AREAS.FlareDetectedUnits}() or @{Functional.Detection#DETECTION_AREAS.SmokeDetectedUnits}() to flare or smoke the detected units when a new detection has taken place.
--
-- 1.5) Flare or Smoke detected zones
-- ----------------------------------
-- Use the methods @{Detection#DETECTION_AREAS.FlareDetectedZones}() or @{Detection#DETECTION_AREAS.SmokeDetectedZones}() to flare or smoke the detected zones when a new detection has taken place.
-- Use the methods @{Functional.Detection#DETECTION_AREAS.FlareDetectedZones}() or @{Functional.Detection#DETECTION_AREAS.SmokeDetectedZones}() to flare or smoke the detected zones when a new detection has taken place.
--
-- ===
--
@ -77,12 +77,12 @@
--- DETECTION_BASE class
-- @type DETECTION_BASE
-- @field Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @field DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
-- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
-- @field #number DetectionRun
-- @extends Base#BASE
-- @extends Core.Base#BASE
DETECTION_BASE = {
ClassName = "DETECTION_BASE",
DetectionSetGroup = nil,
@ -104,8 +104,8 @@ DETECTION_BASE = {
--- DETECTION constructor.
-- @param #DETECTION_BASE self
-- @param Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @param DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
-- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @param Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
-- @return #DETECTION_BASE self
function DETECTION_BASE:New( DetectionSetGroup, DetectionRange )
@ -245,7 +245,7 @@ function DETECTION_BASE:GetDetectedObject( ObjectName )
return nil
end
--- Get the detected @{Set#SET_BASE}s.
--- Get the detected @{Core.Set#SET_BASE}s.
-- @param #DETECTION_BASE self
-- @return #DETECTION_BASE.DetectedSets DetectedSets
function DETECTION_BASE:GetDetectedSets()
@ -266,7 +266,7 @@ end
--- Get a SET of detected objects using a given numeric index.
-- @param #DETECTION_BASE self
-- @param #number Index
-- @return Set#SET_BASE
-- @return Core.Set#SET_BASE
function DETECTION_BASE:GetDetectedSet( Index )
local DetectionSet = self.DetectedSets[Index]
@ -279,7 +279,7 @@ end
--- Get the detection Groups.
-- @param #DETECTION_BASE self
-- @return Group#GROUP
-- @return Wrapper.Group#GROUP
function DETECTION_BASE:GetDetectionSetGroup()
local DetectionSetGroup = self.DetectionSetGroup
@ -313,7 +313,7 @@ function DETECTION_BASE:Schedule( DelayTime, RepeatInterval )
end
--- Form @{Set}s of detected @{Unit#UNIT}s in an array of @{Set#SET_BASE}s.
--- Form @{Set}s of detected @{Wrapper.Unit#UNIT}s in an array of @{Core.Set#SET_BASE}s.
-- @param #DETECTION_BASE self
function DETECTION_BASE:_DetectionScheduler( SchedulerName )
self:F2( { SchedulerName } )
@ -323,7 +323,7 @@ function DETECTION_BASE:_DetectionScheduler( SchedulerName )
self:UnIdentifyAllDetectedObjects() -- Resets the DetectedObjectsIdentified table
for DetectionGroupID, DetectionGroupData in pairs( self.DetectionSetGroup:GetSet() ) do
local DetectionGroup = DetectionGroupData -- Group#GROUP
local DetectionGroup = DetectionGroupData -- Wrapper.Group#GROUP
if DetectionGroup:IsAlive() then
@ -339,7 +339,7 @@ function DETECTION_BASE:_DetectionScheduler( SchedulerName )
)
for DetectionDetectedTargetID, DetectionDetectedTarget in pairs( DetectionDetectedTargets ) do
local DetectionObject = DetectionDetectedTarget.object -- DCSObject#Object
local DetectionObject = DetectionDetectedTarget.object -- Dcs.DCSWrapper.Object#Object
self:T2( DetectionObject )
if DetectionObject and DetectionObject:isExist() and DetectionObject.id_ < 50000000 then
@ -393,9 +393,9 @@ end
--- DETECTION_AREAS class
-- @type DETECTION_AREAS
-- @field DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
-- @field Dcs.DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
-- @field #DETECTION_AREAS.DetectedAreas DetectedAreas A list of areas containing the set of @{Unit}s, @{Zone}s, the center @{Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
-- @extends Detection#DETECTION_BASE
-- @extends Functional.Detection#DETECTION_BASE
DETECTION_AREAS = {
ClassName = "DETECTION_AREAS",
DetectedAreas = { n = 0 },
@ -406,21 +406,21 @@ DETECTION_AREAS = {
-- @list <#DETECTION_AREAS.DetectedArea>
--- @type DETECTION_AREAS.DetectedArea
-- @field Set#SET_UNIT Set -- The Set of Units in the detected area.
-- @field Zone#ZONE_UNIT Zone -- The Zone of the detected area.
-- @field Core.Set#SET_UNIT Set -- The Set of Units in the detected area.
-- @field Core.Zone#ZONE_UNIT Zone -- The Zone of the detected area.
-- @field #boolean Changed Documents if the detected area has changes.
-- @field #table Changes A list of the changes reported on the detected area. (It is up to the user of the detected area to consume those changes).
-- @field #number AreaID -- The identifier of the detected area.
-- @field #boolean FriendliesNearBy Indicates if there are friendlies within the detected area.
-- @field Unit#UNIT NearestFAC The nearest FAC near the Area.
-- @field Wrapper.Unit#UNIT NearestFAC The nearest FAC near the Area.
--- DETECTION_AREAS constructor.
-- @param Detection#DETECTION_AREAS self
-- @param Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @param DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
-- @param DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
-- @return Detection#DETECTION_AREAS self
-- @param Functional.Detection#DETECTION_AREAS self
-- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @param Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
-- @param Dcs.DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
-- @return Functional.Detection#DETECTION_AREAS self
function DETECTION_AREAS:New( DetectionSetGroup, DetectionRange, DetectionZoneRange )
-- Inherits from DETECTION_BASE
@ -439,8 +439,8 @@ function DETECTION_AREAS:New( DetectionSetGroup, DetectionRange, DetectionZoneRa
end
--- Add a detected @{#DETECTION_AREAS.DetectedArea}.
-- @param Set#SET_UNIT Set -- The Set of Units in the detected area.
-- @param Zone#ZONE_UNIT Zone -- The Zone of the detected area.
-- @param Core.Set#SET_UNIT Set -- The Set of Units in the detected area.
-- @param Core.Zone#ZONE_UNIT Zone -- The Zone of the detected area.
-- @return #DETECTION_AREAS.DetectedArea DetectedArea
function DETECTION_AREAS:AddDetectedArea( Set, Zone )
local DetectedAreas = self:GetDetectedAreas()
@ -487,10 +487,10 @@ function DETECTION_AREAS:GetDetectedAreaCount()
return DetectedAreaCount
end
--- Get the @{Set#SET_UNIT} of a detecttion area using a given numeric index.
--- Get the @{Core.Set#SET_UNIT} of a detecttion area using a given numeric index.
-- @param #DETECTION_AREAS self
-- @param #number Index
-- @return Set#SET_UNIT DetectedSet
-- @return Core.Set#SET_UNIT DetectedSet
function DETECTION_AREAS:GetDetectedSet( Index )
local DetectedSetUnit = self.DetectedAreas[Index].Set
@ -501,10 +501,10 @@ function DETECTION_AREAS:GetDetectedSet( Index )
return nil
end
--- Get the @{Zone#ZONE_UNIT} of a detection area using a given numeric index.
--- Get the @{Core.Zone#ZONE_UNIT} of a detection area using a given numeric index.
-- @param #DETECTION_AREAS self
-- @param #number Index
-- @return Zone#ZONE_UNIT DetectedZone
-- @return Core.Zone#ZONE_UNIT DetectedZone
function DETECTION_AREAS:GetDetectedZone( Index )
local DetectedZone = self.DetectedAreas[Index].Zone
@ -517,11 +517,11 @@ end
--- Background worker function to determine if there are friendlies nearby ...
-- @param #DETECTION_AREAS self
-- @param Unit#UNIT ReportUnit
-- @param Wrapper.Unit#UNIT ReportUnit
function DETECTION_AREAS:ReportFriendliesNearBy( ReportGroupData )
self:F2()
local DetectedArea = ReportGroupData.DetectedArea -- Detection#DETECTION_AREAS.DetectedArea
local DetectedArea = ReportGroupData.DetectedArea -- Functional.Detection#DETECTION_AREAS.DetectedArea
local DetectedSet = ReportGroupData.DetectedArea.Set
local DetectedZone = ReportGroupData.DetectedArea.Zone
local DetectedZoneUnit = DetectedZone.ZoneUNIT
@ -537,15 +537,15 @@ function DETECTION_AREAS:ReportFriendliesNearBy( ReportGroupData )
}
--- @param DCSUnit#Unit FoundDCSUnit
-- @param Group#GROUP ReportGroup
--- @param Dcs.DCSWrapper.Unit#Unit FoundDCSUnit
-- @param Wrapper.Group#GROUP ReportGroup
-- @param Set#SET_GROUP ReportSetGroup
local FindNearByFriendlies = function( FoundDCSUnit, ReportGroupData )
local DetectedArea = ReportGroupData.DetectedArea -- Detection#DETECTION_AREAS.DetectedArea
local DetectedArea = ReportGroupData.DetectedArea -- Functional.Detection#DETECTION_AREAS.DetectedArea
local DetectedSet = ReportGroupData.DetectedArea.Set
local DetectedZone = ReportGroupData.DetectedArea.Zone
local DetectedZoneUnit = DetectedZone.ZoneUNIT -- Unit#UNIT
local DetectedZoneUnit = DetectedZone.ZoneUNIT -- Wrapper.Unit#UNIT
local ReportSetGroup = ReportGroupData.ReportSetGroup
local EnemyCoalition = DetectedZoneUnit:GetCoalition()
@ -588,7 +588,7 @@ function DETECTION_AREAS:CalculateThreatLevelA2G( DetectedArea )
local MaxThreatLevelA2G = 0
for UnitName, UnitData in pairs( DetectedArea.Set:GetSet() ) do
local ThreatUnit = UnitData -- Unit#UNIT
local ThreatUnit = UnitData -- Wrapper.Unit#UNIT
local ThreatLevelA2G = ThreatUnit:GetThreatLevel()
if ThreatLevelA2G > MaxThreatLevelA2G then
MaxThreatLevelA2G = ThreatLevelA2G
@ -603,7 +603,7 @@ end
--- Find the nearest FAC of the DetectedArea.
-- @param #DETECTION_AREAS self
-- @param #DETECTION_AREAS.DetectedArea DetectedArea
-- @return Unit#UNIT The nearest FAC unit
-- @return Wrapper.Unit#UNIT The nearest FAC unit
function DETECTION_AREAS:NearestFAC( DetectedArea )
local NearestFAC = nil
@ -611,7 +611,7 @@ function DETECTION_AREAS:NearestFAC( DetectedArea )
for FACGroupName, FACGroupData in pairs( self.DetectionSetGroup:GetSet() ) do
for FACUnit, FACUnitData in pairs( FACGroupData:GetUnits() ) do
local FACUnit = FACUnitData -- Unit#UNIT
local FACUnit = FACUnitData -- Wrapper.Unit#UNIT
if FACUnit:IsActive() then
local Vec3 = FACUnit:GetVec3()
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 )
@ -829,7 +829,7 @@ function DETECTION_AREAS:CreateDetectionSets()
-- Then search for a new center area unit within the set. Note that the new area unit candidate must be within the area range.
for DetectedUnitName, DetectedUnitData in pairs( DetectedSet:GetSet() ) do
local DetectedUnit = DetectedUnitData -- Unit#UNIT
local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT
local DetectedObject = self:GetDetectedObject( DetectedUnit.UnitName )
-- The DetectedObject can be nil when the DetectedUnit is not alive anymore or it is not in the DetectedObjects map.
@ -859,7 +859,7 @@ function DETECTION_AREAS:CreateDetectionSets()
-- If a unit was not found in the set, remove it from the set. This may be added later to other existing or new sets.
for DetectedUnitName, DetectedUnitData in pairs( DetectedSet:GetSet() ) do
local DetectedUnit = DetectedUnitData -- Unit#UNIT
local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT
local DetectedObject = nil
if DetectedUnit:IsAlive() then
--self:E(DetectedUnit:GetName())
@ -909,7 +909,7 @@ function DETECTION_AREAS:CreateDetectionSets()
if DetectedObject then
-- We found an unidentified unit outside of any existing detection area.
local DetectedUnit = UNIT:FindByName( DetectedUnitName ) -- Unit#UNIT
local DetectedUnit = UNIT:FindByName( DetectedUnitName ) -- Wrapper.Unit#UNIT
local AddedToDetectionArea = false
@ -959,7 +959,7 @@ function DETECTION_AREAS:CreateDetectionSets()
DetectedZone.ZoneUNIT:SmokeRed()
end
DetectedSet:ForEachUnit(
--- @param Unit#UNIT DetectedUnit
--- @param Wrapper.Unit#UNIT DetectedUnit
function( DetectedUnit )
if DetectedUnit:IsAlive() then
self:T( "Detected Set #" .. DetectedArea.AreaID .. ":" .. DetectedUnit:GetName() )
@ -973,10 +973,10 @@ function DETECTION_AREAS:CreateDetectionSets()
end
)
if DETECTION_AREAS._FlareDetectedZones or self._FlareDetectedZones then
DetectedZone:FlareZone( POINT_VEC3.SmokeColor.White, 30, math.random( 0,90 ) )
DetectedZone:FlareZone( SMOKECOLOR.White, 30, math.random( 0,90 ) )
end
if DETECTION_AREAS._SmokeDetectedZones or self._SmokeDetectedZones then
DetectedZone:SmokeZone( POINT_VEC3.SmokeColor.White, 30 )
DetectedZone:SmokeZone( SMOKECOLOR.White, 30 )
end
end

View File

@ -80,7 +80,7 @@
-- ============================
-- Create a new SPAWN object with the @{#ESCORT.New} method:
--
-- * @{#ESCORT.New}: Creates a new ESCORT object from a @{Group#GROUP} for a @{Client#CLIENT}, with an optional briefing text.
-- * @{#ESCORT.New}: Creates a new ESCORT object from a @{Wrapper.Group#GROUP} for a @{Wrapper.Client#CLIENT}, with an optional briefing text.
--
-- ESCORT initialization methods.
-- ==============================
@ -117,17 +117,17 @@
--- ESCORT class
-- @type ESCORT
-- @extends Base#BASE
-- @field Client#CLIENT EscortClient
-- @field Group#GROUP EscortGroup
-- @extends Core.Base#BASE
-- @field Wrapper.Client#CLIENT EscortClient
-- @field Wrapper.Group#GROUP EscortGroup
-- @field #string EscortName
-- @field #ESCORT.MODE EscortMode The mode the escort is in.
-- @field Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
-- @field #number FollowDistance The current follow distance.
-- @field #boolean ReportTargets If true, nearby targets are reported.
-- @Field DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup.
-- @field DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup.
-- @field Menu#MENU_CLIENT EscortMenuResumeMission
-- @Field Dcs.DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup.
-- @field Dcs.DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup.
-- @field Core.Menu#MENU_CLIENT EscortMenuResumeMission
ESCORT = {
ClassName = "ESCORT",
EscortName = nil, -- The Escort Name
@ -161,8 +161,8 @@ ESCORT = {
--- ESCORT class constructor for an AI group
-- @param #ESCORT self
-- @param Client#CLIENT EscortClient The client escorted by the EscortGroup.
-- @param Group#GROUP EscortGroup The group AI escorting the EscortClient.
-- @param Wrapper.Client#CLIENT EscortClient The client escorted by the EscortGroup.
-- @param Wrapper.Group#GROUP EscortGroup The group AI escorting the EscortClient.
-- @param #string EscortName Name of the escort.
-- @param #string EscortBriefing A text showing the ESCORT briefing to the player. Note that if no EscortBriefing is provided, the default briefing will be shown.
-- @return #ESCORT self
@ -179,8 +179,8 @@ function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
local self = BASE:Inherit( self, BASE:New() )
self:F( { EscortClient, EscortGroup, EscortName } )
self.EscortClient = EscortClient -- Client#CLIENT
self.EscortGroup = EscortGroup -- Group#GROUP
self.EscortClient = EscortClient -- Wrapper.Client#CLIENT
self.EscortGroup = EscortGroup -- Wrapper.Group#GROUP
self.EscortName = EscortName
self.EscortBriefing = EscortBriefing
@ -268,7 +268,7 @@ end
--- Defines a menu slot to let the escort Join and Follow you at a certain distance.
-- This menu will appear under **Navigation**.
-- @param #ESCORT self
-- @param DCSTypes#Distance Distance The distance in meters that the escort needs to follow the client.
-- @param Dcs.DCSTypes#Distance Distance The distance in meters that the escort needs to follow the client.
-- @return #ESCORT
function ESCORT:MenuFollowAt( Distance )
self:F(Distance)
@ -293,8 +293,8 @@ end
--- Defines a menu slot to let the escort hold at their current position and stay low with a specified height during a specified time in seconds.
-- This menu will appear under **Hold position**.
-- @param #ESCORT self
-- @param DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
-- @return #ESCORT
-- TODO: Implement Seconds parameter. Challenge is to first develop the "continue from last activity" function.
@ -355,8 +355,8 @@ end
--- Defines a menu slot to let the escort hold at the client position and stay low with a specified height during a specified time in seconds.
-- This menu will appear under **Navigation**.
-- @param #ESCORT self
-- @param DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain one or two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
-- @return #ESCORT
-- TODO: Implement Seconds parameter. Challenge is to first develop the "continue from last activity" function.
@ -416,8 +416,8 @@ end
--- Defines a menu slot to let the escort scan for targets at a certain height for a certain time in seconds.
-- This menu will appear under **Scan targets**.
-- @param #ESCORT self
-- @param DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain one or two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
-- @return #ESCORT
function ESCORT:MenuScanForTargets( Height, Seconds, MenuTextFormat )
@ -494,10 +494,10 @@ function ESCORT:MenuFlare( MenuTextFormat )
if not self.EscortMenuFlare then
self.EscortMenuFlare = MENU_CLIENT:New( self.EscortClient, MenuText, self.EscortMenuReportNavigation, ESCORT._Flare, { ParamSelf = self } )
self.EscortMenuFlareGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = UNIT.FlareColor.Green, ParamMessage = "Released a green flare!" } )
self.EscortMenuFlareRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = UNIT.FlareColor.Red, ParamMessage = "Released a red flare!" } )
self.EscortMenuFlareWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = UNIT.FlareColor.White, ParamMessage = "Released a white flare!" } )
self.EscortMenuFlareYellow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release yellow flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = UNIT.FlareColor.Yellow, ParamMessage = "Released a yellow flare!" } )
self.EscortMenuFlareGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Green, ParamMessage = "Released a green flare!" } )
self.EscortMenuFlareRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Red, ParamMessage = "Released a red flare!" } )
self.EscortMenuFlareWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.White, ParamMessage = "Released a white flare!" } )
self.EscortMenuFlareYellow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release yellow flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Yellow, ParamMessage = "Released a yellow flare!" } )
end
return self
@ -542,7 +542,7 @@ end
-- This menu will appear under **Report targets**.
-- Note that if a report targets menu is not specified, no targets will be detected by the escort, and the attack and assisted attack menus will not be displayed.
-- @param #ESCORT self
-- @param DCSTypes#Time Seconds Optional parameter that lets the escort report their current detected targets after specified time interval in seconds. The default time is 30 seconds.
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort report their current detected targets after specified time interval in seconds. The default time is 30 seconds.
-- @return #ESCORT
function ESCORT:MenuReportTargets( Seconds )
self:F( { Seconds } )
@ -664,8 +664,8 @@ function ESCORT._HoldPosition( MenuParam )
local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient
local OrbitGroup = MenuParam.ParamOrbitGroup -- Group#GROUP
local OrbitUnit = OrbitGroup:GetUnit(1) -- Unit#UNIT
local OrbitGroup = MenuParam.ParamOrbitGroup -- Wrapper.Group#GROUP
local OrbitUnit = OrbitGroup:GetUnit(1) -- Wrapper.Unit#UNIT
local OrbitHeight = MenuParam.ParamHeight
local OrbitSeconds = MenuParam.ParamSeconds -- Not implemented yet
@ -714,10 +714,10 @@ function ESCORT._JoinUpAndFollow( MenuParam )
end
--- JoinsUp and Follows a CLIENT.
-- @param Escort#ESCORT self
-- @param Group#GROUP EscortGroup
-- @param Client#CLIENT EscortClient
-- @param DCSTypes#Distance Distance
-- @param Functional.Escort#ESCORT self
-- @param Wrapper.Group#GROUP EscortGroup
-- @param Wrapper.Client#CLIENT EscortClient
-- @param Dcs.DCSTypes#Distance Distance
function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
self:F( { EscortGroup, EscortClient, Distance } )
@ -832,7 +832,7 @@ function ESCORT._ScanTargets( MenuParam )
end
--- @param Group#GROUP EscortGroup
--- @param Wrapper.Group#GROUP EscortGroup
function _Resume( EscortGroup )
env.info( '_Resume' )
@ -851,7 +851,7 @@ function ESCORT._AttackTarget( MenuParam )
local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient
local AttackUnit = MenuParam.ParamUnit -- Unit#UNIT
local AttackUnit = MenuParam.ParamUnit -- Wrapper.Unit#UNIT
self.FollowScheduler:Stop()
@ -892,7 +892,7 @@ function ESCORT._AssistTarget( MenuParam )
local EscortGroup = self.EscortGroup
local EscortClient = self.EscortClient
local EscortGroupAttack = MenuParam.ParamEscortGroup
local AttackUnit = MenuParam.ParamUnit -- Unit#UNIT
local AttackUnit = MenuParam.ParamUnit -- Wrapper.Unit#UNIT
self.FollowScheduler:Stop()
@ -981,7 +981,7 @@ end
function ESCORT:RegisterRoute()
self:F()
local EscortGroup = self.EscortGroup -- Group#GROUP
local EscortGroup = self.EscortGroup -- Wrapper.Group#GROUP
local TaskPoints = EscortGroup:GetTaskRoute()
@ -990,7 +990,7 @@ function ESCORT:RegisterRoute()
return TaskPoints
end
--- @param Escort#ESCORT self
--- @param Functional.Escort#ESCORT self
function ESCORT:_FollowScheduler()
self:F( { self.FollowDistance } )

View File

@ -2,7 +2,7 @@
--
-- ===
--
-- 1) @{MissileTrainer#MISSILETRAINER} class, extends @{Base#BASE}
-- 1) @{Functional.MissileTrainer#MISSILETRAINER} class, extends @{Core.Base#BASE}
-- ===============================================================
-- The @{#MISSILETRAINER} class uses the DCS world messaging system to be alerted of any missiles fired, and when a missile would hit your aircraft,
-- the class will destroy the missile within a certain range, to avoid damage to your aircraft.
@ -83,8 +83,8 @@
--- The MISSILETRAINER class
-- @type MISSILETRAINER
-- @field Set#SET_CLIENT DBClients
-- @extends Base#BASE
-- @field Core.Set#SET_CLIENT DBClients
-- @extends Core.Base#BASE
MISSILETRAINER = {
ClassName = "MISSILETRAINER",
TrackingMissiles = {},
@ -191,7 +191,7 @@ function MISSILETRAINER:New( Distance, Briefing )
-- self.DB:ForEachClient(
-- --- @param Client#CLIENT Client
-- --- @param Wrapper.Client#CLIENT Client
-- function( Client )
--
-- ... actions ...
@ -449,7 +449,7 @@ end
--- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
-- @param #MISSILETRAINER self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function MISSILETRAINER:_EventShot( Event )
self:F( { Event } )

View File

@ -10,7 +10,7 @@
--- The Scoring class
-- @type SCORING
-- @field Players A collection of the current players that have joined the game.
-- @extends Base#BASE
-- @extends Core.Base#BASE
SCORING = {
ClassName = "SCORING",
ClassID = 0,
@ -100,7 +100,7 @@ end
--- Track DEAD or CRASH events for the scoring.
-- @param #SCORING self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function SCORING:_EventOnDeadOrCrash( Event )
self:F( { Event } )
@ -265,8 +265,8 @@ end
--- Registers Scores the players completing a Mission Task.
-- @param #SCORING self
-- @param Mission#MISSION Mission
-- @param Unit#UNIT PlayerUnit
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Unit#UNIT PlayerUnit
-- @param #string Text
-- @param #number Score
function SCORING:_AddMissionTaskScore( Mission, PlayerUnit, Text, Score )
@ -275,18 +275,20 @@ function SCORING:_AddMissionTaskScore( Mission, PlayerUnit, Text, Score )
local MissionName = Mission:GetName()
self:F( { Mission:GetName(), PlayerUnit.UnitName, PlayerName, Text, Score } )
local PlayerData = self.Players[PlayerName]
if not self.Players[PlayerName].Mission[MissionName] then
self.Players[PlayerName].Mission[MissionName] = {}
self.Players[PlayerName].Mission[MissionName].ScoreTask = 0
self.Players[PlayerName].Mission[MissionName].ScoreMission = 0
if not PlayerData.Mission[MissionName] then
PlayerData.Mission[MissionName] = {}
PlayerData.Mission[MissionName].ScoreTask = 0
PlayerData.Mission[MissionName].ScoreMission = 0
end
self:T( PlayerName )
self:T( self.Players[PlayerName].Mission[MissionName] )
self:T( PlayerData.Mission[MissionName] )
self.Players[PlayerName].Score = self.Players[PlayerName].Score + Score
self.Players[PlayerName].Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score
PlayerData.Score = self.Players[PlayerName].Score + Score
PlayerData.Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score
MESSAGE:New( "Player '" .. PlayerName .. "' has " .. Text .. " in Mission '" .. MissionName .. "'. " ..
Score .. " task score!",
@ -298,18 +300,20 @@ end
--- Registers Mission Scores for possible multiple players that contributed in the Mission.
-- @param #SCORING self
-- @param Mission#MISSION Mission
-- @param Unit#UNIT PlayerUnit
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Unit#UNIT PlayerUnit
-- @param #string Text
-- @param #number Score
function SCORING:_AddMissionScore( Mission, Text, Score )
local MissionName = Mission:GetName()
self:F( { Mission, Text, Score } )
self:E( { Mission, Text, Score } )
self:E( self.Players )
for PlayerName, PlayerData in pairs( self.Players ) do
self:E( PlayerData )
if PlayerData.Mission[MissionName] then
PlayerData.Score = PlayerData.Score + Score
@ -326,7 +330,7 @@ end
--- Handles the OnHit event for the scoring.
-- @param #SCORING self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function SCORING:_EventOnHit( Event )
self:F( { Event } )

View File

@ -5,7 +5,7 @@
--- The SEAD class
-- @type SEAD
-- @extends Base#BASE
-- @extends Core.Base#BASE
SEAD = {
ClassName = "SEAD",
TargetSkill = {

View File

@ -1,6 +1,6 @@
--- This module contains the SPAWN class.
--
-- 1) @{Spawn#SPAWN} class, extends @{Base#BASE}
-- 1) @{Functional.Spawn#SPAWN} class, extends @{Core.Base#BASE}
-- =============================================
-- The @{#SPAWN} class allows to spawn dynamically new groups, based on pre-defined initialization settings, modifying the behaviour when groups are spawned.
-- For each group to be spawned, within the mission editor, a group has to be created with the "late activation flag" set. We call this group the *"Spawn Template"* of the SPAWN object.
@ -26,9 +26,10 @@
--
-- 1.1) SPAWN construction methods
-- -------------------------------
-- Create a new SPAWN object with the @{#SPAWN.New} or the @{#SPAWN.NewWithAlias} methods:
-- Create a new SPAWN object with the @{#SPAWN.New}() or the @{#SPAWN.NewWithAlias}() methods:
--
-- * @{#SPAWN.New}: Creates a new SPAWN object taking the name of the group that represents the GROUP Template (definition).
-- * @{#SPAWN.New}(): Creates a new SPAWN object taking the name of the group that represents the GROUP Template (definition).
-- * @{#SPAWN.NewWithAlias}(): Creates a new SPAWN object taking the name of the group that represents the GROUP Template (definition), and gives each spawned @{Group} an different name.
--
-- It is important to understand how the SPAWN class works internally. The SPAWN object created will contain internally a list of groups that will be spawned and that are already spawned.
-- The initialization methods will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons.
@ -36,27 +37,29 @@
--
-- 1.2) SPAWN initialization methods
-- ---------------------------------
-- A spawn object will behave differently based on the usage of initialization methods:
-- A spawn object will behave differently based on the usage of **initialization** methods, which all start with the **Init** prefix:
--
-- * @{#SPAWN.Limit}: Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
-- * @{#SPAWN.RandomizeRoute}: Randomize the routes of spawned groups, and for air groups also optionally the height.
-- * @{#SPAWN.RandomizeTemplate}: Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
-- * @{#SPAWN.Uncontrolled}: Spawn plane groups uncontrolled.
-- * @{#SPAWN.Array}: Make groups visible before they are actually activated, and order these groups like a batallion in an array.
-- * @{#SPAWN.InitRepeat}: Re-spawn groups when they land at the home base. Similar methods are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}.
-- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
-- * @{#SPAWN.InitRandomizeRoute}(): Randomize the routes of spawned groups, and for air groups also optionally the height.
-- * @{#SPAWN.InitRandomizeTemplate}(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
-- * @{#SPAWN.InitUncontrolled}(): Spawn plane groups uncontrolled.
-- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a batallion in an array.
-- * @{#SPAWN.InitRepeat}(): Re-spawn groups when they land at the home base. Similar methods are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}.
-- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius.
-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor.
--
-- 1.3) SPAWN spawning methods
-- ---------------------------
-- Groups can be spawned at different times and methods:
--
-- * @{#SPAWN.Spawn}: Spawn one new group based on the last spawned index.
-- * @{#SPAWN.ReSpawn}: Re-spawn a group based on a given index.
-- * @{#SPAWN.SpawnScheduled}: Spawn groups at scheduled but randomized intervals. You can use @{#SPAWN.SpawnScheduleStart} and @{#SPAWN.SpawnScheduleStop} to start and stop the schedule respectively.
-- * @{#SPAWN.SpawnFromVec3}: Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
-- * @{#SPAWN.SpawnFromVec2}: Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
-- * @{#SPAWN.SpawnFromStatic}: Spawn a new group from a structure, taking the position of a @{STATIC}.
-- * @{#SPAWN.SpawnFromUnit}: Spawn a new group taking the position of a @{UNIT}.
-- * @{#SPAWN.SpawnInZone}: Spawn a new group in a @{ZONE}.
-- * @{#SPAWN.Spawn}(): Spawn one new group based on the last spawned index.
-- * @{#SPAWN.ReSpawn}(): Re-spawn a group based on a given index.
-- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals. You can use @{#SPAWN.SpawnScheduleStart}() and @{#SPAWN.SpawnScheduleStop}() to start and stop the schedule respectively.
-- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
-- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
-- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}.
-- * @{#SPAWN.SpawnFromUnit}(): Spawn a new group taking the position of a @{Unit}.
-- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Zone}.
--
-- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object.
-- You can use the @{GROUP} object to do further actions with the DCSGroup.
@ -67,32 +70,132 @@
-- Every time a SPAWN object spawns a new GROUP object, a reference to the GROUP object is added to an internal table of GROUPS.
-- SPAWN provides methods to iterate through that internal GROUP object reference table:
--
-- * @{#SPAWN.GetFirstAliveGroup}: Will find the first alive GROUP it has spawned, and return the alive GROUP object and the first Index where the first alive GROUP object has been found.
-- * @{#SPAWN.GetNextAliveGroup}: Will find the next alive GROUP object from a given Index, and return a reference to the alive GROUP object and the next Index where the alive GROUP has been found.
-- * @{#SPAWN.GetLastAliveGroup}: Will find the last alive GROUP object, and will return a reference to the last live GROUP object and the last Index where the last alive GROUP object has been found.
-- * @{#SPAWN.GetFirstAliveGroup}(): Will find the first alive GROUP it has spawned, and return the alive GROUP object and the first Index where the first alive GROUP object has been found.
-- * @{#SPAWN.GetNextAliveGroup}(): Will find the next alive GROUP object from a given Index, and return a reference to the alive GROUP object and the next Index where the alive GROUP has been found.
-- * @{#SPAWN.GetLastAliveGroup}(): Will find the last alive GROUP object, and will return a reference to the last live GROUP object and the last Index where the last alive GROUP object has been found.
--
-- You can use the methods @{#SPAWN.GetFirstAliveGroup} and sequently @{#SPAWN.GetNextAliveGroup} to iterate through the alive GROUPS within the SPAWN object, and to actions... See the respective methods for an example.
-- The method @{#SPAWN.GetGroupFromIndex} will return the GROUP object reference from the given Index, dead or alive...
-- You can use the methods @{#SPAWN.GetFirstAliveGroup}() and sequently @{#SPAWN.GetNextAliveGroup}() to iterate through the alive GROUPS within the SPAWN object, and to actions... See the respective methods for an example.
-- The method @{#SPAWN.GetGroupFromIndex}() will return the GROUP object reference from the given Index, dead or alive...
--
-- 1.5) SPAWN object cleaning
-- --------------------------
-- Sometimes, it will occur during a mission run-time, that ground or especially air objects get damaged, and will while being damged stop their activities, while remaining alive.
-- In such cases, the SPAWN object will just sit there and wait until that group gets destroyed, but most of the time it won't,
-- and it may occur that no new groups are or can be spawned as limits are reached.
-- To prevent this, a @{#SPAWN.CleanUp} initialization method has been defined that will silently monitor the status of each spawned group.
-- To prevent this, a @{#SPAWN.InitCleanUp}() initialization method has been defined that will silently monitor the status of each spawned group.
-- Once a group has a velocity = 0, and has been waiting for a defined interval, that group will be cleaned or removed from run-time.
-- There is a catch however :-) If a damaged group has returned to an airbase within the coalition, that group will not be considered as "lost"...
-- In such a case, when the inactive group is cleaned, a new group will Re-spawned automatically.
-- This models AI that has succesfully returned to their airbase, to restart their combat activities.
-- Check the @{#SPAWN.CleanUp} for further info.
-- Check the @{#SPAWN.InitCleanUp}() for further info.
--
-- 1.6) Catch the @{Group} spawn event in a callback function!
-- -----------------------------------------------------------
-- When using the SpawnScheduled method, new @{Group}s are created following the schedule timing parameters.
-- When a new @{Group} is spawned, you maybe want to execute actions with that group spawned at the spawn event.
-- To SPAWN class supports this functionality through the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method, which takes a function as a parameter that you can define locally.
-- Whenever a new @{Group} is spawned, the given function is called, and the @{Group} that was just spawned, is given as a parameter.
-- As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned @{Group} object.
-- A coding example is provided at the description of the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method.
--
-- ====
--
-- **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:
--
-- 2016-08-15: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval )
--
-- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called!
-- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
--
-- 2016-08-15: SPAWN:**InitRandomizeZones( SpawnZones )** added.
--
-- * This method provides the functionality to randomize the spawning of the Groups at a given list of zones of different types.
--
-- 2016-08-14: SPAWN:**OnSpawnGroup**( SpawnCallBackFunction, ... ) replaces SPAWN:_SpawnFunction_( SpawnCallBackFunction, ... ).
--
-- 2016-08-14: SPAWN.SpawnInZone( Zone, __RandomizeGroup__, SpawnIndex ) replaces SpawnInZone( Zone, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ).
--
-- * The RandomizeUnits, OuterRadius and InnerRadius have been replaced with a new method @{#SPAWN.InitRandomizeUnits}( RandomizeUnits, OuterRadius, InnerRadius ).
-- * A new parameter RandomizeGroup to reflect the randomization of the starting position of the Spawned @{Group}.
--
-- 2016-08-14: SPAWN.SpawnFromVec3( Vec3, SpawnIndex ) replaces SpawnFromVec3( Vec3, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
--
-- * The RandomizeUnits, OuterRadius and InnerRadius have been replaced with a new method @{#SPAWN.InitRandomizeUnits}( RandomizeUnits, OuterRadius, InnerRadius ).
-- * A new parameter RandomizeGroup to reflect the randomization of the starting position of the Spawned @{Group}.
--
-- 2016-08-14: SPAWN.SpawnFromVec2( Vec2, SpawnIndex ) replaces SpawnFromVec2( Vec2, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
--
-- * The RandomizeUnits, OuterRadius and InnerRadius have been replaced with a new method @{#SPAWN.InitRandomizeUnits}( RandomizeUnits, OuterRadius, InnerRadius ).
-- * A new parameter RandomizeGroup to reflect the randomization of the starting position of the Spawned @{Group}.
--
-- 2016-08-14: SPAWN.SpawnFromUnit( SpawnUnit, SpawnIndex ) replaces SpawnFromUnit( SpawnUnit, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
--
-- * The RandomizeUnits, OuterRadius and InnerRadius have been replaced with a new method @{#SPAWN.InitRandomizeUnits}( RandomizeUnits, OuterRadius, InnerRadius ).
-- * A new parameter RandomizeGroup to reflect the randomization of the starting position of the Spawned @{Group}.
--
-- 2016-08-14: SPAWN.SpawnFromUnit( SpawnUnit, SpawnIndex ) replaces SpawnFromStatic( SpawnStatic, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
--
-- * The RandomizeUnits, OuterRadius and InnerRadius have been replaced with a new method @{#SPAWN.InitRandomizeUnits}( RandomizeUnits, OuterRadius, InnerRadius ).
-- * A new parameter RandomizeGroup to reflect the randomization of the starting position of the Spawned @{Group}.
--
-- 2016-08-14: SPAWN.**InitRandomizeUnits( RandomizeUnits, OuterRadius, InnerRadius )** added:
--
-- * This method enables the randomization of units at the first route point in a radius band at a spawn event.
--
-- 2016-08-14: SPAWN.**Init**Limit( SpawnMaxUnitsAlive, SpawnMaxGroups ) replaces SPAWN._Limit_( SpawnMaxUnitsAlive, SpawnMaxGroups ):
--
-- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called!
-- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
--
-- 2016-08-14: SPAWN.**Init**Array( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ) replaces SPAWN._Array_( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ).
--
-- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called!
-- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
--
-- 2016-08-14: SPAWN.**Init**RandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight ) replaces SPAWN._RandomizeRoute_( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight ).
--
-- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called!
-- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
--
-- 2016-08-14: SPAWN.**Init**RandomizeTemplate( SpawnTemplatePrefixTable ) replaces SPAWN._RandomizeTemplate_( SpawnTemplatePrefixTable ).
--
-- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called!
-- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
--
-- 2016-08-14: SPAWN.**Init**UnControlled() replaces SPAWN._UnControlled_().
--
-- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called!
-- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
--
-- ===
--
-- AUTHORS and CONTRIBUTIONS
-- =========================
--
-- ### Contributions:
--
-- * **Aaron**: Posed the idea for Group position randomization at SpawnInZone and make the Unit randomization separate from the Group randomization.
--
-- ### Authors:
--
-- * **FlightControl**: Design & Programming
--
--
-- @module Spawn
-- @author FlightControl
--- SPAWN Class
-- @type SPAWN
-- @extends Base#BASE
-- @extends Core.Base#BASE
-- @field ClassName
-- @field #string SpawnTemplatePrefix
-- @field #string SpawnAliasPrefix
@ -100,15 +203,18 @@
-- @field #number MaxAliveUnits
-- @field #number SpawnIndex
-- @field #number MaxAliveGroups
-- @field #SPAWN.SpawnZoneTable SpawnZoneTable
SPAWN = {
ClassName = "SPAWN",
SpawnTemplatePrefix = nil,
SpawnAliasPrefix = nil,
}
--- @type SPAWN.SpawnZoneTable
-- @list <Core.Zone#ZONE_BASE> SpawnZone
--- Creates the main object to spawn a GROUP defined in the DCS ME.
--- Creates the main object to spawn a @{Group} defined in the DCS ME.
-- @param #SPAWN self
-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.
-- @return #SPAWN
@ -183,7 +289,7 @@ end
--- Limits the Maximum amount of Units that can be alive at the same time, and the maximum amount of groups that can be spawned.
-- Note that this method is exceptionally important to balance the performance of the mission. Depending on the machine etc, a mission can only process a maximum amount of units.
-- If the time interval must be short, but there should not be more Units or Groups alive than a maximum amount of units, then this function should be used...
-- If the time interval must be short, but there should not be more Units or Groups alive than a maximum amount of units, then this method should be used...
-- When a @{#SPAWN.New} is executed and the limit of the amount of units alive is reached, then no new spawn will happen of the group, until some of these units of the spawn object will be destroyed.
-- @param #SPAWN self
-- @param #number SpawnMaxUnitsAlive The maximum amount of units that can be alive at runtime.
@ -195,8 +301,8 @@ end
-- -- NATO helicopters engaging in the battle field.
-- -- This helicopter group consists of one Unit. So, this group will SPAWN maximum 2 groups simultaneously within the DCSRTE.
-- -- There will be maximum 24 groups spawned during the whole mission lifetime.
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):Limit( 2, 24 )
function SPAWN:Limit( SpawnMaxUnitsAlive, SpawnMaxGroups )
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):InitLimit( 2, 24 )
function SPAWN:InitLimit( SpawnMaxUnitsAlive, SpawnMaxGroups )
self:F( { self.SpawnTemplatePrefix, SpawnMaxUnitsAlive, SpawnMaxGroups } )
self.SpawnMaxUnitsAlive = SpawnMaxUnitsAlive -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time.
@ -224,8 +330,8 @@ end
-- -- The KA-50 has waypoints Start point ( =0 or SP ), 1, 2, 3, 4, End point (= 5 or DP).
-- -- Waypoints 2 and 3 will only be randomized. The others will remain on their original position with each new spawn of the helicopter.
-- -- The randomization of waypoint 2 and 3 will take place within a radius of 2000 meters.
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):RandomizeRoute( 2, 2, 2000 )
function SPAWN:RandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight )
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):InitRandomizeRoute( 2, 2, 2000 )
function SPAWN:InitRandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight )
self:F( { self.SpawnTemplatePrefix, SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight } )
self.SpawnRandomizeRoute = true
@ -241,9 +347,34 @@ function SPAWN:RandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius, Spaw
return self
end
--- Randomizes the UNITs that are spawned within a radius band given an Outer and Inner radius.
-- @param #SPAWN self
-- @param #boolean RandomizeUnits If true, SPAWN will perform the randomization of the @{UNIT}s position within the group between a given outer and inner radius.
-- @param Dcs.DCSTypes#Distance OuterRadius (optional) The outer radius in meters where the new group will be spawned.
-- @param Dcs.DCSTypes#Distance InnerRadius (optional) The inner radius in meters where the new group will NOT be spawned.
-- @return #SPAWN
-- @usage
-- -- NATO helicopters engaging in the battle field.
-- -- The KA-50 has waypoints Start point ( =0 or SP ), 1, 2, 3, 4, End point (= 5 or DP).
-- -- Waypoints 2 and 3 will only be randomized. The others will remain on their original position with each new spawn of the helicopter.
-- -- The randomization of waypoint 2 and 3 will take place within a radius of 2000 meters.
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):InitRandomizeRoute( 2, 2, 2000 )
function SPAWN:InitRandomizeUnits( RandomizeUnits, OuterRadius, InnerRadius )
self:F( { self.SpawnTemplatePrefix, RandomizeUnits, OuterRadius, InnerRadius } )
--- This function is rather complicated to understand. But I'll try to explain.
-- This function becomes useful when you need to spawn groups with random templates of groups defined within the mission editor,
self.SpawnRandomizeUnits = RandomizeUnits or false
self.SpawnOuterRadius = OuterRadius or 0
self.SpawnInnerRadius = InnerRadius or 0
for GroupID = 1, self.SpawnMaxGroups do
self:_RandomizeRoute( GroupID )
end
return self
end
--- This method is rather complicated to understand. But I'll try to explain.
-- This method becomes useful when you need to spawn groups with random templates of groups defined within the mission editor,
-- but they will all follow the same Template route and have the same prefix name.
-- In other words, this method randomizes between a defined set of groups the template to be used for each new spawn of a group.
-- @param #SPAWN self
@ -258,10 +389,10 @@ end
-- Spawn_US_Platoon = { 'US Tank Platoon 1', 'US Tank Platoon 2', 'US Tank Platoon 3', 'US Tank Platoon 4', 'US Tank Platoon 5',
-- 'US Tank Platoon 6', 'US Tank Platoon 7', 'US Tank Platoon 8', 'US Tank Platoon 9', 'US Tank Platoon 10',
-- 'US Tank Platoon 11', 'US Tank Platoon 12', 'US Tank Platoon 13' }
-- Spawn_US_Platoon_Left = SPAWN:New( 'US Tank Platoon Left' ):Limit( 12, 150 ):Schedule( 200, 0.4 ):RandomizeTemplate( Spawn_US_Platoon ):RandomizeRoute( 3, 3, 2000 )
-- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):Limit( 12, 150 ):Schedule( 200, 0.4 ):RandomizeTemplate( Spawn_US_Platoon ):RandomizeRoute( 3, 3, 2000 )
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):Limit( 12, 150 ):Schedule( 200, 0.4 ):RandomizeTemplate( Spawn_US_Platoon ):RandomizeRoute( 3, 3, 2000 )
function SPAWN:RandomizeTemplate( SpawnTemplatePrefixTable )
-- Spawn_US_Platoon_Left = SPAWN:New( 'US Tank Platoon Left' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
-- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
function SPAWN:InitRandomizeTemplate( SpawnTemplatePrefixTable )
self:F( { self.SpawnTemplatePrefix, SpawnTemplatePrefixTable } )
self.SpawnTemplatePrefixTable = SpawnTemplatePrefixTable
@ -274,12 +405,33 @@ function SPAWN:RandomizeTemplate( SpawnTemplatePrefixTable )
return self
end
--TODO: Add example.
--- This method provides the functionality to randomize the spawning of the Groups at a given list of zones of different types.
-- @param #SPAWN self
-- @param #table SpawnZoneTable A table with @{Zone} objects. If this table is given, then each spawn will be executed within the given list of @{Zone}s objects.
-- @return #SPAWN
-- @usage
-- -- NATO Tank Platoons invading Gori.
-- -- Choose between 3 different zones for each new SPAWN the Group to be executed, regardless of the zone type.
function SPAWN:InitRandomizeZones( SpawnZoneTable )
self:F( { self.SpawnTemplatePrefix, SpawnZoneTable } )
self.SpawnZoneTable = SpawnZoneTable
self.SpawnRandomizeZones = true
for SpawnGroupID = 1, self.SpawnMaxGroups do
self:_RandomizeZones( SpawnGroupID )
end
return self
end
--- For planes and helicopters, when these groups go home and land on their home airbases and farps, they normally would taxi to the parking spot, shut-down their engines and wait forever until the Group is removed by the runtime environment.
-- This function is used to re-spawn automatically (so no extra call is needed anymore) the same group after it has landed.
-- This method is used to re-spawn automatically (so no extra call is needed anymore) the same group after it has landed.
-- This will enable a spawned group to be re-spawned after it lands, until it is destroyed...
-- Note: When the group is respawned, it will re-spawn from the original airbase where it took off.
-- So ensure that the routes for groups that respawn, always return to the original airbase, or players may get confused ...
@ -288,7 +440,7 @@ end
-- @usage
-- -- RU Su-34 - AI Ship Attack
-- -- Re-SPAWN the Group(s) after each landing and Engine Shut-Down automatically.
-- SpawnRU_SU34 = SPAWN:New( 'TF1 RU Su-34 Krymsk@AI - Attack Ships' ):Schedule( 2, 3, 1800, 0.4 ):SpawnUncontrolled():RandomizeRoute( 1, 1, 3000 ):RepeatOnEngineShutDown()
-- SpawnRU_SU34 = SPAWN:New( 'TF1 RU Su-34 Krymsk@AI - Attack Ships' ):Schedule( 2, 3, 1800, 0.4 ):SpawnUncontrolled():InitRandomizeRoute( 1, 1, 3000 ):RepeatOnEngineShutDown()
function SPAWN:InitRepeat()
self:F( { self.SpawnTemplatePrefix, self.SpawnIndex } )
@ -333,11 +485,15 @@ end
-- @param #string SpawnCleanUpInterval The interval to check for inactive groups within seconds.
-- @return #SPAWN self
-- @usage Spawn_Helicopter:CleanUp( 20 ) -- CleanUp the spawning of the helicopters every 20 seconds when they become inactive.
function SPAWN:CleanUp( SpawnCleanUpInterval )
function SPAWN:InitCleanUp( SpawnCleanUpInterval )
self:F( { self.SpawnTemplatePrefix, SpawnCleanUpInterval } )
self.SpawnCleanUpInterval = SpawnCleanUpInterval
self.SpawnCleanUpTimeStamps = {}
local SpawnGroup, SpawnCursor = self:GetFirstAliveGroup()
self:T( { "CleanUp Scheduler:", SpawnGroup } )
--self.CleanUpFunction = routines.scheduleFunction( self._SpawnCleanUpScheduler, { self }, timer.getTime() + 1, SpawnCleanUpInterval )
self.CleanUpScheduler = SCHEDULER:New( self, self._SpawnCleanUpScheduler, {}, 1, SpawnCleanUpInterval, 0.2 )
return self
@ -355,8 +511,8 @@ end
-- @return #SPAWN self
-- @usage
-- -- Define an array of Groups.
-- Spawn_BE_Ground = SPAWN:New( 'BE Ground' ):Limit( 2, 24 ):Visible( 90, "Diamond", 10, 100, 50 )
function SPAWN:Array( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY )
-- Spawn_BE_Ground = SPAWN:New( 'BE Ground' ):InitLimit( 2, 24 ):InitArray( 90, "Diamond", 10, 100, 50 )
function SPAWN:InitArray( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY )
self:F( { self.SpawnTemplatePrefix, SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY } )
self.SpawnVisible = true -- When the first Spawn executes, all the Groups need to be made visible before start.
@ -416,7 +572,7 @@ end
--- Will spawn a group based on the internal index.
-- Note: Uses @{DATABASE} module defined in MOOSE.
-- @param #SPAWN self
-- @return Group#GROUP The group that was spawned. You can use this group for further actions.
-- @return Wrapper.Group#GROUP The group that was spawned. You can use this group for further actions.
function SPAWN:Spawn()
self:F( { self.SpawnTemplatePrefix, self.SpawnIndex, self.AliveUnits } )
@ -427,7 +583,7 @@ end
-- Note: Uses @{DATABASE} module defined in MOOSE.
-- @param #SPAWN self
-- @param #string SpawnIndex The index of the group to be spawned.
-- @return Group#GROUP The group that was spawned. You can use this group for further actions.
-- @return Wrapper.Group#GROUP The group that was spawned. You can use this group for further actions.
function SPAWN:ReSpawn( SpawnIndex )
self:F( { self.SpawnTemplatePrefix, SpawnIndex } )
@ -450,7 +606,8 @@ end
--- Will spawn a group with a specified index number.
-- Uses @{DATABASE} global object defined in MOOSE.
-- @param #SPAWN self
-- @return Group#GROUP The group that was spawned. You can use this group for further actions.
-- @param #string SpawnIndex The index of the group to be spawned.
-- @return Wrapper.Group#GROUP The group that was spawned. You can use this group for further actions.
function SPAWN:SpawnWithIndex( SpawnIndex )
self:F2( { SpawnTemplatePrefix = self.SpawnTemplatePrefix, SpawnIndex = SpawnIndex, AliveUnits = self.AliveUnits, SpawnMaxGroups = self.SpawnMaxGroups } )
@ -459,20 +616,40 @@ function SPAWN:SpawnWithIndex( SpawnIndex )
if self.SpawnGroups[self.SpawnIndex].Visible then
self.SpawnGroups[self.SpawnIndex].Group:Activate()
else
_EVENTDISPATCHER:OnBirthForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnBirth, self )
_EVENTDISPATCHER:OnCrashForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnDeadOrCrash, self )
_EVENTDISPATCHER:OnDeadForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnDeadOrCrash, self )
local SpawnTemplate = self.SpawnGroups[self.SpawnIndex].SpawnTemplate
self:T( SpawnTemplate.name )
if SpawnTemplate then
local PointVec3 = POINT_VEC3:New( SpawnTemplate.route.points[1].x, SpawnTemplate.route.points[1].alt, SpawnTemplate.route.points[1].y )
self:T( { "Current point of ", self.SpawnTemplatePrefix, PointVec3 } )
-- If RandomizeUnits, then Randomize the formation at the start point.
if self.SpawnRandomizeUnits then
for UnitID = 1, #SpawnTemplate.units do
local RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnOuterRadius, self.SpawnInnerRadius )
SpawnTemplate.units[UnitID].x = RandomVec2.x
SpawnTemplate.units[UnitID].y = RandomVec2.y
self:T( 'SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
end
end
end
_EVENTDISPATCHER:OnBirthForTemplate( SpawnTemplate, self._OnBirth, self )
_EVENTDISPATCHER:OnCrashForTemplate( SpawnTemplate, self._OnDeadOrCrash, self )
_EVENTDISPATCHER:OnDeadForTemplate( SpawnTemplate, self._OnDeadOrCrash, self )
if self.Repeat then
_EVENTDISPATCHER:OnTakeOffForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnTakeOff, self )
_EVENTDISPATCHER:OnLandForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnLand, self )
_EVENTDISPATCHER:OnTakeOffForTemplate( SpawnTemplate, self._OnTakeOff, self )
_EVENTDISPATCHER:OnLandForTemplate( SpawnTemplate, self._OnLand, self )
end
if self.RepeatOnEngineShutDown then
_EVENTDISPATCHER:OnEngineShutDownForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnEngineShutDown, self )
_EVENTDISPATCHER:OnEngineShutDownForTemplate( SpawnTemplate, self._OnEngineShutDown, self )
end
self:T3( self.SpawnGroups[self.SpawnIndex].SpawnTemplate )
self:T3( SpawnTemplate.name )
self.SpawnGroups[self.SpawnIndex].Group = _DATABASE:Spawn( self.SpawnGroups[self.SpawnIndex].SpawnTemplate )
self.SpawnGroups[self.SpawnIndex].Group = _DATABASE:Spawn( SpawnTemplate )
-- If there is a SpawnFunction hook defined, call it.
if self.SpawnFunctionHook then
@ -520,7 +697,7 @@ function SPAWN:SpawnScheduled( SpawnTime, SpawnTimeVariation )
end
--- Will re-start the spawning scheduler.
-- Note: This function is only required to be called when the schedule was stopped.
-- Note: This method is only required to be called when the schedule was stopped.
function SPAWN:SpawnScheduleStart()
self:F( { self.SpawnTemplatePrefix } )
@ -536,16 +713,27 @@ end
--- Allows to place a CallFunction hook when a new group spawns.
-- The provided function will be called when a new group is spawned, including its given parameters.
-- The first parameter of the SpawnFunction is the @{Group#GROUP} that was spawned.
-- The provided method will be called when a new group is spawned, including its given parameters.
-- The first parameter of the SpawnFunction is the @{Wrapper.Group#GROUP} that was spawned.
-- @param #SPAWN self
-- @param #function SpawnFunctionHook The function to be called when a group spawns.
-- @param #function SpawnCallBackFunction The function to be called when a group spawns.
-- @param SpawnFunctionArguments A random amount of arguments to be provided to the function when the group spawns.
-- @return #SPAWN
function SPAWN:SpawnFunction( SpawnFunctionHook, ... )
self:F( SpawnFunction )
-- @usage
-- -- Declare SpawnObject and call a function when a new Group is spawned.
-- local SpawnObject = SPAWN
-- :New( "SpawnObject" )
-- :InitLimit( 2, 10 )
-- :OnSpawnGroup(
-- function( SpawnGroup )
-- SpawnGroup:E( "I am spawned" )
-- end
-- )
-- :SpawnScheduled( 300, 0.3 )
function SPAWN:OnSpawnGroup( SpawnCallBackFunction, ... )
self:F( "OnSpawnGroup" )
self.SpawnFunctionHook = SpawnFunctionHook
self.SpawnFunctionHook = SpawnCallBackFunction
self.SpawnFunctionArguments = {}
if arg then
self.SpawnFunctionArguments = arg
@ -556,18 +744,16 @@ end
--- Will spawn a group from a Vec3 in 3D space.
-- This function is mostly advisable to be used if you want to simulate spawning units in the air, like helicopters or airplanes.
-- This method is mostly advisable to be used if you want to simulate spawning units in the air, like helicopters or airplanes.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param DCSTypes#Vec3 Vec3 The Vec3 coordinates where to spawn the group.
-- @param #number OuterRadius (Optional) The outer radius in meters where the new group will be spawned.
-- @param #number InnerRadius (Optional) The inner radius in meters where the new group will NOT be spawned.
-- @param #number SpawnIndex (Optional) The index which group to spawn within the given zone.
-- @return Group#GROUP that was spawned.
-- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 coordinates where to spawn the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil Nothing was spawned.
function SPAWN:SpawnFromVec3( Vec3, OuterRadius, InnerRadius, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, Vec3, OuterRadius, InnerRadius, SpawnIndex } )
function SPAWN:SpawnFromVec3( Vec3, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, Vec3, SpawnIndex } )
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 )
self:T2(PointVec3)
@ -584,33 +770,30 @@ function SPAWN:SpawnFromVec3( Vec3, OuterRadius, InnerRadius, SpawnIndex )
if SpawnTemplate then
self:T( { "Current point of ", self.SpawnTemplatePrefix, Vec3 } )
-- Translate the position of the Group Template to the Vec3.
for UnitID = 1, #SpawnTemplate.units do
self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
local UnitTemplate = SpawnTemplate.units[UnitID]
local SX = UnitTemplate.x
local SY = UnitTemplate.y
local BX = SpawnTemplate.route.points[1].x
local BY = SpawnTemplate.route.points[1].y
local TX = Vec3.x + ( SX - BX )
local TY = Vec3.z + ( SY - BY )
SpawnTemplate.units[UnitID].x = TX
SpawnTemplate.units[UnitID].y = TY
SpawnTemplate.units[UnitID].alt = Vec3.y
self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
end
SpawnTemplate.route.points[1].x = Vec3.x
SpawnTemplate.route.points[1].y = Vec3.z
SpawnTemplate.route.points[1].alt = Vec3.y
InnerRadius = InnerRadius or 0
OuterRadius = OuterRadius or 0
-- Apply SpawnFormation
for UnitID = 1, #SpawnTemplate.units do
local RandomVec2 = PointVec3:GetRandomVec2InRadius( OuterRadius, InnerRadius )
SpawnTemplate.units[UnitID].x = RandomVec2.x
SpawnTemplate.units[UnitID].y = RandomVec2.y
SpawnTemplate.units[UnitID].alt = Vec3.y
self:T( 'SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
end
-- TODO: Need to rework this. A spawn action should always be at the random point to start from. This move is not correct to be here.
-- local RandomVec2 = PointVec3:GetRandomVec2InRadius( OuterRadius, InnerRadius )
-- local Point = {}
-- Point.type = "Turning Point"
-- Point.x = RandomVec2.x
-- Point.y = RandomVec2.y
-- Point.action = "Cone"
-- Point.speed = 5
-- table.insert( SpawnTemplate.route.points, 2, Point )
SpawnTemplate.x = Vec3.x
SpawnTemplate.y = Vec3.z
return self:SpawnWithIndex( self.SpawnIndex )
end
end
@ -619,93 +802,86 @@ function SPAWN:SpawnFromVec3( Vec3, OuterRadius, InnerRadius, SpawnIndex )
end
--- Will spawn a group from a Vec2 in 3D space.
-- This function is mostly advisable to be used if you want to simulate spawning groups on the ground from air units, like vehicles.
-- This method is mostly advisable to be used if you want to simulate spawning groups on the ground from air units, like vehicles.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param DCSTypes#Vec2 Vec2 The Vec2 coordinates where to spawn the group.
-- @param #number OuterRadius (Optional) The outer radius in meters where the new group will be spawned.
-- @param #number InnerRadius (Optional) The inner radius in meters where the new group will NOT be spawned.
-- @param #number SpawnIndex (Optional) The index which group to spawn within the given zone.
-- @return Group#GROUP that was spawned.
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 coordinates where to spawn the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil Nothing was spawned.
function SPAWN:SpawnFromVec2( Vec2, OuterRadius, InnerRadius, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, Vec2, OuterRadius, InnerRadius, SpawnIndex } )
function SPAWN:SpawnFromVec2( Vec2, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, Vec2, SpawnIndex } )
local PointVec2 = POINT_VEC2:NewFromVec2( Vec2 )
return self:SpawnFromVec3( PointVec2:GetVec3(), OuterRadius, InnerRadius, SpawnIndex )
return self:SpawnFromVec3( PointVec2:GetVec3(), SpawnIndex )
end
--- Will spawn a group from a hosting unit. This function is mostly advisable to be used if you want to simulate spawning from air units, like helicopters, which are dropping infantry into a defined Landing Zone.
--- Will spawn a group from a hosting unit. This method is mostly advisable to be used if you want to simulate spawning from air units, like helicopters, which are dropping infantry into a defined Landing Zone.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param Unit#UNIT HostUnit The air or ground unit dropping or unloading the group.
-- @param #number OuterRadius (Optional) The outer radius in meters where the new group will be spawned.
-- @param #number InnerRadius (Optional) The inner radius in meters where the new group will NOT be spawned.
-- @param #number SpawnIndex (Optional) The index which group to spawn within the given zone.
-- @return Group#GROUP that was spawned.
-- @param Wrapper.Unit#UNIT HostUnit The air or ground unit dropping or unloading the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil Nothing was spawned.
function SPAWN:SpawnFromUnit( HostUnit, OuterRadius, InnerRadius, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, HostUnit, OuterRadius, InnerRadius, SpawnIndex } )
function SPAWN:SpawnFromUnit( HostUnit, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, HostUnit, SpawnIndex } )
if HostUnit and HostUnit:IsAlive() then -- and HostUnit:getUnit(1):inAir() == false then
return self:SpawnFromVec3( HostUnit:GetVec3(), OuterRadius, InnerRadius, SpawnIndex )
return self:SpawnFromVec3( HostUnit:GetVec3(), SpawnIndex )
end
return nil
end
--- Will spawn a group from a hosting static. This function is mostly advisable to be used if you want to simulate spawning from buldings and structures (static buildings).
--- Will spawn a group from a hosting static. This method is mostly advisable to be used if you want to simulate spawning from buldings and structures (static buildings).
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param Static#STATIC HostStatic The static dropping or unloading the group.
-- @param #number OuterRadius (Optional) The outer radius in meters where the new group will be spawned.
-- @param #number InnerRadius (Optional) The inner radius in meters where the new group will NOT be spawned.
-- @param #number SpawnIndex (Optional) The index which group to spawn within the given zone.
-- @return Group#GROUP that was spawned.
-- @param Wrapper.Static#STATIC HostStatic The static dropping or unloading the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil Nothing was spawned.
function SPAWN:SpawnFromStatic( HostStatic, OuterRadius, InnerRadius, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, HostStatic, OuterRadius, InnerRadius, SpawnIndex } )
function SPAWN:SpawnFromStatic( HostStatic, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, HostStatic, SpawnIndex } )
if HostStatic and HostStatic:IsAlive() then
return self:SpawnFromVec3( HostStatic:GetVec3(), OuterRadius, InnerRadius, SpawnIndex )
return self:SpawnFromVec3( HostStatic:GetVec3(), SpawnIndex )
end
return nil
end
--- Will spawn a Group within a given @{Zone#ZONE}.
-- Once the group is spawned within the zone, it will continue on its route.
-- The first waypoint (where the group is spawned) is replaced with the zone coordinates.
--- Will spawn a Group within a given @{Zone}.
-- The @{Zone} can be of any type derived from @{Core.Zone#ZONE_BASE}.
-- Once the @{Group} is spawned within the zone, the @{Group} will continue on its route.
-- The **first waypoint** (where the group is spawned) is replaced with the zone location coordinates.
-- @param #SPAWN self
-- @param Zone#ZONE Zone The zone where the group is to be spawned.
-- @param #number ZoneRandomize (Optional) Set to true if you want to randomize the starting point in the zone.
-- @param #number SpawnIndex (Optional) The index which group to spawn within the given zone.
-- @return Group#GROUP that was spawned.
-- @param Core.Zone#ZONE Zone The zone where the group is to be spawned.
-- @param #boolean RandomizeGroup (optional) Randomization of the @{Group} position in the zone.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil when nothing was spawned.
function SPAWN:SpawnInZone( Zone, ZoneRandomize, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, Zone, ZoneRandomize, SpawnIndex } )
function SPAWN:SpawnInZone( Zone, RandomizeGroup, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, Zone, RandomizeGroup, SpawnIndex } )
if Zone then
if ZoneRandomize then
return self:SpawnFromVec2( Zone:GetVec2(), Zone:GetRadius(), 0, SpawnIndex )
if RandomizeGroup then
return self:SpawnFromVec2( Zone:GetRandomVec2(), SpawnIndex )
else
return self:SpawnFromVec2( Zone:GetVec2(), 0, 0, SpawnIndex )
return self:SpawnFromVec2( Zone:GetVec2(), SpawnIndex )
end
end
return nil
end
--- Will spawn a plane group in uncontrolled mode...
--- (AIR) Will spawn a plane group in uncontrolled mode...
-- This will be similar to the uncontrolled flag setting in the ME.
-- @param #SPAWN self
-- @return #SPAWN self
function SPAWN:UnControlled()
function SPAWN:InitUnControlled()
self:F( { self.SpawnTemplatePrefix } )
self.SpawnUnControlled = true
@ -742,12 +918,12 @@ function SPAWN:SpawnGroupName( SpawnIndex )
end
--- Will find the first alive GROUP it has spawned, and return the alive GROUP object and the first Index where the first alive GROUP object has been found.
--- Will find the first alive @{Group} it has spawned, and return the alive @{Group} object and the first Index where the first alive @{Group} object has been found.
-- @param #SPAWN self
-- @return Group#GROUP, #number The GROUP object found, the new Index where the group was found.
-- @return Wrapper.Group#GROUP, #number The @{Group} object found, the new Index where the group was found.
-- @return #nil, #nil When no group is found, #nil is returned.
-- @usage
-- -- Find the first alive GROUP object of the SpawnPlanes SPAWN object GROUP collection that it has spawned during the mission.
-- -- Find the first alive @{Group} object of the SpawnPlanes SPAWN object @{Group} collection that it has spawned during the mission.
-- local GroupPlane, Index = SpawnPlanes:GetFirstAliveGroup()
-- while GroupPlane ~= nil do
-- -- Do actions with the GroupPlane object.
@ -767,13 +943,13 @@ function SPAWN:GetFirstAliveGroup()
end
--- Will find the next alive GROUP object from a given Index, and return a reference to the alive GROUP object and the next Index where the alive GROUP has been found.
--- Will find the next alive @{Group} object from a given Index, and return a reference to the alive @{Group} object and the next Index where the alive @{Group} has been found.
-- @param #SPAWN self
-- @param #number SpawnIndexStart A Index holding the start position to search from. This function can also be used to find the first alive GROUP object from the given Index.
-- @return Group#GROUP, #number The next alive GROUP object found, the next Index where the next alive GROUP object was found.
-- @return #nil, #nil When no alive GROUP object is found from the start Index position, #nil is returned.
-- @param #number SpawnIndexStart A Index holding the start position to search from. This method can also be used to find the first alive @{Group} object from the given Index.
-- @return Wrapper.Group#GROUP, #number The next alive @{Group} object found, the next Index where the next alive @{Group} object was found.
-- @return #nil, #nil When no alive @{Group} object is found from the start Index position, #nil is returned.
-- @usage
-- -- Find the first alive GROUP object of the SpawnPlanes SPAWN object GROUP collection that it has spawned during the mission.
-- -- Find the first alive @{Group} object of the SpawnPlanes SPAWN object @{Group} collection that it has spawned during the mission.
-- local GroupPlane, Index = SpawnPlanes:GetFirstAliveGroup()
-- while GroupPlane ~= nil do
-- -- Do actions with the GroupPlane object.
@ -793,12 +969,12 @@ function SPAWN:GetNextAliveGroup( SpawnIndexStart )
return nil, nil
end
--- Will find the last alive GROUP object, and will return a reference to the last live GROUP object and the last Index where the last alive GROUP object has been found.
--- Will find the last alive @{Group} object, and will return a reference to the last live @{Group} object and the last Index where the last alive @{Group} object has been found.
-- @param #SPAWN self
-- @return Group#GROUP, #number The last alive GROUP object found, the last Index where the last alive GROUP object was found.
-- @return #nil, #nil When no alive GROUP object is found, #nil is returned.
-- @return Wrapper.Group#GROUP, #number The last alive @{Group} object found, the last Index where the last alive @{Group} object was found.
-- @return #nil, #nil When no alive @{Group} object is found, #nil is returned.
-- @usage
-- -- Find the last alive GROUP object of the SpawnPlanes SPAWN object GROUP collection that it has spawned during the mission.
-- -- Find the last alive @{Group} object of the SpawnPlanes SPAWN object @{Group} collection that it has spawned during the mission.
-- local GroupPlane, Index = SpawnPlanes:GetLastAliveGroup()
-- if GroupPlane then -- GroupPlane can be nil!!!
-- -- Do actions with the GroupPlane object.
@ -826,7 +1002,7 @@ end
-- If no index is given, it will return the first group in the list.
-- @param #SPAWN self
-- @param #number SpawnIndex The index of the group to return.
-- @return Group#GROUP self
-- @return Wrapper.Group#GROUP self
function SPAWN:GetGroupFromIndex( SpawnIndex )
self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnIndex } )
@ -846,7 +1022,7 @@ end
-- The method will search for a #-mark, and will return the index behind the #-mark of the DCSUnit.
-- It will return nil of no prefix was found.
-- @param #SPAWN self
-- @param DCSUnit#Unit DCSUnit The @{DCSUnit} to be searched.
-- @param Dcs.DCSWrapper.Unit#Unit DCSUnit The @{DCSUnit} to be searched.
-- @return #string The prefix
-- @return #nil Nothing found
function SPAWN:_GetGroupIndexFromDCSUnit( DCSUnit )
@ -868,7 +1044,7 @@ end
-- The method will search for a #-mark, and will return the text before the #-mark.
-- It will return nil of no prefix was found.
-- @param #SPAWN self
-- @param DCSUnit#UNIT DCSUnit The @{DCSUnit} to be searched.
-- @param Dcs.DCSWrapper.Unit#UNIT DCSUnit The @{DCSUnit} to be searched.
-- @return #string The prefix
-- @return #nil Nothing found
function SPAWN:_GetPrefixFromDCSUnit( DCSUnit )
@ -888,8 +1064,8 @@ end
--- Return the group within the SpawnGroups collection with input a DCSUnit.
-- @param #SPAWN self
-- @param DCSUnit#Unit DCSUnit The @{DCSUnit} to be searched.
-- @return Group#GROUP The Group
-- @param Dcs.DCSWrapper.Unit#Unit DCSUnit The @{DCSUnit} to be searched.
-- @return Wrapper.Group#GROUP The Group
-- @return #nil Nothing found
function SPAWN:_GetGroupFromDCSUnit( DCSUnit )
self:F3( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, DCSUnit } )
@ -1038,8 +1214,6 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex )
for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].name = string.format( SpawnTemplate.name .. '-%02d', UnitID )
SpawnTemplate.units[UnitID].unitId = nil
SpawnTemplate.units[UnitID].x = SpawnTemplate.route.points[1].x
SpawnTemplate.units[UnitID].y = SpawnTemplate.route.points[1].y
end
self:T3( { "Template:", SpawnTemplate } )
@ -1076,6 +1250,8 @@ function SPAWN:_RandomizeRoute( SpawnIndex )
end
end
self:_RandomizeZones( SpawnIndex )
return self
end
@ -1106,6 +1282,57 @@ function SPAWN:_RandomizeTemplate( SpawnIndex )
return self
end
--- Private method that randomizes the @{Zone}s where the Group will be spawned.
-- @param #SPAWN self
-- @param #number SpawnIndex
-- @return #SPAWN self
function SPAWN:_RandomizeZones( SpawnIndex )
self:F( { self.SpawnTemplatePrefix, SpawnIndex, self.SpawnRandomizeZones } )
if self.SpawnRandomizeZones then
local SpawnZone = nil -- Core.Zone#ZONE_BASE
while not SpawnZone do
self:T( { SpawnZoneTableCount = #self.SpawnZoneTable, self.SpawnZoneTable } )
local ZoneID = math.random( #self.SpawnZoneTable )
self:T( ZoneID )
SpawnZone = self.SpawnZoneTable[ ZoneID ]:GetZoneMaybe()
end
self:T( "Preparing Spawn in Zone", SpawnZone:GetName() )
local SpawnVec2 = SpawnZone:GetRandomVec2()
self:T( { SpawnVec2 = SpawnVec2 } )
local SpawnTemplate = self.SpawnGroups[SpawnIndex].SpawnTemplate
self:T( { Route = SpawnTemplate.route } )
for UnitID = 1, #SpawnTemplate.units do
local UnitTemplate = SpawnTemplate.units[UnitID]
self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. UnitTemplate.x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. UnitTemplate.y )
local SX = UnitTemplate.x
local SY = UnitTemplate.y
local BX = SpawnTemplate.route.points[1].x
local BY = SpawnTemplate.route.points[1].y
local TX = SpawnVec2.x + ( SX - BX )
local TY = SpawnVec2.y + ( SY - BY )
UnitTemplate.x = TX
UnitTemplate.y = TY
-- TODO: Manage altitude based on landheight...
--SpawnTemplate.units[UnitID].alt = SpawnVec2:
self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. UnitTemplate.x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. UnitTemplate.y )
end
SpawnTemplate.x = SpawnVec2.x
SpawnTemplate.y = SpawnVec2.y
SpawnTemplate.route.points[1].x = SpawnVec2.x
SpawnTemplate.route.points[1].y = SpawnVec2.y
end
return self
end
function SPAWN:_TranslateRotate( SpawnIndex, SpawnRootX, SpawnRootY, SpawnX, SpawnY, SpawnAngle )
self:F( { self.SpawnTemplatePrefix, SpawnIndex, SpawnRootX, SpawnRootY, SpawnX, SpawnY, SpawnAngle } )
@ -1149,7 +1376,7 @@ function SPAWN:_TranslateRotate( SpawnIndex, SpawnRootX, SpawnRootY, SpawnX, Spa
return self
end
--- Get the next index of the groups to be spawned. This function is complicated, as it is used at several spaces.
--- Get the next index of the groups to be spawned. This method is complicated, as it is used at several spaces.
function SPAWN:_GetSpawnIndex( SpawnIndex )
self:F2( { self.SpawnTemplatePrefix, SpawnIndex, self.SpawnMaxGroups, self.SpawnMaxUnitsAlive, self.AliveUnits, #self.SpawnTemplate.units } )
@ -1177,7 +1404,7 @@ end
-- TODO Need to delete this... _DATABASE does this now ...
--- @param #SPAWN self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function SPAWN:_OnBirth( Event )
if timer.getTime0() < timer.getAbsTime() then
@ -1197,7 +1424,7 @@ end
-- @todo Need to delete this... _DATABASE does this now ...
--- @param #SPAWN self
-- @param Event#EVENTDATA Event
-- @param Core.Event#EVENTDATA Event
function SPAWN:_OnDeadOrCrash( Event )
self:F( self.SpawnTemplatePrefix, Event )
@ -1284,32 +1511,64 @@ function SPAWN:_Scheduler()
return true
end
--- Schedules the CleanUp of Groups
-- @param #SPAWN self
-- @return #boolean True = Continue Scheduler
function SPAWN:_SpawnCleanUpScheduler()
self:F( { "CleanUp Scheduler:", self.SpawnTemplatePrefix } )
local SpawnCursor
local SpawnGroup, SpawnCursor = self:GetFirstAliveGroup( SpawnCursor )
self:T( { "CleanUp Scheduler:", SpawnGroup } )
local SpawnGroup, SpawnCursor = self:GetFirstAliveGroup()
self:T( { "CleanUp Scheduler:", SpawnGroup, SpawnCursor } )
while SpawnGroup do
if SpawnGroup:AllOnGround() and SpawnGroup:GetMaxVelocity() < 1 then
if not self.SpawnCleanUpTimeStamps[SpawnGroup:GetName()] then
self.SpawnCleanUpTimeStamps[SpawnGroup:GetName()] = timer.getTime()
else
if self.SpawnCleanUpTimeStamps[SpawnGroup:GetName()] + self.SpawnCleanUpInterval < timer.getTime() then
self:T( { "CleanUp Scheduler:", "Cleaning:", SpawnGroup } )
SpawnGroup:Destroy()
end
end
else
self.SpawnCleanUpTimeStamps[SpawnGroup:GetName()] = nil
end
local SpawnUnits = SpawnGroup:GetUnits()
for UnitID, UnitData in pairs( SpawnUnits ) do
local SpawnUnit = UnitData -- Wrapper.Unit#UNIT
local SpawnUnitName = SpawnUnit:GetName()
self.SpawnCleanUpTimeStamps[SpawnUnitName] = self.SpawnCleanUpTimeStamps[SpawnUnitName] or {}
local Stamp = self.SpawnCleanUpTimeStamps[SpawnUnitName]
self:T( { SpawnUnitName, Stamp } )
if Stamp.Vec2 then
if SpawnUnit:InAir() == false and SpawnUnit:GetVelocityKMH() < 1 then
local NewVec2 = SpawnUnit:GetVec2()
if Stamp.Vec2.x == NewVec2.x and Stamp.Vec2.y == NewVec2.y then
-- If the plane is not moving, and is on the ground, assign it with a timestamp...
if Stamp.Time + self.SpawnCleanUpInterval < timer.getTime() then
self:T( { "CleanUp Scheduler:", "ReSpawning:", SpawnGroup:GetName() } )
self:ReSpawn( SpawnCursor )
Stamp.Vec2 = nil
Stamp.Time = nil
end
else
Stamp.Time = timer.getTime()
Stamp.Vec2 = SpawnUnit:GetVec2()
end
else
Stamp.Vec2 = nil
Stamp.Time = nil
end
else
if SpawnUnit:InAir() == false then
Stamp.Vec2 = SpawnUnit:GetVec2()
if SpawnUnit:GetVelocityKMH() < 1 then
Stamp.Time = timer.getTime()
end
else
Stamp.Time = nil
Stamp.Vec2 = nil
end
end
end
SpawnGroup, SpawnCursor = self:GetNextAliveGroup( SpawnCursor )
self:T( { "CleanUp Scheduler:", SpawnGroup } )
self:T( { "CleanUp Scheduler:", SpawnGroup, SpawnCursor } )
end

View File

@ -1,71 +1,74 @@
--- The main include file for the MOOSE system.
Include.File( "Routines" )
Include.File( "Utils" )
Include.File( "Base" )
Include.File( "Object" )
Include.File( "Identifiable" )
Include.File( "Positionable" )
Include.File( "Controllable" )
Include.File( "Scheduler" )
Include.File( "Event" )
Include.File( "Menu" )
Include.File( "Group" )
Include.File( "Unit" )
Include.File( "Zone" )
Include.File( "Client" )
Include.File( "Static" )
Include.File( "Airbase" )
Include.File( "Database" )
Include.File( "Set" )
Include.File( "Point" )
Include.File( "Moose" )
Include.File( "Scoring" )
Include.File( "Cargo" )
Include.File( "Message" )
Include.File( "Stage" )
Include.File( "Task" )
Include.File( "GoHomeTask" )
Include.File( "DestroyBaseTask" )
Include.File( "DestroyGroupsTask" )
Include.File( "DestroyRadarsTask" )
Include.File( "DestroyUnitTypesTask" )
Include.File( "PickupTask" )
Include.File( "DeployTask" )
Include.File( "NoTask" )
Include.File( "RouteTask" )
Include.File( "Mission" )
Include.File( "CleanUp" )
Include.File( "Spawn" )
Include.File( "Movement" )
Include.File( "Sead" )
Include.File( "Escort" )
Include.File( "MissileTrainer" )
Include.File( "PatrolZone" )
Include.File( "AIBalancer" )
Include.File( "AirbasePolice" )
--- Core Routines
Include.File( "Utilities/Routines" )
Include.File( "Utilities/Utils" )
Include.File( "Detection" )
Include.File( "DetectionManager" )
--- 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( "StateMachine" )
--- 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( "Process" )
Include.File( "Process_Assign" )
Include.File( "Process_Route" )
Include.File( "Process_Smoke" )
Include.File( "Process_Destroy" )
Include.File( "Process_JTAC" )
--- 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_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_SEAD" )
Include.File( "Tasking/Task_A2G" )
Include.File( "Task" )
Include.File( "Task_SEAD" )
Include.File( "Task_A2G" )
-- The order of the declarations is important here. Don't touch it.
--- Declare the event dispatcher based on the EVENT class
_EVENTDISPATCHER = EVENT:New() -- Event#EVENT
_EVENTDISPATCHER = EVENT:New() -- Core.Event#EVENT
--- Declare the timer dispatcher based on the SCHEDULEDISPATCHER class
_SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.Timer#SCHEDULEDISPATCHER
--- Declare the main database object, which is used internally by the MOOSE classes.
_DATABASE = DATABASE:New() -- Database#DATABASE

View File

@ -1,8 +0,0 @@
local Mission = MISSION:New( "Pickup Cargo", "High", "Test for Cargo Pickup", coalition.side.RED )
local CargoEngineer = UNIT:FindByName( "Engineer" )
local InfantryCargo = CARGO_UNIT:New( Mission, CargoEngineer, "Engineer", "Engineer Sven", "81", 2000, 300 )
local CargoCarrier = UNIT:FindByName( "CargoCarrier" )
InfantryCargo:OnBoard( CargoCarrier )

View File

@ -1,265 +0,0 @@
--- This module contains the PATROLZONE class.
--
-- ===
--
-- 1) @{Patrol#PATROLZONE} class, extends @{Base#BASE}
-- ===================================================
-- The @{Patrol#PATROLZONE} class implements the core functions to patrol a @{Zone}.
--
-- 1.1) PATROLZONE constructor:
-- ----------------------------
-- @{PatrolZone#PATROLZONE.New}(): Creates a new PATROLZONE object.
--
-- 1.2) Modify the PATROLZONE parameters:
-- --------------------------------------
-- The following methods are available to modify the parameters of a PATROLZONE object:
--
-- * @{PatrolZone#PATROLZONE.SetGroup}(): Set the AI Patrol Group.
-- * @{PatrolZone#PATROLZONE.SetSpeed}(): Set the patrol speed of the AI, for the next patrol.
-- * @{PatrolZone#PATROLZONE.SetAltitude}(): Set altitude of the AI, for the next patrol.
--
-- 1.3) Manage the out of fuel in the PATROLZONE:
-- ----------------------------------------------
-- When the PatrolGroup is out of fuel, it is required that a new PatrolGroup is started, before the old PatrolGroup can return to the home base.
-- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated.
-- When the fuel treshold is reached, the PatrolGroup will continue for a given time its patrol task in orbit, while a new PatrolGroup is targetted to the PATROLZONE.
-- Once the time is finished, the old PatrolGroup will return to the base.
-- Use the method @{PatrolZone#PATROLZONE.ManageFuel}() to have this proces in place.
--
-- ===
--
-- @module PatrolZone
-- @author FlightControl
--- PATROLZONE class
-- @type PATROLZONE
-- @field Group#GROUP PatrolGroup The @{Group} patrolling.
-- @field Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @field DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @field DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @field DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h.
-- @field DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h.
-- @extends Base#BASE
PATROLZONE = {
ClassName = "PATROLZONE",
}
--- Creates a new PATROLZONE object, taking a @{Group} object as a parameter. The GROUP needs to be alive.
-- @param #PATROLZONE self
-- @param Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h.
-- @param DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h.
-- @return #PATROLZONE self
-- @usage
-- -- Define a new PATROLZONE Object. This PatrolArea will patrol a group within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
-- PatrolZone = ZONE:New( 'PatrolZone' )
-- PatrolGroup = GROUP:FindByName( "Patrol Group" )
-- PatrolArea = PATROLZONE:New( PatrolGroup, PatrolZone, 3000, 6000, 600, 900 )
function PATROLZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed )
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() )
self.PatrolZone = PatrolZone
self.PatrolFloorAltitude = PatrolFloorAltitude
self.PatrolCeilingAltitude = PatrolCeilingAltitude
self.PatrolMinSpeed = PatrolMinSpeed
self.PatrolMaxSpeed = PatrolMaxSpeed
return self
end
--- Set the @{Group} to act as the Patroller.
-- @param #PATROLZONE self
-- @param Group#GROUP PatrolGroup The @{Group} patrolling.
-- @return #PATROLZONE self
function PATROLZONE:SetGroup( PatrolGroup )
self.PatrolGroup = PatrolGroup
self.PatrolGroupTemplateName = PatrolGroup:GetName()
self:NewPatrolRoute()
if not self.PatrolOutOfFuelMonitor then
self.PatrolOutOfFuelMonitor = SCHEDULER:New( nil, _MonitorOutOfFuelScheduled, { self }, 1, 120, 0 )
self.SpawnPatrolGroup = SPAWN:New( self.PatrolGroupTemplateName )
end
return self
end
--- Sets (modifies) the minimum and maximum speed of the patrol.
-- @param #PATROLZONE self
-- @param DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h.
-- @param DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h.
-- @return #PATROLZONE self
function PATROLZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
self.PatrolMinSpeed = PatrolMinSpeed
self.PatrolMaxSpeed = PatrolMaxSpeed
end
--- Sets the floor and ceiling altitude of the patrol.
-- @param #PATROLZONE self
-- @param DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @return #PATROLZONE self
function PATROLZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )
self.PatrolFloorAltitude = PatrolFloorAltitude
self.PatrolCeilingAltitude = PatrolCeilingAltitude
end
--- @param Group#GROUP PatrolGroup
function _NewPatrolRoute( PatrolGroup )
PatrolGroup:T( "NewPatrolRoute" )
local PatrolZone = PatrolGroup:GetState( PatrolGroup, "PatrolZone" ) -- PatrolZone#PATROLZONE
PatrolZone:NewPatrolRoute()
end
--- Defines a new patrol route using the @{PatrolZone} parameters and settings.
-- @param #PATROLZONE self
-- @return #PATROLZONE self
function PATROLZONE:NewPatrolRoute()
self:F2()
local PatrolRoute = {}
if self.PatrolGroup:IsAlive() then
--- Determine if the PatrolGroup is within the PatrolZone.
-- If not, make a waypoint within the to that the PatrolGroup will fly at maximum speed to that point.
-- --- Calculate the current route point.
-- local CurrentVec2 = self.PatrolGroup:GetVec2()
-- local CurrentAltitude = self.PatrolGroup:GetUnit(1):GetAltitude()
-- local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
-- local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
-- POINT_VEC3.RoutePointAltType.BARO,
-- POINT_VEC3.RoutePointType.TurningPoint,
-- POINT_VEC3.RoutePointAction.TurningPoint,
-- ToPatrolZoneSpeed,
-- true
-- )
--
-- PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint
self:T2( PatrolRoute )
if self.PatrolGroup:IsNotInZone( self.PatrolZone ) then
--- Find a random 2D point in PatrolZone.
local ToPatrolZoneVec2 = self.PatrolZone:GetRandomVec2()
self:T2( ToPatrolZoneVec2 )
--- Define Speed and Altitude.
local ToPatrolZoneAltitude = math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
self:T2( ToPatrolZoneSpeed )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToPatrolZonePointVec3 = POINT_VEC3:New( ToPatrolZoneVec2.x, ToPatrolZoneAltitude, ToPatrolZoneVec2.y )
--- Create a route point of type air.
local ToPatrolZoneRoutePoint = ToPatrolZonePointVec3:RoutePointAir(
POINT_VEC3.RoutePointAltType.BARO,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
ToPatrolZoneSpeed,
true
)
PatrolRoute[#PatrolRoute+1] = ToPatrolZoneRoutePoint
end
--- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
--- Find a random 2D point in PatrolZone.
local ToTargetVec2 = self.PatrolZone:GetRandomVec2()
self:T2( ToTargetVec2 )
--- Define Speed and Altitude.
local ToTargetAltitude = math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude )
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
--- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir(
POINT_VEC3.RoutePointAltType.BARO,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
ToTargetSpeed,
true
)
--ToTargetPointVec3:SmokeRed()
PatrolRoute[#PatrolRoute+1] = ToTargetRoutePoint
--- Now we're going to do something special, we're going to call a function from a waypoint action at the PatrolGroup...
self.PatrolGroup:WayPointInitialize( PatrolRoute )
--- Do a trick, link the NewPatrolRoute function of the PATROLGROUP object to the PatrolGroup in a temporary variable ...
self.PatrolGroup:SetState( self.PatrolGroup, "PatrolZone", self )
self.PatrolGroup:WayPointFunction( #PatrolRoute, 1, "_NewPatrolRoute" )
--- NOW ROUTE THE GROUP!
self.PatrolGroup:WayPointExecute( 1, 2 )
end
end
--- When the PatrolGroup is out of fuel, it is required that a new PatrolGroup is started, before the old PatrolGroup can return to the home base.
-- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated.
-- When the fuel treshold is reached, the PatrolGroup will continue for a given time its patrol task in orbit, while a new PatrolGroup is targetted to the PATROLZONE.
-- Once the time is finished, the old PatrolGroup will return to the base.
-- @param #PATROLZONE self
-- @param #number PatrolFuelTresholdPercentage The treshold in percentage (between 0 and 1) when the PatrolGroup is considered to get out of fuel.
-- @param #number PatrolOutOfFuelOrbitTime The amount of seconds the out of fuel PatrolGroup will orbit before returning to the base.
-- @return #PATROLZONE self
function PATROLZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime )
self.PatrolManageFuel = true
self.PatrolFuelTresholdPercentage = PatrolFuelTresholdPercentage
self.PatrolOutOfFuelOrbitTime = PatrolOutOfFuelOrbitTime
if self.PatrolGroup then
self.PatrolOutOfFuelMonitor = SCHEDULER:New( self, self._MonitorOutOfFuelScheduled, {}, 1, 120, 0 )
self.SpawnPatrolGroup = SPAWN:New( self.PatrolGroupTemplateName )
end
return self
end
--- @param #PATROLZONE self
function _MonitorOutOfFuelScheduled( self )
self:F2( "_MonitorOutOfFuelScheduled" )
if self.PatrolGroup and self.PatrolGroup:IsAlive() then
local Fuel = self.PatrolGroup:GetUnit(1):GetFuel()
if Fuel < self.PatrolFuelTresholdPercentage then
local OldPatrolGroup = self.PatrolGroup
local PatrolGroupTemplate = self.PatrolGroup:GetTemplate()
local OrbitTask = OldPatrolGroup:TaskOrbitCircle( math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ), self.PatrolMinSpeed )
local TimedOrbitTask = OldPatrolGroup:TaskControlled( OrbitTask, OldPatrolGroup:TaskCondition(nil,nil,nil,nil,self.PatrolOutOfFuelOrbitTime,nil ) )
OldPatrolGroup:SetTask( TimedOrbitTask, 10 )
local NewPatrolGroup = self.SpawnPatrolGroup:Spawn()
self.PatrolGroup = NewPatrolGroup
self:NewPatrolRoute()
end
else
self.PatrolOutOfFuelMonitor:Stop()
end
end

View File

@ -1,280 +0,0 @@
--- This module contains the POSITIONABLE class.
--
-- 1) @{Positionable#POSITIONABLE} class, extends @{Identifiable#IDENTIFIABLE}
-- ===========================================================
-- The @{Positionable#POSITIONABLE} class is a wrapper class to handle the POSITIONABLE objects:
--
-- * Support all DCS APIs.
-- * Enhance with POSITIONABLE specific APIs not in the DCS API set.
-- * Manage the "state" of the POSITIONABLE.
--
-- 1.1) POSITIONABLE constructor:
-- ------------------------------
-- The POSITIONABLE class provides the following functions to construct a POSITIONABLE instance:
--
-- * @{Positionable#POSITIONABLE.New}(): Create a POSITIONABLE instance.
--
-- 1.2) POSITIONABLE methods:
-- --------------------------
-- The following methods can be used to identify an measurable object:
--
-- * @{Positionable#POSITIONABLE.GetID}(): Returns the ID of the measurable object.
-- * @{Positionable#POSITIONABLE.GetName}(): Returns the name of the measurable object.
--
-- ===
--
-- @module Positionable
-- @author FlightControl
--- The POSITIONABLE class
-- @type POSITIONABLE
-- @extends Identifiable#IDENTIFIABLE
-- @field #string PositionableName The name of the measurable.
POSITIONABLE = {
ClassName = "POSITIONABLE",
PositionableName = "",
}
--- A DCSPositionable
-- @type DCSPositionable
-- @field id_ The ID of the controllable in DCS
--- Create a new POSITIONABLE from a DCSPositionable
-- @param #POSITIONABLE self
-- @param DCSPositionable#Positionable PositionableName The POSITIONABLE name
-- @return #POSITIONABLE self
function POSITIONABLE:New( PositionableName )
local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) )
return self
end
--- Returns the @{DCSTypes#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission.
-- @param Positionable#POSITIONABLE self
-- @return DCSTypes#Position The 3D position vectors of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPositionVec3()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePosition = DCSPositionable:getPosition()
self:T3( PositionablePosition )
return PositionablePosition
end
return nil
end
--- Returns the @{DCSTypes#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission.
-- @param Positionable#POSITIONABLE self
-- @return DCSTypes#Vec2 The 2D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVec2()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
local PositionableVec2 = {}
PositionableVec2.x = PositionableVec3.x
PositionableVec2.y = PositionableVec3.z
self:T2( PositionableVec2 )
return PositionableVec2
end
return nil
end
--- Returns a POINT_VEC2 object indicating the point in 2D of the POSITIONABLE within the mission.
-- @param Positionable#POSITIONABLE self
-- @return Point#POINT_VEC2 The 2D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPointVec2()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
local PositionablePointVec2 = POINT_VEC2:NewFromVec3( PositionableVec3 )
self:T2( PositionablePointVec2 )
return PositionablePointVec2
end
return nil
end
--- Returns a random @{DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Positionable#POSITIONABLE self
-- @return DCSTypes#Vec3 The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetRandomVec3( Radius )
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePointVec3 = DCSPositionable:getPosition().p
local PositionableRandomVec3 = {}
local angle = math.random() * math.pi*2;
PositionableRandomVec3.x = PositionablePointVec3.x + math.cos( angle ) * math.random() * Radius;
PositionableRandomVec3.y = PositionablePointVec3.y
PositionableRandomVec3.z = PositionablePointVec3.z + math.sin( angle ) * math.random() * Radius;
self:T3( PositionableRandomVec3 )
return PositionableRandomVec3
end
return nil
end
--- Returns the @{DCSTypes#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission.
-- @param Positionable#POSITIONABLE self
-- @return DCSTypes#Vec3 The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVec3()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
self:T3( PositionableVec3 )
return PositionableVec3
end
return nil
end
--- Returns the altitude of the POSITIONABLE.
-- @param Positionable#POSITIONABLE self
-- @return DCSTypes#Distance The altitude of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetAltitude()
self:F2()
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePointVec3 = DCSPositionable:getPoint() --DCSTypes#Vec3
return PositionablePointVec3.y
end
return nil
end
--- Returns if the Positionable is located above a runway.
-- @param Positionable#POSITIONABLE self
-- @return #boolean true if Positionable is above a runway.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:IsAboveRunway()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local Vec2 = self:GetVec2()
local SurfaceType = land.getSurfaceType( Vec2 )
local IsAboveRunway = SurfaceType == land.SurfaceType.RUNWAY
self:T2( IsAboveRunway )
return IsAboveRunway
end
return nil
end
--- Returns the POSITIONABLE heading in degrees.
-- @param Positionable#POSITIONABLE self
-- @return #number The POSTIONABLE heading
function POSITIONABLE:GetHeading()
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePosition = DCSPositionable:getPosition()
if PositionablePosition then
local PositionableHeading = math.atan2( PositionablePosition.x.z, PositionablePosition.x.x )
if PositionableHeading < 0 then
PositionableHeading = PositionableHeading + 2 * math.pi
end
PositionableHeading = PositionableHeading * 180 / math.pi
self:T2( PositionableHeading )
return PositionableHeading
end
end
return nil
end
--- Returns true if the POSITIONABLE is in the air.
-- @param Positionable#POSITIONABLE self
-- @return #boolean true if in the air.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:InAir()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableInAir = DCSPositionable:inAir()
self:T3( PositionableInAir )
return PositionableInAir
end
return nil
end
--- Returns the POSITIONABLE velocity vector.
-- @param Positionable#POSITIONABLE self
-- @return DCSTypes#Vec3 The velocity vector
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVelocity()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVelocityVec3 = DCSPositionable:getVelocity()
self:T3( PositionableVelocityVec3 )
return PositionableVelocityVec3
end
return nil
end
--- Returns the POSITIONABLE velocity in km/h.
-- @param Positionable#POSITIONABLE self
-- @return #number The velocity in km/h
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVelocityKMH()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local VelocityVec3 = self:GetVelocity()
local Velocity = ( VelocityVec3.x ^ 2 + VelocityVec3.y ^ 2 + VelocityVec3.z ^ 2 ) ^ 0.5 -- in meters / sec
local Velocity = Velocity * 3.6 -- now it is in km/h.
self:T3( Velocity )
return Velocity
end
return nil
end

View File

@ -1,90 +0,0 @@
--- @module Process
--- The PROCESS class
-- @type PROCESS
-- @field Scheduler#SCHEDULER ProcessScheduler
-- @field Unit#UNIT ProcessUnit
-- @field Group#GROUP ProcessGroup
-- @field Menu#MENU_GROUP MissionMenu
-- @field Task#TASK_BASE Task
-- @field StateMachine#STATEMACHINE_TASK Fsm
-- @field #string ProcessName
-- @extends Base#BASE
PROCESS = {
ClassName = "TASK",
ProcessScheduler = nil,
NextEvent = nil,
Scores = {},
}
--- Instantiates a new TASK Base. Should never be used. Interface Class.
-- @param #PROCESS self
-- @param #string ProcessName
-- @param Task#TASK_BASE Task
-- @param Unit#UNIT ProcessUnit
-- @return #PROCESS self
function PROCESS:New( ProcessName, Task, ProcessUnit )
local self = BASE:Inherit( self, BASE:New() )
self:F()
self.ProcessUnit = ProcessUnit
self.ProcessGroup = ProcessUnit:GetGroup()
self.MissionMenu = Task.Mission:GetMissionMenu( self.ProcessGroup )
self.Task = Task
self.ProcessName = ProcessName
self.ProcessScheduler = SCHEDULER:New()
return self
end
--- @param #PROCESS self
function PROCESS:NextEvent( NextEvent, ... )
self:F(self.ProcessName)
self.ProcessScheduler:Schedule( self.Fsm, NextEvent, arg, 1 ) -- This schedules the next event, but only if scheduling is activated.
end
--- @param #PROCESS self
function PROCESS:StopEvents()
self:F( { "Stop Process ", self.ProcessName } )
self.ProcessScheduler:Stop()
end
--- Adds a score for the PROCESS to be achieved.
-- @param #PROCESS self
-- @param #string ProcessStatus is the status of the PROCESS when the score needs to be given.
-- @param #string ScoreText is a text describing the score that is given according the status.
-- @param #number Score is a number providing the score of the status.
-- @return #PROCESS self
function PROCESS:AddScore( ProcessStatus, ScoreText, Score )
self:F2( { ProcessStatus, ScoreText, Score } )
self.Scores[ProcessStatus] = self.Scores[ProcessStatus] or {}
self.Scores[ProcessStatus].ScoreText = ScoreText
self.Scores[ProcessStatus].Score = Score
return self
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS:OnStateChange( Fsm, Event, From, To )
self:E( { self.ProcessName, Event, From, To, self.ProcessUnit.UnitName } )
if self:IsTrace() then
MESSAGE:New( "Process " .. self.ProcessName .. " : " .. Event .. " changed to state " .. To, 15 ):ToAll()
end
if self.Scores[To] then
local Scoring = self.Task:GetScoring()
if Scoring then
Scoring:_AddMissionTaskScore( self.Task.Mission, self.ProcessUnit, self.Scores[To].ScoreText, self.Scores[To].Score )
end
end
end

View File

@ -1,185 +0,0 @@
--- This module contains the PROCESS_ASSIGN classes.
--
-- ===
--
-- 1) @{Task_Assign#TASK_ASSIGN_ACCEPT} class, extends @{Task#TASK_BASE}
-- =====================================================================
-- The @{Task_Assign#TASK_ASSIGN_ACCEPT} class accepts by default a task for a player. No player intervention is allowed to reject the task.
--
-- 2) @{Task_Assign#TASK_ASSIGN_MENU_ACCEPT} class, extends @{Task#TASK_BASE}
-- ==========================================================================
-- The @{Task_Assign#TASK_ASSIGN_MENU_ACCEPT} class accepts a task when the player accepts the task through an added menu option.
-- This assignment type is useful to conditionally allow the player to choose whether or not he would accept the task.
-- The assignment type also allows to reject the task.
--
--
--
--
--
--
-- @module Task_Assign
--
do -- PROCESS_ASSIGN_ACCEPT
--- PROCESS_ASSIGN_ACCEPT class
-- @type PROCESS_ASSIGN_ACCEPT
-- @field Task#TASK_BASE Task
-- @field Unit#UNIT ProcessUnit
-- @field Zone#ZONE_BASE TargetZone
-- @extends Task2#TASK2
PROCESS_ASSIGN_ACCEPT = {
ClassName = "PROCESS_ASSIGN_ACCEPT",
}
--- Creates a new task assignment state machine. The process will accept the task by default, no player intervention accepted.
-- @param #PROCESS_ASSIGN_ACCEPT self
-- @param Task#TASK Task
-- @param Unit#UNIT Unit
-- @return #PROCESS_ASSIGN_ACCEPT self
function PROCESS_ASSIGN_ACCEPT:New( Task, ProcessUnit, TaskBriefing )
-- Inherits from BASE
local self = BASE:Inherit( self, PROCESS:New( "ASSIGN_ACCEPT", Task, ProcessUnit ) ) -- #PROCESS_ASSIGN_ACCEPT
self.TaskBriefing = TaskBriefing
self.Fsm = STATEMACHINE_PROCESS:New( self, {
initial = 'UnAssigned',
events = {
{ name = 'Start', from = 'UnAssigned', to = 'Assigned' },
{ name = 'Fail', from = 'UnAssigned', to = 'Failed' },
},
callbacks = {
onAssign = self.OnAssign,
},
endstates = {
'Assigned', 'Failed'
},
} )
return self
end
--- StateMachine callback function for a TASK2
-- @param #PROCESS_ASSIGN_ACCEPT self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_ASSIGN_ACCEPT:OnAssigned( Fsm, Event, From, To )
self:E( { Event, From, To, self.ProcessUnit.UnitName} )
end
end
do -- PROCESS_ASSIGN_MENU_ACCEPT
--- PROCESS_ASSIGN_MENU_ACCEPT class
-- @type PROCESS_ASSIGN_MENU_ACCEPT
-- @field Task#TASK_BASE Task
-- @field Unit#UNIT ProcessUnit
-- @field Zone#ZONE_BASE TargetZone
-- @extends Task2#TASK2
PROCESS_ASSIGN_MENU_ACCEPT = {
ClassName = "PROCESS_ASSIGN_MENU_ACCEPT",
}
--- Creates a new task assignment state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #PROCESS_ASSIGN_MENU_ACCEPT self
-- @param Task#TASK Task
-- @param Unit#UNIT Unit
-- @return #PROCESS_ASSIGN_MENU_ACCEPT self
function PROCESS_ASSIGN_MENU_ACCEPT:New( Task, ProcessUnit, TaskBriefing )
-- Inherits from BASE
local self = BASE:Inherit( self, PROCESS:New( "ASSIGN_MENU_ACCEPT", Task, ProcessUnit ) ) -- #PROCESS_ASSIGN_MENU_ACCEPT
self.TaskBriefing = TaskBriefing
self.Fsm = STATEMACHINE_PROCESS:New( self, {
initial = 'UnAssigned',
events = {
{ name = 'Start', from = 'UnAssigned', to = 'AwaitAccept' },
{ name = 'Assign', from = 'AwaitAccept', to = 'Assigned' },
{ name = 'Reject', from = 'AwaitAccept', to = 'Rejected' },
{ name = 'Fail', from = 'AwaitAccept', to = 'Rejected' },
},
callbacks = {
onStart = self.OnStart,
onAssign = self.OnAssign,
onReject = self.OnReject,
},
endstates = {
'Assigned', 'Rejected'
},
} )
return self
end
--- StateMachine callback function for a TASK2
-- @param #PROCESS_ASSIGN_MENU_ACCEPT self
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_ASSIGN_MENU_ACCEPT:OnStart( Fsm, Event, From, To )
self:E( { Event, From, To, self.ProcessUnit.UnitName} )
MESSAGE:New( self.TaskBriefing .. "\nAccess the radio menu to accept the task. You have 30 seconds or the assignment will be cancelled.", 30, "Assignment" ):ToGroup( self.ProcessUnit:GetGroup() )
self.MenuText = self.Task.TaskName
local ProcessGroup = self.ProcessUnit:GetGroup()
self.Menu = MENU_GROUP:New( ProcessGroup, "Task " .. self.MenuText .. " acceptance" )
self.MenuAcceptTask = MENU_GROUP_COMMAND:New( ProcessGroup, "Accept task " .. self.MenuText, self.Menu, self.MenuAssign, self )
self.MenuRejectTask = MENU_GROUP_COMMAND:New( ProcessGroup, "Reject task " .. self.MenuText, self.Menu, self.MenuReject, self )
end
--- Menu function.
-- @param #PROCESS_ASSIGN_MENU_ACCEPT self
function PROCESS_ASSIGN_MENU_ACCEPT:MenuAssign()
self:E( )
self:NextEvent( self.Fsm.Assign )
end
--- Menu function.
-- @param #PROCESS_ASSIGN_MENU_ACCEPT self
function PROCESS_ASSIGN_MENU_ACCEPT:MenuReject()
self:E( )
self:NextEvent( self.Fsm.Reject )
end
--- StateMachine callback function for a TASK2
-- @param #PROCESS_ASSIGN_MENU_ACCEPT self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_ASSIGN_MENU_ACCEPT:OnAssign( Fsm, Event, From, To )
self:E( { Event, From, To, self.ProcessUnit.UnitName} )
self.Menu:Remove()
end
--- StateMachine callback function for a TASK2
-- @param #PROCESS_ASSIGN_MENU_ACCEPT self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_ASSIGN_MENU_ACCEPT:OnReject( Fsm, Event, From, To )
self:E( { Event, From, To, self.ProcessUnit.UnitName} )
self.Menu:Remove()
self.Task:UnAssignFromUnit( self.ProcessUnit )
self.ProcessUnit:Destroy()
end
end

View File

@ -1,180 +0,0 @@
--- @module Process_Destroy
--- PROCESS_DESTROY class
-- @type PROCESS_DESTROY
-- @field Unit#UNIT ProcessUnit
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Process#PROCESS
PROCESS_DESTROY = {
ClassName = "PROCESS_DESTROY",
Fsm = {},
TargetSetUnit = nil,
}
--- Creates a new DESTROY process.
-- @param #PROCESS_DESTROY self
-- @param Task#TASK Task
-- @param Unit#UNIT ProcessUnit
-- @param Set#SET_UNIT TargetSetUnit
-- @return #PROCESS_DESTROY self
function PROCESS_DESTROY:New( Task, ProcessName, ProcessUnit, TargetSetUnit )
-- Inherits from BASE
local self = BASE:Inherit( self, PROCESS:New( ProcessName, Task, ProcessUnit ) ) -- #PROCESS_DESTROY
self.TargetSetUnit = TargetSetUnit
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
self.DisplayCategory = "HQ" -- Targets is the default display category
self.Fsm = STATEMACHINE_PROCESS:New( self, {
initial = 'Assigned',
events = {
{ name = 'Start', from = 'Assigned', to = 'Waiting' },
{ name = 'Start', from = 'Waiting', to = 'Waiting' },
{ name = 'HitTarget', from = 'Waiting', to = 'Destroy' },
{ name = 'MoreTargets', from = 'Destroy', to = 'Waiting' },
{ name = 'Destroyed', from = 'Destroy', to = 'Success' },
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
{ name = 'Fail', from = 'Waiting', to = 'Failed' },
{ name = 'Fail', from = 'Destroy', to = 'Failed' },
},
callbacks = {
onStart = self.OnStart,
onWaiting = self.OnWaiting,
onHitTarget = self.OnHitTarget,
onMoreTargets = self.OnMoreTargets,
onDestroyed = self.OnDestroyed,
onKilled = self.OnKilled,
},
endstates = { 'Success', 'Failed' }
} )
_EVENTDISPATCHER:OnDead( self.EventDead, self )
return self
end
--- Process Events
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_DESTROY self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_DESTROY:OnStart( Fsm, Event, From, To )
self:NextEvent( Fsm.Start )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_DESTROY self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_DESTROY:OnWaiting( Fsm, Event, From, To )
local TaskGroup = self.ProcessUnit:GetGroup()
if self.DisplayCount >= self.DisplayInterval then
MESSAGE:New( "Your group with assigned " .. self.Task:GetName() .. " task has " .. self.TargetSetUnit:GetUnitTypesText() .. " targets left to be destroyed.", 5, "HQ" ):ToGroup( TaskGroup )
self.DisplayCount = 1
else
self.DisplayCount = self.DisplayCount + 1
end
return true -- Process always the event.
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_DESTROY self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function PROCESS_DESTROY:OnHitTarget( Fsm, Event, From, To, Event )
self.TargetSetUnit:Flush()
if self.TargetSetUnit:FindUnit( Event.IniUnitName ) then
self.TargetSetUnit:RemoveUnitsByName( Event.IniUnitName )
local TaskGroup = self.ProcessUnit:GetGroup()
MESSAGE:New( "You hit a target. Your group with assigned " .. self.Task:GetName() .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed.", 15, "HQ" ):ToGroup( TaskGroup )
end
if self.TargetSetUnit:Count() > 0 then
self:NextEvent( Fsm.MoreTargets )
else
self:NextEvent( Fsm.Destroyed )
end
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_DESTROY self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_DESTROY:OnMoreTargets( Fsm, Event, From, To )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_DESTROY self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA DCSEvent
function PROCESS_DESTROY:OnKilled( Fsm, Event, From, To )
self:NextEvent( Fsm.Restart )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_DESTROY self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_DESTROY:OnRestart( Fsm, Event, From, To )
self:NextEvent( Fsm.Menu )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_DESTROY self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_DESTROY:OnDestroyed( Fsm, Event, From, To )
end
--- DCS Events
--- @param #PROCESS_DESTROY self
-- @param Event#EVENTDATA Event
function PROCESS_DESTROY:EventDead( Event )
if Event.IniDCSUnit then
self:NextEvent( self.Fsm.HitTarget, Event )
end
end

View File

@ -1,86 +0,0 @@
--- @module Task_Route
--- PROCESS_ROUTE class
-- @type PROCESS_ROUTE
-- @field Task#TASK TASK
-- @field Unit#UNIT ProcessUnit
-- @field Zone#ZONE_BASE TargetZone
-- @extends Task2#TASK2
PROCESS_ROUTE = {
ClassName = "PROCESS_ROUTE",
}
--- Creates a new routing state machine. The task will route a CLIENT to a ZONE until the CLIENT is within that ZONE.
-- @param #PROCESS_ROUTE self
-- @param Task#TASK Task
-- @param Unit#UNIT Unit
-- @return #PROCESS_ROUTE self
function PROCESS_ROUTE:New( Task, ProcessUnit, TargetZone )
-- Inherits from BASE
local self = BASE:Inherit( self, PROCESS:New( "ROUTE", Task, ProcessUnit ) ) -- #PROCESS_ROUTE
self.TargetZone = TargetZone
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
self.DisplayCategory = "HQ" -- Route is the default display category
self.Fsm = STATEMACHINE_PROCESS:New( self, {
initial = 'UnArrived',
events = {
{ name = 'Start', from = 'UnArrived', to = 'UnArrived' },
{ name = 'Fail', from = 'UnArrived', to = 'Failed' },
},
callbacks = {
onleaveUnArrived = self.OnLeaveUnArrived,
onFail = self.OnFail,
},
endstates = {
'Arrived', 'Failed'
},
} )
return self
end
--- Task Events
--- StateMachine callback function for a TASK2
-- @param #PROCESS_ROUTE self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_ROUTE:OnLeaveUnArrived( Fsm, Event, From, To )
if self.ProcessUnit:IsAlive() then
local IsInZone = self.ProcessUnit:IsInZone( self.TargetZone )
if self.DisplayCount >= self.DisplayInterval then
if not IsInZone then
local ZoneVec2 = self.TargetZone:GetVec2()
local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y )
local TaskUnitVec2 = self.ProcessUnit:GetVec2()
local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y )
local RouteText = self.ProcessUnit:GetCallsign() .. ": Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target."
MESSAGE:New( RouteText, self.DisplayTime, self.DisplayCategory ):ToGroup( self.ProcessUnit:GetGroup() )
end
self.DisplayCount = 1
else
self.DisplayCount = self.DisplayCount + 1
end
--if not IsInZone then
self:NextEvent( Fsm.Start )
--end
return IsInZone -- if false, then the event will not be executed...
end
return false
end

View File

@ -1,108 +0,0 @@
--- @module Process_Smoke
do -- PROCESS_SMOKE_TARGETS
--- PROCESS_SMOKE_TARGETS class
-- @type PROCESS_SMOKE_TARGETS
-- @field Task#TASK_BASE Task
-- @field Unit#UNIT ProcessUnit
-- @field Set#SET_UNIT TargetSetUnit
-- @field Zone#ZONE_BASE TargetZone
-- @extends Task2#TASK2
PROCESS_SMOKE_TARGETS = {
ClassName = "PROCESS_SMOKE_TARGETS",
}
--- Creates a new task assignment state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #PROCESS_SMOKE_TARGETS self
-- @param Task#TASK Task
-- @param Unit#UNIT Unit
-- @return #PROCESS_SMOKE_TARGETS self
function PROCESS_SMOKE_TARGETS:New( Task, ProcessUnit, TargetSetUnit, TargetZone )
-- Inherits from BASE
local self = BASE:Inherit( self, PROCESS:New( "ASSIGN_MENU_ACCEPT", Task, ProcessUnit ) ) -- #PROCESS_SMOKE_TARGETS
self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone
self.Fsm = STATEMACHINE_PROCESS:New( self, {
initial = 'None',
events = {
{ name = 'Start', from = 'None', to = 'AwaitSmoke' },
{ name = 'Next', from = 'AwaitSmoke', to = 'Smoking' },
{ name = 'Next', from = 'Smoking', to = 'AwaitSmoke' },
{ name = 'Fail', from = 'Smoking', to = 'Failed' },
{ name = 'Fail', from = 'AwaitSmoke', to = 'Failed' },
{ name = 'Fail', from = 'None', to = 'Failed' },
},
callbacks = {
onStart = self.OnStart,
onNext = self.OnNext,
onSmoking = self.OnSmoking,
},
endstates = {
},
} )
return self
end
--- StateMachine callback function for a TASK2
-- @param #PROCESS_SMOKE_TARGETS self
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_SMOKE_TARGETS:OnStart( Fsm, Event, From, To )
self:E( { Event, From, To, self.ProcessUnit.UnitName} )
self:E("Set smoke menu")
local ProcessGroup = self.ProcessUnit:GetGroup()
local MissionMenu = self.Task.Mission:GetMissionMenu( ProcessGroup )
local function MenuSmoke( MenuParam )
self:E( MenuParam )
local self = MenuParam.self
local SmokeColor = MenuParam.SmokeColor
self.SmokeColor = SmokeColor
self:NextEvent( self.Fsm.Next )
end
self.Menu = MENU_GROUP:New( ProcessGroup, "Target acquisition", MissionMenu )
self.MenuSmokeBlue = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop blue smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Blue } )
self.MenuSmokeGreen = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop green smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Green } )
self.MenuSmokeOrange = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop Orange smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Orange } )
self.MenuSmokeRed = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop Red smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Red } )
self.MenuSmokeWhite = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop White smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.White } )
end
--- StateMachine callback function for a TASK2
-- @param #PROCESS_SMOKE_TARGETS self
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_SMOKE_TARGETS:OnSmoking( Fsm, Event, From, To )
self:E( { Event, From, To, self.ProcessUnit.UnitName} )
self.TargetSetUnit:ForEachUnit(
--- @param Unit#UNIT SmokeUnit
function( SmokeUnit )
if math.random( 1, ( 100 * self.TargetSetUnit:Count() ) / 4 ) <= 100 then
SCHEDULER:New( self,
function()
if SmokeUnit:IsAlive() then
SmokeUnit:Smoke( self.SmokeColor, 150 )
end
end, {}, math.random( 10, 60 )
)
end
end
)
end
end

View File

@ -1,202 +0,0 @@
--- This module contains the SCHEDULER class.
--
-- 1) @{Scheduler#SCHEDULER} class, extends @{Base#BASE}
-- =====================================================
-- The @{Scheduler#SCHEDULER} class models time events calling given event handling functions.
--
-- 1.1) SCHEDULER constructor
-- --------------------------
-- The SCHEDULER class is quite easy to use:
--
-- * @{Scheduler#SCHEDULER.New}: Setup a new scheduler and start it with the specified parameters.
--
-- 1.2) SCHEDULER timer stop and start
-- -----------------------------------
-- The SCHEDULER can be stopped and restarted with the following methods:
--
-- * @{Scheduler#SCHEDULER.Start}: (Re-)Start the scheduler.
-- * @{Scheduler#SCHEDULER.Stop}: Stop the scheduler.
--
-- 1.3) Reschedule new time event
-- ------------------------------
-- With @{Scheduler#SCHEDULER.Schedule} a new time event can be scheduled.
--
-- ===
--
-- ### Contributions:
--
-- * Mechanist : Concept & Testing
--
-- ### Authors:
--
-- * FlightControl : Design & Programming
--
-- ===
--
-- @module Scheduler
--- The SCHEDULER class
-- @type SCHEDULER
-- @field #number ScheduleID the ID of the scheduler.
-- @extends Base#BASE
SCHEDULER = {
ClassName = "SCHEDULER",
}
--- SCHEDULER constructor.
-- @param #SCHEDULER self
-- @param #table TimeEventObject Specified for which Moose object the timer is setup. If a value of nil is provided, a scheduler will be setup without an object reference.
-- @param #function TimeEventFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in TimeEventFunctionArguments.
-- @param #table TimeEventFunctionArguments Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
-- @param #number StartSeconds Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
-- @param #number RepeatSecondsInterval Specifies the interval in seconds when the scheduler will call the event function.
-- @param #number RandomizationFactor Specifies a randomization factor between 0 and 1 to randomize the RepeatSecondsInterval.
-- @param #number StopSeconds Specifies the amount of seconds when the scheduler will be stopped.
-- @return #SCHEDULER self
function SCHEDULER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds )
local self = BASE:Inherit( self, BASE:New() )
self:F2( { TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds } )
self:Schedule( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds )
return self
end
--- Schedule a new time event. Note that the schedule will only take place if the scheduler is *started*. Even for a single schedule event, the scheduler needs to be started also.
-- @param #SCHEDULER self
-- @param #table TimeEventObject Specified for which Moose object the timer is setup. If a value of nil is provided, a scheduler will be setup without an object reference.
-- @param #function TimeEventFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in TimeEventFunctionArguments.
-- @param #table TimeEventFunctionArguments Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
-- @param #number StartSeconds Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
-- @param #number RepeatSecondsInterval Specifies the interval in seconds when the scheduler will call the event function.
-- @param #number RandomizationFactor Specifies a randomization factor between 0 and 1 to randomize the RepeatSecondsInterval.
-- @param #number StopSeconds Specifies the amount of seconds when the scheduler will be stopped.
-- @return #SCHEDULER self
function SCHEDULER:Schedule( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds )
self:F2( { TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds } )
self.TimeEventObject = TimeEventObject
self.TimeEventFunction = TimeEventFunction
self.TimeEventFunctionArguments = TimeEventFunctionArguments
self.StartSeconds = StartSeconds
self.Repeat = false
self.RepeatSecondsInterval = RepeatSecondsInterval or 0
self.RandomizationFactor = RandomizationFactor or 0
self.StopSeconds = StopSeconds
self.StartTime = timer.getTime()
self:Start()
return self
end
--- (Re-)Starts the scheduler.
-- @param #SCHEDULER self
-- @return #SCHEDULER self
function SCHEDULER:Start()
self:F2( self.TimeEventObject )
if self.RepeatSecondsInterval ~= 0 then
self.Repeat = true
end
if self.StartSeconds then
if self.ScheduleID then
timer.removeFunction( self.ScheduleID )
end
self.ScheduleID = timer.scheduleFunction( self._Scheduler, self, timer.getTime() + self.StartSeconds + .01 )
end
return self
end
--- Stops the scheduler.
-- @param #SCHEDULER self
-- @return #SCHEDULER self
function SCHEDULER:Stop()
self:F2( self.TimeEventObject )
self.Repeat = false
if self.ScheduleID then
self:E( "Stop Schedule" )
timer.removeFunction( self.ScheduleID )
end
self.ScheduleID = nil
return self
end
-- Private Functions
--- @param #SCHEDULER self
function SCHEDULER:_Scheduler()
self:F2( self.TimeEventFunctionArguments )
local ErrorHandler = function( errmsg )
env.info( "Error in SCHEDULER function:" .. errmsg )
if debug ~= nil then
env.info( debug.traceback() )
end
return errmsg
end
local StartTime = self.StartTime
local StopSeconds = self.StopSeconds
local Repeat = self.Repeat
local RandomizationFactor = self.RandomizationFactor
local RepeatSecondsInterval = self.RepeatSecondsInterval
local ScheduleID = self.ScheduleID
local Status, Result
if self.TimeEventObject then
Status, Result = xpcall( function() return self.TimeEventFunction( self.TimeEventObject, unpack( self.TimeEventFunctionArguments ) ) end, ErrorHandler )
else
Status, Result = xpcall( function() return self.TimeEventFunction( unpack( self.TimeEventFunctionArguments ) ) end, ErrorHandler )
end
self:T( { "Timer Event2 .. " .. self.ScheduleID, Status, Result, StartTime, RepeatSecondsInterval, RandomizationFactor, StopSeconds } )
if Status and ( ( Result == nil ) or ( Result and Result ~= false ) ) then
if Repeat and ( not StopSeconds or ( StopSeconds and timer.getTime() <= StartTime + StopSeconds ) ) then
local ScheduleTime =
timer.getTime() +
self.RepeatSecondsInterval +
math.random(
- ( RandomizationFactor * RepeatSecondsInterval / 2 ),
( RandomizationFactor * RepeatSecondsInterval / 2 )
) +
0.01
self:T( { self.TimeEventFunctionArguments, "Repeat:", timer.getTime(), ScheduleTime } )
return ScheduleTime -- returns the next time the function needs to be called.
else
timer.removeFunction( ScheduleID )
self.ScheduleID = nil
end
else
timer.removeFunction( ScheduleID )
self.ScheduleID = nil
end
return nil
end

View File

@ -1,290 +0,0 @@
--- This module contains the STATEMACHINE class.
-- This development is based on a state machine implementation made by Conroy Kyle.
-- The state machine can be found here: https://github.com/kyleconroy/lua-state-machine
--
-- I've taken the development and enhanced it to make the state machine hierarchical...
-- It is a fantastic development, this module.
--
-- ===
--
-- 1) @{Workflow#STATEMACHINE} class, extends @{Base#BASE}
-- ==============================================
--
-- 1.1) Add or remove objects from the STATEMACHINE
-- --------------------------------------------
-- @module StateMachine
-- @author FlightControl
--- STATEMACHINE class
-- @type STATEMACHINE
STATEMACHINE = {
ClassName = "STATEMACHINE",
}
--- Creates a new STATEMACHINE object.
-- @param #STATEMACHINE self
-- @return #STATEMACHINE
function STATEMACHINE:New( options )
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() )
--local self = routines.utils.deepCopy( self ) -- Create a new self instance
assert(options.events)
--local MT = {}
--setmetatable( self, MT )
--self.__index = self
self.options = options
self.current = options.initial or 'none'
self.events = {}
self.subs = {}
self.endstates = {}
for _, event in ipairs(options.events or {}) do
local name = event.name
self[name] = self[name] or self:_create_transition(name)
self.events[name] = self.events[name] or { map = {} }
self:_add_to_map(self.events[name].map, event)
end
for name, callback in pairs(options.callbacks or {}) do
self[name] = callback
end
for name, sub in pairs( options.subs or {} ) do
self:_submap( self.subs, sub, name )
end
for name, endstate in pairs( options.endstates or {} ) do
self.endstates[endstate] = endstate
end
return self
end
function STATEMACHINE:LoadCallBacks( CallBackTable )
for name, callback in pairs( CallBackTable or {} ) do
self[name] = callback
end
end
function STATEMACHINE:_submap( subs, sub, name )
self:E( { sub = sub, name = name } )
subs[sub.onstateparent] = subs[sub.onstateparent] or {}
subs[sub.onstateparent][sub.oneventparent] = subs[sub.onstateparent][sub.oneventparent] or {}
local Index = #subs[sub.onstateparent][sub.oneventparent] + 1
subs[sub.onstateparent][sub.oneventparent][Index] = {}
subs[sub.onstateparent][sub.oneventparent][Index].fsm = sub.fsm
subs[sub.onstateparent][sub.oneventparent][Index].event = sub.event
subs[sub.onstateparent][sub.oneventparent][Index].returnevents = sub.returnevents -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
subs[sub.onstateparent][sub.oneventparent][Index].name = name
subs[sub.onstateparent][sub.oneventparent][Index].fsmparent = self
end
function STATEMACHINE:_call_handler(handler, params)
if handler then
return handler(unpack(params))
end
end
function STATEMACHINE:_create_transition(name)
self:E( { name = name } )
return function(self, ...)
local can, to = self:can(name)
self:T( { name, can, to } )
if can then
local from = self.current
local params = { self, name, from, to, ... }
if self:_call_handler(self["onbefore" .. name], params) == false
or self:_call_handler(self["onleave" .. from], params) == false then
return false
end
self.current = to
local execute = true
local subtable = self:_gosub( to, name )
for _, sub in pairs( subtable ) do
self:F( "calling sub: " .. sub.event )
sub.fsm.fsmparent = self
sub.fsm.returnevents = sub.returnevents
sub.fsm[sub.event]( sub.fsm )
execute = true
end
local fsmparent, event = self:_isendstate( to )
if fsmparent and event then
self:F( { "end state: ", fsmparent, event } )
self:_call_handler(self["onenter" .. to] or self["on" .. to], params)
self:_call_handler(self["onafter" .. name] or self["on" .. name], params)
self:_call_handler(self["onstatechange"], params)
fsmparent[event]( fsmparent )
execute = false
end
if execute then
self:F( { "execute: " .. to, name } )
self:_call_handler(self["onenter" .. to] or self["on" .. to], params)
self:_call_handler(self["onafter" .. name] or self["on" .. name], params)
self:_call_handler(self["onstatechange"], params)
end
return true
end
return false
end
end
function STATEMACHINE:_gosub( parentstate, parentevent )
local fsmtable = {}
if self.subs[parentstate] and self.subs[parentstate][parentevent] then
return self.subs[parentstate][parentevent]
else
return {}
end
end
function STATEMACHINE:_isendstate( state )
local fsmparent = self.fsmparent
if fsmparent and self.endstates[state] then
self:E( { state = state, endstates = self.endstates, endstate = self.endstates[state] } )
local returnevent = nil
local fromstate = fsmparent.current
self:E( fromstate )
self:E( self.returnevents )
for _, eventname in pairs( self.returnevents ) do
local event = fsmparent.events[eventname]
self:E( event )
local to = event and event.map[fromstate] or event.map['*']
if to and to == state then
return fsmparent, eventname
else
self:E( { "could not find parent event name for state", fromstate, to } )
end
end
end
return nil
end
function STATEMACHINE:_add_to_map(map, event)
if type(event.from) == 'string' then
map[event.from] = event.to
else
for _, from in ipairs(event.from) do
map[from] = event.to
end
end
end
function STATEMACHINE:is(state)
return self.current == state
end
function STATEMACHINE:can(e)
local event = self.events[e]
local to = event and event.map[self.current] or event.map['*']
return to ~= nil, to
end
function STATEMACHINE:cannot(e)
return not self:can(e)
end
function STATEMACHINE:todot(filename)
local dotfile = io.open(filename,'w')
dotfile:write('digraph {\n')
local transition = function(event,from,to)
dotfile:write(string.format('%s -> %s [label=%s];\n',from,to,event))
end
for _, event in pairs(self.options.events) do
if type(event.from) == 'table' then
for _, from in ipairs(event.from) do
transition(event.name,from,event.to)
end
else
transition(event.name,event.from,event.to)
end
end
dotfile:write('}\n')
dotfile:close()
end
--- STATEMACHINE_PROCESS class
-- @type STATEMACHINE_PROCESS
-- @field Process#PROCESS Process
-- @extends StateMachine#STATEMACHINE
STATEMACHINE_PROCESS = {
ClassName = "STATEMACHINE_PROCESS",
}
--- Creates a new STATEMACHINE_PROCESS object.
-- @param #STATEMACHINE_PROCESS self
-- @return #STATEMACHINE_PROCESS
function STATEMACHINE_PROCESS:New( Process, options )
local FsmProcess = routines.utils.deepCopy( self ) -- Create a new self instance
local Parent = STATEMACHINE:New(options)
setmetatable( FsmProcess, Parent )
FsmProcess.__index = FsmProcess
FsmProcess["onstatechange"] = Process.OnStateChange
FsmProcess.Process = Process
return FsmProcess
end
function STATEMACHINE_PROCESS:_call_handler( handler, params )
if handler then
return handler( self.Process, unpack( params ) )
end
end
--- STATEMACHINE_TASK class
-- @type STATEMACHINE_TASK
-- @field Task#TASK_BASE Task
-- @extends StateMachine#STATEMACHINE
STATEMACHINE_TASK = {
ClassName = "STATEMACHINE_TASK",
}
--- Creates a new STATEMACHINE_TASK object.
-- @param #STATEMACHINE_TASK self
-- @return #STATEMACHINE_TASK
function STATEMACHINE_TASK:New( Task, TaskUnit, options )
local FsmTask = routines.utils.deepCopy( self ) -- Create a new self instance
local Parent = STATEMACHINE:New(options)
setmetatable( FsmTask, Parent )
FsmTask.__index = FsmTask
FsmTask["onstatechange"] = Task.OnStateChange
FsmTask["onAssigned"] = Task.OnAssigned
FsmTask["onSuccess"] = Task.OnSuccess
FsmTask["onFailed"] = Task.OnFailed
FsmTask.Task = Task
FsmTask.TaskUnit = TaskUnit
return FsmTask
end
function STATEMACHINE_TASK:_call_handler( handler, params )
if handler then
return handler( self.Task, self.TaskUnit, unpack( params ) )
end
end

View File

@ -1,864 +0,0 @@
--- This module contains the TASK_BASE class.
--
-- 1) @{#TASK_BASE} class, extends @{Base#BASE}
-- ============================================
-- 1.1) The @{#TASK_BASE} class implements the methods for task orchestration within MOOSE.
-- ----------------------------------------------------------------------------------------
-- The class provides a couple of methods to:
--
-- * @{#TASK_BASE.AssignToGroup}():Assign a task to a group (of players).
-- * @{#TASK_BASE.AddProcess}():Add a @{Process} to a task.
-- * @{#TASK_BASE.RemoveProcesses}():Remove a running @{Process} from a running task.
-- * @{#TASK_BASE.AddStateMachine}():Add a @{StateMachine} to a task.
-- * @{#TASK_BASE.RemoveStateMachines}():Remove @{StateMachine}s from a task.
-- * @{#TASK_BASE.HasStateMachine}():Enquire if the task has a @{StateMachine}
-- * @{#TASK_BASE.AssignToUnit}(): Assign a task to a unit. (Needs to be implemented in the derived classes from @{#TASK_BASE}.
-- * @{#TASK_BASE.UnAssignFromUnit}(): Unassign the task from a unit.
--
-- 1.2) Set and enquire task status (beyond the task state machine processing).
-- ----------------------------------------------------------------------------
-- A task needs to implement as a minimum the following task states:
--
-- * **Success**: Expresses the successful execution and finalization of the task.
-- * **Failed**: Expresses the failure of a task.
-- * **Planned**: Expresses that the task is created, but not yet in execution and is not assigned yet.
-- * **Assigned**: Expresses that the task is assigned to a Group of players, and that the task is in execution mode.
--
-- A task may also implement the following task states:
--
-- * **Rejected**: Expresses that the task is rejected by a player, who was requested to accept the task.
-- * **Cancelled**: Expresses that the task is cancelled by HQ or through a logical situation where a cancellation of the task is required.
--
-- A task can implement more statusses than the ones outlined above. Please consult the documentation of the specific tasks to understand the different status modelled.
--
-- The status of tasks can be set by the methods **State** followed by the task status. An example is `StateAssigned()`.
-- The status of tasks can be enquired by the methods **IsState** followed by the task status name. An example is `if IsStateAssigned() then`.
--
-- 1.3) Add scoring when reaching a certain task status:
-- -----------------------------------------------------
-- Upon reaching a certain task status in a task, additional scoring can be given. If the Mission has a scoring system attached, the scores will be added to the mission scoring.
-- Use the method @{#TASK_BASE.AddScore}() to add scores when a status is reached.
--
-- 1.4) Task briefing:
-- -------------------
-- A task briefing can be given that is shown to the player when he is assigned to the task.
--
-- ===
--
-- ### Authors: FlightControl - Design and Programming
--
-- @module Task
--- The TASK_BASE class
-- @type TASK_BASE
-- @field Scheduler#SCHEDULER TaskScheduler
-- @field Mission#MISSION Mission
-- @field StateMachine#STATEMACHINE Fsm
-- @field Set#SET_GROUP SetGroup The Set of Groups assigned to the Task
-- @extends Base#BASE
TASK_BASE = {
ClassName = "TASK_BASE",
TaskScheduler = nil,
Processes = {},
Players = nil,
Scores = {},
Menu = {},
SetGroup = nil,
}
--- Instantiates a new TASK_BASE. Should never be used. Interface Class.
-- @param #TASK_BASE self
-- @param Mission#MISSION The mission wherein the Task is registered.
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task
-- @param #string TaskType The type of the Task
-- @param #string TaskCategory The category of the Task (A2G, A2A, Transport, ... )
-- @return #TASK_BASE self
function TASK_BASE:New( Mission, SetGroup, TaskName, TaskType, TaskCategory )
local self = BASE:Inherit( self, BASE:New() )
self:E( "New TASK " .. TaskName )
self.Processes = {}
self.Fsm = {}
self.Mission = Mission
self.SetGroup = SetGroup
self:SetCategory( TaskCategory )
self:SetType( TaskType )
self:SetName( TaskName )
self:SetID( Mission:GetNextTaskID( self ) ) -- The Mission orchestrates the task sequences ..
self.TaskBriefing = "You are assigned to the task: " .. self.TaskName .. "."
return self
end
--- Cleans all references of a TASK_BASE.
-- @param #TASK_BASE self
-- @return #nil
function TASK_BASE:CleanUp()
_EVENTDISPATCHER:OnPlayerLeaveRemove( self )
_EVENTDISPATCHER:OnDeadRemove( self )
_EVENTDISPATCHER:OnCrashRemove( self )
_EVENTDISPATCHER:OnPilotDeadRemove( self )
return nil
end
--- Assign the @{Task}to a @{Group}.
-- @param #TASK_BASE self
-- @param Group#GROUP TaskGroup
function TASK_BASE:AssignToGroup( TaskGroup )
self:F2( TaskGroup:GetName() )
local TaskGroupName = TaskGroup:GetName()
TaskGroup:SetState( TaskGroup, "Assigned", self )
self:RemoveMenuForGroup( TaskGroup )
self:SetAssignedMenuForGroup( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
if PlayerName ~= nil or PlayerName ~= "" then
self:AssignToUnit( TaskUnit )
end
end
end
--- Send the briefng message of the @{Task} to the assigned @{Group}s.
-- @param #TASK_BASE self
function TASK_BASE:SendBriefingToAssignedGroups()
self:F2()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if self:IsAssignedToGroup( TaskGroup ) then
TaskGroup:Message( self.TaskBriefing, 60 )
end
end
end
--- Assign the @{Task} from the @{Group}s.
-- @param #TASK_BASE self
function TASK_BASE:UnAssignFromGroups()
self:F2()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
TaskGroup:SetState( TaskGroup, "Assigned", nil )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
if PlayerName ~= nil or PlayerName ~= "" then
self:UnAssignFromUnit( TaskUnit )
end
end
end
end
--- Returns if the @{Task} is assigned to the Group.
-- @param #TASK_BASE self
-- @param Group#GROUP TaskGroup
-- @return #boolean
function TASK_BASE:IsAssignedToGroup( TaskGroup )
local TaskGroupName = TaskGroup:GetName()
if self:IsStateAssigned() then
if TaskGroup:GetState( TaskGroup, "Assigned" ) == self then
return true
end
end
return false
end
--- Assign the @{Task}to an alive @{Unit}.
-- @param #TASK_BASE self
-- @param Unit#UNIT TaskUnit
-- @return #TASK_BASE self
function TASK_BASE:AssignToUnit( TaskUnit )
self:F( TaskUnit:GetName() )
return nil
end
--- UnAssign the @{Task} from an alive @{Unit}.
-- @param #TASK_BASE self
-- @param Unit#UNIT TaskUnit
-- @return #TASK_BASE self
function TASK_BASE:UnAssignFromUnit( TaskUnitName )
self:F( TaskUnitName )
if self:HasStateMachine( TaskUnitName ) == true then
self:RemoveStateMachines( TaskUnitName )
self:RemoveProcesses( TaskUnitName )
end
return self
end
--- Set the menu options of the @{Task} to all the groups in the SetGroup.
-- @param #TASK_BASE self
-- @return #TASK_BASE self
function TASK_BASE:SetPlannedMenu()
local MenuText = self:GetPlannedMenuText()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if not self:IsAssignedToGroup( TaskGroup ) then
self:SetPlannedMenuForGroup( TaskGroup, MenuText )
end
end
end
--- Set the menu options of the @{Task} to all the groups in the SetGroup.
-- @param #TASK_BASE self
-- @return #TASK_BASE self
function TASK_BASE:SetAssignedMenu()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if self:IsAssignedToGroup( TaskGroup ) then
self:SetAssignedMenuForGroup( TaskGroup )
end
end
end
--- Remove the menu options of the @{Task} to all the groups in the SetGroup.
-- @param #TASK_BASE self
-- @return #TASK_BASE self
function TASK_BASE:RemoveMenu()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
self:RemoveMenuForGroup( TaskGroup )
end
end
--- Set the planned menu option of the @{Task}.
-- @param #TASK_BASE self
-- @param Group#GROUP TaskGroup
-- @param #string MenuText The menu text.
-- @return #TASK_BASE self
function TASK_BASE:SetPlannedMenuForGroup( TaskGroup, MenuText )
self:E( TaskGroup:GetName() )
local TaskMission = self.Mission:GetName()
local TaskCategory = self:GetCategory()
local TaskType = self:GetType()
local Mission = self.Mission
Mission.MenuMission = Mission.MenuMission or {}
local MenuMission = Mission.MenuMission
Mission.MenuCategory = Mission.MenuCategory or {}
local MenuCategory = Mission.MenuCategory
Mission.MenuType = Mission.MenuType or {}
local MenuType = Mission.MenuType
self.Menu = self.Menu or {}
local Menu = self.Menu
local TaskGroupName = TaskGroup:GetName()
MenuMission[TaskGroupName] = MenuMission[TaskGroupName] or MENU_GROUP:New( TaskGroup, TaskMission, nil )
MenuCategory[TaskGroupName] = MenuCategory[TaskGroupName] or {}
MenuCategory[TaskGroupName][TaskCategory] = MenuCategory[TaskGroupName][TaskCategory] or MENU_GROUP:New( TaskGroup, TaskCategory, MenuMission[TaskGroupName] )
MenuType[TaskGroupName] = MenuType[TaskGroupName] or {}
MenuType[TaskGroupName][TaskType] = MenuType[TaskGroupName][TaskType] or MENU_GROUP:New( TaskGroup, TaskType, MenuCategory[TaskGroupName][TaskCategory] )
if Menu[TaskGroupName] then
Menu[TaskGroupName]:Remove()
end
Menu[TaskGroupName] = MENU_GROUP_COMMAND:New( TaskGroup, MenuText, MenuType[TaskGroupName][TaskType], self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } )
return self
end
--- Set the assigned menu options of the @{Task}.
-- @param #TASK_BASE self
-- @param Group#GROUP TaskGroup
-- @return #TASK_BASE self
function TASK_BASE:SetAssignedMenuForGroup( TaskGroup )
self:E( TaskGroup:GetName() )
local TaskMission = self.Mission:GetName()
local Mission = self.Mission
Mission.MenuMission = Mission.MenuMission or {}
local MenuMission = Mission.MenuMission
self.MenuStatus = self.MenuStatus or {}
local MenuStatus = self.MenuStatus
self.MenuAbort = self.MenuAbort or {}
local MenuAbort = self.MenuAbort
local TaskGroupName = TaskGroup:GetName()
MenuMission[TaskGroupName] = MenuMission[TaskGroupName] or MENU_GROUP:New( TaskGroup, TaskMission, nil )
MenuStatus[TaskGroupName] = MENU_GROUP_COMMAND:New( TaskGroup, "Task Status", MenuMission[TaskGroupName], self.MenuTaskStatus, { self = self, TaskGroup = TaskGroup } )
MenuAbort[TaskGroupName] = MENU_GROUP_COMMAND:New( TaskGroup, "Abort Task", MenuMission[TaskGroupName], self.MenuTaskAbort, { self = self, TaskGroup = TaskGroup } )
return self
end
--- Remove the menu option of the @{Task} for a @{Group}.
-- @param #TASK_BASE self
-- @param Group#GROUP TaskGroup
-- @return #TASK_BASE self
function TASK_BASE:RemoveMenuForGroup( TaskGroup )
local TaskGroupName = TaskGroup:GetName()
local Mission = self.Mission
local MenuMission = Mission.MenuMission
local MenuCategory = Mission.MenuCategory
local MenuType = Mission.MenuType
local MenuStatus = self.MenuStatus
local MenuAbort = self.MenuAbort
local Menu = self.Menu
Menu = Menu or {}
if Menu[TaskGroupName] then
Menu[TaskGroupName]:Remove()
Menu[TaskGroupName] = nil
end
MenuType = MenuType or {}
if MenuType[TaskGroupName] then
for _, Menu in pairs( MenuType[TaskGroupName] ) do
Menu:Remove()
end
MenuType[TaskGroupName] = nil
end
MenuCategory = MenuCategory or {}
if MenuCategory[TaskGroupName] then
for _, Menu in pairs( MenuCategory[TaskGroupName] ) do
Menu:Remove()
end
MenuCategory[TaskGroupName] = nil
end
MenuStatus = MenuStatus or {}
if MenuStatus[TaskGroupName] then
MenuStatus[TaskGroupName]:Remove()
MenuStatus[TaskGroupName] = nil
end
MenuAbort = MenuAbort or {}
if MenuAbort[TaskGroupName] then
MenuAbort[TaskGroupName]:Remove()
MenuAbort[TaskGroupName] = nil
end
end
function TASK_BASE.MenuAssignToGroup( MenuParam )
local self = MenuParam.self
local TaskGroup = MenuParam.TaskGroup
self:AssignToGroup( TaskGroup )
end
function TASK_BASE.MenuTaskStatus( MenuParam )
local self = MenuParam.self
local TaskGroup = MenuParam.TaskGroup
--self:AssignToGroup( TaskGroup )
end
function TASK_BASE.MenuTaskAbort( MenuParam )
local self = MenuParam.self
local TaskGroup = MenuParam.TaskGroup
--self:AssignToGroup( TaskGroup )
end
--- Returns the @{Task} name.
-- @param #TASK_BASE self
-- @return #string TaskName
function TASK_BASE:GetTaskName()
return self.TaskName
end
--- Add Process to @{Task} with key @{Unit}.
-- @param #TASK_BASE self
-- @param Unit#UNIT TaskUnit
-- @return #TASK_BASE self
function TASK_BASE:AddProcess( TaskUnit, Process )
local TaskUnitName = TaskUnit:GetName()
self.Processes = self.Processes or {}
self.Processes[TaskUnitName] = self.Processes[TaskUnitName] or {}
self.Processes[TaskUnitName][#self.Processes[TaskUnitName]+1] = Process
return Process
end
--- Remove Processes from @{Task} with key @{Unit}
-- @param #TASK_BASE self
-- @param #string TaskUnitName
-- @return #TASK_BASE self
function TASK_BASE:RemoveProcesses( TaskUnitName )
for ProcessID, ProcessData in pairs( self.Processes[TaskUnitName] ) do
local Process = ProcessData -- Process#PROCESS
Process:StopEvents()
Process = nil
self.Processes[TaskUnitName][ProcessID] = nil
self:E( self.Processes[TaskUnitName][ProcessID] )
end
self.Processes[TaskUnitName] = nil
end
--- Fail processes from @{Task} with key @{Unit}
-- @param #TASK_BASE self
-- @param #string TaskUnitName
-- @return #TASK_BASE self
function TASK_BASE:FailProcesses( TaskUnitName )
for ProcessID, ProcessData in pairs( self.Processes[TaskUnitName] ) do
local Process = ProcessData -- Process#PROCESS
Process.Fsm:Fail()
end
end
--- Add a FiniteStateMachine to @{Task} with key @{Unit}
-- @param #TASK_BASE self
-- @param Unit#UNIT TaskUnit
-- @return #TASK_BASE self
function TASK_BASE:AddStateMachine( TaskUnit, Fsm )
local TaskUnitName = TaskUnit:GetName()
self.Fsm[TaskUnitName] = self.Fsm[TaskUnitName] or {}
self.Fsm[TaskUnitName][#self.Fsm[TaskUnitName]+1] = Fsm
return Fsm
end
--- Remove FiniteStateMachines from @{Task} with key @{Unit}
-- @param #TASK_BASE self
-- @param #string TaskUnitName
-- @return #TASK_BASE self
function TASK_BASE:RemoveStateMachines( TaskUnitName )
for _, Fsm in pairs( self.Fsm[TaskUnitName] ) do
Fsm = nil
self.Fsm[TaskUnitName][_] = nil
self:E( self.Fsm[TaskUnitName][_] )
end
self.Fsm[TaskUnitName] = nil
end
--- Checks if there is a FiniteStateMachine assigned to @{Unit} for @{Task}
-- @param #TASK_BASE self
-- @param #string TaskUnitName
-- @return #TASK_BASE self
function TASK_BASE:HasStateMachine( TaskUnitName )
self:F( { TaskUnitName, self.Fsm[TaskUnitName] ~= nil } )
return ( self.Fsm[TaskUnitName] ~= nil )
end
--- Register a potential new assignment for a new spawned @{Unit}.
-- Tasks only get assigned if there are players in it.
-- @param #TASK_BASE self
-- @param Event#EVENTDATA Event
-- @return #TASK_BASE self
function TASK_BASE:_EventAssignUnit( Event )
if Event.IniUnit then
self:F( Event )
local TaskUnit = Event.IniUnit
if TaskUnit:IsAlive() then
local TaskPlayerName = TaskUnit:GetPlayerName()
if TaskPlayerName ~= nil then
if not self:HasStateMachine( TaskUnit ) then
-- Check if the task was assigned to the group, if it was assigned to the group, assign to the unit just spawned and initiate the processes.
local TaskGroup = TaskUnit:GetGroup()
if self:IsAssignedToGroup( TaskGroup ) then
self:AssignToUnit( TaskUnit )
end
end
end
end
end
return nil
end
--- Catches the "player leave unit" event for a @{Unit} ....
-- When a player is an air unit, and leaves the unit:
--
-- * and he is not at an airbase runway on the ground, he will fail its task.
-- * and he is on an airbase and on the ground, the process for him will just continue to work, he can switch airplanes, and take-off again.
-- This is important to model the change from plane types for a player during mission assignment.
-- @param #TASK_BASE self
-- @param Event#EVENTDATA Event
-- @return #TASK_BASE self
function TASK_BASE:_EventPlayerLeaveUnit( Event )
self:F( Event )
if Event.IniUnit then
local TaskUnit = Event.IniUnit
local TaskUnitName = Event.IniUnitName
-- Check if for this unit in the task there is a process ongoing.
if self:HasStateMachine( TaskUnitName ) then
if TaskUnit:IsAir() then
if TaskUnit:IsAboveRunway() then
-- do nothing
else
self:E( "IsNotAboveRunway" )
-- Player left airplane during an assigned task and was not at an airbase.
self:FailProcesses( TaskUnitName )
self:UnAssignFromUnit( TaskUnitName )
end
end
end
end
return nil
end
--- UnAssigns a @{Unit} that is left by a player, crashed, dead, ....
-- There are only assignments if there are players in it.
-- @param #TASK_BASE self
-- @param Event#EVENTDATA Event
-- @return #TASK_BASE self
function TASK_BASE:_EventDead( Event )
self:F( Event )
if Event.IniUnit then
local TaskUnit = Event.IniUnit
local TaskUnitName = Event.IniUnitName
-- Check if for this unit in the task there is a process ongoing.
if self:HasStateMachine( TaskUnitName ) then
self:FailProcesses( TaskUnitName )
self:UnAssignFromUnit( TaskUnitName )
end
local TaskGroup = Event.IniUnit:GetGroup()
TaskGroup:SetState( TaskGroup, "Assigned", nil )
end
return nil
end
--- Gets the Scoring of the task
-- @param #TASK_BASE self
-- @return Scoring#SCORING Scoring
function TASK_BASE:GetScoring()
return self.Mission:GetScoring()
end
--- Gets the Task Index, which is a combination of the Task category, the Task type, the Task name.
-- @param #TASK_BASE self
-- @return #string The Task ID
function TASK_BASE:GetTaskIndex()
local TaskCategory = self:GetCategory()
local TaskType = self:GetType()
local TaskName = self:GetName()
return TaskCategory .. "." ..TaskType .. "." .. TaskName
end
--- Sets the Name of the Task
-- @param #TASK_BASE self
-- @param #string TaskName
function TASK_BASE:SetName( TaskName )
self.TaskName = TaskName
end
--- Gets the Name of the Task
-- @param #TASK_BASE self
-- @return #string The Task Name
function TASK_BASE:GetName()
return self.TaskName
end
--- Sets the Type of the Task
-- @param #TASK_BASE self
-- @param #string TaskType
function TASK_BASE:SetType( TaskType )
self.TaskType = TaskType
end
--- Gets the Type of the Task
-- @param #TASK_BASE self
-- @return #string TaskType
function TASK_BASE:GetType()
return self.TaskType
end
--- Sets the Category of the Task
-- @param #TASK_BASE self
-- @param #string TaskCategory
function TASK_BASE:SetCategory( TaskCategory )
self.TaskCategory = TaskCategory
end
--- Gets the Category of the Task
-- @param #TASK_BASE self
-- @return #string TaskCategory
function TASK_BASE:GetCategory()
return self.TaskCategory
end
--- Sets the ID of the Task
-- @param #TASK_BASE self
-- @param #string TaskID
function TASK_BASE:SetID( TaskID )
self.TaskID = TaskID
end
--- Gets the ID of the Task
-- @param #TASK_BASE self
-- @return #string TaskID
function TASK_BASE:GetID()
return self.TaskID
end
--- Sets a @{Task} to status **Success**.
-- @param #TASK_BASE self
function TASK_BASE:StateSuccess()
self:SetState( self, "State", "Success" )
return self
end
--- Is the @{Task} status **Success**.
-- @param #TASK_BASE self
function TASK_BASE:IsStateSuccess()
return self:GetStateString() == "Success"
end
--- Sets a @{Task} to status **Failed**.
-- @param #TASK_BASE self
function TASK_BASE:StateFailed()
self:SetState( self, "State", "Failed" )
return self
end
--- Is the @{Task} status **Failed**.
-- @param #TASK_BASE self
function TASK_BASE:IsStateFailed()
return self:GetStateString() == "Failed"
end
--- Sets a @{Task} to status **Planned**.
-- @param #TASK_BASE self
function TASK_BASE:StatePlanned()
self:SetState( self, "State", "Planned" )
return self
end
--- Is the @{Task} status **Planned**.
-- @param #TASK_BASE self
function TASK_BASE:IsStatePlanned()
return self:GetStateString() == "Planned"
end
--- Sets a @{Task} to status **Assigned**.
-- @param #TASK_BASE self
function TASK_BASE:StateAssigned()
self:SetState( self, "State", "Assigned" )
return self
end
--- Is the @{Task} status **Assigned**.
-- @param #TASK_BASE self
function TASK_BASE:IsStateAssigned()
return self:GetStateString() == "Assigned"
end
--- Sets a @{Task} to status **Hold**.
-- @param #TASK_BASE self
function TASK_BASE:StateHold()
self:SetState( self, "State", "Hold" )
return self
end
--- Is the @{Task} status **Hold**.
-- @param #TASK_BASE self
function TASK_BASE:IsStateHold()
return self:GetStateString() == "Hold"
end
--- Sets a @{Task} to status **Replanned**.
-- @param #TASK_BASE self
function TASK_BASE:StateReplanned()
self:SetState( self, "State", "Replanned" )
return self
end
--- Is the @{Task} status **Replanned**.
-- @param #TASK_BASE self
function TASK_BASE:IsStateReplanned()
return self:GetStateString() == "Replanned"
end
--- Gets the @{Task} status.
-- @param #TASK_BASE self
function TASK_BASE:GetStateString()
return self:GetState( self, "State" )
end
--- Sets a @{Task} briefing.
-- @param #TASK_BASE self
-- @param #string TaskBriefing
-- @return #TASK_BASE self
function TASK_BASE:SetBriefing( TaskBriefing )
self.TaskBriefing = TaskBriefing
return self
end
--- Adds a score for the TASK to be achieved.
-- @param #TASK_BASE self
-- @param #string TaskStatus is the status of the TASK when the score needs to be given.
-- @param #string ScoreText is a text describing the score that is given according the status.
-- @param #number Score is a number providing the score of the status.
-- @return #TASK_BASE self
function TASK_BASE:AddScore( TaskStatus, ScoreText, Score )
self:F2( { TaskStatus, ScoreText, Score } )
self.Scores[TaskStatus] = self.Scores[TaskStatus] or {}
self.Scores[TaskStatus].ScoreText = ScoreText
self.Scores[TaskStatus].Score = Score
return self
end
--- StateMachine callback function for a TASK
-- @param #TASK_BASE self
-- @param Unit#UNIT TaskUnit
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function TASK_BASE:OnAssigned( TaskUnit, Fsm, Event, From, To )
self:E("Assigned")
local TaskGroup = TaskUnit:GetGroup()
TaskGroup:Message( self.TaskBriefing, 20 )
self:RemoveMenuForGroup( TaskGroup )
self:SetAssignedMenuForGroup( TaskGroup )
end
--- StateMachine callback function for a TASK
-- @param #TASK_BASE self
-- @param Unit#UNIT TaskUnit
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function TASK_BASE:OnSuccess( TaskUnit, Fsm, Event, From, To )
self:E("Success")
self:UnAssignFromGroups()
local TaskGroup = TaskUnit:GetGroup()
self.Mission:SetPlannedMenu()
self:StateSuccess()
-- The task has become successful, the event catchers can be cleaned.
self:CleanUp()
end
--- StateMachine callback function for a TASK
-- @param #TASK_BASE self
-- @param Unit#UNIT TaskUnit
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function TASK_BASE:OnFailed( TaskUnit, Fsm, Event, From, To )
self:E( { "Failed for unit ", TaskUnit:GetName(), TaskUnit:GetPlayerName() } )
-- A task cannot be "failed", so a task will always be there waiting for players to join.
-- When the player leaves its unit, we will need to check whether he was on the ground or not at an airbase.
-- When the player crashes, we will need to check whether in the group there are other players still active. It not, we reset the task from Assigned to Planned, otherwise, we just leave as Assigned.
self:UnAssignFromGroups()
self:StatePlanned()
end
--- StateMachine callback function for a TASK
-- @param #TASK_BASE self
-- @param Unit#UNIT TaskUnit
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function TASK_BASE:OnStateChange( TaskUnit, Fsm, Event, From, To )
if self:IsTrace() then
MESSAGE:New( "Task " .. self.TaskName .. " : " .. Event .. " changed to state " .. To, 15 ):ToAll()
end
self:E( { Event, From, To } )
self:SetState( self, "State", To )
if self.Scores[To] then
local Scoring = self:GetScoring()
if Scoring then
Scoring:_AddMissionScore( self.Mission, self.Scores[To].ScoreText, self.Scores[To].Score )
end
end
end
--- @param #TASK_BASE self
function TASK_BASE:_Schedule()
self:F2()
self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 )
return self
end
--- @param #TASK_BASE self
function TASK_BASE._Scheduler()
self:F2()
return true
end

View File

@ -1,150 +0,0 @@
--- This module contains the TASK_A2G classes.
--
-- 1) @{#TASK_A2G} class, extends @{Task#TASK_BASE}
-- =================================================
-- The @{#TASK_A2G} class defines a CAS or BAI task of a @{Set} of Target Units,
-- located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}.
-- The TASK_A2G is implemented using a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses:
--
-- * **None**: Start of the process
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task.
-- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Route#PROCESS_ROUTE} is started to route the active Units in the Group to the attack zone.
-- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task.
-- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
-- ===
--
-- ### Authors: FlightControl - Design and Programming
--
-- @module Task_A2G
do -- TASK_A2G
--- The TASK_A2G class
-- @type TASK_A2G
-- @extends Task#TASK_BASE
TASK_A2G = {
ClassName = "TASK_A2G",
}
--- Instantiates a new TASK_A2G.
-- @param #TASK_A2G self
-- @param 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 #string TaskType BAI or CAS
-- @param Set#SET_UNIT UnitSetTargets
-- @param Zone#ZONE_BASE TargetZone
-- @return #TASK_A2G self
function TASK_A2G:New( Mission, SetGroup, TaskName, TaskType, TargetSetUnit, TargetZone, FACUnit )
local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, TaskType, "A2G" ) )
self:F()
self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone
self.FACUnit = FACUnit
_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
_EVENTDISPATCHER:OnDead( self._EventDead, self )
_EVENTDISPATCHER:OnCrash( self._EventDead, self )
_EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
return self
end
--- Removes a TASK_A2G.
-- @param #TASK_A2G self
-- @return #nil
function TASK_A2G:CleanUp()
self:GetParent( self ):CleanUp()
return nil
end
--- Assign the @{Task} to a @{Unit}.
-- @param #TASK_A2G self
-- @param Unit#UNIT TaskUnit
-- @return #TASK_A2G self
function TASK_A2G:AssignToUnit( TaskUnit )
self:F( TaskUnit:GetName() )
local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) )
local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) )
local ProcessDestroy = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, self.TaskType, TaskUnit, self.TargetSetUnit ) )
local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) )
local ProcessJTAC = self:AddProcess( TaskUnit, PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) )
local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, {
initial = 'None',
events = {
{ name = 'Next', from = 'None', to = 'Planned' },
{ name = 'Next', from = 'Planned', to = 'Assigned' },
{ name = 'Reject', from = 'Planned', to = 'Rejected' },
{ name = 'Next', from = 'Assigned', to = 'Success' },
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
{ name = 'Fail', from = 'Arrived', to = 'Failed' }
},
callbacks = {
onNext = self.OnNext,
onRemove = self.OnRemove,
},
subs = {
Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } },
Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' },
Destroy = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessDestroy.Fsm, event = 'Start', returnevents = { 'Next' } },
Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', },
JTAC = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessJTAC.Fsm, event = 'Start', },
}
} ) )
ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 )
ProcessDestroy:AddScore( "Destroy", "destroyed a ground unit", 25 )
ProcessDestroy:AddScore( "Failed", "failed to destroy a ground unit", -100 )
Process:Next()
return self
end
--- StateMachine callback function for a TASK
-- @param #TASK_A2G self
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function TASK_A2G:OnNext( Fsm, Event, From, To, Event )
self:SetState( self, "State", To )
end
--- @param #TASK_A2G self
function TASK_A2G:GetPlannedMenuText()
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end
--- @param #TASK_A2G self
function TASK_A2G:_Schedule()
self:F2()
self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 )
return self
end
--- @param #TASK_A2G self
function TASK_A2G._Scheduler()
self:F2()
return true
end
end

View File

@ -1,146 +0,0 @@
--- This module contains the TASK_SEAD classes.
--
-- 1) @{#TASK_SEAD} class, extends @{Task#TASK_BASE}
-- =================================================
-- The @{#TASK_SEAD} class defines a SEAD task for a @{Set} of Target Units, located at a Target Zone,
-- based on the tasking capabilities defined in @{Task#TASK_BASE}.
-- The TASK_SEAD is implemented using a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses:
--
-- * **None**: Start of the process
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task.
-- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Route#PROCESS_ROUTE} is started to route the active Units in the Group to the attack zone.
-- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task.
-- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
-- ===
--
-- ### Authors: FlightControl - Design and Programming
--
-- @module Task_SEAD
do -- TASK_SEAD
--- The TASK_SEAD class
-- @type TASK_SEAD
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Task#TASK_BASE
TASK_SEAD = {
ClassName = "TASK_SEAD",
}
--- Instantiates a new TASK_SEAD.
-- @param #TASK_SEAD self
-- @param Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets
-- @param Zone#ZONE_BASE TargetZone
-- @return #TASK_SEAD self
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone )
local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "SEAD", "A2G" ) )
self:F()
self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone
_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
_EVENTDISPATCHER:OnDead( self._EventDead, self )
_EVENTDISPATCHER:OnCrash( self._EventDead, self )
_EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
return self
end
--- Removes a TASK_SEAD.
-- @param #TASK_SEAD self
-- @return #nil
function TASK_SEAD:CleanUp()
self:GetParent(self):CleanUp()
return nil
end
--- Assign the @{Task} to a @{Unit}.
-- @param #TASK_SEAD self
-- @param Unit#UNIT TaskUnit
-- @return #TASK_SEAD self
function TASK_SEAD:AssignToUnit( TaskUnit )
self:F( TaskUnit:GetName() )
local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) )
local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) )
local ProcessSEAD = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, "SEAD", TaskUnit, self.TargetSetUnit ) )
local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) )
local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, {
initial = 'None',
events = {
{ name = 'Next', from = 'None', to = 'Planned' },
{ name = 'Next', from = 'Planned', to = 'Assigned' },
{ name = 'Reject', from = 'Planned', to = 'Rejected' },
{ name = 'Next', from = 'Assigned', to = 'Success' },
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
{ name = 'Fail', from = 'Arrived', to = 'Failed' }
},
callbacks = {
onNext = self.OnNext,
onRemove = self.OnRemove,
},
subs = {
Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } },
Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' },
Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSEAD.Fsm, event = 'Start', returnevents = { 'Next' } },
Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', }
}
} ) )
ProcessRoute:AddScore( "Failed", "failed to destroy a radar", -100 )
ProcessSEAD:AddScore( "Destroy", "destroyed a radar", 25 )
ProcessSEAD:AddScore( "Failed", "failed to destroy a radar", -100 )
self:AddScore( "Success", "Destroyed all target radars", 250 )
Process:Next()
return self
end
--- StateMachine callback function for a TASK
-- @param #TASK_SEAD self
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Event#EVENTDATA Event
function TASK_SEAD:OnNext( Fsm, Event, From, To )
self:SetState( self, "State", To )
end
--- @param #TASK_SEAD self
function TASK_SEAD:GetPlannedMenuText()
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end
--- @param #TASK_SEAD self
function TASK_SEAD:_Schedule()
self:F2()
self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 )
return self
end
--- @param #TASK_SEAD self
function TASK_SEAD._Scheduler()
self:F2()
return true
end
end

View File

@ -0,0 +1,268 @@
--- A COMMANDCENTER is the owner of multiple missions within MOOSE.
-- A COMMANDCENTER governs multiple missions, the tasking and the reporting.
-- @module CommandCenter
--- The REPORT class
-- @type REPORT
-- @extends Core.Base#BASE
REPORT = {
ClassName = "REPORT",
}
--- Create a new REPORT.
-- @param #REPORT self
-- @param #string Title
-- @return #REPORT
function REPORT:New( Title )
local self = BASE:Inherit( self, BASE:New() )
self.Report = {}
self.Report[#self.Report+1] = Title
return self
end
--- Add a new line to a REPORT.
-- @param #REPORT self
-- @param #string Text
-- @return #REPORT
function REPORT:Add( Text )
self.Report[#self.Report+1] = Text
return self.Report[#self.Report+1]
end
function REPORT:Text()
return table.concat( self.Report, "\n" )
end
--- The COMMANDCENTER class
-- @type COMMANDCENTER
-- @field Wrapper.Group#GROUP HQ
-- @field Dcs.DCSCoalitionWrapper.Object#coalition CommandCenterCoalition
-- @list<Tasking.Mission#MISSION> Missions
-- @extends Core.Base#BASE
COMMANDCENTER = {
ClassName = "COMMANDCENTER",
CommandCenterName = "",
CommandCenterCoalition = nil,
CommandCenterPositionable = nil,
Name = "",
}
--- The constructor takes an IDENTIFIABLE as the HQ command center.
-- @param #COMMANDCENTER self
-- @param Wrapper.Positionable#POSITIONABLE CommandCenterPositionable
-- @param #string CommandCenterName
-- @return #COMMANDCENTER
function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
local self = BASE:Inherit( self, BASE:New() )
self.CommandCenterPositionable = CommandCenterPositionable
self.CommandCenterName = CommandCenterName or CommandCenterPositionable:GetName()
self.CommandCenterCoalition = CommandCenterPositionable:GetCoalition()
self.Missions = setmetatable( {}, { __mode = "v" } )
self:EventOnBirth(
--- @param #COMMANDCENTER self
--- @param Core.Event#EVENTDATA EventData
function( self, EventData )
self:E( { EventData } )
local EventGroup = GROUP:Find( EventData.IniDCSGroup )
if EventGroup and self:HasGroup( EventGroup ) then
local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu )
local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Summary Report", MenuReporting, self.ReportSummary, self, EventGroup )
local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Details Report", MenuReporting, self.ReportDetails, self, EventGroup )
self:ReportSummary( EventGroup )
end
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:JoinUnit( PlayerUnit )
Mission:ReportDetails()
end
end
)
-- When a player enters a client or a unit, the CommandCenter will check for each Mission and each Task in the Mission if the player has things to do.
-- For these elements, it will=
-- - Set the correct menu.
-- - Assign the PlayerUnit to the Task if required.
-- - Send a message to the other players in the group that this player has joined.
self:EventOnPlayerEnterUnit(
--- @param #COMMANDCENTER self
-- @param Core.Event#EVENTDATA EventData
function( self, EventData )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:JoinUnit( PlayerUnit )
Mission:ReportDetails()
end
end
)
-- Handle when a player leaves a slot and goes back to spectators ...
-- The PlayerUnit will be UnAssigned from the Task.
-- When there is no Unit left running the Task, the Task goes into Abort...
self:EventOnPlayerLeaveUnit(
--- @param #TASK self
-- @param Core.Event#EVENTDATA EventData
function( self, EventData )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
Mission:AbortUnit( PlayerUnit )
end
end
)
-- Handle when a player leaves a slot and goes back to spectators ...
-- The PlayerUnit will be UnAssigned from the Task.
-- When there is no Unit left running the Task, the Task goes into Abort...
self:EventOnCrash(
--- @param #TASK self
-- @param Core.Event#EVENTDATA EventData
function( self, EventData )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
Mission:CrashUnit( PlayerUnit )
end
end
)
return self
end
--- Gets the name of the HQ command center.
-- @param #COMMANDCENTER self
-- @return #string
function COMMANDCENTER:GetName()
return self.HQName
end
--- Gets the POSITIONABLE of the HQ command center.
-- @param #COMMANDCENTER self
-- @return Wrapper.Positionable#POSITIONABLE
function COMMANDCENTER:GetPositionable()
return self.CommandCenterPositionable
end
--- Get the Missions governed by the HQ command center.
-- @param #COMMANDCENTER self
-- @return #list<Tasking.Mission#MISSION>
function COMMANDCENTER:GetMissions()
return self.Missions
end
--- Add a MISSION to be governed by the HQ command center.
-- @param #COMMANDCENTER self
-- @param Tasking.Mission#MISSION Mission
-- @return Tasking.Mission#MISSION
function COMMANDCENTER:AddMission( Mission )
self.Missions[Mission] = Mission
return Mission
end
--- Removes a MISSION to be governed by the HQ command center.
-- The given Mission is not nilified.
-- @param #COMMANDCENTER self
-- @param Tasking.Mission#MISSION Mission
-- @return Tasking.Mission#MISSION
function COMMANDCENTER:RemoveMission( Mission )
self.Missions[Mission] = nil
return Mission
end
--- Sets the menu structure of the Missions governed by the HQ command center.
-- @param #COMMANDCENTER self
function COMMANDCENTER:SetMenu()
self:F()
self.CommandCenterMenu = self.CommandCenterMenu or MENU_COALITION:New( self.CommandCenterCoalition, "HQ" )
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:SetMenu()
end
end
--- Checks of the COMMANDCENTER has a GROUP.
-- @param #COMMANDCENTER self
-- @param Wrapper.Group#GROUP
-- @return #boolean
function COMMANDCENTER:HasGroup( MissionGroup )
local Has = false
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
if Mission:HasGroup( MissionGroup ) then
Has = true
break
end
end
return Has
end
--- Send a CC message to a GROUP.
-- @param #COMMANDCENTER self
function COMMANDCENTER:MessageToGroup( Message, TaskGroup )
self:GetPositionable():MessageToGroup( Message , 20, TaskGroup )
end
--- Send a CC message to the coalition of the CC.
-- @param #COMMANDCENTER self
function COMMANDCENTER:MessageToCoalition( Message )
local CCCoalition = self:GetPositionable():GetCoalition()
self:GetPositionable():MessageToBlue( Message , 20, CCCoalition )
end
--- Report the status of all MISSIONs to a GROUP.
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
-- @param #COMMANDCENTER self
function COMMANDCENTER:ReportSummary( ReportGroup )
self:E( ReportGroup )
local Report = REPORT:New()
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
Report:Add( " - " .. Mission:ReportOverview() )
end
self:GetPositionable():MessageToGroup( Report:Text(), 30, ReportGroup )
end
--- Report the status of a Task to a Group.
-- Report the details of a Mission, listing the Mission, and all the Task details.
-- @param #COMMANDCENTER self
function COMMANDCENTER:ReportDetails( ReportGroup, Task )
self:E( ReportGroup )
local Report = REPORT:New()
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
Report:Add( " - " .. Mission:ReportDetails() )
end
self:GetPositionable():MessageToGroup( Report:Text(), 30, ReportGroup )
end

View File

@ -1,38 +1,38 @@
--- This module contains the DETECTION_MANAGER class and derived classes.
-- This module contains the DETECTION_MANAGER class and derived classes.
--
-- ===
--
-- 1) @{DetectionManager#DETECTION_MANAGER} class, extends @{Base#BASE}
-- 1) @{Tasking.DetectionManager#DETECTION_MANAGER} class, extends @{Core.Base#BASE}
-- ====================================================================
-- The @{DetectionManager#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
-- The @{Tasking.DetectionManager#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
-- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour.
--
-- 1.1) DETECTION_MANAGER constructor:
-- -----------------------------------
-- * @{DetectionManager#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
-- * @{Tasking.DetectionManager#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
--
-- 1.2) DETECTION_MANAGER reporting:
-- ---------------------------------
-- Derived DETECTION_MANAGER classes will reports detected units using the method @{DetectionManager#DETECTION_MANAGER.ReportDetected}(). This method implements polymorphic behaviour.
-- Derived DETECTION_MANAGER classes will reports detected units using the method @{Tasking.DetectionManager#DETECTION_MANAGER.ReportDetected}(). This method implements polymorphic behaviour.
--
-- The time interval in seconds of the reporting can be changed using the methods @{DetectionManager#DETECTION_MANAGER.SetReportInterval}().
-- To control how long a reporting message is displayed, use @{DetectionManager#DETECTION_MANAGER.SetReportDisplayTime}().
-- Derived classes need to implement the method @{DetectionManager#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report.
-- The time interval in seconds of the reporting can be changed using the methods @{Tasking.DetectionManager#DETECTION_MANAGER.SetReportInterval}().
-- To control how long a reporting message is displayed, use @{Tasking.DetectionManager#DETECTION_MANAGER.SetReportDisplayTime}().
-- Derived classes need to implement the method @{Tasking.DetectionManager#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report.
--
-- Reporting can be started and stopped using the methods @{DetectionManager#DETECTION_MANAGER.StartReporting}() and @{DetectionManager#DETECTION_MANAGER.StopReporting}() respectively.
-- If an ad-hoc report is requested, use the method @{DetectionManager#DETECTION_MANAGER#ReportNow}().
-- Reporting can be started and stopped using the methods @{Tasking.DetectionManager#DETECTION_MANAGER.StartReporting}() and @{Tasking.DetectionManager#DETECTION_MANAGER.StopReporting}() respectively.
-- If an ad-hoc report is requested, use the method @{Tasking.DetectionManager#DETECTION_MANAGER#ReportNow}().
--
-- The default reporting interval is every 60 seconds. The reporting messages are displayed 15 seconds.
--
-- ===
--
-- 2) @{DetectionManager#DETECTION_REPORTING} class, extends @{DetectionManager#DETECTION_MANAGER}
-- 2) @{Tasking.DetectionManager#DETECTION_REPORTING} class, extends @{Tasking.DetectionManager#DETECTION_MANAGER}
-- =========================================================================================
-- The @{DetectionManager#DETECTION_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{DetectionManager#DETECTION_MANAGER} class.
-- The @{Tasking.DetectionManager#DETECTION_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{Tasking.DetectionManager#DETECTION_MANAGER} class.
--
-- 2.1) DETECTION_REPORTING constructor:
-- -------------------------------
-- The @{DetectionManager#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
-- The @{Tasking.DetectionManager#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
--
-- ===
--
@ -64,7 +64,7 @@ do -- DETECTION MANAGER
--- DETECTION_MANAGER class.
-- @type DETECTION_MANAGER
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
-- @field Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @extends Base#BASE
DETECTION_MANAGER = {
ClassName = "DETECTION_MANAGER",
@ -75,12 +75,12 @@ do -- DETECTION MANAGER
--- FAC constructor.
-- @param #DETECTION_MANAGER self
-- @param Set#SET_GROUP SetGroup
-- @param Detection#DETECTION_BASE Detection
-- @param Functional.Detection#DETECTION_BASE Detection
-- @return #DETECTION_MANAGER self
function DETECTION_MANAGER:New( SetGroup, Detection )
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() ) -- Detection#DETECTION_MANAGER
local self = BASE:Inherit( self, BASE:New() ) -- Functional.Detection#DETECTION_MANAGER
self.SetGroup = SetGroup
self.Detection = Detection
@ -125,7 +125,7 @@ do -- DETECTION MANAGER
--- Reports the detected items to the @{Set#SET_GROUP}.
-- @param #DETECTION_MANAGER self
-- @param Detection#DETECTION_BASE Detection
-- @param Functional.Detection#DETECTION_BASE Detection
-- @return #DETECTION_MANAGER self
function DETECTION_MANAGER:ReportDetected( Detection )
self:F2()
@ -148,7 +148,7 @@ do -- DETECTION MANAGER
return self
end
--- Report the detected @{Unit#UNIT}s detected within the @{Detection#DETECTION_BASE} object to the @{Set#SET_GROUP}s.
--- Report the detected @{Wrapper.Unit#UNIT}s detected within the @{Functional.Detection#DETECTION_BASE} object to the @{Set#SET_GROUP}s.
-- @param #DETECTION_MANAGER self
function DETECTION_MANAGER:_FacScheduler( SchedulerName )
self:F2( { SchedulerName } )
@ -156,7 +156,7 @@ do -- DETECTION MANAGER
return self:ProcessDetected( self.Detection )
-- self.SetGroup:ForEachGroup(
-- --- @param Group#GROUP Group
-- --- @param Wrapper.Group#GROUP Group
-- function( Group )
-- if Group:IsAlive() then
-- return self:ProcessDetected( self.Detection )
@ -175,7 +175,7 @@ do -- DETECTION_REPORTING
--- DETECTION_REPORTING class.
-- @type DETECTION_REPORTING
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
-- @field Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @extends #DETECTION_MANAGER
DETECTION_REPORTING = {
ClassName = "DETECTION_REPORTING",
@ -185,7 +185,7 @@ do -- DETECTION_REPORTING
--- DETECTION_REPORTING constructor.
-- @param #DETECTION_REPORTING self
-- @param Set#SET_GROUP SetGroup
-- @param Detection#DETECTION_AREAS Detection
-- @param Functional.Detection#DETECTION_AREAS Detection
-- @return #DETECTION_REPORTING self
function DETECTION_REPORTING:New( SetGroup, Detection )
@ -198,7 +198,7 @@ do -- DETECTION_REPORTING
--- Creates a string of the detected items in a @{Detection}.
-- @param #DETECTION_MANAGER self
-- @param Set#SET_UNIT DetectedSet The detected Set created by the @{Detection#DETECTION_BASE} object.
-- @param Set#SET_UNIT DetectedSet The detected Set created by the @{Functional.Detection#DETECTION_BASE} object.
-- @return #DETECTION_MANAGER self
function DETECTION_REPORTING:GetDetectedItemsText( DetectedSet )
self:F2()
@ -207,7 +207,7 @@ do -- DETECTION_REPORTING
local UnitTypes = {}
for DetectedUnitID, DetectedUnitData in pairs( DetectedSet:GetSet() ) do
local DetectedUnit = DetectedUnitData -- Unit#UNIT
local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT
if DetectedUnit:IsAlive() then
local UnitType = DetectedUnit:GetTypeName()
@ -230,8 +230,8 @@ do -- DETECTION_REPORTING
--- Reports the detected items to the @{Set#SET_GROUP}.
-- @param #DETECTION_REPORTING self
-- @param Group#GROUP Group The @{Group} object to where the report needs to go.
-- @param Detection#DETECTION_AREAS Detection The detection created by the @{Detection#DETECTION_BASE} object.
-- @param Wrapper.Group#GROUP Group The @{Group} object to where the report needs to go.
-- @param Functional.Detection#DETECTION_AREAS Detection The detection created by the @{Functional.Detection#DETECTION_BASE} object.
-- @return #boolean Return true if you want the reporting to continue... false will cancel the reporting loop.
function DETECTION_REPORTING:ProcessDetected( Group, Detection )
self:F2( Group )
@ -239,7 +239,7 @@ do -- DETECTION_REPORTING
self:E( Group )
local DetectedMsg = {}
for DetectedAreaID, DetectedAreaData in pairs( Detection:GetDetectedAreas() ) do
local DetectedArea = DetectedAreaData -- Detection#DETECTION_AREAS.DetectedArea
local DetectedArea = DetectedAreaData -- Functional.Detection#DETECTION_AREAS.DetectedArea
DetectedMsg[#DetectedMsg+1] = " - Group #" .. DetectedAreaID .. ": " .. self:GetDetectedItemsText( DetectedArea.Set )
end
local FACGroup = Detection:GetDetectionGroups()
@ -255,10 +255,10 @@ do -- DETECTION_DISPATCHER
--- DETECTION_DISPATCHER class.
-- @type DETECTION_DISPATCHER
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
-- @field Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @field Mission#MISSION Mission
-- @field Group#GROUP CommandCenter
-- @extends DetectionManager#DETECTION_MANAGER
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @field Tasking.Mission#MISSION Mission
-- @field Wrapper.Group#GROUP CommandCenter
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
DETECTION_DISPATCHER = {
ClassName = "DETECTION_DISPATCHER",
Mission = nil,
@ -270,7 +270,7 @@ do -- DETECTION_DISPATCHER
--- DETECTION_DISPATCHER constructor.
-- @param #DETECTION_DISPATCHER self
-- @param Set#SET_GROUP SetGroup
-- @param Detection#DETECTION_BASE Detection
-- @param Functional.Detection#DETECTION_BASE Detection
-- @return #DETECTION_DISPATCHER self
function DETECTION_DISPATCHER:New( Mission, CommandCenter, SetGroup, Detection )
@ -288,7 +288,7 @@ do -- DETECTION_DISPATCHER
--- Creates a SEAD task when there are targets for it.
-- @param #DETECTION_DISPATCHER self
-- @param Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
-- @return #nil If there are no targets to be set.
function DETECTION_DISPATCHER:EvaluateSEAD( DetectedArea )
@ -316,8 +316,8 @@ do -- DETECTION_DISPATCHER
--- Creates a CAS task when there are targets for it.
-- @param #DETECTION_DISPATCHER self
-- @param Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Task#TASK_BASE
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Tasking.Task#TASK
function DETECTION_DISPATCHER:EvaluateCAS( DetectedArea )
self:F( { DetectedArea.AreaID } )
@ -344,8 +344,8 @@ do -- DETECTION_DISPATCHER
--- Creates a BAI task when there are targets for it.
-- @param #DETECTION_DISPATCHER self
-- @param Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Task#TASK_BASE
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Tasking.Task#TASK
function DETECTION_DISPATCHER:EvaluateBAI( DetectedArea, FriendlyCoalition )
self:F( { DetectedArea.AreaID } )
@ -373,14 +373,15 @@ do -- DETECTION_DISPATCHER
--- Evaluates the removal of the Task from the Mission.
-- Can only occur when the DetectedArea is Changed AND the state of the Task is "Planned".
-- @param #DETECTION_DISPATCHER self
-- @param Mission#MISSION Mission
-- @param Task#TASK_BASE Task
-- @param Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Task#TASK_BASE
-- @param Tasking.Mission#MISSION Mission
-- @param Tasking.Task#TASK Task
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
-- @return Tasking.Task#TASK
function DETECTION_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedArea )
if Task then
if Task:IsStatePlanned() and DetectedArea.Changed == true then
self:E( "Removing Tasking: " .. Task:GetTaskName() )
Mission:RemoveTaskMenu( Task )
Task = Mission:RemoveTask( Task )
end
@ -392,7 +393,7 @@ do -- DETECTION_DISPATCHER
--- Assigns tasks in relation to the detected items to the @{Set#SET_GROUP}.
-- @param #DETECTION_DISPATCHER self
-- @param Detection#DETECTION_AREAS Detection The detection created by the @{Detection#DETECTION_AREAS} object.
-- @param Functional.Detection#DETECTION_AREAS Detection The detection created by the @{Functional.Detection#DETECTION_AREAS} object.
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
function DETECTION_DISPATCHER:ProcessDetected( Detection )
self:F2()
@ -406,7 +407,7 @@ do -- DETECTION_DISPATCHER
--- First we need to the detected targets.
for DetectedAreaID, DetectedAreaData in ipairs( Detection:GetDetectedAreas() ) do
local DetectedArea = DetectedAreaData -- Detection#DETECTION_AREAS.DetectedArea
local DetectedArea = DetectedAreaData -- Functional.Detection#DETECTION_AREAS.DetectedArea
local DetectedSet = DetectedArea.Set
local DetectedZone = DetectedArea.Zone
self:E( { "Targets in DetectedArea", DetectedArea.AreaID, DetectedSet:Count(), tostring( DetectedArea ) } )
@ -420,11 +421,12 @@ do -- DETECTION_DISPATCHER
if not SEADTask then
local TargetSetUnit = self:EvaluateSEAD( DetectedArea ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
SEADTask = Mission:AddTask( TASK_SEAD:New( Mission, self.SetGroup, "SEAD." .. AreaID, TargetSetUnit , DetectedZone ) ):StatePlanned()
SEADTask = Mission:AddTask( TASK_SEAD:New( Mission, self.SetGroup, "SEAD." .. AreaID, TargetSetUnit , DetectedZone ) )
end
end
if SEADTask and SEADTask:IsStatePlanned() then
SEADTask:SetPlannedMenu()
self:E( "Planned" )
--SEADTask:SetPlannedMenu()
TaskMsg[#TaskMsg+1] = " - " .. SEADTask:GetStateString() .. " SEAD " .. AreaID .. " - " .. SEADTask.TargetSetUnit:GetUnitTypesText()
end
@ -434,11 +436,11 @@ do -- DETECTION_DISPATCHER
if not CASTask then
local TargetSetUnit = self:EvaluateCAS( DetectedArea ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
CASTask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "CAS." .. AreaID, "CAS", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) ):StatePlanned()
CASTask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "CAS." .. AreaID, "CAS", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) )
end
end
if CASTask and CASTask:IsStatePlanned() then
CASTask:SetPlannedMenu()
--CASTask:SetPlannedMenu()
TaskMsg[#TaskMsg+1] = " - " .. CASTask:GetStateString() .. " CAS " .. AreaID .. " - " .. CASTask.TargetSetUnit:GetUnitTypesText()
end
@ -448,11 +450,11 @@ do -- DETECTION_DISPATCHER
if not BAITask then
local TargetSetUnit = self:EvaluateBAI( DetectedArea, self.CommandCenter:GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
BAITask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "BAI." .. AreaID, "BAI", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) ):StatePlanned()
BAITask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "BAI." .. AreaID, "BAI", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) )
end
end
if BAITask and BAITask:IsStatePlanned() then
BAITask:SetPlannedMenu()
--BAITask:SetPlannedMenu()
TaskMsg[#TaskMsg+1] = " - " .. BAITask:GetStateString() .. " BAI " .. AreaID .. " - " .. BAITask.TargetSetUnit:GetUnitTypesText()
end
@ -483,6 +485,9 @@ do -- DETECTION_DISPATCHER
end
-- TODO set menus using the HQ coordinator
Mission:SetMenu()
if #AreaMsg > 0 then
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then

View File

@ -4,16 +4,15 @@
--- The MISSION class
-- @type MISSION
-- @extends Base#BASE
-- @field #MISSION.Clients _Clients
-- @field Menu#MENU_COALITION MissionMenu
-- @field Core.Menu#MENU_COALITION MissionMenu
-- @field #string MissionBriefing
-- @extends Core.Fsm#FSM
MISSION = {
ClassName = "MISSION",
Name = "",
MissionStatus = "PENDING",
_Clients = {},
Tasks = {},
TaskMenus = {},
TaskCategoryMenus = {},
TaskTypeMenus = {},
@ -31,36 +30,66 @@ MISSION = {
_GoalTasks = {}
}
--- @type MISSION.Clients
-- @list <Client#CLIENTS>
function MISSION:Meta()
local self = BASE:Inherit( self, BASE:New() )
return self
end
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
-- @param #MISSION self
-- @param Tasking.CommandCenter#COMMANDCENTER CommandCenter
-- @param #string MissionName is the name of the mission. This name will be used to reference the status of each mission by the players.
-- @param #string MissionPriority is a string indicating the "priority" of the Mission. f.e. "Primary", "Secondary" or "First", "Second". It is free format and up to the Mission designer to choose. There are no rules behind this field.
-- @param #string MissionBriefing is a string indicating the mission briefing to be shown when a player joins a @{CLIENT}.
-- @param DCSCoalitionObject#coalition MissionCoalition is a string indicating the coalition or party to which this mission belongs to. It is free format and can be chosen freely by the mission designer. Note that this field is not to be confused with the coalition concept of the ME. Examples of a Mission Coalition could be "NATO", "CCCP", "Intruders", "Terrorists"...
-- @param Dcs.DCSCoalitionWrapper.Object#coalition MissionCoalition is a string indicating the coalition or party to which this mission belongs to. It is free format and can be chosen freely by the mission designer. Note that this field is not to be confused with the coalition concept of the ME. Examples of a Mission Coalition could be "NATO", "CCCP", "Intruders", "Terrorists"...
-- @return #MISSION self
function MISSION:New( MissionName, MissionPriority, MissionBriefing, MissionCoalition )
function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefing, MissionCoalition )
self = MISSION:Meta()
local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM
self:SetStartState( "Idle" )
self:AddTransition( "Idle", "Start", "Ongoing" )
self:AddTransition( "Ongoing", "Stop", "Idle" )
self:AddTransition( "Ongoing", "Complete", "Completed" )
self:AddTransition( "*", "Fail", "Failed" )
self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
self.CommandCenter = CommandCenter
CommandCenter:AddMission( self )
self.Name = MissionName
self.MissionPriority = MissionPriority
self.MissionBriefing = MissionBriefing
self.MissionCoalition = MissionCoalition
self.Tasks = {}
return self
end
--- FSM function for a MISSION
-- @param #MISSION self
-- @param #string Event
-- @param #string From
-- @param #string To
function MISSION:onbeforeComplete( Event, From, To )
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if not Task:IsStateSuccess() and not Task:IsStateFailed() and not Task:IsStateAborted() and not Task:IsStateCancelled() then
return false -- Mission cannot be completed. Other Tasks are still active.
end
end
return true -- Allow Mission completion.
end
--- FSM function for a MISSION
-- @param #MISSION self
-- @param #string Event
-- @param #string From
-- @param #string To
function MISSION:onenterCompleted( Event, From, To )
self:GetCommandCenter():MessageToCoalition( "Mission " .. self:GetName() .. " has been completed! Good job guys!" )
end
--- Gets the mission name.
-- @param #MISSION self
-- @return #MISSION self
@ -68,6 +97,70 @@ function MISSION:GetName()
return self.Name
end
--- Add a Unit to join the Mission.
-- For each Task within the Mission, the Unit is joined with the Task.
-- If the Unit was not part of a Task in the Mission, false is returned.
-- If the Unit is part of a Task in the Mission, true is returned.
-- @param #MISSION self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission.
-- @return #boolean true if Unit is part of a Task in the Mission.
function MISSION:JoinUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitAdded = false
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:JoinUnit( PlayerUnit ) then
PlayerUnitAdded = true
end
end
return PlayerUnitAdded
end
--- Aborts a PlayerUnit from the Mission.
-- For each Task within the Mission, the PlayerUnit is removed from Task where it is assigned.
-- If the Unit was not part of a Task in the Mission, false is returned.
-- If the Unit is part of a Task in the Mission, true is returned.
-- @param #MISSION self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission.
-- @return #boolean true if Unit is part of a Task in the Mission.
function MISSION:AbortUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitRemoved = false
for TaskID, Task in pairs( self:GetTasks() ) do
if Task:AbortUnit( PlayerUnit ) then
PlayerUnitRemoved = true
end
end
return PlayerUnitRemoved
end
--- Handles a crash of a PlayerUnit from the Mission.
-- For each Task within the Mission, the PlayerUnit is removed from Task where it is assigned.
-- If the Unit was not part of a Task in the Mission, false is returned.
-- If the Unit is part of a Task in the Mission, true is returned.
-- @param #MISSION self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player crashing.
-- @return #boolean true if Unit is part of a Task in the Mission.
function MISSION:CrashUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitRemoved = false
for TaskID, Task in pairs( self:GetTasks() ) do
if Task:CrashUnit( PlayerUnit ) then
PlayerUnitRemoved = true
end
end
return PlayerUnitRemoved
end
--- Add a scoring to the mission.
-- @param #MISSION self
-- @return #MISSION self
@ -83,28 +176,57 @@ function MISSION:GetScoring()
return self.Scoring
end
--- Get the groups for which TASKS are given in the mission
-- @param #MISSION self
-- @return Core.Set#SET_GROUP
function MISSION:GetGroups()
local SetGroup = SET_GROUP:New()
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
local GroupSet = Task:GetGroups()
GroupSet:ForEachGroup(
function( TaskGroup )
SetGroup:Add( TaskGroup, TaskGroup )
end
)
end
return SetGroup
end
--- Sets the Planned Task menu.
-- @param #MISSION self
function MISSION:SetPlannedMenu()
-- @param Core.Menu#MENU_COALITION CommandCenterMenu
function MISSION:SetMenu()
self:F()
for _, Task in pairs( self.Tasks ) do
local Task = Task -- Task#TASK_BASE
Task:RemoveMenu()
Task:SetPlannedMenu()
for _, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
Task:SetMenu()
end
end
--- Gets the COMMANDCENTER.
-- @param #MISSION self
-- @return Tasking.CommandCenter#COMMANDCENTER
function MISSION:GetCommandCenter()
return self.CommandCenter
end
--- Sets the Assigned Task menu.
-- @param #MISSION self
-- @param Task#TASK_BASE Task
-- @param Tasking.Task#TASK Task
-- @param #string MenuText The menu text.
-- @return #MISSION self
function MISSION:SetAssignedMenu( Task )
for _, Task in pairs( self.Tasks ) do
local Task = Task -- Task#TASK_BASE
local Task = Task -- Tasking.Task#TASK
Task:RemoveMenu()
Task:SetAssignedMenu()
end
@ -113,7 +235,7 @@ end
--- Removes a Task menu.
-- @param #MISSION self
-- @param Task#TASK_BASE Task
-- @param Tasking.Task#TASK Task
-- @return #MISSION self
function MISSION:RemoveTaskMenu( Task )
@ -123,11 +245,19 @@ end
--- Gets the mission menu for the coalition.
-- @param #MISSION self
-- @param Group#GROUP TaskGroup
-- @return Menu#MENU_COALITION self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return Core.Menu#MENU_COALITION self
function MISSION:GetMissionMenu( TaskGroup )
local CommandCenter = self:GetCommandCenter()
local CommandCenterMenu = CommandCenter.CommandCenterMenu
local MissionName = self:GetName()
local TaskGroupName = TaskGroup:GetName()
return self.MenuMission[TaskGroupName]
local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu )
return MissionMenu
end
@ -140,9 +270,8 @@ function MISSION:ClearMissionMenu()
end
--- Get the TASK identified by the TaskNumber from the Mission. This function is useful in GoalFunctions.
-- @param #string TaskIndex is the Index of the @{Task} within the @{Mission}.
-- @param #number TaskID is the ID of the @{Task} within the @{Mission}.
-- @return Task#TASK_BASE The Task
-- @param #string TaskName The Name of the @{Task} within the @{Mission}.
-- @return Tasking.Task#TASK The Task
-- @return #nil Returns nil if no task was found.
function MISSION:GetTask( TaskName )
self:F( { TaskName } )
@ -155,15 +284,18 @@ end
-- Note that there can be multiple @{Task}s registered to be completed.
-- Each Task can be set a certain Goals. The Mission will not be completed until all Goals are reached.
-- @param #MISSION self
-- @param Task#TASK_BASE Task is the @{Task} object.
-- @return Task#TASK_BASE The task added.
-- @param Tasking.Task#TASK Task is the @{Task} object.
-- @return Tasking.Task#TASK The task added.
function MISSION:AddTask( Task )
local TaskName = Task:GetTaskName()
self:F( TaskName )
self.Tasks[TaskName] = self.Tasks[TaskName] or { n = 0 }
self.Tasks[TaskName] = Task
self:GetCommandCenter():SetMenu()
return Task
end
@ -172,27 +304,30 @@ end
-- Note that there can be multiple @{Task}s registered to be completed.
-- Each Task can be set a certain Goals. The Mission will not be completed until all Goals are reached.
-- @param #MISSION self
-- @param Task#TASK_BASE Task is the @{Task} object.
-- @param Tasking.Task#TASK Task is the @{Task} object.
-- @return #nil The cleaned Task reference.
function MISSION:RemoveTask( Task )
local TaskName = Task:GetTaskName()
self:F( TaskName )
self.Tasks[TaskName] = self.Tasks[TaskName] or { n = 0 }
Task:CleanUp() -- Cleans all events and sets task to nil to get Garbage Collected
-- Ensure everything gets garbarge collected.
self.Tasks[TaskName] = nil
Task = nil
collectgarbage()
self:GetCommandCenter():SetMenu()
return nil
end
--- Return the next @{Task} ID to be completed within the @{Mission}.
-- @param #MISSION self
-- @param Task#TASK_BASE Task is the @{Task} object.
-- @return Task#TASK_BASE The task added.
-- @param Tasking.Task#TASK Task is the @{Task} object.
-- @return Tasking.Task#TASK The task added.
function MISSION:GetNextTaskID( Task )
local TaskName = Task:GetTaskName()
@ -274,25 +409,96 @@ function MISSION:StatusToClients()
end
end
--- Handles the reporting. After certain time intervals, a MISSION report MESSAGE will be shown to All Players.
function MISSION:ReportTrigger()
self:F()
function MISSION:HasGroup( TaskGroup )
local Has = false
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:HasGroup( TaskGroup ) then
Has = true
break
end
end
return Has
end
if self.MissionReportShow == true then
self.MissionReportShow = false
return true
else
if self.MissionReportFlash == true then
if timer.getTime() >= self.MissionReportTrigger then
self.MissionReportTrigger = timer.getTime() + self.MissionTimeInterval
return true
else
return false
end
else
return false
end
end
--- Create a summary report of the Mission (one line).
-- @param #MISSION self
-- @return #string
function MISSION:ReportSummary()
local Report = REPORT:New()
-- List the name of the mission.
local Name = self:GetName()
-- Determine the status of the mission.
local Status = self:GetState()
-- Determine how many tasks are remaining.
local TasksRemaining = 0
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:IsStateSuccess() or Task:IsStateFailed() then
else
TasksRemaining = TasksRemaining + 1
end
end
Report:Add( "Mission " .. Name .. " - " .. Status .. " - " .. TasksRemaining .. " tasks remaining." )
return Report:Text()
end
--- Create a overview report of the Mission (multiple lines).
-- @param #MISSION self
-- @return #string
function MISSION:ReportOverview()
local Report = REPORT:New()
-- List the name of the mission.
local Name = self:GetName()
-- Determine the status of the mission.
local Status = self:GetState()
Report:Add( "Mission " .. Name .. " - State '" .. Status .. "'" )
-- Determine how many tasks are remaining.
local TasksRemaining = 0
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
Report:Add( "- " .. Task:ReportSummary() )
end
return Report:Text()
end
--- Create a detailed report of the Mission, listing all the details of the Task.
-- @param #MISSION self
-- @return #string
function MISSION:ReportDetails()
local Report = REPORT:New()
-- List the name of the mission.
local Name = self:GetName()
-- Determine the status of the mission.
local Status = self:GetState()
Report:Add( "Mission " .. Name .. " - State '" .. Status .. "'" )
-- Determine how many tasks are remaining.
local TasksRemaining = 0
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
Report:Add( Task:ReportDetails() )
end
return Report:Text()
end
--- Report the status of all MISSIONs to all active Clients.
@ -405,7 +611,7 @@ end
function MISSION:GetTasks()
self:F()
return self._Tasks
return self.Tasks
end
@ -456,7 +662,7 @@ function MISSIONSCHEDULER.Scheduler()
for ClientID, ClientData in pairs( Mission._Clients ) do
local Client = ClientData -- Client#CLIENT
local Client = ClientData -- Wrapper.Client#CLIENT
if Client:IsAlive() then

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,9 @@
--- TASK2_MENU_CLIENT class
-- @type TASK2_MENU_CLIENT
-- @field Unit#UNIT TaskUnit
-- @field Set#SET_UNIT TargetSet
-- @field Menu#MENU_CLIENT_COMMAND MenuTask
-- @field Wrapper.Unit#UNIT TaskUnit
-- @field Core.Set#SET_UNIT TargetSet
-- @field Core.Menu#MENU_CLIENT_COMMAND MenuTask
-- @extends Task2#TASK2
TASK2_MENU_CLIENT = {
ClassName = "TASK2_MENU_CLIENT",
@ -14,8 +14,8 @@ TASK2_MENU_CLIENT = {
--- Creates a new MENU handling machine.
-- @param #TASK2_MENU_CLIENT self
-- @param Mission#MISSION Mission
-- @param Unit#UNIT TaskUnit
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param #string MenuText The text of the menu item.
-- @return #TASK2_MENU_CLIENT self
function TASK2_MENU_CLIENT:New( Mission, TaskUnit, MenuText )
@ -25,7 +25,7 @@ function TASK2_MENU_CLIENT:New( Mission, TaskUnit, MenuText )
self.MenuText = MenuText
self.Fsm = STATEMACHINE_TASK:New( self, {
self.Fsm = FSM_TASK:New( self, {
initial = 'Unassigned',
events = {
{ name = 'Menu', from = 'Unassigned', to = 'AwaitingMenu' },
@ -47,7 +47,7 @@ end
--- StateMachine callback function for a TASK2
-- @param #TASK2_MENU_CLIENT self
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param Core.Fsm#FSM_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
@ -71,7 +71,7 @@ end
--- StateMachine callback function for a TASK2
-- @param #TASK2_MENU_CLIENT self
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param Core.Fsm#FSM_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To

View File

@ -0,0 +1,84 @@
--- (AI) (SP) (MP) Tasking for Air to Ground Processes.
--
-- 1) @{#TASK_A2G} class, extends @{Tasking.Task#TASK}
-- =================================================
-- The @{#TASK_A2G} class defines a CAS or BAI task of a @{Set} of Target Units,
-- located at a Target Zone, based on the tasking capabilities defined in @{Tasking.Task#TASK}.
-- The TASK_A2G is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
--
-- * **None**: Start of the process
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Fsm.Assign#ACT_ASSIGN_ACCEPT} is started to accept the task.
-- * **Assigned**: The SEAD task is assigned to a @{Wrapper.Group#GROUP}. Upon Assigned, the sub-process @{Process_Fsm.Route#ACT_ROUTE} is started to route the active Units in the Group to the attack zone.
-- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task.
-- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
-- ===
--
-- ### Authors: FlightControl - Design and Programming
--
-- @module Task_A2G
do -- TASK_A2G
--- The TASK_A2G class
-- @type TASK_A2G
-- @extends Tasking.Task#TASK
TASK_A2G = {
ClassName = "TASK_A2G",
}
--- Instantiates a new TASK_A2G.
-- @param #TASK_A2G 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 #string TaskType BAI or CAS
-- @param Set#SET_UNIT UnitSetTargets
-- @param Core.Zone#ZONE_BASE TargetZone
-- @return #TASK_A2G self
function TASK_A2G:New( Mission, SetGroup, TaskName, TaskType, TargetSetUnit, TargetZone, FACUnit )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) )
self:F()
self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone
self.FACUnit = FACUnit
local Fsm = self:GetUnitProcess()
Fsm:AddProcess( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( "Attack the Area" ), { Assigned = "Route", Rejected = "Eject" } )
Fsm:AddProcess( "Assigned", "Route", ACT_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Update" } )
Fsm:AddAction ( "Rejected", "Eject", "Planned" )
Fsm:AddAction ( "Arrived", "Update", "Updated" )
Fsm:AddProcess( "Updated", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, "Attack" ), { Accounted = "Success" } )
Fsm:AddProcess( "Updated", "Smoke", ACT_ASSIST_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) )
--Fsm:AddProcess( "Updated", "JTAC", PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) )
Fsm:AddAction ( "Accounted", "Success", "Success" )
Fsm:AddAction ( "Failed", "Fail", "Failed" )
function Fsm:onenterUpdated( TaskUnit )
self:E( { self } )
self:Account()
self:Smoke()
end
--_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
--_EVENTDISPATCHER:OnDead( self._EventDead, self )
--_EVENTDISPATCHER:OnCrash( self._EventDead, self )
--_EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
return self
end
--- @param #TASK_A2G self
function TASK_A2G:GetPlannedMenuText()
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end
end

View File

@ -1,69 +1,92 @@
--- This module contains the AIBALANCER class.
--- This module contains the AI_BALANCER class.
--
-- ===
--
-- 1) @{AIBalancer#AIBALANCER} class, extends @{Base#BASE}
-- ================================================
-- The @{AIBalancer#AIBALANCER} class controls the dynamic spawning of AI GROUPS depending on a SET_CLIENT.
-- 1) @{AI.AI_Balancer#AI_BALANCER} class, extends @{Core.Base#BASE}
-- =======================================================
-- The @{AI.AI_Balancer#AI_BALANCER} class controls the dynamic spawning of AI GROUPS depending on a SET_CLIENT.
-- There will be as many AI GROUPS spawned as there at CLIENTS in SET_CLIENT not spawned.
-- The AI_Balancer uses the @{PatrolCore.Zone#AI_PATROLZONE} class to make AI patrol an zone until the fuel treshold is reached.
--
-- 1.1) AIBALANCER construction method:
-- 1.1) AI_BALANCER construction method:
-- ------------------------------------
-- Create a new AIBALANCER object with the @{#AIBALANCER.New} method:
-- Create a new AI_BALANCER object with the @{#AI_BALANCER.New} method:
--
-- * @{#AIBALANCER.New}: Creates a new AIBALANCER object.
-- * @{#AI_BALANCER.New}: Creates a new AI_BALANCER object.
--
-- 1.2) AIBALANCER returns AI to Airbases:
-- 1.2) AI_BALANCER returns AI to Airbases:
-- ---------------------------------------
-- You can configure to have the AI to return to:
--
-- * @{#AIBALANCER.ReturnToHomeAirbase}: Returns the AI to the home @{Airbase#AIRBASE}.
-- * @{#AIBALANCER.ReturnToNearestAirbases}: Returns the AI to the nearest friendly @{Airbase#AIRBASE}.
-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the home @{Wrapper.Airbase#AIRBASE}.
-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}.
--
-- 1.3) AIBALANCER allows AI to patrol specific zones:
-- 1.3) AI_BALANCER allows AI to patrol specific zones:
-- ---------------------------------------------------
-- Use @{AIBalancer#AIBALANCER.SetPatrolZone}() to specify a zone where the AI needs to patrol.
-- Use @{AI.AI_Balancer#AI_BALANCER.SetPatrolZone}() to specify a zone where the AI needs to patrol.
--
-- ===
--
-- **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:
--
-- 2016-08-17: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval )
--
-- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called!
-- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
--
-- ===
--
-- AUTHORS and CONTRIBUTIONS
-- =========================
--
-- ### Contributions:
--
-- * **Dutch_Baron (James)** Who you can search on the Eagle Dynamics Forums.
-- Working together with James has resulted in the creation of the AIBALANCER class.
-- * **Dutch_Baron (James)**: Who you can search on the Eagle Dynamics Forums.
-- Working together with James has resulted in the creation of the AI_BALANCER class.
-- James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-)
--
-- * **SNAFU**
-- * **SNAFU**:
-- Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE.
-- None of the script code has been used however within the new AIBALANCER moose class.
-- None of the script code has been used however within the new AI_BALANCER moose class.
--
-- ### Authors:
--
-- * FlightControl - Framework Design & Programming
-- * FlightControl: Framework Design & Programming
--
-- @module AIBalancer
-- @module AI_Balancer
--- AIBALANCER class
-- @type AIBALANCER
-- @field Set#SET_CLIENT SetClient
-- @field Spawn#SPAWN SpawnAI
--- AI_BALANCER class
-- @type AI_BALANCER
-- @field Core.Set#SET_CLIENT SetClient
-- @field Functional.Spawn#SPAWN SpawnAI
-- @field #boolean ToNearestAirbase
-- @field Set#SET_AIRBASE ReturnAirbaseSet
-- @field DCSTypes#Distance ReturnTresholdRange
-- @field Core.Set#SET_AIRBASE ReturnAirbaseSet
-- @field Dcs.DCSTypes#Distance ReturnTresholdRange
-- @field #boolean ToHomeAirbase
-- @field PatrolZone#PATROLZONE PatrolZone
-- @extends Base#BASE
AIBALANCER = {
ClassName = "AIBALANCER",
-- @field PatrolCore.Zone#AI_PATROLZONE PatrolZone
-- @extends Core.Base#BASE
AI_BALANCER = {
ClassName = "AI_BALANCER",
PatrolZones = {},
AIGroups = {},
}
--- Creates a new AIBALANCER object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
-- @param #AIBALANCER self
--- Creates a new AI_BALANCER object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
-- @param #AI_BALANCER self
-- @param SetClient A SET_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player).
-- @param SpawnAI A SPAWN object that will spawn the AI units required, balancing the SetClient.
-- @return #AIBALANCER self
function AIBALANCER:New( SetClient, SpawnAI )
-- @return #AI_BALANCER self
function AI_BALANCER:New( SetClient, SpawnAI )
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() )
@ -98,40 +121,57 @@ function AIBALANCER:New( SetClient, SpawnAI )
return self
end
--- Returns the AI to the nearest friendly @{Airbase#AIRBASE}.
-- @param #AIBALANCER self
-- @param DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Airbase#AIRBASE}.
-- @param Set#SET_AIRBASE ReturnAirbaseSet The SET of @{Set#SET_AIRBASE}s to evaluate where to return to.
function AIBALANCER:ReturnToNearestAirbases( ReturnTresholdRange, ReturnAirbaseSet )
--- Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}.
-- @param #AI_BALANCER self
-- @param Dcs.DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
-- @param Core.Set#SET_AIRBASE ReturnAirbaseSet The SET of @{Core.Set#SET_AIRBASE}s to evaluate where to return to.
function AI_BALANCER:ReturnToNearestAirbases( ReturnTresholdRange, ReturnAirbaseSet )
self.ToNearestAirbase = true
self.ReturnTresholdRange = ReturnTresholdRange
self.ReturnAirbaseSet = ReturnAirbaseSet
end
--- Returns the AI to the home @{Airbase#AIRBASE}.
-- @param #AIBALANCER self
-- @param DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Airbase#AIRBASE}.
function AIBALANCER:ReturnToHomeAirbase( ReturnTresholdRange )
--- Returns the AI to the home @{Wrapper.Airbase#AIRBASE}.
-- @param #AI_BALANCER self
-- @param Dcs.DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
function AI_BALANCER:ReturnToHomeAirbase( ReturnTresholdRange )
self.ToHomeAirbase = true
self.ReturnTresholdRange = ReturnTresholdRange
end
--- Let the AI patrol a @{Zone} with a given Speed range and Altitude range.
-- @param #AIBALANCER self
-- @param PatrolZone#PATROLZONE PatrolZone The @{PatrolZone} where the AI needs to patrol.
-- @return PatrolZone#PATROLZONE self
function AIBALANCER:SetPatrolZone( PatrolZone )
-- @param #AI_BALANCER self
-- @param PatrolCore.Zone#AI_PATROLZONE PatrolZone The @{PatrolZone} where the AI needs to patrol.
-- @return PatrolCore.Zone#AI_PATROLZONE self
function AI_BALANCER:SetPatrolZone( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed )
self.PatrolZone = PatrolZone
self.PatrolZone = AI_PATROLZONE:New(
self.SpawnAI,
PatrolZone,
PatrolFloorAltitude,
PatrolCeilingAltitude,
PatrolMinSpeed,
PatrolMaxSpeed
)
end
--- @param #AIBALANCER self
function AIBALANCER:_ClientAliveMonitorScheduler()
--- Get the @{PatrolZone} object assigned by the @{AI_Balancer} object.
-- @param #AI_BALANCER self
-- @return PatrolCore.Zone#AI_PATROLZONE PatrolZone The @{PatrolZone} where the AI needs to patrol.
function AI_BALANCER:GetPatrolZone()
return self.PatrolZone
end
--- @param #AI_BALANCER self
function AI_BALANCER:_ClientAliveMonitorScheduler()
self.SetClient:ForEachClient(
--- @param Client#CLIENT Client
--- @param Wrapper.Client#CLIENT Client
function( Client )
local ClientAIAliveState = Client:GetState( self, 'AIAlive' )
self:T( ClientAIAliveState )
@ -139,7 +179,7 @@ function AIBALANCER:_ClientAliveMonitorScheduler()
if ClientAIAliveState == true then
Client:SetState( self, 'AIAlive', false )
local AIGroup = self.AIGroups[Client.UnitName] -- Group#GROUP
local AIGroup = self.AIGroups[Client.UnitName] -- Wrapper.Group#GROUP
-- local PatrolZone = Client:GetState( self, "PatrolZone" )
-- if PatrolZone then
@ -160,7 +200,7 @@ function AIBALANCER:_ClientAliveMonitorScheduler()
self:E( RangeZone )
_DATABASE:ForEachPlayer(
--- @param Unit#UNIT RangeTestUnit
--- @param Wrapper.Unit#UNIT RangeTestUnit
function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange )
self:E( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } )
if RangeTestUnit:IsInZone( RangeZone ) == true then
@ -172,8 +212,8 @@ function AIBALANCER:_ClientAliveMonitorScheduler()
end
end,
--- @param Zone#ZONE_RADIUS RangeZone
-- @param Group#GROUP AIGroup
--- @param Core.Zone#ZONE_RADIUS RangeZone
-- @param Wrapper.Group#GROUP AIGroup
function( RangeZone, AIGroup, PlayerInRange )
local AIGroupTemplate = AIGroup:GetTemplate()
if PlayerInRange.Value == false then
@ -215,7 +255,7 @@ function AIBALANCER:_ClientAliveMonitorScheduler()
--- Now test if the AIGroup needs to patrol a zone, otherwise let it follow its route...
if self.PatrolZone then
self.PatrolZones[#self.PatrolZones+1] = PATROLZONE:New(
self.PatrolZones[#self.PatrolZones+1] = AI_PATROLZONE:New(
self.PatrolZone.PatrolZone,
self.PatrolZone.PatrolFloorAltitude,
self.PatrolZone.PatrolCeilingAltitude,

View File

@ -1,14 +1,14 @@
--- This module contains the TASK_PICKUP classes.
--
-- 1) @{#TASK_PICKUP} class, extends @{Task#TASK_BASE}
-- 1) @{#TASK_PICKUP} class, extends @{Tasking.Task#TASK}
-- ===================================================
-- The @{#TASK_PICKUP} class defines a pickup task of a @{Set} of @{CARGO} objects defined within the mission.
-- based on the tasking capabilities defined in @{Task#TASK_BASE}.
-- The TASK_PICKUP is implemented using a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses:
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
-- The TASK_PICKUP is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
--
-- * **None**: Start of the process
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task.
-- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Route#PROCESS_ROUTE} is started to route the active Units in the Group to the attack zone.
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Fsm.Assign#ACT_ASSIGN_ACCEPT} is started to accept the task.
-- * **Assigned**: The SEAD task is assigned to a @{Wrapper.Group#GROUP}. Upon Assigned, the sub-process @{Process_Fsm.Route#ACT_ROUTE} is started to route the active Units in the Group to the attack zone.
-- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task.
-- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
@ -23,22 +23,22 @@ do -- TASK_PICKUP
--- The TASK_PICKUP class
-- @type TASK_PICKUP
-- @extends Task#TASK_BASE
-- @extends Tasking.Task#TASK
TASK_PICKUP = {
ClassName = "TASK_PICKUP",
}
--- Instantiates a new TASK_PICKUP.
-- @param #TASK_PICKUP self
-- @param Mission#MISSION Mission
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP AssignedSetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param #string TaskType BAI or CAS
-- @param Set#SET_UNIT UnitSetTargets
-- @param Zone#ZONE_BASE TargetZone
-- @param Core.Zone#ZONE_BASE TargetZone
-- @return #TASK_PICKUP self
function TASK_PICKUP:New( Mission, AssignedSetGroup, TaskName, TaskType )
local self = BASE:Inherit( self, TASK_BASE:New( Mission, AssignedSetGroup, TaskName, TaskType, "PICKUP" ) )
local self = BASE:Inherit( self, TASK:New( Mission, AssignedSetGroup, TaskName, TaskType, "PICKUP" ) )
self:F()
_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
@ -62,15 +62,15 @@ do -- TASK_PICKUP
--- Assign the @{Task} to a @{Unit}.
-- @param #TASK_PICKUP self
-- @param Unit#UNIT TaskUnit
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_PICKUP self
function TASK_PICKUP:AssignToUnit( TaskUnit )
self:F( TaskUnit:GetName() )
local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) )
local ProcessAssign = self:AddProcess( TaskUnit, ACT_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) )
local ProcessPickup = self:AddProcess( TaskUnit, PROCESS_PICKUP:New( self, self.TaskType, TaskUnit ) )
local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, {
local Process = self:AddStateMachine( TaskUnit, FSM_TASK:New( self, TaskUnit, {
initial = 'None',
events = {
{ name = 'Next', from = 'None', to = 'Planned' },
@ -98,7 +98,7 @@ do -- TASK_PICKUP
--- StateMachine callback function for a TASK
-- @param #TASK_PICKUP self
-- @param StateMachine#STATEMACHINE_TASK Fsm
-- @param Core.Fsm#FSM_TASK Fsm
-- @param #string Event
-- @param #string From
-- @param #string To

View File

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

View File

@ -1,3 +1,16 @@
--- This module contains derived utilities taken from the MIST framework,
-- which are excellent tools to be reused in an OO environment!.
--
-- ### Authors:
--
-- * Grimes : Design & Programming of the MIST framework.
--
-- ### Contributions:
--
-- * FlightControl : Rework to OO framework
--
-- @module Utils
--- @type SMOKECOLOR
-- @field Green
@ -100,11 +113,11 @@ UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a s
tbl_str[#tbl_str + 1] = table.concat(val_str)
end
elseif type(val) == 'function' then
-- tbl_str[#tbl_str + 1] = "function " .. tostring(ind)
-- tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
tbl_str[#tbl_str + 1] = "f() " .. tostring(ind)
tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it
else
-- env.info('unable to serialize value type ' .. routines.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind))
-- env.info( debug.traceback() )
env.info('unable to serialize value type ' .. routines.utils.basicSerialize(type(val)) .. ' at index ' .. tostring(ind))
env.info( debug.traceback() )
end
end

View File

@ -2,7 +2,7 @@
--
-- ===
--
-- 1) @{Airbase#AIRBASE} class, extends @{Positionable#POSITIONABLE}
-- 1) @{Wrapper.Airbase#AIRBASE} class, extends @{Wrapper.Positionable#POSITIONABLE}
-- =================================================================
-- The @{AIRBASE} class is a wrapper class to handle the DCS Airbase objects:
--
@ -33,7 +33,7 @@
-- ---------------------
-- The DCS Airbase APIs are used extensively within MOOSE. The AIRBASE class has for each DCS Airbase API a corresponding method.
-- To be able to distinguish easily in your code the difference between a AIRBASE API call and a DCS Airbase API call,
-- the first letter of the method is also capitalized. So, by example, the DCS Airbase method @{DCSAirbase#Airbase.getName}()
-- the first letter of the method is also capitalized. So, by example, the DCS Airbase method @{Dcs.DCSWrapper.Airbase#Airbase.getName}()
-- is implemented in the AIRBASE class as @{#AIRBASE.GetName}().
--
-- More functions will be added
@ -49,7 +49,7 @@
--- The AIRBASE class
-- @type AIRBASE
-- @extends Positionable#POSITIONABLE
-- @extends Wrapper.Positionable#POSITIONABLE
AIRBASE = {
ClassName="AIRBASE",
CategoryName = {
@ -64,7 +64,7 @@ AIRBASE = {
--- Create a new AIRBASE from DCSAirbase.
-- @param #AIRBASE self
-- @param #string AirbaseName The name of the airbase.
-- @return Airbase#AIRBASE
-- @return Wrapper.Airbase#AIRBASE
function AIRBASE:Register( AirbaseName )
local self = BASE:Inherit( self, POSITIONABLE:New( AirbaseName ) )
@ -76,8 +76,8 @@ end
--- Finds a AIRBASE from the _DATABASE using a DCSAirbase object.
-- @param #AIRBASE self
-- @param DCSAirbase#Airbase DCSAirbase An existing DCS Airbase object reference.
-- @return Airbase#AIRBASE self
-- @param Dcs.DCSWrapper.Airbase#Airbase DCSAirbase An existing DCS Airbase object reference.
-- @return Wrapper.Airbase#AIRBASE self
function AIRBASE:Find( DCSAirbase )
local AirbaseName = DCSAirbase:getName()
@ -88,7 +88,7 @@ end
--- Find a AIRBASE in the _DATABASE using the name of an existing DCS Airbase.
-- @param #AIRBASE self
-- @param #string AirbaseName The Airbase Name.
-- @return Airbase#AIRBASE self
-- @return Wrapper.Airbase#AIRBASE self
function AIRBASE:FindByName( AirbaseName )
local AirbaseFound = _DATABASE:FindAirbase( AirbaseName )

View File

@ -1,10 +1,10 @@
--- This module contains the CLIENT class.
--
-- 1) @{Client#CLIENT} class, extends @{Unit#UNIT}
-- 1) @{Wrapper.Client#CLIENT} class, extends @{Wrapper.Unit#UNIT}
-- ===============================================
-- Clients are those **Units** defined within the Mission Editor that have the skillset defined as __Client__ or __Player__.
-- Note that clients are NOT the same as Units, they are NOT necessarily alive.
-- The @{Client#CLIENT} class is a wrapper class to handle the DCS Unit objects that have the skillset defined as __Client__ or __Player__:
-- The @{Wrapper.Client#CLIENT} class is a wrapper class to handle the DCS Unit objects that have the skillset defined as __Client__ or __Player__:
--
-- * Wraps the DCS Unit objects with skill level set to Player or Client.
-- * Support all DCS Unit APIs.
@ -39,7 +39,7 @@
--- The CLIENT class
-- @type CLIENT
-- @extends Unit#UNIT
-- @extends Wrapper.Unit#UNIT
CLIENT = {
ONBOARDSIDE = {
NONE = 0,
@ -92,6 +92,7 @@ end
-- @param #CLIENT self
-- @param #string ClientName Name of the DCS **Unit** as defined within the Mission Editor.
-- @param #string ClientBriefing Text that describes the briefing of the mission when a Player logs into the Client.
-- @param #boolean Error A flag that indicates whether an error should be raised if the CLIENT cannot be found. By default an error will be raised.
-- @return #CLIENT
-- @usage
-- -- Create new Clients.
@ -102,7 +103,7 @@ end
-- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 3' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*HOT-Deploy Troops 2' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 4' ):Transport() )
function CLIENT:FindByName( ClientName, ClientBriefing )
function CLIENT:FindByName( ClientName, ClientBriefing, Error )
local ClientFound = _DATABASE:FindClient( ClientName )
if ClientFound then
@ -113,7 +114,9 @@ function CLIENT:FindByName( ClientName, ClientBriefing )
return ClientFound
end
error( "CLIENT not found for: " .. ClientName )
if not Error then
error( "CLIENT not found for: " .. ClientName )
end
end
function CLIENT:Register( ClientName )
@ -236,7 +239,7 @@ end
--- @param #CLIENT self
function CLIENT:_AliveCheckScheduler( SchedulerName )
self:F( { SchedulerName, self.ClientName, self.ClientAlive2, self.ClientBriefingShown, self.ClientCallBack } )
self:F3( { SchedulerName, self.ClientName, self.ClientAlive2, self.ClientBriefingShown, self.ClientCallBack } )
if self:IsAlive() then
if self.ClientAlive2 == false then
@ -259,7 +262,7 @@ end
--- Return the DCSGroup of a Client.
-- This function is modified to deal with a couple of bugs in DCS 1.5.3
-- @param #CLIENT self
-- @return DCSGroup#Group
-- @return Dcs.DCSWrapper.Group#Group
function CLIENT:GetDCSGroup()
self:F3()
@ -333,10 +336,10 @@ function CLIENT:GetDCSGroup()
end
-- TODO: Check DCSTypes#Group.ID
-- TODO: Check Dcs.DCSTypes#Group.ID
--- Get the group ID of the client.
-- @param #CLIENT self
-- @return DCSTypes#Group.ID
-- @return Dcs.DCSTypes#Group.ID
function CLIENT:GetClientGroupID()
local ClientGroup = self:GetDCSGroup()
@ -359,7 +362,7 @@ end
--- Returns the UNIT of the CLIENT.
-- @param #CLIENT self
-- @return Unit#UNIT
-- @return Wrapper.Unit#UNIT
function CLIENT:GetClientGroupUnit()
self:F2()
@ -375,7 +378,7 @@ end
--- Returns the DCSUnit of the CLIENT.
-- @param #CLIENT self
-- @return DCSTypes#Unit
-- @return Dcs.DCSTypes#Unit
function CLIENT:GetClientGroupDCSUnit()
self:F2()
@ -396,8 +399,8 @@ function CLIENT:IsTransport()
return self.ClientTransport
end
--- Shows the @{Cargo#CARGO} contained within the CLIENT to the player as a message.
-- The @{Cargo#CARGO} is shown using the @{Message#MESSAGE} distribution system.
--- 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()
@ -430,7 +433,7 @@ end
-- @param #string Message is the text describing the message.
-- @param #number MessageDuration is the duration in seconds that the Message should be displayed.
-- @param #string MessageCategory is the category of the message (the title).
-- @param #number MessageInterval is the interval in seconds between the display of the @{Message#MESSAGE} when the CLIENT is in the air.
-- @param #number MessageInterval is the interval in seconds between the display of the @{Core.Message#MESSAGE} when the CLIENT is in the air.
-- @param #string MessageID is the identifier of the message when displayed with intervals.
function CLIENT:Message( Message, MessageDuration, MessageCategory, MessageInterval, MessageID )
self:F( { Message, MessageDuration, MessageCategory, MessageInterval } )

View File

@ -1,8 +1,8 @@
--- This module contains the CONTROLLABLE class.
--
-- 1) @{Controllable#CONTROLLABLE} class, extends @{Positionable#POSITIONABLE}
-- 1) @{Wrapper.Controllable#CONTROLLABLE} class, extends @{Wrapper.Positionable#POSITIONABLE}
-- ===========================================================
-- The @{Controllable#CONTROLLABLE} class is a wrapper class to handle the DCS Controllable objects:
-- The @{Wrapper.Controllable#CONTROLLABLE} class is a wrapper class to handle the DCS Controllable objects:
--
-- * Support all DCS Controllable APIs.
-- * Enhance with Controllable specific APIs not in the DCS Controllable API set.
@ -18,7 +18,7 @@
-- 1.2) CONTROLLABLE task methods
-- ------------------------------
-- Several controllable task methods are available that help you to prepare tasks.
-- These methods return a string consisting of the task description, which can then be given to either a @{Controllable#CONTROLLABLE.PushTask} or @{Controllable#SetTask} method to assign the task to the CONTROLLABLE.
-- These methods return a string consisting of the task description, which can then be given to either a @{Wrapper.Controllable#CONTROLLABLE.PushTask} or @{Wrapper.Controllable#SetTask} method to assign the task to the CONTROLLABLE.
-- Tasks are specific for the category of the CONTROLLABLE, more specific, for AIR, GROUND or AIR and GROUND.
-- Each task description where applicable indicates for which controllable category the task is valid.
-- There are 2 main subdivisions of tasks: Assigned tasks and EnRoute tasks.
@ -44,7 +44,7 @@
-- * @{#CONTROLLABLE.TaskHold}: (GROUND) Hold ground controllable from moving.
-- * @{#CONTROLLABLE.TaskHoldPosition}: (AIR) Hold position at the current position of the first unit of the controllable.
-- * @{#CONTROLLABLE.TaskLand}: (AIR HELICOPTER) Landing at the ground. For helicopters only.
-- * @{#CONTROLLABLE.TaskLandAtZone}: (AIR) Land the controllable at a @{Zone#ZONE_RADIUS).
-- * @{#CONTROLLABLE.TaskLandAtZone}: (AIR) Land the controllable at a @{Core.Zone#ZONE_RADIUS).
-- * @{#CONTROLLABLE.TaskOrbitCircle}: (AIR) Orbit at the current position of the first unit of the controllable at a specified alititude.
-- * @{#CONTROLLABLE.TaskOrbitCircleAtVec2}: (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed.
-- * @{#CONTROLLABLE.TaskRefueling}: (AIR) Refueling from the nearest tanker. No parameters.
@ -127,8 +127,8 @@
--- The CONTROLLABLE class
-- @type CONTROLLABLE
-- @extends Positionable#POSITIONABLE
-- @field DCSControllable#Controllable DCSControllable The DCS controllable class.
-- @extends Wrapper.Positionable#POSITIONABLE
-- @field Dcs.DCSWrapper.Controllable#Controllable DCSControllable The DCS controllable class.
-- @field #string ControllableName The name of the controllable.
CONTROLLABLE = {
ClassName = "CONTROLLABLE",
@ -138,7 +138,7 @@ CONTROLLABLE = {
--- Create a new CONTROLLABLE from a DCSControllable
-- @param #CONTROLLABLE self
-- @param DCSControllable#Controllable ControllableName The DCS Controllable name
-- @param Dcs.DCSWrapper.Controllable#Controllable ControllableName The DCS Controllable name
-- @return #CONTROLLABLE self
function CONTROLLABLE:New( ControllableName )
local self = BASE:Inherit( self, POSITIONABLE:New( ControllableName ) )
@ -151,7 +151,7 @@ end
--- Get the controller for the CONTROLLABLE.
-- @param #CONTROLLABLE self
-- @return DCSController#Controller
-- @return Dcs.DCSController#Controller
function CONTROLLABLE:_GetController()
self:F2( { self.ControllableName } )
local DCSControllable = self:GetDCSObject()
@ -171,7 +171,7 @@ end
--- Popping current Task from the controllable.
-- @param #CONTROLLABLE self
-- @return Controllable#CONTROLLABLE self
-- @return Wrapper.Controllable#CONTROLLABLE self
function CONTROLLABLE:PopCurrentTask()
self:F2()
@ -188,7 +188,7 @@ end
--- Pushing Task on the queue from the controllable.
-- @param #CONTROLLABLE self
-- @return Controllable#CONTROLLABLE self
-- @return Wrapper.Controllable#CONTROLLABLE self
function CONTROLLABLE:PushTask( DCSTask, WaitTime )
self:F2()
@ -215,7 +215,7 @@ end
--- Clearing the Task Queue and Setting the Task on the queue from the controllable.
-- @param #CONTROLLABLE self
-- @return Controllable#CONTROLLABLE self
-- @return Wrapper.Controllable#CONTROLLABLE self
function CONTROLLABLE:SetTask( DCSTask, WaitTime )
self:F2( { DCSTask } )
@ -231,9 +231,10 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime )
-- Controller.setTask( Controller, DCSTask )
if not WaitTime then
WaitTime = 1
Controller:setTask( DCSTask )
else
SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime )
end
SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime )
return self
end
@ -244,13 +245,13 @@ end
--- Return a condition section for a controlled task.
-- @param #CONTROLLABLE self
-- @param DCSTime#Time time
-- @param Dcs.DCSTime#Time time
-- @param #string userFlag
-- @param #boolean userFlagValue
-- @param #string condition
-- @param DCSTime#Time duration
-- @param Dcs.DCSTime#Time duration
-- @param #number lastWayPoint
-- return DCSTask#Task
-- return Dcs.DCSTasking.Task#Task
function CONTROLLABLE:TaskCondition( time, userFlag, userFlagValue, condition, duration, lastWayPoint )
self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } )
@ -268,9 +269,9 @@ end
--- Return a Controlled Task taking a Task and a TaskCondition.
-- @param #CONTROLLABLE self
-- @param DCSTask#Task DCSTask
-- @param Dcs.DCSTasking.Task#Task DCSTask
-- @param #DCSStopCondition DCSStopCondition
-- @return DCSTask#Task
-- @return Dcs.DCSTasking.Task#Task
function CONTROLLABLE:TaskControlled( DCSTask, DCSStopCondition )
self:F2( { DCSTask, DCSStopCondition } )
@ -290,8 +291,8 @@ end
--- Return a Combo Task taking an array of Tasks.
-- @param #CONTROLLABLE self
-- @param DCSTask#TaskArray DCSTasks Array of @{DCSTask#Task}
-- @return DCSTask#Task
-- @param Dcs.DCSTasking.Task#TaskArray DCSTasks Array of @{Dcs.DCSTasking.Task#Task}
-- @return Dcs.DCSTasking.Task#Task
function CONTROLLABLE:TaskCombo( DCSTasks )
self:F2( { DCSTasks } )
@ -310,8 +311,8 @@ end
--- Return a WrappedAction Task taking a Command.
-- @param #CONTROLLABLE self
-- @param DCSCommand#Command DCSCommand
-- @return DCSTask#Task
-- @param Dcs.DCSCommand#Command DCSCommand
-- @return Dcs.DCSTasking.Task#Task
function CONTROLLABLE:TaskWrappedAction( DCSCommand, Index )
self:F2( { DCSCommand } )
@ -333,7 +334,7 @@ end
--- Executes a command action
-- @param #CONTROLLABLE self
-- @param DCSCommand#Command DCSCommand
-- @param Dcs.DCSCommand#Command DCSCommand
-- @return #CONTROLLABLE self
function CONTROLLABLE:SetCommand( DCSCommand )
self:F2( DCSCommand )
@ -353,7 +354,7 @@ end
-- @param #CONTROLLABLE self
-- @param #number FromWayPoint
-- @param #number ToWayPoint
-- @return DCSTask#Task
-- @return Dcs.DCSTasking.Task#Task
-- @usage
-- --- This test demonstrates the use(s) of the SwitchWayPoint method of the GROUP class.
-- HeliGroup = GROUP:FindByName( "Helicopter" )
@ -384,7 +385,7 @@ end
--- Perform stop route command
-- @param #CONTROLLABLE self
-- @param #boolean StopRoute
-- @return DCSTask#Task
-- @return Dcs.DCSTasking.Task#Task
function CONTROLLABLE:CommandStopRoute( StopRoute, Index )
self:F2( { StopRoute, Index } )
@ -405,14 +406,14 @@ end
--- (AIR) Attack a Controllable.
-- @param #CONTROLLABLE self
-- @param Controllable#CONTROLLABLE AttackGroup The Controllable to be attacked.
-- @param Wrapper.Controllable#CONTROLLABLE AttackGroup The Controllable to be attacked.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param DCSTypes#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude.
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackControllable" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit )
self:F2( { self.ControllableName, AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } )
@ -463,14 +464,14 @@ end
--- (AIR) Attack the Unit.
-- @param #CONTROLLABLE self
-- @param Unit#UNIT AttackUnit The unit.
-- @param Wrapper.Unit#UNIT AttackUnit The unit.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackControllable" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, ControllableAttack )
self:F2( { self.ControllableName, AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, ControllableAttack } )
@ -507,13 +508,13 @@ end
--- (AIR) Delivering weapon at the point on the ground.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec2 Vec2 2D-coordinates of the point to deliver weapon at.
-- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point to deliver weapon at.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) Desired quantity of passes. The parameter is not the same in AttackControllable and AttackUnit tasks.
-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskBombing( Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack )
self:F2( { self.ControllableName, Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack } )
@ -547,7 +548,7 @@ end
--- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec2 Point The point to hold the position.
-- @param Dcs.DCSTypes#Vec2 Point The point to hold the position.
-- @param #number Altitude The altitude to hold the position.
-- @param #number Speed The speed flying when holding the position.
-- @return #CONTROLLABLE self
@ -625,13 +626,13 @@ end
--- (AIR) Attacking the map object (building, structure, e.t.c).
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec2 Vec2 2D-coordinates of the point the map object is closest to. The distance between the point and the map object must not be greater than 2000 meters. Object id is not used here because Mission Editor doesn't support map object identificators.
-- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point the map object is closest to. The distance between the point and the map object must not be greater than 2000 meters. Object id is not used here because Mission Editor doesn't support map object identificators.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskAttackMapObject( Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack )
self:F2( { self.ControllableName, Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack } )
@ -666,13 +667,13 @@ end
--- (AIR) Delivering weapon on the runway.
-- @param #CONTROLLABLE self
-- @param Airbase#AIRBASE Airbase Airbase to attack.
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase to attack.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskBombingRunway( Airbase, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack )
self:F2( { self.ControllableName, Airbase, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack } )
@ -707,7 +708,7 @@ end
--- (AIR) Refueling from the nearest tanker. No parameters.
-- @param #CONTROLLABLE self
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskRefueling()
self:F2( { self.ControllableName } )
@ -729,7 +730,7 @@ end
--- (AIR HELICOPTER) Landing at the ground. For helicopters only.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec2 Point The point where to land.
-- @param Dcs.DCSTypes#Vec2 Point The point where to land.
-- @param #number Duration The duration in seconds to stay on the ground.
-- @return #CONTROLLABLE self
function CONTROLLABLE:TaskLandAtVec2( Point, Duration )
@ -766,9 +767,9 @@ function CONTROLLABLE:TaskLandAtVec2( Point, Duration )
return DCSTask
end
--- (AIR) Land the controllable at a @{Zone#ZONE_RADIUS).
--- (AIR) Land the controllable at a @{Core.Zone#ZONE_RADIUS).
-- @param #CONTROLLABLE self
-- @param Zone#ZONE Zone The zone where to land.
-- @param Core.Zone#ZONE Zone The zone where to land.
-- @param #number Duration The duration in seconds to stay on the ground.
-- @return #CONTROLLABLE self
function CONTROLLABLE:TaskLandAtZone( Zone, Duration, RandomPoint )
@ -793,10 +794,10 @@ end
-- The unit / controllable will follow lead unit of another controllable, wingmens of both controllables will continue following their leaders.
-- If another controllable is on land the unit / controllable will orbit around.
-- @param #CONTROLLABLE self
-- @param Controllable#CONTROLLABLE FollowControllable The controllable to be followed.
-- @param DCSTypes#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around.
-- @param Wrapper.Controllable#CONTROLLABLE FollowControllable The controllable to be followed.
-- @param Dcs.DCSTypes#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around.
-- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Follow task is finished.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskFollow( FollowControllable, Vec3, LastWaypointIndex )
self:F2( { self.ControllableName, FollowControllable, Vec3, LastWaypointIndex } )
@ -835,12 +836,12 @@ end
-- The unit / controllable will follow lead unit of another controllable, wingmens of both controllables will continue following their leaders.
-- The unit / controllable will also protect that controllable from threats of specified types.
-- @param #CONTROLLABLE self
-- @param Controllable#CONTROLLABLE EscortControllable The controllable to be escorted.
-- @param DCSTypes#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around.
-- @param Wrapper.Controllable#CONTROLLABLE EscortControllable The controllable to be escorted.
-- @param Dcs.DCSTypes#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around.
-- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Follow task is finished.
-- @param #number EngagementDistanceMax Maximal distance from escorted controllable to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax.
-- @param DCSTypes#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage.
-- @return DCSTask#Task The DCS task structure.
-- @param Dcs.DCSTypes#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes )
self:F2( { self.ControllableName, FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes } )
@ -882,9 +883,9 @@ end
--- (GROUND) Fire at a VEC2 point until ammunition is finished.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec2 Vec2 The point to fire at.
-- @param DCSTypes#Distance Radius The radius of the zone to deploy the fire at.
-- @return DCSTask#Task The DCS task structure.
-- @param Dcs.DCSTypes#Vec2 Vec2 The point to fire at.
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone to deploy the fire at.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius )
self:F2( { self.ControllableName, Vec2, Radius } )
@ -910,7 +911,7 @@ end
--- (GROUND) Hold ground controllable from moving.
-- @param #CONTROLLABLE self
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskHold()
self:F2( { self.ControllableName } )
@ -937,11 +938,11 @@ end
-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC.
-- If the task is assigned to the controllable lead unit will be a FAC.
-- @param #CONTROLLABLE self
-- @param Controllable#CONTROLLABLE AttackGroup Target CONTROLLABLE.
-- @param Wrapper.Controllable#CONTROLLABLE AttackGroup Target CONTROLLABLE.
-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.Designation Designation (optional) Designation type.
-- @param Dcs.DCSTypes#AI.Task.Designation Designation (optional) Designation type.
-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink )
self:F2( { self.ControllableName, AttackGroup, WeaponType, Designation, Datalink } )
@ -969,14 +970,14 @@ function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation,
return DCSTask
end
-- EN-ROUTE TASKS FOR AIRBORNE CONTROLLABLES
-- EN-ACT_ROUTE TASKS FOR AIRBORNE CONTROLLABLES
--- (AIR) Engaging targets of defined types.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Distance Distance Maximal distance from the target to a route leg. If the target is on a greater distance it will be ignored.
-- @param DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage.
-- @param Dcs.DCSTypes#Distance Distance Maximal distance from the target to a route leg. If the target is on a greater distance it will be ignored.
-- @param Dcs.DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage.
-- @param #number Priority All enroute tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEngageTargets( Distance, TargetTypes, Priority )
self:F2( { self.ControllableName, Distance, TargetTypes, Priority } )
@ -1006,11 +1007,11 @@ end
--- (AIR) Engaging a targets of defined types at circle-shaped zone.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec2 Vec2 2D-coordinates of the zone.
-- @param DCSTypes#Distance Radius Radius of the zone.
-- @param DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage.
-- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the zone.
-- @param Dcs.DCSTypes#Distance Radius Radius of the zone.
-- @param Dcs.DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage.
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEngageTargets( Vec2, Radius, TargetTypes, Priority )
self:F2( { self.ControllableName, Vec2, Radius, TargetTypes, Priority } )
@ -1041,15 +1042,15 @@ end
--- (AIR) Engaging a controllable. The task does not assign the target controllable to the unit/controllable to attack now; it just allows the unit/controllable to engage the target controllable as well as other assigned targets.
-- @param #CONTROLLABLE self
-- @param Controllable#CONTROLLABLE AttackGroup The Controllable to be attacked.
-- @param Wrapper.Controllable#CONTROLLABLE AttackGroup The Controllable to be attacked.
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param DCSTypes#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude.
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackControllable" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit )
self:F2( { self.ControllableName, AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } )
@ -1102,15 +1103,15 @@ end
--- (AIR) Attack the Unit.
-- @param #CONTROLLABLE self
-- @param Unit#UNIT AttackUnit The UNIT.
-- @param Wrapper.Unit#UNIT AttackUnit The UNIT.
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackControllable" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEngageUnit( AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, ControllableAttack )
self:F2( { self.ControllableName, AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, ControllableAttack } )
@ -1150,7 +1151,7 @@ end
--- (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters.
-- @param #CONTROLLABLE self
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskAWACS( )
self:F2( { self.ControllableName } )
@ -1173,7 +1174,7 @@ end
--- (AIR) Aircraft will act as a tanker for friendly units. No parameters.
-- @param #CONTROLLABLE self
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskTanker( )
self:F2( { self.ControllableName } )
@ -1198,7 +1199,7 @@ end
--- (GROUND) Ground unit (EW-radar) will act as an EWR for friendly units (will provide them with information about contacts). No parameters.
-- @param #CONTROLLABLE self
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskEWR( )
self:F2( { self.ControllableName } )
@ -1225,12 +1226,12 @@ end
-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC.
-- If the task is assigned to the controllable lead unit will be a FAC.
-- @param #CONTROLLABLE self
-- @param Controllable#CONTROLLABLE AttackGroup Target CONTROLLABLE.
-- @param Wrapper.Controllable#CONTROLLABLE AttackGroup Target CONTROLLABLE.
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param DCSTypes#AI.Task.Designation Designation (optional) Designation type.
-- @param Dcs.DCSTypes#AI.Task.Designation Designation (optional) Designation type.
-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink )
self:F2( { self.ControllableName, AttackGroup, WeaponType, Priority, Designation, Datalink } )
@ -1265,9 +1266,9 @@ end
-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC.
-- If the task is assigned to the controllable lead unit will be a FAC.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Distance Radius The maximal distance from the FAC to a target.
-- @param Dcs.DCSTypes#Distance Radius The maximal distance from the FAC to a target.
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:EnRouteTaskFAC( Radius, Priority )
self:F2( { self.ControllableName, Radius, Priority } )
@ -1296,10 +1297,10 @@ end
--- (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec2 Point The point where to wait.
-- @param Dcs.DCSTypes#Vec2 Point The point where to wait.
-- @param #number Duration The duration in seconds to wait.
-- @param #CONTROLLABLE EmbarkingControllable The controllable to be embarked.
-- @return DCSTask#Task The DCS task structure
-- @return Dcs.DCSTasking.Task#Task The DCS task structure
function CONTROLLABLE:TaskEmbarking( Point, Duration, EmbarkingControllable )
self:F2( { self.ControllableName, Point, Duration, EmbarkingControllable.DCSControllable } )
@ -1323,13 +1324,13 @@ end
--- Move to a defined Vec2 Point, and embark to a controllable when arrived within a defined Radius.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec2 Point The point where to wait.
-- @param Dcs.DCSTypes#Vec2 Point The point where to wait.
-- @param #number Radius The radius of the embarking zone around the Point.
-- @return DCSTask#Task The DCS task structure.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskEmbarkToTransport( Point, Radius )
self:F2( { self.ControllableName, Point, Radius } )
local DCSTask --DCSTask#Task
local DCSTask --Dcs.DCSTasking.Task#Task
DCSTask = { id = 'EmbarkToTransport',
params = { x = Point.x,
y = Point.y,
@ -1346,7 +1347,7 @@ end
--- (AIR + GROUND) Return a mission task from a mission template.
-- @param #CONTROLLABLE self
-- @param #table TaskMission A table containing the mission task.
-- @return DCSTask#Task
-- @return Dcs.DCSTasking.Task#Task
function CONTROLLABLE:TaskMission( TaskMission )
self:F2( Points )
@ -1360,7 +1361,7 @@ end
--- Return a Misson task to follow a given route defined by Points.
-- @param #CONTROLLABLE self
-- @param #table Points A table of route points.
-- @return DCSTask#Task
-- @return Dcs.DCSTasking.Task#Task
function CONTROLLABLE:TaskRoute( Points )
self:F2( Points )
@ -1373,7 +1374,7 @@ end
--- (AIR + GROUND) Make the Controllable move to fly to a given point.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec3 Point The destination point in Vec3 format.
-- @param Dcs.DCSTypes#Vec3 Point The destination point in Vec3 format.
-- @param #number Speed The speed to travel.
-- @return #CONTROLLABLE self
function CONTROLLABLE:TaskRouteToVec2( Point, Speed )
@ -1424,7 +1425,7 @@ end
--- (AIR + GROUND) Make the Controllable move to a given point.
-- @param #CONTROLLABLE self
-- @param DCSTypes#Vec3 Point The destination point in Vec3 format.
-- @param Dcs.DCSTypes#Vec3 Point The destination point in Vec3 format.
-- @param #number Speed The speed to travel.
-- @return #CONTROLLABLE self
function CONTROLLABLE:TaskRouteToVec3( Point, Speed )
@ -1507,7 +1508,7 @@ end
-- A speed can be given in km/h.
-- A given formation can be given.
-- @param #CONTROLLABLE self
-- @param Zone#ZONE Zone The zone where to route to.
-- @param Core.Zone#ZONE Zone The zone where to route to.
-- @param #boolean Randomize Defines whether to target point gets randomized within the Zone.
-- @param #number Speed The speed.
-- @param Base#FORMATION Formation The formation string.
@ -1565,11 +1566,11 @@ function CONTROLLABLE:TaskRouteToZone( Zone, Randomize, Speed, Formation )
return nil
end
--- (AIR) Return the Controllable to an @{Airbase#AIRBASE}
--- (AIR) Return the Controllable to an @{Wrapper.Airbase#AIRBASE}
-- A speed can be given in km/h.
-- A given formation can be given.
-- @param #CONTROLLABLE self
-- @param Airbase#AIRBASE ReturnAirbase The @{Airbase#AIRBASE} to return to.
-- @param Wrapper.Airbase#AIRBASE ReturnAirbase The @{Wrapper.Airbase#AIRBASE} to return to.
-- @param #number Speed (optional) The speed.
-- @return #string The route
function CONTROLLABLE:RouteReturnToAirbase( ReturnAirbase, Speed )
@ -1689,7 +1690,7 @@ function CONTROLLABLE:GetTaskRoute()
return routines.utils.deepCopy( _DATABASE.Templates.Controllables[self.ControllableName].Template.route.points )
end
--- Return the route of a controllable by using the @{Database#DATABASE} class.
--- Return the route of a controllable by using the @{Core.Database#DATABASE} class.
-- @param #CONTROLLABLE self
-- @param #number Begin The route point from where the copy will start. The base route point is 0.
-- @param #number End The route point where the copy will end. The End point is the last point - the End point. The last point has base 0.
@ -1744,7 +1745,7 @@ end
--- Return the detected targets of the controllable.
-- The optional parametes specify the detection methods that can be applied.
-- If no detection method is given, the detection will use all the available methods by default.
-- @param Controllable#CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE self
-- @param #boolean DetectVisual (optional)
-- @param #boolean DetectOptical (optional)
-- @param #boolean DetectRadar (optional)
@ -1813,8 +1814,8 @@ function CONTROLLABLE:OptionROEHoldFirePossible()
end
--- Holding weapons.
-- @param Controllable#CONTROLLABLE self
-- @return Controllable#CONTROLLABLE self
-- @param Wrapper.Controllable#CONTROLLABLE self
-- @return Wrapper.Controllable#CONTROLLABLE self
function CONTROLLABLE:OptionROEHoldFire()
self:F2( { self.ControllableName } )
@ -2114,7 +2115,7 @@ function CONTROLLABLE:OptionROTVertical()
end
--- Retrieve the controllable mission and allow to place function hooks within the mission waypoint plan.
-- Use the method @{Controllable#CONTROLLABLE:WayPointFunction} to define the hook functions for specific waypoints.
-- Use the method @{Wrapper.Controllable#CONTROLLABLE:WayPointFunction} to define the hook functions for specific waypoints.
-- Use the method @{Controllable@CONTROLLABLE:WayPointExecute) to start the execution of the new mission plan.
-- Note that when WayPointInitialize is called, the Mission of the controllable is RESTARTED!
-- @param #CONTROLLABLE self
@ -2154,7 +2155,7 @@ function CONTROLLABLE:TaskFunction( WayPoint, WayPointIndex, FunctionString, Fun
local DCSTask
local DCSScript = {}
DCSScript[#DCSScript+1] = "local MissionControllable = CONTROLLABLE:Find( ... ) "
DCSScript[#DCSScript+1] = "local MissionControllable = GROUP:Find( ... ) "
if FunctionArguments and #FunctionArguments > 0 then
DCSScript[#DCSScript+1] = FunctionString .. "( MissionControllable, " .. table.concat( FunctionArguments, "," ) .. ")"
@ -2202,118 +2203,4 @@ end
-- Message APIs
--- Returns a message with the callsign embedded (if there is one).
-- @param #CONTROLLABLE self
-- @param #string Message The message text
-- @param DCSTypes#Duration Duration The duration of the message.
-- @return Message#MESSAGE
function CONTROLLABLE:GetMessage( Message, Duration )
local DCSObject = self:GetDCSObject()
if DCSObject then
return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")" )
end
return nil
end
--- Send a message to all coalitions.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #CONTROLLABLE self
-- @param #string Message The message text
-- @param DCSTypes#Duration Duration The duration of the message.
function CONTROLLABLE:MessageToAll( Message, Duration )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToAll()
end
return nil
end
--- Send a message to the red coalition.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #CONTROLLABLE self
-- @param #string Message The message text
-- @param DCSTYpes#Duration Duration The duration of the message.
function CONTROLLABLE:MessageToRed( Message, Duration )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToRed()
end
return nil
end
--- Send a message to the blue coalition.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #CONTROLLABLE self
-- @param #string Message The message text
-- @param DCSTypes#Duration Duration The duration of the message.
function CONTROLLABLE:MessageToBlue( Message, Duration )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToBlue()
end
return nil
end
--- Send a message to a client.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #CONTROLLABLE self
-- @param #string Message The message text
-- @param DCSTypes#Duration Duration The duration of the message.
-- @param Client#CLIENT Client The client object receiving the message.
function CONTROLLABLE:MessageToClient( Message, Duration, Client )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToClient( Client )
end
return nil
end
--- Send a message to a @{Group}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #CONTROLLABLE self
-- @param #string Message The message text
-- @param DCSTypes#Duration Duration The duration of the message.
-- @param Group#GROUP MessageGroup The GROUP object receiving the message.
function CONTROLLABLE:MessageToGroup( Message, Duration, MessageGroup )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
if DCSObject:isExist() then
self:GetMessage( Message, Duration ):ToGroup( MessageGroup )
end
end
return nil
end
--- Send a message to the players in the @{Group}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #CONTROLLABLE self
-- @param #string Message The message text
-- @param DCSTypes#Duration Duration The duration of the message.
function CONTROLLABLE:Message( Message, Duration )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToGroup( self )
end
return nil
end

View File

@ -1,8 +1,8 @@
--- This module contains the GROUP class.
--
-- 1) @{Group#GROUP} class, extends @{Controllable#CONTROLLABLE}
-- 1) @{Wrapper.Group#GROUP} class, extends @{Wrapper.Controllable#CONTROLLABLE}
-- =============================================================
-- The @{Group#GROUP} class is a wrapper class to handle the DCS Group objects:
-- The @{Wrapper.Group#GROUP} class is a wrapper class to handle the DCS Group objects:
--
-- * Support all DCS Group APIs.
-- * Enhance with Group specific APIs not in the DCS Group API set.
@ -32,7 +32,7 @@
-- -----------------------
-- Several group task methods are available that help you to prepare tasks.
-- These methods return a string consisting of the task description, which can then be given to either a
-- @{Controllable#CONTROLLABLE.PushTask} or @{Controllable#CONTROLLABLE.SetTask} method to assign the task to the GROUP.
-- @{Wrapper.Controllable#CONTROLLABLE.PushTask} or @{Wrapper.Controllable#CONTROLLABLE.SetTask} method to assign the task to the GROUP.
-- Tasks are specific for the category of the GROUP, more specific, for AIR, GROUND or AIR and GROUND.
-- Each task description where applicable indicates for which group category the task is valid.
-- There are 2 main subdivisions of tasks: Assigned tasks and EnRoute tasks.
@ -44,63 +44,63 @@
--
-- Find below a list of the **assigned task** methods:
--
-- * @{Controllable#CONTROLLABLE.TaskAttackGroup}: (AIR) Attack a Group.
-- * @{Controllable#CONTROLLABLE.TaskAttackMapObject}: (AIR) Attacking the map object (building, structure, e.t.c).
-- * @{Controllable#CONTROLLABLE.TaskAttackUnit}: (AIR) Attack the Unit.
-- * @{Controllable#CONTROLLABLE.TaskBombing}: (Controllable#CONTROLLABLEDelivering weapon at the point on the ground.
-- * @{Controllable#CONTROLLABLE.TaskBombingRunway}: (AIR) Delivering weapon on the runway.
-- * @{Controllable#CONTROLLABLE.TaskEmbarking}: (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group.
-- * @{Controllable#CONTROLLABLE.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location.
-- * @{Controllable#CONTROLLABLE.TaskEscort}: (AIR) Escort another airborne group.
-- * @{Controllable#CONTROLLABLE.TaskFAC_AttackGroup}: (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction.
-- * @{Controllable#CONTROLLABLE.TaskFireAtPoint}: (GROUND) Fire at a VEC2 point until ammunition is finished.
-- * @{Controllable#CONTROLLABLE.TaskFollow}: (AIR) Following another airborne group.
-- * @{Controllable#CONTROLLABLE.TaskHold}: (GROUND) Hold ground group from moving.
-- * @{Controllable#CONTROLLABLE.TaskHoldPosition}: (AIR) Hold position at the current position of the first unit of the group.
-- * @{Controllable#CONTROLLABLE.TaskLand}: (AIR HELICOPTER) Landing at the ground. For helicopters only.
-- * @{Controllable#CONTROLLABLE.TaskLandAtZone}: (AIR) Land the group at a @{Zone#ZONE_RADIUS).
-- * @{Controllable#CONTROLLABLE.TaskOrbitCircle}: (AIR) Orbit at the current position of the first unit of the group at a specified alititude.
-- * @{Controllable#CONTROLLABLE.TaskOrbitCircleAtVec2}: (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed.
-- * @{Controllable#CONTROLLABLE.TaskRefueling}: (AIR) Refueling from the nearest tanker. No parameters.
-- * @{Controllable#CONTROLLABLE.TaskRoute}: (AIR + GROUND) Return a Misson task to follow a given route defined by Points.
-- * @{Controllable#CONTROLLABLE.TaskRouteToVec2}: (AIR + GROUND) Make the Group move to a given point.
-- * @{Controllable#CONTROLLABLE.TaskRouteToVec3}: (AIR + GROUND) Make the Group move to a given point.
-- * @{Controllable#CONTROLLABLE.TaskRouteToZone}: (AIR + GROUND) Route the group to a given zone.
-- * @{Controllable#CONTROLLABLE.TaskReturnToBase}: (AIR) Route the group to an airbase.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskAttackGroup}: (AIR) Attack a Group.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskAttackMapObject}: (AIR) Attacking the map object (building, structure, e.t.c).
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskAttackUnit}: (AIR) Attack the Unit.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskBombing}: (Wrapper.Controllable#CONTROLLABLEDelivering weapon at the point on the ground.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskBombingRunway}: (AIR) Delivering weapon on the runway.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskEmbarking}: (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskEscort}: (AIR) Escort another airborne group.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskFAC_AttackGroup}: (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskFireAtPoint}: (GROUND) Fire at a VEC2 point until ammunition is finished.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskFollow}: (AIR) Following another airborne group.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskHold}: (GROUND) Hold ground group from moving.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskHoldPosition}: (AIR) Hold position at the current position of the first unit of the group.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskLand}: (AIR HELICOPTER) Landing at the ground. For helicopters only.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskLandAtZone}: (AIR) Land the group at a @{Core.Zone#ZONE_RADIUS).
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskOrbitCircle}: (AIR) Orbit at the current position of the first unit of the group at a specified alititude.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskOrbitCircleAtVec2}: (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskRefueling}: (AIR) Refueling from the nearest tanker. No parameters.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskRoute}: (AIR + GROUND) Return a Misson task to follow a given route defined by Points.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskRouteToVec2}: (AIR + GROUND) Make the Group move to a given point.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskRouteToVec3}: (AIR + GROUND) Make the Group move to a given point.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskRouteToZone}: (AIR + GROUND) Route the group to a given zone.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskReturnToBase}: (AIR) Route the group to an airbase.
--
-- ### 1.2.2) EnRoute task methods
--
-- EnRoute tasks require the targets of the task need to be detected by the group (using its sensors) before the task can be executed:
--
-- * @{Controllable#CONTROLLABLE.EnRouteTaskAWACS}: (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters.
-- * @{Controllable#CONTROLLABLE.EnRouteTaskEngageGroup}: (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets.
-- * @{Controllable#CONTROLLABLE.EnRouteTaskEngageTargets}: (AIR) Engaging targets of defined types.
-- * @{Controllable#CONTROLLABLE.EnRouteTaskEWR}: (AIR) Attack the Unit.
-- * @{Controllable#CONTROLLABLE.EnRouteTaskFAC}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets.
-- * @{Controllable#CONTROLLABLE.EnRouteTaskFAC_EngageGroup}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets.
-- * @{Controllable#CONTROLLABLE.EnRouteTaskTanker}: (AIR) Aircraft will act as a tanker for friendly units. No parameters.
-- * @{Wrapper.Controllable#CONTROLLABLE.EnRouteTaskAWACS}: (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters.
-- * @{Wrapper.Controllable#CONTROLLABLE.EnRouteTaskEngageGroup}: (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets.
-- * @{Wrapper.Controllable#CONTROLLABLE.EnRouteTaskEngageTargets}: (AIR) Engaging targets of defined types.
-- * @{Wrapper.Controllable#CONTROLLABLE.EnRouteTaskEWR}: (AIR) Attack the Unit.
-- * @{Wrapper.Controllable#CONTROLLABLE.EnRouteTaskFAC}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets.
-- * @{Wrapper.Controllable#CONTROLLABLE.EnRouteTaskFAC_EngageGroup}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets.
-- * @{Wrapper.Controllable#CONTROLLABLE.EnRouteTaskTanker}: (AIR) Aircraft will act as a tanker for friendly units. No parameters.
--
-- ### 1.2.3) Preparation task methods
--
-- There are certain task methods that allow to tailor the task behaviour:
--
-- * @{Controllable#CONTROLLABLE.TaskWrappedAction}: Return a WrappedAction Task taking a Command.
-- * @{Controllable#CONTROLLABLE.TaskCombo}: Return a Combo Task taking an array of Tasks.
-- * @{Controllable#CONTROLLABLE.TaskCondition}: Return a condition section for a controlled task.
-- * @{Controllable#CONTROLLABLE.TaskControlled}: Return a Controlled Task taking a Task and a TaskCondition.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskWrappedAction}: Return a WrappedAction Task taking a Command.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskCombo}: Return a Combo Task taking an array of Tasks.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskCondition}: Return a condition section for a controlled task.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskControlled}: Return a Controlled Task taking a Task and a TaskCondition.
--
-- ### 1.2.4) Obtain the mission from group templates
--
-- Group templates contain complete mission descriptions. Sometimes you want to copy a complete mission from a group and assign it to another:
--
-- * @{Controllable#CONTROLLABLE.TaskMission}: (AIR + GROUND) Return a mission task from a mission template.
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskMission}: (AIR + GROUND) Return a mission task from a mission template.
--
-- 1.3) GROUP Command methods
-- --------------------------
-- Group **command methods** prepare the execution of commands using the @{Controllable#CONTROLLABLE.SetCommand} method:
-- Group **command methods** prepare the execution of commands using the @{Wrapper.Controllable#CONTROLLABLE.SetCommand} method:
--
-- * @{Controllable#CONTROLLABLE.CommandDoScript}: Do Script command.
-- * @{Controllable#CONTROLLABLE.CommandSwitchWayPoint}: Perform a switch waypoint command.
-- * @{Wrapper.Controllable#CONTROLLABLE.CommandDoScript}: Do Script command.
-- * @{Wrapper.Controllable#CONTROLLABLE.CommandSwitchWayPoint}: Perform a switch waypoint command.
--
-- 1.4) GROUP Option methods
-- -------------------------
@ -108,31 +108,31 @@
--
-- ### 1.4.1) Rule of Engagement:
--
-- * @{Controllable#CONTROLLABLE.OptionROEWeaponFree}
-- * @{Controllable#CONTROLLABLE.OptionROEOpenFire}
-- * @{Controllable#CONTROLLABLE.OptionROEReturnFire}
-- * @{Controllable#CONTROLLABLE.OptionROEEvadeFire}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROEWeaponFree}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROEOpenFire}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROEReturnFire}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROEEvadeFire}
--
-- To check whether an ROE option is valid for a specific group, use:
--
-- * @{Controllable#CONTROLLABLE.OptionROEWeaponFreePossible}
-- * @{Controllable#CONTROLLABLE.OptionROEOpenFirePossible}
-- * @{Controllable#CONTROLLABLE.OptionROEReturnFirePossible}
-- * @{Controllable#CONTROLLABLE.OptionROEEvadeFirePossible}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROEWeaponFreePossible}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROEOpenFirePossible}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROEReturnFirePossible}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROEEvadeFirePossible}
--
-- ### 1.4.2) Rule on thread:
--
-- * @{Controllable#CONTROLLABLE.OptionROTNoReaction}
-- * @{Controllable#CONTROLLABLE.OptionROTPassiveDefense}
-- * @{Controllable#CONTROLLABLE.OptionROTEvadeFire}
-- * @{Controllable#CONTROLLABLE.OptionROTVertical}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROTNoReaction}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROTPassiveDefense}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROTEvadeFire}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROTVertical}
--
-- To test whether an ROT option is valid for a specific group, use:
--
-- * @{Controllable#CONTROLLABLE.OptionROTNoReactionPossible}
-- * @{Controllable#CONTROLLABLE.OptionROTPassiveDefensePossible}
-- * @{Controllable#CONTROLLABLE.OptionROTEvadeFirePossible}
-- * @{Controllable#CONTROLLABLE.OptionROTVerticalPossible}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROTNoReactionPossible}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROTPassiveDefensePossible}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROTEvadeFirePossible}
-- * @{Wrapper.Controllable#CONTROLLABLE.OptionROTVerticalPossible}
--
-- 1.5) GROUP Zone validation methods
-- ----------------------------------
@ -143,14 +143,14 @@
-- * @{#GROUP.IsPartlyInZone}: Returns true if some units of the group are within a @{Zone}.
-- * @{#GROUP.IsNotInZone}: Returns true if none of the group units of the group are within a @{Zone}.
--
-- The zone can be of any @{Zone} class derived from @{Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on.
-- The zone can be of any @{Zone} class derived from @{Core.Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on.
--
-- @module Group
-- @author FlightControl
--- The GROUP class
-- @type GROUP
-- @extends Controllable#CONTROLLABLE
-- @extends Wrapper.Controllable#CONTROLLABLE
-- @field #string GroupName The name of the group.
GROUP = {
ClassName = "GROUP",
@ -158,7 +158,7 @@ GROUP = {
--- Create a new GROUP from a DCSGroup
-- @param #GROUP self
-- @param DCSGroup#Group GroupName The DCS Group name
-- @param Dcs.DCSWrapper.Group#Group GroupName The DCS Group name
-- @return #GROUP self
function GROUP:Register( GroupName )
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) )
@ -171,11 +171,11 @@ end
--- Find the GROUP wrapper class instance using the DCS Group.
-- @param #GROUP self
-- @param DCSGroup#Group DCSGroup The DCS Group.
-- @param Dcs.DCSWrapper.Group#Group DCSGroup The DCS Group.
-- @return #GROUP The GROUP.
function GROUP:Find( DCSGroup )
local GroupName = DCSGroup:getName() -- Group#GROUP
local GroupName = DCSGroup:getName() -- Wrapper.Group#GROUP
local GroupFound = _DATABASE:FindGroup( GroupName )
return GroupFound
end
@ -194,7 +194,7 @@ end
--- Returns the DCS Group.
-- @param #GROUP self
-- @return DCSGroup#Group The DCS Group.
-- @return Dcs.DCSWrapper.Group#Group The DCS Group.
function GROUP:GetDCSObject()
local DCSGroup = Group.getByName( self.GroupName )
@ -246,7 +246,7 @@ end
--- Returns category of the DCS Group.
-- @param #GROUP self
-- @return DCSGroup#Group.Category The category ID
-- @return Dcs.DCSWrapper.Group#Group.Category The category ID
function GROUP:GetCategory()
self:F2( self.GroupName )
@ -286,7 +286,7 @@ end
--- Returns the coalition of the DCS Group.
-- @param #GROUP self
-- @return DCSCoalitionObject#coalition.side The coalition side of the DCS Group.
-- @return Dcs.DCSCoalitionWrapper.Object#coalition.side The coalition side of the DCS Group.
function GROUP:GetCoalition()
self:F2( self.GroupName )
@ -302,7 +302,7 @@ end
--- Returns the country of the DCS Group.
-- @param #GROUP self
-- @return DCScountry#country.id The country identifier.
-- @return Dcs.DCScountry#country.id The country identifier.
-- @return #nil The DCS Group is not existing or alive.
function GROUP:GetCountry()
self:F2( self.GroupName )
@ -321,7 +321,7 @@ end
-- If the underlying DCS Unit does not exist, the method will return nil. .
-- @param #GROUP self
-- @param #number UnitNumber The number of the UNIT wrapper class to be returned.
-- @return Unit#UNIT The UNIT wrapper class.
-- @return Wrapper.Unit#UNIT The UNIT wrapper class.
function GROUP:GetUnit( UnitNumber )
self:F2( { self.GroupName, UnitNumber } )
@ -341,7 +341,7 @@ end
-- If the underlying DCS Unit does not exist, the method will return nil. .
-- @param #GROUP self
-- @param #number UnitNumber The number of the DCS Unit to be returned.
-- @return DCSUnit#Unit The DCS Unit.
-- @return Dcs.DCSWrapper.Unit#Unit The DCS Unit.
function GROUP:GetDCSUnit( UnitNumber )
self:F2( { self.GroupName, UnitNumber } )
@ -474,7 +474,7 @@ end
--- Returns the current point (Vec2 vector) of the first DCS Unit in the DCS Group.
-- @param #GROUP self
-- @return DCSTypes#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group.
-- @return Dcs.DCSTypes#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group.
function GROUP:GetVec2()
self:F2( self.GroupName )
@ -486,7 +486,7 @@ function GROUP:GetVec2()
end
--- Returns the current Vec3 vector of the first DCS Unit in the GROUP.
-- @return DCSTypes#Vec3 Current Vec3 of the first DCS Unit of the GROUP.
-- @return Dcs.DCSTypes#Vec3 Current Vec3 of the first DCS Unit of the GROUP.
function GROUP:GetVec3()
self:F2( self.GroupName )
@ -501,13 +501,13 @@ end
--- Returns true if all units of the group are within a @{Zone}.
-- @param #GROUP self
-- @param Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE}
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the Group is completely within the @{Core.Zone#ZONE_BASE}
function GROUP:IsCompletelyInZone( Zone )
self:F2( { self.GroupName, Zone } )
for UnitID, UnitData in pairs( self:GetUnits() ) do
local Unit = UnitData -- Unit#UNIT
local Unit = UnitData -- Wrapper.Unit#UNIT
-- TODO: Rename IsPointVec3InZone to IsVec3InZone
if Zone:IsPointVec3InZone( Unit:GetVec3() ) then
else
@ -520,13 +520,13 @@ end
--- Returns true if some units of the group are within a @{Zone}.
-- @param #GROUP self
-- @param Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE}
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the Group is completely within the @{Core.Zone#ZONE_BASE}
function GROUP:IsPartlyInZone( Zone )
self:F2( { self.GroupName, Zone } )
for UnitID, UnitData in pairs( self:GetUnits() ) do
local Unit = UnitData -- Unit#UNIT
local Unit = UnitData -- Wrapper.Unit#UNIT
if Zone:IsPointVec3InZone( Unit:GetVec3() ) then
return true
end
@ -537,13 +537,13 @@ end
--- Returns true if none of the group units of the group are within a @{Zone}.
-- @param #GROUP self
-- @param Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE}
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the Group is completely within the @{Core.Zone#ZONE_BASE}
function GROUP:IsNotInZone( Zone )
self:F2( { self.GroupName, Zone } )
for UnitID, UnitData in pairs( self:GetUnits() ) do
local Unit = UnitData -- Unit#UNIT
local Unit = UnitData -- Wrapper.Unit#UNIT
if Zone:IsPointVec3InZone( Unit:GetVec3() ) then
return false
end
@ -673,19 +673,19 @@ function GROUP:GetMaxVelocity()
local DCSGroup = self:GetDCSObject()
if DCSGroup then
local MaxVelocity = 0
local GroupVelocityMax = 0
for Index, UnitData in pairs( DCSGroup:getUnits() ) do
local Velocity = UnitData:getVelocity()
local VelocityTotal = math.abs( Velocity.x ) + math.abs( Velocity.y ) + math.abs( Velocity.z )
local UnitVelocityVec3 = UnitData:getVelocity()
local UnitVelocity = math.abs( UnitVelocityVec3.x ) + math.abs( UnitVelocityVec3.y ) + math.abs( UnitVelocityVec3.z )
if VelocityTotal < MaxVelocity then
MaxVelocity = VelocityTotal
if UnitVelocity > GroupVelocityMax then
GroupVelocityMax = UnitVelocity
end
end
return MaxVelocity
return GroupVelocityMax
end
return nil
@ -712,7 +712,7 @@ end
-- SPAWNING
--- Respawn the @{GROUP} using a (tweaked) template of the Group.
-- The template must be retrieved with the @{Group#GROUP.GetTemplate}() function.
-- The template must be retrieved with the @{Wrapper.Group#GROUP.GetTemplate}() function.
-- The template contains all the definitions as declared within the mission file.
-- To understand templates, do the following:
--
@ -728,7 +728,7 @@ end
-- * When the group is alive, it will tweak the template x, y and heading coordinates of the group and the embedded units to the current units positions.
-- * Then it will destroy the current alive group.
-- * And it will respawn the group using your new template definition.
-- @param Group#GROUP self
-- @param Wrapper.Group#GROUP self
-- @param #table Template The template of the Group retrieved with GROUP:GetTemplate()
function GROUP:Respawn( Template )
@ -740,7 +740,7 @@ function GROUP:Respawn( Template )
self:E( #Template.units )
for UnitID, UnitData in pairs( self:GetUnits() ) do
local GroupUnit = UnitData -- Unit#UNIT
local GroupUnit = UnitData -- Wrapper.Unit#UNIT
self:E( GroupUnit:GetName() )
if GroupUnit:IsAlive() then
local GroupUnitVec3 = GroupUnit:GetVec3()
@ -777,7 +777,7 @@ end
--- Sets the CountryID of the group in a Template.
-- @param #GROUP self
-- @param DCScountry#country.id CountryID The country ID.
-- @param Dcs.DCScountry#country.id CountryID The country ID.
-- @return #table
function GROUP:SetTemplateCountry( Template, CountryID )
Template.CountryID = CountryID
@ -786,7 +786,7 @@ end
--- Sets the CoalitionID of the group in a Template.
-- @param #GROUP self
-- @param DCSCoalitionObject#coalition.side CoalitionID The coalition ID.
-- @param Dcs.DCSCoalitionWrapper.Object#coalition.side CoalitionID The coalition ID.
-- @return #table
function GROUP:SetTemplateCoalition( Template, CoalitionID )
Template.CoalitionID = CoalitionID
@ -814,7 +814,7 @@ function GROUP:GetTaskRoute()
return routines.utils.deepCopy( _DATABASE.Templates.Groups[self.GroupName].Template.route.points )
end
--- Return the route of a group by using the @{Database#DATABASE} class.
--- Return the route of a group by using the @{Core.Database#DATABASE} class.
-- @param #GROUP self
-- @param #number Begin The route point from where the copy will start. The base route point is 0.
-- @param #number End The route point where the copy will end. The End point is the last point - the End point. The last point has base 0.

View File

@ -1,8 +1,8 @@
--- This module contains the IDENTIFIABLE class.
--
-- 1) @{Identifiable#IDENTIFIABLE} class, extends @{Object#OBJECT}
-- 1) @{#IDENTIFIABLE} class, extends @{Wrapper.Object#OBJECT}
-- ===============================================================
-- The @{Identifiable#IDENTIFIABLE} class is a wrapper class to handle the DCS Identifiable objects:
-- The @{#IDENTIFIABLE} class is a wrapper class to handle the DCS Identifiable objects:
--
-- * Support all DCS Identifiable APIs.
-- * Enhance with Identifiable specific APIs not in the DCS Identifiable API set.
@ -12,18 +12,18 @@
-- ------------------------------
-- The IDENTIFIABLE class provides the following functions to construct a IDENTIFIABLE instance:
--
-- * @{Identifiable#IDENTIFIABLE.New}(): Create a IDENTIFIABLE instance.
-- * @{#IDENTIFIABLE.New}(): Create a IDENTIFIABLE instance.
--
-- 1.2) IDENTIFIABLE methods:
-- --------------------------
-- The following methods can be used to identify an identifiable object:
--
-- * @{Identifiable#IDENTIFIABLE.GetName}(): Returns the name of the Identifiable.
-- * @{Identifiable#IDENTIFIABLE.IsAlive}(): Returns if the Identifiable is alive.
-- * @{Identifiable#IDENTIFIABLE.GetTypeName}(): Returns the type name of the Identifiable.
-- * @{Identifiable#IDENTIFIABLE.GetCoalition}(): Returns the coalition of the Identifiable.
-- * @{Identifiable#IDENTIFIABLE.GetCountry}(): Returns the country of the Identifiable.
-- * @{Identifiable#IDENTIFIABLE.GetDesc}(): Returns the descriptor structure of the Identifiable.
-- * @{#IDENTIFIABLE.GetName}(): Returns the name of the Identifiable.
-- * @{#IDENTIFIABLE.IsAlive}(): Returns if the Identifiable is alive.
-- * @{#IDENTIFIABLE.GetTypeName}(): Returns the type name of the Identifiable.
-- * @{#IDENTIFIABLE.GetCoalition}(): Returns the coalition of the Identifiable.
-- * @{#IDENTIFIABLE.GetCountry}(): Returns the country of the Identifiable.
-- * @{#IDENTIFIABLE.GetDesc}(): Returns the descriptor structure of the Identifiable.
--
--
-- ===
@ -33,7 +33,7 @@
--- The IDENTIFIABLE class
-- @type IDENTIFIABLE
-- @extends Object#OBJECT
-- @extends Wrapper.Object#OBJECT
-- @field #string IdentifiableName The name of the identifiable.
IDENTIFIABLE = {
ClassName = "IDENTIFIABLE",
@ -50,7 +50,7 @@ local _CategoryName = {
--- Create a new IDENTIFIABLE from a DCSIdentifiable
-- @param #IDENTIFIABLE self
-- @param DCSIdentifiable#Identifiable IdentifiableName The DCS Identifiable name
-- @param Dcs.DCSWrapper.Identifiable#Identifiable IdentifiableName The DCS Identifiable name
-- @return #IDENTIFIABLE self
function IDENTIFIABLE:New( IdentifiableName )
local self = BASE:Inherit( self, OBJECT:New( IdentifiableName ) )
@ -60,11 +60,11 @@ function IDENTIFIABLE:New( IdentifiableName )
end
--- Returns if the Identifiable is alive.
-- @param Identifiable#IDENTIFIABLE self
-- @param #IDENTIFIABLE self
-- @return #boolean true if Identifiable is alive.
-- @return #nil The DCS Identifiable is not existing or alive.
function IDENTIFIABLE:IsAlive()
self:F2( self.IdentifiableName )
self:F3( self.IdentifiableName )
local DCSIdentifiable = self:GetDCSObject()
@ -81,7 +81,7 @@ end
--- Returns DCS Identifiable object name.
-- The function provides access to non-activated objects too.
-- @param Identifiable#IDENTIFIABLE self
-- @param #IDENTIFIABLE self
-- @return #string The name of the DCS Identifiable.
-- @return #nil The DCS Identifiable is not existing or alive.
function IDENTIFIABLE:GetName()
@ -100,7 +100,7 @@ end
--- Returns the type name of the DCS Identifiable.
-- @param Identifiable#IDENTIFIABLE self
-- @param #IDENTIFIABLE self
-- @return #string The type name of the DCS Identifiable.
-- @return #nil The DCS Identifiable is not existing or alive.
function IDENTIFIABLE:GetTypeName()
@ -121,7 +121,7 @@ end
--- Returns category of the DCS Identifiable.
-- @param #IDENTIFIABLE self
-- @return DCSObject#Object.Category The category ID
-- @return Dcs.DCSWrapper.Object#Object.Category The category ID
function IDENTIFIABLE:GetCategory()
self:F2( self.ObjectName )
@ -137,7 +137,7 @@ end
--- Returns the DCS Identifiable category name as defined within the DCS Identifiable Descriptor.
-- @param Identifiable#IDENTIFIABLE self
-- @param #IDENTIFIABLE self
-- @return #string The DCS Identifiable Category Name
function IDENTIFIABLE:GetCategoryName()
local DCSIdentifiable = self:GetDCSObject()
@ -152,8 +152,8 @@ function IDENTIFIABLE:GetCategoryName()
end
--- Returns coalition of the Identifiable.
-- @param Identifiable#IDENTIFIABLE self
-- @return DCSCoalitionObject#coalition.side The side of the coalition.
-- @param #IDENTIFIABLE self
-- @return Dcs.DCSCoalitionWrapper.Object#coalition.side The side of the coalition.
-- @return #nil The DCS Identifiable is not existing or alive.
function IDENTIFIABLE:GetCoalition()
self:F2( self.IdentifiableName )
@ -171,8 +171,8 @@ function IDENTIFIABLE:GetCoalition()
end
--- Returns country of the Identifiable.
-- @param Identifiable#IDENTIFIABLE self
-- @return DCScountry#country.id The country identifier.
-- @param #IDENTIFIABLE self
-- @return Dcs.DCScountry#country.id The country identifier.
-- @return #nil The DCS Identifiable is not existing or alive.
function IDENTIFIABLE:GetCountry()
self:F2( self.IdentifiableName )
@ -192,8 +192,8 @@ end
--- Returns Identifiable descriptor. Descriptor type depends on Identifiable category.
-- @param Identifiable#IDENTIFIABLE self
-- @return DCSIdentifiable#Identifiable.Desc The Identifiable descriptor.
-- @param #IDENTIFIABLE self
-- @return Dcs.DCSWrapper.Identifiable#Identifiable.Desc The Identifiable descriptor.
-- @return #nil The DCS Identifiable is not existing or alive.
function IDENTIFIABLE:GetDesc()
self:F2( self.IdentifiableName )

View File

@ -1,8 +1,8 @@
--- This module contains the OBJECT class.
--
-- 1) @{Object#OBJECT} class, extends @{Base#BASE}
-- 1) @{Wrapper.Object#OBJECT} class, extends @{Core.Base#BASE}
-- ===========================================================
-- The @{Object#OBJECT} class is a wrapper class to handle the DCS Object objects:
-- The @{Wrapper.Object#OBJECT} class is a wrapper class to handle the DCS Object objects:
--
-- * Support all DCS Object APIs.
-- * Enhance with Object specific APIs not in the DCS Object API set.
@ -12,13 +12,13 @@
-- ------------------------------
-- The OBJECT class provides the following functions to construct a OBJECT instance:
--
-- * @{Object#OBJECT.New}(): Create a OBJECT instance.
-- * @{Wrapper.Object#OBJECT.New}(): Create a OBJECT instance.
--
-- 1.2) OBJECT methods:
-- --------------------------
-- The following methods can be used to identify an Object object:
--
-- * @{Object#OBJECT.GetID}(): Returns the ID of the Object object.
-- * @{Wrapper.Object#OBJECT.GetID}(): Returns the ID of the Object object.
--
-- ===
--
@ -27,7 +27,7 @@
--- The OBJECT class
-- @type OBJECT
-- @extends Base#BASE
-- @extends Core.Base#BASE
-- @field #string ObjectName The name of the Object.
OBJECT = {
ClassName = "OBJECT",
@ -41,7 +41,7 @@ OBJECT = {
--- Create a new OBJECT from a DCSObject
-- @param #OBJECT self
-- @param DCSObject#Object ObjectName The Object name
-- @param Dcs.DCSWrapper.Object#Object ObjectName The Object name
-- @return #OBJECT self
function OBJECT:New( ObjectName )
local self = BASE:Inherit( self, BASE:New() )
@ -52,8 +52,8 @@ end
--- Returns the unit's unique identifier.
-- @param Object#OBJECT self
-- @return DCSObject#Object.ID ObjectID
-- @param Wrapper.Object#OBJECT self
-- @return Dcs.DCSWrapper.Object#Object.ID ObjectID
-- @return #nil The DCS Object is not existing or alive.
function OBJECT:GetID()
self:F2( self.ObjectName )

View File

@ -0,0 +1,414 @@
--- This module contains the POSITIONABLE class.
--
-- 1) @{Wrapper.Positionable#POSITIONABLE} class, extends @{Wrapper.Identifiable#IDENTIFIABLE}
-- ===========================================================
-- The @{Wrapper.Positionable#POSITIONABLE} class is a wrapper class to handle the POSITIONABLE objects:
--
-- * Support all DCS APIs.
-- * Enhance with POSITIONABLE specific APIs not in the DCS API set.
-- * Manage the "state" of the POSITIONABLE.
--
-- 1.1) POSITIONABLE constructor:
-- ------------------------------
-- The POSITIONABLE class provides the following functions to construct a POSITIONABLE instance:
--
-- * @{Wrapper.Positionable#POSITIONABLE.New}(): Create a POSITIONABLE instance.
--
-- 1.2) POSITIONABLE methods:
-- --------------------------
-- The following methods can be used to identify an measurable object:
--
-- * @{Wrapper.Positionable#POSITIONABLE.GetID}(): Returns the ID of the measurable object.
-- * @{Wrapper.Positionable#POSITIONABLE.GetName}(): Returns the name of the measurable object.
--
-- ===
--
-- @module Positionable
-- @author FlightControl
--- The POSITIONABLE class
-- @type POSITIONABLE
-- @extends Wrapper.Identifiable#IDENTIFIABLE
-- @field #string PositionableName The name of the measurable.
POSITIONABLE = {
ClassName = "POSITIONABLE",
PositionableName = "",
}
--- A DCSPositionable
-- @type DCSPositionable
-- @field id_ The ID of the controllable in DCS
--- Create a new POSITIONABLE from a DCSPositionable
-- @param #POSITIONABLE self
-- @param Dcs.DCSWrapper.Positionable#Positionable PositionableName The POSITIONABLE name
-- @return #POSITIONABLE self
function POSITIONABLE:New( PositionableName )
local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) )
return self
end
--- Returns the @{Dcs.DCSTypes#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPositionVec3()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePosition = DCSPositionable:getPosition()
self:T3( PositionablePosition )
return PositionablePosition
end
return nil
end
--- Returns the @{Dcs.DCSTypes#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Dcs.DCSTypes#Vec2 The 2D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVec2()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
local PositionableVec2 = {}
PositionableVec2.x = PositionableVec3.x
PositionableVec2.y = PositionableVec3.z
self:T2( PositionableVec2 )
return PositionableVec2
end
return nil
end
--- Returns a POINT_VEC2 object indicating the point in 2D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Core.Point#POINT_VEC2 The 2D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPointVec2()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
local PositionablePointVec2 = POINT_VEC2:NewFromVec3( PositionableVec3 )
self:T2( PositionablePointVec2 )
return PositionablePointVec2
end
return nil
end
--- Returns a random @{Dcs.DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Dcs.DCSTypes#Vec3 The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetRandomVec3( Radius )
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePointVec3 = DCSPositionable:getPosition().p
local PositionableRandomVec3 = {}
local angle = math.random() * math.pi*2;
PositionableRandomVec3.x = PositionablePointVec3.x + math.cos( angle ) * math.random() * Radius;
PositionableRandomVec3.y = PositionablePointVec3.y
PositionableRandomVec3.z = PositionablePointVec3.z + math.sin( angle ) * math.random() * Radius;
self:T3( PositionableRandomVec3 )
return PositionableRandomVec3
end
return nil
end
--- Returns the @{Dcs.DCSTypes#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Dcs.DCSTypes#Vec3 The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVec3()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
self:T3( PositionableVec3 )
return PositionableVec3
end
return nil
end
--- Returns the altitude of the POSITIONABLE.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Dcs.DCSTypes#Distance The altitude of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetAltitude()
self:F2()
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePointVec3 = DCSPositionable:getPoint() --Dcs.DCSTypes#Vec3
return PositionablePointVec3.y
end
return nil
end
--- Returns if the Positionable is located above a runway.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return #boolean true if Positionable is above a runway.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:IsAboveRunway()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local Vec2 = self:GetVec2()
local SurfaceType = land.getSurfaceType( Vec2 )
local IsAboveRunway = SurfaceType == land.SurfaceType.RUNWAY
self:T2( IsAboveRunway )
return IsAboveRunway
end
return nil
end
--- Returns the POSITIONABLE heading in degrees.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return #number The POSTIONABLE heading
function POSITIONABLE:GetHeading()
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePosition = DCSPositionable:getPosition()
if PositionablePosition then
local PositionableHeading = math.atan2( PositionablePosition.x.z, PositionablePosition.x.x )
if PositionableHeading < 0 then
PositionableHeading = PositionableHeading + 2 * math.pi
end
PositionableHeading = PositionableHeading * 180 / math.pi
self:T2( PositionableHeading )
return PositionableHeading
end
end
return nil
end
--- Returns true if the POSITIONABLE is in the air.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return #boolean true if in the air.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:InAir()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableInAir = DCSPositionable:inAir()
self:T3( PositionableInAir )
return PositionableInAir
end
return nil
end
--- Returns the POSITIONABLE velocity vector.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Dcs.DCSTypes#Vec3 The velocity vector
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVelocity()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVelocityVec3 = DCSPositionable:getVelocity()
self:T3( PositionableVelocityVec3 )
return PositionableVelocityVec3
end
return nil
end
--- Returns the POSITIONABLE velocity in km/h.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return #number The velocity in km/h
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVelocityKMH()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local VelocityVec3 = self:GetVelocity()
local Velocity = ( VelocityVec3.x ^ 2 + VelocityVec3.y ^ 2 + VelocityVec3.z ^ 2 ) ^ 0.5 -- in meters / sec
local Velocity = Velocity * 3.6 -- now it is in km/h.
self:T3( Velocity )
return Velocity
end
return nil
end
--- Returns a message with the callsign embedded (if there is one).
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTypes#Duration Duration The duration of the message.
-- @return Core.Message#MESSAGE
function POSITIONABLE:GetMessage( Message, Duration )
local DCSObject = self:GetDCSObject()
if DCSObject then
return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")" )
end
return nil
end
--- Send a message to all coalitions.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTypes#Duration Duration The duration of the message.
function POSITIONABLE:MessageToAll( Message, Duration )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToAll()
end
return nil
end
--- Send a message to a coalition.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTYpes#Duration Duration The duration of the message.
function POSITIONABLE:MessageToCoalition( Message, Duration, MessageCoalition )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToCoalition( MessageCoalition )
end
return nil
end
--- Send a message to the red coalition.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTYpes#Duration Duration The duration of the message.
function POSITIONABLE:MessageToRed( Message, Duration )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToRed()
end
return nil
end
--- Send a message to the blue coalition.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTypes#Duration Duration The duration of the message.
function POSITIONABLE:MessageToBlue( Message, Duration )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToBlue()
end
return nil
end
--- Send a message to a client.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTypes#Duration Duration The duration of the message.
-- @param Wrapper.Client#CLIENT Client The client object receiving the message.
function POSITIONABLE:MessageToClient( Message, Duration, Client )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToClient( Client )
end
return nil
end
--- Send a message to a @{Group}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTypes#Duration Duration The duration of the message.
-- @param Wrapper.Group#GROUP MessageGroup The GROUP object receiving the message.
function POSITIONABLE:MessageToGroup( Message, Duration, MessageGroup )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
if DCSObject:isExist() then
self:GetMessage( Message, Duration ):ToGroup( MessageGroup )
end
end
return nil
end
--- Send a message to the players in the @{Group}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTypes#Duration Duration The duration of the message.
function POSITIONABLE:Message( Message, Duration )
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
self:GetMessage( Message, Duration ):ToGroup( self )
end
return nil
end

View File

@ -1,10 +1,10 @@
--- This module contains the STATIC class.
--
-- 1) @{Static#STATIC} class, extends @{Positionable#POSITIONABLE}
-- 1) @{Wrapper.Static#STATIC} class, extends @{Wrapper.Positionable#POSITIONABLE}
-- ===============================================================
-- Statics are **Static Units** defined within the Mission Editor.
-- Note that Statics are almost the same as Units, but they don't have a controller.
-- The @{Static#STATIC} class is a wrapper class to handle the DCS Static objects:
-- The @{Wrapper.Static#STATIC} class is a wrapper class to handle the DCS Static objects:
--
-- * Wraps the DCS Static objects.
-- * Support all DCS Static APIs.
@ -38,7 +38,7 @@
--- The STATIC class
-- @type STATIC
-- @extends Positionable#POSITIONABLE
-- @extends Wrapper.Positionable#POSITIONABLE
STATIC = {
ClassName = "STATIC",
}

View File

@ -1,8 +1,8 @@
--- This module contains the UNIT class.
--
-- 1) @{Unit#UNIT} class, extends @{Controllable#CONTROLLABLE}
-- 1) @{#UNIT} class, extends @{Wrapper.Controllable#CONTROLLABLE}
-- ===========================================================
-- The @{Unit#UNIT} class is a wrapper class to handle the DCS Unit objects:
-- The @{#UNIT} class is a wrapper class to handle the DCS Unit objects:
--
-- * Support all DCS Unit APIs.
-- * Enhance with Unit specific APIs not in the DCS Unit API set.
@ -33,7 +33,7 @@
-- ------------------
-- The DCS Unit APIs are used extensively within MOOSE. The UNIT class has for each DCS Unit API a corresponding method.
-- To be able to distinguish easily in your code the difference between a UNIT API call and a DCS Unit API call,
-- the first letter of the method is also capitalized. So, by example, the DCS Unit method @{DCSUnit#Unit.getName}()
-- the first letter of the method is also capitalized. So, by example, the DCS Unit method @{Dcs.DCSWrapper.Unit#Unit.getName}()
-- is implemented in the UNIT class as @{#UNIT.GetName}().
--
-- 1.3) Smoke, Flare Units
@ -60,7 +60,7 @@
-- The UNIT class contains methods to test the location or proximity against zones or other objects.
--
-- ### 1.6.1) Zones
-- To test whether the Unit is within a **zone**, use the @{#UNIT.IsInZone}() or the @{#UNIT.IsNotInZone}() methods. Any zone can be tested on, but the zone must be derived from @{Zone#ZONE_BASE}.
-- To test whether the Unit is within a **zone**, use the @{#UNIT.IsInZone}() or the @{#UNIT.IsNotInZone}() methods. Any zone can be tested on, but the zone must be derived from @{Core.Zone#ZONE_BASE}.
--
-- ### 1.6.2) Units
-- Test if another DCS Unit is within a given radius of the current DCS Unit, use the @{#UNIT.OtherUnitInRadius}() method.
@ -74,40 +74,11 @@
--- The UNIT class
-- @type UNIT
-- @extends Controllable#CONTROLLABLE
-- @field #UNIT.FlareColor FlareColor
-- @field #UNIT.SmokeColor SmokeColor
-- @extends Wrapper.Controllable#CONTROLLABLE
UNIT = {
ClassName="UNIT",
FlareColor = {
Green = trigger.flareColor.Green,
Red = trigger.flareColor.Red,
White = trigger.flareColor.White,
Yellow = trigger.flareColor.Yellow
},
SmokeColor = {
Green = trigger.smokeColor.Green,
Red = trigger.smokeColor.Red,
White = trigger.smokeColor.White,
Orange = trigger.smokeColor.Orange,
Blue = trigger.smokeColor.Blue
},
}
}
--- FlareColor
-- @type UNIT.FlareColor
-- @field Green
-- @field Red
-- @field White
-- @field Yellow
--- SmokeColor
-- @type UNIT.SmokeColor
-- @field Green
-- @field Red
-- @field White
-- @field Orange
-- @field Blue
--- Unit.SensorType
-- @type Unit.SensorType
@ -122,7 +93,7 @@ UNIT = {
--- Create a new UNIT from DCSUnit.
-- @param #UNIT self
-- @param #string UnitName The name of the DCS unit.
-- @return Unit#UNIT
-- @return #UNIT
function UNIT:Register( UnitName )
local self = BASE:Inherit( self, CONTROLLABLE:New( UnitName ) )
self.UnitName = UnitName
@ -133,8 +104,8 @@ end
--- Finds a UNIT from the _DATABASE using a DCSUnit object.
-- @param #UNIT self
-- @param DCSUnit#Unit DCSUnit An existing DCS Unit object reference.
-- @return Unit#UNIT self
-- @param Dcs.DCSWrapper.Unit#Unit DCSUnit An existing DCS Unit object reference.
-- @return #UNIT self
function UNIT:Find( DCSUnit )
local UnitName = DCSUnit:getName()
@ -145,7 +116,7 @@ end
--- Find a UNIT in the _DATABASE using the name of an existing DCS Unit.
-- @param #UNIT self
-- @param #string UnitName The Unit Name.
-- @return Unit#UNIT self
-- @return #UNIT self
function UNIT:FindByName( UnitName )
local UnitFound = _DATABASE:FindUnit( UnitName )
@ -162,7 +133,7 @@ end
--- @param #UNIT self
-- @return DCSUnit#Unit
-- @return Dcs.DCSWrapper.Unit#Unit
function UNIT:GetDCSObject()
local DCSUnit = Unit.getByName( self.UnitName )
@ -182,24 +153,25 @@ end
-- * When the unit is alive, it will tweak the template x, y and heading coordinates of the group and the embedded units to the current units positions.
-- * Then it will respawn the re-modelled group.
--
-- @param Unit#UNIT self
-- @param DCSTypes#Vec3 SpawnVec3 The position where to Spawn the new Unit at.
-- @param #UNIT self
-- @param Dcs.DCSTypes#Vec3 SpawnVec3 The position where to Spawn the new Unit at.
-- @param #number Heading The heading of the unit respawn.
function UNIT:ReSpawn( SpawnVec3, Heading )
local SpawnGroupTemplate = UTILS.DeepCopy( _DATABASE:GetGroupTemplateFromUnitName( self:Name() ) )
self:T( SpawnGroupTemplate )
local SpawnGroup = self:GetGroup()
if SpawnGroup then
local Vec3 = SpawnGroup:GetVec3()
SpawnGroupTemplate.x = Vec3.x
SpawnGroupTemplate.y = Vec3.z
SpawnGroupTemplate.x = SpawnVec3.x
SpawnGroupTemplate.y = SpawnVec3.z
self:E( #SpawnGroupTemplate.units )
for UnitID, UnitData in pairs( SpawnGroup:GetUnits() ) do
local GroupUnit = UnitData -- Unit#UNIT
local GroupUnit = UnitData -- #UNIT
self:E( GroupUnit:GetName() )
if GroupUnit:IsAlive() then
local GroupUnitVec3 = GroupUnit:GetVec3()
@ -222,6 +194,36 @@ function UNIT:ReSpawn( SpawnVec3, Heading )
SpawnGroupTemplate.units[UnitTemplateID].y = SpawnVec3.z
SpawnGroupTemplate.units[UnitTemplateID].heading = Heading
self:E( { UnitTemplateID, SpawnGroupTemplate.units[UnitTemplateID], SpawnGroupTemplate.units[UnitTemplateID] } )
else
self:E( SpawnGroupTemplate.units[UnitTemplateID].name )
local GroupUnit = UNIT:FindByName( SpawnGroupTemplate.units[UnitTemplateID].name ) -- #UNIT
if GroupUnit and GroupUnit:IsAlive() then
local GroupUnitVec3 = GroupUnit:GetVec3()
local GroupUnitHeading = GroupUnit:GetHeading()
UnitTemplateData.alt = GroupUnitVec3.y
UnitTemplateData.x = GroupUnitVec3.x
UnitTemplateData.y = GroupUnitVec3.z
UnitTemplateData.heading = GroupUnitHeading
else
if SpawnGroupTemplate.units[UnitTemplateID].name ~= self:Name() then
self:T("nilling")
SpawnGroupTemplate.units[UnitTemplateID].delete = true
end
end
end
end
-- Remove obscolete units from the group structure
i = 1
while i <= #SpawnGroupTemplate.units do
local UnitTemplateData = SpawnGroupTemplate.units[i]
self:T( UnitTemplateData.name )
if UnitTemplateData.delete then
table.remove( SpawnGroupTemplate.units, i )
else
i = i + 1
end
end
@ -231,7 +233,7 @@ end
--- Returns if the unit is activated.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #boolean true if Unit is activated.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:IsActive()
@ -251,7 +253,7 @@ end
--- Returns the Unit's callsign - the localized string.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #string The Callsign of the Unit.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetCallsign()
@ -270,7 +272,7 @@ end
--- Returns name of the player that control the unit or nil if the unit is controlled by A.I.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #string Player Name
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetPlayerName()
@ -294,7 +296,7 @@ end
-- The number is the same number the unit has in ME.
-- It may not be changed during the mission.
-- If any unit in the group is destroyed, the numbers of another units will not be changed.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #number The Unit number.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetNumber()
@ -311,8 +313,8 @@ function UNIT:GetNumber()
end
--- Returns the unit's group if it exist and nil otherwise.
-- @param Unit#UNIT self
-- @return Group#GROUP The Group of the Unit.
-- @param Wrapper.Unit#UNIT self
-- @return Wrapper.Group#GROUP The Group of the Unit.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetGroup()
self:F2( self.UnitName )
@ -333,7 +335,7 @@ end
--- Returns the prefix name of the DCS Unit. A prefix name is a part of the name before a '#'-sign.
-- DCS Units spawned with the @{SPAWN} class contain a '#'-sign to indicate the end of the (base) DCS Unit name.
-- The spawn sequence number and unit number are contained within the name after the '#' sign.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #string The name of the DCS Unit.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetPrefix()
@ -351,8 +353,8 @@ function UNIT:GetPrefix()
end
--- Returns the Unit's ammunition.
-- @param Unit#UNIT self
-- @return DCSUnit#Unit.Ammo
-- @param #UNIT self
-- @return Dcs.DCSWrapper.Unit#Unit.Ammo
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetAmmo()
self:F2( self.UnitName )
@ -368,8 +370,8 @@ function UNIT:GetAmmo()
end
--- Returns the unit sensors.
-- @param Unit#UNIT self
-- @return DCSUnit#Unit.Sensors
-- @param #UNIT self
-- @return Dcs.DCSWrapper.Unit#Unit.Sensors
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetSensors()
self:F2( self.UnitName )
@ -388,7 +390,7 @@ end
-- unit:hasSensors(Unit.SensorType.RADAR, Unit.RadarType.AS)
--- Returns if the unit has sensors of a certain type.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #boolean returns true if the unit has specified types of sensors. This function is more preferable than Unit.getSensors() if you don't want to get information about all the unit's sensors, and just want to check if the unit has specified types of sensors.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:HasSensors( ... )
@ -405,7 +407,7 @@ function UNIT:HasSensors( ... )
end
--- Returns if the unit is SEADable.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #boolean returns true if the unit is SEADable.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:HasSEAD()
@ -431,9 +433,9 @@ end
--
-- * First value indicates if at least one of the unit's radar(s) is on.
-- * Second value is the object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #boolean Indicates if at least one of the unit's radar(s) is on.
-- @return DCSObject#Object The object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
-- @return Dcs.DCSWrapper.Object#Object The object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetRadar()
self:F2( self.UnitName )
@ -449,7 +451,7 @@ function UNIT:GetRadar()
end
--- Returns relative amount of fuel (from 0.0 to 1.0) the unit has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #number The relative amount of fuel (from 0.0 to 1.0).
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetFuel()
@ -466,7 +468,7 @@ function UNIT:GetFuel()
end
--- Returns the unit's health. Dead units has health <= 1.0.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #number The Unit's health value.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetLife()
@ -483,7 +485,7 @@ function UNIT:GetLife()
end
--- Returns the Unit's initial health.
-- @param Unit#UNIT self
-- @param #UNIT self
-- @return #number The Unit's initial health value.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetLife0()
@ -560,8 +562,8 @@ end
--- Returns true if the unit is within a @{Zone}.
-- @param #UNIT self
-- @param Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the unit is within the @{Zone#ZONE_BASE}
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the unit is within the @{Core.Zone#ZONE_BASE}
function UNIT:IsInZone( Zone )
self:F2( { self.UnitName, Zone } )
@ -577,8 +579,8 @@ end
--- Returns true if the unit is not within a @{Zone}.
-- @param #UNIT self
-- @param Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the unit is not within the @{Zone#ZONE_BASE}
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the unit is not within the @{Core.Zone#ZONE_BASE}
function UNIT:IsNotInZone( Zone )
self:F2( { self.UnitName, Zone } )
@ -594,8 +596,8 @@ end
--- Returns true if there is an **other** DCS Unit within a radius of the current 2D point of the DCS Unit.
-- @param Unit#UNIT self
-- @param Unit#UNIT AwaitUnit The other UNIT wrapper object.
-- @param #UNIT self
-- @param #UNIT AwaitUnit The other UNIT wrapper object.
-- @param Radius The radius in meters with the DCS Unit in the centre.
-- @return true If the other DCS Unit is within the radius of the 2D point of the DCS Unit.
-- @return #nil The DCS Unit is not existing or alive.
@ -624,6 +626,7 @@ end
--- Signal a flare at the position of the UNIT.
-- @param #UNIT self
-- @param Utilities.Utils#FLARECOLOR FlareColor
function UNIT:Flare( FlareColor )
self:F2()
trigger.action.signalFlare( self:GetVec3(), FlareColor , 0 )

View File

@ -43,7 +43,7 @@ end
--- Handle the S_EVENT_DEAD events to validate the destruction of units for the task monitoring.
-- @param #DESTROYBASETASK self
-- @param Event#EVENTDATA Event structure of MOOSE.
-- @param Core.Event#EVENTDATA Event structure of MOOSE.
function DESTROYBASETASK:EventDead( Event )
self:F( { Event } )

View File

@ -32,8 +32,8 @@ end
--- Report Goal Progress.
-- @param #DESTROYGROUPSTASK self
-- @param DCSGroup#Group DestroyGroup Group structure describing the group to be evaluated.
-- @param DCSUnit#Unit DestroyUnit Unit structure describing the Unit to be evaluated.
-- @param Dcs.DCSWrapper.Group#Group DestroyGroup Group structure describing the group to be evaluated.
-- @param Dcs.DCSWrapper.Unit#Unit DestroyUnit Unit structure describing the Unit to be evaluated.
-- @return #number The DestroyCount reflecting the amount of units destroyed within the group.
function DESTROYGROUPSTASK:ReportGoalProgress( DestroyGroup, DestroyUnit )
self:F( { DestroyGroup, DestroyUnit, self.DestroyPercentage } )

View File

@ -68,9 +68,9 @@ end
--- Execute
-- @param #STAGEBRIEF self
-- @param Mission#MISSION Mission
-- @param Client#CLIENT Client
-- @param Task#TASK Task
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Client#CLIENT Client
-- @param Tasking.Task#TASK Task
-- @return #boolean
function STAGEBRIEF:Execute( Mission, Client, Task )
local Valid = BASE:Inherited(self):Execute( Mission, Client, Task )
@ -228,9 +228,9 @@ end
--- Execute the routing.
-- @param #STAGEROUTE self
-- @param Mission#MISSION Mission
-- @param Client#CLIENT Client
-- @param Task#TASK Task
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Client#CLIENT Client
-- @param Tasking.Task#TASK Task
function STAGEROUTE:Execute( Mission, Client, Task )
self:F()
local Valid = BASE:Inherited(self):Execute( Mission, Client, Task )
@ -300,9 +300,9 @@ end
--- Execute the landing coordination.
-- @param #STAGELANDING self
-- @param Mission#MISSION Mission
-- @param Client#CLIENT Client
-- @param Task#TASK Task
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Client#CLIENT Client
-- @param Tasking.Task#TASK Task
function STAGELANDING:Execute( Mission, Client, Task )
self:F()
@ -524,9 +524,9 @@ end
--- Coordinate UnLoading
-- @param #STAGEUNLOAD self
-- @param Mission#MISSION Mission
-- @param Client#CLIENT Client
-- @param Task#TASK Task
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Client#CLIENT Client
-- @param Tasking.Task#TASK Task
function STAGEUNLOAD:Execute( Mission, Client, Task )
self:F()
@ -562,9 +562,9 @@ end
--- Validate UnLoading
-- @param #STAGEUNLOAD self
-- @param Mission#MISSION Mission
-- @param Client#CLIENT Client
-- @param Task#TASK Task
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Client#CLIENT Client
-- @param Tasking.Task#TASK Task
function STAGEUNLOAD:Validate( Mission, Client, Task )
self:F()
env.info( 'STAGEUNLOAD:Validate()' )
@ -835,9 +835,9 @@ end
--- Execute Arrival
-- @param #STAGEARRIVE self
-- @param Mission#MISSION Mission
-- @param Client#CLIENT Client
-- @param Task#TASK Task
-- @param Tasking.Mission#MISSION Mission
-- @param Wrapper.Client#CLIENT Client
-- @param Tasking.Task#TASK Task
function STAGEARRIVE:Execute( Mission, Client, Task )
self:F()
@ -915,7 +915,7 @@ end
_TransportStage: Defines the different stages of which of transport missions can be in. This table is internal and is used to control the sequence of messages, actions and flow.
- _TransportStage.START
- _TransportStage.ROUTE
- _TransportStage.ACT_ROUTE
- _TransportStage.LAND
- _TransportStage.EXECUTE
- _TransportStage.DONE
@ -924,7 +924,7 @@ end
_TransportStage = {
HOLD = "HOLD",
START = "START",
ROUTE = "ROUTE",
ACT_ROUTE = "ACT_ROUTE",
LANDING = "LANDING",
LANDED = "LANDED",
EXECUTING = "EXECUTING",
@ -937,7 +937,7 @@ _TransportStage = {
_TransportStageMsgTime = {
HOLD = 10,
START = 60,
ROUTE = 5,
ACT_ROUTE = 5,
LANDING = 10,
LANDED = 30,
EXECUTING = 30,
@ -950,7 +950,7 @@ _TransportStageMsgTime = {
_TransportStageTime = {
HOLD = 10,
START = 5,
ROUTE = 5,
ACT_ROUTE = 5,
LANDING = 1,
LANDED = 1,
EXECUTING = 5,

View File

@ -1,19 +1,127 @@
2016-12-06
- Renamed the documentation references following the structure of the files.
-- All STATEMACHINE references became FSM
-- FSM_TEMPLATE references are also abbreviated by FSMT
-- Removed Process#PROCESS references.
-- All cross file documentation references updated. That was a lot of work!
- Tasking is working now. But needs further cleanup.
- Templates are assigned to Tasks. When a task is assigned to a player, the FSMT
- Removed 2nd level in tasking. Now there is only one level.
- Tasking works now with FSM.
- Made FSMT process templates that can be used in Tasks.
- Scoring can now also be added to the templates.
2016-09-01
- Expanded the CARGO classes and implemented the CARGO_GROUPED classes.
-- Finished the correct state machine implementation to Board, UnBoard, Load, UnLoad cargo to and from carriers.
-- Created the CARGO_GROUPED class, which groups CARGO_UNITs into one group. The cargo behaves like groups, but can be transported by carriers.
-- Documented CARGO event functions, state transition functions + overall documentation.
-- Updated test missions located in the directory: Moose_Test_CARGO
- Expanded the PROCESS_PATROLZONE class.
2016-08-21
- Made a new STATEMACHINE_CONTROLLABLE object, which models a base state machine class to be inherited by AI controllable classes.
-- Created the class as such that intherited AI classes become "finite state machines".
-- Each STATEMACHINE_CONTROLLABLE class contains a Controllable object, which is one Unit, Client or Group object.
-- Added state transition functions that are called before and after the state transition.
-- Event functions are automatically added to the class, based on the FSMT.
-- Added immediate and delayed event processing as part of the STATEMACHINE_CONTROLLABLE class.
--- Events that start with __Event are processed with a delay. The delay is given in seconds as a parameter.
- Created a new PROCESS_PATROLZONE class, which inherites STATEMACHINE_CONTROLLABLE.
-- This class implements a complete new revamped patrol zone AI pattern.
-- Created a new test directory: Moose_Test_PROCESS_PATROLZONE with test missions.
2016-08-15
- Removed the old classes and moved into an "Old" folder in the Moose/Development folder.
-- Cleaned Moose.lua + Documented class types
-- Cleaned Create_Moose.bat + Documented class types
- Extend the ZONE_BASE class with a probability randomization factor, that can be used for zone randomization purposes.
- Documented the Zone module classes.
- Changed and removed the POINT_VEC3 SmokeColor and FlareColor structure. Replaced with SMOKECOLOR and FLARECOLOR types.
-- Replaced also code in test missions with SMOKECOLOR and FLARECOLOR references.
- Added change logs of API changes in MOOSE documentation.
- Added ZONE_BASE:GetName() method.
- Added ZONE_BASE:GetZoneProbability() method.
- Added ZONE_BASE:SetZoneProbability() method.
- Added ZONE_BASE:GetZoneMaybe() method.
- Added SPAWN:InitRandomizeZones() method.
- Renamed SPAWN:CleanUp() method to SPAWN:InitCleanUp() method.
- Reviewed documentation of the PatrolZone module and PATROLZONE class.
2016-08-14
- Changed Spawn APIs to express Group position and Unit position randomization.
- Changed the API protocol of SpawnInZone() method.
-- Removed OuterRadius and InnerRadius parameters !!!
- Changed the API protocol of SpawnFromUnit() method.
-- Removed OuterRadius and InnerRadius parameters !!!
- Added InitRandomizeUnits() method, taking 3 parameters:
-- RandomizeUnits given the value true, will randomize the units upon spawning, false (default) will not randomize the untis.
-- OuterRadius is the outer radius of the band where the units will be spawned, if RandomizeUnits is true.
-- InnerRadius is the inner radius of the band where the units will not be spawned, if RandomizeUnits is true.
- Removed SpawnFunction() method.
- Added OnSpawnGroup() method as the new official CallBack function method to catch when a new function will be called.
-- Documented OnSpawnGroup() method.
- Renamed Limit() method to InitLimit() method.
- Renamed Array() method to InitArray() method.
- Renamed RandomizeRoute() method to InitRandomizeRoute() method.
- Renamed RandomizeTemplate() method to InitRandomizeTemplate() method.
- Renamed UnControlled() method to InitUnControlled method.
- Reviewed all test missions for the changes executed and made adaptions where necessary + re-tests.
2016-08-12
- Temporary release of the new cargo handling.
-- Released available functionality to handle one CARGO_UNIT loading, boarding, unloading.
-- Created CARGO_UNIT test missions.
- Added Translate() method in POINT_VEC3, translating a 3D point over the horizontal plane with a Distance and Angle coordinate.
2016-08-08
- Added briefing to method ESCORT:New()
-- If no EscortBriefing is given, the New() method will show the default briefing.
2016-08-06
- Made PointVec3 and Vec3, PointVec2 and Vec2 terminology used in the code consistent.
-- Replaced method PointVec3() to Vec3() where the code manages a Vec3. Replaced all references to the method.
-- Replaced method PointVec2() to Vec2() where the code manages a Vec2. Replaced all references to the method.
-- Replaced method RandomPointVec3() to RandomVec3() where the code manages a Vec3. Replaced all references to the method.
2016-08-03
- Fixed error at SPAWN:RandomizeTemplate()
-- Units started in wrong x, y position (at the template, instead of at the master template of the SPAWN).
-- Adjusted x, y and alt to the start position of the first unit of the master template.
@ -21,9 +129,11 @@
-- Regenerated MOOSE.lua
2016-07-31
- Added a SpawnHeight parameter to the SPAWN method RandomizeRoute(), based upon a bug report of David. Air units will now also have optionally the route height randomized.
2016-07-29
- Documentation of methods GetFirstAliveGroup, GetNextAliveGroup, GetLastAliveGroup + code snippets.
2016-07-23

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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