Merge remote-tracking branch 'refs/remotes/origin/master' into Bugfix

This commit is contained in:
FlightControl 2016-06-10 17:56:48 +02:00
commit bd81d16327
34 changed files with 3962 additions and 1597 deletions

View File

@ -0,0 +1,74 @@
--- This module contains the AIBALANCER class.
--
-- ===
--
-- 1) @{AIBalancer#AIBALANCER} class, extends @{Base#BASE}
-- ================================================
-- The @{AIBalancer#AIBALANCER} class controls the dynamic spawning of AI GROUPS depending on a SET_CLIENT.
-- There will be as many AI GROUPS spawned as there at CLIENTS in SET_CLIENT not spawned.
--
-- 1.1) AIBALANCER construction method:
-- ------------------------------------
-- Create a new AIBALANCER object with the @{#AIBALANCER.New} method:
--
-- * @{#AIBALANCER.New}: Creates a new AIBALANCER object.
--
--
-- ===
-- @module AIBalancer
-- @author FlightControl
--- AIBALANCER class
-- @type AIBALANCER
-- @field Set#SET_CLIENT SetClient
-- @field Spawn#SPAWN SpawnAI
-- @extends Base#BASE
AIBALANCER = {
ClassName = "AIBALANCER",
}
--- Creates a new AIBALANCER object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
-- @param #AIBALANCER self
-- @param SetClient A SET_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player).
-- @param SpawnAI A SPAWN object that will spawn the AI units required, balancing the SetClient.
-- @return #AIBALANCER self
function AIBALANCER:New( SetClient, SpawnAI )
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() )
self.SetClient = SetClient
self.SpawnAI = SpawnAI
self.AIMonitorSchedule = SCHEDULER:New( self, self._ClientAliveMonitorScheduler, {}, 1, 10, 0 )
return self
end
--- @param #AIBALANCER self
function AIBALANCER:_ClientAliveMonitorScheduler()
self.SetClient:ForEachClient(
--- @param Client#CLIENT Client
function( Client )
local ClientAIAliveState = Client:GetState( self, 'AIAlive' )
self:T( ClientAIAliveState )
if Client:IsAlive() then
if ClientAIAliveState == true then
Client:SetState( self, 'AIAlive', false )
local AIGroup = Client:GetState( self, 'AIGroup' ) -- Group#GROUP
AIGroup:Destroy()
end
else
if not ClientAIAliveState or ClientAIAliveState == false then
Client:SetState( self, 'AIAlive', true )
Client:SetState( self, 'AIGroup', self.SpawnAI:Spawn() )
end
end
end
)
return true
end

View File

@ -68,7 +68,8 @@ local _TraceClassMethod = {}
BASE = {
ClassName = "BASE",
ClassID = 0,
Events = {}
Events = {},
States = {}
}
--- The Formation Class
@ -323,6 +324,36 @@ function BASE:onEvent(event)
end
end
function BASE:SetState( Object, StateName, State )
local ClassNameAndID = Object:GetClassNameAndID()
if not self.States[ClassNameAndID] then
self.States[ClassNameAndID] = {}
end
self.States[ClassNameAndID][StateName] = State
return self.States[ClassNameAndID][StateName]
end
function BASE:GetState( Object, StateName )
local ClassNameAndID = Object:GetClassNameAndID()
if self.States[ClassNameAndID] then
return self.States[ClassNameAndID][StateName]
end
return nil
end
function BASE:ClearState( Object, StateName )
local ClassNameAndID = Object:GetClassNameAndID()
if self.States[ClassNameAndID] then
self.States[ClassNameAndID][StateName] = nil
end
end
-- Trace section
-- Log a trace (only shown when trace is on)
@ -426,10 +457,10 @@ function BASE:F3( Arguments )
end
--- Trace a function logic. Can be anywhere within the function logic.
--- Trace a function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
function BASE:_T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
if _TraceOn and ( ( _TraceAll == true ) or ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) ) then
@ -452,6 +483,21 @@ function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
end
end
--- Trace a function logic level 1. Can be anywhere within the function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
function BASE:T( Arguments )
local DebugInfoCurrent = debug.getinfo( 2, "nl" )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 1 then
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end
--- Trace a function logic level 2. Can be anywhere within the function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
@ -461,7 +507,7 @@ function BASE:T2( Arguments )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 2 then
self:T( Arguments, DebugInfoCurrent, DebugInfoFrom )
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end
@ -475,7 +521,7 @@ function BASE:T3( Arguments )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 3 then
self:T( Arguments, DebugInfoCurrent, DebugInfoFrom )
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end

View File

