mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
1843 lines
54 KiB
Lua
1843 lines
54 KiB
Lua
--- **Wrapper** -- GROUP wraps the DCS Class Group objects.
|
|
--
|
|
-- ===
|
|
--
|
|
-- 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.
|
|
--
|
|
-- **IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).**
|
|
--
|
|
-- See the detailed documentation on the GROUP class.
|
|
--
|
|
-- ===
|
|
--
|
|
-- ### Author: **FlightControl**
|
|
--
|
|
-- ### Contributions:
|
|
--
|
|
-- * [**Entropy**](https://forums.eagle.ru/member.php?u=111471), **Afinegan**: Came up with the requirement for AIOnOff().
|
|
--
|
|
-- ===
|
|
--
|
|
-- @module Wrapper.Group
|
|
-- @image Wrapper_Group.JPG
|
|
|
|
|
|
--- @type GROUP
|
|
-- @extends Wrapper.Controllable#CONTROLLABLE
|
|
-- @field #string GroupName The name of the group.
|
|
|
|
|
|
--- Wrapper class of the DCS world Group object.
|
|
--
|
|
-- 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.
|
|
--
|
|
-- ## GROUP task methods
|
|
--
|
|
-- A GROUP is a @{Wrapper.Controllable}. See the @{Wrapper.Controllable} task methods section for a description of the task methods.
|
|
--
|
|
-- ### 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:
|
|
--
|
|
-- * @{Wrapper.Controllable#CONTROLLABLE.TaskMission}: (AIR + GROUND) Return a mission task from a mission template.
|
|
--
|
|
-- ## GROUP Command methods
|
|
--
|
|
-- A GROUP is a @{Wrapper.Controllable}. See the @{Wrapper.Controllable} command methods section for a description of the command methods.
|
|
--
|
|
-- ## GROUP option methods
|
|
--
|
|
-- A GROUP is a @{Wrapper.Controllable}. See the @{Wrapper.Controllable} option methods section for a description of the option methods.
|
|
--
|
|
-- ## GROUP Zone validation methods
|
|
--
|
|
-- The group can be validated whether it is completely, partly or not within a @{Zone}.
|
|
-- Use the following Zone validation methods on the group:
|
|
--
|
|
-- * @{#GROUP.IsCompletelyInZone}: Returns true if all units of the group are within a @{Zone}.
|
|
-- * @{#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 @{Core.Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on.
|
|
--
|
|
-- ## GROUP AI methods
|
|
--
|
|
-- A GROUP has AI methods to control the AI activation.
|
|
--
|
|
-- * @{#GROUP.SetAIOnOff}(): Turns the GROUP AI On or Off.
|
|
-- * @{#GROUP.SetAIOn}(): Turns the GROUP AI On.
|
|
-- * @{#GROUP.SetAIOff}(): Turns the GROUP AI Off.
|
|
--
|
|
-- @field #GROUP GROUP
|
|
GROUP = {
|
|
ClassName = "GROUP",
|
|
}
|
|
|
|
|
|
--- Enumerator for location at airbases
|
|
-- @type GROUP.Takeoff
|
|
GROUP.Takeoff = {
|
|
Air = 1,
|
|
Runway = 2,
|
|
Hot = 3,
|
|
Cold = 4,
|
|
}
|
|
|
|
GROUPTEMPLATE = {}
|
|
|
|
GROUPTEMPLATE.Takeoff = {
|
|
[GROUP.Takeoff.Air] = { "Turning Point", "Turning Point" },
|
|
[GROUP.Takeoff.Runway] = { "TakeOff", "From Runway" },
|
|
[GROUP.Takeoff.Hot] = { "TakeOffParkingHot", "From Parking Area Hot" },
|
|
[GROUP.Takeoff.Cold] = { "TakeOffParking", "From Parking Area" }
|
|
}
|
|
|
|
--- Create a new GROUP from a given GroupTemplate as a parameter.
|
|
-- Note that the GroupTemplate is NOT spawned into the mission.
|
|
-- It is merely added to the @{Core.Database}.
|
|
-- @param #GROUP self
|
|
-- @param #table GroupTemplate The GroupTemplate Structure exactly as defined within the mission editor.
|
|
-- @param DCS#coalition.side CoalitionSide The coalition.side of the group.
|
|
-- @param DCS#Group.Category CategoryID The Group.Category of the group.
|
|
-- @param DCS#country.id CountryID the country.id of the group.
|
|
-- @return #GROUP self
|
|
function GROUP:NewTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID )
|
|
local GroupName = GroupTemplate.name
|
|
|
|
_DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID, GroupName )
|
|
|
|
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) )
|
|
self.GroupName = GroupName
|
|
|
|
if not _DATABASE.GROUPS[GroupName] then
|
|
_DATABASE.GROUPS[GroupName] = self
|
|
end
|
|
|
|
self:SetEventPriority( 4 )
|
|
return self
|
|
end
|
|
|
|
|
|
|
|
--- Create a new GROUP from an existing Group in the Mission.
|
|
-- @param #GROUP self
|
|
-- @param #string GroupName The Group name
|
|
-- @return #GROUP self
|
|
function GROUP:Register( GroupName )
|
|
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP
|
|
self.GroupName = GroupName
|
|
|
|
self:SetEventPriority( 4 )
|
|
return self
|
|
end
|
|
|
|
-- Reference methods.
|
|
|
|
--- Find the GROUP wrapper class instance using the DCS Group.
|
|
-- @param #GROUP self
|
|
-- @param DCS#Group DCSGroup The DCS Group.
|
|
-- @return #GROUP The GROUP.
|
|
function GROUP:Find( DCSGroup )
|
|
|
|
local GroupName = DCSGroup:getName() -- Wrapper.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 DCS#Group The DCS Group.
|
|
function GROUP:GetDCSObject()
|
|
local DCSGroup = Group.getByName( self.GroupName )
|
|
|
|
if DCSGroup then
|
|
return DCSGroup
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Returns the @{DCS#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission.
|
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
|
-- @return DCS#Position The 3D position vectors of the POSITIONABLE.
|
|
-- @return #nil The POSITIONABLE is not existing or alive.
|
|
function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3()
|
|
self:F2( self.PositionableName )
|
|
|
|
local DCSPositionable = self:GetDCSObject()
|
|
|
|
if DCSPositionable then
|
|
local PositionablePosition = DCSPositionable:getUnits()[1]:getPosition().p
|
|
self:T3( PositionablePosition )
|
|
return PositionablePosition
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Returns if the Group is alive.
|
|
-- The Group must:
|
|
--
|
|
-- * Exist at run-time.
|
|
-- * Has at least one unit.
|
|
--
|
|
-- When the first @{Wrapper.Unit} of the Group is active, it will return true.
|
|
-- If the first @{Wrapper.Unit} of the Group is inactive, it will return false.
|
|
--
|
|
-- @param #GROUP self
|
|
-- @return #boolean true if the Group is alive and active.
|
|
-- @return #boolean false if the Group is alive but inactive.
|
|
-- @return #nil if the group does not exist anymore.
|
|
function GROUP:IsAlive()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject() -- DCS#Group
|
|
|
|
if DCSGroup then
|
|
if DCSGroup:isExist() then
|
|
local DCSUnit = DCSGroup:getUnit(1) -- DCS#Unit
|
|
if DCSUnit then
|
|
local GroupIsAlive = DCSUnit:isActive()
|
|
self:T3( GroupIsAlive )
|
|
return GroupIsAlive
|
|
end
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Destroys the DCS Group and all of its DCS Units.
|
|
-- Note that this destroy method also can raise a destroy event at run-time.
|
|
-- So all event listeners will catch the destroy event of this group for each unit in the group.
|
|
-- To raise these events, provide the `GenerateEvent` parameter.
|
|
-- @param #GROUP self
|
|
-- @param #boolean GenerateEvent true if you want to generate a crash or dead event for each unit.
|
|
-- @usage
|
|
-- -- Air unit example: destroy the Helicopter and generate a S_EVENT_CRASH for each unit in the Helicopter group.
|
|
-- Helicopter = GROUP:FindByName( "Helicopter" )
|
|
-- Helicopter:Destroy( true )
|
|
-- @usage
|
|
-- -- Ground unit example: destroy the Tanks and generate a S_EVENT_DEAD for each unit in the Tanks group.
|
|
-- Tanks = GROUP:FindByName( "Tanks" )
|
|
-- Tanks:Destroy( true )
|
|
-- @usage
|
|
-- -- Ship unit example: destroy the Ship silently.
|
|
-- Ship = GROUP:FindByName( "Ship" )
|
|
-- Ship:Destroy( true )
|
|
function GROUP:Destroy( GenerateEvent )
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
for Index, UnitData in pairs( DCSGroup:getUnits() ) do
|
|
if GenerateEvent and GenerateEvent == true then
|
|
if self:IsAir() then
|
|
self:CreateEventCrash( timer.getTime(), UnitData )
|
|
else
|
|
self:CreateEventDead( timer.getTime(), UnitData )
|
|
end
|
|
else
|
|
self:CreateEventRemoveUnit( timer.getTime(), UnitData )
|
|
end
|
|
end
|
|
USERFLAG:New( self:GetName() ):Set( 100 )
|
|
DCSGroup:destroy()
|
|
DCSGroup = nil
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
--- Returns category of the DCS Group.
|
|
-- @param #GROUP self
|
|
-- @return DCS#Group.Category The category ID
|
|
function GROUP:GetCategory()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
if DCSGroup then
|
|
local GroupCategory = DCSGroup:getCategory()
|
|
self:T3( GroupCategory )
|
|
return GroupCategory
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Returns the category name of the #GROUP.
|
|
-- @param #GROUP self
|
|
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
|
|
function GROUP:GetCategoryName()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
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 DCS#coalition.side The coalition side of the DCS Group.
|
|
function GROUP:GetCoalition()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
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 DCS#country.id The country identifier or nil if the DCS Group is not existing or alive.
|
|
function GROUP:GetCountry()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
if DCSGroup then
|
|
local GroupCountry = DCSGroup:getUnit(1):getCountry()
|
|
self:T3( GroupCountry )
|
|
return GroupCountry
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
--- Check if at least one (or all) unit(s) has (have) a certain attribute.
|
|
-- See [hoggit documentation](https://wiki.hoggitworld.com/view/DCS_func_hasAttribute).
|
|
-- @param #GROUP self
|
|
-- @param #string attribute The name of the attribute the group is supposed to have. Valid attributes can be found in the "db_attributes.lua" file which is located at in "C:\Program Files\Eagle Dynamics\DCS World\Scripts\Database".
|
|
-- @param #boolean all If true, all units of the group must have the attribute in order to return true. Default is only one unit of a heterogenious group needs to have the attribute.
|
|
-- @return #boolean Group has this attribute.
|
|
function GROUP:HasAttribute(attribute, all)
|
|
|
|
-- Get all units of the group.
|
|
local _units=self:GetUnits()
|
|
|
|
local _allhave=true
|
|
local _onehas=false
|
|
|
|
for _,_unit in pairs(_units) do
|
|
local _unit=_unit --Wrapper.Unit#UNIT
|
|
if _unit then
|
|
local _hastit=_unit:HasAttribute(attribute)
|
|
if _hastit==true then
|
|
_onehas=true
|
|
else
|
|
_allhave=false
|
|
end
|
|
end
|
|
end
|
|
|
|
if all==true then
|
|
return _allhave
|
|
else
|
|
return _onehas
|
|
end
|
|
end
|
|
|
|
--- Returns the maximum speed of the group.
|
|
-- If the group is heterogenious and consists of different units, the max speed of the slowest unit is returned.
|
|
-- @param #GROUP self
|
|
-- @return #number Speed in km/h.
|
|
function GROUP:GetSpeedMax()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
if DCSGroup then
|
|
|
|
local Units=self:GetUnits()
|
|
|
|
local speedmax=nil
|
|
|
|
for _,unit in pairs(Units) do
|
|
local unit=unit --Wrapper.Unit#UNIT
|
|
local speed=unit:GetSpeedMax()
|
|
if speedmax==nil then
|
|
speedmax=speed
|
|
elseif speed<speedmax then
|
|
speedmax=speed
|
|
end
|
|
end
|
|
|
|
return speedmax
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
--- Returns a list of @{Wrapper.Unit} objects of the @{Wrapper.Group}.
|
|
-- @param #GROUP self
|
|
-- @return #list<Wrapper.Unit#UNIT> The list of @{Wrapper.Unit} objects of the @{Wrapper.Group}.
|
|
function GROUP:GetUnits()
|
|
self:F2( { self.GroupName } )
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
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 a list of @{Wrapper.Unit} objects of the @{Wrapper.Group} that are occupied by a player.
|
|
-- @param #GROUP self
|
|
-- @return #list<Wrapper.Unit#UNIT> The list of player occupied @{Wrapper.Unit} objects of the @{Wrapper.Group}.
|
|
function GROUP:GetPlayerUnits()
|
|
self:F2( { self.GroupName } )
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local DCSUnits = DCSGroup:getUnits()
|
|
local Units = {}
|
|
for Index, UnitData in pairs( DCSUnits ) do
|
|
local PlayerUnit = UNIT:Find( UnitData )
|
|
if PlayerUnit:GetPlayerName() then
|
|
Units[#Units+1] = PlayerUnit
|
|
end
|
|
end
|
|
self:T3( Units )
|
|
return Units
|
|
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 Wrapper.Unit#UNIT The UNIT wrapper class.
|
|
function GROUP:GetUnit( UnitNumber )
|
|
self:F3( { self.GroupName, UnitNumber } )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local DCSUnit = DCSGroup:getUnit( UnitNumber )
|
|
local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) )
|
|
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 DCS#Unit The DCS Unit.
|
|
function GROUP:GetDCSUnit( UnitNumber )
|
|
self:F3( { self.GroupName, UnitNumber } )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
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:F3( { self.GroupName } )
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local GroupSize = DCSGroup:getSize()
|
|
|
|
if GroupSize then
|
|
self:T3( GroupSize )
|
|
return GroupSize
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
--- Returns the average velocity Vec3 vector.
|
|
-- @param Wrapper.Group#GROUP self
|
|
-- @return DCS#Vec3 The velocity Vec3 vector
|
|
-- @return #nil The GROUP is not existing or alive.
|
|
function GROUP:GetVelocityVec3()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup and DCSGroup:isExist() then
|
|
local GroupUnits = DCSGroup:getUnits()
|
|
local GroupCount = #GroupUnits
|
|
|
|
local VelocityVec3 = { x = 0, y = 0, z = 0 }
|
|
|
|
for _, DCSUnit in pairs( GroupUnits ) do
|
|
local UnitVelocityVec3 = DCSUnit:getVelocity()
|
|
VelocityVec3.x = VelocityVec3.x + UnitVelocityVec3.x
|
|
VelocityVec3.y = VelocityVec3.y + UnitVelocityVec3.y
|
|
VelocityVec3.z = VelocityVec3.z + UnitVelocityVec3.z
|
|
end
|
|
|
|
VelocityVec3.x = VelocityVec3.x / GroupCount
|
|
VelocityVec3.y = VelocityVec3.y / GroupCount
|
|
VelocityVec3.z = VelocityVec3.z / GroupCount
|
|
|
|
return VelocityVec3
|
|
end
|
|
|
|
BASE:E( { "Cannot GetVelocityVec3", Group = self, Alive = self:IsAlive() } )
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
--- Returns the average group height in meters.
|
|
-- @param Wrapper.Group#GROUP self
|
|
-- @param #boolean FromGround Measure from the ground or from sea level. Provide **true** for measuring from the ground. **false** or **nil** if you measure from sea level.
|
|
-- @return DCS#Vec3 The height of the group or nil if is not existing or alive.
|
|
function GROUP:GetHeight( FromGround )
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local GroupUnits = DCSGroup:getUnits()
|
|
local GroupCount = #GroupUnits
|
|
|
|
local GroupHeight = 0
|
|
|
|
for _, DCSUnit in pairs( GroupUnits ) do
|
|
local GroupPosition = DCSUnit:getPosition()
|
|
|
|
if FromGround == true then
|
|
local LandHeight = land.getHeight( { x = GroupPosition.p.x, y = GroupPosition.p.z } )
|
|
GroupHeight = GroupHeight + ( GroupPosition.p.y - LandHeight )
|
|
else
|
|
GroupHeight = GroupHeight + GroupPosition.p.y
|
|
end
|
|
end
|
|
|
|
return GroupHeight / GroupCount
|
|
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:F3( { self.GroupName } )
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local GroupInitialSize = DCSGroup:getInitialSize()
|
|
self:T3( GroupInitialSize )
|
|
return GroupInitialSize
|
|
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:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local DCSUnits = DCSGroup:getUnits()
|
|
self:T3( DCSUnits )
|
|
return DCSUnits
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
--- Activates a GROUP.
|
|
-- @param #GROUP self
|
|
function GROUP:Activate()
|
|
self:F2( { self.GroupName } )
|
|
trigger.action.activateGroup( self:GetDCSObject() )
|
|
return self:GetDCSObject()
|
|
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:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local GroupTypeName = DCSGroup:getUnit(1):getTypeName()
|
|
self:T3( GroupTypeName )
|
|
return( GroupTypeName )
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Gets the player name of the group.
|
|
-- @param #GROUP self
|
|
-- @return #string The player name of the group.
|
|
function GROUP:GetPlayerName()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local PlayerName = DCSGroup:getUnit(1):getPlayerName()
|
|
self:T3( PlayerName )
|
|
return( PlayerName )
|
|
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:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local GroupCallSign = DCSGroup:getUnit(1):getCallsign()
|
|
self:T3( GroupCallSign )
|
|
return GroupCallSign
|
|
end
|
|
|
|
BASE:E( { "Cannot GetCallsign", Positionable = self, Alive = self:IsAlive() } )
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Returns the current point (Vec2 vector) of the first DCS Unit in the DCS Group.
|
|
-- @param #GROUP self
|
|
-- @return DCS#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group.
|
|
function GROUP:GetVec2()
|
|
self:F2( self.GroupName )
|
|
|
|
local UnitPoint = self:GetUnit(1)
|
|
UnitPoint:GetVec2()
|
|
local GroupPointVec2 = UnitPoint:GetVec2()
|
|
self:T3( GroupPointVec2 )
|
|
return GroupPointVec2
|
|
end
|
|
|
|
--- Returns the current Vec3 vector of the first DCS Unit in the GROUP.
|
|
-- @param #GROUP self
|
|
-- @return DCS#Vec3 Current Vec3 of the first DCS Unit of the GROUP.
|
|
function GROUP:GetVec3()
|
|
self:F2( self.GroupName )
|
|
|
|
local GroupVec3 = self:GetUnit(1):GetVec3()
|
|
self:T3( GroupVec3 )
|
|
return GroupVec3
|
|
end
|
|
|
|
--- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission.
|
|
-- @param #GROUP self
|
|
-- @return Core.Point#POINT_VEC2 The 2D point vector of the first DCS Unit of the GROUP.
|
|
-- @return #nil The first UNIT is not existing or alive.
|
|
function GROUP:GetPointVec2()
|
|
self:F2(self.GroupName)
|
|
|
|
local FirstUnit = self:GetUnit(1)
|
|
|
|
if FirstUnit then
|
|
local FirstUnitPointVec2 = FirstUnit:GetPointVec2()
|
|
self:T3(FirstUnitPointVec2)
|
|
return FirstUnitPointVec2
|
|
end
|
|
|
|
BASE:E( { "Cannot GetPointVec2", Group = self, Alive = self:IsAlive() } )
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Returns a COORDINATE object indicating the point of the first UNIT of the GROUP within the mission.
|
|
-- @param Wrapper.Group#GROUP self
|
|
-- @return Core.Point#COORDINATE The COORDINATE of the GROUP.
|
|
function GROUP:GetCoordinate()
|
|
self:F2( self.PositionableName )
|
|
|
|
local FirstUnit = self:GetUnit(1)
|
|
|
|
if FirstUnit then
|
|
local FirstUnitCoordinate = FirstUnit:GetCoordinate()
|
|
self:T3(FirstUnitCoordinate)
|
|
return FirstUnitCoordinate
|
|
end
|
|
|
|
BASE:E( { "Cannot GetCoordinate", Group = self, Alive = self:IsAlive() } )
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
--- Returns a random @{DCS#Vec3} vector (point in 3D of the UNIT within the mission) within a range around the first UNIT of the GROUP.
|
|
-- @param #GROUP self
|
|
-- @param #number Radius
|
|
-- @return DCS#Vec3 The random 3D point vector around the first UNIT of the GROUP.
|
|
-- @return #nil The GROUP is invalid or empty
|
|
-- @usage
|
|
-- -- If Radius is ignored, returns the DCS#Vec3 of first UNIT of the GROUP
|
|
function GROUP:GetRandomVec3(Radius)
|
|
self:F2(self.GroupName)
|
|
|
|
local FirstUnit = self:GetUnit(1)
|
|
|
|
if FirstUnit then
|
|
local FirstUnitRandomPointVec3 = FirstUnit:GetRandomVec3(Radius)
|
|
self:T3(FirstUnitRandomPointVec3)
|
|
return FirstUnitRandomPointVec3
|
|
end
|
|
|
|
BASE:E( { "Cannot GetRandomVec3", Group = self, Alive = self:IsAlive() } )
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Returns the mean heading of every UNIT in the GROUP in degrees
|
|
-- @param #GROUP self
|
|
-- @return #number mean heading of the GROUP
|
|
-- @return #nil The first UNIT is not existing or alive.
|
|
function GROUP:GetHeading()
|
|
self:F2(self.GroupName)
|
|
|
|
local GroupSize = self:GetSize()
|
|
local HeadingAccumulator = 0
|
|
|
|
if GroupSize then
|
|
for i = 1, GroupSize do
|
|
HeadingAccumulator = HeadingAccumulator + self:GetUnit(i):GetHeading()
|
|
end
|
|
return math.floor(HeadingAccumulator / GroupSize)
|
|
end
|
|
|
|
BASE:E( { "Cannot GetHeading", Group = self, Alive = self:IsAlive() } )
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
--- Return the fuel state and unit reference for the unit with the least
|
|
-- amount of fuel in the group.
|
|
-- @param #GROUP self
|
|
-- @return #number The fuel state of the unit with the least amount of fuel
|
|
-- @return #Unit reference to #Unit object for further processing
|
|
function GROUP:GetFuelMin()
|
|
self:F(self.ControllableName)
|
|
|
|
if not self:GetDCSObject() then
|
|
BASE:E( { "Cannot GetFuel", Group = self, Alive = self:IsAlive() } )
|
|
return 0
|
|
end
|
|
|
|
local min = 65535 -- some sufficiently large number to init with
|
|
local unit = nil
|
|
local tmp = nil
|
|
|
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
|
tmp = UnitData:GetFuel()
|
|
if tmp < min then
|
|
min = tmp
|
|
unit = UnitData
|
|
end
|
|
end
|
|
|
|
return min, unit
|
|
end
|
|
|
|
--- Returns relative amount of fuel (from 0.0 to 1.0) the group has in its
|
|
-- internal tanks. If there are additional fuel tanks the value may be
|
|
-- greater than 1.0.
|
|
-- @param #GROUP self
|
|
-- @return #number The relative amount of fuel (from 0.0 to 1.0).
|
|
-- @return #nil The GROUP is not existing or alive.
|
|
function GROUP:GetFuelAvg()
|
|
self:F( self.ControllableName )
|
|
|
|
local DCSControllable = self:GetDCSObject()
|
|
|
|
if DCSControllable then
|
|
local GroupSize = self:GetSize()
|
|
local TotalFuel = 0
|
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
local UnitFuel = Unit:GetFuel()
|
|
self:F( { Fuel = UnitFuel } )
|
|
TotalFuel = TotalFuel + UnitFuel
|
|
end
|
|
local GroupFuel = TotalFuel / GroupSize
|
|
return GroupFuel
|
|
end
|
|
|
|
BASE:E( { "Cannot GetFuel", Group = self, Alive = self:IsAlive() } )
|
|
|
|
return 0
|
|
end
|
|
|
|
--- Returns relative amount of fuel (from 0.0 to 1.0) the group has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0.
|
|
-- @param #GROUP self
|
|
-- @return #number The relative amount of fuel (from 0.0 to 1.0).
|
|
-- @return #nil The GROUP is not existing or alive.
|
|
function GROUP:GetFuel()
|
|
return self:GetFuelAvg()
|
|
end
|
|
|
|
|
|
do -- Is Zone methods
|
|
|
|
--- Returns true if all units of the group are within a @{Zone}.
|
|
-- @param #GROUP self
|
|
-- @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 } )
|
|
|
|
if not self:IsAlive() then return false end
|
|
|
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
if Zone:IsVec3InZone( Unit:GetVec3() ) then
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
--- Returns true if some but NOT ALL units of the group are within a @{Zone}.
|
|
-- @param #GROUP self
|
|
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
|
-- @return #boolean Returns true if the Group is partially within the @{Core.Zone#ZONE_BASE}
|
|
function GROUP:IsPartlyInZone( Zone )
|
|
self:F2( { self.GroupName, Zone } )
|
|
|
|
local IsOneUnitInZone = false
|
|
local IsOneUnitOutsideZone = false
|
|
|
|
if not self:IsAlive() then return false end
|
|
|
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
if Zone:IsVec3InZone( Unit:GetVec3() ) then
|
|
IsOneUnitInZone = true
|
|
else
|
|
IsOneUnitOutsideZone = true
|
|
end
|
|
end
|
|
|
|
if IsOneUnitInZone and IsOneUnitOutsideZone then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
--- Returns true if part or all units of the group are within a @{Zone}.
|
|
-- @param #GROUP self
|
|
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
|
-- @return #boolean Returns true if the Group is partially or completely within the @{Core.Zone#ZONE_BASE}.
|
|
function GROUP:IsPartlyOrCompletelyInZone( Zone )
|
|
return self:IsPartlyInZone(Zone) or self:IsCompletelyInZone(Zone)
|
|
end
|
|
|
|
--- Returns true if none of the group units of the group are within a @{Zone}.
|
|
-- @param #GROUP self
|
|
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
|
-- @return #boolean Returns true if the Group is not within the @{Core.Zone#ZONE_BASE}
|
|
function GROUP:IsNotInZone( Zone )
|
|
self:F2( { self.GroupName, Zone } )
|
|
|
|
if not self:IsAlive() then return true end
|
|
|
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
if Zone:IsVec3InZone( Unit:GetVec3() ) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
--- Returns the number of UNITs that are in the @{Zone}
|
|
-- @param #GROUP self
|
|
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
|
-- @return #number The number of UNITs that are in the @{Zone}
|
|
function GROUP:CountInZone( Zone )
|
|
self:F2( {self.GroupName, Zone} )
|
|
local Count = 0
|
|
|
|
if not self:IsAlive() then return Count end
|
|
|
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
if Zone:IsVec3InZone( Unit:GetVec3() ) then
|
|
Count = Count + 1
|
|
end
|
|
end
|
|
|
|
return Count
|
|
end
|
|
|
|
--- 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:GetDCSObject()
|
|
|
|
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:GetDCSObject()
|
|
|
|
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:GetDCSObject()
|
|
|
|
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:GetDCSObject()
|
|
|
|
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:GetDCSObject()
|
|
|
|
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:GetDCSObject()
|
|
|
|
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
|
|
|
|
end
|
|
|
|
do -- AI methods
|
|
|
|
--- Turns the AI On or Off for the GROUP.
|
|
-- @param #GROUP self
|
|
-- @param #boolean AIOnOff The value true turns the AI On, the value false turns the AI Off.
|
|
-- @return #GROUP The GROUP.
|
|
function GROUP:SetAIOnOff( AIOnOff )
|
|
|
|
local DCSGroup = self:GetDCSObject() -- DCS#Group
|
|
|
|
if DCSGroup then
|
|
local DCSController = DCSGroup:getController() -- DCS#Controller
|
|
if DCSController then
|
|
DCSController:setOnOff( AIOnOff )
|
|
return self
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Turns the AI On for the GROUP.
|
|
-- @param #GROUP self
|
|
-- @return #GROUP The GROUP.
|
|
function GROUP:SetAIOn()
|
|
|
|
return self:SetAIOnOff( true )
|
|
end
|
|
|
|
--- Turns the AI Off for the GROUP.
|
|
-- @param #GROUP self
|
|
-- @return #GROUP The GROUP.
|
|
function GROUP:SetAIOff()
|
|
|
|
return self:SetAIOnOff( false )
|
|
end
|
|
|
|
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:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local GroupVelocityMax = 0
|
|
|
|
for Index, UnitData in pairs( DCSGroup:getUnits() ) do
|
|
|
|
local UnitVelocityVec3 = UnitData:getVelocity()
|
|
local UnitVelocity = math.abs( UnitVelocityVec3.x ) + math.abs( UnitVelocityVec3.y ) + math.abs( UnitVelocityVec3.z )
|
|
|
|
if UnitVelocity > GroupVelocityMax then
|
|
GroupVelocityMax = UnitVelocity
|
|
end
|
|
end
|
|
|
|
return GroupVelocityMax
|
|
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
|
|
|
|
-- RESPAWNING
|
|
|
|
--- Returns the group template from the @{DATABASE} (_DATABASE object).
|
|
-- @param #GROUP self
|
|
-- @return #table
|
|
function GROUP:GetTemplate()
|
|
local GroupName = self:GetName()
|
|
return UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ) )
|
|
end
|
|
|
|
--- Returns the group template route.points[] (the waypoints) from the @{DATABASE} (_DATABASE object).
|
|
-- @param #GROUP self
|
|
-- @return #table
|
|
function GROUP:GetTemplateRoutePoints()
|
|
local GroupName = self:GetName()
|
|
return UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ).route.points )
|
|
end
|
|
|
|
|
|
|
|
--- Sets the controlled status in a Template.
|
|
-- @param #GROUP self
|
|
-- @param #boolean Controlled true is controlled, false is uncontrolled.
|
|
-- @return #table
|
|
function GROUP:SetTemplateControlled( Template, Controlled )
|
|
Template.uncontrolled = not Controlled
|
|
return Template
|
|
end
|
|
|
|
--- Sets the CountryID of the group in a Template.
|
|
-- @param #GROUP self
|
|
-- @param DCS#country.id CountryID The country ID.
|
|
-- @return #table
|
|
function GROUP:SetTemplateCountry( Template, CountryID )
|
|
Template.CountryID = CountryID
|
|
return Template
|
|
end
|
|
|
|
--- Sets the CoalitionID of the group in a Template.
|
|
-- @param #GROUP self
|
|
-- @param DCS#coalition.side CoalitionID The coalition ID.
|
|
-- @return #table
|
|
function GROUP:SetTemplateCoalition( Template, CoalitionID )
|
|
Template.CoalitionID = CoalitionID
|
|
return Template
|
|
end
|
|
|
|
|
|
--- Set the heading for the units in degrees within the respawned group.
|
|
-- @param #GROUP self
|
|
-- @param #number Heading The heading in meters.
|
|
-- @return #GROUP self
|
|
function GROUP:InitHeading( Heading )
|
|
self.InitRespawnHeading = Heading
|
|
return self
|
|
end
|
|
|
|
|
|
--- Set the height for the units in meters for the respawned group. (This is applicable for air units).
|
|
-- @param #GROUP self
|
|
-- @param #number Height The height in meters.
|
|
-- @return #GROUP self
|
|
function GROUP:InitHeight( Height )
|
|
self.InitRespawnHeight = Height
|
|
return self
|
|
end
|
|
|
|
|
|
--- Set the respawn @{Zone} for the respawned group.
|
|
-- @param #GROUP self
|
|
-- @param Core.Zone#ZONE Zone The zone in meters.
|
|
-- @return #GROUP self
|
|
function GROUP:InitZone( Zone )
|
|
self.InitRespawnZone = Zone
|
|
return self
|
|
end
|
|
|
|
|
|
--- Randomize the positions of the units of the respawned group within the @{Zone}.
|
|
-- When a Respawn happens, the units of the group will be placed at random positions within the Zone (selected).
|
|
-- @param #GROUP self
|
|
-- @param #boolean PositionZone true will randomize the positions within the Zone.
|
|
-- @return #GROUP self
|
|
function GROUP:InitRandomizePositionZone( PositionZone )
|
|
|
|
self.InitRespawnRandomizePositionZone = PositionZone
|
|
self.InitRespawnRandomizePositionInner = nil
|
|
self.InitRespawnRandomizePositionOuter = nil
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Randomize the positions of the units of the respawned group in a circle band.
|
|
-- When a Respawn happens, the units of the group will be positioned at random places within the Outer and Inner radius.
|
|
-- Thus, a band is created around the respawn location where the units will be placed at random positions.
|
|
-- @param #GROUP self
|
|
-- @param #boolean OuterRadius Outer band in meters from the center.
|
|
-- @param #boolean InnerRadius Inner band in meters from the center.
|
|
-- @return #GROUP self
|
|
function GROUP:InitRandomizePositionRadius( OuterRadius, InnerRadius )
|
|
|
|
self.InitRespawnRandomizePositionZone = nil
|
|
self.InitRespawnRandomizePositionOuter = OuterRadius
|
|
self.InitRespawnRandomizePositionInner = InnerRadius
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Respawn the @{Wrapper.Group} at a @{Point}.
|
|
-- The method will setup the new group template according the Init(Respawn) settings provided for the group.
|
|
-- These settings can be provided by calling the relevant Init...() methods of the Group.
|
|
--
|
|
-- - @{#GROUP.InitHeading}: Set the heading for the units in degrees within the respawned group.
|
|
-- - @{#GROUP.InitHeight}: Set the height for the units in meters for the respawned group. (This is applicable for air units).
|
|
-- - @{#GROUP.InitRandomizeHeading}: Randomize the headings for the units within the respawned group.
|
|
-- - @{#GROUP.InitZone}: Set the respawn @{Zone} for the respawned group.
|
|
-- - @{#GROUP.InitRandomizeZones}: Randomize the respawn @{Zone} between one of the @{Zone}s given for the respawned group.
|
|
-- - @{#GROUP.InitRandomizePositionZone}: Randomize the positions of the units of the respawned group within the @{Zone}.
|
|
-- - @{#GROUP.InitRandomizePositionRadius}: Randomize the positions of the units of the respawned group in a circle band.
|
|
-- - @{#GROUP.InitRandomizeTemplates}: Randomize the Template for the respawned group.
|
|
--
|
|
--
|
|
-- Notes:
|
|
--
|
|
-- - When InitZone or InitRandomizeZones is not used, the position of the respawned group will be its current position.
|
|
-- - The current alive group will always be destroyed and respawned using the template definition.
|
|
--
|
|
-- @param Wrapper.Group#GROUP self
|
|
-- @param #table Template (optional) The template of the Group retrieved with GROUP:GetTemplate(). If the template is not provided, the template will be retrieved of the group itself.
|
|
function GROUP:Respawn( Template, Reset )
|
|
|
|
if not Template then
|
|
Template = self:GetTemplate()
|
|
end
|
|
|
|
if self:IsAlive() then
|
|
local Zone = self.InitRespawnZone -- Core.Zone#ZONE
|
|
local Vec3 = Zone and Zone:GetVec3() or self:GetVec3()
|
|
local From = { x = Template.x, y = Template.y }
|
|
Template.x = Vec3.x
|
|
Template.y = Vec3.z
|
|
--Template.x = nil
|
|
--Template.y = nil
|
|
|
|
self:F( #Template.units )
|
|
if Reset == true then
|
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
|
local GroupUnit = UnitData -- Wrapper.Unit#UNIT
|
|
self:F( GroupUnit:GetName() )
|
|
if GroupUnit:IsAlive() then
|
|
self:F( "Alive" )
|
|
local GroupUnitVec3 = GroupUnit:GetVec3()
|
|
if Zone then
|
|
if self.InitRespawnRandomizePositionZone then
|
|
GroupUnitVec3 = Zone:GetRandomVec3()
|
|
else
|
|
if self.InitRespawnRandomizePositionInner and self.InitRespawnRandomizePositionOuter then
|
|
GroupUnitVec3 = POINT_VEC3:NewFromVec2( From ):GetRandomPointVec3InRadius( self.InitRespawnRandomizePositionsOuter, self.InitRespawnRandomizePositionsInner )
|
|
else
|
|
GroupUnitVec3 = Zone:GetVec3()
|
|
end
|
|
end
|
|
end
|
|
|
|
Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y
|
|
Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position.
|
|
Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position.
|
|
Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or GroupUnit:GetHeading()
|
|
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
|
end
|
|
end
|
|
else
|
|
for UnitID, TemplateUnitData in pairs( Template.units ) do
|
|
self:F( "Reset" )
|
|
local GroupUnitVec3 = { x = TemplateUnitData.x, y = TemplateUnitData.alt, z = TemplateUnitData.y }
|
|
if Zone then
|
|
if self.InitRespawnRandomizePositionZone then
|
|
GroupUnitVec3 = Zone:GetRandomVec3()
|
|
else
|
|
if self.InitRespawnRandomizePositionInner and self.InitRespawnRandomizePositionOuter then
|
|
GroupUnitVec3 = POINT_VEC3:NewFromVec2( From ):GetRandomPointVec3InRadius( self.InitRespawnRandomizePositionsOuter, self.InitRespawnRandomizePositionsInner )
|
|
else
|
|
GroupUnitVec3 = Zone:GetVec3()
|
|
end
|
|
end
|
|
end
|
|
|
|
Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y
|
|
Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position.
|
|
Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position.
|
|
Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or TemplateUnitData.heading
|
|
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
self:Destroy()
|
|
_DATABASE:Spawn( Template )
|
|
|
|
self:ResetEvents()
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
|
|
--- Respawn a group at an airbase.
|
|
-- Note that the group has to be on parking spots at the airbase already in order for this to work.
|
|
-- So each unit of the group is respawned at exactly the same parking spot as it currently occupies.
|
|
-- @param Wrapper.Group#GROUP self
|
|
-- @param #table SpawnTemplate (Optional) The spawn template for the group. If no template is given it is exacted from the group.
|
|
-- @param Core.Spawn#SPAWN.Takeoff Takeoff (Optional) Takeoff type. Sould be either SPAWN.Takeoff.Cold or SPAWN.Takeoff.Hot. Default is SPAWN.Takeoff.Hot.
|
|
-- @param #boolean Uncontrolled (Optional) If true, spawn in uncontrolled state.
|
|
-- @return Wrapper.Group#GROUP Group spawned at airbase or nil if group could not be spawned.
|
|
function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) -- R2.4
|
|
self:F2( { SpawnTemplate, Takeoff, Uncontrolled} )
|
|
|
|
-- Get closest airbase. Should be the one we are currently on.
|
|
local airbase=self:GetCoordinate():GetClosestAirbase()
|
|
|
|
if airbase then
|
|
self:F2("Closest airbase = "..airbase:GetName())
|
|
else
|
|
self:E("ERROR: could not find closest airbase!")
|
|
return nil
|
|
end
|
|
-- Takeoff type. Default hot.
|
|
Takeoff = Takeoff or SPAWN.Takeoff.Hot
|
|
|
|
-- Coordinate of the airbase.
|
|
local AirbaseCoord=airbase:GetCoordinate()
|
|
|
|
-- Spawn template.
|
|
SpawnTemplate = SpawnTemplate or self:GetTemplate()
|
|
|
|
if SpawnTemplate then
|
|
|
|
local SpawnPoint = SpawnTemplate.route.points[1]
|
|
|
|
-- These are only for ships.
|
|
SpawnPoint.linkUnit = nil
|
|
SpawnPoint.helipadId = nil
|
|
SpawnPoint.airdromeId = nil
|
|
|
|
-- Aibase id and category.
|
|
local AirbaseID = airbase:GetID()
|
|
local AirbaseCategory = airbase:GetDesc().category
|
|
|
|
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
|
|
SpawnPoint.linkUnit = AirbaseID
|
|
SpawnPoint.helipadId = AirbaseID
|
|
elseif AirbaseCategory == Airbase.Category.AIRDROME then
|
|
SpawnPoint.airdromeId = AirbaseID
|
|
end
|
|
|
|
SpawnPoint.alt = AirbaseCoord:GetLandHeight()
|
|
SpawnPoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
|
|
SpawnPoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
|
|
|
|
-- Get the units of the group.
|
|
local units=self:GetUnits()
|
|
|
|
for UnitID,_unit in pairs(units) do
|
|
|
|
local unit=_unit --Wrapper.Unit#UNIT
|
|
|
|
-- Get closest parking spot of current unit. Note that we look for occupied spots since the unit is currently sitting on it!
|
|
local Parkingspot, TermialID, Distance=unit:GetCoordinate():GetClosestParkingSpot(airbase)
|
|
|
|
--Parkingspot:MarkToAll("parking spot")
|
|
self:T2(string.format("Closest parking spot distance = %s, terminal ID=%s", tostring(Distance), tostring(TermialID)))
|
|
|
|
-- Get unit coordinates for respawning position.
|
|
local uc=unit:GetCoordinate()
|
|
SpawnTemplate.units[UnitID].x = Parkingspot.x
|
|
SpawnTemplate.units[UnitID].y = Parkingspot.z
|
|
SpawnTemplate.units[UnitID].alt = Parkingspot.y
|
|
|
|
SpawnTemplate.units[UnitID].parking = TermialID
|
|
SpawnTemplate.units[UnitID].parking_id = nil
|
|
|
|
end
|
|
|
|
SpawnPoint.x = AirbaseCoord.x
|
|
SpawnPoint.y = AirbaseCoord.z
|
|
|
|
SpawnTemplate.x = AirbaseCoord.x
|
|
SpawnTemplate.y = AirbaseCoord.z
|
|
|
|
-- Set uncontrolled state.
|
|
SpawnTemplate.uncontrolled=Uncontrolled
|
|
|
|
-- Destroy and respawn.
|
|
self:Destroy()
|
|
_DATABASE:Spawn( SpawnTemplate )
|
|
|
|
-- Reset events.
|
|
self:ResetEvents()
|
|
|
|
return self
|
|
end
|
|
|
|
return nil
|
|
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 @{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.
|
|
-- @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
|
|
else
|
|
error( "Template not found for Group : " .. GroupName )
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Calculate the maxium A2G threat level of the Group.
|
|
-- @param #GROUP self
|
|
function GROUP:CalculateThreatLevelA2G()
|
|
|
|
local MaxThreatLevelA2G = 0
|
|
for UnitName, UnitData in pairs( self:GetUnits() ) do
|
|
local ThreatUnit = UnitData -- Wrapper.Unit#UNIT
|
|
local ThreatLevelA2G = ThreatUnit:GetThreatLevel()
|
|
if ThreatLevelA2G > MaxThreatLevelA2G then
|
|
MaxThreatLevelA2G = ThreatLevelA2G
|
|
end
|
|
end
|
|
|
|
self:T3( MaxThreatLevelA2G )
|
|
return MaxThreatLevelA2G
|
|
end
|
|
|
|
--- Returns true if the first unit of the GROUP is in the air.
|
|
-- @param Wrapper.Group#GROUP self
|
|
-- @return #boolean true if in the first unit of the group is in the air.
|
|
-- @return #nil The GROUP is not existing or not alive.
|
|
function GROUP:InAir()
|
|
self:F2( self.GroupName )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
local DCSUnit = DCSGroup:getUnit(1)
|
|
if DCSUnit then
|
|
local GroupInAir = DCSGroup:getUnit(1):inAir()
|
|
self:T3( GroupInAir )
|
|
return GroupInAir
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
do -- Route methods
|
|
|
|
--- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}.
|
|
-- The following things are to be taken into account:
|
|
--
|
|
-- * The group is respawned to achieve the RTB, there may be side artefacts as a result of this. (Like weapons suddenly come back).
|
|
-- * A group consisting out of more than one unit, may rejoin formation when respawned.
|
|
-- * A speed can be given in km/h. If no speed is specified, the maximum speed of the first unit will be taken to return to base.
|
|
-- * When there is no @{Wrapper.Airbase} object specified, the group will return to the home base if the route of the group is pinned at take-off or at landing to a base.
|
|
-- * When there is no @{Wrapper.Airbase} object specified and the group route is not pinned to any airbase, it will return to the nearest airbase.
|
|
--
|
|
-- @param #GROUP self
|
|
-- @param Wrapper.Airbase#AIRBASE RTBAirbase (optional) The @{Wrapper.Airbase} to return to. If blank, the controllable will return to the nearest friendly airbase.
|
|
-- @param #number Speed (optional) The Speed, if no Speed is given, the maximum Speed of the first unit is selected.
|
|
-- @return #GROUP
|
|
function GROUP:RouteRTB( RTBAirbase, Speed )
|
|
self:F( { RTBAirbase:GetName(), Speed } )
|
|
|
|
local DCSGroup = self:GetDCSObject()
|
|
|
|
if DCSGroup then
|
|
|
|
if RTBAirbase then
|
|
|
|
local GroupPoint = self:GetVec2()
|
|
local GroupVelocity = self:GetUnit(1):GetDesc().speedMax
|
|
|
|
local PointFrom = {}
|
|
PointFrom.x = GroupPoint.x
|
|
PointFrom.y = GroupPoint.y
|
|
PointFrom.type = "Turning Point"
|
|
PointFrom.action = "Turning Point"
|
|
PointFrom.speed = GroupVelocity
|
|
|
|
|
|
local PointTo = {}
|
|
local AirbasePointVec2 = RTBAirbase:GetPointVec2()
|
|
local AirbaseAirPoint = AirbasePointVec2:WaypointAir(
|
|
POINT_VEC3.RoutePointAltType.BARO,
|
|
"Land",
|
|
"Landing",
|
|
Speed or self:GetUnit(1):GetDesc().speedMax
|
|
)
|
|
|
|
AirbaseAirPoint["airdromeId"] = RTBAirbase:GetID()
|
|
AirbaseAirPoint["speed_locked"] = true,
|
|
|
|
self:F(AirbaseAirPoint )
|
|
|
|
local Points = { PointFrom, AirbaseAirPoint }
|
|
|
|
self:T3( Points )
|
|
|
|
local Template = self:GetTemplate()
|
|
Template.route.points = Points
|
|
self:Respawn( Template )
|
|
|
|
--self:Route( Points )
|
|
else
|
|
self:ClearTasks()
|
|
end
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
end
|
|
|
|
function GROUP:OnReSpawn( ReSpawnFunction )
|
|
|
|
self.ReSpawnFunction = ReSpawnFunction
|
|
end
|
|
|
|
do -- Event Handling
|
|
|
|
--- Subscribe to a DCS Event.
|
|
-- @param #GROUP self
|
|
-- @param Core.Event#EVENTS Event
|
|
-- @param #function EventFunction (optional) The function to be called when the event occurs for the GROUP.
|
|
-- @return #GROUP
|
|
function GROUP:HandleEvent( Event, EventFunction, ... )
|
|
|
|
self:EventDispatcher():OnEventForGroup( self:GetName(), EventFunction, self, Event, ... )
|
|
|
|
return self
|
|
end
|
|
|
|
--- UnSubscribe to a DCS event.
|
|
-- @param #GROUP self
|
|
-- @param Core.Event#EVENTS Event
|
|
-- @return #GROUP
|
|
function GROUP:UnHandleEvent( Event )
|
|
|
|
self:EventDispatcher():RemoveEvent( self, Event )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Reset the subscriptions.
|
|
-- @param #GROUP self
|
|
-- @return #GROUP
|
|
function GROUP:ResetEvents()
|
|
|
|
self:EventDispatcher():Reset( self )
|
|
|
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
|
UnitData:ResetEvents()
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
end
|
|
|
|
do -- Players
|
|
|
|
--- Get player names
|
|
-- @param #GROUP self
|
|
-- @return #table The group has players, an array of player names is returned.
|
|
-- @return #nil The group has no players
|
|
function GROUP:GetPlayerNames()
|
|
|
|
local HasPlayers = false
|
|
|
|
local PlayerNames = {}
|
|
|
|
local Units = self:GetUnits()
|
|
for UnitID, UnitData in pairs( Units ) do
|
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
local PlayerName = Unit:GetPlayerName()
|
|
if PlayerName and PlayerName ~= "" then
|
|
PlayerNames = PlayerNames or {}
|
|
table.insert( PlayerNames, PlayerName )
|
|
HasPlayers = true
|
|
end
|
|
end
|
|
|
|
if HasPlayers == true then
|
|
self:F2( PlayerNames )
|
|
return PlayerNames
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
--- Get the active player count in the group.
|
|
-- @param #GROUP self
|
|
-- @return #number The amount of players.
|
|
function GROUP:GetPlayerCount()
|
|
|
|
local PlayerCount = 0
|
|
|
|
local Units = self:GetUnits()
|
|
for UnitID, UnitData in pairs( Units or {} ) do
|
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
local PlayerName = Unit:GetPlayerName()
|
|
if PlayerName and PlayerName ~= "" then
|
|
PlayerCount = PlayerCount + 1
|
|
end
|
|
end
|
|
|
|
return PlayerCount
|
|
end
|
|
|
|
end
|
|
|
|
--do -- Smoke
|
|
--
|
|
----- Signal a flare at the position of the GROUP.
|
|
---- @param #GROUP self
|
|
---- @param Utilities.Utils#FLARECOLOR FlareColor
|
|
--function GROUP:Flare( FlareColor )
|
|
-- self:F2()
|
|
-- trigger.action.signalFlare( self:GetVec3(), FlareColor , 0 )
|
|
--end
|
|
--
|
|
----- Signal a white flare at the position of the GROUP.
|
|
---- @param #GROUP self
|
|
--function GROUP:FlareWhite()
|
|
-- self:F2()
|
|
-- trigger.action.signalFlare( self:GetVec3(), trigger.flareColor.White , 0 )
|
|
--end
|
|
--
|
|
----- Signal a yellow flare at the position of the GROUP.
|
|
---- @param #GROUP self
|
|
--function GROUP:FlareYellow()
|
|
-- self:F2()
|
|
-- trigger.action.signalFlare( self:GetVec3(), trigger.flareColor.Yellow , 0 )
|
|
--end
|
|
--
|
|
----- Signal a green flare at the position of the GROUP.
|
|
---- @param #GROUP self
|
|
--function GROUP:FlareGreen()
|
|
-- self:F2()
|
|
-- trigger.action.signalFlare( self:GetVec3(), trigger.flareColor.Green , 0 )
|
|
--end
|
|
--
|
|
----- Signal a red flare at the position of the GROUP.
|
|
---- @param #GROUP self
|
|
--function GROUP:FlareRed()
|
|
-- self:F2()
|
|
-- local Vec3 = self:GetVec3()
|
|
-- if Vec3 then
|
|
-- trigger.action.signalFlare( Vec3, trigger.flareColor.Red, 0 )
|
|
-- end
|
|
--end
|
|
--
|
|
----- Smoke the GROUP.
|
|
---- @param #GROUP self
|
|
--function GROUP:Smoke( SmokeColor, Range )
|
|
-- self:F2()
|
|
-- if Range then
|
|
-- trigger.action.smoke( self:GetRandomVec3( Range ), SmokeColor )
|
|
-- else
|
|
-- trigger.action.smoke( self:GetVec3(), SmokeColor )
|
|
-- end
|
|
--
|
|
--end
|
|
--
|
|
----- Smoke the GROUP Green.
|
|
---- @param #GROUP self
|
|
--function GROUP:SmokeGreen()
|
|
-- self:F2()
|
|
-- trigger.action.smoke( self:GetVec3(), trigger.smokeColor.Green )
|
|
--end
|
|
--
|
|
----- Smoke the GROUP Red.
|
|
---- @param #GROUP self
|
|
--function GROUP:SmokeRed()
|
|
-- self:F2()
|
|
-- trigger.action.smoke( self:GetVec3(), trigger.smokeColor.Red )
|
|
--end
|
|
--
|
|
----- Smoke the GROUP White.
|
|
---- @param #GROUP self
|
|
--function GROUP:SmokeWhite()
|
|
-- self:F2()
|
|
-- trigger.action.smoke( self:GetVec3(), trigger.smokeColor.White )
|
|
--end
|
|
--
|
|
----- Smoke the GROUP Orange.
|
|
---- @param #GROUP self
|
|
--function GROUP:SmokeOrange()
|
|
-- self:F2()
|
|
-- trigger.action.smoke( self:GetVec3(), trigger.smokeColor.Orange )
|
|
--end
|
|
--
|
|
----- Smoke the GROUP Blue.
|
|
---- @param #GROUP self
|
|
--function GROUP:SmokeBlue()
|
|
-- self:F2()
|
|
-- trigger.action.smoke( self:GetVec3(), trigger.smokeColor.Blue )
|
|
--end
|
|
--
|
|
--
|
|
--
|
|
--end |