diff --git a/Moose Development/Moose/AIBalancer.lua b/Moose Development/Moose/AIBalancer.lua new file mode 100644 index 000000000..6dadedd6b --- /dev/null +++ b/Moose Development/Moose/AIBalancer.lua @@ -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 + + + diff --git a/Moose Development/Moose/Base.lua b/Moose Development/Moose/Base.lua index 1d91baca7..85c4133ec 100644 --- a/Moose Development/Moose/Base.lua +++ b/Moose Development/Moose/Base.lua @@ -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 diff --git a/Moose Development/Moose/Database.lua b/Moose Development/Moose/Database.lua index 5cda371f0..ac0ca55f7 100644 --- a/Moose Development/Moose/Database.lua +++ b/Moose Development/Moose/Database.lua @@ -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 diff --git a/Moose Development/Moose/Message.lua b/Moose Development/Moose/Message.lua index 8c69d9e4b..b55a48c6f 100644 --- a/Moose Development/Moose/Message.lua +++ b/Moose Development/Moose/Message.lua @@ -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 diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua index 5221d8f73..f01a5b380 100644 --- a/Moose Development/Moose/Moose.lua +++ b/Moose Development/Moose/Moose.lua @@ -35,6 +35,7 @@ Include.File( "Movement" ) Include.File( "Sead" ) Include.File( "Escort" ) Include.File( "MissileTrainer" ) +Include.File( "AIBalancer" ) diff --git a/Moose Development/Moose/Set.lua b/Moose Development/Moose/Set.lua index be3cf1526..6ec5bec0e 100644 --- a/Moose Development/Moose/Set.lua +++ b/Moose Development/Moose/Set.lua @@ -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 + diff --git a/Moose Development/Moose/Unit.lua b/Moose Development/Moose/Unit.lua index 8d1a1c1fb..b01ed3c63 100644 --- a/Moose Development/Moose/Unit.lua +++ b/Moose Development/Moose/Unit.lua @@ -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 diff --git a/Moose Mission Setup/Moose Create Dynamic/Moose_Dynamic_Loader.lua b/Moose Mission Setup/Moose Create Dynamic/Moose_Dynamic_Loader.lua index aa7f1fd9d..8c3b6bdf7 100644 --- a/Moose Mission Setup/Moose Create Dynamic/Moose_Dynamic_Loader.lua +++ b/Moose Mission Setup/Moose Create Dynamic/Moose_Dynamic_Loader.lua @@ -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") \ No newline at end of file diff --git a/Moose Mission Setup/Moose Create Static/Moose_Static_Loader.lua b/Moose Mission Setup/Moose Create Static/Moose_Static_Loader.lua index 87ccd7151..ac3a5aab8 100644 --- a/Moose Mission Setup/Moose Create Static/Moose_Static_Loader.lua +++ b/Moose Mission Setup/Moose Create Static/Moose_Static_Loader.lua @@ -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") diff --git a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua index 52bfe1b8a..37a7a4c09 100644 --- a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua +++ b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua @@ -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 *** ' ) diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua index 52bfe1b8a..37a7a4c09 100644 --- a/Moose Mission Setup/Moose.lua +++ b/Moose Mission Setup/Moose.lua @@ -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 *** ' ) diff --git a/Moose Mission Setup/Moose_Create.bat b/Moose Mission Setup/Moose_Create.bat index c83d141d0..14fffeead 100644 --- a/Moose Mission Setup/Moose_Create.bat +++ b/Moose Mission Setup/Moose_Create.bat @@ -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 diff --git a/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.lua b/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.lua new file mode 100644 index 000000000..ef23d4354 --- /dev/null +++ b/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.lua @@ -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 ) diff --git a/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz b/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz new file mode 100644 index 000000000..ac1d06595 Binary files /dev/null and b/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz differ diff --git a/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz b/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz index 2ddd4a78b..a4ad7daf4 100644 Binary files a/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz and b/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz differ diff --git a/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz b/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz index e1d4bb895..b29e52ad5 100644 Binary files a/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz and b/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz differ diff --git a/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz b/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz index 355f1f252..cf6959463 100644 Binary files a/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz and b/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz differ diff --git a/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz b/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz index 69c931104..8c8eb9cdd 100644 Binary files a/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz and b/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz differ diff --git a/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz b/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz index 07d8b34a1..057f9fc6b 100644 Binary files a/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz and b/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz differ diff --git a/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz b/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz index 0dfc8dcb6..697ff6505 100644 Binary files a/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz and b/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz b/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz index d7288cbcd..d85f80c1b 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz and b/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz b/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz index 1855e720b..bc0af828c 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz and b/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz differ diff --git a/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz b/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz index 9930ee92b..fe2291f9f 100644 Binary files a/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz and b/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz differ diff --git a/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz b/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz index b4fd92676..1040d3075 100644 Binary files a/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz and b/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz index 82222cecf..bb7bb57a9 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz and b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz index 83e754f6a..812d4ebf2 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz and b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz index 7fdebb91a..0e9de4089 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz and b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz index 69196e86d..7c78b1d6c 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz and b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz differ diff --git a/Moose Training/Documentation/GroupSet.html b/Moose Training/Documentation/GroupSet.html deleted file mode 100644 index e0ae7f72c..000000000 --- a/Moose Training/Documentation/GroupSet.html +++ /dev/null @@ -1,620 +0,0 @@ - - - - - - -
-
- -
-
-
-
- -
-

Module GroupSet

- -

Create and manage a set of groups.

- - - -

#GROUPSET class

-

Mission designers can use the GROUPSET class to build sets of groups belonging to certain:

- -
    -
  • Coalitions
  • -
  • Categories
  • -
  • Countries
  • -
  • Starting with certain prefix strings.
  • -
- -

GROUPSET construction methods:

-

