mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
2963 lines
96 KiB
Lua
2963 lines
96 KiB
Lua
--- **Core** - SET_ classes define **collections** of objects to perform **bulk actions** and logically **group** objects.
|
|
--
|
|
-- 
|
|
--
|
|
-- ===
|
|
--
|
|
-- SET_ classes group objects of the same type into a collection, which is either:
|
|
--
|
|
-- * Manually managed using the **:Add...()** or **:Remove...()** methods. The initial SET can be filtered with the **@{#SET_BASE.FilterOnce}()** method
|
|
-- * Dynamically updated when new objects are created or objects are destroyed using the **@{#SET_BASE.FilterStart}()** method.
|
|
--
|
|
-- Various types of SET_ classes are available:
|
|
--
|
|
-- * @{#SET_UNIT}: Defines a colleciton of @{Unit}s filtered by filter criteria.
|
|
-- * @{#SET_GROUP}: Defines a collection of @{Group}s filtered by filter criteria.
|
|
-- * @{#SET_CLIENT}: Defines a collection of @{Client}s filterd by filter criteria.
|
|
-- * @{#SET_AIRBASE}: Defines a collection of @{Airbase}s filtered by filter criteria.
|
|
--
|
|
-- These classes are derived from @{#SET_BASE}, which contains the main methods to manage SETs.
|
|
--
|
|
-- A multitude of other methods are available in SET_ classes that allow to:
|
|
--
|
|
-- * Validate the presence of objects in the SET.
|
|
-- * Trigger events when objects in the SET change a zone presence.
|
|
--
|
|
-- ### Authors:
|
|
--
|
|
-- * FlightControl : Design & Programming
|
|
--
|
|
-- ### Contributions:
|
|
--
|
|
--
|
|
-- @module Set
|
|
|
|
|
|
--- @type SET_BASE
|
|
-- @field #table Filter
|
|
-- @field #table Set
|
|
-- @field #table List
|
|
-- @field Core.Scheduler#SCHEDULER CallScheduler
|
|
-- @extends Core.Base#BASE
|
|
|
|
|
|
--- # 1) SET_BASE class, extends @{Base#BASE}
|
|
-- The @{Set#SET_BASE} class defines the core functions that define a collection of objects.
|
|
-- A SET provides iterators to iterate the SET, but will **temporarily** yield the ForEach interator loop at defined **"intervals"** to the mail simulator loop.
|
|
-- In this way, large loops can be done while not blocking the simulator main processing loop.
|
|
-- The default **"yield interval"** is after 10 objects processed.
|
|
-- The default **"time interval"** is after 0.001 seconds.
|
|
--
|
|
-- ## 1.1) Add or remove objects from the SET
|
|
--
|
|
-- Some key core functions are @{Set#SET_BASE.Add} and @{Set#SET_BASE.Remove} to add or remove objects from the SET in your logic.
|
|
--
|
|
-- ## 1.2) Define the SET iterator **"yield interval"** and the **"time interval"**
|
|
--
|
|
-- Modify the iterator intervals with the @{Set#SET_BASE.SetInteratorIntervals} method.
|
|
-- You can set the **"yield interval"**, and the **"time interval"**. (See above).
|
|
--
|
|
-- @field #SET_BASE SET_BASE
|
|
SET_BASE = {
|
|
ClassName = "SET_BASE",
|
|
Filter = {},
|
|
Set = {},
|
|
List = {},
|
|
Index = {},
|
|
}
|
|
|
|
|
|
--- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
|
|
-- @param #SET_BASE self
|
|
-- @return #SET_BASE
|
|
-- @usage
|
|
-- -- Define a new SET_BASE Object. This DBObject will contain a reference to all Group and Unit Templates defined within the ME and the DCSRTE.
|
|
-- DBObject = SET_BASE:New()
|
|
function SET_BASE:New( Database )
|
|
|
|
-- Inherits from BASE
|
|
local self = BASE:Inherit( self, BASE:New() ) -- Core.Set#SET_BASE
|
|
|
|
self.Database = Database
|
|
|
|
self.YieldInterval = 10
|
|
self.TimeInterval = 0.001
|
|
|
|
self.Set = {}
|
|
|
|
self.List = {}
|
|
self.List.__index = self.List
|
|
self.List = setmetatable( { Count = 0 }, self.List )
|
|
|
|
self.Index = {}
|
|
|
|
self.CallScheduler = SCHEDULER:New( self )
|
|
|
|
self:SetEventPriority( 2 )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Finds an @{Base#BASE} object based on the object Name.
|
|
-- @param #SET_BASE self
|
|
-- @param #string ObjectName
|
|
-- @return Core.Base#BASE The Object found.
|
|
function SET_BASE:_Find( ObjectName )
|
|
|
|
local ObjectFound = self.Set[ObjectName]
|
|
return ObjectFound
|
|
end
|
|
|
|
|
|
--- Gets the Set.
|
|
-- @param #SET_BASE self
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:GetSet()
|
|
self:F2()
|
|
|
|
return self.Set
|
|
end
|
|
|
|
--- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using a given ObjectName as the index.
|
|
-- @param #SET_BASE self
|
|
-- @param #string ObjectName
|
|
-- @param Core.Base#BASE Object
|
|
-- @return Core.Base#BASE The added BASE Object.
|
|
function SET_BASE:Add( ObjectName, Object )
|
|
self:F( ObjectName )
|
|
|
|
local t = { _ = Object }
|
|
|
|
if self.List.last then
|
|
self.List.last._next = t
|
|
t._prev = self.List.last
|
|
self.List.last = t
|
|
else
|
|
-- this is the first node
|
|
self.List.first = t
|
|
self.List.last = t
|
|
end
|
|
|
|
self.List.Count = self.List.Count + 1
|
|
|
|
self.Set[ObjectName] = t._
|
|
|
|
table.insert( self.Index, ObjectName )
|
|
|
|
end
|
|
|
|
--- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using the Object Name as the index.
|
|
-- @param #SET_BASE self
|
|
-- @param Wrapper.Object#OBJECT Object
|
|
-- @return Core.Base#BASE The added BASE Object.
|
|
function SET_BASE:AddObject( Object )
|
|
self:F2( Object.ObjectName )
|
|
|
|
self:T( Object.UnitName )
|
|
self:T( Object.ObjectName )
|
|
self:Add( Object.ObjectName, Object )
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Removes a @{Base#BASE} object from the @{Set#SET_BASE} and derived classes, based on the Object Name.
|
|
-- @param #SET_BASE self
|
|
-- @param #string ObjectName
|
|
function SET_BASE:Remove( ObjectName )
|
|
self:F( ObjectName )
|
|
|
|
local t = self.Set[ObjectName]
|
|
|
|
self:E( { ObjectName, t } )
|
|
|
|
if t then
|
|
if t._next then
|
|
if t._prev then
|
|
t._next._prev = t._prev
|
|
t._prev._next = t._next
|
|
else
|
|
-- this was the first node
|
|
t._next._prev = nil
|
|
self.List._first = t._next
|
|
end
|
|
elseif t._prev then
|
|
-- this was the last node
|
|
t._prev._next = nil
|
|
self.List._last = t._prev
|
|
else
|
|
-- this was the only node
|
|
self.List._first = nil
|
|
self.List._last = nil
|
|
end
|
|
|
|
t._next = nil
|
|
t._prev = nil
|
|
self.List.Count = self.List.Count - 1
|
|
|
|
for Index, Key in ipairs( self.Index ) do
|
|
if Key == ObjectName then
|
|
table.remove( self.Index, Index )
|
|
break
|
|
end
|
|
end
|
|
|
|
self.Set[ObjectName] = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--- Gets a @{Base#BASE} object from the @{Set#SET_BASE} and derived classes, based on the Object Name.
|
|
-- @param #SET_BASE self
|
|
-- @param #string ObjectName
|
|
-- @return Core.Base#BASE
|
|
function SET_BASE:Get( ObjectName )
|
|
self:F( ObjectName )
|
|
|
|
local t = self.Set[ObjectName]
|
|
|
|
self:T3( { ObjectName, t } )
|
|
|
|
return t
|
|
|
|
end
|
|
|
|
--- Gets the first object from the @{Set#SET_BASE} and derived classes.
|
|
-- @param #SET_BASE self
|
|
-- @return Core.Base#BASE
|
|
function SET_BASE:GetFirst()
|
|
self:F()
|
|
|
|
local ObjectName = self.Index[1]
|
|
local FirstObject = self.Set[ObjectName]
|
|
self:T3( { FirstObject } )
|
|
return FirstObject
|
|
end
|
|
|
|
--- Gets the last object from the @{Set#SET_BASE} and derived classes.
|
|
-- @param #SET_BASE self
|
|
-- @return Core.Base#BASE
|
|
function SET_BASE:GetLast()
|
|
self:F()
|
|
|
|
local ObjectName = self.Index[#self.Index]
|
|
local LastObject = self.Set[ObjectName]
|
|
self:T3( { LastObject } )
|
|
return LastObject
|
|
end
|
|
|
|
--- Gets a random object from the @{Set#SET_BASE} and derived classes.
|
|
-- @param #SET_BASE self
|
|
-- @return Core.Base#BASE
|
|
function SET_BASE:GetRandom()
|
|
self:F()
|
|
|
|
local RandomItem = self.Set[self.Index[math.random(#self.Index)]]
|
|
|
|
self:T3( { RandomItem } )
|
|
|
|
return RandomItem
|
|
end
|
|
|
|
|
|
--- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes.
|
|
-- @param #SET_BASE self
|
|
-- @return #number Count
|
|
function SET_BASE:Count()
|
|
|
|
return #self.Index or 0
|
|
end
|
|
|
|
|
|
|
|
--- Copies the Filter criteria from a given Set (for rebuilding a new Set based on an existing Set).
|
|
-- @param #SET_BASE self
|
|
-- @param #SET_BASE BaseSet
|
|
-- @return #SET_BASE
|
|
function SET_BASE:SetDatabase( BaseSet )
|
|
|
|
-- Copy the filter criteria of the BaseSet
|
|
local OtherFilter = routines.utils.deepCopy( BaseSet.Filter )
|
|
self.Filter = OtherFilter
|
|
|
|
-- Now base the new Set on the BaseSet
|
|
self.Database = BaseSet:GetSet()
|
|
return self
|
|
end
|
|
|
|
|
|
|
|
--- Define the SET iterator **"yield interval"** and the **"time interval"**.
|
|
-- @param #SET_BASE self
|
|
-- @param #number YieldInterval Sets the frequency when the iterator loop will yield after the number of objects processed. The default frequency is 10 objects processed.
|
|
-- @param #number TimeInterval Sets the time in seconds when the main logic will resume the iterator loop. The default time is 0.001 seconds.
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:SetIteratorIntervals( YieldInterval, TimeInterval )
|
|
|
|
self.YieldInterval = YieldInterval
|
|
self.TimeInterval = TimeInterval
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Filters for the defined collection.
|
|
-- @param #SET_BASE self
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:FilterOnce()
|
|
|
|
for ObjectName, Object in pairs( self.Database ) do
|
|
|
|
if self:IsIncludeObject( Object ) then
|
|
self:Add( ObjectName, Object )
|
|
end
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Starts the filtering for the defined collection.
|
|
-- @param #SET_BASE self
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:_FilterStart()
|
|
|
|
for ObjectName, Object in pairs( self.Database ) do
|
|
|
|
if self:IsIncludeObject( Object ) then
|
|
self:E( { "Adding Object:", ObjectName } )
|
|
self:Add( ObjectName, Object )
|
|
end
|
|
end
|
|
|
|
self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
|
|
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
|
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
|
|
|
-- Follow alive players and clients
|
|
self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit )
|
|
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit )
|
|
|
|
|
|
return self
|
|
end
|
|
|
|
--- Starts the filtering of the Dead events for the collection.
|
|
-- @param #SET_BASE self
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:FilterDeads()
|
|
|
|
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Starts the filtering of the Crash events for the collection.
|
|
-- @param #SET_BASE self
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:FilterCrashes()
|
|
|
|
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Stops the filtering for the defined collection.
|
|
-- @param #SET_BASE self
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:FilterStop()
|
|
|
|
self:UnHandleEvent( EVENTS.Birth )
|
|
self:UnHandleEvent( EVENTS.Dead )
|
|
self:UnHandleEvent( EVENTS.Crash )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_BASE while identifying the nearest object from a @{Point#POINT_VEC2}.
|
|
-- @param #SET_BASE self
|
|
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest object in the set.
|
|
-- @return Core.Base#BASE The closest object.
|
|
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
|
|
self:F2( PointVec2 )
|
|
|
|
local NearestObject = nil
|
|
local ClosestDistance = nil
|
|
|
|
for ObjectID, ObjectData in pairs( self.Set ) do
|
|
if NearestObject == nil then
|
|
NearestObject = ObjectData
|
|
ClosestDistance = PointVec2:DistanceFromVec2( ObjectData:GetVec2() )
|
|
else
|
|
local Distance = PointVec2:DistanceFromVec2( ObjectData:GetVec2() )
|
|
if Distance < ClosestDistance then
|
|
NearestObject = ObjectData
|
|
ClosestDistance = Distance
|
|
end
|
|
end
|
|
end
|
|
|
|
return NearestObject
|
|
end
|
|
|
|
|
|
|
|
----- Private method that registers all alive players in the mission.
|
|
---- @param #SET_BASE self
|
|
---- @return #SET_BASE self
|
|
--function SET_BASE:_RegisterPlayers()
|
|
--
|
|
-- local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) }
|
|
-- for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
|
-- for UnitId, UnitData in pairs( CoalitionData ) do
|
|
-- self:T3( { "UnitData:", UnitData } )
|
|
-- if UnitData and UnitData:isExist() then
|
|
-- local UnitName = UnitData:getName()
|
|
-- if not self.PlayersAlive[UnitName] then
|
|
-- self:E( { "Add player for unit:", UnitName, UnitData:getPlayerName() } )
|
|
-- self.PlayersAlive[UnitName] = UnitData:getPlayerName()
|
|
-- end
|
|
-- end
|
|
-- end
|
|
-- end
|
|
--
|
|
-- return self
|
|
--end
|
|
|
|
--- Events
|
|
|
|
--- Handles the OnBirth event for the Set.
|
|
-- @param #SET_BASE self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
function SET_BASE:_EventOnBirth( Event )
|
|
self:F3( { Event } )
|
|
|
|
if Event.IniDCSUnit then
|
|
local ObjectName, Object = self:AddInDatabase( Event )
|
|
self:T3( ObjectName, Object )
|
|
if Object and self:IsIncludeObject( Object ) then
|
|
self:Add( ObjectName, Object )
|
|
--self:_EventOnPlayerEnterUnit( Event )
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Handles the OnDead or OnCrash event for alive units set.
|
|
-- @param #SET_BASE self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
function SET_BASE:_EventOnDeadOrCrash( Event )
|
|
self:F3( { Event } )
|
|
|
|
if Event.IniDCSUnit then
|
|
local ObjectName, Object = self:FindInDatabase( Event )
|
|
if ObjectName then
|
|
self:Remove( ObjectName )
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Handles the OnPlayerEnterUnit event to fill the active players table (with the unit filter applied).
|
|
-- @param #SET_BASE self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
function SET_BASE:_EventOnPlayerEnterUnit( Event )
|
|
self:F3( { Event } )
|
|
|
|
if Event.IniDCSUnit then
|
|
local ObjectName, Object = self:AddInDatabase( Event )
|
|
self:T3( ObjectName, Object )
|
|
if self:IsIncludeObject( Object ) then
|
|
self:Add( ObjectName, Object )
|
|
--self:_EventOnPlayerEnterUnit( Event )
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Handles the OnPlayerLeaveUnit event to clean the active players table.
|
|
-- @param #SET_BASE self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
function SET_BASE:_EventOnPlayerLeaveUnit( Event )
|
|
self:F3( { Event } )
|
|
|
|
local ObjectName = Event.IniDCSUnit
|
|
if Event.IniDCSUnit then
|
|
if Event.IniDCSGroup then
|
|
local GroupUnits = Event.IniDCSGroup:getUnits()
|
|
local PlayerCount = 0
|
|
for _, DCSUnit in pairs( GroupUnits ) do
|
|
if DCSUnit ~= Event.IniDCSUnit then
|
|
if DCSUnit:getPlayerName() ~= nil then
|
|
PlayerCount = PlayerCount + 1
|
|
end
|
|
end
|
|
end
|
|
self:E(PlayerCount)
|
|
if PlayerCount == 0 then
|
|
self:Remove( Event.IniDCSGroupName )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Iterators
|
|
|
|
--- Iterate the SET_BASE and derived classes and call an iterator function for the given SET_BASE, providing the Object for each element within the set and optional parameters.
|
|
-- @param #SET_BASE self
|
|
-- @param #function IteratorFunction The function that will be called.
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArguments )
|
|
self:F3( arg )
|
|
|
|
Set = Set or self:GetSet()
|
|
arg = arg or {}
|
|
|
|
local function CoRoutine()
|
|
local Count = 0
|
|
for ObjectID, ObjectData in pairs( Set ) do
|
|
local Object = ObjectData
|
|
self:T3( Object )
|
|
if Function then
|
|
if Function( unpack( FunctionArguments ), Object ) == true then
|
|
IteratorFunction( Object, unpack( arg ) )
|
|
end
|
|
else
|
|
IteratorFunction( Object, unpack( arg ) )
|
|
end
|
|
Count = Count + 1
|
|
-- if Count % self.YieldInterval == 0 then
|
|
-- coroutine.yield( false )
|
|
-- end
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- local co = coroutine.create( CoRoutine )
|
|
local co = CoRoutine
|
|
|
|
local function Schedule()
|
|
|
|
-- local status, res = coroutine.resume( co )
|
|
local status, res = co()
|
|
self:T3( { status, res } )
|
|
|
|
if status == false then
|
|
error( res )
|
|
end
|
|
if res == false then
|
|
return true -- resume next time the loop
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
--self.CallScheduler:Schedule( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 )
|
|
Schedule()
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
----- Iterate the SET_BASE and call an interator function for each **alive** unit, providing the Unit and optional parameters.
|
|
---- @param #SET_BASE self
|
|
---- @param #function IteratorFunction The function that will be called when there is an alive unit in the SET_BASE. The function needs to accept a UNIT parameter.
|
|
---- @return #SET_BASE self
|
|
--function SET_BASE:ForEachDCSUnitAlive( IteratorFunction, ... )
|
|
-- self:F3( arg )
|
|
--
|
|
-- self:ForEach( IteratorFunction, arg, self.DCSUnitsAlive )
|
|
--
|
|
-- return self
|
|
--end
|
|
--
|
|
----- Iterate the SET_BASE and call an interator function for each **alive** player, providing the Unit of the player and optional parameters.
|
|
---- @param #SET_BASE self
|
|
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a UNIT parameter.
|
|
---- @return #SET_BASE self
|
|
--function SET_BASE:ForEachPlayer( IteratorFunction, ... )
|
|
-- self:F3( arg )
|
|
--
|
|
-- self:ForEach( IteratorFunction, arg, self.PlayersAlive )
|
|
--
|
|
-- return self
|
|
--end
|
|
--
|
|
--
|
|
----- Iterate the SET_BASE and call an interator function for each client, providing the Client to the function and optional parameters.
|
|
---- @param #SET_BASE self
|
|
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a CLIENT parameter.
|
|
---- @return #SET_BASE self
|
|
--function SET_BASE:ForEachClient( IteratorFunction, ... )
|
|
-- self:F3( arg )
|
|
--
|
|
-- self:ForEach( IteratorFunction, arg, self.Clients )
|
|
--
|
|
-- return self
|
|
--end
|
|
|
|
|
|
--- Decides whether to include the Object
|
|
-- @param #SET_BASE self
|
|
-- @param #table Object
|
|
-- @return #SET_BASE self
|
|
function SET_BASE:IsIncludeObject( Object )
|
|
self:F3( Object )
|
|
|
|
return true
|
|
end
|
|
|
|
--- Flushes the current SET_BASE contents in the log ... (for debugging reasons).
|
|
-- @param #SET_BASE self
|
|
-- @return #string A string with the names of the objects.
|
|
function SET_BASE:Flush()
|
|
self:F3()
|
|
|
|
local ObjectNames = ""
|
|
for ObjectName, Object in pairs( self.Set ) do
|
|
ObjectNames = ObjectNames .. ObjectName .. ", "
|
|
end
|
|
self:E( { "Objects in Set:", ObjectNames } )
|
|
|
|
return ObjectNames
|
|
end
|
|
|
|
|
|
--- @type SET_GROUP
|
|
-- @extends Core.Set#SET_BASE
|
|
|
|
--- # 2) SET_GROUP class, extends @{Set#SET_BASE}
|
|
--
|
|
-- Mission designers can use the @{Set#SET_GROUP} class to build sets of groups belonging to certain:
|
|
--
|
|
-- * Coalitions
|
|
-- * Categories
|
|
-- * Countries
|
|
-- * Starting with certain prefix strings.
|
|
--
|
|
-- ## 2.1) SET_GROUP constructor
|
|
--
|
|
-- Create a new SET_GROUP object with the @{#SET_GROUP.New} method:
|
|
--
|
|
-- * @{#SET_GROUP.New}: Creates a new SET_GROUP object.
|
|
--
|
|
-- ## 2.2) Add or Remove GROUP(s) from SET_GROUP
|
|
--
|
|
-- GROUPS can be added and removed using the @{Set#SET_GROUP.AddGroupsByName} and @{Set#SET_GROUP.RemoveGroupsByName} respectively.
|
|
-- These methods take a single GROUP name or an array of GROUP names to be added or removed from SET_GROUP.
|
|
--
|
|
-- ## 2.3) SET_GROUP filter criteria
|
|
--
|
|
-- You can set filter criteria to define the set of groups within the SET_GROUP.
|
|
-- Filter criteria are defined by:
|
|
--
|
|
-- * @{#SET_GROUP.FilterCoalitions}: Builds the SET_GROUP with the groups belonging to the coalition(s).
|
|
-- * @{#SET_GROUP.FilterCategories}: Builds the SET_GROUP with the groups belonging to the category(ies).
|
|
-- * @{#SET_GROUP.FilterCountries}: Builds the SET_GROUP with the gruops belonging to the country(ies).
|
|
-- * @{#SET_GROUP.FilterPrefixes}: Builds the SET_GROUP with the groups starting with the same prefix string(s).
|
|
--
|
|
-- Once the filter criteria have been set for the SET_GROUP, you can start filtering using:
|
|
--
|
|
-- * @{#SET_GROUP.FilterStart}: Starts the filtering of the groups within the SET_GROUP and add or remove GROUP objects **dynamically**.
|
|
--
|
|
-- Planned filter criteria within development are (so these are not yet available):
|
|
--
|
|
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Zone#ZONE}.
|
|
--
|
|
-- ## 2.4) SET_GROUP iterators
|
|
--
|
|
-- Once the filters have been defined and the SET_GROUP has been built, you can iterate the SET_GROUP with the available iterator methods.
|
|
-- The iterator methods will walk the SET_GROUP set, and call for each element within the set a function that you provide.
|
|
-- The following iterator methods are currently available within the SET_GROUP:
|
|
--
|
|
-- * @{#SET_GROUP.ForEachGroup}: Calls a function for each alive group it finds within the SET_GROUP.
|
|
-- * @{#SET_GROUP.ForEachGroupCompletelyInZone}: Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence completely in a @{Zone}, providing the GROUP and optional parameters to the called function.
|
|
-- * @{#SET_GROUP.ForEachGroupPartlyInZone}: Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence partly in a @{Zone}, providing the GROUP and optional parameters to the called function.
|
|
-- * @{#SET_GROUP.ForEachGroupNotInZone}: Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence not in a @{Zone}, providing the GROUP and optional parameters to the called function.
|
|
--
|
|
-- ===
|
|
-- @field #SET_GROUP SET_GROUP
|
|
SET_GROUP = {
|
|
ClassName = "SET_GROUP",
|
|
Filter = {
|
|
Coalitions = nil,
|
|
Categories = nil,
|
|
Countries = nil,
|
|
GroupPrefixes = nil,
|
|
},
|
|
FilterMeta = {
|
|
Coalitions = {
|
|
red = coalition.side.RED,
|
|
blue = coalition.side.BLUE,
|
|
neutral = coalition.side.NEUTRAL,
|
|
},
|
|
Categories = {
|
|
plane = Group.Category.AIRPLANE,
|
|
helicopter = Group.Category.HELICOPTER,
|
|
ground = Group.Category.GROUND_UNIT,
|
|
ship = Group.Category.SHIP,
|
|
structure = Group.Category.STRUCTURE,
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
--- Creates a new SET_GROUP object, building a set of groups belonging to a coalitions, categories, countries, types or with defined prefix names.
|
|
-- @param #SET_GROUP self
|
|
-- @return #SET_GROUP
|
|
-- @usage
|
|
-- -- Define a new SET_GROUP Object. This DBObject will contain a reference to all alive GROUPS.
|
|
-- DBObject = SET_GROUP:New()
|
|
function SET_GROUP:New()
|
|
|
|
-- Inherits from BASE
|
|
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.GROUPS ) )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Add GROUP(s) to SET_GROUP.
|
|
-- @param Core.Set#SET_GROUP self
|
|
-- @param #string AddGroupNames A single name or an array of GROUP names.
|
|
-- @return self
|
|
function SET_GROUP:AddGroupsByName( AddGroupNames )
|
|
|
|
local AddGroupNamesArray = ( type( AddGroupNames ) == "table" ) and AddGroupNames or { AddGroupNames }
|
|
|
|
for AddGroupID, AddGroupName in pairs( AddGroupNamesArray ) do
|
|
self:Add( AddGroupName, GROUP:FindByName( AddGroupName ) )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Remove GROUP(s) from SET_GROUP.
|
|
-- @param Core.Set#SET_GROUP self
|
|
-- @param Wrapper.Group#GROUP RemoveGroupNames A single name or an array of GROUP names.
|
|
-- @return self
|
|
function SET_GROUP:RemoveGroupsByName( RemoveGroupNames )
|
|
|
|
local RemoveGroupNamesArray = ( type( RemoveGroupNames ) == "table" ) and RemoveGroupNames or { RemoveGroupNames }
|
|
|
|
for RemoveGroupID, RemoveGroupName in pairs( RemoveGroupNamesArray ) do
|
|
self:Remove( RemoveGroupName.GroupName )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Finds a Group based on the Group Name.
|
|
-- @param #SET_GROUP self
|
|
-- @param #string GroupName
|
|
-- @return Wrapper.Group#GROUP The found Group.
|
|
function SET_GROUP:FindGroup( GroupName )
|
|
|
|
local GroupFound = self.Set[GroupName]
|
|
return GroupFound
|
|
end
|
|
|
|
--- Iterate the SET_GROUP while identifying the nearest object from a @{Point#POINT_VEC2}.
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest object in the set.
|
|
-- @return Wrapper.Group#GROUP The closest group.
|
|
function SET_GROUP:FindNearestGroupFromPointVec2( PointVec2 )
|
|
self:F2( PointVec2 )
|
|
|
|
local NearestGroup = nil
|
|
local ClosestDistance = nil
|
|
|
|
for ObjectID, ObjectData in pairs( self.Set ) do
|
|
if NearestGroup == nil then
|
|
NearestGroup = ObjectData
|
|
ClosestDistance = PointVec2:DistanceFromVec2( ObjectData:GetVec2() )
|
|
else
|
|
local Distance = PointVec2:DistanceFromVec2( ObjectData:GetVec2() )
|
|
if Distance < ClosestDistance then
|
|
NearestGroup = ObjectData
|
|
ClosestDistance = Distance
|
|
end
|
|
end
|
|
end
|
|
|
|
return NearestGroup
|
|
end
|
|
|
|
|
|
--- Builds a set of groups of coalitions.
|
|
-- Possible current coalitions are red, blue and neutral.
|
|
-- @param #SET_GROUP self
|
|
-- @param #string Coalitions Can take the following values: "red", "blue", "neutral".
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:FilterCoalitions( Coalitions )
|
|
if not self.Filter.Coalitions then
|
|
self.Filter.Coalitions = {}
|
|
end
|
|
if type( Coalitions ) ~= "table" then
|
|
Coalitions = { Coalitions }
|
|
end
|
|
for CoalitionID, Coalition in pairs( Coalitions ) do
|
|
self.Filter.Coalitions[Coalition] = Coalition
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of groups out of categories.
|
|
-- Possible current categories are plane, helicopter, ground, ship.
|
|
-- @param #SET_GROUP self
|
|
-- @param #string Categories Can take the following values: "plane", "helicopter", "ground", "ship".
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:FilterCategories( Categories )
|
|
if not self.Filter.Categories then
|
|
self.Filter.Categories = {}
|
|
end
|
|
if type( Categories ) ~= "table" then
|
|
Categories = { Categories }
|
|
end
|
|
for CategoryID, Category in pairs( Categories ) do
|
|
self.Filter.Categories[Category] = Category
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- Builds a set of groups of defined countries.
|
|
-- Possible current countries are those known within DCS world.
|
|
-- @param #SET_GROUP self
|
|
-- @param #string Countries Can take those country strings known within DCS world.
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:FilterCountries( Countries )
|
|
if not self.Filter.Countries then
|
|
self.Filter.Countries = {}
|
|
end
|
|
if type( Countries ) ~= "table" then
|
|
Countries = { Countries }
|
|
end
|
|
for CountryID, Country in pairs( Countries ) do
|
|
self.Filter.Countries[Country] = Country
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of groups of defined GROUP prefixes.
|
|
-- All the groups starting with the given prefixes will be included within the set.
|
|
-- @param #SET_GROUP self
|
|
-- @param #string Prefixes The prefix of which the group name starts with.
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:FilterPrefixes( Prefixes )
|
|
if not self.Filter.GroupPrefixes then
|
|
self.Filter.GroupPrefixes = {}
|
|
end
|
|
if type( Prefixes ) ~= "table" then
|
|
Prefixes = { Prefixes }
|
|
end
|
|
for PrefixID, Prefix in pairs( Prefixes ) do
|
|
self.Filter.GroupPrefixes[Prefix] = Prefix
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Starts the filtering.
|
|
-- @param #SET_GROUP self
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:FilterStart()
|
|
|
|
if _DATABASE then
|
|
self:_FilterStart()
|
|
end
|
|
|
|
|
|
|
|
return self
|
|
end
|
|
|
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the GROUP
|
|
-- @return #table The GROUP
|
|
function SET_GROUP:AddInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
if Event.IniObjectCategory == 1 then
|
|
if not self.Database[Event.IniDCSGroupName] then
|
|
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
|
self:T3( self.Database[Event.IniDCSGroupName] )
|
|
end
|
|
end
|
|
|
|
return Event.IniDCSGroupName, self.Database[Event.IniDCSGroupName]
|
|
end
|
|
|
|
--- Handles the Database to check on any event that Object exists in the Database.
|
|
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the GROUP
|
|
-- @return #table The GROUP
|
|
function SET_GROUP:FindInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
return Event.IniDCSGroupName, self.Database[Event.IniDCSGroupName]
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and call an iterator function for each **alive** GROUP, providing the GROUP and optional parameters.
|
|
-- @param #SET_GROUP self
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the SET_GROUP. The function needs to accept a GROUP parameter.
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:ForEachGroup( IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence completely in a @{Zone}, providing the GROUP and optional parameters to the called function.
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the SET_GROUP. The function needs to accept a GROUP parameter.
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:ForEachGroupCompletelyInZone( ZoneObject, IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set,
|
|
--- @param Core.Zone#ZONE_BASE ZoneObject
|
|
-- @param Wrapper.Group#GROUP GroupObject
|
|
function( ZoneObject, GroupObject )
|
|
if GroupObject:IsCompletelyInZone( ZoneObject ) then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end, { ZoneObject } )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence partly in a @{Zone}, providing the GROUP and optional parameters to the called function.
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the SET_GROUP. The function needs to accept a GROUP parameter.
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:ForEachGroupPartlyInZone( ZoneObject, IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set,
|
|
--- @param Core.Zone#ZONE_BASE ZoneObject
|
|
-- @param Wrapper.Group#GROUP GroupObject
|
|
function( ZoneObject, GroupObject )
|
|
if GroupObject:IsPartlyInZone( ZoneObject ) then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end, { ZoneObject } )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence not in a @{Zone}, providing the GROUP and optional parameters to the called function.
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the SET_GROUP. The function needs to accept a GROUP parameter.
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:ForEachGroupNotInZone( ZoneObject, IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set,
|
|
--- @param Core.Zone#ZONE_BASE ZoneObject
|
|
-- @param Wrapper.Group#GROUP GroupObject
|
|
function( ZoneObject, GroupObject )
|
|
if GroupObject:IsNotInZone( ZoneObject ) then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end, { ZoneObject } )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and return true if all the @{Wrapper.Group#GROUP} are completely in the @{Core.Zone#ZONE}
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @return #boolean true if all the @{Wrapper.Group#GROUP} are completly in the @{Core.Zone#ZONE}, false otherwise
|
|
-- @usage
|
|
-- local MyZone = ZONE:New("Zone1")
|
|
-- local MySetGroup = SET_GROUP:New()
|
|
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
|
|
--
|
|
-- if MySetGroup:AllCompletelyInZone(MyZone) then
|
|
-- MESSAGE:New("All the SET's GROUP are in zone !", 10):ToAll()
|
|
-- else
|
|
-- MESSAGE:New("Some or all SET's GROUP are outside zone !", 10):ToAll()
|
|
-- end
|
|
function SET_GROUP:AllCompletelyInZone(Zone)
|
|
self:F2(Zone)
|
|
local Set = self:GetSet()
|
|
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
|
|
if not GroupData:IsCompletelyInZone(Zone) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and return true if at least one of the @{Wrapper.Group#GROUP} is completely inside the @{Core.Zone#ZONE}
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is completly inside the @{Core.Zone#ZONE}, false otherwise.
|
|
-- @usage
|
|
-- local MyZone = ZONE:New("Zone1")
|
|
-- local MySetGroup = SET_GROUP:New()
|
|
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
|
|
--
|
|
-- if MySetGroup:AnyCompletelyInZone(MyZone) then
|
|
-- MESSAGE:New("At least one GROUP is completely in zone !", 10):ToAll()
|
|
-- else
|
|
-- MESSAGE:New("No GROUP is completely in zone !", 10):ToAll()
|
|
-- end
|
|
function SET_GROUP:AnyCompletelyInZone(Zone)
|
|
self:F2(Zone)
|
|
local Set = self:GetSet()
|
|
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
|
|
if GroupData:IsCompletelyInZone(Zone) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and return true if at least one @{#UNIT} of one @{GROUP} of the @{SET_GROUP} is in @{ZONE}
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completly inside the @{Core.Zone#ZONE}, false otherwise.
|
|
-- @usage
|
|
-- local MyZone = ZONE:New("Zone1")
|
|
-- local MySetGroup = SET_GROUP:New()
|
|
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
|
|
--
|
|
-- if MySetGroup:AnyPartlyInZone(MyZone) then
|
|
-- MESSAGE:New("At least one GROUP has at least one UNIT in zone !", 10):ToAll()
|
|
-- else
|
|
-- MESSAGE:New("No UNIT of any GROUP is in zone !", 10):ToAll()
|
|
-- end
|
|
function SET_GROUP:AnyInZone(Zone)
|
|
self:F2(Zone)
|
|
local Set = self:GetSet()
|
|
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
|
|
if GroupData:IsPartlyInZone(Zone) or GroupData:IsCompletelyInZone(Zone) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and return true if at least one @{GROUP} of the @{SET_GROUP} is partly in @{ZONE}.
|
|
-- Will return false if a @{GROUP} is fully in the @{ZONE}
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completly inside the @{Core.Zone#ZONE}, false otherwise.
|
|
-- @usage
|
|
-- local MyZone = ZONE:New("Zone1")
|
|
-- local MySetGroup = SET_GROUP:New()
|
|
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
|
|
--
|
|
-- if MySetGroup:AnyPartlyInZone(MyZone) then
|
|
-- MESSAGE:New("At least one GROUP is partially in the zone, but none are fully in it !", 10):ToAll()
|
|
-- else
|
|
-- MESSAGE:New("No GROUP are in zone, or one GROUP is completely in it !", 10):ToAll()
|
|
-- end
|
|
function SET_GROUP:AnyPartlyInZone(Zone)
|
|
self:F2(Zone)
|
|
local IsPartlyInZone = false
|
|
local Set = self:GetSet()
|
|
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
|
|
if GroupData:IsCompletelyInZone(Zone) then
|
|
return false
|
|
elseif GroupData:IsPartlyInZone(Zone) then
|
|
IsPartlyInZone = true -- at least one GROUP is partly in zone
|
|
end
|
|
end
|
|
|
|
if IsPartlyInZone then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and return true if no @{GROUP} of the @{SET_GROUP} is in @{ZONE}
|
|
-- This could also be achieved with `not SET_GROUP:AnyPartlyInZone(Zone)`, but it's easier for the
|
|
-- mission designer to add a dedicated method
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @return #boolean true if no @{Wrapper.Group#GROUP} is inside the @{Core.Zone#ZONE} in any way, false otherwise.
|
|
-- @usage
|
|
-- local MyZone = ZONE:New("Zone1")
|
|
-- local MySetGroup = SET_GROUP:New()
|
|
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
|
|
--
|
|
-- if MySetGroup:NoneInZone(MyZone) then
|
|
-- MESSAGE:New("No GROUP is completely in zone !", 10):ToAll()
|
|
-- else
|
|
-- MESSAGE:New("No UNIT of any GROUP is in zone !", 10):ToAll()
|
|
-- end
|
|
function SET_GROUP:NoneInZone(Zone)
|
|
self:F2(Zone)
|
|
local Set = self:GetSet()
|
|
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
|
|
if not GroupData:IsNotInZone(Zone) then -- If the GROUP is in Zone in any way
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and count how many GROUPs are completely in the Zone
|
|
-- That could easily be done with SET_GROUP:ForEachGroupCompletelyInZone(), but this function
|
|
-- provides an easy to use shortcut...
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @return #number the number of GROUPs completely in the Zone
|
|
-- @usage
|
|
-- local MyZone = ZONE:New("Zone1")
|
|
-- local MySetGroup = SET_GROUP:New()
|
|
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
|
|
--
|
|
-- MESSAGE:New("There are " .. MySetGroup:CountInZone(MyZone) .. " GROUPs in the Zone !", 10):ToAll()
|
|
function SET_GROUP:CountInZone(Zone)
|
|
self:F2(Zone)
|
|
local Count = 0
|
|
local Set = self:GetSet()
|
|
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
|
|
if GroupData:IsCompletelyInZone(Zone) then
|
|
Count = Count + 1
|
|
end
|
|
end
|
|
return Count
|
|
end
|
|
|
|
--- Iterate the SET_GROUP and count how many UNITs are completely in the Zone
|
|
-- @param #SET_GROUP self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @return #number the number of GROUPs completely in the Zone
|
|
-- @usage
|
|
-- local MyZone = ZONE:New("Zone1")
|
|
-- local MySetGroup = SET_GROUP:New()
|
|
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
|
|
--
|
|
-- MESSAGE:New("There are " .. MySetGroup:CountUnitInZone(MyZone) .. " UNITs in the Zone !", 10):ToAll()
|
|
function SET_GROUP:CountUnitInZone(Zone)
|
|
self:F2(Zone)
|
|
local Count = 0
|
|
local Set = self:GetSet()
|
|
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
|
|
if GroupData:IsCompletelyInZone(Zone) then
|
|
Count = Count + 1
|
|
end
|
|
end
|
|
return Count
|
|
end
|
|
|
|
----- Iterate the SET_GROUP and call an interator function for each **alive** player, providing the Group of the player and optional parameters.
|
|
---- @param #SET_GROUP self
|
|
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a GROUP parameter.
|
|
---- @return #SET_GROUP self
|
|
--function SET_GROUP:ForEachPlayer( IteratorFunction, ... )
|
|
-- self:F2( arg )
|
|
--
|
|
-- self:ForEach( IteratorFunction, arg, self.PlayersAlive )
|
|
--
|
|
-- return self
|
|
--end
|
|
--
|
|
--
|
|
----- Iterate the SET_GROUP and call an interator function for each client, providing the Client to the function and optional parameters.
|
|
---- @param #SET_GROUP self
|
|
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a CLIENT parameter.
|
|
---- @return #SET_GROUP self
|
|
--function SET_GROUP:ForEachClient( IteratorFunction, ... )
|
|
-- self:F2( arg )
|
|
--
|
|
-- self:ForEach( IteratorFunction, arg, self.Clients )
|
|
--
|
|
-- return self
|
|
--end
|
|
|
|
|
|
---
|
|
-- @param #SET_GROUP self
|
|
-- @param Wrapper.Group#GROUP MooseGroup
|
|
-- @return #SET_GROUP self
|
|
function SET_GROUP:IsIncludeObject( MooseGroup )
|
|
self:F2( MooseGroup )
|
|
local MooseGroupInclude = true
|
|
|
|
if self.Filter.Coalitions then
|
|
local MooseGroupCoalition = false
|
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
|
self:T3( { "Coalition:", MooseGroup:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
|
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == MooseGroup:GetCoalition() then
|
|
MooseGroupCoalition = true
|
|
end
|
|
end
|
|
MooseGroupInclude = MooseGroupInclude and MooseGroupCoalition
|
|
end
|
|
|
|
if self.Filter.Categories then
|
|
local MooseGroupCategory = false
|
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
|
self:T3( { "Category:", MooseGroup:GetCategory(), self.FilterMeta.Categories[CategoryName], CategoryName } )
|
|
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == MooseGroup:GetCategory() then
|
|
MooseGroupCategory = true
|
|
end
|
|
end
|
|
MooseGroupInclude = MooseGroupInclude and MooseGroupCategory
|
|
end
|
|
|
|
if self.Filter.Countries then
|
|
local MooseGroupCountry = false
|
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
|
self:T3( { "Country:", MooseGroup:GetCountry(), CountryName } )
|
|
if country.id[CountryName] == MooseGroup:GetCountry() then
|
|
MooseGroupCountry = true
|
|
end
|
|
end
|
|
MooseGroupInclude = MooseGroupInclude and MooseGroupCountry
|
|
end
|
|
|
|
if self.Filter.GroupPrefixes then
|
|
local MooseGroupPrefix = false
|
|
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
|
self:T3( { "Prefix:", string.find( MooseGroup:GetName(), GroupPrefix, 1 ), GroupPrefix } )
|
|
if string.find( MooseGroup:GetName(), GroupPrefix, 1 ) then
|
|
MooseGroupPrefix = true
|
|
end
|
|
end
|
|
MooseGroupInclude = MooseGroupInclude and MooseGroupPrefix
|
|
end
|
|
|
|
self:T2( MooseGroupInclude )
|
|
return MooseGroupInclude
|
|
end
|
|
|
|
--- @type SET_UNIT
|
|
-- @extends Core.Set#SET_BASE
|
|
|
|
--- # 3) SET_UNIT class, extends @{Set#SET_BASE}
|
|
--
|
|
-- Mission designers can use the SET_UNIT class to build sets of units belonging to certain:
|
|
--
|
|
-- * Coalitions
|
|
-- * Categories
|
|
-- * Countries
|
|
-- * Unit types
|
|
-- * Starting with certain prefix strings.
|
|
--
|
|
-- ## 3.1) SET_UNIT constructor
|
|
--
|
|
-- Create a new SET_UNIT object with the @{#SET_UNIT.New} method:
|
|
--
|
|
-- * @{#SET_UNIT.New}: Creates a new SET_UNIT object.
|
|
--
|
|
-- ## 3.2) Add or Remove UNIT(s) from SET_UNIT
|
|
--
|
|
-- UNITs can be added and removed using the @{Set#SET_UNIT.AddUnitsByName} and @{Set#SET_UNIT.RemoveUnitsByName} respectively.
|
|
-- These methods take a single UNIT name or an array of UNIT names to be added or removed from SET_UNIT.
|
|
--
|
|
-- ## 3.3) SET_UNIT filter criteria
|
|
--
|
|
-- You can set filter criteria to define the set of units within the SET_UNIT.
|
|
-- Filter criteria are defined by:
|
|
--
|
|
-- * @{#SET_UNIT.FilterCoalitions}: Builds the SET_UNIT with the units belonging to the coalition(s).
|
|
-- * @{#SET_UNIT.FilterCategories}: Builds the SET_UNIT with the units belonging to the category(ies).
|
|
-- * @{#SET_UNIT.FilterTypes}: Builds the SET_UNIT with the units belonging to the unit type(s).
|
|
-- * @{#SET_UNIT.FilterCountries}: Builds the SET_UNIT with the units belonging to the country(ies).
|
|
-- * @{#SET_UNIT.FilterPrefixes}: Builds the SET_UNIT with the units starting with the same prefix string(s).
|
|
--
|
|
-- Once the filter criteria have been set for the SET_UNIT, you can start filtering using:
|
|
--
|
|
-- * @{#SET_UNIT.FilterStart}: Starts the filtering of the units within the SET_UNIT.
|
|
--
|
|
-- Planned filter criteria within development are (so these are not yet available):
|
|
--
|
|
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Zone#ZONE}.
|
|
--
|
|
-- ## 3.4) SET_UNIT iterators
|
|
--
|
|
-- Once the filters have been defined and the SET_UNIT has been built, you can iterate the SET_UNIT with the available iterator methods.
|
|
-- The iterator methods will walk the SET_UNIT set, and call for each element within the set a function that you provide.
|
|
-- The following iterator methods are currently available within the SET_UNIT:
|
|
--
|
|
-- * @{#SET_UNIT.ForEachUnit}: Calls a function for each alive unit it finds within the SET_UNIT.
|
|
-- * @{#SET_GROUP.ForEachGroupCompletelyInZone}: Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence completely in a @{Zone}, providing the GROUP and optional parameters to the called function.
|
|
-- * @{#SET_GROUP.ForEachGroupNotInZone}: Iterate the SET_GROUP and call an iterator function for each **alive** GROUP presence not in a @{Zone}, providing the GROUP and optional parameters to the called function.
|
|
--
|
|
-- Planned iterators methods in development are (so these are not yet available):
|
|
--
|
|
-- * @{#SET_UNIT.ForEachUnitInUnit}: Calls a function for each unit contained within the SET_UNIT.
|
|
-- * @{#SET_UNIT.ForEachUnitCompletelyInZone}: Iterate and call an iterator function for each **alive** UNIT presence completely in a @{Zone}, providing the UNIT and optional parameters to the called function.
|
|
-- * @{#SET_UNIT.ForEachUnitNotInZone}: Iterate and call an iterator function for each **alive** UNIT presence not in a @{Zone}, providing the UNIT and optional parameters to the called function.
|
|
--
|
|
-- ## 3.5 ) SET_UNIT atomic methods
|
|
--
|
|
-- Various methods exist for a SET_UNIT to perform actions or calculations and retrieve results from the SET_UNIT:
|
|
--
|
|
-- * @{#SET_UNIT.GetTypeNames}(): Retrieve the type names of the @{Unit}s in the SET, delimited by a comma.
|
|
--
|
|
-- ===
|
|
-- @field #SET_UNIT SET_UNIT
|
|
SET_UNIT = {
|
|
ClassName = "SET_UNIT",
|
|
Units = {},
|
|
Filter = {
|
|
Coalitions = nil,
|
|
Categories = nil,
|
|
Types = nil,
|
|
Countries = nil,
|
|
UnitPrefixes = nil,
|
|
},
|
|
FilterMeta = {
|
|
Coalitions = {
|
|
red = coalition.side.RED,
|
|
blue = coalition.side.BLUE,
|
|
neutral = coalition.side.NEUTRAL,
|
|
},
|
|
Categories = {
|
|
plane = Unit.Category.AIRPLANE,
|
|
helicopter = Unit.Category.HELICOPTER,
|
|
ground = Unit.Category.GROUND_UNIT,
|
|
ship = Unit.Category.SHIP,
|
|
structure = Unit.Category.STRUCTURE,
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
--- Creates a new SET_UNIT object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
|
|
-- @param #SET_UNIT self
|
|
-- @return #SET_UNIT
|
|
-- @usage
|
|
-- -- Define a new SET_UNIT Object. This DBObject will contain a reference to all alive Units.
|
|
-- DBObject = SET_UNIT:New()
|
|
function SET_UNIT:New()
|
|
|
|
-- Inherits from BASE
|
|
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.UNITS ) )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Add UNIT(s) to SET_UNIT.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string AddUnit A single UNIT.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:AddUnit( AddUnit )
|
|
self:F2( AddUnit:GetName() )
|
|
|
|
self:Add( AddUnit:GetName(), AddUnit )
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Add UNIT(s) to SET_UNIT.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string AddUnitNames A single name or an array of UNIT names.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:AddUnitsByName( AddUnitNames )
|
|
|
|
local AddUnitNamesArray = ( type( AddUnitNames ) == "table" ) and AddUnitNames or { AddUnitNames }
|
|
|
|
self:T( AddUnitNamesArray )
|
|
for AddUnitID, AddUnitName in pairs( AddUnitNamesArray ) do
|
|
self:Add( AddUnitName, UNIT:FindByName( AddUnitName ) )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Remove UNIT(s) from SET_UNIT.
|
|
-- @param Core.Set#SET_UNIT self
|
|
-- @param Wrapper.Unit#UNIT RemoveUnitNames A single name or an array of UNIT names.
|
|
-- @return self
|
|
function SET_UNIT:RemoveUnitsByName( RemoveUnitNames )
|
|
|
|
local RemoveUnitNamesArray = ( type( RemoveUnitNames ) == "table" ) and RemoveUnitNames or { RemoveUnitNames }
|
|
|
|
for RemoveUnitID, RemoveUnitName in pairs( RemoveUnitNamesArray ) do
|
|
self:Remove( RemoveUnitName )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Finds a Unit based on the Unit Name.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string UnitName
|
|
-- @return Wrapper.Unit#UNIT The found Unit.
|
|
function SET_UNIT:FindUnit( UnitName )
|
|
|
|
local UnitFound = self.Set[UnitName]
|
|
return UnitFound
|
|
end
|
|
|
|
|
|
|
|
--- Builds a set of units of coalitions.
|
|
-- Possible current coalitions are red, blue and neutral.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string Coalitions Can take the following values: "red", "blue", "neutral".
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:FilterCoalitions( Coalitions )
|
|
if not self.Filter.Coalitions then
|
|
self.Filter.Coalitions = {}
|
|
end
|
|
if type( Coalitions ) ~= "table" then
|
|
Coalitions = { Coalitions }
|
|
end
|
|
for CoalitionID, Coalition in pairs( Coalitions ) do
|
|
self.Filter.Coalitions[Coalition] = Coalition
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of units out of categories.
|
|
-- Possible current categories are plane, helicopter, ground, ship.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string Categories Can take the following values: "plane", "helicopter", "ground", "ship".
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:FilterCategories( Categories )
|
|
if not self.Filter.Categories then
|
|
self.Filter.Categories = {}
|
|
end
|
|
if type( Categories ) ~= "table" then
|
|
Categories = { Categories }
|
|
end
|
|
for CategoryID, Category in pairs( Categories ) do
|
|
self.Filter.Categories[Category] = Category
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of units of defined unit types.
|
|
-- Possible current types are those types known within DCS world.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string Types Can take those type strings known within DCS world.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:FilterTypes( Types )
|
|
if not self.Filter.Types then
|
|
self.Filter.Types = {}
|
|
end
|
|
if type( Types ) ~= "table" then
|
|
Types = { Types }
|
|
end
|
|
for TypeID, Type in pairs( Types ) do
|
|
self.Filter.Types[Type] = Type
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of units of defined countries.
|
|
-- Possible current countries are those known within DCS world.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string Countries Can take those country strings known within DCS world.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:FilterCountries( Countries )
|
|
if not self.Filter.Countries then
|
|
self.Filter.Countries = {}
|
|
end
|
|
if type( Countries ) ~= "table" then
|
|
Countries = { Countries }
|
|
end
|
|
for CountryID, Country in pairs( Countries ) do
|
|
self.Filter.Countries[Country] = Country
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of units of defined unit prefixes.
|
|
-- All the units starting with the given prefixes will be included within the set.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string Prefixes The prefix of which the unit name starts with.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:FilterPrefixes( Prefixes )
|
|
if not self.Filter.UnitPrefixes then
|
|
self.Filter.UnitPrefixes = {}
|
|
end
|
|
if type( Prefixes ) ~= "table" then
|
|
Prefixes = { Prefixes }
|
|
end
|
|
for PrefixID, Prefix in pairs( Prefixes ) do
|
|
self.Filter.UnitPrefixes[Prefix] = Prefix
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- Builds a set of units having a radar of give types.
|
|
-- All the units having a radar of a given type will be included within the set.
|
|
-- @param #SET_UNIT self
|
|
-- @param #table RadarTypes The radar types.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:FilterHasRadar( RadarTypes )
|
|
|
|
self.Filter.RadarTypes = self.Filter.RadarTypes or {}
|
|
if type( RadarTypes ) ~= "table" then
|
|
RadarTypes = { RadarTypes }
|
|
end
|
|
for RadarTypeID, RadarType in pairs( RadarTypes ) do
|
|
self.Filter.RadarTypes[RadarType] = RadarType
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- Builds a set of SEADable units.
|
|
-- @param #SET_UNIT self
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:FilterHasSEAD()
|
|
|
|
self.Filter.SEAD = true
|
|
return self
|
|
end
|
|
|
|
|
|
|
|
--- Starts the filtering.
|
|
-- @param #SET_UNIT self
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:FilterStart()
|
|
|
|
if _DATABASE then
|
|
self:_FilterStart()
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
|
-- @param #SET_UNIT self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the UNIT
|
|
-- @return #table The UNIT
|
|
function SET_UNIT:AddInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
if Event.IniObjectCategory == 1 then
|
|
if not self.Database[Event.IniDCSUnitName] then
|
|
self.Database[Event.IniDCSUnitName] = UNIT:Register( Event.IniDCSUnitName )
|
|
self:T3( self.Database[Event.IniDCSUnitName] )
|
|
end
|
|
end
|
|
|
|
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
|
end
|
|
|
|
--- Handles the Database to check on any event that Object exists in the Database.
|
|
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
|
-- @param #SET_UNIT self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the UNIT
|
|
-- @return #table The UNIT
|
|
function SET_UNIT:FindInDatabase( Event )
|
|
self:E( { Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName], Event } )
|
|
|
|
|
|
return Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName]
|
|
end
|
|
|
|
--- Iterate the SET_UNIT and call an interator function for each **alive** UNIT, providing the UNIT and optional parameters.
|
|
-- @param #SET_UNIT self
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:ForEachUnit( IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_UNIT and call an iterator function for each **alive** UNIT presence completely in a @{Zone}, providing the UNIT and optional parameters to the called function.
|
|
-- @param #SET_UNIT self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:ForEachUnitCompletelyInZone( ZoneObject, IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set,
|
|
--- @param Core.Zone#ZONE_BASE ZoneObject
|
|
-- @param Wrapper.Unit#UNIT UnitObject
|
|
function( ZoneObject, UnitObject )
|
|
if UnitObject:IsInZone( ZoneObject ) then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end, { ZoneObject } )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_UNIT and call an iterator function for each **alive** UNIT presence not in a @{Zone}, providing the UNIT and optional parameters to the called function.
|
|
-- @param #SET_UNIT self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:ForEachUnitNotInZone( ZoneObject, IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set,
|
|
--- @param Core.Zone#ZONE_BASE ZoneObject
|
|
-- @param Wrapper.Unit#UNIT UnitObject
|
|
function( ZoneObject, UnitObject )
|
|
if UnitObject:IsNotInZone( ZoneObject ) then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end, { ZoneObject } )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Returns map of unit types.
|
|
-- @param #SET_UNIT self
|
|
-- @return #map<#string,#number> A map of the unit types found. The key is the UnitTypeName and the value is the amount of unit types found.
|
|
function SET_UNIT:GetUnitTypes()
|
|
self:F2()
|
|
|
|
local MT = {} -- Message Text
|
|
local UnitTypes = {}
|
|
|
|
for UnitID, UnitData in pairs( self:GetSet() ) do
|
|
local TextUnit = UnitData -- Wrapper.Unit#UNIT
|
|
if TextUnit:IsAlive() then
|
|
local UnitType = TextUnit:GetTypeName()
|
|
|
|
if not UnitTypes[UnitType] then
|
|
UnitTypes[UnitType] = 1
|
|
else
|
|
UnitTypes[UnitType] = UnitTypes[UnitType] + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
for UnitTypeID, UnitType in pairs( UnitTypes ) do
|
|
MT[#MT+1] = UnitType .. " of " .. UnitTypeID
|
|
end
|
|
|
|
return UnitTypes
|
|
end
|
|
|
|
|
|
--- Returns a comma separated string of the unit types with a count in the @{Set}.
|
|
-- @param #SET_UNIT self
|
|
-- @return #string The unit types string
|
|
function SET_UNIT:GetUnitTypesText()
|
|
self:F2()
|
|
|
|
local MT = {} -- Message Text
|
|
local UnitTypes = self:GetUnitTypes()
|
|
|
|
for UnitTypeID, UnitType in pairs( UnitTypes ) do
|
|
MT[#MT+1] = UnitType .. " of " .. UnitTypeID
|
|
end
|
|
|
|
return table.concat( MT, ", " )
|
|
end
|
|
|
|
--- Returns map of unit threat levels.
|
|
-- @param #SET_UNIT self
|
|
-- @return #table.
|
|
function SET_UNIT:GetUnitThreatLevels()
|
|
self:F2()
|
|
|
|
local UnitThreatLevels = {}
|
|
|
|
for UnitID, UnitData in pairs( self:GetSet() ) do
|
|
local ThreatUnit = UnitData -- Wrapper.Unit#UNIT
|
|
if ThreatUnit:IsAlive() then
|
|
local UnitThreatLevel, UnitThreatLevelText = ThreatUnit:GetThreatLevel()
|
|
local ThreatUnitName = ThreatUnit:GetName()
|
|
|
|
UnitThreatLevels[UnitThreatLevel] = UnitThreatLevels[UnitThreatLevel] or {}
|
|
UnitThreatLevels[UnitThreatLevel].UnitThreatLevelText = UnitThreatLevelText
|
|
UnitThreatLevels[UnitThreatLevel].Units = UnitThreatLevels[UnitThreatLevel].Units or {}
|
|
UnitThreatLevels[UnitThreatLevel].Units[ThreatUnitName] = ThreatUnit
|
|
end
|
|
end
|
|
|
|
return UnitThreatLevels
|
|
end
|
|
|
|
--- Calculate the maxium A2G threat level of the SET_UNIT.
|
|
-- @param #SET_UNIT self
|
|
function SET_UNIT:CalculateThreatLevelA2G()
|
|
|
|
local MaxThreatLevelA2G = 0
|
|
for UnitName, UnitData in pairs( self:GetSet() ) 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 if the @{Set} has targets having a radar (of a given type).
|
|
-- @param #SET_UNIT self
|
|
-- @param Dcs.DCSWrapper.Unit#Unit.RadarType RadarType
|
|
-- @return #number The amount of radars in the Set with the given type
|
|
function SET_UNIT:HasRadar( RadarType )
|
|
self:F2( RadarType )
|
|
|
|
local RadarCount = 0
|
|
for UnitID, UnitData in pairs( self:GetSet()) do
|
|
local UnitSensorTest = UnitData -- Wrapper.Unit#UNIT
|
|
local HasSensors
|
|
if RadarType then
|
|
HasSensors = UnitSensorTest:HasSensors( Unit.SensorType.RADAR, RadarType )
|
|
else
|
|
HasSensors = UnitSensorTest:HasSensors( Unit.SensorType.RADAR )
|
|
end
|
|
self:T3(HasSensors)
|
|
if HasSensors then
|
|
RadarCount = RadarCount + 1
|
|
end
|
|
end
|
|
|
|
return RadarCount
|
|
end
|
|
|
|
--- Returns if the @{Set} has targets that can be SEADed.
|
|
-- @param #SET_UNIT self
|
|
-- @return #number The amount of SEADable units in the Set
|
|
function SET_UNIT:HasSEAD()
|
|
self:F2()
|
|
|
|
local SEADCount = 0
|
|
for UnitID, UnitData in pairs( self:GetSet()) do
|
|
local UnitSEAD = UnitData -- Wrapper.Unit#UNIT
|
|
if UnitSEAD:IsAlive() then
|
|
local UnitSEADAttributes = UnitSEAD:GetDesc().attributes
|
|
|
|
local HasSEAD = UnitSEAD:HasSEAD()
|
|
|
|
self:T3(HasSEAD)
|
|
if HasSEAD then
|
|
SEADCount = SEADCount + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
return SEADCount
|
|
end
|
|
|
|
--- Returns if the @{Set} has ground targets.
|
|
-- @param #SET_UNIT self
|
|
-- @return #number The amount of ground targets in the Set.
|
|
function SET_UNIT:HasGroundUnits()
|
|
self:F2()
|
|
|
|
local GroundUnitCount = 0
|
|
for UnitID, UnitData in pairs( self:GetSet()) do
|
|
local UnitTest = UnitData -- Wrapper.Unit#UNIT
|
|
if UnitTest:IsGround() then
|
|
GroundUnitCount = GroundUnitCount + 1
|
|
end
|
|
end
|
|
|
|
return GroundUnitCount
|
|
end
|
|
|
|
--- Returns if the @{Set} has friendly ground units.
|
|
-- @param #SET_UNIT self
|
|
-- @return #number The amount of ground targets in the Set.
|
|
function SET_UNIT:HasFriendlyUnits( FriendlyCoalition )
|
|
self:F2()
|
|
|
|
local FriendlyUnitCount = 0
|
|
for UnitID, UnitData in pairs( self:GetSet()) do
|
|
local UnitTest = UnitData -- Wrapper.Unit#UNIT
|
|
if UnitTest:IsFriendly( FriendlyCoalition ) then
|
|
FriendlyUnitCount = FriendlyUnitCount + 1
|
|
end
|
|
end
|
|
|
|
return FriendlyUnitCount
|
|
end
|
|
|
|
|
|
|
|
----- Iterate the SET_UNIT and call an interator function for each **alive** player, providing the Unit of the player and optional parameters.
|
|
---- @param #SET_UNIT self
|
|
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a UNIT parameter.
|
|
---- @return #SET_UNIT self
|
|
--function SET_UNIT:ForEachPlayer( IteratorFunction, ... )
|
|
-- self:F2( arg )
|
|
--
|
|
-- self:ForEach( IteratorFunction, arg, self.PlayersAlive )
|
|
--
|
|
-- return self
|
|
--end
|
|
--
|
|
--
|
|
----- Iterate the SET_UNIT and call an interator function for each client, providing the Client to the function and optional parameters.
|
|
---- @param #SET_UNIT self
|
|
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a CLIENT parameter.
|
|
---- @return #SET_UNIT self
|
|
--function SET_UNIT:ForEachClient( IteratorFunction, ... )
|
|
-- self:F2( arg )
|
|
--
|
|
-- self:ForEach( IteratorFunction, arg, self.Clients )
|
|
--
|
|
-- return self
|
|
--end
|
|
|
|
|
|
---
|
|
-- @param #SET_UNIT self
|
|
-- @param Wrapper.Unit#UNIT MUnit
|
|
-- @return #SET_UNIT self
|
|
function SET_UNIT:IsIncludeObject( MUnit )
|
|
self:F2( MUnit )
|
|
local MUnitInclude = true
|
|
|
|
if self.Filter.Coalitions then
|
|
local MUnitCoalition = false
|
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
|
self:T3( { "Coalition:", MUnit:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
|
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == MUnit:GetCoalition() then
|
|
MUnitCoalition = true
|
|
end
|
|
end
|
|
MUnitInclude = MUnitInclude and MUnitCoalition
|
|
end
|
|
|
|
if self.Filter.Categories then
|
|
local MUnitCategory = false
|
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
|
self:T3( { "Category:", MUnit:GetDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } )
|
|
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == MUnit:GetDesc().category then
|
|
MUnitCategory = true
|
|
end
|
|
end
|
|
MUnitInclude = MUnitInclude and MUnitCategory
|
|
end
|
|
|
|
if self.Filter.Types then
|
|
local MUnitType = false
|
|
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
|
self:T3( { "Type:", MUnit:GetTypeName(), TypeName } )
|
|
if TypeName == MUnit:GetTypeName() then
|
|
MUnitType = true
|
|
end
|
|
end
|
|
MUnitInclude = MUnitInclude and MUnitType
|
|
end
|
|
|
|
if self.Filter.Countries then
|
|
local MUnitCountry = false
|
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
|
self:T3( { "Country:", MUnit:GetCountry(), CountryName } )
|
|
if country.id[CountryName] == MUnit:GetCountry() then
|
|
MUnitCountry = true
|
|
end
|
|
end
|
|
MUnitInclude = MUnitInclude and MUnitCountry
|
|
end
|
|
|
|
if self.Filter.UnitPrefixes then
|
|
local MUnitPrefix = false
|
|
for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do
|
|
self:T3( { "Prefix:", string.find( MUnit:GetName(), UnitPrefix, 1 ), UnitPrefix } )
|
|
if string.find( MUnit:GetName(), UnitPrefix, 1 ) then
|
|
MUnitPrefix = true
|
|
end
|
|
end
|
|
MUnitInclude = MUnitInclude and MUnitPrefix
|
|
end
|
|
|
|
if self.Filter.RadarTypes then
|
|
local MUnitRadar = false
|
|
for RadarTypeID, RadarType in pairs( self.Filter.RadarTypes ) do
|
|
self:T3( { "Radar:", RadarType } )
|
|
if MUnit:HasSensors( Unit.SensorType.RADAR, RadarType ) == true then
|
|
if MUnit:GetRadar() == true then -- This call is necessary to evaluate the SEAD capability.
|
|
self:T3( "RADAR Found" )
|
|
end
|
|
MUnitRadar = true
|
|
end
|
|
end
|
|
MUnitInclude = MUnitInclude and MUnitRadar
|
|
end
|
|
|
|
if self.Filter.SEAD then
|
|
local MUnitSEAD = false
|
|
if MUnit:HasSEAD() == true then
|
|
self:T3( "SEAD Found" )
|
|
MUnitSEAD = true
|
|
end
|
|
MUnitInclude = MUnitInclude and MUnitSEAD
|
|
end
|
|
|
|
self:T2( MUnitInclude )
|
|
return MUnitInclude
|
|
end
|
|
|
|
|
|
--- Retrieve the type names of the @{Unit}s in the SET, delimited by an optional delimiter.
|
|
-- @param #SET_UNIT self
|
|
-- @param #string Delimiter (optional) The delimiter, which is default a comma.
|
|
-- @return #string The types of the @{Unit}s delimited.
|
|
function SET_UNIT:GetTypeNames( Delimiter )
|
|
|
|
Delimiter = Delimiter or ", "
|
|
local TypeReport = REPORT:New()
|
|
local Types = {}
|
|
|
|
for UnitName, UnitData in pairs( self:GetSet() ) do
|
|
|
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
local UnitTypeName = Unit:GetTypeName()
|
|
|
|
if not Types[UnitTypeName] then
|
|
Types[UnitTypeName] = UnitTypeName
|
|
TypeReport:Add( UnitTypeName )
|
|
end
|
|
end
|
|
|
|
return TypeReport:Text( Delimiter )
|
|
end
|
|
|
|
|
|
--- SET_CLIENT
|
|
|
|
|
|
--- @type SET_CLIENT
|
|
-- @extends Core.Set#SET_BASE
|
|
|
|
|
|
|
|
--- # 4) SET_CLIENT class, extends @{Set#SET_BASE}
|
|
--
|
|
-- Mission designers can use the @{Set#SET_CLIENT} class to build sets of units belonging to certain:
|
|
--
|
|
-- * Coalitions
|
|
-- * Categories
|
|
-- * Countries
|
|
-- * Client types
|
|
-- * Starting with certain prefix strings.
|
|
--
|
|
-- ## 4.1) SET_CLIENT constructor
|
|
--
|
|
-- Create a new SET_CLIENT object with the @{#SET_CLIENT.New} method:
|
|
--
|
|
-- * @{#SET_CLIENT.New}: Creates a new SET_CLIENT object.
|
|
--
|
|
-- ## 4.2) Add or Remove CLIENT(s) from SET_CLIENT
|
|
--
|
|
-- CLIENTs can be added and removed using the @{Set#SET_CLIENT.AddClientsByName} and @{Set#SET_CLIENT.RemoveClientsByName} respectively.
|
|
-- These methods take a single CLIENT name or an array of CLIENT names to be added or removed from SET_CLIENT.
|
|
--
|
|
-- ## 4.3) SET_CLIENT filter criteria
|
|
--
|
|
-- You can set filter criteria to define the set of clients within the SET_CLIENT.
|
|
-- Filter criteria are defined by:
|
|
--
|
|
-- * @{#SET_CLIENT.FilterCoalitions}: Builds the SET_CLIENT with the clients belonging to the coalition(s).
|
|
-- * @{#SET_CLIENT.FilterCategories}: Builds the SET_CLIENT with the clients belonging to the category(ies).
|
|
-- * @{#SET_CLIENT.FilterTypes}: Builds the SET_CLIENT with the clients belonging to the client type(s).
|
|
-- * @{#SET_CLIENT.FilterCountries}: Builds the SET_CLIENT with the clients belonging to the country(ies).
|
|
-- * @{#SET_CLIENT.FilterPrefixes}: Builds the SET_CLIENT with the clients starting with the same prefix string(s).
|
|
--
|
|
-- Once the filter criteria have been set for the SET_CLIENT, you can start filtering using:
|
|
--
|
|
-- * @{#SET_CLIENT.FilterStart}: Starts the filtering of the clients within the SET_CLIENT.
|
|
--
|
|
-- Planned filter criteria within development are (so these are not yet available):
|
|
--
|
|
-- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Zone#ZONE}.
|
|
--
|
|
-- ## 4.4) SET_CLIENT iterators
|
|
--
|
|
-- Once the filters have been defined and the SET_CLIENT has been built, you can iterate the SET_CLIENT with the available iterator methods.
|
|
-- The iterator methods will walk the SET_CLIENT set, and call for each element within the set a function that you provide.
|
|
-- The following iterator methods are currently available within the SET_CLIENT:
|
|
--
|
|
-- * @{#SET_CLIENT.ForEachClient}: Calls a function for each alive client it finds within the SET_CLIENT.
|
|
--
|
|
-- ===
|
|
-- @field #SET_CLIENT SET_CLIENT
|
|
SET_CLIENT = {
|
|
ClassName = "SET_CLIENT",
|
|
Clients = {},
|
|
Filter = {
|
|
Coalitions = nil,
|
|
Categories = nil,
|
|
Types = nil,
|
|
Countries = nil,
|
|
ClientPrefixes = nil,
|
|
},
|
|
FilterMeta = {
|
|
Coalitions = {
|
|
red = coalition.side.RED,
|
|
blue = coalition.side.BLUE,
|
|
neutral = coalition.side.NEUTRAL,
|
|
},
|
|
Categories = {
|
|
plane = Unit.Category.AIRPLANE,
|
|
helicopter = Unit.Category.HELICOPTER,
|
|
ground = Unit.Category.GROUND_UNIT,
|
|
ship = Unit.Category.SHIP,
|
|
structure = Unit.Category.STRUCTURE,
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
--- Creates a new SET_CLIENT object, building a set of clients belonging to a coalitions, categories, countries, types or with defined prefix names.
|
|
-- @param #SET_CLIENT self
|
|
-- @return #SET_CLIENT
|
|
-- @usage
|
|
-- -- Define a new SET_CLIENT Object. This DBObject will contain a reference to all Clients.
|
|
-- DBObject = SET_CLIENT:New()
|
|
function SET_CLIENT:New()
|
|
-- Inherits from BASE
|
|
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.CLIENTS ) )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Add CLIENT(s) to SET_CLIENT.
|
|
-- @param Core.Set#SET_CLIENT self
|
|
-- @param #string AddClientNames A single name or an array of CLIENT names.
|
|
-- @return self
|
|
function SET_CLIENT:AddClientsByName( AddClientNames )
|
|
|
|
local AddClientNamesArray = ( type( AddClientNames ) == "table" ) and AddClientNames or { AddClientNames }
|
|
|
|
for AddClientID, AddClientName in pairs( AddClientNamesArray ) do
|
|
self:Add( AddClientName, CLIENT:FindByName( AddClientName ) )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Remove CLIENT(s) from SET_CLIENT.
|
|
-- @param Core.Set#SET_CLIENT self
|
|
-- @param Wrapper.Client#CLIENT RemoveClientNames A single name or an array of CLIENT names.
|
|
-- @return self
|
|
function SET_CLIENT:RemoveClientsByName( RemoveClientNames )
|
|
|
|
local RemoveClientNamesArray = ( type( RemoveClientNames ) == "table" ) and RemoveClientNames or { RemoveClientNames }
|
|
|
|
for RemoveClientID, RemoveClientName in pairs( RemoveClientNamesArray ) do
|
|
self:Remove( RemoveClientName.ClientName )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Finds a Client based on the Client Name.
|
|
-- @param #SET_CLIENT self
|
|
-- @param #string ClientName
|
|
-- @return Wrapper.Client#CLIENT The found Client.
|
|
function SET_CLIENT:FindClient( ClientName )
|
|
|
|
local ClientFound = self.Set[ClientName]
|
|
return ClientFound
|
|
end
|
|
|
|
|
|
|
|
--- Builds a set of clients of coalitions.
|
|
-- Possible current coalitions are red, blue and neutral.
|
|
-- @param #SET_CLIENT self
|
|
-- @param #string Coalitions Can take the following values: "red", "blue", "neutral".
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:FilterCoalitions( Coalitions )
|
|
if not self.Filter.Coalitions then
|
|
self.Filter.Coalitions = {}
|
|
end
|
|
if type( Coalitions ) ~= "table" then
|
|
Coalitions = { Coalitions }
|
|
end
|
|
for CoalitionID, Coalition in pairs( Coalitions ) do
|
|
self.Filter.Coalitions[Coalition] = Coalition
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of clients out of categories.
|
|
-- Possible current categories are plane, helicopter, ground, ship.
|
|
-- @param #SET_CLIENT self
|
|
-- @param #string Categories Can take the following values: "plane", "helicopter", "ground", "ship".
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:FilterCategories( Categories )
|
|
if not self.Filter.Categories then
|
|
self.Filter.Categories = {}
|
|
end
|
|
if type( Categories ) ~= "table" then
|
|
Categories = { Categories }
|
|
end
|
|
for CategoryID, Category in pairs( Categories ) do
|
|
self.Filter.Categories[Category] = Category
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of clients of defined client types.
|
|
-- Possible current types are those types known within DCS world.
|
|
-- @param #SET_CLIENT self
|
|
-- @param #string Types Can take those type strings known within DCS world.
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:FilterTypes( Types )
|
|
if not self.Filter.Types then
|
|
self.Filter.Types = {}
|
|
end
|
|
if type( Types ) ~= "table" then
|
|
Types = { Types }
|
|
end
|
|
for TypeID, Type in pairs( Types ) do
|
|
self.Filter.Types[Type] = Type
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of clients of defined countries.
|
|
-- Possible current countries are those known within DCS world.
|
|
-- @param #SET_CLIENT self
|
|
-- @param #string Countries Can take those country strings known within DCS world.
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:FilterCountries( Countries )
|
|
if not self.Filter.Countries then
|
|
self.Filter.Countries = {}
|
|
end
|
|
if type( Countries ) ~= "table" then
|
|
Countries = { Countries }
|
|
end
|
|
for CountryID, Country in pairs( Countries ) do
|
|
self.Filter.Countries[Country] = Country
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of clients of defined client prefixes.
|
|
-- All the clients starting with the given prefixes will be included within the set.
|
|
-- @param #SET_CLIENT self
|
|
-- @param #string Prefixes The prefix of which the client name starts with.
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:FilterPrefixes( Prefixes )
|
|
if not self.Filter.ClientPrefixes then
|
|
self.Filter.ClientPrefixes = {}
|
|
end
|
|
if type( Prefixes ) ~= "table" then
|
|
Prefixes = { Prefixes }
|
|
end
|
|
for PrefixID, Prefix in pairs( Prefixes ) do
|
|
self.Filter.ClientPrefixes[Prefix] = Prefix
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Starts the filtering.
|
|
-- @param #SET_CLIENT self
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:FilterStart()
|
|
|
|
if _DATABASE then
|
|
self:_FilterStart()
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
|
-- @param #SET_CLIENT self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the CLIENT
|
|
-- @return #table The CLIENT
|
|
function SET_CLIENT:AddInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
|
end
|
|
|
|
--- Handles the Database to check on any event that Object exists in the Database.
|
|
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
|
-- @param #SET_CLIENT self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the CLIENT
|
|
-- @return #table The CLIENT
|
|
function SET_CLIENT:FindInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
|
end
|
|
|
|
--- Iterate the SET_CLIENT and call an interator function for each **alive** CLIENT, providing the CLIENT and optional parameters.
|
|
-- @param #SET_CLIENT self
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:ForEachClient( IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_CLIENT and call an iterator function for each **alive** CLIENT presence completely in a @{Zone}, providing the CLIENT and optional parameters to the called function.
|
|
-- @param #SET_CLIENT self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:ForEachClientInZone( ZoneObject, IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set,
|
|
--- @param Core.Zone#ZONE_BASE ZoneObject
|
|
-- @param Wrapper.Client#CLIENT ClientObject
|
|
function( ZoneObject, ClientObject )
|
|
if ClientObject:IsInZone( ZoneObject ) then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end, { ZoneObject } )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_CLIENT and call an iterator function for each **alive** CLIENT presence not in a @{Zone}, providing the CLIENT and optional parameters to the called function.
|
|
-- @param #SET_CLIENT self
|
|
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:ForEachClientNotInZone( ZoneObject, IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set,
|
|
--- @param Core.Zone#ZONE_BASE ZoneObject
|
|
-- @param Wrapper.Client#CLIENT ClientObject
|
|
function( ZoneObject, ClientObject )
|
|
if ClientObject:IsNotInZone( ZoneObject ) then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end, { ZoneObject } )
|
|
|
|
return self
|
|
end
|
|
|
|
---
|
|
-- @param #SET_CLIENT self
|
|
-- @param Wrapper.Client#CLIENT MClient
|
|
-- @return #SET_CLIENT self
|
|
function SET_CLIENT:IsIncludeObject( MClient )
|
|
self:F2( MClient )
|
|
|
|
local MClientInclude = true
|
|
|
|
if MClient then
|
|
local MClientName = MClient.UnitName
|
|
|
|
if self.Filter.Coalitions then
|
|
local MClientCoalition = false
|
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
|
local ClientCoalitionID = _DATABASE:GetCoalitionFromClientTemplate( MClientName )
|
|
self:T3( { "Coalition:", ClientCoalitionID, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
|
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == ClientCoalitionID then
|
|
MClientCoalition = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Coalition", MClientCoalition } )
|
|
MClientInclude = MClientInclude and MClientCoalition
|
|
end
|
|
|
|
if self.Filter.Categories then
|
|
local MClientCategory = false
|
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
|
local ClientCategoryID = _DATABASE:GetCategoryFromClientTemplate( MClientName )
|
|
self:T3( { "Category:", ClientCategoryID, self.FilterMeta.Categories[CategoryName], CategoryName } )
|
|
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == ClientCategoryID then
|
|
MClientCategory = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Category", MClientCategory } )
|
|
MClientInclude = MClientInclude and MClientCategory
|
|
end
|
|
|
|
if self.Filter.Types then
|
|
local MClientType = false
|
|
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
|
self:T3( { "Type:", MClient:GetTypeName(), TypeName } )
|
|
if TypeName == MClient:GetTypeName() then
|
|
MClientType = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Type", MClientType } )
|
|
MClientInclude = MClientInclude and MClientType
|
|
end
|
|
|
|
if self.Filter.Countries then
|
|
local MClientCountry = false
|
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
|
local ClientCountryID = _DATABASE:GetCountryFromClientTemplate(MClientName)
|
|
self:T3( { "Country:", ClientCountryID, country.id[CountryName], CountryName } )
|
|
if country.id[CountryName] and country.id[CountryName] == ClientCountryID then
|
|
MClientCountry = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Country", MClientCountry } )
|
|
MClientInclude = MClientInclude and MClientCountry
|
|
end
|
|
|
|
if self.Filter.ClientPrefixes then
|
|
local MClientPrefix = false
|
|
for ClientPrefixId, ClientPrefix in pairs( self.Filter.ClientPrefixes ) do
|
|
self:T3( { "Prefix:", string.find( MClient.UnitName, ClientPrefix, 1 ), ClientPrefix } )
|
|
if string.find( MClient.UnitName, ClientPrefix, 1 ) then
|
|
MClientPrefix = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Prefix", MClientPrefix } )
|
|
MClientInclude = MClientInclude and MClientPrefix
|
|
end
|
|
end
|
|
|
|
self:T2( MClientInclude )
|
|
return MClientInclude
|
|
end
|
|
|
|
--- @type SET_AIRBASE
|
|
-- @extends Core.Set#SET_BASE
|
|
|
|
--- # 5) SET_AIRBASE class, extends @{Set#SET_BASE}
|
|
--
|
|
-- Mission designers can use the @{Set#SET_AIRBASE} class to build sets of airbases optionally belonging to certain:
|
|
--
|
|
-- * Coalitions
|
|
--
|
|
-- ## 5.1) SET_AIRBASE constructor
|
|
--
|
|
-- Create a new SET_AIRBASE object with the @{#SET_AIRBASE.New} method:
|
|
--
|
|
-- * @{#SET_AIRBASE.New}: Creates a new SET_AIRBASE object.
|
|
--
|
|
-- ## 5.2) Add or Remove AIRBASEs from SET_AIRBASE
|
|
--
|
|
-- AIRBASEs can be added and removed using the @{Set#SET_AIRBASE.AddAirbasesByName} and @{Set#SET_AIRBASE.RemoveAirbasesByName} respectively.
|
|
-- These methods take a single AIRBASE name or an array of AIRBASE names to be added or removed from SET_AIRBASE.
|
|
--
|
|
-- ## 5.3) SET_AIRBASE filter criteria
|
|
--
|
|
-- You can set filter criteria to define the set of clients within the SET_AIRBASE.
|
|
-- Filter criteria are defined by:
|
|
--
|
|
-- * @{#SET_AIRBASE.FilterCoalitions}: Builds the SET_AIRBASE with the airbases belonging to the coalition(s).
|
|
--
|
|
-- Once the filter criteria have been set for the SET_AIRBASE, you can start filtering using:
|
|
--
|
|
-- * @{#SET_AIRBASE.FilterStart}: Starts the filtering of the airbases within the SET_AIRBASE.
|
|
--
|
|
-- ## 5.4) SET_AIRBASE iterators
|
|
--
|
|
-- Once the filters have been defined and the SET_AIRBASE has been built, you can iterate the SET_AIRBASE with the available iterator methods.
|
|
-- The iterator methods will walk the SET_AIRBASE set, and call for each airbase within the set a function that you provide.
|
|
-- The following iterator methods are currently available within the SET_AIRBASE:
|
|
--
|
|
-- * @{#SET_AIRBASE.ForEachAirbase}: Calls a function for each airbase it finds within the SET_AIRBASE.
|
|
--
|
|
-- ===
|
|
-- @field #SET_AIRBASE SET_AIRBASE
|
|
SET_AIRBASE = {
|
|
ClassName = "SET_AIRBASE",
|
|
Airbases = {},
|
|
Filter = {
|
|
Coalitions = nil,
|
|
},
|
|
FilterMeta = {
|
|
Coalitions = {
|
|
red = coalition.side.RED,
|
|
blue = coalition.side.BLUE,
|
|
neutral = coalition.side.NEUTRAL,
|
|
},
|
|
Categories = {
|
|
airdrome = Airbase.Category.AIRDROME,
|
|
helipad = Airbase.Category.HELIPAD,
|
|
ship = Airbase.Category.SHIP,
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
--- Creates a new SET_AIRBASE object, building a set of airbases belonging to a coalitions and categories.
|
|
-- @param #SET_AIRBASE self
|
|
-- @return #SET_AIRBASE self
|
|
-- @usage
|
|
-- -- Define a new SET_AIRBASE Object. The DatabaseSet will contain a reference to all Airbases.
|
|
-- DatabaseSet = SET_AIRBASE:New()
|
|
function SET_AIRBASE:New()
|
|
-- Inherits from BASE
|
|
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.AIRBASES ) )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Add AIRBASEs to SET_AIRBASE.
|
|
-- @param Core.Set#SET_AIRBASE self
|
|
-- @param #string AddAirbaseNames A single name or an array of AIRBASE names.
|
|
-- @return self
|
|
function SET_AIRBASE:AddAirbasesByName( AddAirbaseNames )
|
|
|
|
local AddAirbaseNamesArray = ( type( AddAirbaseNames ) == "table" ) and AddAirbaseNames or { AddAirbaseNames }
|
|
|
|
for AddAirbaseID, AddAirbaseName in pairs( AddAirbaseNamesArray ) do
|
|
self:Add( AddAirbaseName, AIRBASE:FindByName( AddAirbaseName ) )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Remove AIRBASEs from SET_AIRBASE.
|
|
-- @param Core.Set#SET_AIRBASE self
|
|
-- @param Wrapper.Airbase#AIRBASE RemoveAirbaseNames A single name or an array of AIRBASE names.
|
|
-- @return self
|
|
function SET_AIRBASE:RemoveAirbasesByName( RemoveAirbaseNames )
|
|
|
|
local RemoveAirbaseNamesArray = ( type( RemoveAirbaseNames ) == "table" ) and RemoveAirbaseNames or { RemoveAirbaseNames }
|
|
|
|
for RemoveAirbaseID, RemoveAirbaseName in pairs( RemoveAirbaseNamesArray ) do
|
|
self:Remove( RemoveAirbaseName.AirbaseName )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Finds a Airbase based on the Airbase Name.
|
|
-- @param #SET_AIRBASE self
|
|
-- @param #string AirbaseName
|
|
-- @return Wrapper.Airbase#AIRBASE The found Airbase.
|
|
function SET_AIRBASE:FindAirbase( AirbaseName )
|
|
|
|
local AirbaseFound = self.Set[AirbaseName]
|
|
return AirbaseFound
|
|
end
|
|
|
|
|
|
|
|
--- Builds a set of airbases of coalitions.
|
|
-- Possible current coalitions are red, blue and neutral.
|
|
-- @param #SET_AIRBASE self
|
|
-- @param #string Coalitions Can take the following values: "red", "blue", "neutral".
|
|
-- @return #SET_AIRBASE self
|
|
function SET_AIRBASE:FilterCoalitions( Coalitions )
|
|
if not self.Filter.Coalitions then
|
|
self.Filter.Coalitions = {}
|
|
end
|
|
if type( Coalitions ) ~= "table" then
|
|
Coalitions = { Coalitions }
|
|
end
|
|
for CoalitionID, Coalition in pairs( Coalitions ) do
|
|
self.Filter.Coalitions[Coalition] = Coalition
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of airbases out of categories.
|
|
-- Possible current categories are plane, helicopter, ground, ship.
|
|
-- @param #SET_AIRBASE self
|
|
-- @param #string Categories Can take the following values: "airdrome", "helipad", "ship".
|
|
-- @return #SET_AIRBASE self
|
|
function SET_AIRBASE:FilterCategories( Categories )
|
|
if not self.Filter.Categories then
|
|
self.Filter.Categories = {}
|
|
end
|
|
if type( Categories ) ~= "table" then
|
|
Categories = { Categories }
|
|
end
|
|
for CategoryID, Category in pairs( Categories ) do
|
|
self.Filter.Categories[Category] = Category
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- Starts the filtering.
|
|
-- @param #SET_AIRBASE self
|
|
-- @return #SET_AIRBASE self
|
|
function SET_AIRBASE:FilterStart()
|
|
|
|
if _DATABASE then
|
|
self:_FilterStart()
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
|
-- @param #SET_AIRBASE self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the AIRBASE
|
|
-- @return #table The AIRBASE
|
|
function SET_AIRBASE:AddInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
|
end
|
|
|
|
--- Handles the Database to check on any event that Object exists in the Database.
|
|
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
|
-- @param #SET_AIRBASE self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the AIRBASE
|
|
-- @return #table The AIRBASE
|
|
function SET_AIRBASE:FindInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
|
end
|
|
|
|
--- Iterate the SET_AIRBASE and call an interator function for each AIRBASE, providing the AIRBASE and optional parameters.
|
|
-- @param #SET_AIRBASE self
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive AIRBASE in the SET_AIRBASE. The function needs to accept a AIRBASE parameter.
|
|
-- @return #SET_AIRBASE self
|
|
function SET_AIRBASE:ForEachAirbase( IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_AIRBASE while identifying the nearest @{Airbase#AIRBASE} from a @{Point#POINT_VEC2}.
|
|
-- @param #SET_AIRBASE self
|
|
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest @{Airbase#AIRBASE}.
|
|
-- @return Wrapper.Airbase#AIRBASE The closest @{Airbase#AIRBASE}.
|
|
function SET_AIRBASE:FindNearestAirbaseFromPointVec2( PointVec2 )
|
|
self:F2( PointVec2 )
|
|
|
|
local NearestAirbase = self:FindNearestObjectFromPointVec2( PointVec2 )
|
|
return NearestAirbase
|
|
end
|
|
|
|
|
|
|
|
---
|
|
-- @param #SET_AIRBASE self
|
|
-- @param Wrapper.Airbase#AIRBASE MAirbase
|
|
-- @return #SET_AIRBASE self
|
|
function SET_AIRBASE:IsIncludeObject( MAirbase )
|
|
self:F2( MAirbase )
|
|
|
|
local MAirbaseInclude = true
|
|
|
|
if MAirbase then
|
|
local MAirbaseName = MAirbase:GetName()
|
|
|
|
if self.Filter.Coalitions then
|
|
local MAirbaseCoalition = false
|
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
|
local AirbaseCoalitionID = _DATABASE:GetCoalitionFromAirbase( MAirbaseName )
|
|
self:T3( { "Coalition:", AirbaseCoalitionID, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
|
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == AirbaseCoalitionID then
|
|
MAirbaseCoalition = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Coalition", MAirbaseCoalition } )
|
|
MAirbaseInclude = MAirbaseInclude and MAirbaseCoalition
|
|
end
|
|
|
|
if self.Filter.Categories then
|
|
local MAirbaseCategory = false
|
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
|
local AirbaseCategoryID = _DATABASE:GetCategoryFromAirbase( MAirbaseName )
|
|
self:T3( { "Category:", AirbaseCategoryID, self.FilterMeta.Categories[CategoryName], CategoryName } )
|
|
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == AirbaseCategoryID then
|
|
MAirbaseCategory = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Category", MAirbaseCategory } )
|
|
MAirbaseInclude = MAirbaseInclude and MAirbaseCategory
|
|
end
|
|
end
|
|
|
|
self:T2( MAirbaseInclude )
|
|
return MAirbaseInclude
|
|
end
|
|
|
|
--- @type SET_CARGO
|
|
-- @extends Core.Set#SET_BASE
|
|
|
|
--- # SET_CARGO class, extends @{Set#SET_BASE}
|
|
--
|
|
-- Mission designers can use the @{Set#SET_CARGO} class to build sets of cargos optionally belonging to certain:
|
|
--
|
|
-- * Coalitions
|
|
-- * Types
|
|
-- * Name or Prefix
|
|
--
|
|
-- ## SET_CARGO constructor
|
|
--
|
|
-- Create a new SET_CARGO object with the @{#SET_CARGO.New} method:
|
|
--
|
|
-- * @{#SET_CARGO.New}: Creates a new SET_CARGO object.
|
|
--
|
|
-- ## Add or Remove CARGOs from SET_CARGO
|
|
--
|
|
-- CARGOs can be added and removed using the @{Set#SET_CARGO.AddCargosByName} and @{Set#SET_CARGO.RemoveCargosByName} respectively.
|
|
-- These methods take a single CARGO name or an array of CARGO names to be added or removed from SET_CARGO.
|
|
--
|
|
-- ## SET_CARGO filter criteria
|
|
--
|
|
-- You can set filter criteria to automatically maintain the SET_CARGO contents.
|
|
-- Filter criteria are defined by:
|
|
--
|
|
-- * @{#SET_CARGO.FilterCoalitions}: Builds the SET_CARGO with the cargos belonging to the coalition(s).
|
|
-- * @{#SET_CARGO.FilterPrefixes}: Builds the SET_CARGO with the cargos containing the prefix string(s).
|
|
-- * @{#SET_CARGO.FilterTypes}: Builds the SET_CARGO with the cargos belonging to the cargo type(s).
|
|
-- * @{#SET_CARGO.FilterCountries}: Builds the SET_CARGO with the cargos belonging to the country(ies).
|
|
--
|
|
-- Once the filter criteria have been set for the SET_CARGO, you can start filtering using:
|
|
--
|
|
-- * @{#SET_CARGO.FilterStart}: Starts the filtering of the cargos within the SET_CARGO.
|
|
--
|
|
-- ## SET_CARGO iterators
|
|
--
|
|
-- Once the filters have been defined and the SET_CARGO has been built, you can iterate the SET_CARGO with the available iterator methods.
|
|
-- The iterator methods will walk the SET_CARGO set, and call for each cargo within the set a function that you provide.
|
|
-- The following iterator methods are currently available within the SET_CARGO:
|
|
--
|
|
-- * @{#SET_CARGO.ForEachCargo}: Calls a function for each cargo it finds within the SET_CARGO.
|
|
--
|
|
-- @field #SET_CARGO SET_CARGO
|
|
--
|
|
SET_CARGO = {
|
|
ClassName = "SET_CARGO",
|
|
Cargos = {},
|
|
Filter = {
|
|
Coalitions = nil,
|
|
Types = nil,
|
|
Countries = nil,
|
|
ClientPrefixes = nil,
|
|
},
|
|
FilterMeta = {
|
|
Coalitions = {
|
|
red = coalition.side.RED,
|
|
blue = coalition.side.BLUE,
|
|
neutral = coalition.side.NEUTRAL,
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
--- Creates a new SET_CARGO object, building a set of cargos belonging to a coalitions and categories.
|
|
-- @param #SET_CARGO self
|
|
-- @return #SET_CARGO self
|
|
-- @usage
|
|
-- -- Define a new SET_CARGO Object. The DatabaseSet will contain a reference to all Cargos.
|
|
-- DatabaseSet = SET_CARGO:New()
|
|
function SET_CARGO:New()
|
|
-- Inherits from BASE
|
|
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.CARGOS ) )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Add CARGOs to SET_CARGO.
|
|
-- @param Core.Set#SET_CARGO self
|
|
-- @param #string AddCargoNames A single name or an array of CARGO names.
|
|
-- @return self
|
|
function SET_CARGO:AddCargosByName( AddCargoNames )
|
|
|
|
local AddCargoNamesArray = ( type( AddCargoNames ) == "table" ) and AddCargoNames or { AddCargoNames }
|
|
|
|
for AddCargoID, AddCargoName in pairs( AddCargoNamesArray ) do
|
|
self:Add( AddCargoName, CARGO:FindByName( AddCargoName ) )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
--- Remove CARGOs from SET_CARGO.
|
|
-- @param Core.Set#SET_CARGO self
|
|
-- @param Wrapper.Cargo#CARGO RemoveCargoNames A single name or an array of CARGO names.
|
|
-- @return self
|
|
function SET_CARGO:RemoveCargosByName( RemoveCargoNames )
|
|
|
|
local RemoveCargoNamesArray = ( type( RemoveCargoNames ) == "table" ) and RemoveCargoNames or { RemoveCargoNames }
|
|
|
|
for RemoveCargoID, RemoveCargoName in pairs( RemoveCargoNamesArray ) do
|
|
self:Remove( RemoveCargoName.CargoName )
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Finds a Cargo based on the Cargo Name.
|
|
-- @param #SET_CARGO self
|
|
-- @param #string CargoName
|
|
-- @return Wrapper.Cargo#CARGO The found Cargo.
|
|
function SET_CARGO:FindCargo( CargoName )
|
|
|
|
local CargoFound = self.Set[CargoName]
|
|
return CargoFound
|
|
end
|
|
|
|
|
|
|
|
--- Builds a set of cargos of coalitions.
|
|
-- Possible current coalitions are red, blue and neutral.
|
|
-- @param #SET_CARGO self
|
|
-- @param #string Coalitions Can take the following values: "red", "blue", "neutral".
|
|
-- @return #SET_CARGO self
|
|
function SET_CARGO:FilterCoalitions( Coalitions )
|
|
if not self.Filter.Coalitions then
|
|
self.Filter.Coalitions = {}
|
|
end
|
|
if type( Coalitions ) ~= "table" then
|
|
Coalitions = { Coalitions }
|
|
end
|
|
for CoalitionID, Coalition in pairs( Coalitions ) do
|
|
self.Filter.Coalitions[Coalition] = Coalition
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- Builds a set of cargos of defined cargo types.
|
|
-- Possible current types are those types known within DCS world.
|
|
-- @param #SET_CARGO self
|
|
-- @param #string Types Can take those type strings known within DCS world.
|
|
-- @return #SET_CARGO self
|
|
function SET_CARGO:FilterTypes( Types )
|
|
if not self.Filter.Types then
|
|
self.Filter.Types = {}
|
|
end
|
|
if type( Types ) ~= "table" then
|
|
Types = { Types }
|
|
end
|
|
for TypeID, Type in pairs( Types ) do
|
|
self.Filter.Types[Type] = Type
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of cargos of defined countries.
|
|
-- Possible current countries are those known within DCS world.
|
|
-- @param #SET_CARGO self
|
|
-- @param #string Countries Can take those country strings known within DCS world.
|
|
-- @return #SET_CARGO self
|
|
function SET_CARGO:FilterCountries( Countries )
|
|
if not self.Filter.Countries then
|
|
self.Filter.Countries = {}
|
|
end
|
|
if type( Countries ) ~= "table" then
|
|
Countries = { Countries }
|
|
end
|
|
for CountryID, Country in pairs( Countries ) do
|
|
self.Filter.Countries[Country] = Country
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
--- Builds a set of cargos of defined cargo prefixes.
|
|
-- All the cargos starting with the given prefixes will be included within the set.
|
|
-- @param #SET_CARGO self
|
|
-- @param #string Prefixes The prefix of which the cargo name starts with.
|
|
-- @return #SET_CARGO self
|
|
function SET_CARGO:FilterPrefixes( Prefixes )
|
|
if not self.Filter.CargoPrefixes then
|
|
self.Filter.CargoPrefixes = {}
|
|
end
|
|
if type( Prefixes ) ~= "table" then
|
|
Prefixes = { Prefixes }
|
|
end
|
|
for PrefixID, Prefix in pairs( Prefixes ) do
|
|
self.Filter.CargoPrefixes[Prefix] = Prefix
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
|
|
--- Starts the filtering.
|
|
-- @param #SET_CARGO self
|
|
-- @return #SET_CARGO self
|
|
function SET_CARGO:FilterStart()
|
|
|
|
if _DATABASE then
|
|
self:_FilterStart()
|
|
end
|
|
|
|
self:HandleEvent( EVENTS.NewCargo )
|
|
self:HandleEvent( EVENTS.DeleteCargo )
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
|
-- @param #SET_CARGO self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the CARGO
|
|
-- @return #table The CARGO
|
|
function SET_CARGO:AddInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
|
end
|
|
|
|
--- Handles the Database to check on any event that Object exists in the Database.
|
|
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
|
-- @param #SET_CARGO self
|
|
-- @param Core.Event#EVENTDATA Event
|
|
-- @return #string The name of the CARGO
|
|
-- @return #table The CARGO
|
|
function SET_CARGO:FindInDatabase( Event )
|
|
self:F3( { Event } )
|
|
|
|
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
|
end
|
|
|
|
--- Iterate the SET_CARGO and call an interator function for each CARGO, providing the CARGO and optional parameters.
|
|
-- @param #SET_CARGO self
|
|
-- @param #function IteratorFunction The function that will be called when there is an alive CARGO in the SET_CARGO. The function needs to accept a CARGO parameter.
|
|
-- @return #SET_CARGO self
|
|
function SET_CARGO:ForEachCargo( IteratorFunction, ... )
|
|
self:F2( arg )
|
|
|
|
self:ForEach( IteratorFunction, arg, self.Set )
|
|
|
|
return self
|
|
end
|
|
|
|
--- Iterate the SET_CARGO while identifying the nearest @{Cargo#CARGO} from a @{Point#POINT_VEC2}.
|
|
-- @param #SET_CARGO self
|
|
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest @{Cargo#CARGO}.
|
|
-- @return Wrapper.Cargo#CARGO The closest @{Cargo#CARGO}.
|
|
function SET_CARGO:FindNearestCargoFromPointVec2( PointVec2 )
|
|
self:F2( PointVec2 )
|
|
|
|
local NearestCargo = self:FindNearestObjectFromPointVec2( PointVec2 )
|
|
return NearestCargo
|
|
end
|
|
|
|
|
|
|
|
---
|
|
-- @param #SET_CARGO self
|
|
-- @param AI.AI_Cargo#AI_CARGO MCargo
|
|
-- @return #SET_CARGO self
|
|
function SET_CARGO:IsIncludeObject( MCargo )
|
|
self:F2( MCargo )
|
|
|
|
local MCargoInclude = true
|
|
|
|
if MCargo then
|
|
local MCargoName = MCargo:GetName()
|
|
|
|
if self.Filter.Coalitions then
|
|
local MCargoCoalition = false
|
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
|
local CargoCoalitionID = MCargo:GetCoalition()
|
|
self:T3( { "Coalition:", CargoCoalitionID, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
|
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == CargoCoalitionID then
|
|
MCargoCoalition = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Coalition", MCargoCoalition } )
|
|
MCargoInclude = MCargoInclude and MCargoCoalition
|
|
end
|
|
|
|
if self.Filter.Types then
|
|
local MCargoType = false
|
|
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
|
self:T3( { "Type:", MCargo:GetType(), TypeName } )
|
|
if TypeName == MCargo:GetType() then
|
|
MCargoType = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Type", MCargoType } )
|
|
MCargoInclude = MCargoInclude and MCargoType
|
|
end
|
|
|
|
if self.Filter.CargoPrefixes then
|
|
local MCargoPrefix = false
|
|
for CargoPrefixId, CargoPrefix in pairs( self.Filter.CargoPrefixes ) do
|
|
self:T3( { "Prefix:", string.find( MCargo.Name, CargoPrefix, 1 ), CargoPrefix } )
|
|
if string.find( MCargo.Name, CargoPrefix, 1 ) then
|
|
MCargoPrefix = true
|
|
end
|
|
end
|
|
self:T( { "Evaluated Prefix", MCargoPrefix } )
|
|
MCargoInclude = MCargoInclude and MCargoPrefix
|
|
end
|
|
end
|
|
|
|
self:T2( MCargoInclude )
|
|
return MCargoInclude
|
|
end
|
|
|
|
--- Handles the OnEventNewCargo event for the Set.
|
|
-- @param #SET_CARGO self
|
|
-- @param Core.Event#EVENTDATA EventData
|
|
function SET_CARGO:OnEventNewCargo( EventData )
|
|
|
|
if EventData.Cargo then
|
|
if EventData.Cargo and self:IsIncludeObject( EventData.Cargo ) then
|
|
self:Add( EventData.Cargo.Name , EventData.Cargo )
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Handles the OnDead or OnCrash event for alive units set.
|
|
-- @param #SET_CARGO self
|
|
-- @param Core.Event#EVENTDATA EventData
|
|
function SET_CARGO:OnEventDeleteCargo( EventData )
|
|
self:F3( { EventData } )
|
|
|
|
if EventData.Cargo then
|
|
local Cargo = _DATABASE:FindCargo( EventData.Cargo.Name )
|
|
if Cargo and Cargo.Name then
|
|
self:Remove( Cargo.Name )
|
|
end
|
|
end
|
|
end
|
|
|