@ -105,6 +105,7 @@ function DATABASE:New()
self:_RegisterTemplates()
self:_RegisterGroupsAndUnits()
self:_RegisterClients()
self:_RegisterStatics()
self:_RegisterPlayers()
@ -287,7 +288,7 @@ end
-- @param #DATABASE self
-- @param #table GroupTemplate
-- @return #DATABASE self
function DATABASE:_RegisterTemplate( GroupTemplate )
function DATABASE:_RegisterTemplate( GroupTemplate, CoalitionName, CategoryName, CountryName )
local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name)
@ -306,6 +307,9 @@ function DATABASE:_RegisterTemplate( GroupTemplate )
self.Templates.Groups[GroupTemplateName].groupId = GroupTemplate.groupId
self.Templates.Groups[GroupTemplateName].UnitCount = #GroupTemplate.units
self.Templates.Groups[GroupTemplateName].Units = GroupTemplate.units
self.Templates.Groups[GroupTemplateName].CategoryName = CategoryName
self.Templates.Groups[GroupTemplateName].CoalitionName = CoalitionName
self.Templates.Groups[GroupTemplateName].CountryName = CountryName
self:T2( { "Group", self.Templates.Groups[GroupTemplateName].GroupName, self.Templates.Groups[GroupTemplateName].UnitCount } )
@ -318,9 +322,15 @@ function DATABASE:_RegisterTemplate( GroupTemplate )
self.Templates.Units[UnitTemplateName].GroupName = GroupTemplateName
self.Templates.Units[UnitTemplateName].GroupTemplate = GroupTemplate
self.Templates.Units[UnitTemplateName].GroupId = GroupTemplate.groupId
self.Templates.Units[UnitTemplateName].CategoryName = CategoryName
self.Templates.Units[UnitTemplateName].CoalitionName = CoalitionName
self.Templates.Units[UnitTemplateName].CountryName = CountryName
self:E( {"skill",UnitTemplate.skill})
if UnitTemplate.skill and (UnitTemplate.skill == "Client" or UnitTemplate.skill == "Player") then
self.Templates.ClientsByName[UnitTemplateName] = UnitTemplate
self.Templates.ClientsByName[UnitTemplateName].CategoryName = CategoryName
self.Templates.ClientsByName[UnitTemplateName].CoalitionName = CoalitionName
self.Templates.ClientsByName[UnitTemplateName].CountryName = CountryName
self.Templates.ClientsByID[UnitTemplate.unitId] = UnitTemplate
end
self:E( { "Unit", self.Templates.Units[UnitTemplateName].UnitName } )
@ -380,8 +390,16 @@ function DATABASE:_RegisterGroupsAndUnits()
end
end
return self
end
--- Private method that registers all Units of skill Client or Player within in the mission.
-- @param #DATABASE self
-- @return #DATABASE self
function DATABASE:_RegisterClients()
for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do
self:E( { "Adding Client:", ClientName } )
self:E( { "Register Client:", ClientName } )
self:AddClient( ClientName )
end
@ -608,25 +626,25 @@ function DATABASE:_RegisterTemplates()
self.Navpoints = {}
self.UNITS = {}
--Build routines.db.units and self.Navpoints
for coa_name, coa_data in pairs(env.mission.coalition) do
for CoalitionName, coa_data in pairs(env.mission.coalition) do
if (coa_name == 'red' or coa_name == 'blue') and type(coa_data) == 'table' then
if (CoalitionName == 'red' or CoalitionName == 'blue') and type(coa_data) == 'table' then
--self.Units[coa_name] = {}
----------------------------------------------
-- build nav points DB
self.Navpoints[coa_name] = {}
self.Navpoints[CoalitionName] = {}
if coa_data.nav_points then --navpoints
for nav_ind, nav_data in pairs(coa_data.nav_points) do
if type(nav_data) == 'table' then
self.Navpoints[coa_name][nav_ind] = routines.utils.deepCopy(nav_data)
self.Navpoints[CoalitionName][nav_ind] = routines.utils.deepCopy(nav_data)
self.Navpoints[coa_name][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory.
self.Navpoints[coa_name][nav_ind]['point'] = {} -- point is used by SSE, support it.
self.Navpoints[coa_name][nav_ind]['point']['x'] = nav_data.x
self.Navpoints[coa_name][nav_ind]['point']['y'] = 0
self.Navpoints[coa_name][nav_ind]['point']['z'] = nav_data.y
self.Navpoints[CoalitionName][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory.
self.Navpoints[CoalitionName][nav_ind]['point'] = {} -- point is used by SSE, support it.
self.Navpoints[CoalitionName][nav_ind]['point']['x'] = nav_data.x
self.Navpoints[CoalitionName][nav_ind]['point']['y'] = 0
self.Navpoints[CoalitionName][nav_ind]['point']['z'] = nav_data.y
end
end
end
@ -634,7 +652,7 @@ function DATABASE:_RegisterTemplates()
if coa_data.country then --there is a country table
for cntry_id, cntry_data in pairs(coa_data.country) do
local countryName = string.lower(cntry_data.name)
local CountryName = string.upper(cntry_data.name)
--self.Units[coa_name][countryName] = {}
--self.Units[coa_name][countryName]["countryId"] = cntry_data.id
@ -644,7 +662,7 @@ function DATABASE:_RegisterTemplates()
if obj_type_name == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" or obj_type_name == "static" then --should be an unncessary check
local category = obj_type_name
local CategoryName = obj_type_name
if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's a group!
@ -653,7 +671,7 @@ function DATABASE:_RegisterTemplates()
for group_num, GroupTemplate in pairs(obj_type_data.group) do
if GroupTemplate and GroupTemplate.units and type(GroupTemplate.units) == 'table' then --making sure again- this is a valid group
self:_RegisterTemplate( GroupTemplate )
self:_RegisterTemplate( GroupTemplate, CoalitionName, CategoryName, CountryName )
end --if GroupTemplate and GroupTemplate.units then
end --for group_num, GroupTemplate in pairs(obj_type_data.group) do
end --if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then

View File

@ -8,15 +8,16 @@
--
-- 1.1) MESSAGE construction methods
-- ---------------------------------
-- Messages are created with MESSAGE:@{New}. Note that when the MESSAGE object is created, no message is sent yet.
-- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
-- To send messages, you need to use the To functions.
--
-- 1.2) Send messages with MESSAGE To methods
-- ------------------------------------------
-- Messages are sent to:
-- * Clients with MESSAGE:@{ToClient}().
-- * Coalitions with MESSAGE:@{ToCoalition}().
-- * All Players with MESSAGE:@{ToAll}().
--
-- * Clients with @{Message#MESSAGE.ToClient}.
-- * Coalitions with @{Message#MESSAGE.ToCoalition}.
-- * All Players with @{Message#MESSAGE.ToAll}.
--
-- @module Message
-- @author FlightControl

View File

@ -35,6 +35,7 @@ Include.File( "Movement" )
Include.File( "Sead" )
Include.File( "Escort" )
Include.File( "MissileTrainer" )
Include.File( "AIBalancer" )

View File

@ -38,7 +38,7 @@
--
-- 2.2) Add or Remove GROUP(s) from SET_GROUP:
-- -------------------------------------------
-- GROUPS can be added and removed using the @{Set#SET_GROUP.AddGroupsByName} and @{Set#SET_GROUPS.RemoveGroupsByName} respectively.
-- 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:
@ -88,8 +88,12 @@
--
-- * @{#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.2) SET_UNIT filter criteria:
-- 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:
@ -108,19 +112,69 @@
--
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Zone#ZONE}.
--
-- 3.3) SET_UNIT iterators:
-- 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.ForEachUnitInGroup}: Calls a function for each group contained within the SET_UNIT.
-- * @{#SET_UNIT.ForEachUnitInZone}: Calls a function for each unit within a certain zone contained within the SET_UNIT.
-- * @{#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.
--
-- 4) @{Set#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 construction method:
-- ----------------------------------
-- 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.
--
-- ====
--
@ -487,7 +541,7 @@ function SET_GROUP:AddGroupsByName( AddGroupNames )
return self
end
--- Remove GROUP(s) to SET_GROUP.
--- Remove GROUP(s) from SET_GROUP.
-- @param Set#SET_GROUP self
-- @param Group#GROUP RemoveGroupNames A single name or an array of GROUP names.
-- @return self
@ -838,6 +892,36 @@ function SET_UNIT:New()
return self
end
--- Add UNIT(s) to SET_UNIT.
-- @param Set#SET_UNIT self
-- @param #string AddUnitNames A single name or an array of UNIT names.
-- @return self
function SET_UNIT:AddUnitsByName( AddUnitNames )
local AddUnitNamesArray = ( type( AddUnitNames ) == "table" ) and AddUnitNames or { AddUnitNames }
for AddUnitID, AddUnitName in pairs( AddUnitNamesArray ) do
self:Add( AddUnitName, UNIT:FindByName( AddUnitName ) )
end
return self
end
--- Remove UNIT(s) from SET_UNIT.
-- @param Set#SET_UNIT self
-- @param Unit#UNIT RemoveUnitNames A single name or an array of UNIT names.
-- @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.UnitName )
end
return self
end
--- Finds a Unit based on the Unit Name.
-- @param #SET_UNIT self
@ -1001,6 +1085,51 @@ function SET_UNIT:ForEachUnit( IteratorFunction, ... )
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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
function SET_UNIT:ForEachUnitCompletelyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsCompletelyInZone( 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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
function SET_UNIT:ForEachUnitNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsNotInZone( ZoneObject ) then
return true
else
return false
end
end, { ZoneObject } )
return self
end
----- Interate 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
@ -1095,3 +1224,362 @@ function SET_UNIT:IsIncludeObject( MUnit )
return MUnitInclude
end
--- SET_CLIENT
--- SET_CLIENT class
-- @type SET_CLIENT
-- @extends Set#SET_BASE
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 = "plane",
helicopter = "helicopter",
ground = "vehicle",
ship = "ship",
structure = "static",
},
},
}
--- 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 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 Set#SET_CLIENT self
-- @param 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 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 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 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
--- Interate 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 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:ForEachClientCompletelyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Client#CLIENT ClientObject
function( ZoneObject, ClientObject )
if ClientObject:IsCompletelyInZone( 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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
-- @return #SET_CLIENT self
function SET_CLIENT:ForEachClientNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Client#CLIENT ClientObject
function( ZoneObject, ClientObject )
if ClientObject:IsNotInZone( ZoneObject ) then
return true
else
return false
end
end, { ZoneObject } )
return self
end
---
-- @param #SET_CLIENT self
-- @param 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 ClientCoalitionName = _DATABASE.Templates.ClientsByName[MClientName].CoalitionName
self:T3( { "Coalition:", ClientCoalitionName, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == ClientCoalitionName 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 ClientCategoryName = _DATABASE.Templates.ClientsByName[MClientName].CategoryName
self:T3( { "Category:", ClientCategoryName, self.FilterMeta.Categories[CategoryName], CategoryName } )
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == ClientCategoryName 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 ClientCountryName = _DATABASE.Templates.ClientsByName[MClientName].CountryName
self:T3( { "Country:", ClientCountryName, country.id[CountryName], CountryName } )
if country.id[CountryName] and country.id[ClientCountryName] and country.id[CountryName] == country.id[ClientCountryName] 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

View File

@ -160,7 +160,8 @@ function UNIT:GetDCSUnit()
if DCSUnit then
return DCSUnit
end
self:E( "Unit " .. self.UnitName .. " not found!" )
return nil
end
@ -470,9 +471,11 @@ function UNIT:GetDesc()
if DCSUnit then
local UnitDesc = DCSUnit:getDesc()
self:T2( UnitDesc )
return UnitDesc
end
self:E( "Unit " .. self.UnitName .. "not found!" )
return nil
end

View File

@ -1,6 +1,5 @@
local base = _G
env.info("Loading MOOSE " .. base.timer.getAbsTime() )
Include = {}
@ -39,5 +38,3 @@ env.info( "Include.MissionPath = " .. Include.MissionPath)
Include.Files = {}
Include.File( "Moose" )
env.info("Loaded MOOSE Include Engine")

View File

@ -1,5 +1,4 @@
local base = _G
env.info("Loading MOOSE " .. base.timer.getAbsTime() )
Include = {}
@ -11,14 +10,4 @@ end
Include.File = function( IncludeFile )
end
Include.ProgramPath = "Scripts/Moose/Moose/"
Include.MissionPath = Include.Path()
env.info( "Include.ProgramPath = " .. Include.ProgramPath)
env.info( "Include.MissionPath = " .. Include.MissionPath)
Include.Files = {}
Include.File( "Moose" )
env.info("Loaded MOOSE Include Engine")

View File

@ -1,7 +1,6 @@
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20160609_1242' )
env.info( 'Moose Generation Timestamp: 20160610_1430' )
local base = _G
env.info("Loading MOOSE " .. base.timer.getAbsTime() )
Include = {}
@ -13,17 +12,7 @@ end
Include.File = function( IncludeFile )
end
Include.ProgramPath = "Scripts/Moose/Moose/"
Include.MissionPath = Include.Path()
env.info( "Include.ProgramPath = " .. Include.ProgramPath)
env.info( "Include.MissionPath = " .. Include.MissionPath)
Include.Files = {}
Include.File( "Moose" )
env.info("Loaded MOOSE Include Engine")
--- Various routines
-- @module routines
-- @author Flightcontrol
@ -2614,7 +2603,8 @@ local _TraceClassMethod = {}
BASE = {
ClassName = "BASE",
ClassID = 0,
Events = {}
Events = {},
States = {}
}
--- The Formation Class
@ -2869,6 +2859,36 @@ function BASE:onEvent(event)
end
end
function BASE:SetState( Object, StateName, State )
local ClassNameAndID = Object:GetClassNameAndID()
if not self.States[ClassNameAndID] then
self.States[ClassNameAndID] = {}
end
self.States[ClassNameAndID][StateName] = State
return self.States[ClassNameAndID][StateName]
end
function BASE:GetState( Object, StateName )
local ClassNameAndID = Object:GetClassNameAndID()
if self.States[ClassNameAndID] then
return self.States[ClassNameAndID][StateName]
end
return nil
end
function BASE:ClearState( Object, StateName )
local ClassNameAndID = Object:GetClassNameAndID()
if self.States[ClassNameAndID] then
self.States[ClassNameAndID][StateName] = nil
end
end
-- Trace section
-- Log a trace (only shown when trace is on)
@ -2972,10 +2992,10 @@ function BASE:F3( Arguments )
end
--- Trace a function logic. Can be anywhere within the function logic.
--- Trace a function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
function BASE:_T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
if _TraceOn and ( ( _TraceAll == true ) or ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) ) then
@ -2998,6 +3018,21 @@ function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
end
end
--- Trace a function logic level 1. Can be anywhere within the function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
function BASE:T( Arguments )
local DebugInfoCurrent = debug.getinfo( 2, "nl" )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 1 then
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end
--- Trace a function logic level 2. Can be anywhere within the function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
@ -3007,7 +3042,7 @@ function BASE:T2( Arguments )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 2 then
self:T( Arguments, DebugInfoCurrent, DebugInfoFrom )
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end
@ -3021,7 +3056,7 @@ function BASE:T3( Arguments )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 3 then
self:T( Arguments, DebugInfoCurrent, DebugInfoFrom )
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end
@ -6965,7 +7000,8 @@ function UNIT:GetDCSUnit()
if DCSUnit then
return DCSUnit
end
self:E( "Unit " .. self.UnitName .. " not found!" )
return nil
end
@ -7275,9 +7311,11 @@ function UNIT:GetDesc()
if DCSUnit then
local UnitDesc = DCSUnit:getDesc()
self:T2( UnitDesc )
return UnitDesc
end
self:E( "Unit " .. self.UnitName .. "not found!" )
return nil
end
@ -8748,6 +8786,7 @@ function DATABASE:New()
self:_RegisterTemplates()
self:_RegisterGroupsAndUnits()
self:_RegisterClients()
self:_RegisterStatics()
self:_RegisterPlayers()
@ -8930,7 +8969,7 @@ end
-- @param #DATABASE self
-- @param #table GroupTemplate
-- @return #DATABASE self
function DATABASE:_RegisterTemplate( GroupTemplate )
function DATABASE:_RegisterTemplate( GroupTemplate, CoalitionName, CategoryName, CountryName )
local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name)
@ -8949,6 +8988,9 @@ function DATABASE:_RegisterTemplate( GroupTemplate )
self.Templates.Groups[GroupTemplateName].groupId = GroupTemplate.groupId
self.Templates.Groups[GroupTemplateName].UnitCount = #GroupTemplate.units
self.Templates.Groups[GroupTemplateName].Units = GroupTemplate.units
self.Templates.Groups[GroupTemplateName].CategoryName = CategoryName
self.Templates.Groups[GroupTemplateName].CoalitionName = CoalitionName
self.Templates.Groups[GroupTemplateName].CountryName = CountryName
self:T2( { "Group", self.Templates.Groups[GroupTemplateName].GroupName, self.Templates.Groups[GroupTemplateName].UnitCount } )
@ -8961,9 +9003,15 @@ function DATABASE:_RegisterTemplate( GroupTemplate )
self.Templates.Units[UnitTemplateName].GroupName = GroupTemplateName
self.Templates.Units[UnitTemplateName].GroupTemplate = GroupTemplate
self.Templates.Units[UnitTemplateName].GroupId = GroupTemplate.groupId
self.Templates.Units[UnitTemplateName].CategoryName = CategoryName
self.Templates.Units[UnitTemplateName].CoalitionName = CoalitionName
self.Templates.Units[UnitTemplateName].CountryName = CountryName
self:E( {"skill",UnitTemplate.skill})
if UnitTemplate.skill and (UnitTemplate.skill == "Client" or UnitTemplate.skill == "Player") then
self.Templates.ClientsByName[UnitTemplateName] = UnitTemplate
self.Templates.ClientsByName[UnitTemplateName].CategoryName = CategoryName
self.Templates.ClientsByName[UnitTemplateName].CoalitionName = CoalitionName
self.Templates.ClientsByName[UnitTemplateName].CountryName = CountryName
self.Templates.ClientsByID[UnitTemplate.unitId] = UnitTemplate
end
self:E( { "Unit", self.Templates.Units[UnitTemplateName].UnitName } )
@ -9023,8 +9071,16 @@ function DATABASE:_RegisterGroupsAndUnits()
end
end
return self
end
--- Private method that registers all Units of skill Client or Player within in the mission.
-- @param #DATABASE self
-- @return #DATABASE self
function DATABASE:_RegisterClients()
for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do
self:E( { "Adding Client:", ClientName } )
self:E( { "Register Client:", ClientName } )
self:AddClient( ClientName )
end
@ -9251,25 +9307,25 @@ function DATABASE:_RegisterTemplates()
self.Navpoints = {}
self.UNITS = {}
--Build routines.db.units and self.Navpoints
for coa_name, coa_data in pairs(env.mission.coalition) do
for CoalitionName, coa_data in pairs(env.mission.coalition) do
if (coa_name == 'red' or coa_name == 'blue') and type(coa_data) == 'table' then
if (CoalitionName == 'red' or CoalitionName == 'blue') and type(coa_data) == 'table' then
--self.Units[coa_name] = {}
----------------------------------------------
-- build nav points DB
self.Navpoints[coa_name] = {}
self.Navpoints[CoalitionName] = {}
if coa_data.nav_points then --navpoints
for nav_ind, nav_data in pairs(coa_data.nav_points) do
if type(nav_data) == 'table' then
self.Navpoints[coa_name][nav_ind] = routines.utils.deepCopy(nav_data)
self.Navpoints[CoalitionName][nav_ind] = routines.utils.deepCopy(nav_data)
self.Navpoints[coa_name][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory.
self.Navpoints[coa_name][nav_ind]['point'] = {} -- point is used by SSE, support it.
self.Navpoints[coa_name][nav_ind]['point']['x'] = nav_data.x
self.Navpoints[coa_name][nav_ind]['point']['y'] = 0
self.Navpoints[coa_name][nav_ind]['point']['z'] = nav_data.y
self.Navpoints[CoalitionName][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory.
self.Navpoints[CoalitionName][nav_ind]['point'] = {} -- point is used by SSE, support it.
self.Navpoints[CoalitionName][nav_ind]['point']['x'] = nav_data.x
self.Navpoints[CoalitionName][nav_ind]['point']['y'] = 0
self.Navpoints[CoalitionName][nav_ind]['point']['z'] = nav_data.y
end
end
end
@ -9277,7 +9333,7 @@ function DATABASE:_RegisterTemplates()
if coa_data.country then --there is a country table
for cntry_id, cntry_data in pairs(coa_data.country) do
local countryName = string.lower(cntry_data.name)
local CountryName = string.upper(cntry_data.name)
--self.Units[coa_name][countryName] = {}
--self.Units[coa_name][countryName]["countryId"] = cntry_data.id
@ -9287,7 +9343,7 @@ function DATABASE:_RegisterTemplates()
if obj_type_name == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" or obj_type_name == "static" then --should be an unncessary check
local category = obj_type_name
local CategoryName = obj_type_name
if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's a group!
@ -9296,7 +9352,7 @@ function DATABASE:_RegisterTemplates()
for group_num, GroupTemplate in pairs(obj_type_data.group) do
if GroupTemplate and GroupTemplate.units and type(GroupTemplate.units) == 'table' then --making sure again- this is a valid group
self:_RegisterTemplate( GroupTemplate )
self:_RegisterTemplate( GroupTemplate, CoalitionName, CategoryName, CountryName )
end --if GroupTemplate and GroupTemplate.units then
end --for group_num, GroupTemplate in pairs(obj_type_data.group) do
end --if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then
@ -9354,7 +9410,7 @@ end
--
-- 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_GROUPS.RemoveGroupsByName} respectively.
-- 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:
@ -9404,8 +9460,12 @@ end
--
-- * @{#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.2) SET_UNIT filter criteria:
-- 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:
@ -9424,19 +9484,69 @@ end
--
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Zone#ZONE}.
--
-- 3.3) SET_UNIT iterators:
-- 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.ForEachUnitInGroup}: Calls a function for each group contained within the SET_UNIT.
-- * @{#SET_UNIT.ForEachUnitInZone}: Calls a function for each unit within a certain zone contained within the SET_UNIT.
-- * @{#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.
--
-- 4) @{Set#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 construction method:
-- ----------------------------------
-- 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.
--
-- ====
--
@ -9803,7 +9913,7 @@ function SET_GROUP:AddGroupsByName( AddGroupNames )
return self
end
--- Remove GROUP(s) to SET_GROUP.
--- Remove GROUP(s) from SET_GROUP.
-- @param Set#SET_GROUP self
-- @param Group#GROUP RemoveGroupNames A single name or an array of GROUP names.
-- @return self
@ -10154,6 +10264,36 @@ function SET_UNIT:New()
return self
end
--- Add UNIT(s) to SET_UNIT.
-- @param Set#SET_UNIT self
-- @param #string AddUnitNames A single name or an array of UNIT names.
-- @return self
function SET_UNIT:AddUnitsByName( AddUnitNames )
local AddUnitNamesArray = ( type( AddUnitNames ) == "table" ) and AddUnitNames or { AddUnitNames }
for AddUnitID, AddUnitName in pairs( AddUnitNamesArray ) do
self:Add( AddUnitName, UNIT:FindByName( AddUnitName ) )
end
return self
end
--- Remove UNIT(s) from SET_UNIT.
-- @param Set#SET_UNIT self
-- @param Unit#UNIT RemoveUnitNames A single name or an array of UNIT names.
-- @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.UnitName )
end
return self
end
--- Finds a Unit based on the Unit Name.
-- @param #SET_UNIT self
@ -10317,6 +10457,51 @@ function SET_UNIT:ForEachUnit( IteratorFunction, ... )
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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
function SET_UNIT:ForEachUnitCompletelyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsCompletelyInZone( 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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
function SET_UNIT:ForEachUnitNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsNotInZone( ZoneObject ) then
return true
else
return false
end
end, { ZoneObject } )
return self
end
----- Interate 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
@ -10411,6 +10596,365 @@ function SET_UNIT:IsIncludeObject( MUnit )
return MUnitInclude
end
--- SET_CLIENT
--- SET_CLIENT class
-- @type SET_CLIENT
-- @extends Set#SET_BASE
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 = "plane",
helicopter = "helicopter",
ground = "vehicle",
ship = "ship",
structure = "static",
},
},
}
--- 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 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 Set#SET_CLIENT self
-- @param 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 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 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 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
--- Interate 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 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:ForEachClientCompletelyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Client#CLIENT ClientObject
function( ZoneObject, ClientObject )
if ClientObject:IsCompletelyInZone( 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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
-- @return #SET_CLIENT self
function SET_CLIENT:ForEachClientNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Client#CLIENT ClientObject
function( ZoneObject, ClientObject )
if ClientObject:IsNotInZone( ZoneObject ) then
return true
else
return false
end
end, { ZoneObject } )
return self
end
---
-- @param #SET_CLIENT self
-- @param 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 ClientCoalitionName = _DATABASE.Templates.ClientsByName[MClientName].CoalitionName
self:T3( { "Coalition:", ClientCoalitionName, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == ClientCoalitionName 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 ClientCategoryName = _DATABASE.Templates.ClientsByName[MClientName].CategoryName
self:T3( { "Category:", ClientCategoryName, self.FilterMeta.Categories[CategoryName], CategoryName } )
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == ClientCategoryName 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 ClientCountryName = _DATABASE.Templates.ClientsByName[MClientName].CountryName
self:T3( { "Country:", ClientCountryName, country.id[CountryName], CountryName } )
if country.id[CountryName] and country.id[ClientCountryName] and country.id[CountryName] == country.id[ClientCountryName] 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
--- This module contains the POINT classes.
--
-- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE}
@ -10639,6 +11183,7 @@ Include.File( "Movement" )
Include.File( "Sead" )
Include.File( "Escort" )
Include.File( "MissileTrainer" )
Include.File( "AIBalancer" )
@ -12573,15 +13118,16 @@ end
--
-- 1.1) MESSAGE construction methods
-- ---------------------------------
-- Messages are created with MESSAGE:@{New}. Note that when the MESSAGE object is created, no message is sent yet.
-- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
-- To send messages, you need to use the To functions.
--
-- 1.2) Send messages with MESSAGE To methods
-- ------------------------------------------
-- Messages are sent to:
-- * Clients with MESSAGE:@{ToClient}().
-- * Coalitions with MESSAGE:@{ToCoalition}().
-- * All Players with MESSAGE:@{ToAll}().
--
-- * Clients with @{Message#MESSAGE.ToClient}.
-- * Coalitions with @{Message#MESSAGE.ToCoalition}.
-- * All Players with @{Message#MESSAGE.ToAll}.
--
-- @module Message
-- @author FlightControl
@ -19362,4 +19908,78 @@ function MISSILETRAINER:_TrackMissiles()
return true
end
--- This module contains the AIBALANCER class.
--
-- ===
--
-- 1) @{AIBalancer#AIBALANCER} class, extends @{Base#BASE}
-- ================================================
-- The @{AIBalancer#AIBALANCER} class controls the dynamic spawning of AI GROUPS depending on a SET_CLIENT.
-- There will be as many AI GROUPS spawned as there at CLIENTS in SET_CLIENT not spawned.
--
-- 1.1) AIBALANCER construction method:
-- ------------------------------------
-- Create a new AIBALANCER object with the @{#AIBALANCER.New} method:
--
-- * @{#AIBALANCER.New}: Creates a new AIBALANCER object.
--
--
-- ===
-- @module AIBalancer
-- @author FlightControl
--- AIBALANCER class
-- @type AIBALANCER
-- @field Set#SET_CLIENT SetClient
-- @field Spawn#SPAWN SpawnAI
-- @extends Base#BASE
AIBALANCER = {
ClassName = "AIBALANCER",
}
--- Creates a new AIBALANCER object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
-- @param #AIBALANCER self
-- @param SetClient A SET_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player).
-- @param SpawnAI A SPAWN object that will spawn the AI units required, balancing the SetClient.
-- @return #AIBALANCER self
function AIBALANCER:New( SetClient, SpawnAI )
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() )
self.SetClient = SetClient
self.SpawnAI = SpawnAI
self.AIMonitorSchedule = SCHEDULER:New( self, self._ClientAliveMonitorScheduler, {}, 1, 10, 0 )
return self
end
--- @param #AIBALANCER self
function AIBALANCER:_ClientAliveMonitorScheduler()
self.SetClient:ForEachClient(
--- @param Client#CLIENT Client
function( Client )
local ClientAIAliveState = Client:GetState( self, 'AIAlive' )
self:T( ClientAIAliveState )
if Client:IsAlive() then
if ClientAIAliveState == true then
Client:SetState( self, 'AIAlive', false )
local AIGroup = Client:GetState( self, 'AIGroup' ) -- Group#GROUP
AIGroup:Destroy()
end
else
if not ClientAIAliveState or ClientAIAliveState == false then
Client:SetState( self, 'AIAlive', true )
Client:SetState( self, 'AIGroup', self.SpawnAI:Spawn() )
end
end
end
)
return true
end
env.info( '*** MOOSE INCLUDE END *** ' )

View File

@ -1,7 +1,6 @@
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20160609_1242' )
env.info( 'Moose Generation Timestamp: 20160610_1430' )
local base = _G
env.info("Loading MOOSE " .. base.timer.getAbsTime() )
Include = {}
@ -13,17 +12,7 @@ end
Include.File = function( IncludeFile )
end
Include.ProgramPath = "Scripts/Moose/Moose/"
Include.MissionPath = Include.Path()
env.info( "Include.ProgramPath = " .. Include.ProgramPath)
env.info( "Include.MissionPath = " .. Include.MissionPath)
Include.Files = {}
Include.File( "Moose" )
env.info("Loaded MOOSE Include Engine")
--- Various routines
-- @module routines
-- @author Flightcontrol
@ -2614,7 +2603,8 @@ local _TraceClassMethod = {}
BASE = {
ClassName = "BASE",
ClassID = 0,
Events = {}
Events = {},
States = {}
}
--- The Formation Class
@ -2869,6 +2859,36 @@ function BASE:onEvent(event)
end
end
function BASE:SetState( Object, StateName, State )
local ClassNameAndID = Object:GetClassNameAndID()
if not self.States[ClassNameAndID] then
self.States[ClassNameAndID] = {}
end
self.States[ClassNameAndID][StateName] = State
return self.States[ClassNameAndID][StateName]
end
function BASE:GetState( Object, StateName )
local ClassNameAndID = Object:GetClassNameAndID()
if self.States[ClassNameAndID] then
return self.States[ClassNameAndID][StateName]
end
return nil
end
function BASE:ClearState( Object, StateName )
local ClassNameAndID = Object:GetClassNameAndID()
if self.States[ClassNameAndID] then
self.States[ClassNameAndID][StateName] = nil
end
end
-- Trace section
-- Log a trace (only shown when trace is on)
@ -2972,10 +2992,10 @@ function BASE:F3( Arguments )
end
--- Trace a function logic. Can be anywhere within the function logic.
--- Trace a function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
function BASE:_T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
if _TraceOn and ( ( _TraceAll == true ) or ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) ) then
@ -2998,6 +3018,21 @@ function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam )
end
end
--- Trace a function logic level 1. Can be anywhere within the function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
function BASE:T( Arguments )
local DebugInfoCurrent = debug.getinfo( 2, "nl" )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 1 then
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end
--- Trace a function logic level 2. Can be anywhere within the function logic.
-- @param #BASE self
-- @param Arguments A #table or any field.
@ -3007,7 +3042,7 @@ function BASE:T2( Arguments )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 2 then
self:T( Arguments, DebugInfoCurrent, DebugInfoFrom )
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end
@ -3021,7 +3056,7 @@ function BASE:T3( Arguments )
local DebugInfoFrom = debug.getinfo( 3, "l" )
if _TraceLevel >= 3 then
self:T( Arguments, DebugInfoCurrent, DebugInfoFrom )
self:_T( Arguments, DebugInfoCurrent, DebugInfoFrom )
end
end
@ -6965,7 +7000,8 @@ function UNIT:GetDCSUnit()
if DCSUnit then
return DCSUnit
end
self:E( "Unit " .. self.UnitName .. " not found!" )
return nil
end
@ -7275,9 +7311,11 @@ function UNIT:GetDesc()
if DCSUnit then
local UnitDesc = DCSUnit:getDesc()
self:T2( UnitDesc )
return UnitDesc
end
self:E( "Unit " .. self.UnitName .. "not found!" )
return nil
end
@ -8748,6 +8786,7 @@ function DATABASE:New()
self:_RegisterTemplates()
self:_RegisterGroupsAndUnits()
self:_RegisterClients()
self:_RegisterStatics()
self:_RegisterPlayers()
@ -8930,7 +8969,7 @@ end
-- @param #DATABASE self
-- @param #table GroupTemplate
-- @return #DATABASE self
function DATABASE:_RegisterTemplate( GroupTemplate )
function DATABASE:_RegisterTemplate( GroupTemplate, CoalitionName, CategoryName, CountryName )
local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name)
@ -8949,6 +8988,9 @@ function DATABASE:_RegisterTemplate( GroupTemplate )
self.Templates.Groups[GroupTemplateName].groupId = GroupTemplate.groupId
self.Templates.Groups[GroupTemplateName].UnitCount = #GroupTemplate.units
self.Templates.Groups[GroupTemplateName].Units = GroupTemplate.units
self.Templates.Groups[GroupTemplateName].CategoryName = CategoryName
self.Templates.Groups[GroupTemplateName].CoalitionName = CoalitionName
self.Templates.Groups[GroupTemplateName].CountryName = CountryName
self:T2( { "Group", self.Templates.Groups[GroupTemplateName].GroupName, self.Templates.Groups[GroupTemplateName].UnitCount } )
@ -8961,9 +9003,15 @@ function DATABASE:_RegisterTemplate( GroupTemplate )
self.Templates.Units[UnitTemplateName].GroupName = GroupTemplateName
self.Templates.Units[UnitTemplateName].GroupTemplate = GroupTemplate
self.Templates.Units[UnitTemplateName].GroupId = GroupTemplate.groupId
self.Templates.Units[UnitTemplateName].CategoryName = CategoryName
self.Templates.Units[UnitTemplateName].CoalitionName = CoalitionName
self.Templates.Units[UnitTemplateName].CountryName = CountryName
self:E( {"skill",UnitTemplate.skill})
if UnitTemplate.skill and (UnitTemplate.skill == "Client" or UnitTemplate.skill == "Player") then
self.Templates.ClientsByName[UnitTemplateName] = UnitTemplate
self.Templates.ClientsByName[UnitTemplateName].CategoryName = CategoryName
self.Templates.ClientsByName[UnitTemplateName].CoalitionName = CoalitionName
self.Templates.ClientsByName[UnitTemplateName].CountryName = CountryName
self.Templates.ClientsByID[UnitTemplate.unitId] = UnitTemplate
end
self:E( { "Unit", self.Templates.Units[UnitTemplateName].UnitName } )
@ -9023,8 +9071,16 @@ function DATABASE:_RegisterGroupsAndUnits()
end
end
return self
end
--- Private method that registers all Units of skill Client or Player within in the mission.
-- @param #DATABASE self
-- @return #DATABASE self
function DATABASE:_RegisterClients()
for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do
self:E( { "Adding Client:", ClientName } )
self:E( { "Register Client:", ClientName } )
self:AddClient( ClientName )
end
@ -9251,25 +9307,25 @@ function DATABASE:_RegisterTemplates()
self.Navpoints = {}
self.UNITS = {}
--Build routines.db.units and self.Navpoints
for coa_name, coa_data in pairs(env.mission.coalition) do
for CoalitionName, coa_data in pairs(env.mission.coalition) do
if (coa_name == 'red' or coa_name == 'blue') and type(coa_data) == 'table' then
if (CoalitionName == 'red' or CoalitionName == 'blue') and type(coa_data) == 'table' then
--self.Units[coa_name] = {}
----------------------------------------------
-- build nav points DB
self.Navpoints[coa_name] = {}
self.Navpoints[CoalitionName] = {}
if coa_data.nav_points then --navpoints
for nav_ind, nav_data in pairs(coa_data.nav_points) do
if type(nav_data) == 'table' then
self.Navpoints[coa_name][nav_ind] = routines.utils.deepCopy(nav_data)
self.Navpoints[CoalitionName][nav_ind] = routines.utils.deepCopy(nav_data)
self.Navpoints[coa_name][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory.
self.Navpoints[coa_name][nav_ind]['point'] = {} -- point is used by SSE, support it.
self.Navpoints[coa_name][nav_ind]['point']['x'] = nav_data.x
self.Navpoints[coa_name][nav_ind]['point']['y'] = 0
self.Navpoints[coa_name][nav_ind]['point']['z'] = nav_data.y
self.Navpoints[CoalitionName][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory.
self.Navpoints[CoalitionName][nav_ind]['point'] = {} -- point is used by SSE, support it.
self.Navpoints[CoalitionName][nav_ind]['point']['x'] = nav_data.x
self.Navpoints[CoalitionName][nav_ind]['point']['y'] = 0
self.Navpoints[CoalitionName][nav_ind]['point']['z'] = nav_data.y
end
end
end
@ -9277,7 +9333,7 @@ function DATABASE:_RegisterTemplates()
if coa_data.country then --there is a country table
for cntry_id, cntry_data in pairs(coa_data.country) do
local countryName = string.lower(cntry_data.name)
local CountryName = string.upper(cntry_data.name)
--self.Units[coa_name][countryName] = {}
--self.Units[coa_name][countryName]["countryId"] = cntry_data.id
@ -9287,7 +9343,7 @@ function DATABASE:_RegisterTemplates()
if obj_type_name == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" or obj_type_name == "static" then --should be an unncessary check
local category = obj_type_name
local CategoryName = obj_type_name
if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's a group!
@ -9296,7 +9352,7 @@ function DATABASE:_RegisterTemplates()
for group_num, GroupTemplate in pairs(obj_type_data.group) do
if GroupTemplate and GroupTemplate.units and type(GroupTemplate.units) == 'table' then --making sure again- this is a valid group
self:_RegisterTemplate( GroupTemplate )
self:_RegisterTemplate( GroupTemplate, CoalitionName, CategoryName, CountryName )
end --if GroupTemplate and GroupTemplate.units then
end --for group_num, GroupTemplate in pairs(obj_type_data.group) do
end --if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then
@ -9354,7 +9410,7 @@ end
--
-- 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_GROUPS.RemoveGroupsByName} respectively.
-- 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:
@ -9404,8 +9460,12 @@ end
--
-- * @{#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.2) SET_UNIT filter criteria:
-- 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:
@ -9424,19 +9484,69 @@ end
--
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Zone#ZONE}.
--
-- 3.3) SET_UNIT iterators:
-- 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.ForEachUnitInGroup}: Calls a function for each group contained within the SET_UNIT.
-- * @{#SET_UNIT.ForEachUnitInZone}: Calls a function for each unit within a certain zone contained within the SET_UNIT.
-- * @{#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.
--
-- 4) @{Set#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 construction method:
-- ----------------------------------
-- 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.
--
-- ====
--
@ -9803,7 +9913,7 @@ function SET_GROUP:AddGroupsByName( AddGroupNames )
return self
end
--- Remove GROUP(s) to SET_GROUP.
--- Remove GROUP(s) from SET_GROUP.
-- @param Set#SET_GROUP self
-- @param Group#GROUP RemoveGroupNames A single name or an array of GROUP names.
-- @return self
@ -10154,6 +10264,36 @@ function SET_UNIT:New()
return self
end
--- Add UNIT(s) to SET_UNIT.
-- @param Set#SET_UNIT self
-- @param #string AddUnitNames A single name or an array of UNIT names.
-- @return self
function SET_UNIT:AddUnitsByName( AddUnitNames )
local AddUnitNamesArray = ( type( AddUnitNames ) == "table" ) and AddUnitNames or { AddUnitNames }
for AddUnitID, AddUnitName in pairs( AddUnitNamesArray ) do
self:Add( AddUnitName, UNIT:FindByName( AddUnitName ) )
end
return self
end
--- Remove UNIT(s) from SET_UNIT.
-- @param Set#SET_UNIT self
-- @param Unit#UNIT RemoveUnitNames A single name or an array of UNIT names.
-- @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.UnitName )
end
return self
end
--- Finds a Unit based on the Unit Name.
-- @param #SET_UNIT self
@ -10317,6 +10457,51 @@ function SET_UNIT:ForEachUnit( IteratorFunction, ... )
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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
function SET_UNIT:ForEachUnitCompletelyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsCompletelyInZone( 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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
function SET_UNIT:ForEachUnitNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsNotInZone( ZoneObject ) then
return true
else
return false
end
end, { ZoneObject } )
return self
end
----- Interate 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
@ -10411,6 +10596,365 @@ function SET_UNIT:IsIncludeObject( MUnit )
return MUnitInclude
end
--- SET_CLIENT
--- SET_CLIENT class
-- @type SET_CLIENT
-- @extends Set#SET_BASE
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 = "plane",
helicopter = "helicopter",
ground = "vehicle",
ship = "ship",
structure = "static",
},
},
}
--- 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 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 Set#SET_CLIENT self
-- @param 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 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 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 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
--- Interate 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 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:ForEachClientCompletelyInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Client#CLIENT ClientObject
function( ZoneObject, ClientObject )
if ClientObject:IsCompletelyInZone( 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 Zone#ZONE ZoneObject The Zone to be tested for.
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
-- @return #SET_CLIENT self
function SET_CLIENT:ForEachClientNotInZone( ZoneObject, IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set,
--- @param Zone#ZONE_BASE ZoneObject
-- @param Client#CLIENT ClientObject
function( ZoneObject, ClientObject )
if ClientObject:IsNotInZone( ZoneObject ) then
return true
else
return false
end
end, { ZoneObject } )
return self
end
---
-- @param #SET_CLIENT self
-- @param 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 ClientCoalitionName = _DATABASE.Templates.ClientsByName[MClientName].CoalitionName
self:T3( { "Coalition:", ClientCoalitionName, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == ClientCoalitionName 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 ClientCategoryName = _DATABASE.Templates.ClientsByName[MClientName].CategoryName
self:T3( { "Category:", ClientCategoryName, self.FilterMeta.Categories[CategoryName], CategoryName } )
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == ClientCategoryName 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 ClientCountryName = _DATABASE.Templates.ClientsByName[MClientName].CountryName
self:T3( { "Country:", ClientCountryName, country.id[CountryName], CountryName } )
if country.id[CountryName] and country.id[ClientCountryName] and country.id[CountryName] == country.id[ClientCountryName] 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
--- This module contains the POINT classes.
--
-- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE}
@ -10639,6 +11183,7 @@ Include.File( "Movement" )
Include.File( "Sead" )
Include.File( "Escort" )
Include.File( "MissileTrainer" )
Include.File( "AIBalancer" )
@ -12573,15 +13118,16 @@ end
--
-- 1.1) MESSAGE construction methods
-- ---------------------------------
-- Messages are created with MESSAGE:@{New}. Note that when the MESSAGE object is created, no message is sent yet.
-- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
-- To send messages, you need to use the To functions.
--
-- 1.2) Send messages with MESSAGE To methods
-- ------------------------------------------
-- Messages are sent to:
-- * Clients with MESSAGE:@{ToClient}().
-- * Coalitions with MESSAGE:@{ToCoalition}().
-- * All Players with MESSAGE:@{ToAll}().
--
-- * Clients with @{Message#MESSAGE.ToClient}.
-- * Coalitions with @{Message#MESSAGE.ToCoalition}.
-- * All Players with @{Message#MESSAGE.ToAll}.
--
-- @module Message
-- @author FlightControl
@ -19362,4 +19908,78 @@ function MISSILETRAINER:_TrackMissiles()
return true
end
--- This module contains the AIBALANCER class.
--
-- ===
--
-- 1) @{AIBalancer#AIBALANCER} class, extends @{Base#BASE}
-- ================================================
-- The @{AIBalancer#AIBALANCER} class controls the dynamic spawning of AI GROUPS depending on a SET_CLIENT.
-- There will be as many AI GROUPS spawned as there at CLIENTS in SET_CLIENT not spawned.
--
-- 1.1) AIBALANCER construction method:
-- ------------------------------------
-- Create a new AIBALANCER object with the @{#AIBALANCER.New} method:
--
-- * @{#AIBALANCER.New}: Creates a new AIBALANCER object.
--
--
-- ===
-- @module AIBalancer
-- @author FlightControl
--- AIBALANCER class
-- @type AIBALANCER
-- @field Set#SET_CLIENT SetClient
-- @field Spawn#SPAWN SpawnAI
-- @extends Base#BASE
AIBALANCER = {
ClassName = "AIBALANCER",
}
--- Creates a new AIBALANCER object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
-- @param #AIBALANCER self
-- @param SetClient A SET_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player).
-- @param SpawnAI A SPAWN object that will spawn the AI units required, balancing the SetClient.
-- @return #AIBALANCER self
function AIBALANCER:New( SetClient, SpawnAI )
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() )
self.SetClient = SetClient
self.SpawnAI = SpawnAI
self.AIMonitorSchedule = SCHEDULER:New( self, self._ClientAliveMonitorScheduler, {}, 1, 10, 0 )
return self
end
--- @param #AIBALANCER self
function AIBALANCER:_ClientAliveMonitorScheduler()
self.SetClient:ForEachClient(
--- @param Client#CLIENT Client
function( Client )
local ClientAIAliveState = Client:GetState( self, 'AIAlive' )
self:T( ClientAIAliveState )
if Client:IsAlive() then
if ClientAIAliveState == true then
Client:SetState( self, 'AIAlive', false )
local AIGroup = Client:GetState( self, 'AIGroup' ) -- Group#GROUP
AIGroup:Destroy()
end
else
if not ClientAIAliveState or ClientAIAliveState == false then
Client:SetState( self, 'AIAlive', true )
Client:SetState( self, 'AIGroup', self.SpawnAI:Spawn() )
end
end
end
)
return true
end
env.info( '*** MOOSE INCLUDE END *** ' )

View File

@ -72,6 +72,7 @@ COPY /b Moose.lua + %1\Movement.lua Moose.lua
COPY /b Moose.lua + %1\Sead.lua Moose.lua
COPY /b Moose.lua + %1\Escort.lua Moose.lua
COPY /b Moose.lua + %1\MissileTrainer.lua Moose.lua
COPY /b Moose.lua + %1\AIBalancer.lua Moose.lua
GOTO End

View File

@ -0,0 +1,8 @@
local US_PlanesClientSet = SET_CLIENT:New():FilterCountries( "USA" ):FilterCategories( "plane" ):FilterStart()
local US_PlanesSpawn = SPAWN:New( "AI US" )
local RU_AIBalancer = AIBALANCER:New( US_PlanesClientSet, US_PlanesSpawn )
local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ):FilterStart()
local RU_PlanesSpawn = SPAWN:New( "AI RU" )
local RU_AIBalancer = AIBALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn )

View File

@ -1,620 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<link rel="stylesheet" href="stylesheet.css" type="text/css"/>
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div>
<div id="main">
<div id="navigation">
<h2>Modules</h2>
<ul><li>
<a href="index.html">index</a>
</li></ul>
<ul>
<li><a href="Airbase.html">Airbase</a></li>
<li><a href="Base.html">Base</a></li>
<li><a href="CARGO.html">CARGO</a></li>
<li><a href="CleanUp.html">CleanUp</a></li>
<li><a href="Client.html">Client</a></li>
<li><a href="DCSAirbase.html">DCSAirbase</a></li>
<li><a href="DCSCoalitionObject.html">DCSCoalitionObject</a></li>
<li><a href="DCSCommand.html">DCSCommand</a></li>
<li><a href="DCSController.html">DCSController</a></li>
<li><a href="DCSGroup.html">DCSGroup</a></li>
<li><a href="DCSObject.html">DCSObject</a></li>
<li><a href="DCSTask.html">DCSTask</a></li>
<li><a href="DCSTypes.html">DCSTypes</a></li>
<li><a href="DCSUnit.html">DCSUnit</a></li>
<li><a href="DCSWorld.html">DCSWorld</a></li>
<li><a href="DCStimer.html">DCStimer</a></li>
<li><a href="DEPLOYTASK.html">DEPLOYTASK</a></li>
<li><a href="DESTROYBASETASK.html">DESTROYBASETASK</a></li>
<li><a href="DESTROYGROUPSTASK.html">DESTROYGROUPSTASK</a></li>
<li><a href="DESTROYRADARSTASK.html">DESTROYRADARSTASK</a></li>
<li><a href="DESTROYUNITTYPESTASK.html">DESTROYUNITTYPESTASK</a></li>
<li><a href="Database.html">Database</a></li>
<li><a href="Escort.html">Escort</a></li>
<li><a href="Event.html">Event</a></li>
<li><a href="GOHOMETASK.html">GOHOMETASK</a></li>
<li><a href="Group.html">Group</a></li>
<li>GroupSet</li>
<li><a href="MOVEMENT.html">MOVEMENT</a></li>
<li><a href="Menu.html">Menu</a></li>
<li><a href="Message.html">Message</a></li>
<li><a href="MissileTrainer.html">MissileTrainer</a></li>
<li><a href="Mission.html">Mission</a></li>
<li><a href="NOTASK.html">NOTASK</a></li>
<li><a href="PICKUPTASK.html">PICKUPTASK</a></li>
<li><a href="Point.html">Point</a></li>
<li><a href="ROUTETASK.html">ROUTETASK</a></li>
<li><a href="STAGE.html">STAGE</a></li>
<li><a href="Scheduler.html">Scheduler</a></li>
<li><a href="Scoring.html">Scoring</a></li>
<li><a href="Sead.html">Sead</a></li>
<li><a href="Set.html">Set</a></li>
<li><a href="Spawn.html">Spawn</a></li>
<li><a href="Static.html">Static</a></li>
<li><a href="StaticObject.html">StaticObject</a></li>
<li><a href="TASK.html">TASK</a></li>
<li><a href="Unit.html">Unit</a></li>
<li><a href="UnitSet.html">UnitSet</a></li>
<li><a href="Zone.html">Zone</a></li>
<li><a href="env.html">env</a></li>
<li><a href="land.html">land</a></li>
<li><a href="routines.html">routines</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>GroupSet</code></h1>
<p>Create and manage a set of groups.</p>
<h1><a href="##(GROUPSET)">#GROUPSET</a> class</h1>
<p>Mission designers can use the GROUPSET class to build sets of groups belonging to certain:</p>
<ul>
<li>Coalitions</li>
<li>Categories</li>
<li>Countries</li>
<li>Starting with certain prefix strings.</li>
</ul>
<h1>GROUPSET construction methods:</h1>
<p>Create a new GROUPSET object with the <a href="##(GROUPSET).New">GROUPSET.New</a> method:</p>
<ul>
<li><a href="##(GROUPSET).New">GROUPSET.New</a>: Creates a new GROUPSET object.</li>
</ul>
<h1>GROUPSET filter criteria: </h1>
<p>You can set filter criteria to define the set of groups within the GROUPSET.
Filter criteria are defined by:</p>
<ul>
<li><a href="##(GROUPSET).FilterCoalitions">GROUPSET.FilterCoalitions</a>: Builds the GROUPSET with the groups belonging to the coalition(s).</li>
<li><a href="##(GROUPSET).FilterCategories">GROUPSET.FilterCategories</a>: Builds the GROUPSET with the groups belonging to the category(ies).</li>
<li><a href="##(GROUPSET).FilterCountries">GROUPSET.FilterCountries</a>: Builds the GROUPSET with the gruops belonging to the country(ies).</li>
<li><a href="##(GROUPSET).FilterPrefixes">GROUPSET.FilterPrefixes</a>: Builds the GROUPSET with the groups starting with the same prefix string(s).</li>
</ul>
<p>Once the filter criteria have been set for the GROUPSET, you can start filtering using:</p>
<ul>
<li><a href="##(GROUPSET).FilterStart">GROUPSET.FilterStart</a>: Starts the filtering of the groups within the GROUPSET.</li>
</ul>
<p>Planned filter criteria within development are (so these are not yet available):</p>
<ul>
<li><a href="##(GROUPSET).FilterZones">GROUPSET.FilterZones</a>: Builds the GROUPSET with the groups within a <a href="Zone.html##(ZONE)">Zone#ZONE</a>.</li>
</ul>
<h1>GROUPSET iterators:</h1>
<p>Once the filters have been defined and the GROUPSET has been built, you can iterate the GROUPSET with the available iterator methods.
The iterator methods will walk the GROUPSET set, and call for each element within the set a function that you provide.
The following iterator methods are currently available within the GROUPSET:</p>
<ul>
<li><a href="##(GROUPSET).ForEachGroup">GROUPSET.ForEachGroup</a>: Calls a function for each alive group it finds within the GROUPSET.</li>
</ul>
<h2>Global(s)</h2>
<table class="function_list">
<tr>
<td class="name" nowrap="nowrap"><a href="#GROUPSET">GROUPSET</a></td>
<td class="summary">
</td>
</tr>
</table>
<h2><a id="#(GROUPSET)">Type <code>GROUPSET</code></a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).AddInDatabase">GROUPSET:AddInDatabase(Event)</a></td>
<td class="summary">
<p>Handles the Database to check on an event (birth) that the Object was added in the Database.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).ClassName">GROUPSET.ClassName</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).Filter">GROUPSET.Filter</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).FilterCategories">GROUPSET:FilterCategories(Categories)</a></td>
<td class="summary">
<p>Builds a set of groups out of categories.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).FilterCoalitions">GROUPSET:FilterCoalitions(Coalitions)</a></td>
<td class="summary">
<p>Builds a set of groups of coalitions.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).FilterCountries">GROUPSET:FilterCountries(Countries)</a></td>
<td class="summary">
<p>Builds a set of groups of defined countries.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).FilterMeta">GROUPSET.FilterMeta</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).FilterPrefixes">GROUPSET:FilterPrefixes(Prefixes)</a></td>
<td class="summary">
<p>Builds a set of groups of defined GROUP prefixes.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).FilterStart">GROUPSET:FilterStart()</a></td>
<td class="summary">
<p>Starts the filtering.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).FindGroup">GROUPSET:FindGroup(GroupName)</a></td>
<td class="summary">
<p>Finds a Group based on the Group Name.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).FindInDatabase">GROUPSET:FindInDatabase(Event)</a></td>
<td class="summary">
<p>Handles the Database to check on any event that Object exists in the Database.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).ForEachGroup">GROUPSET:ForEachGroup(IteratorFunction, ...)</a></td>
<td class="summary">
<p>Interate the GROUPSET and call an interator function for each <strong>alive</strong> GROUP, providing the GROUP and optional parameters.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).IsIncludeObject">GROUPSET:IsIncludeObject(MooseGroup)</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUPSET).New">GROUPSET:New()</a></td>
<td class="summary">
<p>Creates a new GROUPSET object, building a set of groups belonging to a coalitions, categories, countries, types or with defined prefix names.</p>
</td>
</tr>
</table>
<h2>Global(s)</h2>
<dl class="function">
<dt>
<em><a href="##(GROUPSET)">#GROUPSET</a></em>
<a id="GROUPSET" >
<strong>GROUPSET</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<h2><a id="#(GroupSet)" >Type <code>GroupSet</code></a></h2>
<h2><a id="#(GROUPSET)" >Type <code>GROUPSET</code></a></h2>
<p>GROUPSET class</p>
<h3>Field(s)</h3>
<dl class="function">
<dt>
<a id="#(GROUPSET).AddInDatabase" >
<strong>GROUPSET:AddInDatabase(Event)</strong>
</a>
</dt>
<dd>
<p>Handles the Database to check on an event (birth) that the Object was added in the Database.</p>
<p>This is required, because sometimes the _DATABASE birth event gets called later than the SET birth event!</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Event.html##(EVENTDATA)">Event#EVENTDATA</a> Event </em></code>: </p>
</li>
</ul>
<h3>Return values</h3>
<ol>
<li>
<p><em>#string:</em>
The name of the GROUP</p>
</li>
<li>
<p><em>#table:</em>
The GROUP</p>
</li>
</ol>
</dd>
</dl>
<dl class="function">
<dt>
<em>#string</em>
<a id="#(GROUPSET).ClassName" >
<strong>GROUPSET.ClassName</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">
<dt>
<em></em>
<a id="#(GROUPSET).Filter" >
<strong>GROUPSET.Filter</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).FilterCategories" >
<strong>GROUPSET:FilterCategories(Categories)</strong>
</a>
</dt>
<dd>
<p>Builds a set of groups out of categories.</p>
<p>Possible current categories are plane, helicopter, ground, ship.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Categories </em></code>:
Can take the following values: "plane", "helicopter", "ground", "ship".</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(GROUPSET)">#GROUPSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).FilterCoalitions" >
<strong>GROUPSET:FilterCoalitions(Coalitions)</strong>
</a>
</dt>
<dd>
<p>Builds a set of groups of coalitions.</p>
<p>Possible current coalitions are red, blue and neutral.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Coalitions </em></code>:
Can take the following values: "red", "blue", "neutral".</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(GROUPSET)">#GROUPSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).FilterCountries" >
<strong>GROUPSET:FilterCountries(Countries)</strong>
</a>
</dt>
<dd>
<p>Builds a set of groups of defined countries.</p>
<p>Possible current countries are those known within DCS world.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Countries </em></code>:
Can take those country strings known within DCS world.</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(GROUPSET)">#GROUPSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<em></em>
<a id="#(GROUPSET).FilterMeta" >
<strong>GROUPSET.FilterMeta</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).FilterPrefixes" >
<strong>GROUPSET:FilterPrefixes(Prefixes)</strong>
</a>
</dt>
<dd>
<p>Builds a set of groups of defined GROUP prefixes.</p>
<p>All the groups starting with the given prefixes will be included within the set.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Prefixes </em></code>:
The prefix of which the group name starts with.</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(GROUPSET)">#GROUPSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).FilterStart" >
<strong>GROUPSET:FilterStart()</strong>
</a>
</dt>
<dd>
<p>Starts the filtering.</p>
<h3>Return value</h3>
<p><em><a href="##(GROUPSET)">#GROUPSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).FindGroup" >
<strong>GROUPSET:FindGroup(GroupName)</strong>
</a>
</dt>
<dd>
<p>Finds a Group based on the Group Name.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string GroupName </em></code>: </p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="Group.html##(GROUP)">Group#GROUP</a>:</em>
The found Group.</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).FindInDatabase" >
<strong>GROUPSET:FindInDatabase(Event)</strong>
</a>
</dt>
<dd>
<p>Handles the Database to check on any event that Object exists in the Database.</p>
<p>This is required, because sometimes the _DATABASE event gets called later than the SET event or vise versa!</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Event.html##(EVENTDATA)">Event#EVENTDATA</a> Event </em></code>: </p>
</li>
</ul>
<h3>Return values</h3>
<ol>
<li>
<p><em>#string:</em>
The name of the GROUP</p>
</li>
<li>
<p><em>#table:</em>
The GROUP</p>
</li>
</ol>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).ForEachGroup" >
<strong>GROUPSET:ForEachGroup(IteratorFunction, ...)</strong>
</a>
</dt>
<dd>
<p>Interate the GROUPSET and call an interator function for each <strong>alive</strong> GROUP, providing the GROUP and optional parameters.</p>
<h3>Parameters</h3>
<ul>
<li>
<p><code><em>#function IteratorFunction </em></code>:
The function that will be called when there is an alive GROUP in the GROUPSET. The function needs to accept a GROUP parameter.</p>
</li>
<li>
<p><code><em> ... </em></code>: </p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(GROUPSET)">#GROUPSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).IsIncludeObject" >
<strong>GROUPSET:IsIncludeObject(MooseGroup)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Group.html##(GROUP)">Group#GROUP</a> MooseGroup </em></code>: </p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(GROUPSET)">#GROUPSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(GROUPSET).New" >
<strong>GROUPSET:New()</strong>
</a>
</dt>
<dd>
<p>Creates a new GROUPSET object, building a set of groups belonging to a coalitions, categories, countries, types or with defined prefix names.</p>
<h3>Return value</h3>
<p><em><a href="##(GROUPSET)">#GROUPSET</a>:</em></p>
<h3>Usage:</h3>
<pre class="example"><code>-- Define a new GROUPSET Object. This DBObject will contain a reference to all alive GROUPS.
DBObject = GROUPSET:New()</code></pre>
</dd>
</dl>
</div>
</div>
</body>
</html>