Create a new GROUPSET object with the GROUPSET.New method:

- - - - -

GROUPSET filter criteria:

-

You can set filter criteria to define the set of groups within the GROUPSET. -Filter criteria are defined by:

- - - -

Once the filter criteria have been set for the GROUPSET, you can start filtering using:

- - - -

Planned filter criteria within development are (so these are not yet available):

- - - - -

GROUPSET iterators:

-

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:

- - - - -

Global(s)

- - - - - -
GROUPSET - -
-

Type GROUPSET

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GROUPSET:AddInDatabase(Event) -

Handles the Database to check on an event (birth) that the Object was added in the Database.

-
GROUPSET.ClassName - -
GROUPSET.Filter - -
GROUPSET:FilterCategories(Categories) -

Builds a set of groups out of categories.

-
GROUPSET:FilterCoalitions(Coalitions) -

Builds a set of groups of coalitions.

-
GROUPSET:FilterCountries(Countries) -

Builds a set of groups of defined countries.

-
GROUPSET.FilterMeta - -
GROUPSET:FilterPrefixes(Prefixes) -

Builds a set of groups of defined GROUP prefixes.

-
GROUPSET:FilterStart() -

Starts the filtering.

-
GROUPSET:FindGroup(GroupName) -

Finds a Group based on the Group Name.

-
GROUPSET:FindInDatabase(Event) -

Handles the Database to check on any event that Object exists in the Database.

-
GROUPSET:ForEachGroup(IteratorFunction, ...) -

Interate the GROUPSET and call an interator function for each alive GROUP, providing the GROUP and optional parameters.

-
GROUPSET:IsIncludeObject(MooseGroup) - -
GROUPSET:New() -

Creates a new GROUPSET object, building a set of groups belonging to a coalitions, categories, countries, types or with defined prefix names.

-
- -

Global(s)

-
-
- - #GROUPSET - -GROUPSET - -
-
- - - -
-
-

Type GroupSet

- -

Type GROUPSET

- -

GROUPSET class

- -

Field(s)

-
-
- - -GROUPSET:AddInDatabase(Event) - -
-
- -

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 birth event!

- -

Parameter

- -

Return values

-
    -
  1. - -

    #string: -The name of the GROUP

    - -
  2. -
  3. - -

    #table: -The GROUP

    - -
  4. -
-
-
-
-
- - #string - -GROUPSET.ClassName - -
-
- - - -
-
-
-
- - - -GROUPSET.Filter - -
-
- - - -
-
-
-
- - -GROUPSET:FilterCategories(Categories) - -
-
- -

Builds a set of groups out of categories.

- - -

Possible current categories are plane, helicopter, ground, ship.

- -

Parameter

-
    -
  • - -

    #string Categories : -Can take the following values: "plane", "helicopter", "ground", "ship".

    - -
  • -
-

Return value

- -

#GROUPSET: -self

- -
-
-
-
- - -GROUPSET:FilterCoalitions(Coalitions) - -
-
- -

Builds a set of groups of coalitions.

- - -

Possible current coalitions are red, blue and neutral.

- -

Parameter

-
    -
  • - -

    #string Coalitions : -Can take the following values: "red", "blue", "neutral".

    - -
  • -
-

Return value

- -

#GROUPSET: -self

- -
-
-
-
- - -GROUPSET:FilterCountries(Countries) - -
-
- -

Builds a set of groups of defined countries.

- - -

Possible current countries are those known within DCS world.

- -

Parameter

-
    -
  • - -

    #string Countries : -Can take those country strings known within DCS world.

    - -
  • -
-

Return value

- -

#GROUPSET: -self

- -
-
-
-
- - - -GROUPSET.FilterMeta - -
-
- - - -
-
-
-
- - -GROUPSET:FilterPrefixes(Prefixes) - -
-
- -

Builds a set of groups of defined GROUP prefixes.

- - -

All the groups starting with the given prefixes will be included within the set.

- -

Parameter

-
    -
  • - -

    #string Prefixes : -The prefix of which the group name starts with.

    - -
  • -
-

Return value

- -

#GROUPSET: -self

- -
-
-
-
- - -GROUPSET:FilterStart() - -
-
- -

Starts the filtering.

- -

Return value

- -

#GROUPSET: -self

- -
-
-
-
- - -GROUPSET:FindGroup(GroupName) - -
-
- -

Finds a Group based on the Group Name.

- -

Parameter

-
    -
  • - -

    #string GroupName :

    - -
  • -
-

Return value

- -

Group#GROUP: -The found Group.

- -
-
-
-
- - -GROUPSET:FindInDatabase(Event) - -
-
- -

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 event or vise versa!

- -

Parameter

- -

Return values

-
    -
  1. - -

    #string: -The name of the GROUP

    - -
  2. -
  3. - -

    #table: -The GROUP

    - -
  4. -
-
-
-
-
- - -GROUPSET:ForEachGroup(IteratorFunction, ...) - -
-
- -

Interate the GROUPSET and call an interator function for each alive GROUP, providing the GROUP and optional parameters.

- -

Parameters

-
    -
  • - -

    #function IteratorFunction : -The function that will be called when there is an alive GROUP in the GROUPSET. The function needs to accept a GROUP parameter.

    - -
  • -
  • - -

    ... :

    - -
  • -
-

Return value

- -

#GROUPSET: -self

- -
-
-
-
- - -GROUPSET:IsIncludeObject(MooseGroup) - -
-
- - - -

Parameter

- -

Return value

- -

#GROUPSET: -self

- -
-
-
-
- - -GROUPSET:New() - -
-
- -

Creates a new GROUPSET object, building a set of groups belonging to a coalitions, categories, countries, types or with defined prefix names.

- -

Return value

- -

#GROUPSET:

- - -

Usage:

