diff --git a/Embedded/Moose_Create_Embedded.bat b/Embedded/Moose_Create_Embedded.bat index bd830b9a3..c4e58833c 100644 --- a/Embedded/Moose_Create_Embedded.bat +++ b/Embedded/Moose_Create_Embedded.bat @@ -5,12 +5,13 @@ echo env.info( 'Moose Embedded' ) > Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Routines.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Base.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Event.lua Moose_Embedded.lua +copy /b Moose_Embedded.lua + ..\Moose\Menu.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Group.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Unit.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Zone.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Database.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Moose.lua Moose_Embedded.lua -copy /b Moose_Embedded.lua + ..\Moose\TimeTrigger.lua Moose_Embedded.lua +copy /b Moose_Embedded.lua + ..\Moose\Scheduler.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Scoring.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Cargo.lua Moose_Embedded.lua copy /b Moose_Embedded.lua + ..\Moose\Client.lua Moose_Embedded.lua diff --git a/Embedded/Moose_Embedded.lua b/Embedded/Moose_Embedded.lua index 459565c40..3a922dc43 100644 --- a/Embedded/Moose_Embedded.lua +++ b/Embedded/Moose_Embedded.lua @@ -2933,6 +2933,7 @@ end -- @param #number Level function BASE:TraceLevel( Level ) _TraceLevel = Level + self:E( "Tracing level " .. Level ) end --- Set tracing for a class @@ -2941,6 +2942,7 @@ end function BASE:TraceClass( Class ) _TraceClass[Class] = true _TraceClassMethod[Class] = {} + self:E( "Tracing class " .. Class ) end --- Set tracing for a specific method of class @@ -2953,6 +2955,7 @@ function BASE:TraceClassMethod( Class, Method ) _TraceClassMethod[Class].Method = {} end _TraceClassMethod[Class].Method[Method] = true + self:E( "Tracing method " .. Method .. " of class " .. Class ) end --- Trace a function call. Must be at the beginning of the function logic. @@ -3556,6 +3559,377 @@ function EVENT:onEvent( Event ) end end +--- Encapsulation of DCS World Menu system in a set of MENU classes. +-- @module Menu + +Include.File( "Routines" ) +Include.File( "Base" ) + +--- The MENU class +-- @type MENU +-- @extends Base#BASE +MENU = { + ClassName = "MENU", + MenuPath = nil, + MenuText = "", + MenuParentPath = nil +} + +--- +function MENU:New( MenuText, MenuParentPath ) + + -- Arrange meta tables + local Child = BASE:Inherit( self, BASE:New() ) + + Child.MenuPath = nil + Child.MenuText = MenuText + Child.MenuParentPath = MenuParentPath + return Child +end + +--- The COMMANDMENU class +-- @type COMMANDMENU +-- @extends Menu#MENU +COMMANDMENU = { + ClassName = "COMMANDMENU", + CommandMenuFunction = nil, + CommandMenuArgument = nil +} + +function COMMANDMENU:New( MenuText, ParentMenu, CommandMenuFunction, CommandMenuArgument ) + + -- Arrange meta tables + + local MenuParentPath = nil + if ParentMenu ~= nil then + MenuParentPath = ParentMenu.MenuPath + end + + local Child = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) ) + + Child.MenuPath = missionCommands.addCommand( MenuText, MenuParentPath, CommandMenuFunction, CommandMenuArgument ) + Child.CommandMenuFunction = CommandMenuFunction + Child.CommandMenuArgument = CommandMenuArgument + return Child +end + +--- The SUBMENU class +-- @type SUBMENU +-- @extends Menu#MENU +SUBMENU = { + ClassName = "SUBMENU" +} + +function SUBMENU:New( MenuText, ParentMenu ) + + -- Arrange meta tables + local MenuParentPath = nil + if ParentMenu ~= nil then + MenuParentPath = ParentMenu.MenuPath + end + + local Child = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) ) + + Child.MenuPath = missionCommands.addSubMenu( MenuText, MenuParentPath ) + return Child +end + +-- This local variable is used to cache the menus registered under clients. +-- Menus don't dissapear when clients are destroyed and restarted. +-- So every menu for a client created must be tracked so that program logic accidentally does not create +-- the same menus twice during initialization logic. +-- These menu classes are handling this logic with this variable. +local _MENUCLIENTS = {} + +--- The MENU_CLIENT class +-- @type MENU_CLIENT +-- @extends Menu#MENU +MENU_CLIENT = { + ClassName = "MENU_CLIENT" +} + +--- Creates a new menu item for a group +-- @param self +-- @param Client#CLIENT MenuClient The Client owning the menu. +-- @param #string MenuText The text for the menu. +-- @param #table ParentMenu The parent menu. +-- @return #MENU_CLIENT self +function MENU_CLIENT:New( MenuClient, MenuText, ParentMenu ) + + -- Arrange meta tables + local MenuParentPath = {} + if ParentMenu ~= nil then + MenuParentPath = ParentMenu.MenuPath + end + + local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) ) + self:F( { MenuClient, MenuText, ParentMenu } ) + + self.MenuClient = MenuClient + self.MenuClientGroupID = MenuClient:GetClientGroupID() + self.MenuParentPath = MenuParentPath + self.MenuText = MenuText + self.ParentMenu = ParentMenu + + self.Menus = {} + + if not _MENUCLIENTS[self.MenuClientGroupID] then + _MENUCLIENTS[self.MenuClientGroupID] = {} + end + + local MenuPath = _MENUCLIENTS[self.MenuClientGroupID] + + self:T( { MenuClient:GetClientGroupName(), MenuPath[table.concat(MenuParentPath)], MenuParentPath, MenuText } ) + + local MenuPathID = table.concat(MenuParentPath) .. "/" .. MenuText + if MenuPath[MenuPathID] then + missionCommands.removeItemForGroup( self.MenuClient:GetClientGroupID(), MenuPath[MenuPathID] ) + end + + self.MenuPath = missionCommands.addSubMenuForGroup( self.MenuClient:GetClientGroupID(), MenuText, MenuParentPath ) + MenuPath[MenuPathID] = self.MenuPath + + self:T( { MenuClient:GetClientGroupName(), self.MenuPath } ) + + if ParentMenu and ParentMenu.Menus then + ParentMenu.Menus[self.MenuPath] = self + end + return self +end + +--- Removes the sub menus recursively of this MENU_CLIENT. +-- @param #MENU_CLIENT self +-- @return #MENU_CLIENT self +function MENU_CLIENT:RemoveSubMenus() + self:F( self.MenuPath ) + + for MenuID, Menu in pairs( self.Menus ) do + Menu:Remove() + end + +end + +--- Removes the sub menus recursively of this MENU_CLIENT. +-- @param #MENU_CLIENT self +-- @return #MENU_CLIENT self +function MENU_CLIENT:Remove() + self:F( self.MenuPath ) + + self:RemoveSubMenus() + + if not _MENUCLIENTS[self.MenuClientGroupID] then + _MENUCLIENTS[self.MenuClientGroupID] = {} + end + + local MenuPath = _MENUCLIENTS[self.MenuClientGroupID] + + if MenuPath[table.concat(self.MenuParentPath) .. "/" .. self.MenuText] then + MenuPath[table.concat(self.MenuParentPath) .. "/" .. self.MenuText] = nil + end + + missionCommands.removeItemForGroup( self.MenuClient:GetClientGroupID(), self.MenuPath ) + self.ParentMenu.Menus[self.MenuPath] = nil + return nil +end + + +--- The MENU_CLIENT_COMMAND class +-- @type MENU_CLIENT_COMMAND +-- @extends Menu#MENU +MENU_CLIENT_COMMAND = { + ClassName = "MENU_CLIENT_COMMAND" +} + +--- Creates a new radio command item for a group +-- @param self +-- @param Client#CLIENT MenuClient The Client owning the menu. +-- @param MenuText The text for the menu. +-- @param ParentMenu The parent menu. +-- @param CommandMenuFunction A function that is called when the menu key is pressed. +-- @param CommandMenuArgument An argument for the function. +-- @return Menu#MENU_CLIENT_COMMAND self +function MENU_CLIENT_COMMAND:New( MenuClient, MenuText, ParentMenu, CommandMenuFunction, CommandMenuArgument ) + + -- Arrange meta tables + + local MenuParentPath = {} + if ParentMenu ~= nil then + MenuParentPath = ParentMenu.MenuPath + end + + local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) ) + + self.MenuClient = MenuClient + self.MenuClientGroupID = MenuClient:GetClientGroupID() + self.MenuParentPath = MenuParentPath + self.MenuText = MenuText + self.ParentMenu = ParentMenu + + if not _MENUCLIENTS[self.MenuClientGroupID] then + _MENUCLIENTS[self.MenuClientGroupID] = {} + end + + local MenuPath = _MENUCLIENTS[self.MenuClientGroupID] + + self:T( { MenuClient:GetClientGroupName(), MenuPath[table.concat(MenuParentPath)], MenuParentPath, MenuText, CommandMenuFunction, CommandMenuArgument } ) + + local MenuPathID = table.concat(MenuParentPath) .. "/" .. MenuText + if MenuPath[MenuPathID] then + missionCommands.removeItemForGroup( self.MenuClient:GetClientGroupID(), MenuPath[MenuPathID] ) + end + + self.MenuPath = missionCommands.addCommandForGroup( self.MenuClient:GetClientGroupID(), MenuText, MenuParentPath, CommandMenuFunction, CommandMenuArgument ) + MenuPath[MenuPathID] = self.MenuPath + + self.CommandMenuFunction = CommandMenuFunction + self.CommandMenuArgument = CommandMenuArgument + + ParentMenu.Menus[self.MenuPath] = self + + return self +end + +function MENU_CLIENT_COMMAND:Remove() + self:F( self.MenuPath ) + + if not _MENUCLIENTS[self.MenuClientGroupID] then + _MENUCLIENTS[self.MenuClientGroupID] = {} + end + + local MenuPath = _MENUCLIENTS[self.MenuClientGroupID] + + if MenuPath[table.concat(self.MenuParentPath) .. "/" .. self.MenuText] then + MenuPath[table.concat(self.MenuParentPath) .. "/" .. self.MenuText] = nil + end + + missionCommands.removeItemForGroup( self.MenuClient:GetClientGroupID(), self.MenuPath ) + self.ParentMenu.Menus[self.MenuPath] = nil + return nil +end + + +--- The MENU_COALITION class +-- @type MENU_COALITION +-- @extends Menu#MENU +MENU_COALITION = { + ClassName = "MENU_COALITION" +} + +--- Creates a new coalition menu item +-- @param #MENU_COALITION self +-- @param DCSCoalition#coalition.side MenuCoalition The coalition owning the menu. +-- @param #string MenuText The text for the menu. +-- @param #table ParentMenu The parent menu. +-- @return #MENU_COALITION self +function MENU_COALITION:New( MenuCoalition, MenuText, ParentMenu ) + + -- Arrange meta tables + local MenuParentPath = {} + if ParentMenu ~= nil then + MenuParentPath = ParentMenu.MenuPath + end + + local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) ) + self:F( { MenuCoalition, MenuText, ParentMenu } ) + + self.MenuCoalition = MenuCoalition + self.MenuParentPath = MenuParentPath + self.MenuText = MenuText + self.ParentMenu = ParentMenu + + self.Menus = {} + + self:T( { MenuParentPath, MenuText } ) + + self.MenuPath = missionCommands.addSubMenuForCoalition( self.MenuCoalition, MenuText, MenuParentPath ) + + self:T( { self.MenuPath } ) + + if ParentMenu and ParentMenu.Menus then + ParentMenu.Menus[self.MenuPath] = self + end + return self +end + +--- Removes the sub menus recursively of this MENU_COALITION. +-- @param #MENU_COALITION self +-- @return #MENU_COALITION self +function MENU_COALITION:RemoveSubMenus() + self:F( self.MenuPath ) + + for MenuID, Menu in pairs( self.Menus ) do + Menu:Remove() + end + +end + +--- Removes the sub menus recursively of this MENU_COALITION. +-- @param #MENU_COALITION self +-- @return #MENU_COALITION self +function MENU_COALITION:Remove() + self:F( self.MenuPath ) + + self:RemoveSubMenus() + missionCommands.removeItemForCoalition( self.MenuCoalition, self.MenuPath ) + self.ParentMenu.Menus[self.MenuPath] = nil + + return nil +end + + +--- The MENU_COALITION_COMMAND class +-- @type MENU_COALITION_COMMAND +-- @extends Menu#MENU +MENU_COALITION_COMMAND = { + ClassName = "MENU_COALITION_COMMAND" +} + +--- Creates a new radio command item for a group +-- @param #MENU_COALITION_COMMAND self +-- @param DCSCoalition#coalition.side MenuCoalition The coalition owning the menu. +-- @param MenuText The text for the menu. +-- @param ParentMenu The parent menu. +-- @param CommandMenuFunction A function that is called when the menu key is pressed. +-- @param CommandMenuArgument An argument for the function. +-- @return #MENU_COALITION_COMMAND self +function MENU_COALITION_COMMAND:New( MenuCoalition, MenuText, ParentMenu, CommandMenuFunction, CommandMenuArgument ) + + -- Arrange meta tables + + local MenuParentPath = {} + if ParentMenu ~= nil then + MenuParentPath = ParentMenu.MenuPath + end + + local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) ) + + self.MenuCoalition = MenuCoalition + self.MenuParentPath = MenuParentPath + self.MenuText = MenuText + self.ParentMenu = ParentMenu + + self:T( { MenuParentPath, MenuText, CommandMenuFunction, CommandMenuArgument } ) + + self.MenuPath = missionCommands.addCommandForCoalition( self.MenuCoalition, MenuText, MenuParentPath, CommandMenuFunction, CommandMenuArgument ) + + self.CommandMenuFunction = CommandMenuFunction + self.CommandMenuArgument = CommandMenuArgument + + ParentMenu.Menus[self.MenuPath] = self + + return self +end + +--- Removes a radio command item for a coalition +-- @param #MENU_COALITION_COMMAND self +-- @return #MENU_COALITION_COMMAND self +function MENU_COALITION_COMMAND:Remove() + self:F( self.MenuPath ) + + missionCommands.removeItemForCoalition( self.MenuCoalition, self.MenuPath ) + self.ParentMenu.Menus[self.MenuPath] = nil + return nil +end --- A GROUP class abstraction of a DCSGroup class. -- The GROUP class will take an abstraction of the DCSGroup class, providing more methods that can be done with a GROUP. -- @module Group @@ -3650,6 +4024,18 @@ function GROUP:NewFromDCSUnit( DCSUnit ) return self end +--- Returns the name of the Group. +-- @param #GROUP self +-- @return #string GroupName +function GROUP:GetName() + + local GroupName = self.DCSGroup:getName() + + return GroupName +end + + + --- Retrieve the group mission and allow to place function hooks within the mission waypoint plan. -- Use the method @{Group#GROUP:WayPointFunction} to define the hook functions for specific waypoints. -- Use the method @{Group@GROUP:WayPointExecute) to start the execution of the new mission plan. @@ -3686,7 +4072,12 @@ function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionAr local DCSScript = {} DCSScript[#DCSScript+1] = "local MissionGroup = GROUP.FindGroup( ... ) " - DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")" + + if FunctionArguments.n > 0 then + DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")" + else + DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup )" + end DCSTask = self:TaskWrappedAction( self:CommandDoScript( @@ -4152,6 +4543,41 @@ function GROUP:TaskWrappedAction( DCSCommand, Index ) return DCSTaskWrappedAction end +--- Executes a command action +-- @param #GROUP self +-- @param DCSCommand#Command DCSCommand +-- @return #GROUP self +function GROUP:SetCommand( DCSCommand ) + self:F( DCSCommand ) + + local Controller = self:_GetController() + + Controller:setCommand( DCSCommand ) + + return self +end + +--- Perform a switch waypoint command +-- @param #GROUP self +-- @param #number FromWayPoint +-- @param #number ToWayPoint +-- @return DCSTask#Task +function GROUP:CommandSwitchWayPoint( FromWayPoint, ToWayPoint, Index ) + self:F( { FromWayPoint, ToWayPoint, Index } ) + + local CommandSwitchWayPoint = { + id = 'SwitchWaypoint', + params = { + fromWaypointIndex = FromWayPoint, + goToWaypointIndex = ToWayPoint, + }, + } + + self:T( { CommandSwitchWayPoint } ) + return CommandSwitchWayPoint +end + + --- Orbit at a specified position at a specified alititude during a specified duration with a specified speed. -- @param #GROUP self -- @param #Vec2 Point The point to hold the position. @@ -4159,7 +4585,7 @@ end -- @param #number Speed The speed flying when holding the position. -- @return #GROUP self function GROUP:TaskOrbitCircleAtVec2( Point, Altitude, Speed ) - self:F( { self.GroupName, Point, Altitude, Speed } ) + self:F( { self.GroupName, Point, Altitude, Speed } ) -- pattern = enum AI.Task.OribtPattern, -- point = Vec2, @@ -4290,8 +4716,41 @@ function GROUP:TaskAttackUnit( AttackUnit ) params = { unitId = AttackUnit:GetID(), expend = AI.Task.WeaponExpend.TWO, groupAttack = true, - } - } + }, + }, + + self:T( { DCSTask } ) + return DCSTask +end + +--- Attack a Group. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup The Group to be attacked. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackGroup( AttackGroup ) + self:F( { self.GroupName, AttackGroup } ) + +-- AttackGroup = { +-- id = 'AttackGroup', +-- params = { +-- groupId = Group.ID, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- directionEnabled = boolean, +-- direction = Azimuth, +-- altitudeEnabled = boolean, +-- altitude = Distance, +-- attackQtyLimit = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'AttackGroup', + params = { groupId = AttackGroup:GetID(), + expend = AI.Task.WeaponExpend.TWO, + }, + }, self:T( { DCSTask } ) return DCSTask @@ -5573,6 +6032,9 @@ end -- This method expects EXACTLY the same structure as a structure within the ME, and needs 2 additional fields defined: -- SpawnCountryID, SpawnCategoryID -- This method is used by the SPAWN class. +-- @param #DATABASE self +-- @param #table SpawnTemplate +-- @return #DATABASE self function DATABASE:Spawn( SpawnTemplate ) self:F( SpawnTemplate.name ) @@ -5621,7 +6083,10 @@ function DATABASE:GetStatusGroup( GroupName ) end end ---- Registers new Group Templates within the DATABASE Object. +--- Private method that registers new Group Templates within the DATABASE Object. +-- @param #DATABASE self +-- @param #table GroupTemplate +-- @return #DATABASE self function DATABASE:_RegisterGroup( GroupTemplate ) local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name) @@ -5630,6 +6095,12 @@ function DATABASE:_RegisterGroup( GroupTemplate ) self.Groups[GroupTemplateName] = {} self.Groups[GroupTemplateName].Status = nil end + + -- Delete the spans from the route, it is not needed and takes memory. + if GroupTemplate.route and GroupTemplate.route.spans then + GroupTemplate.route.spans = nil + end + self.Groups[GroupTemplateName].GroupName = GroupTemplateName self.Groups[GroupTemplateName].Template = GroupTemplate self.Groups[GroupTemplateName].groupId = GroupTemplate.groupId @@ -5901,7 +6372,7 @@ _EVENTDISPATCHER = EVENT:New() -- #EVENT _DATABASE = DATABASE:New():ScanEnvironment() -- Database#DATABASE --- Models time events calling event handing functions. --- @module TimeTrigger +-- @module Scheduler -- @author FlightControl Include.File( "Routines" ) @@ -5910,24 +6381,24 @@ Include.File( "Cargo" ) Include.File( "Message" ) ---- The TIMETRIGGER class --- @type TIMETRIGGER +--- The SCHEDULER class +-- @type SCHEDULER -- @extends Base#BASE -TIMETRIGGER = { - ClassName = "TIMETRIGGER", +SCHEDULER = { + ClassName = "SCHEDULER", } ---- TIMETRIGGER constructor. --- @param #TIMETRIGGER self +--- SCHEDULER constructor. +-- @param #SCHEDULER self -- @param #function TimeEventFunction -- @param #table TimeEventFunctionArguments -- @param #number StartSeconds -- @param #number RepeatSecondsInterval -- @param #number RandomizationFactor -- @param #number StopSeconds --- @return #TIMETRIGGER -function TIMETRIGGER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds ) +-- @return #SCHEDULER +function SCHEDULER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds ) local self = BASE:Inherit( self, BASE:New() ) self:F( { TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds } ) @@ -5954,7 +6425,7 @@ function TIMETRIGGER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionA self.StartTime = timer.getTime() - self:T("Calling function" .. timer.getTime() + self.StartSeconds ) + self:T("Calling function " .. timer.getTime() + self.StartSeconds ) timer.scheduleFunction( self.Scheduler, self, timer.getTime() + self.StartSeconds + .01 ) @@ -5962,12 +6433,27 @@ function TIMETRIGGER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionA return self end -function TIMETRIGGER:Scheduler() +function SCHEDULER:Scheduler() self:F( self.TimeEventFunctionArguments ) + + local ErrorHandler = function( errmsg ) - local Result = self.TimeEventFunction( self.TimeEventObject, unpack( self.TimeEventFunctionArguments ) ) + env.info( "Error in SCHEDULER function:" .. errmsg ) + env.info( debug.traceback() ) - if Result and Result == true then + return errmsg + end + + local Status, Result + if self.TimeEventObject then + Status, Result = xpcall( function() return self.TimeEventFunction( self.TimeEventObject, unpack( self.TimeEventFunctionArguments ) ) end, ErrorHandler ) + else + Status, Result = xpcall( function() return self.TimeEventFunction( unpack( self.TimeEventFunctionArguments ) ) end, ErrorHandler ) + end + + self:T( { Status, Result } ) + + if Status and Status == true and Result and Result == true then if not self.StopSeconds or ( self.StopSeconds and timer.getTime() <= self.StartTime + self.StopSeconds ) then timer.scheduleFunction( self.Scheduler, @@ -11926,6 +12412,8 @@ function SPAWN:SpawnWithIndex( SpawnIndex ) if self.RepeatOnEngineShutDown then _EVENTDISPATCHER:OnEngineShutDownForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnEngineShutDown, self ) end + + self:T( self.SpawnGroups[self.SpawnIndex].SpawnTemplate ) self.SpawnGroups[self.SpawnIndex].Group = _DATABASE:Spawn( self.SpawnGroups[self.SpawnIndex].SpawnTemplate ) @@ -12057,6 +12545,9 @@ function SPAWN:SpawnFromUnit( HostUnit, OuterRadius, InnerRadius, SpawnIndex ) if SpawnTemplate then local UnitPoint = HostUnit:GetPointVec2() + + self:T( { "Current point of ", self.SpawnTemplatePrefix, UnitPoint } ) + --for PointID, Point in pairs( SpawnTemplate.route.points ) do --Point.x = UnitPoint.x --Point.y = UnitPoint.y @@ -12064,9 +12555,6 @@ function SPAWN:SpawnFromUnit( HostUnit, OuterRadius, InnerRadius, SpawnIndex ) --Point.alt_type = nil --end - SpawnTemplate.route.points = nil - SpawnTemplate.route.points = {} - SpawnTemplate.route.points[1] = {} SpawnTemplate.route.points[1].x = UnitPoint.x SpawnTemplate.route.points[1].y = UnitPoint.y @@ -12377,7 +12865,6 @@ function SPAWN:_InitializeSpawnGroups( SpawnIndex ) self.SpawnGroups[SpawnIndex].Visible = false self.SpawnGroups[SpawnIndex].Spawned = false self.SpawnGroups[SpawnIndex].UnControlled = false - self.SpawnGroups[SpawnIndex].Spawned = false self.SpawnGroups[SpawnIndex].SpawnTime = 0 self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix = self.SpawnTemplatePrefix @@ -12431,6 +12918,9 @@ end --- Gets the Group Template from the ME environment definition. -- This method used the @{DATABASE} object, which contains ALL initial and new spawned object in MOOSE. +-- @param #SPAWN self +-- @param #string SpawnTemplatePrefix +-- @return @SPAWN self function SPAWN:_GetTemplate( SpawnTemplatePrefix ) self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnTemplatePrefix } ) @@ -12451,6 +12941,10 @@ function SPAWN:_GetTemplate( SpawnTemplatePrefix ) end --- Prepares the new Group Template. +-- @param #SPAWN self +-- @param #string SpawnTemplatePrefix +-- @param #number SpawnIndex +-- @return #SPAWN self function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix } ) @@ -12461,6 +12955,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) SpawnTemplate.lateActivation = false if SpawnTemplate.SpawnCategoryID == Group.Category.GROUND then + self:T( "For ground units, visible needs to be false..." ) SpawnTemplate.visible = false end @@ -12480,7 +12975,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) end ---- Internal function randomizing the routes. +--- Private method randomizing the routes. -- @param #SPAWN self -- @param #number SpawnIndex The index of the group to be spawned. -- @return #SPAWN @@ -12504,7 +12999,10 @@ function SPAWN:_RandomizeRoute( SpawnIndex ) return self end - +--- Private method that randomizes the template of the group. +-- @param #SPAWN self +-- @param #number SpawnIndex +-- @return #SPAWN self function SPAWN:_RandomizeTemplate( SpawnIndex ) self:F( { self.SpawnTemplatePrefix, SpawnIndex } ) @@ -12514,6 +13012,7 @@ function SPAWN:_RandomizeTemplate( SpawnIndex ) self.SpawnGroups[SpawnIndex].SpawnTemplate.route = routines.utils.deepCopy( self.SpawnTemplate.route ) self.SpawnGroups[SpawnIndex].SpawnTemplate.x = self.SpawnTemplate.x self.SpawnGroups[SpawnIndex].SpawnTemplate.y = self.SpawnTemplate.y + self.SpawnGroups[SpawnIndex].SpawnTemplate.start_time = self.SpawnTemplate.start_time for UnitID = 1, #self.SpawnGroups[SpawnIndex].SpawnTemplate.units do self.SpawnGroups[SpawnIndex].SpawnTemplate.units[UnitID].heading = self.SpawnTemplate.units[1].heading end @@ -14258,7 +14757,7 @@ end -- @author FlightControl Include.File( "Client" ) -Include.File( "TimeTrigger" ) +Include.File( "Scheduler" ) --- The MISSILETRAINER class -- @type MISSILETRAINER @@ -14268,7 +14767,7 @@ MISSILETRAINER = { } --- Creates the main object which is handling missile tracking. --- When a missile is fired a TIMETRIGGER is set off that follows the missile. When near a certain a client player, the missile will be destroyed. +-- When a missile is fired a SCHEDULER is set off that follows the missile. When near a certain a client player, the missile will be destroyed. -- @param #MISSILETRAINER -- @param #number Distance The distance in meters when a tracked missile needs to be destroyed when close to a player. -- @return #MISSILETRAINER @@ -14276,8 +14775,8 @@ function MISSILETRAINER:New( Distance ) local self = BASE:Inherit( self, BASE:New() ) self:F( Distance ) - self.TimeTriggers = {} - self.TimeTriggerID = 0 + self.Schedulers = {} + self.SchedulerID = 0 self.Distance = Distance @@ -14307,7 +14806,7 @@ function MISSILETRAINER:_EventShot( Event ) self:T( TrainerTargetSkill ) if TrainerTargetSkill == "Client" or TrainerTargetSkill == "Player" then - self.TimeTriggers[#self.TimeTriggers+1] = TIMETRIGGER:New( self, self._FollowMissile, { TrainerSourceDCSUnit, TrainerWeapon, TrainerTargetDCSUnit }, 0.5, 0.05, 0 ) + self.Schedulers[#self.Schedulers+1] = SCHEDULER:New( self, self._FollowMissile, { TrainerSourceDCSUnit, TrainerWeapon, TrainerTargetDCSUnit }, 0.5, 0.05, 0 ) end end diff --git a/Moose/Base.lua b/Moose/Base.lua index 3eb5acd45..c96e27047 100644 --- a/Moose/Base.lua +++ b/Moose/Base.lua @@ -353,6 +353,7 @@ end -- @param #number Level function BASE:TraceLevel( Level ) _TraceLevel = Level + self:E( "Tracing level " .. Level ) end --- Set tracing for a class @@ -361,6 +362,7 @@ end function BASE:TraceClass( Class ) _TraceClass[Class] = true _TraceClassMethod[Class] = {} + self:E( "Tracing class " .. Class ) end --- Set tracing for a specific method of class @@ -373,6 +375,7 @@ function BASE:TraceClassMethod( Class, Method ) _TraceClassMethod[Class].Method = {} end _TraceClassMethod[Class].Method[Method] = true + self:E( "Tracing method " .. Method .. " of class " .. Class ) end --- Trace a function call. Must be at the beginning of the function logic. diff --git a/Moose/Database.lua b/Moose/Database.lua index a0c915eda..631bd665b 100644 --- a/Moose/Database.lua +++ b/Moose/Database.lua @@ -282,6 +282,9 @@ end -- This method expects EXACTLY the same structure as a structure within the ME, and needs 2 additional fields defined: -- SpawnCountryID, SpawnCategoryID -- This method is used by the SPAWN class. +-- @param #DATABASE self +-- @param #table SpawnTemplate +-- @return #DATABASE self function DATABASE:Spawn( SpawnTemplate ) self:F( SpawnTemplate.name ) @@ -330,7 +333,10 @@ function DATABASE:GetStatusGroup( GroupName ) end end ---- Registers new Group Templates within the DATABASE Object. +--- Private method that registers new Group Templates within the DATABASE Object. +-- @param #DATABASE self +-- @param #table GroupTemplate +-- @return #DATABASE self function DATABASE:_RegisterGroup( GroupTemplate ) local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name) @@ -339,6 +345,12 @@ function DATABASE:_RegisterGroup( GroupTemplate ) self.Groups[GroupTemplateName] = {} self.Groups[GroupTemplateName].Status = nil end + + -- Delete the spans from the route, it is not needed and takes memory. + if GroupTemplate.route and GroupTemplate.route.spans then + GroupTemplate.route.spans = nil + end + self.Groups[GroupTemplateName].GroupName = GroupTemplateName self.Groups[GroupTemplateName].Template = GroupTemplate self.Groups[GroupTemplateName].groupId = GroupTemplate.groupId diff --git a/Moose/Group.lua b/Moose/Group.lua index c7f9faa4b..e93f50b69 100644 --- a/Moose/Group.lua +++ b/Moose/Group.lua @@ -92,6 +92,18 @@ function GROUP:NewFromDCSUnit( DCSUnit ) return self end +--- Returns the name of the Group. +-- @param #GROUP self +-- @return #string GroupName +function GROUP:GetName() + + local GroupName = self.DCSGroup:getName() + + return GroupName +end + + + --- Retrieve the group mission and allow to place function hooks within the mission waypoint plan. -- Use the method @{Group#GROUP:WayPointFunction} to define the hook functions for specific waypoints. -- Use the method @{Group@GROUP:WayPointExecute) to start the execution of the new mission plan. @@ -128,7 +140,12 @@ function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionAr local DCSScript = {} DCSScript[#DCSScript+1] = "local MissionGroup = GROUP.FindGroup( ... ) " - DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")" + + if FunctionArguments.n > 0 then + DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")" + else + DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup )" + end DCSTask = self:TaskWrappedAction( self:CommandDoScript( @@ -594,6 +611,41 @@ function GROUP:TaskWrappedAction( DCSCommand, Index ) return DCSTaskWrappedAction end +--- Executes a command action +-- @param #GROUP self +-- @param DCSCommand#Command DCSCommand +-- @return #GROUP self +function GROUP:SetCommand( DCSCommand ) + self:F( DCSCommand ) + + local Controller = self:_GetController() + + Controller:setCommand( DCSCommand ) + + return self +end + +--- Perform a switch waypoint command +-- @param #GROUP self +-- @param #number FromWayPoint +-- @param #number ToWayPoint +-- @return DCSTask#Task +function GROUP:CommandSwitchWayPoint( FromWayPoint, ToWayPoint, Index ) + self:F( { FromWayPoint, ToWayPoint, Index } ) + + local CommandSwitchWayPoint = { + id = 'SwitchWaypoint', + params = { + fromWaypointIndex = FromWayPoint, + goToWaypointIndex = ToWayPoint, + }, + } + + self:T( { CommandSwitchWayPoint } ) + return CommandSwitchWayPoint +end + + --- Orbit at a specified position at a specified alititude during a specified duration with a specified speed. -- @param #GROUP self -- @param #Vec2 Point The point to hold the position. @@ -601,7 +653,7 @@ end -- @param #number Speed The speed flying when holding the position. -- @return #GROUP self function GROUP:TaskOrbitCircleAtVec2( Point, Altitude, Speed ) - self:F( { self.GroupName, Point, Altitude, Speed } ) + self:F( { self.GroupName, Point, Altitude, Speed } ) -- pattern = enum AI.Task.OribtPattern, -- point = Vec2, @@ -732,8 +784,41 @@ function GROUP:TaskAttackUnit( AttackUnit ) params = { unitId = AttackUnit:GetID(), expend = AI.Task.WeaponExpend.TWO, groupAttack = true, - } - } + }, + }, + + self:T( { DCSTask } ) + return DCSTask +end + +--- Attack a Group. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup The Group to be attacked. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackGroup( AttackGroup ) + self:F( { self.GroupName, AttackGroup } ) + +-- AttackGroup = { +-- id = 'AttackGroup', +-- params = { +-- groupId = Group.ID, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- directionEnabled = boolean, +-- direction = Azimuth, +-- altitudeEnabled = boolean, +-- altitude = Distance, +-- attackQtyLimit = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'AttackGroup', + params = { groupId = AttackGroup:GetID(), + expend = AI.Task.WeaponExpend.TWO, + }, + }, self:T( { DCSTask } ) return DCSTask diff --git a/Moose/Menu.lua b/Moose/Menu.lua index f386e118d..e5bdfa778 100644 --- a/Moose/Menu.lua +++ b/Moose/Menu.lua @@ -245,3 +245,127 @@ function MENU_CLIENT_COMMAND:Remove() self.ParentMenu.Menus[self.MenuPath] = nil return nil end + + +--- The MENU_COALITION class +-- @type MENU_COALITION +-- @extends Menu#MENU +MENU_COALITION = { + ClassName = "MENU_COALITION" +} + +--- Creates a new coalition menu item +-- @param #MENU_COALITION self +-- @param DCSCoalition#coalition.side MenuCoalition The coalition owning the menu. +-- @param #string MenuText The text for the menu. +-- @param #table ParentMenu The parent menu. +-- @return #MENU_COALITION self +function MENU_COALITION:New( MenuCoalition, MenuText, ParentMenu ) + + -- Arrange meta tables + local MenuParentPath = {} + if ParentMenu ~= nil then + MenuParentPath = ParentMenu.MenuPath + end + + local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) ) + self:F( { MenuCoalition, MenuText, ParentMenu } ) + + self.MenuCoalition = MenuCoalition + self.MenuParentPath = MenuParentPath + self.MenuText = MenuText + self.ParentMenu = ParentMenu + + self.Menus = {} + + self:T( { MenuParentPath, MenuText } ) + + self.MenuPath = missionCommands.addSubMenuForCoalition( self.MenuCoalition, MenuText, MenuParentPath ) + + self:T( { self.MenuPath } ) + + if ParentMenu and ParentMenu.Menus then + ParentMenu.Menus[self.MenuPath] = self + end + return self +end + +--- Removes the sub menus recursively of this MENU_COALITION. +-- @param #MENU_COALITION self +-- @return #MENU_COALITION self +function MENU_COALITION:RemoveSubMenus() + self:F( self.MenuPath ) + + for MenuID, Menu in pairs( self.Menus ) do + Menu:Remove() + end + +end + +--- Removes the sub menus recursively of this MENU_COALITION. +-- @param #MENU_COALITION self +-- @return #MENU_COALITION self +function MENU_COALITION:Remove() + self:F( self.MenuPath ) + + self:RemoveSubMenus() + missionCommands.removeItemForCoalition( self.MenuCoalition, self.MenuPath ) + self.ParentMenu.Menus[self.MenuPath] = nil + + return nil +end + + +--- The MENU_COALITION_COMMAND class +-- @type MENU_COALITION_COMMAND +-- @extends Menu#MENU +MENU_COALITION_COMMAND = { + ClassName = "MENU_COALITION_COMMAND" +} + +--- Creates a new radio command item for a group +-- @param #MENU_COALITION_COMMAND self +-- @param DCSCoalition#coalition.side MenuCoalition The coalition owning the menu. +-- @param MenuText The text for the menu. +-- @param ParentMenu The parent menu. +-- @param CommandMenuFunction A function that is called when the menu key is pressed. +-- @param CommandMenuArgument An argument for the function. +-- @return #MENU_COALITION_COMMAND self +function MENU_COALITION_COMMAND:New( MenuCoalition, MenuText, ParentMenu, CommandMenuFunction, CommandMenuArgument ) + + -- Arrange meta tables + + local MenuParentPath = {} + if ParentMenu ~= nil then + MenuParentPath = ParentMenu.MenuPath + end + + local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) ) + + self.MenuCoalition = MenuCoalition + self.MenuParentPath = MenuParentPath + self.MenuText = MenuText + self.ParentMenu = ParentMenu + + self:T( { MenuParentPath, MenuText, CommandMenuFunction, CommandMenuArgument } ) + + self.MenuPath = missionCommands.addCommandForCoalition( self.MenuCoalition, MenuText, MenuParentPath, CommandMenuFunction, CommandMenuArgument ) + + self.CommandMenuFunction = CommandMenuFunction + self.CommandMenuArgument = CommandMenuArgument + + ParentMenu.Menus[self.MenuPath] = self + + return self +end + +--- Removes a radio command item for a coalition +-- @param #MENU_COALITION_COMMAND self +-- @return #MENU_COALITION_COMMAND self +function MENU_COALITION_COMMAND:Remove() + self:F( self.MenuPath ) + + missionCommands.removeItemForCoalition( self.MenuCoalition, self.MenuPath ) + self.ParentMenu.Menus[self.MenuPath] = nil + return nil +end diff --git a/Moose/MissileTrainer.lua b/Moose/MissileTrainer.lua index cc2c15aa9..e805103b4 100644 --- a/Moose/MissileTrainer.lua +++ b/Moose/MissileTrainer.lua @@ -3,7 +3,7 @@ -- @author FlightControl Include.File( "Client" ) -Include.File( "TimeTrigger" ) +Include.File( "Scheduler" ) --- The MISSILETRAINER class -- @type MISSILETRAINER @@ -13,7 +13,7 @@ MISSILETRAINER = { } --- Creates the main object which is handling missile tracking. --- When a missile is fired a TIMETRIGGER is set off that follows the missile. When near a certain a client player, the missile will be destroyed. +-- When a missile is fired a SCHEDULER is set off that follows the missile. When near a certain a client player, the missile will be destroyed. -- @param #MISSILETRAINER -- @param #number Distance The distance in meters when a tracked missile needs to be destroyed when close to a player. -- @return #MISSILETRAINER @@ -21,8 +21,8 @@ function MISSILETRAINER:New( Distance ) local self = BASE:Inherit( self, BASE:New() ) self:F( Distance ) - self.TimeTriggers = {} - self.TimeTriggerID = 0 + self.Schedulers = {} + self.SchedulerID = 0 self.Distance = Distance @@ -52,7 +52,7 @@ function MISSILETRAINER:_EventShot( Event ) self:T( TrainerTargetSkill ) if TrainerTargetSkill == "Client" or TrainerTargetSkill == "Player" then - self.TimeTriggers[#self.TimeTriggers+1] = TIMETRIGGER:New( self, self._FollowMissile, { TrainerSourceDCSUnit, TrainerWeapon, TrainerTargetDCSUnit }, 0.5, 0.05, 0 ) + self.Schedulers[#self.Schedulers+1] = SCHEDULER:New( self, self._FollowMissile, { TrainerSourceDCSUnit, TrainerWeapon, TrainerTargetDCSUnit }, 0.5, 0.05, 0 ) end end diff --git a/Moose/TimeTrigger.lua b/Moose/Scheduler.lua similarity index 61% rename from Moose/TimeTrigger.lua rename to Moose/Scheduler.lua index 4b3a9f9a2..3134e2626 100644 --- a/Moose/TimeTrigger.lua +++ b/Moose/Scheduler.lua @@ -1,5 +1,5 @@ --- Models time events calling event handing functions. --- @module TimeTrigger +-- @module Scheduler -- @author FlightControl Include.File( "Routines" ) @@ -8,24 +8,24 @@ Include.File( "Cargo" ) Include.File( "Message" ) ---- The TIMETRIGGER class --- @type TIMETRIGGER +--- The SCHEDULER class +-- @type SCHEDULER -- @extends Base#BASE -TIMETRIGGER = { - ClassName = "TIMETRIGGER", +SCHEDULER = { + ClassName = "SCHEDULER", } ---- TIMETRIGGER constructor. --- @param #TIMETRIGGER self +--- SCHEDULER constructor. +-- @param #SCHEDULER self -- @param #function TimeEventFunction -- @param #table TimeEventFunctionArguments -- @param #number StartSeconds -- @param #number RepeatSecondsInterval -- @param #number RandomizationFactor -- @param #number StopSeconds --- @return #TIMETRIGGER -function TIMETRIGGER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds ) +-- @return #SCHEDULER +function SCHEDULER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds ) local self = BASE:Inherit( self, BASE:New() ) self:F( { TimeEventObject, TimeEventFunction, TimeEventFunctionArguments, StartSeconds, RepeatSecondsInterval, RandomizationFactor, StopSeconds } ) @@ -52,7 +52,7 @@ function TIMETRIGGER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionA self.StartTime = timer.getTime() - self:T("Calling function" .. timer.getTime() + self.StartSeconds ) + self:T("Calling function " .. timer.getTime() + self.StartSeconds ) timer.scheduleFunction( self.Scheduler, self, timer.getTime() + self.StartSeconds + .01 ) @@ -60,12 +60,27 @@ function TIMETRIGGER:New( TimeEventObject, TimeEventFunction, TimeEventFunctionA return self end -function TIMETRIGGER:Scheduler() +function SCHEDULER:Scheduler() self:F( self.TimeEventFunctionArguments ) + + local ErrorHandler = function( errmsg ) - local Result = self.TimeEventFunction( self.TimeEventObject, unpack( self.TimeEventFunctionArguments ) ) + env.info( "Error in SCHEDULER function:" .. errmsg ) + env.info( debug.traceback() ) - if Result and Result == true then + return errmsg + end + + local Status, Result + if self.TimeEventObject then + Status, Result = xpcall( function() return self.TimeEventFunction( self.TimeEventObject, unpack( self.TimeEventFunctionArguments ) ) end, ErrorHandler ) + else + Status, Result = xpcall( function() return self.TimeEventFunction( unpack( self.TimeEventFunctionArguments ) ) end, ErrorHandler ) + end + + self:T( { Status, Result } ) + + if Status and Status == true and Result and Result == true then if not self.StopSeconds or ( self.StopSeconds and timer.getTime() <= self.StartTime + self.StopSeconds ) then timer.scheduleFunction( self.Scheduler, diff --git a/Moose/Spawn.lua b/Moose/Spawn.lua index 35241ac0d..91a5af746 100644 --- a/Moose/Spawn.lua +++ b/Moose/Spawn.lua @@ -456,6 +456,8 @@ function SPAWN:SpawnWithIndex( SpawnIndex ) if self.RepeatOnEngineShutDown then _EVENTDISPATCHER:OnEngineShutDownForTemplate( self.SpawnGroups[self.SpawnIndex].SpawnTemplate, self._OnEngineShutDown, self ) end + + self:T( self.SpawnGroups[self.SpawnIndex].SpawnTemplate ) self.SpawnGroups[self.SpawnIndex].Group = _DATABASE:Spawn( self.SpawnGroups[self.SpawnIndex].SpawnTemplate ) @@ -587,6 +589,9 @@ function SPAWN:SpawnFromUnit( HostUnit, OuterRadius, InnerRadius, SpawnIndex ) if SpawnTemplate then local UnitPoint = HostUnit:GetPointVec2() + + self:T( { "Current point of ", self.SpawnTemplatePrefix, UnitPoint } ) + --for PointID, Point in pairs( SpawnTemplate.route.points ) do --Point.x = UnitPoint.x --Point.y = UnitPoint.y @@ -594,9 +599,6 @@ function SPAWN:SpawnFromUnit( HostUnit, OuterRadius, InnerRadius, SpawnIndex ) --Point.alt_type = nil --end - SpawnTemplate.route.points = nil - SpawnTemplate.route.points = {} - SpawnTemplate.route.points[1] = {} SpawnTemplate.route.points[1].x = UnitPoint.x SpawnTemplate.route.points[1].y = UnitPoint.y @@ -907,7 +909,6 @@ function SPAWN:_InitializeSpawnGroups( SpawnIndex ) self.SpawnGroups[SpawnIndex].Visible = false self.SpawnGroups[SpawnIndex].Spawned = false self.SpawnGroups[SpawnIndex].UnControlled = false - self.SpawnGroups[SpawnIndex].Spawned = false self.SpawnGroups[SpawnIndex].SpawnTime = 0 self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix = self.SpawnTemplatePrefix @@ -961,6 +962,9 @@ end --- Gets the Group Template from the ME environment definition. -- This method used the @{DATABASE} object, which contains ALL initial and new spawned object in MOOSE. +-- @param #SPAWN self +-- @param #string SpawnTemplatePrefix +-- @return @SPAWN self function SPAWN:_GetTemplate( SpawnTemplatePrefix ) self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix, SpawnTemplatePrefix } ) @@ -981,6 +985,10 @@ function SPAWN:_GetTemplate( SpawnTemplatePrefix ) end --- Prepares the new Group Template. +-- @param #SPAWN self +-- @param #string SpawnTemplatePrefix +-- @param #number SpawnIndex +-- @return #SPAWN self function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix } ) @@ -991,6 +999,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) SpawnTemplate.lateActivation = false if SpawnTemplate.SpawnCategoryID == Group.Category.GROUND then + self:T( "For ground units, visible needs to be false..." ) SpawnTemplate.visible = false end @@ -1010,7 +1019,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) end ---- Internal function randomizing the routes. +--- Private method randomizing the routes. -- @param #SPAWN self -- @param #number SpawnIndex The index of the group to be spawned. -- @return #SPAWN @@ -1034,7 +1043,10 @@ function SPAWN:_RandomizeRoute( SpawnIndex ) return self end - +--- Private method that randomizes the template of the group. +-- @param #SPAWN self +-- @param #number SpawnIndex +-- @return #SPAWN self function SPAWN:_RandomizeTemplate( SpawnIndex ) self:F( { self.SpawnTemplatePrefix, SpawnIndex } ) @@ -1044,6 +1056,7 @@ function SPAWN:_RandomizeTemplate( SpawnIndex ) self.SpawnGroups[SpawnIndex].SpawnTemplate.route = routines.utils.deepCopy( self.SpawnTemplate.route ) self.SpawnGroups[SpawnIndex].SpawnTemplate.x = self.SpawnTemplate.x self.SpawnGroups[SpawnIndex].SpawnTemplate.y = self.SpawnTemplate.y + self.SpawnGroups[SpawnIndex].SpawnTemplate.start_time = self.SpawnTemplate.start_time for UnitID = 1, #self.SpawnGroups[SpawnIndex].SpawnTemplate.units do self.SpawnGroups[SpawnIndex].SpawnTemplate.units[UnitID].heading = self.SpawnTemplate.units[1].heading end