FlightControl ade8135b5a Revert "Added lots of new GROUP functions"
This reverts commit 8b01579a425814eaa0f6b9e4d4f455961ccc03c7.
2016-06-02 14:47:14 +02:00

1893 lines
49 KiB
Lua

--- GROUP class.
--
-- @{GROUP} class
-- ==============
-- The @{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.
-- * Handle local Group Controller.
-- * Manage the "state" of the DCS Group.
--
--
-- GROUP reference methods
-- =======================
-- For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the _@{DATABASE} object.
-- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the @{SPAWN} class).
--
-- The GROUP class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference
-- using the DCS Group or the DCS GroupName.
--
-- Another thing to know is that GROUP objects do not "contain" the DCS Group object.
-- The GROUP methods will reference the DCS Group object by name when it is needed during API execution.
-- If the DCS Group object does not exist or is nil, the GROUP methods will return nil and log an exception in the DCS.log file.
--
-- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance:
--
-- * @{#GROUP.Find}(): Find a GROUP instance from the _DATABASE object using a DCS Group object.
-- * @{#GROUP.FindByName}(): Find a GROUP instance from the _DATABASE object using a DCS Group name.
--
-- IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).
-- @module Group
-- @author FlightControl
Include.File( "Routines" )
Include.File( "Base" )
Include.File( "Message" )
Include.File( "Unit" )
--- The GROUP class
-- @type GROUP
-- @extends Base#BASE
-- @field DCSGroup#Group DCSGroup The DCS group class.
-- @field #string GroupName The name of the group.
GROUP = {
ClassName = "GROUP",
GroupName = "",
GroupID = 0,
Controller = nil,
DCSGroup = nil,
WayPointFunctions = {},
}
--- A DCSGroup
-- @type DCSGroup
-- @field id_ The ID of the group in DCS
--- Create a new GROUP from a DCSGroup
-- @param #GROUP self
-- @param DCSGroup#Group GroupName The DCS Group name
-- @return #GROUP self
function GROUP:Register( GroupName )
local self = BASE:Inherit( self, BASE:New() )
self:F2( GroupName )
self.GroupName = GroupName
return self
end
-- Reference methods.
--- Find the GROUP wrapper class instance using the DCS Group.
-- @param #GROUP self
-- @param DCSGroup#Group DCSGroup The DCS Group.
-- @return #GROUP The GROUP.
function GROUP:Find( DCSGroup )
local GroupName = DCSGroup:getName() -- Group#GROUP
local GroupFound = _DATABASE:FindGroup( GroupName )
return GroupFound
end
--- Find the created GROUP using the DCS Group Name.
-- @param #GROUP self
-- @param #string GroupName The DCS Group Name.
-- @return #GROUP The GROUP.
function GROUP:FindByName( GroupName )
local GroupFound = _DATABASE:FindGroup( GroupName )
return GroupFound
end
-- DCS Group methods support.
--- Returns the DCS Group.
-- @param #GROUP self
-- @return DCSGroup#Group The DCS Group.
function GROUP:GetDCSGroup()
local DCSGroup = Group.getByName( self.GroupName )
if DCSGroup then
return DCSGroup
end
return nil
end
--- Returns if the DCS Group is alive.
-- When the group exists at run-time, this method will return true, otherwise false.
-- @param #GROUP self
-- @return #boolean true if the DCS Group is alive.
function GROUP:IsAlive()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupIsAlive = DCSGroup:isExist()
self:T3( GroupIsAlive )
return GroupIsAlive
end
return nil
end
--- Destroys the DCS Group and all of its DCS Units.
-- Note that this destroy method also raises a destroy event at run-time.
-- So all event listeners will catch the destroy event of this DCS Group.
-- @param #GROUP self
function GROUP:Destroy()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
for Index, UnitData in pairs( DCSGroup:getUnits() ) do
self:CreateEventCrash( timer.getTime(), UnitData )
end
DCSGroup:destroy()
DCSGroup = nil
end
return nil
end
--- Returns category of the DCS Group.
-- @param #GROUP self
-- @return DCSGroup#Group.Category The category ID
function GROUP:GetCategory()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupCategory = DCSGroup:getCategory()
self:T3( GroupCategory )
return GroupCategory
end
return nil
end
--- Returns the category name of the DCS Group.
-- @param #GROUP self
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
function GROUP:GetCategoryName()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local CategoryNames = {
[Group.Category.AIRPLANE] = "Airplane",
[Group.Category.HELICOPTER] = "Helicopter",
[Group.Category.GROUND] = "Ground Unit",
[Group.Category.SHIP] = "Ship",
}
local GroupCategory = DCSGroup:getCategory()
self:T3( GroupCategory )
return CategoryNames[GroupCategory]
end
return nil
end
--- Returns the coalition of the DCS Group.
-- @param #GROUP self
-- @return DCSCoalitionObject#coalition.side The coalition side of the DCS Group.
function GROUP:GetCoalition()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupCoalition = DCSGroup:getCoalition()
self:T3( GroupCoalition )
return GroupCoalition
end
return nil
end
--- Returns the country of the DCS Group.
-- @param #GROUP self
-- @return DCScountry#country.id The country identifier.
-- @return #nil The DCS Group is not existing or alive.
function GROUP:GetCountry()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupCountry = DCSGroup:getUnit(1):getCountry()
self:T3( GroupCountry )
return GroupCountry
end
return nil
end
--- Returns the name of the DCS Group.
-- @param #GROUP self
-- @return #string The DCS Group name.
function GROUP:GetName()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupName = DCSGroup:getName()
self:T3( GroupName )
return GroupName
end
return nil
end
--- Returns the DCS Group identifier.
-- @param #GROUP self
-- @return #number The identifier of the DCS Group.
function GROUP:GetID()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupID = DCSGroup:getID()
self:T3( GroupID )
return GroupID
end
return nil
end
--- Returns the UNIT wrapper class with number UnitNumber.
-- 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.
function GROUP:GetUnit( UnitNumber )
self:F2( { self.GroupName, UnitNumber } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) )
self:T3( UnitFound.UnitName )
self:T2( UnitFound )
return UnitFound
end
return nil
end
--- Returns the DCS Unit with number UnitNumber.
-- 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.
function GROUP:GetDCSUnit( UnitNumber )
self:F2( { self.GroupName, UnitNumber } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local DCSUnitFound = DCSGroup:getUnit( UnitNumber )
self:T3( DCSUnitFound )
return DCSUnitFound
end
return nil
end
--- Returns current size of the DCS Group.
-- If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed.
-- @param #GROUP self
-- @return #number The DCS Group size.
function GROUP:GetSize()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupSize = DCSGroup:getSize()
self:T3( GroupSize )
return GroupSize
end
return nil
end
---
--- Returns the initial size of the DCS Group.
-- If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged.
-- @param #GROUP self
-- @return #number The DCS Group initial size.
function GROUP:GetInitialSize()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupInitialSize = DCSGroup:getInitialSize()
self:T3( GroupInitialSize )
return GroupInitialSize
end
return nil
end
--- Returns the UNITs wrappers of the DCS Units of the DCS Group.
-- @param #GROUP self
-- @return #table The UNITs wrappers.
function GROUP:GetUnits()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local DCSUnits = DCSGroup:getUnits()
local Units = {}
for Index, UnitData in pairs( DCSUnits ) do
Units[#Units+1] = UNIT:Find( UnitData )
end
self:T3( Units )
return Units
end
return nil
end
--- Returns the DCS Units of the DCS Group.
-- @param #GROUP self
-- @return #table The DCS Units.
function GROUP:GetDCSUnits()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local DCSUnits = DCSGroup:getUnits()
self:T3( DCSUnits )
return DCSUnits
end
return nil
end
--- Get the controller for the GROUP.
-- @param #GROUP self
-- @return DCSController#Controller
function GROUP:_GetController()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupController = DCSGroup:getController()
self:T3( GroupController )
return GroupController
end
return nil
end
--- Retrieve the group mission and allow to place function hooks within the mission waypoint plan.
-- Use the method @{Group#GROUP:WayPointFunction} to define the hook functions for specific waypoints.
-- Use the method @{Group@GROUP:WayPointExecute) to start the execution of the new mission plan.
-- Note that when WayPointInitialize is called, the Mission of the group is RESTARTED!
-- @param #GROUP self
-- @return #GROUP
function GROUP:WayPointInitialize()
self.WayPoints = self:GetTaskRoute()
return self
end
--- Registers a waypoint function that will be executed when the group moves over the WayPoint.
-- @param #GROUP self
-- @param #number WayPoint The waypoint number. Note that the start waypoint on the route is WayPoint 1!
-- @param #number WayPointIndex When defining multiple WayPoint functions for one WayPoint, use WayPointIndex to set the sequence of actions.
-- @param #function WayPointFunction The waypoint function to be called when the group moves over the waypoint. The waypoint function takes variable parameters.
-- @return #GROUP
function GROUP:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... )
self:F2( { WayPoint, WayPointIndex, WayPointFunction } )
table.insert( self.WayPoints[WayPoint].task.params.tasks, WayPointIndex )
self.WayPoints[WayPoint].task.params.tasks[WayPointIndex] = self:TaskFunction( WayPoint, WayPointIndex, WayPointFunction, arg )
return self
end
function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionArguments )
local DCSTask
local DCSScript = {}
DCSScript[#DCSScript+1] = "local MissionGroup = GROUP:Find( ... ) "
if FunctionArguments.n > 0 then
DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")"
else
DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup )"
end
DCSTask = self:TaskWrappedAction(
self:CommandDoScript(
table.concat( DCSScript )
), WayPointIndex
)
self:T3( DCSTask )
return DCSTask
end
--- Executes the WayPoint plan.
-- The function gets a WayPoint parameter, that you can use to restart the mission at a specific WayPoint.
-- Note that when the WayPoint parameter is used, the new start mission waypoint of the group will be 1!
-- @param #GROUP self
-- @param #number WayPoint The WayPoint from where to execute the mission.
-- @param #WaitTime The amount seconds to wait before initiating the mission.
-- @return #GROUP
function GROUP:WayPointExecute( WayPoint, WaitTime )
if not WayPoint then
WayPoint = 1
end
-- When starting the mission from a certain point, the TaskPoints need to be deleted before the given WayPoint.
for TaskPointID = 1, WayPoint - 1 do
table.remove( self.WayPoints, 1 )
end
self:T3( self.WayPoints )
self:SetTask( self:TaskRoute( self.WayPoints ), WaitTime )
return self
end
--- Activates a GROUP.
-- @param #GROUP self
function GROUP:Activate()
self:F2( { self.GroupName } )
trigger.action.activateGroup( self:GetDCSGroup() )
return self:GetDCSGroup()
end
--- Gets the type name of the group.
-- @param #GROUP self
-- @return #string The type name of the group.
function GROUP:GetTypeName()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupTypeName = DCSGroup:getUnit(1):getTypeName()
self:T3( GroupTypeName )
return( GroupTypeName )
end
return nil
end
--- Gets the CallSign of the first DCS Unit of the DCS Group.
-- @param #GROUP self
-- @return #string The CallSign of the first DCS Unit of the DCS Group.
function GROUP:GetCallsign()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupCallSign = DCSGroup:getUnit(1):getCallsign()
self:T3( GroupCallSign )
return GroupCallSign
end
return nil
end
--- Returns the current point (Vec2 vector) of the first DCS Unit in the DCS Group.
-- @return DCSTypes#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group.
function GROUP:GetPointVec2()
self:F2( self.GroupName )
local GroupPointVec2 = self:GetUnit(1):GetPointVec2()
self:T3( GroupPointVec2 )
return GroupPointVec2
end
--- Returns the current point (Vec3 vector) of the first DCS Unit in the DCS Group.
-- @return DCSTypes#Vec3 Current Vec3 point of the first DCS Unit of the DCS Group.
function GROUP:GetPointVec3()
self:F2( self.GroupName )
local GroupPointVec3 = self:GetUnit(1):GetPointVec3()
self:T3( GroupPointVec3 )
return GroupPointVec3
end
-- Is Functions
--- Returns if the group is of an air category.
-- If the group is a helicopter or a plane, then this method will return true, otherwise false.
-- @param #GROUP self
-- @return #boolean Air category evaluation result.
function GROUP:IsAir()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER
self:T3( IsAirResult )
return IsAirResult
end
return nil
end
--- Returns if the DCS Group contains Helicopters.
-- @param #GROUP self
-- @return #boolean true if DCS Group contains Helicopters.
function GROUP:IsHelicopter()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupCategory = DCSGroup:getCategory()
self:T2( GroupCategory )
return GroupCategory == Group.Category.HELICOPTER
end
return nil
end
--- Returns if the DCS Group contains AirPlanes.
-- @param #GROUP self
-- @return #boolean true if DCS Group contains AirPlanes.
function GROUP:IsAirPlane()
self:F2()
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupCategory = DCSGroup:getCategory()
self:T2( GroupCategory )
return GroupCategory == Group.Category.AIRPLANE
end
return nil
end
--- Returns if the DCS Group contains Ground troops.
-- @param #GROUP self
-- @return #boolean true if DCS Group contains Ground troops.
function GROUP:IsGround()
self:F2()
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupCategory = DCSGroup:getCategory()
self:T2( GroupCategory )
return GroupCategory == Group.Category.GROUND
end
return nil
end
--- Returns if the DCS Group contains Ships.
-- @param #GROUP self
-- @return #boolean true if DCS Group contains Ships.
function GROUP:IsShip()
self:F2()
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupCategory = DCSGroup:getCategory()
self:T2( GroupCategory )
return GroupCategory == Group.Category.SHIP
end
return nil
end
--- Returns if all units of the group are on the ground or landed.
-- If all units of this group are on the ground, this function will return true, otherwise false.
-- @param #GROUP self
-- @return #boolean All units on the ground result.
function GROUP:AllOnGround()
self:F2()
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local AllOnGroundResult = true
for Index, UnitData in pairs( DCSGroup:getUnits() ) do
if UnitData:inAir() then
AllOnGroundResult = false
end
end
self:T3( AllOnGroundResult )
return AllOnGroundResult
end
return nil
end
--- Returns the current maximum velocity of the group.
-- Each unit within the group gets evaluated, and the maximum velocity (= the unit which is going the fastest) is returned.
-- @param #GROUP self
-- @return #number Maximum velocity found.
function GROUP:GetMaxVelocity()
self:F2()
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local MaxVelocity = 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 )
if VelocityTotal < MaxVelocity then
MaxVelocity = VelocityTotal
end
end
return MaxVelocity
end
return nil
end
--- Returns the current minimum height of the group.
-- Each unit within the group gets evaluated, and the minimum height (= the unit which is the lowest elevated) is returned.
-- @param #GROUP self
-- @return #number Minimum height found.
function GROUP:GetMinHeight()
self:F2()
end
--- Returns the current maximum height of the group.
-- Each unit within the group gets evaluated, and the maximum height (= the unit which is the highest elevated) is returned.
-- @param #GROUP self
-- @return #number Maximum height found.
function GROUP:GetMaxHeight()
self:F2()
end
-- Tasks
--- Popping current Task from the group.
-- @param #GROUP self
-- @return Group#GROUP self
function GROUP:PopCurrentTask()
self:F2()
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
Controller:popTask()
return self
end
return nil
end
--- Pushing Task on the queue from the group.
-- @param #GROUP self
-- @return Group#GROUP self
function GROUP:PushTask( DCSTask, WaitTime )
self:F2()
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
-- When a group SPAWNs, it takes about a second to get the group in the simulator. Setting tasks to unspawned groups provides unexpected results.
-- Therefore we schedule the functions to set the mission and options for the Group.
-- Controller:pushTask( DCSTask )
if WaitTime then
--routines.scheduleFunction( Controller.pushTask, { Controller, DCSTask }, timer.getTime() + WaitTime )
SCHEDULER:New( Controller, Controller.pushTask, { DCSTask }, WaitTime )
else
Controller:pushTask( DCSTask )
end
return self
end
return nil
end
--- Clearing the Task Queue and Setting the Task on the queue from the group.
-- @param #GROUP self
-- @return Group#GROUP self
function GROUP:SetTask( DCSTask, WaitTime )
self:F2( { DCSTask } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
-- When a group SPAWNs, it takes about a second to get the group in the simulator. Setting tasks to unspawned groups provides unexpected results.
-- Therefore we schedule the functions to set the mission and options for the Group.
-- Controller.setTask( Controller, DCSTask )
if not WaitTime then
WaitTime = 1
end
--routines.scheduleFunction( Controller.setTask, { Controller, DCSTask }, timer.getTime() + WaitTime )
SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime )
return self
end
return nil
end
--- Return a condition section for a controlled task
-- @param #GROUP self
-- @param DCSTime#Time time
-- @param #string userFlag
-- @param #boolean userFlagValue
-- @param #string condition
-- @param DCSTime#Time duration
-- @param #number lastWayPoint
-- return DCSTask#Task
function GROUP:TaskCondition( time, userFlag, userFlagValue, condition, duration, lastWayPoint )
self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } )
local DCSStopCondition = {}
DCSStopCondition.time = time
DCSStopCondition.userFlag = userFlag
DCSStopCondition.userFlagValue = userFlagValue
DCSStopCondition.condition = condition
DCSStopCondition.duration = duration
DCSStopCondition.lastWayPoint = lastWayPoint
self:T3( { DCSStopCondition } )
return DCSStopCondition
end
--- Return a Controlled Task taking a Task and a TaskCondition
-- @param #GROUP self
-- @param DCSTask#Task DCSTask
-- @param #DCSStopCondition DCSStopCondition
-- @return DCSTask#Task
function GROUP:TaskControlled( DCSTask, DCSStopCondition )
self:F2( { DCSTask, DCSStopCondition } )
local DCSTaskControlled
DCSTaskControlled = {
id = 'ControlledTask',
params = {
task = DCSTask,
stopCondition = DCSStopCondition
}
}
self:T3( { DCSTaskControlled } )
return DCSTaskControlled
end
--- Return a Combo Task taking an array of Tasks
-- @param #GROUP self
-- @param #list<DCSTask#Task> DCSTasks
-- @return DCSTask#Task
function GROUP:TaskCombo( DCSTasks )
self:F2( { DCSTasks } )
local DCSTaskCombo
DCSTaskCombo = {
id = 'ComboTask',
params = {
tasks = DCSTasks
}
}
self:T3( { DCSTaskCombo } )
return DCSTaskCombo
end
--- Return a WrappedAction Task taking a Command
-- @param #GROUP self
-- @param DCSCommand#Command DCSCommand
-- @return DCSTask#Task
function GROUP:TaskWrappedAction( DCSCommand, Index )
self:F2( { DCSCommand } )
local DCSTaskWrappedAction
DCSTaskWrappedAction = {
id = "WrappedAction",
enabled = true,
number = Index,
auto = false,
params = {
action = DCSCommand,
},
}
self:T3( { DCSTaskWrappedAction } )
return DCSTaskWrappedAction
end
--- Executes a command action
-- @param #GROUP self
-- @param DCSCommand#Command DCSCommand
-- @return #GROUP self
function GROUP:SetCommand( DCSCommand )
self:F2( DCSCommand )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
Controller:setCommand( DCSCommand )
return self
end
return nil
end
--- Perform a switch waypoint command
-- @param #GROUP self
-- @param #number FromWayPoint
-- @param #number ToWayPoint
-- @return DCSTask#Task
function GROUP:CommandSwitchWayPoint( FromWayPoint, ToWayPoint, Index )
self:F2( { FromWayPoint, ToWayPoint, Index } )
local CommandSwitchWayPoint = {
id = 'SwitchWaypoint',
params = {
fromWaypointIndex = FromWayPoint,
goToWaypointIndex = ToWayPoint,
},
}
self:T3( { CommandSwitchWayPoint } )
return CommandSwitchWayPoint
end
--- Orbit at a specified position at a specified alititude during a specified duration with a specified speed.
-- @param #GROUP self
-- @param 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 #GROUP self
function GROUP:TaskOrbitCircleAtVec2( Point, Altitude, Speed )
self:F2( { self.GroupName, Point, Altitude, Speed } )
-- pattern = enum AI.Task.OribtPattern,
-- point = Vec2,
-- point2 = Vec2,
-- speed = Distance,
-- altitude = Distance
local LandHeight = land.getHeight( Point )
self:T3( { LandHeight } )
local DCSTask = { id = 'Orbit',
params = { pattern = AI.Task.OrbitPattern.CIRCLE,
point = Point,
speed = Speed,
altitude = Altitude + LandHeight
}
}
-- local AITask = { id = 'ControlledTask',
-- params = { task = { id = 'Orbit',
-- params = { pattern = AI.Task.OrbitPattern.CIRCLE,
-- point = Point,
-- speed = Speed,
-- altitude = Altitude + LandHeight
-- }
-- },
-- stopCondition = { duration = Duration
-- }
-- }
-- }
-- )
return DCSTask
end
--- Orbit at the current position of the first unit of the group at a specified alititude
-- @param #GROUP self
-- @param #number Altitude The altitude to hold the position.
-- @param #number Speed The speed flying when holding the position.
-- @return #GROUP self
function GROUP:TaskOrbitCircle( Altitude, Speed )
self:F2( { self.GroupName, Altitude, Speed } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupPoint = self:GetPointVec2()
return self:TaskOrbitCircleAtVec2( GroupPoint, Altitude, Speed )
end
return nil
end
--- Hold position at the current position of the first unit of the group.
-- @param #GROUP self
-- @param #number Duration The maximum duration in seconds to hold the position.
-- @return #GROUP self
function GROUP:TaskHoldPosition()
self:F2( { self.GroupName } )
return self:TaskOrbitCircle( 30, 10 )
end
--- Land the group at a Vec2Point.
-- @param #GROUP self
-- @param DCSTypes#Vec2 Point The point where to land.
-- @param #number Duration The duration in seconds to stay on the ground.
-- @return #GROUP self
function GROUP:TaskLandAtVec2( Point, Duration )
self:F2( { self.GroupName, Point, Duration } )
local DCSTask
if Duration and Duration > 0 then
DCSTask = { id = 'Land', params = { point = Point, durationFlag = true, duration = Duration } }
else
DCSTask = { id = 'Land', params = { point = Point, durationFlag = false } }
end
self:T3( DCSTask )
return DCSTask
end
--- Land the group at a @{Zone#ZONE).
-- @param #GROUP self
-- @param Zone#ZONE Zone The zone where to land.
-- @param #number Duration The duration in seconds to stay on the ground.
-- @return #GROUP self
function GROUP:TaskLandAtZone( Zone, Duration, RandomPoint )
self:F2( { self.GroupName, Zone, Duration, RandomPoint } )
local Point
if RandomPoint then
Point = Zone:GetRandomPointVec2()
else
Point = Zone:GetPointVec2()
end
local DCSTask = self:TaskLandAtVec2( Point, Duration )
self:T3( DCSTask )
return DCSTask
end
--- Attack the Unit.
-- @param #GROUP self
-- @param Unit#UNIT The unit.
-- @return DCSTask#Task The DCS task structure.
function GROUP:TaskAttackUnit( AttackUnit )
self:F2( { self.GroupName, AttackUnit } )
-- AttackUnit = {
-- id = 'AttackUnit',
-- params = {
-- unitId = Unit.ID,
-- weaponType = number,
-- expend = enum AI.Task.WeaponExpend
-- attackQty = number,
-- direction = Azimuth,
-- attackQtyLimit = boolean,
-- groupAttack = boolean,
-- }
-- }
local DCSTask
DCSTask = { id = 'AttackUnit',
params = { unitId = AttackUnit:GetID(),
expend = AI.Task.WeaponExpend.TWO,
groupAttack = true,
},
},
self:T3( { DCSTask } )
return DCSTask
end
--- Attack a Group.
-- @param #GROUP self
-- @param Group#GROUP AttackGroup The Group to be attacked.
-- @return DCSTask#Task The DCS task structure.
function GROUP:TaskAttackGroup( AttackGroup )
self:F2( { self.GroupName, AttackGroup } )
-- AttackGroup = {
-- id = 'AttackGroup',
-- params = {
-- groupId = Group.ID,
-- weaponType = number,
-- expend = enum AI.Task.WeaponExpend,
-- attackQty = number,
-- directionEnabled = boolean,
-- direction = Azimuth,
-- altitudeEnabled = boolean,
-- altitude = Distance,
-- attackQtyLimit = boolean,
-- }
-- }
local DCSTask
DCSTask = { id = 'AttackGroup',
params = { groupId = AttackGroup:GetID(),
expend = AI.Task.WeaponExpend.TWO,
},
},
self:T3( { DCSTask } )
return DCSTask
end
--- Fires at a VEC2 point.
-- @param #GROUP self
-- @param DCSTypes#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.
function GROUP:TaskFireAtPoint( PointVec2, Radius )
self:F2( { self.GroupName, PointVec2, Radius } )
-- FireAtPoint = {
-- id = 'FireAtPoint',
-- params = {
-- point = Vec2,
-- radius = Distance,
-- }
-- }
local DCSTask
DCSTask = { id = 'FireAtPoint',
params = { point = PointVec2,
radius = Radius,
}
}
self:T3( { DCSTask } )
return DCSTask
end
--- Move the group to a Vec2 Point, wait for a defined duration and embark a group.
-- @param #GROUP self
-- @param DCSTypes#Vec2 Point The point where to wait.
-- @param #number Duration The duration in seconds to wait.
-- @param #GROUP EmbarkingGroup The group to be embarked.
-- @return DCSTask#Task The DCS task structure
function GROUP:TaskEmbarkingAtVec2( Point, Duration, EmbarkingGroup )
self:F2( { self.GroupName, Point, Duration, EmbarkingGroup.DCSGroup } )
local DCSTask
DCSTask = { id = 'Embarking',
params = { x = Point.x,
y = Point.y,
duration = Duration,
groupsForEmbarking = { EmbarkingGroup.GroupID },
durationFlag = true,
distributionFlag = false,
distribution = {},
}
}
self:T3( { DCSTask } )
return DCSTask
end
--- Move to a defined Vec2 Point, and embark to a group when arrived within a defined Radius.
-- @param #GROUP self
-- @param 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.
function GROUP:TaskEmbarkToTransportAtVec2( Point, Radius )
self:F2( { self.GroupName, Point, Radius } )
local DCSTask --DCSTask#Task
DCSTask = { id = 'EmbarkToTransport',
params = { x = Point.x,
y = Point.y,
zoneRadius = Radius,
}
}
self:T3( { DCSTask } )
return DCSTask
end
--- Return a Misson task from a mission template.
-- @param #GROUP self
-- @param #table TaskMission A table containing the mission task.
-- @return DCSTask#Task
function GROUP:TaskMission( TaskMission )
self:F2( Points )
local DCSTask
DCSTask = { id = 'Mission', params = { TaskMission, }, }
self:T3( { DCSTask } )
return DCSTask
end
--- Return a Misson task to follow a given route defined by Points.
-- @param #GROUP self
-- @param #table Points A table of route points.
-- @return DCSTask#Task
function GROUP:TaskRoute( Points )
self:F2( Points )
local DCSTask
DCSTask = { id = 'Mission', params = { route = { points = Points, }, }, }
self:T3( { DCSTask } )
return DCSTask
end
--- Make the DCS Group to fly to a given point and hover.
-- @param #GROUP self
-- @param DCSTypes#Vec3 Point The destination point in Vec3 format.
-- @param #number Speed The speed to travel.
-- @return #GROUP self
function GROUP:TaskRouteToVec2( Point, Speed )
self:F2( { Point, Speed } )
local GroupPoint = self:GetUnit( 1 ):GetPointVec2()
local PointFrom = {}
PointFrom.x = GroupPoint.x
PointFrom.y = GroupPoint.y
PointFrom.type = "Turning Point"
PointFrom.action = "Turning Point"
PointFrom.speed = Speed
PointFrom.speed_locked = true
PointFrom.properties = {
["vnav"] = 1,
["scale"] = 0,
["angle"] = 0,
["vangle"] = 0,
["steer"] = 2,
}
local PointTo = {}
PointTo.x = Point.x
PointTo.y = Point.y
PointTo.type = "Turning Point"
PointTo.action = "Fly Over Point"
PointTo.speed = Speed
PointTo.speed_locked = true
PointTo.properties = {
["vnav"] = 1,
["scale"] = 0,
["angle"] = 0,
["vangle"] = 0,
["steer"] = 2,
}
local Points = { PointFrom, PointTo }
self:T3( Points )
self:Route( Points )
return self
end
--- Make the DCS Group to fly to a given point and hover.
-- @param #GROUP self
-- @param DCSTypes#Vec3 Point The destination point in Vec3 format.
-- @param #number Speed The speed to travel.
-- @return #GROUP self
function GROUP:TaskRouteToVec3( Point, Speed )
self:F2( { Point, Speed } )
local GroupPoint = self:GetUnit( 1 ):GetPointVec3()
local PointFrom = {}
PointFrom.x = GroupPoint.x
PointFrom.y = GroupPoint.z
PointFrom.alt = GroupPoint.y
PointFrom.alt_type = "BARO"
PointFrom.type = "Turning Point"
PointFrom.action = "Turning Point"
PointFrom.speed = Speed
PointFrom.speed_locked = true
PointFrom.properties = {
["vnav"] = 1,
["scale"] = 0,
["angle"] = 0,
["vangle"] = 0,
["steer"] = 2,
}
local PointTo = {}
PointTo.x = Point.x
PointTo.y = Point.z
PointTo.alt = Point.y
PointTo.alt_type = "BARO"
PointTo.type = "Turning Point"
PointTo.action = "Fly Over Point"
PointTo.speed = Speed
PointTo.speed_locked = true
PointTo.properties = {
["vnav"] = 1,
["scale"] = 0,
["angle"] = 0,
["vangle"] = 0,
["steer"] = 2,
}
local Points = { PointFrom, PointTo }
self:T3( Points )
self:Route( Points )
return self
end
--- Make the group to follow a given route.
-- @param #GROUP self
-- @param #table GoPoints A table of Route Points.
-- @return #GROUP self
function GROUP:Route( GoPoints )
self:F2( GoPoints )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Points = routines.utils.deepCopy( GoPoints )
local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, }
local Controller = self:_GetController()
--Controller.setTask( Controller, MissionTask )
--routines.scheduleFunction( Controller.setTask, { Controller, MissionTask}, timer.getTime() + 1 )
SCHEDULER:New( Controller, Controller.setTask, { MissionTask }, 1 )
return self
end
return nil
end
--- Route the group to a given zone.
-- The group final destination point can be randomized.
-- A speed can be given in km/h.
-- A given formation can be given.
-- @param #GROUP self
-- @param 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.
function GROUP:TaskRouteToZone( Zone, Randomize, Speed, Formation )
self:F2( Zone )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local GroupPoint = self:GetPointVec2()
local PointFrom = {}
PointFrom.x = GroupPoint.x
PointFrom.y = GroupPoint.y
PointFrom.type = "Turning Point"
PointFrom.action = "Cone"
PointFrom.speed = 20 / 1.6
local PointTo = {}
local ZonePoint
if Randomize then
ZonePoint = Zone:GetRandomPointVec2()
else
ZonePoint = Zone:GetPointVec2()
end
PointTo.x = ZonePoint.x
PointTo.y = ZonePoint.y
PointTo.type = "Turning Point"
if Formation then
PointTo.action = Formation
else
PointTo.action = "Cone"
end
if Speed then
PointTo.speed = Speed
else
PointTo.speed = 20 / 1.6
end
local Points = { PointFrom, PointTo }
self:T3( Points )
self:Route( Points )
return self
end
return nil
end
-- Commands
--- Do Script command
-- @param #GROUP self
-- @param #string DoScript
-- @return #DCSCommand
function GROUP:CommandDoScript( DoScript )
local DCSDoScript = {
id = "Script",
params = {
command = DoScript,
},
}
self:T3( DCSDoScript )
return DCSDoScript
end
--- Return the mission template of the group.
-- @param #GROUP self
-- @return #table The MissionTemplate
function GROUP:GetTaskMission()
self:F2( self.GroupName )
return routines.utils.deepCopy( _DATABASE.Templates.Groups[self.GroupName].Template )
end
--- Return the mission route of the group.
-- @param #GROUP self
-- @return #table The mission route defined by points.
function GROUP:GetTaskRoute()
self:F2( self.GroupName )
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.
-- @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.
-- @param #boolean Randomize Randomization of the route, when true.
-- @param #number Radius When randomization is on, the randomization is within the radius.
function GROUP:CopyRoute( Begin, End, Randomize, Radius )
self:F2( { Begin, End } )
local Points = {}
-- Could be a Spawned Group
local GroupName = string.match( self:GetName(), ".*#" )
if GroupName then
GroupName = GroupName:sub( 1, -2 )
else
GroupName = self:GetName()
end
self:T3( { GroupName } )
local Template = _DATABASE.Templates.Groups[GroupName].Template
if Template then
if not Begin then
Begin = 0
end
if not End then
End = 0
end
for TPointID = Begin + 1, #Template.route.points - End do
if Template.route.points[TPointID] then
Points[#Points+1] = routines.utils.deepCopy( Template.route.points[TPointID] )
if Randomize then
if not Radius then
Radius = 500
end
Points[#Points].x = Points[#Points].x + math.random( Radius * -1, Radius )
Points[#Points].y = Points[#Points].y + math.random( Radius * -1, Radius )
end
end
end
return Points
end
return nil
end
function GROUP:GetDetectedTargets()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
return self:_GetController():getDetectedTargets()
end
return nil
end
function GROUP:IsTargetDetected( DCSObject )
self:F2( self.GroupName )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity
= self:_GetController().isTargetDetected( self:_GetController(), DCSObject,
Controller.Detection.VISUAL,
Controller.Detection.OPTIC,
Controller.Detection.RADAR,
Controller.Detection.IRST,
Controller.Detection.RWR,
Controller.Detection.DLINK
)
return TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity
end
return nil
end
-- Options
--- Can the GROUP hold their weapons?
-- @param #GROUP self
-- @return #boolean
function GROUP:OptionROEHoldFirePossible()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
if self:IsAir() or self:IsGround() or self:IsShip() then
return true
end
return false
end
return nil
end
--- Holding weapons.
-- @param Group#GROUP self
-- @return Group#GROUP self
function GROUP:OptionROEHoldFire()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_HOLD )
elseif self:IsGround() then
Controller:setOption( AI.Option.Ground.id.ROE, AI.Option.Ground.val.ROE.WEAPON_HOLD )
elseif self:IsShip() then
Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.WEAPON_HOLD )
end
return self
end
return nil
end
--- Can the GROUP attack returning on enemy fire?
-- @param #GROUP self
-- @return #boolean
function GROUP:OptionROEReturnFirePossible()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
if self:IsAir() or self:IsGround() or self:IsShip() then
return true
end
return false
end
return nil
end
--- Return fire.
-- @param #GROUP self
-- @return #GROUP self
function GROUP:OptionROEReturnFire()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.RETURN_FIRE )
elseif self:IsGround() then
Controller:setOption( AI.Option.Ground.id.ROE, AI.Option.Ground.val.ROE.RETURN_FIRE )
elseif self:IsShip() then
Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.RETURN_FIRE )
end
return self
end
return nil
end
--- Can the GROUP attack designated targets?
-- @param #GROUP self
-- @return #boolean
function GROUP:OptionROEOpenFirePossible()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
if self:IsAir() or self:IsGround() or self:IsShip() then
return true
end
return false
end
return nil
end
--- Openfire.
-- @param #GROUP self
-- @return #GROUP self
function GROUP:OptionROEOpenFire()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.OPEN_FIRE )
elseif self:IsGround() then
Controller:setOption( AI.Option.Ground.id.ROE, AI.Option.Ground.val.ROE.OPEN_FIRE )
elseif self:IsShip() then
Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.OPEN_FIRE )
end
return self
end
return nil
end
--- Can the GROUP attack targets of opportunity?
-- @param #GROUP self
-- @return #boolean
function GROUP:OptionROEWeaponFreePossible()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
if self:IsAir() then
return true
end
return false
end
return nil
end
--- Weapon free.
-- @param #GROUP self
-- @return #GROUP self
function GROUP:OptionROEWeaponFree()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_FREE )
end
return self
end
return nil
end
--- Can the GROUP ignore enemy fire?
-- @param #GROUP self
-- @return #boolean
function GROUP:OptionROTNoReactionPossible()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
if self:IsAir() then
return true
end
return false
end
return nil
end
--- No evasion on enemy threats.
-- @param #GROUP self
-- @return #GROUP self
function GROUP:OptionROTNoReaction()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.NO_REACTION )
end
return self
end
return nil
end
--- Can the GROUP evade using passive defenses?
-- @param #GROUP self
-- @return #boolean
function GROUP:OptionROTPassiveDefensePossible()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
if self:IsAir() then
return true
end
return false
end
return nil
end
--- Evasion passive defense.
-- @param #GROUP self
-- @return #GROUP self
function GROUP:OptionROTPassiveDefense()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.PASSIVE_DEFENCE )
end
return self
end
return nil
end
--- Can the GROUP evade on enemy fire?
-- @param #GROUP self
-- @return #boolean
function GROUP:OptionROTEvadeFirePossible()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
if self:IsAir() then
return true
end
return false
end
return nil
end
--- Evade on fire.
-- @param #GROUP self
-- @return #GROUP self
function GROUP:OptionROTEvadeFire()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.EVADE_FIRE )
end
return self
end
return nil
end
--- Can the GROUP evade on fire using vertical manoeuvres?
-- @param #GROUP self
-- @return #boolean
function GROUP:OptionROTVerticalPossible()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
if self:IsAir() then
return true
end
return false
end
return nil
end
--- Evade on fire using vertical manoeuvres.
-- @param #GROUP self
-- @return #GROUP self
function GROUP:OptionROTVertical()
self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
local Controller = self:_GetController()
if self:IsAir() then
Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.BYPASS_AND_ESCAPE )
end
return self
end
return nil
end
-- Message APIs
--- Returns a message for a coalition or a client.
-- @param #GROUP self
-- @param #string Message The message text
-- @param #Duration Duration The duration of the message.
-- @return Message#MESSAGE
function GROUP:Message( Message, Duration )
self:F2( { Message, Duration } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
return MESSAGE:New( Message, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")", Duration, self:GetClassNameAndID() )
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 #GROUP self
-- @param #string Message The message text
-- @param #Duration Duration The duration of the message.
function GROUP:MessageToAll( Message, Duration )
self:F2( { Message, Duration } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
self:Message( 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 #GROUP self
-- @param #string Message The message text
-- @param #Duration Duration The duration of the message.
function GROUP:MessageToRed( Message, Duration )
self:F2( { Message, Duration } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
self:Message( 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 #GROUP self
-- @param #string Message The message text
-- @param #Duration Duration The duration of the message.
function GROUP:MessageToBlue( Message, Duration )
self:F2( { Message, Duration } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
self:Message( 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 #GROUP self
-- @param #string Message The message text
-- @param #Duration Duration The duration of the message.
-- @param Client#CLIENT Client The client object receiving the message.
function GROUP:MessageToClient( Message, Duration, Client )
self:F2( { Message, Duration } )
local DCSGroup = self:GetDCSGroup()
if DCSGroup then
self:Message( Message, Duration ):ToClient( Client )
end
return nil
end