-
-- Define a new GROUPSET Object. This DBObject will contain a reference to all alive GROUPS.
-DBObject = GROUPSET:New()
- -
-
- -
- -
- - diff --git a/Moose Training/Documentation/Message.html b/Moose Training/Documentation/Message.html index a3d1fd6be..b19eb8463 100644 --- a/Moose Training/Documentation/Message.html +++ b/Moose Training/Documentation/Message.html @@ -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.

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(). -

+

Messages are sent to:

+ +

Global(s)

diff --git a/Moose Training/Documentation/UnitSet.html b/Moose Training/Documentation/UnitSet.html deleted file mode 100644 index 4f6d4cbad..000000000 --- a/Moose Training/Documentation/UnitSet.html +++ /dev/null @@ -1,685 +0,0 @@ - - - - - - -
-
- -
-
-
-
- -
-

Module UnitSet

- -

Create and manage a set of units.

- - - -

#UNITSET class

-

Mission designers can use the UNITSET class to build sets of units belonging to certain:

- -
    -
  • Coalitions
  • -
  • Categories
  • -
  • Countries
  • -
  • Unit types
  • -
  • Starting with certain prefix strings.
  • -
- -

UNITSET construction methods:

-

Create a new UNITSET object with the UNITSET.New method:

- - - - -

UNITSET filter criteria:

-

You can set filter criteria to define the set of units within the UNITSET. -Filter criteria are defined by:

- - - -

Once the filter criteria have been set for the UNITSET, you can start filtering using:

- - - -

Planned filter criteria within development are (so these are not yet available):

- - - - -

UNITSET iterators:

-

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:

- - - -

Planned iterators methods in development are (so these are not yet available):

- - - - -

Global(s)

-
- - - - -
UNITSET - -
-

Type UNITSET

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UNITSET:AddInDatabase(Event) -

Handles the Database to check on an event (birth) that the Object was added in the Database.

-
UNITSET.ClassName - -
UNITSET.Filter - -
UNITSET:FilterCategories(Categories) -

Builds a set of units out of categories.

-
UNITSET:FilterCoalitions(Coalitions) -

Builds a set of units of coalitions.

-
UNITSET:FilterCountries(Countries) -

Builds a set of units of defined countries.

-
UNITSET.FilterMeta - -
UNITSET:FilterPrefixes(Prefixes) -

Builds a set of units of defined unit prefixes.

-
UNITSET:FilterStart() -

Starts the filtering.

-
UNITSET:FilterTypes(Types) -

Builds a set of units of defined unit types.

-
UNITSET:FindInDatabase(Event) -

Handles the Database to check on any event that Object exists in the Database.

-
UNITSET:FindUnit(UnitName) -

Finds a Unit based on the Unit Name.

-
UNITSET:ForEachUnit(IteratorFunction, ...) -

Interate the UNITSET and call an interator function for each alive UNIT, providing the UNIT and optional parameters.

-
UNITSET:IsIncludeObject(MUnit) - -
UNITSET:New() -

Creates a new UNITSET object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.

-
UNITSET.Units - -
- -

Global(s)

-
-
- - #UNITSET - -UNITSET - -
-
- - - -
-
-

Type UnitSet

- -

Type UNITSET

- -

UNITSET class

- -

Field(s)

-
-
- - -UNITSET:AddInDatabase(Event) - -
-
- -

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 birth event!

- -

Parameter

- -

Return values

-
    -
  1. - -

    #string: -The name of the UNIT

    - -
  2. -
  3. - -

    #table: -The UNIT

    - -
  4. -
-
-
-
-
- - #string - -UNITSET.ClassName - -
-
- - - -
-
-
-
- - - -UNITSET.Filter - -
-
- - - -
-
-
-
- - -UNITSET:FilterCategories(Categories) - -
-
- -

Builds a set of units out of categories.

- - -

Possible current categories are plane, helicopter, ground, ship.

- -

Parameter

-
    -
  • - -

    #string Categories : -Can take the following values: "plane", "helicopter", "ground", "ship".

    - -
  • -
-

Return value

- -

#UNITSET: -self

- -
-
-
-
- - -UNITSET:FilterCoalitions(Coalitions) - -
-
- -

Builds a set of units of coalitions.

- - -

Possible current coalitions are red, blue and neutral.

- -

Parameter

-
    -
  • - -

    #string Coalitions : -Can take the following values: "red", "blue", "neutral".

    - -
  • -
-

Return value

- -

#UNITSET: -self

- -
-
-
-
- - -UNITSET:FilterCountries(Countries) - -
-
- -

Builds a set of units of defined countries.

- - -

Possible current countries are those known within DCS world.

- -

Parameter

-
    -
  • - -

    #string Countries : -Can take those country strings known within DCS world.

    - -
  • -
-

Return value

- -

#UNITSET: -self

- -
-
-
-
- - - -UNITSET.FilterMeta - -
-
- - - -
-
-
-
- - -UNITSET:FilterPrefixes(Prefixes) - -
-
- -

Builds a set of units of defined unit prefixes.

- - -

All the units starting with the given prefixes will be included within the set.

- -

Parameter

-
    -
  • - -

    #string Prefixes : -The prefix of which the unit name starts with.

    - -
  • -
-

Return value

- -

#UNITSET: -self

- -
-
-
-
- - -UNITSET:FilterStart() - -
-
- -

Starts the filtering.

- -

Return value

- -

#UNITSET: -self

- -
-
-
-
- - -UNITSET:FilterTypes(Types) - -
-
- -

Builds a set of units of defined unit types.

- - -

Possible current types are those types known within DCS world.

- -

Parameter

-
    -
  • - -

    #string Types : -Can take those type strings known within DCS world.

    - -
  • -
-

Return value

- -

#UNITSET: -self

- -
-
-
-
- - -UNITSET:FindInDatabase(Event) - -
-
- -

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 event or vise versa!

- -

Parameter

- -