View File

@ -81,15 +81,18 @@ Messages are shown on the display panel for an amount of seconds, and will then
Messages can contain a category which is indicating the category of the message.</p>
<h2>1.1) MESSAGE construction methods</h2>
<p>Messages are created with MESSAGE:<a href="New.html">New</a>. Note that when the MESSAGE object is created, no message is sent yet.
<p>Messages are created with <a href="Message.html##(MESSAGE).New">Message#MESSAGE.New</a>. Note that when the MESSAGE object is created, no message is sent yet.
To send messages, you need to use the To functions.</p>
<h2>1.2) Send messages with MESSAGE To methods</h2>
<p>Messages are sent to:
* Clients with MESSAGE:<a href="ToClient.html">ToClient</a>().
* Coalitions with MESSAGE:<a href="ToCoalition.html">ToCoalition</a>().
* All Players with MESSAGE:<a href="ToAll.html">ToAll</a>().
</p>
<p>Messages are sent to:</p>
<ul>
<li>Clients with <a href="Message.html##(MESSAGE).ToClient">Message#MESSAGE.ToClient</a>.</li>
<li>Coalitions with <a href="Message.html##(MESSAGE).ToCoalition">Message#MESSAGE.ToCoalition</a>.</li>
<li>All Players with <a href="Message.html##(MESSAGE).ToAll">Message#MESSAGE.ToAll</a>.
</li>
</ul>
<h2>Global(s)</h2>
<table class="function_list">