Return values

-
    -
  1. - -

    #string: -The name of the UNIT

    - -
  2. -
  3. - -

    #table: -The UNIT

    - -
  4. -
-
-
-
-
- - -UNITSET:FindUnit(UnitName) - -
-
- -

Finds a Unit based on the Unit Name.

- -

Parameter

-
    -
  • - -

    #string UnitName :

    - -
  • -
-

Return value

- -

Unit#UNIT: -The found Unit.

- -
-
-
-
- - -UNITSET:ForEachUnit(IteratorFunction, ...) - -
-
- -

Interate the UNITSET and call an interator function for each alive UNIT, providing the UNIT and optional parameters.

- -

Parameters

-
    -
  • - -

    #function IteratorFunction : -The function that will be called when there is an alive UNIT in the UNITSET. The function needs to accept a UNIT parameter.

    - -
  • -
  • - -

    ... :

    - -
  • -
-

Return value

- -

#UNITSET: -self

- -
-
-
-
- - -UNITSET:IsIncludeObject(MUnit) - -
-
- - - -

Parameter

- -

Return value

- -

#UNITSET: -self

- -
-
-
-
- - -UNITSET:New() - -
-
- -

Creates a new UNITSET object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.

- -

Return value

- -

#UNITSET:

- - -

Usage:

-
-- Define a new UNITSET Object. This DBObject will contain a reference to all alive Units.
-DBObject = UNITSET:New()
- -
-
-
-
- - - -UNITSET.Units - -
-
- - - -
-
- -
- - - - diff --git a/Moose Training/Documentation/stylesheet.css b/Moose Training/Documentation/stylesheet.css index 1b82635b5..3477e7fe8 100644 --- a/Moose Training/Documentation/stylesheet.css +++ b/Moose Training/Documentation/stylesheet.css @@ -1,131 +1,884 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +@import url('https://fonts.googleapis.com/css?family=Architects+Daughter'); + html { - color: #000; - background: #FFF; + font-family: sans-serif; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -ms-text-size-adjust: 100%; /* 2 */ } -body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td { - margin: 0; - padding: 0; -} -table { - border-collapse: collapse; - border-spacing: 0; -} -fieldset,img { - border: 0; -} -address,caption,cite,code,dfn,em,strong,th,var,optgroup { - font-style: inherit; - font-weight: inherit; -} -del,ins { - text-decoration: none; -} -li { - list-style: bullet; - margin-left: 20px; -} -caption,th { - text-align: left; -} -h1,h2,h3,h4,h5,h6 { - font-size: 100%; - font-weight: bold; -} -q:before,q:after { - content: ''; -} -abbr,acronym { - border: 0; - font-variant: normal; -} -sup { - vertical-align: baseline; -} -sub { - vertical-align: baseline; -} -legend { - color: #000; -} -input,button,textarea,select,optgroup,option { - font-family: inherit; - font-size: inherit; - font-style: inherit; - font-weight: inherit; -} -input,button,textarea,select {*font-size:100%; -} -/* END RESET */ + +/** + * Remove default margin. + */ body { - margin-left: 1em; - margin-right: 1em; - font-family: arial, helvetica, geneva, sans-serif; - background-color: #ffffff; margin: 0px; + margin: 0; } -code, tt { font-family: monospace; } +/* HTML5 display definitions + ========================================================================== */ -body, p, td, th { font-size: .95em; line-height: 1.2em;} +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ -p, ul { margin: 10px 0 0 10px;} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} -strong { font-weight: bold;} +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ -em { font-style: italic;} +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ h1 { - font-size: 1.5em; - margin: 25px 0 20px 0; + margin: 0.67em 0; + font-size: 2em; } -h2, h3, h4 { margin: 15px 0 10px 0; } -h2 { font-size: 1.25em; } -h3 { font-size: 1.15em; } -h4 { font-size: 1.06em; } -a:link { font-weight: bold; color: #004080; text-decoration: none; } -a:visited { font-weight: bold; color: #006699; text-decoration: none; } -a:link:hover { text-decoration: underline; } +/** + * Address styling not present in IE 8/9. + */ + +mark { + color: #000; + background: #ff0; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ hr { - color:#cccccc; - background: #00007f; - height: 1px; + height: 0; + -moz-box-sizing: content-box; + box-sizing: content-box; } -blockquote { margin-left: 3em; } +/** + * Contain overflow in all browsers. + */ -ul { list-style-type: disc; } - -p.name { - font-family: "Andale Mono", monospace; - padding-top: 1em; +pre { + overflow: auto; } -p:first-child { - margin-top: 0px; +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } -pre.example { - background-color: rgb(245, 245, 245); - border: 1px solid silver; - padding: 10px; - margin: 10px 0 10px 0; - font-family: "Andale Mono", monospace; - font-size: .85em; +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + margin: 0; /* 3 */ + font: inherit; /* 2 */ + color: inherit; /* 1 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-box-sizing: content-box; /* 2 */ + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; /* 1 */ +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + padding: 0.35em 0.625em 0.75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + padding: 0; /* 2 */ + border: 0; /* 1 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-spacing: 0; + border-collapse: collapse; +} + +td, +th { + padding: 0; +} + +/* LAYOUT STYLES */ +body { + font-family: 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 15px; + font-weight: 400; + line-height: 1.5; + color: #666; + background: #fafafa url(../../images/body-bg.jpg) 0 0 repeat; + margin-left: 1em; + margin-right: 1em; + margin: 0px; +} + +p { + margin-top: 0; +} + + +a { + color: #2879d0; +} +a:hover { + color: #2268b2; +} + +header { + padding-top: 40px; + padding-bottom: 40px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + background: #2e7bcf url(../images/header-bg.jpg) 0 0 repeat-x; + border-bottom: solid 1px #275da1; +} + +h1 { + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 32px; + font-weight: normal; + line-height: 1.5; +} + +h2 { + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 26px; + font-weight: normal; + line-height: 1.3; +} + +h3 { + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 22px; + font-weight: normal; + line-height: 1.1; +} + +.inner { + position: relative; + width: 940px; + margin: 0 auto; +} + +#content-wrapper { + padding-top: 30px; + border-top: solid 1px #fff; +} + +#main-content { + float: left; + width: 690px; +} + +#main-content img { + max-width: 100%; +} + +aside#sidebar { + float: right; + width: 200px; + min-height: 504px; + padding-left: 20px; + font-size: 12px; + line-height: 1.3; + background: transparent url(../../images/sidebar-bg.jpg) 0 0 no-repeat; +} + +aside#sidebar p.repo-owner, +aside#sidebar p.repo-owner a { + font-weight: bold; +} + +#downloads { + margin-bottom: 40px; +} + +a.button { + width: 134px; + height: 58px; + padding-top: 22px; + padding-left: 68px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 23px; + line-height: 1.2; + color: #fff; +} +a.button small { + display: block; + font-size: 11px; +} +header a.button { + position: absolute; + top: 0; + right: 0; + background: transparent url(../images/github-button.png) 0 0 no-repeat; +} +aside a.button { + display: block; + width: 138px; + padding-left: 64px; + margin-bottom: 20px; + font-size: 21px; + background: transparent url(../images/download-button.png) 0 0 no-repeat; +} + +code, pre { + margin-bottom: 30px; + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; + font-size: 13px; + color: #222; +} + +code { + padding: 0 3px; + background-color: #f2f8fc; + border: solid 1px #dbe7f3; } pre { - background-color: rgb(245, 245, 245); - border: 1px solid silver; - padding: 10px; - margin: 10px 0 10px 0; - font-family: "Andale Mono", monospace; + padding: 20px; + overflow: auto; + text-shadow: none; + background: #fff; + border: solid 1px #f2f2f2; +} +pre code { + padding: 0; + color: #2879d0; + background-color: #fff; + border: none; +} + +ul, ol, dl { + margin-bottom: 20px; } -table.index { border: 1px #00007f; } -table.index td { text-align: left; vertical-align: top; } +/* COMMON STYLES */ + +hr { + height: 0; + margin-top: 1em; + margin-bottom: 1em; + border: 0; + border-top: solid 1px #ddd; +} + +table { + width: 100%; + border: 1px solid #ebebeb; +} + +th { + font-weight: 500; +} + +td { + font-weight: 300; + text-align: center; + border: 1px solid #ebebeb; +} + +form { + padding: 20px; + background: #f2f2f2; + +} + + +/* GENERAL ELEMENT TYPE STYLES */ + +#main-content h1 { + margin-top: 0; + margin-bottom: 0; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 2.8em; + font-weight: normal; + color: #474747; + text-indent: 6px; + letter-spacing: -1px; +} + +#main-content h1:before { + padding-right: 0.3em; + margin-left: -0.9em; + color: #9ddcff; + content: "/"; +} + +#main-content h2 { + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 22px; + font-weight: bold; + color: #474747; + text-indent: 4px; +} +#main-content h2:before { + padding-right: 0.3em; + margin-left: -1.5em; + content: "//"; + color: #9ddcff; +} + +#main-content h3 { + margin-top: 24px; + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 18px; + font-weight: bold; + color: #474747; + text-indent: 3px; +} + +#main-content h3:before { + padding-right: 0.3em; + margin-left: -2em; + content: "///"; + color: #9ddcff; +} + +#main-content h4 { + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 15px; + font-weight: bold; + color: #474747; + text-indent: 3px; +} + +h4:before { + padding-right: 0.3em; + margin-left: -2.8em; + content: "////"; + color: #9ddcff; +} + +#main-content h5 { + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 14px; + color: #474747; + text-indent: 3px; +} +h5:before { + padding-right: 0.3em; + margin-left: -3.2em; + content: "/////"; + color: #9ddcff; +} + +#main-content h6 { + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: .8em; + color: #474747; + text-indent: 3px; +} +h6:before { + padding-right: 0.3em; + margin-left: -3.7em; + content: "//////"; + color: #9ddcff; +} + +p { + margin-bottom: 20px; +} + +a { + text-decoration: none; +} + +p a { + font-weight: 400; +} + +blockquote { + padding: 0 0 0 30px; + margin-bottom: 20px; + font-size: 1.6em; + border-left: 10px solid #e9e9e9; +} + +ul { + list-style-position: inside; + list-style: disc; + padding-left: 20px; +} + +ol { + list-style-position: inside; + list-style: decimal; + padding-left: 3px; +} + +footer { + padding-top: 20px; + padding-bottom: 30px; + margin-top: 40px; + font-size: 13px; + color: #aaa; + background: transparent url('../../images/hr.png') 0 0 no-repeat; +} + +footer a { + color: #666; +} +footer a:hover { + color: #444; +} + +/* MISC */ +.clearfix:after { + display: block; + height: 0; + clear: both; + visibility: hidden; + content: '.'; +} + +.clearfix {display: inline-block;} +* html .clearfix {height: 1%;} +.clearfix {display: block;} + +/* #Media Queries +================================================== */ + +/* Smaller than standard 960 (devices and browsers) */ +@media only screen and (max-width: 959px) { } + +/* Tablet Portrait size to standard 960 (devices and browsers) */ +@media only screen and (min-width: 768px) and (max-width: 959px) { + .inner { + width: 740px; + } + header h1, header h2 { + width: 340px; + } + header h1 { + font-size: 60px; + } + header h2 { + font-size: 30px; + } + #main-content { + width: 490px; + } + #main-content h1:before, + #main-content h2:before, + #main-content h3:before, + #main-content h4:before, + #main-content h5:before, + #main-content h6:before { + padding-right: 0; + margin-left: 0; + content: none; + } +} + +/* All Mobile Sizes (devices and browser) */ +@media only screen and (max-width: 767px) { + .inner { + width: 93%; + } + header { + padding: 20px 0; + } + header .inner { + position: relative; + } + header h1, header h2 { + width: 100%; + } + header h1 { + font-size: 48px; + } + header h2 { + font-size: 24px; + } + header a.button { + position: relative; + display: inline-block; + width: auto; + height: auto; + padding: 5px 10px; + margin-top: 15px; + font-size: 13px; + line-height: 1; + color: #2879d0; + text-align: center; + background-color: #9ddcff; + background-image: none; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + header a.button small { + display: inline; + font-size: 13px; + } + #main-content, + aside#sidebar { + float: none; + width: 100% ! important; + } + aside#sidebar { + min-height: 0; + padding: 20px 0; + margin-top: 20px; + background-image: none; + border-top: solid 1px #ddd; + } + aside#sidebar a.button { + display: none; + } + #main-content h1:before, + #main-content h2:before, + #main-content h3:before, + #main-content h4:before, + #main-content h5:before, + #main-content h6:before { + padding-right: 0; + margin-left: 0; + content: none; + } +} + +/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */ +@media only screen and (min-width: 480px) and (max-width: 767px) { } + +/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */ +@media only screen and (max-width: 479px) { } + #container { margin-left: 1em; @@ -144,7 +897,8 @@ table.index td { text-align: left; vertical-align: top; } } #main { - background-color: #f0f0f0; + color: #666; + background: #fafafa url(../../images/body-bg.jpg) 0 0 repeat; border-left: 2px solid #cccccc; } @@ -152,20 +906,28 @@ table.index td { text-align: left; vertical-align: top; } float: left; width: 18em; vertical-align: top; - background-color: #f0f0f0; overflow: scroll; position: fixed; height:100%; + background: #2e7bcf url(../../images/header-bg.jpg) 0 0 repeat-x; + color: #fff; } #navigation h2 { - background-color:#e7e7e7; - font-size:1.1em; - color:#000000; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + background: #2e7bcf url(../images/header-bg.jpg) 0 0 repeat-x; + border-bottom: solid 1px #275da1; + width: 540px; + margin-top: 0; + margin-bottom: 0.2em; + font-size: 36px; + font-weight: normal; + line-height: 1; + color: #fff; + letter-spacing: -1px; text-align: left; padding:0.2em; border-top:1px solid #dddddd; - border-bottom:1px solid #dddddd; } #navigation ul @@ -173,16 +935,24 @@ table.index td { text-align: left; vertical-align: top; } font-size:1em; list-style-type: none; margin: 1px 1px 10px 1px; + color: #fff; } #navigation li { text-indent: -1em; display: block; margin: 3px 0px 0px 22px; + color: #fff; } +#navigation ul li a { + color: #fff; +} + + #navigation li li a { margin: 0px 3px 0px -1em; + color: #fff; } #content { @@ -193,6 +963,27 @@ table.index td { text-align: left; vertical-align: top; } background-color: #ffffff; } + +#content h2 a { + color: #000; + border-bottom: 1px solid #000; +} + +#content h2 a code { +font-size: 22px; +font-weight: 400; +background-color: transparent; +color: #2879d0; +border: none; +} + +#content h1 code { +font-size: 26px; +font-weight: 400; +background-color: transparent; +border: none; +} + #about { clear: both; padding: 5px; @@ -200,70 +991,45 @@ table.index td { text-align: left; vertical-align: top; } background-color: #ffffff; } -@media print { - body { - font: 12pt "Times New Roman", "TimeNR", Times, serif; - } - a { font-weight: bold; color: #004080; text-decoration: underline; } - - #main { - background-color: #ffffff; - border-left: 0px; - } - - #container { - margin-left: 2%; - margin-right: 2%; - background-color: #ffffff; - } - - #content { - padding: 1em; - background-color: #ffffff; - } - - #navigation { - display: none; - } - pre.example { - font-family: "Andale Mono", monospace; - font-size: 10pt; - page-break-inside: avoid; - } -} - -table.module_list { - border-width: 1px; - border-style: solid; - border-color: #cccccc; - border-collapse: collapse; -} -table.module_list td { - border-width: 1px; - padding: 3px; - border-style: solid; - border-color: #cccccc; -} -table.module_list td.name { background-color: #f0f0f0; } -table.module_list td.summary { width: 100%; } - - table.function_list { border-width: 1px; border-style: solid; border-color: #cccccc; border-collapse: collapse; } + table.function_list td { border-width: 1px; padding: 3px; border-style: solid; border-color: #cccccc; + word-wrap:break-word; } -table.function_list td.name { background-color: #f0f0f0; } -table.function_list td.summary { width: 100%; } -dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;} -dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;} -dl.table h3, dl.function h3 {font-size: .95em;} +table.function_list td.name { font-weight: 400; width:50%; white-space: normal; text-align:left;} +table.function_list td.summary { width: 50%; } + +dl.table dt, dl.function { + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} + +dl.table dt, dl.function dt { + border-top: 1px solid #000; + padding-top: 0.5em; + padding-bottom: 0.5em; + border-bottom: 1px solid #ccc; +} + +dl.table dd, dl.function dd { + padding-bottom: 0.5em; + margin: 20px 0 0 20px; +} + +dl.table dd, dl.function dd p { + font-weight : normal; +} + +dl.table h3, dl.function h3 {font-size: 1.5em;} diff --git a/Moose Training/Presentations/DCS World - MOOSE - Development - Part 1 - Tools and Installation.pptx b/Moose Training/Presentations/DCS World - MOOSE - Development - Part 1 - Tools and Installation.pptx index a8abf34b8..b40406f48 100644 Binary files a/Moose Training/Presentations/DCS World - MOOSE - Development - Part 1 - Tools and Installation.pptx and b/Moose Training/Presentations/DCS World - MOOSE - Development - Part 1 - Tools and Installation.pptx differ diff --git a/Moose Training/Stylesheet/stylesheet.css b/Moose Training/Stylesheet/stylesheet.css new file mode 100644 index 000000000..3477e7fe8 --- /dev/null +++ b/Moose Training/Stylesheet/stylesheet.css @@ -0,0 +1,1035 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +@import url('https://fonts.googleapis.com/css?family=Architects+Daughter'); + +html { + font-family: sans-serif; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -ms-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + margin: 0.67em 0; + font-size: 2em; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + color: #000; + background: #ff0; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + height: 0; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + margin: 0; /* 3 */ + font: inherit; /* 2 */ + color: inherit; /* 1 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-box-sizing: content-box; /* 2 */ + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; /* 1 */ +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + padding: 0.35em 0.625em 0.75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + padding: 0; /* 2 */ + border: 0; /* 1 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-spacing: 0; + border-collapse: collapse; +} + +td, +th { + padding: 0; +} + +/* LAYOUT STYLES */ +body { + font-family: 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 15px; + font-weight: 400; + line-height: 1.5; + color: #666; + background: #fafafa url(../../images/body-bg.jpg) 0 0 repeat; + margin-left: 1em; + margin-right: 1em; + margin: 0px; +} + +p { + margin-top: 0; +} + + +a { + color: #2879d0; +} +a:hover { + color: #2268b2; +} + +header { + padding-top: 40px; + padding-bottom: 40px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + background: #2e7bcf url(../images/header-bg.jpg) 0 0 repeat-x; + border-bottom: solid 1px #275da1; +} + +h1 { + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 32px; + font-weight: normal; + line-height: 1.5; +} + +h2 { + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 26px; + font-weight: normal; + line-height: 1.3; +} + +h3 { + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 22px; + font-weight: normal; + line-height: 1.1; +} + +.inner { + position: relative; + width: 940px; + margin: 0 auto; +} + +#content-wrapper { + padding-top: 30px; + border-top: solid 1px #fff; +} + +#main-content { + float: left; + width: 690px; +} + +#main-content img { + max-width: 100%; +} + +aside#sidebar { + float: right; + width: 200px; + min-height: 504px; + padding-left: 20px; + font-size: 12px; + line-height: 1.3; + background: transparent url(../../images/sidebar-bg.jpg) 0 0 no-repeat; +} + +aside#sidebar p.repo-owner, +aside#sidebar p.repo-owner a { + font-weight: bold; +} + +#downloads { + margin-bottom: 40px; +} + +a.button { + width: 134px; + height: 58px; + padding-top: 22px; + padding-left: 68px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 23px; + line-height: 1.2; + color: #fff; +} +a.button small { + display: block; + font-size: 11px; +} +header a.button { + position: absolute; + top: 0; + right: 0; + background: transparent url(../images/github-button.png) 0 0 no-repeat; +} +aside a.button { + display: block; + width: 138px; + padding-left: 64px; + margin-bottom: 20px; + font-size: 21px; + background: transparent url(../images/download-button.png) 0 0 no-repeat; +} + +code, pre { + margin-bottom: 30px; + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; + font-size: 13px; + color: #222; +} + +code { + padding: 0 3px; + background-color: #f2f8fc; + border: solid 1px #dbe7f3; +} + +pre { + padding: 20px; + overflow: auto; + text-shadow: none; + background: #fff; + border: solid 1px #f2f2f2; +} +pre code { + padding: 0; + color: #2879d0; + background-color: #fff; + border: none; +} + +ul, ol, dl { + margin-bottom: 20px; +} + + +/* COMMON STYLES */ + +hr { + height: 0; + margin-top: 1em; + margin-bottom: 1em; + border: 0; + border-top: solid 1px #ddd; +} + +table { + width: 100%; + border: 1px solid #ebebeb; +} + +th { + font-weight: 500; +} + +td { + font-weight: 300; + text-align: center; + border: 1px solid #ebebeb; +} + +form { + padding: 20px; + background: #f2f2f2; + +} + + +/* GENERAL ELEMENT TYPE STYLES */ + +#main-content h1 { + margin-top: 0; + margin-bottom: 0; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 2.8em; + font-weight: normal; + color: #474747; + text-indent: 6px; + letter-spacing: -1px; +} + +#main-content h1:before { + padding-right: 0.3em; + margin-left: -0.9em; + color: #9ddcff; + content: "/"; +} + +#main-content h2 { + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 22px; + font-weight: bold; + color: #474747; + text-indent: 4px; +} +#main-content h2:before { + padding-right: 0.3em; + margin-left: -1.5em; + content: "//"; + color: #9ddcff; +} + +#main-content h3 { + margin-top: 24px; + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 18px; + font-weight: bold; + color: #474747; + text-indent: 3px; +} + +#main-content h3:before { + padding-right: 0.3em; + margin-left: -2em; + content: "///"; + color: #9ddcff; +} + +#main-content h4 { + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 15px; + font-weight: bold; + color: #474747; + text-indent: 3px; +} + +h4:before { + padding-right: 0.3em; + margin-left: -2.8em; + content: "////"; + color: #9ddcff; +} + +#main-content h5 { + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: 14px; + color: #474747; + text-indent: 3px; +} +h5:before { + padding-right: 0.3em; + margin-left: -3.2em; + content: "/////"; + color: #9ddcff; +} + +#main-content h6 { + margin-bottom: 8px; + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + font-size: .8em; + color: #474747; + text-indent: 3px; +} +h6:before { + padding-right: 0.3em; + margin-left: -3.7em; + content: "//////"; + color: #9ddcff; +} + +p { + margin-bottom: 20px; +} + +a { + text-decoration: none; +} + +p a { + font-weight: 400; +} + +blockquote { + padding: 0 0 0 30px; + margin-bottom: 20px; + font-size: 1.6em; + border-left: 10px solid #e9e9e9; +} + +ul { + list-style-position: inside; + list-style: disc; + padding-left: 20px; +} + +ol { + list-style-position: inside; + list-style: decimal; + padding-left: 3px; +} + +footer { + padding-top: 20px; + padding-bottom: 30px; + margin-top: 40px; + font-size: 13px; + color: #aaa; + background: transparent url('../../images/hr.png') 0 0 no-repeat; +} + +footer a { + color: #666; +} +footer a:hover { + color: #444; +} + +/* MISC */ +.clearfix:after { + display: block; + height: 0; + clear: both; + visibility: hidden; + content: '.'; +} + +.clearfix {display: inline-block;} +* html .clearfix {height: 1%;} +.clearfix {display: block;} + +/* #Media Queries +================================================== */ + +/* Smaller than standard 960 (devices and browsers) */ +@media only screen and (max-width: 959px) { } + +/* Tablet Portrait size to standard 960 (devices and browsers) */ +@media only screen and (min-width: 768px) and (max-width: 959px) { + .inner { + width: 740px; + } + header h1, header h2 { + width: 340px; + } + header h1 { + font-size: 60px; + } + header h2 { + font-size: 30px; + } + #main-content { + width: 490px; + } + #main-content h1:before, + #main-content h2:before, + #main-content h3:before, + #main-content h4:before, + #main-content h5:before, + #main-content h6:before { + padding-right: 0; + margin-left: 0; + content: none; + } +} + +/* All Mobile Sizes (devices and browser) */ +@media only screen and (max-width: 767px) { + .inner { + width: 93%; + } + header { + padding: 20px 0; + } + header .inner { + position: relative; + } + header h1, header h2 { + width: 100%; + } + header h1 { + font-size: 48px; + } + header h2 { + font-size: 24px; + } + header a.button { + position: relative; + display: inline-block; + width: auto; + height: auto; + padding: 5px 10px; + margin-top: 15px; + font-size: 13px; + line-height: 1; + color: #2879d0; + text-align: center; + background-color: #9ddcff; + background-image: none; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + header a.button small { + display: inline; + font-size: 13px; + } + #main-content, + aside#sidebar { + float: none; + width: 100% ! important; + } + aside#sidebar { + min-height: 0; + padding: 20px 0; + margin-top: 20px; + background-image: none; + border-top: solid 1px #ddd; + } + aside#sidebar a.button { + display: none; + } + #main-content h1:before, + #main-content h2:before, + #main-content h3:before, + #main-content h4:before, + #main-content h5:before, + #main-content h6:before { + padding-right: 0; + margin-left: 0; + content: none; + } +} + +/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */ +@media only screen and (min-width: 480px) and (max-width: 767px) { } + +/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */ +@media only screen and (max-width: 479px) { } + + +#container { + margin-left: 1em; + margin-right: 1em; + background-color: #f0f0f0; +} + +#product { + text-align: center; + border-bottom: 1px solid #cccccc; + background-color: #ffffff; +} + +#product big { + font-size: 2em; +} + +#main { + color: #666; + background: #fafafa url(../../images/body-bg.jpg) 0 0 repeat; + border-left: 2px solid #cccccc; +} + +#navigation { + float: left; + width: 18em; + vertical-align: top; + overflow: scroll; + position: fixed; + height:100%; + background: #2e7bcf url(../../images/header-bg.jpg) 0 0 repeat-x; + color: #fff; +} + +#navigation h2 { + font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif; + background: #2e7bcf url(../images/header-bg.jpg) 0 0 repeat-x; + border-bottom: solid 1px #275da1; + width: 540px; + margin-top: 0; + margin-bottom: 0.2em; + font-size: 36px; + font-weight: normal; + line-height: 1; + color: #fff; + letter-spacing: -1px; + text-align: left; + padding:0.2em; + border-top:1px solid #dddddd; +} + +#navigation ul +{ + font-size:1em; + list-style-type: none; + margin: 1px 1px 10px 1px; + color: #fff; +} + +#navigation li { + text-indent: -1em; + display: block; + margin: 3px 0px 0px 22px; + color: #fff; +} + +#navigation ul li a { + color: #fff; +} + + +#navigation li li a { + margin: 0px 3px 0px -1em; + color: #fff; +} + +#content { + margin-left: 18em; + padding: 1em; + border-left: 2px solid #cccccc; + border-right: 2px solid #cccccc; + background-color: #ffffff; +} + + +#content h2 a { + color: #000; + border-bottom: 1px solid #000; +} + +#content h2 a code { +font-size: 22px; +font-weight: 400; +background-color: transparent; +color: #2879d0; +border: none; +} + +#content h1 code { +font-size: 26px; +font-weight: 400; +background-color: transparent; +border: none; +} + +#about { + clear: both; + padding: 5px; + border-top: 2px solid #cccccc; + background-color: #ffffff; +} + +table.function_list { + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} + +table.function_list td { + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; + word-wrap:break-word; +} + +table.function_list td.name { font-weight: 400; width:50%; white-space: normal; text-align:left;} +table.function_list td.summary { width: 50%; } + + +dl.table dt, dl.function { + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} + +dl.table dt, dl.function dt { + border-top: 1px solid #000; + padding-top: 0.5em; + padding-bottom: 0.5em; + border-bottom: 1px solid #ccc; +} + +dl.table dd, dl.function dd { + padding-bottom: 0.5em; + margin: 20px 0 0 20px; +} + +dl.table dd, dl.function dd p { + font-weight : normal; +} + +dl.table h3, dl.function h3 {font-size: 1.5em;}