View File

@ -1,685 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<link rel="stylesheet" href="stylesheet.css" type="text/css"/>
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div>
<div id="main">
<div id="navigation">
<h2>Modules</h2>
<ul><li>
<a href="index.html">index</a>
</li></ul>
<ul>
<li><a href="Airbase.html">Airbase</a></li>
<li><a href="Base.html">Base</a></li>
<li><a href="CARGO.html">CARGO</a></li>
<li><a href="CleanUp.html">CleanUp</a></li>
<li><a href="Client.html">Client</a></li>
<li><a href="DCSAirbase.html">DCSAirbase</a></li>
<li><a href="DCSCoalitionObject.html">DCSCoalitionObject</a></li>
<li><a href="DCSCommand.html">DCSCommand</a></li>
<li><a href="DCSController.html">DCSController</a></li>
<li><a href="DCSGroup.html">DCSGroup</a></li>
<li><a href="DCSObject.html">DCSObject</a></li>
<li><a href="DCSTask.html">DCSTask</a></li>
<li><a href="DCSTypes.html">DCSTypes</a></li>
<li><a href="DCSUnit.html">DCSUnit</a></li>
<li><a href="DCSWorld.html">DCSWorld</a></li>
<li><a href="DCStimer.html">DCStimer</a></li>
<li><a href="DEPLOYTASK.html">DEPLOYTASK</a></li>
<li><a href="DESTROYBASETASK.html">DESTROYBASETASK</a></li>
<li><a href="DESTROYGROUPSTASK.html">DESTROYGROUPSTASK</a></li>
<li><a href="DESTROYRADARSTASK.html">DESTROYRADARSTASK</a></li>
<li><a href="DESTROYUNITTYPESTASK.html">DESTROYUNITTYPESTASK</a></li>
<li><a href="Database.html">Database</a></li>
<li><a href="Escort.html">Escort</a></li>
<li><a href="Event.html">Event</a></li>
<li><a href="GOHOMETASK.html">GOHOMETASK</a></li>
<li><a href="Group.html">Group</a></li>
<li><a href="GroupSet.html">GroupSet</a></li>
<li><a href="MOVEMENT.html">MOVEMENT</a></li>
<li><a href="Menu.html">Menu</a></li>
<li><a href="Message.html">Message</a></li>
<li><a href="MissileTrainer.html">MissileTrainer</a></li>
<li><a href="Mission.html">Mission</a></li>
<li><a href="NOTASK.html">NOTASK</a></li>
<li><a href="PICKUPTASK.html">PICKUPTASK</a></li>
<li><a href="Point.html">Point</a></li>
<li><a href="ROUTETASK.html">ROUTETASK</a></li>
<li><a href="STAGE.html">STAGE</a></li>
<li><a href="Scheduler.html">Scheduler</a></li>
<li><a href="Scoring.html">Scoring</a></li>
<li><a href="Sead.html">Sead</a></li>
<li><a href="Set.html">Set</a></li>
<li><a href="Spawn.html">Spawn</a></li>
<li><a href="Static.html">Static</a></li>
<li><a href="StaticObject.html">StaticObject</a></li>
<li><a href="TASK.html">TASK</a></li>
<li><a href="Unit.html">Unit</a></li>
<li>UnitSet</li>
<li><a href="Zone.html">Zone</a></li>
<li><a href="env.html">env</a></li>
<li><a href="land.html">land</a></li>
<li><a href="routines.html">routines</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>UnitSet</code></h1>
<p>Create and manage a set of units.</p>
<h1><a href="##(UNITSET)">#UNITSET</a> class</h1>
<p>Mission designers can use the UNITSET class to build sets of units belonging to certain:</p>
<ul>
<li>Coalitions</li>
<li>Categories</li>
<li>Countries</li>
<li>Unit types</li>
<li>Starting with certain prefix strings.</li>
</ul>
<h1>UNITSET construction methods:</h1>
<p>Create a new UNITSET object with the <a href="##(UNITSET).New">UNITSET.New</a> method:</p>
<ul>
<li><a href="##(UNITSET).New">UNITSET.New</a>: Creates a new UNITSET object.</li>
</ul>
<h1>UNITSET filter criteria: </h1>
<p>You can set filter criteria to define the set of units within the UNITSET.
Filter criteria are defined by:</p>
<ul>
<li><a href="##(UNITSET).FilterCoalitions">UNITSET.FilterCoalitions</a>: Builds the UNITSET with the units belonging to the coalition(s).</li>
<li><a href="##(UNITSET).FilterCategories">UNITSET.FilterCategories</a>: Builds the UNITSET with the units belonging to the category(ies).</li>
<li><a href="##(UNITSET).FilterTypes">UNITSET.FilterTypes</a>: Builds the UNITSET with the units belonging to the unit type(s).</li>
<li><a href="##(UNITSET).FilterCountries">UNITSET.FilterCountries</a>: Builds the UNITSET with the units belonging to the country(ies).</li>
<li><a href="##(UNITSET).FilterPrefixes">UNITSET.FilterPrefixes</a>: Builds the UNITSET with the units starting with the same prefix string(s).</li>
</ul>
<p>Once the filter criteria have been set for the UNITSET, you can start filtering using:</p>
<ul>
<li><a href="##(UNITSET).FilterStart">UNITSET.FilterStart</a>: Starts the filtering of the units within the UNITSET.</li>
</ul>
<p>Planned filter criteria within development are (so these are not yet available):</p>
<ul>
<li><a href="##(UNITSET).FilterZones">UNITSET.FilterZones</a>: Builds the UNITSET with the units within a <a href="Zone.html##(ZONE)">Zone#ZONE</a>.</li>
</ul>
<h1>UNITSET iterators:</h1>
<p>Once the filters have been defined and the UNITSET has been built, you can iterate the UNITSET with the available iterator methods.
The iterator methods will walk the UNITSET set, and call for each element within the set a function that you provide.
The following iterator methods are currently available within the UNITSET:</p>
<ul>
<li><a href="##(UNITSET).ForEachUnit">UNITSET.ForEachUnit</a>: Calls a function for each alive unit it finds within the UNITSET.</li>
</ul>
<p>Planned iterators methods in development are (so these are not yet available):</p>
<ul>
<li><a href="##(UNITSET).ForEachUnitInGroup">UNITSET.ForEachUnitInGroup</a>: Calls a function for each group contained within the UNITSET.</li>
<li><a href="##(UNITSET).ForEachUnitInZone">UNITSET.ForEachUnitInZone</a>: Calls a function for each unit within a certain zone contained within the UNITSET.</li>
</ul>
<h2>Global(s)</h2>
<table class="function_list">
<tr>
<td class="name" nowrap="nowrap"><a href="#UNITSET">UNITSET</a></td>
<td class="summary">
</td>
</tr>
</table>
<h2><a id="#(UNITSET)">Type <code>UNITSET</code></a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).AddInDatabase">UNITSET:AddInDatabase(Event)</a></td>
<td class="summary">
<p>Handles the Database to check on an event (birth) that the Object was added in the Database.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).ClassName">UNITSET.ClassName</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).Filter">UNITSET.Filter</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FilterCategories">UNITSET:FilterCategories(Categories)</a></td>
<td class="summary">
<p>Builds a set of units out of categories.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FilterCoalitions">UNITSET:FilterCoalitions(Coalitions)</a></td>
<td class="summary">
<p>Builds a set of units of coalitions.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FilterCountries">UNITSET:FilterCountries(Countries)</a></td>
<td class="summary">
<p>Builds a set of units of defined countries.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FilterMeta">UNITSET.FilterMeta</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FilterPrefixes">UNITSET:FilterPrefixes(Prefixes)</a></td>
<td class="summary">
<p>Builds a set of units of defined unit prefixes.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FilterStart">UNITSET:FilterStart()</a></td>
<td class="summary">
<p>Starts the filtering.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FilterTypes">UNITSET:FilterTypes(Types)</a></td>
<td class="summary">
<p>Builds a set of units of defined unit types.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FindInDatabase">UNITSET:FindInDatabase(Event)</a></td>
<td class="summary">
<p>Handles the Database to check on any event that Object exists in the Database.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).FindUnit">UNITSET:FindUnit(UnitName)</a></td>
<td class="summary">
<p>Finds a Unit based on the Unit Name.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).ForEachUnit">UNITSET:ForEachUnit(IteratorFunction, ...)</a></td>
<td class="summary">
<p>Interate the UNITSET and call an interator function for each <strong>alive</strong> UNIT, providing the UNIT and optional parameters.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).IsIncludeObject">UNITSET:IsIncludeObject(MUnit)</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).New">UNITSET:New()</a></td>
<td class="summary">
<p>Creates a new UNITSET object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNITSET).Units">UNITSET.Units</a></td>
<td class="summary">
</td>
</tr>
</table>
<h2>Global(s)</h2>
<dl class="function">
<dt>
<em><a href="##(UNITSET)">#UNITSET</a></em>
<a id="UNITSET" >
<strong>UNITSET</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<h2><a id="#(UnitSet)" >Type <code>UnitSet</code></a></h2>
<h2><a id="#(UNITSET)" >Type <code>UNITSET</code></a></h2>
<p>UNITSET class</p>
<h3>Field(s)</h3>
<dl class="function">
<dt>
<a id="#(UNITSET).AddInDatabase" >
<strong>UNITSET:AddInDatabase(Event)</strong>
</a>
</dt>
<dd>
<p>Handles the Database to check on an event (birth) that the Object was added in the Database.</p>
<p>This is required, because sometimes the _DATABASE birth event gets called later than the SET birth event!</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Event.html##(EVENTDATA)">Event#EVENTDATA</a> Event </em></code>: </p>
</li>
</ul>
<h3>Return values</h3>
<ol>
<li>
<p><em>#string:</em>
The name of the UNIT</p>
</li>
<li>
<p><em>#table:</em>
The UNIT</p>
</li>
</ol>
</dd>
</dl>
<dl class="function">
<dt>
<em>#string</em>
<a id="#(UNITSET).ClassName" >
<strong>UNITSET.ClassName</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">
<dt>
<em></em>
<a id="#(UNITSET).Filter" >
<strong>UNITSET.Filter</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).FilterCategories" >
<strong>UNITSET:FilterCategories(Categories)</strong>
</a>
</dt>
<dd>
<p>Builds a set of units out of categories.</p>
<p>Possible current categories are plane, helicopter, ground, ship.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Categories </em></code>:
Can take the following values: "plane", "helicopter", "ground", "ship".</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).FilterCoalitions" >
<strong>UNITSET:FilterCoalitions(Coalitions)</strong>
</a>
</dt>
<dd>
<p>Builds a set of units of coalitions.</p>
<p>Possible current coalitions are red, blue and neutral.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Coalitions </em></code>:
Can take the following values: "red", "blue", "neutral".</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).FilterCountries" >
<strong>UNITSET:FilterCountries(Countries)</strong>
</a>
</dt>
<dd>
<p>Builds a set of units of defined countries.</p>
<p>Possible current countries are those known within DCS world.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Countries </em></code>:
Can take those country strings known within DCS world.</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<em></em>
<a id="#(UNITSET).FilterMeta" >
<strong>UNITSET.FilterMeta</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).FilterPrefixes" >
<strong>UNITSET:FilterPrefixes(Prefixes)</strong>
</a>
</dt>
<dd>
<p>Builds a set of units of defined unit prefixes.</p>
<p>All the units starting with the given prefixes will be included within the set.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Prefixes </em></code>:
The prefix of which the unit name starts with.</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).FilterStart" >
<strong>UNITSET:FilterStart()</strong>
</a>
</dt>
<dd>
<p>Starts the filtering.</p>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).FilterTypes" >
<strong>UNITSET:FilterTypes(Types)</strong>
</a>
</dt>
<dd>
<p>Builds a set of units of defined unit types.</p>
<p>Possible current types are those types known within DCS world.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string Types </em></code>:
Can take those type strings known within DCS world.</p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).FindInDatabase" >
<strong>UNITSET:FindInDatabase(Event)</strong>
</a>
</dt>
<dd>
<p>Handles the Database to check on any event that Object exists in the Database.</p>
<p>This is required, because sometimes the _DATABASE event gets called later than the SET event or vise versa!</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Event.html##(EVENTDATA)">Event#EVENTDATA</a> Event </em></code>: </p>
</li>
</ul>
<h3>Return values</h3>
<ol>
<li>
<p><em>#string:</em>
The name of the UNIT</p>
</li>
<li>
<p><em>#table:</em>
The UNIT</p>
</li>
</ol>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).FindUnit" >
<strong>UNITSET:FindUnit(UnitName)</strong>
</a>
</dt>
<dd>
<p>Finds a Unit based on the Unit Name.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em>#string UnitName </em></code>: </p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="Unit.html##(UNIT)">Unit#UNIT</a>:</em>
The found Unit.</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).ForEachUnit" >
<strong>UNITSET:ForEachUnit(IteratorFunction, ...)</strong>
</a>
</dt>
<dd>
<p>Interate the UNITSET and call an interator function for each <strong>alive</strong> UNIT, providing the UNIT and optional parameters.</p>
<h3>Parameters</h3>
<ul>
<li>
<p><code><em>#function IteratorFunction </em></code>:
The function that will be called when there is an alive UNIT in the UNITSET. The function needs to accept a UNIT parameter.</p>
</li>
<li>
<p><code><em> ... </em></code>: </p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).IsIncludeObject" >
<strong>UNITSET:IsIncludeObject(MUnit)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Unit.html##(UNIT)">Unit#UNIT</a> MUnit </em></code>: </p>
</li>
</ul>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNITSET).New" >
<strong>UNITSET:New()</strong>
</a>
</dt>
<dd>
<p>Creates a new UNITSET object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.</p>
<h3>Return value</h3>
<p><em><a href="##(UNITSET)">#UNITSET</a>:</em></p>
<h3>Usage:</h3>
<pre class="example"><code>-- Define a new UNITSET Object. This DBObject will contain a reference to all alive Units.
DBObject = UNITSET:New()</code></pre>
</dd>
</dl>
<dl class="function">
<dt>
<em></em>
<a id="#(UNITSET).Units" >
<strong>UNITSET.Units</strong>
</a>
</dt>
<dd>
</dd>
</dl>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff