From 87f4ebee64f0373f242ce787b065af45a9960164 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 29 Dec 2020 01:10:40 +0100 Subject: [PATCH 01/11] Clients --- Moose Development/Moose/Core/Base.lua | 31 +++++++-- Moose Development/Moose/Core/Database.lua | 71 ++++++++++----------- Moose Development/Moose/Core/Event.lua | 22 +++++++ Moose Development/Moose/Wrapper/Airbase.lua | 40 ++++++------ Moose Development/Moose/Wrapper/Client.lua | 9 ++- 5 files changed, 106 insertions(+), 67 deletions(-) diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index 0262e2759..83c78c7ce 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -765,31 +765,48 @@ function BASE:CreateEventTakeoff( EventTime, Initiator ) world.onEvent( Event ) end + --- Creation of a S_EVENT_PLAYER_ENTER_AIRCRAFT event. + -- @param #BASE self + -- @param Wrapper.Unit#UNIT PlayerUnit The aircraft unit the player entered. + function BASE:CreateEventPlayerEnterAircraft( PlayerUnit ) + self:F( { PlayerUnit } ) + + local Event = { + id = EVENTS.PlayerEnterAircraft, + time = timer.getTime(), + initiator = PlayerUnit:GetDCSObject() + } + + world.onEvent(Event) + end + -- TODO: Complete DCS#Event structure. --- The main event handling function... This function captures all events generated for the class. -- @param #BASE self -- @param DCS#Event event function BASE:onEvent(event) - --self:F( { BaseEventCodes[event.id], event } ) if self then - for EventID, EventObject in pairs( self.Events ) do + + for EventID, EventObject in pairs(self.Events) do if EventObject.EventEnabled then - --env.info( 'onEvent Table EventObject.Self = ' .. tostring(EventObject.Self) ) - --env.info( 'onEvent event.id = ' .. tostring(event.id) ) - --env.info( 'onEvent EventObject.Event = ' .. tostring(EventObject.Event) ) + if event.id == EventObject.Event then + if self == EventObject.Self then + if event.initiator and event.initiator:isExist() then event.IniUnitName = event.initiator:getName() end + if event.target and event.target:isExist() then event.TgtUnitName = event.target:getName() end - --self:T( { BaseEventCodes[event.id], event } ) - --EventObject.EventFunction( self, event ) + end + end + end end end diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 6bd87bdd8..f633848ac 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -140,37 +140,6 @@ function DATABASE:New() self.UNITS_Position = 0 - --- @param #DATABASE self - local function CheckPlayers( self ) - - local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ), AlivePlayersNeutral = coalition.getPlayers( coalition.side.NEUTRAL )} - for CoalitionId, CoalitionData in pairs( CoalitionsData ) do - --self:E( { "CoalitionData:", CoalitionData } ) - for UnitId, UnitData in pairs( CoalitionData ) do - if UnitData and UnitData:isExist() then - - local UnitName = UnitData:getName() - local PlayerName = UnitData:getPlayerName() - local PlayerUnit = UNIT:Find( UnitData ) - --self:T( { "UnitData:", UnitData, UnitName, PlayerName, PlayerUnit } ) - - if PlayerName and PlayerName ~= "" then - if self.PLAYERS[PlayerName] == nil or self.PLAYERS[PlayerName] ~= UnitName then - --self:E( { "Add player for unit:", UnitName, PlayerName } ) - self:AddPlayer( UnitName, PlayerName ) - --_EVENTDISPATCHER:CreateEventPlayerEnterUnit( PlayerUnit ) - local Settings = SETTINGS:Set( PlayerName ) - Settings:SetPlayerMenu( PlayerUnit ) - end - end - end - end - end - end - - --self:E( "Scheduling" ) - --PlayerCheckSchedule = SCHEDULER:New( nil, CheckPlayers, { self }, 1, 1 ) - return self end @@ -224,8 +193,7 @@ end --- Deletes a Static from the DATABASE based on the Static Name. -- @param #DATABASE self function DATABASE:DeleteStatic( DCSStaticName ) - - --self.STATICS[DCSStaticName] = nil + self.STATICS[DCSStaticName] = nil end --- Finds a STATIC based on the StaticName. @@ -867,7 +835,7 @@ end function DATABASE:_RegisterClients() for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do - self:T( { "Register Client:", ClientName } ) + self:I(string.format("Register Client %s", tostring(ClientName))) self:AddClient( ClientName ) end @@ -877,15 +845,15 @@ end --- @param #DATABASE self function DATABASE:_RegisterStatics() - local CoalitionsData = { GroupsRed = coalition.getStaticObjects( coalition.side.RED ), GroupsBlue = coalition.getStaticObjects( coalition.side.BLUE ) } - self:I( { Statics = CoalitionsData } ) + local CoalitionsData={GroupsRed=coalition.getStaticObjects(coalition.side.RED), GroupsBlue=coalition.getStaticObjects(coalition.side.BLUE), GroupsNeutral=coalition.getStaticObjects(coalition.side.NEUTRAL)} + for CoalitionId, CoalitionData in pairs( CoalitionsData ) do for DCSStaticId, DCSStatic in pairs( CoalitionData ) do if DCSStatic:isExist() then local DCSStaticName = DCSStatic:getName() - self:T( { "Register Static:", DCSStaticName } ) + self:I( { "Register Static:", DCSStaticName } ) self:AddStatic( DCSStaticName ) else self:E( { "Static does not exist: ", DCSStatic } ) @@ -911,9 +879,24 @@ function DATABASE:_RegisterAirbases() -- Add and register airbase. local airbase=self:AddAirbase( DCSAirbaseName ) + + -- Unique ID. + local airbaseUID=airbase:GetID(true) -- Debug output. - self:I(string.format("Register Airbase: %s, getID=%d, GetID=%d (unique=%d)", DCSAirbaseName, DCSAirbase:getID(), airbase:GetID(), airbase:GetID(true))) + local text=string.format("Register Airbase: %s (ID=%d UID=%d), category=%s, parking=%d [", tostring(DCSAirbaseName), airbaseID, airbaseUID, AIRBASE.CategoryName[airbase.category], airbase.NparkingTotal) + for _,terminalType in pairs(AIRBASE.TerminalType) do + if airbase.NparkingTerminal and airbase.NparkingTerminal[terminalType] then + text=text..string.format("%d=%d ", terminalType, airbase.NparkingTerminal[terminalType]) + end + end + text=text.."]" + self:I(text) + + -- Check for DCS bug IDs. + if airbaseID~=airbase:GetID() then + --self:E("WARNING: :getID does NOT match :GetID!") + end end @@ -945,9 +928,13 @@ function DATABASE:_EventOnBirth( Event ) end end if Event.IniObjectCategory == 1 then + Event.IniUnit = self:FindUnit( Event.IniDCSUnitName ) Event.IniGroup = self:FindGroup( Event.IniDCSGroupName ) + + -- Get player name. local PlayerName = Event.IniUnit:GetPlayerName() + if PlayerName then self:I( { "Player Joined:", PlayerName } ) self:AddClient( Event.IniDCSUnitName ) @@ -956,10 +943,16 @@ function DATABASE:_EventOnBirth( Event ) end local Settings = SETTINGS:Set( PlayerName ) Settings:SetPlayerMenu( Event.IniUnit ) - --MENU_INDEX:Refresh( Event.IniGroup ) end + + _DATABASE:CreateEventBirth(-EventTime,Initiator,IniUnitName,place,subplace) + end + end + + + end diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index 1f0b99b0a..a4a15ce44 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -192,6 +192,7 @@ world.event.S_EVENT_DELETE_ZONE = world.event.S_EVENT_MAX + 1003 world.event.S_EVENT_NEW_ZONE_GOAL = world.event.S_EVENT_MAX + 1004 world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005 world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006 +world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007 --- The different types of events supported by MOOSE. @@ -233,6 +234,7 @@ EVENTS = { NewZoneGoal = world.event.S_EVENT_NEW_ZONE_GOAL, DeleteZoneGoal = world.event.S_EVENT_DELETE_ZONE_GOAL, RemoveUnit = world.event.S_EVENT_REMOVE_UNIT, + PlayerEnterAircraft = world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT, -- Added with DCS 2.5.6 DetailedFailure = world.event.S_EVENT_DETAILED_FAILURE or -1, --We set this to -1 for backward compatibility to DCS 2.5.5 and earlier Kill = world.event.S_EVENT_KILL or -1, @@ -489,6 +491,11 @@ local _EVENTMETA = { Event = "OnEventRemoveUnit", Text = "S_EVENT_REMOVE_UNIT" }, + [EVENTS.PlayerEnterAircraft] = { + Order = 1, + Event = "OnEventPlayerEnterAircraft", + Text = "S_EVENT_PLAYER_ENTER_AIRCRAFT" + }, -- Added with DCS 2.5.6 [EVENTS.DetailedFailure] = { Order = 1, @@ -914,6 +921,21 @@ do -- Event Creation world.onEvent( Event ) end + + --- Creation of a S_EVENT_PLAYER_ENTER_AIRCRAFT event. + -- @param #EVENT self + -- @param Wrapper.Unit#UNIT PlayerUnit The aircraft unit the player entered. + function EVENT:CreateEventPlayerEnterAircraft( PlayerUnit ) + self:F( { PlayerUnit } ) + + local Event = { + id = EVENTS.PlayerEnterAircraft, + time = timer.getTime(), + initiator = PlayerUnit:GetDCSObject() + } + + world.onEvent( Event ) + end end diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 74097fd5c..078d8069f 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -829,25 +829,27 @@ function AIRBASE:_InitParkingSpots() -- Put coordinates of parking spots into table. for _,spot in pairs(parkingdata) do - -- New parking spot. - local park={} --#AIRBASE.ParkingSpot - park.Vec3=spot.vTerminalPos - park.Coordinate=COORDINATE:NewFromVec3(spot.vTerminalPos) - park.DistToRwy=spot.fDistToRW - park.Free=nil - park.TerminalID=spot.Term_Index - park.TerminalID0=spot.Term_Index_0 - park.TerminalType=spot.Term_Type - park.TOAC=spot.TO_AC - - for _,terminalType in pairs(AIRBASE.TerminalType) do - if self._CheckTerminalType(terminalType, park.TerminalType) then - self.NparkingTerminal[terminalType]=self.NparkingTerminal[terminalType]+1 - end - end - - self.parkingByID[park.TerminalID]=park - table.insert(self.parking, park) + -- New parking spot. + local park={} --#AIRBASE.ParkingSpot + park.Vec3=spot.vTerminalPos + park.Coordinate=COORDINATE:NewFromVec3(spot.vTerminalPos) + park.DistToRwy=spot.fDistToRW + park.Free=nil + park.TerminalID=spot.Term_Index + park.TerminalID0=spot.Term_Index_0 + park.TerminalType=spot.Term_Type + park.TOAC=spot.TO_AC + + self.NparkingTotal=self.NparkingTotal+1 + + for _,terminalType in pairs(AIRBASE.TerminalType) do + if self._CheckTerminalType(terminalType, park.TerminalType) then + self.NparkingTerminal[terminalType]=self.NparkingTerminal[terminalType]+1 + end + end + + self.parkingByID[park.TerminalID]=park + table.insert(self.parking, park) end return self diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 4e6cce0de..64e42950d 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -117,6 +117,8 @@ end -- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*HOT-Deploy Troops 2' ):Transport() ) -- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 4' ):Transport() ) function CLIENT:FindByName( ClientName, ClientBriefing, Error ) + + -- Client local ClientFound = _DATABASE:FindClient( ClientName ) if ClientFound then @@ -132,6 +134,10 @@ function CLIENT:FindByName( ClientName, ClientBriefing, Error ) end end +--- Transport defines that the Client is a Transport. Transports show cargo. +-- @param #CLIENT self +-- @param #string ClientName Name of the client unit. +-- @return #CLIENT function CLIENT:Register( ClientName ) local self = BASE:Inherit( self, UNIT:Register( ClientName ) ) -- #CLIENT @@ -204,8 +210,6 @@ function CLIENT:ShowMissionBriefing( MissionBriefing ) return self end - - --- Resets a CLIENT. -- @param #CLIENT self -- @param #string ClientName Name of the Group as defined within the Mission Editor. The Group must have a Unit with the type Client. @@ -291,6 +295,7 @@ function CLIENT:GetDCSGroup() local ClientUnit = Unit.getByName( self.ClientName ) local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) } + for CoalitionId, CoalitionData in pairs( CoalitionsData ) do self:T3( { "CoalitionData:", CoalitionData } ) for UnitId, UnitData in pairs( CoalitionData ) do From f725039da5865a769871524be890f8b4773efa15 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 31 Dec 2020 00:51:54 +0100 Subject: [PATCH 02/11] Client and Event updates --- Moose Development/Moose/Core/Base.lua | 9 +- Moose Development/Moose/Core/Database.lua | 99 +++++++++++++++------- Moose Development/Moose/Core/Event.lua | 9 +- Moose Development/Moose/Wrapper/Client.lua | 8 +- 4 files changed, 87 insertions(+), 38 deletions(-) diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index 83c78c7ce..4398c6d1a 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -676,6 +676,13 @@ do -- Event Handling -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. + --- Occurs when a player enters a slot and takes control of an aircraft. + -- **NOTE**: This is a workaround of a long standing DCS bug with the PLAYER_ENTER_UNIT event. + -- initiator : The unit that is being taken control of. + -- @function [parent=#BASE] OnEventPlayerEnterAircraft + -- @param #BASE self + -- @param Core.Event#EVENTDATA EventData The EventData structure. + end @@ -765,7 +772,7 @@ function BASE:CreateEventTakeoff( EventTime, Initiator ) world.onEvent( Event ) end - --- Creation of a S_EVENT_PLAYER_ENTER_AIRCRAFT event. + --- Creation of a `S_EVENT_PLAYER_ENTER_AIRCRAFT` event. -- @param #BASE self -- @param Wrapper.Unit#UNIT PlayerUnit The aircraft unit the player entered. function BASE:CreateEventPlayerEnterAircraft( PlayerUnit ) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index f633848ac..9a9f0c738 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -24,7 +24,7 @@ -- === -- -- ### Author: **FlightControl** --- ### Contributions: +-- ### Contributions: **funkyfranky** -- -- === -- @@ -33,6 +33,9 @@ --- @type DATABASE +-- @field #string ClassName Name of the class. +-- @field #table Templates Templates: Units, Groups, Statics, ClientsByName, ClientsByID. +-- @field #table CLIENTS Clients. -- @extends Core.Base#BASE --- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator. @@ -126,8 +129,6 @@ function DATABASE:New() self:HandleEvent( EVENTS.DeleteCargo ) self:HandleEvent( EVENTS.NewZone ) self:HandleEvent( EVENTS.DeleteZone ) - - -- Follow alive players and clients --self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event. self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit ) @@ -135,8 +136,8 @@ function DATABASE:New() self:_RegisterGroupsAndUnits() self:_RegisterClients() self:_RegisterStatics() - --self:_RegisterPlayers() self:_RegisterAirbases() + --self:_RegisterPlayers() self.UNITS_Position = 0 @@ -156,14 +157,22 @@ end --- Adds a Unit based on the Unit Name in the DATABASE. -- @param #DATABASE self +-- @param #string DCSUnitName Unit name. +-- @return Wrapper.Unit#UNIT The added unit. function DATABASE:AddUnit( DCSUnitName ) - if not self.UNITS[DCSUnitName] then + if not self.UNITS[DCSUnitName] then + + -- Debug info. self:T( { "Add UNIT:", DCSUnitName } ) - local UnitRegister = UNIT:Register( DCSUnitName ) - self.UNITS[DCSUnitName] = UNIT:Register( DCSUnitName ) + + --local UnitRegister = UNIT:Register( DCSUnitName ) + + -- Register unit + self.UNITS[DCSUnitName]=UNIT:Register(DCSUnitName) - table.insert( self.UNITS_Index, DCSUnitName ) + -- This is not used anywhere in MOOSE as far as I can see so I remove it until there comes an error somewhere. + --table.insert(self.UNITS_Index, DCSUnitName ) end return self.UNITS[DCSUnitName] @@ -179,6 +188,8 @@ end --- Adds a Static based on the Static Name in the DATABASE. -- @param #DATABASE self +-- @param #string DCSStaticName Name of the static. +-- @return Wrapper.Static#STATIC The static object. function DATABASE:AddStatic( DCSStaticName ) if not self.STATICS[DCSStaticName] then @@ -594,6 +605,9 @@ function DATABASE:Spawn( SpawnTemplate ) end --- Set a status to a Group within the Database, this to check crossing events for example. +-- @param #DATABASE self +-- @param #string GroupName Group name. +-- @param #string Status Status. function DATABASE:SetStatusGroup( GroupName, Status ) self:F2( Status ) @@ -601,8 +615,11 @@ function DATABASE:SetStatusGroup( GroupName, Status ) end --- Get a status to a Group within the Database, this to check crossing events for example. +-- @param #DATABASE self +-- @param #string GroupName Group name. +-- @return #string Status or an empty string "". function DATABASE:GetStatusGroup( GroupName ) - self:F2( Status ) + self:F2( GroupName ) if self.Templates.Groups[GroupName] then return self.Templates.Groups[GroupName].Status @@ -616,7 +633,8 @@ end -- @param #table GroupTemplate -- @param DCS#coalition.side CoalitionSide The coalition.side of the object. -- @param DCS#Object.Category CategoryID The Object.category of the object. --- @param DCS#country.id CountryID the country.id of the object +-- @param DCS#country.id CountryID the country ID of the object. +-- @param #string GroupName (Optional) The name of the group. Default is `GroupTemplate.name`. -- @return #DATABASE self function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID, GroupName ) @@ -681,6 +699,10 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category ) end +--- Get group template. +-- @param #DATABASE self +-- @param #string GroupName Group name. +-- @return #table Group template table. function DATABASE:GetGroupTemplate( GroupName ) local GroupTemplate = self.Templates.Groups[GroupName].Template GroupTemplate.SpawnCoalitionID = self.Templates.Groups[GroupName].CoalitionID @@ -691,7 +713,10 @@ end --- Private method that registers new Static Templates within the DATABASE Object. -- @param #DATABASE self --- @param #table StaticTemplate +-- @param #table StaticTemplate Template table. +-- @param #number CoalitionID Coalition ID. +-- @param #number CategoryID Category ID. +-- @param #number CountryID Country ID. -- @return #DATABASE self function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID ) @@ -721,10 +746,13 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category self:AddStatic( StaticTemplateName ) + return self end - ---- @param #DATABASE self +--- Get static group template. +-- @param #DATABASE self +-- @param #string StaticName Name of the static +-- @return #table Static template table. function DATABASE:GetStaticGroupTemplate( StaticName ) local StaticTemplate = self.Templates.Statics[StaticName].GroupTemplate return StaticTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID @@ -913,20 +941,28 @@ function DATABASE:_EventOnBirth( Event ) self:F( { Event } ) if Event.IniDCSUnit then + if Event.IniObjectCategory == 3 then + self:AddStatic( Event.IniDCSUnitName ) + else + if Event.IniObjectCategory == 1 then + self:AddUnit( Event.IniDCSUnitName ) self:AddGroup( Event.IniDCSGroupName ) + -- Add airbase if it was spawned later in the mission. local DCSAirbase = Airbase.getByName(Event.IniDCSUnitName) if DCSAirbase then self:I(string.format("Adding airbase %s", tostring(Event.IniDCSUnitName))) self:AddAirbase(Event.IniDCSUnitName) end + end end + if Event.IniObjectCategory == 1 then Event.IniUnit = self:FindUnit( Event.IniDCSUnitName ) @@ -936,17 +972,28 @@ function DATABASE:_EventOnBirth( Event ) local PlayerName = Event.IniUnit:GetPlayerName() if PlayerName then - self:I( { "Player Joined:", PlayerName } ) + + -- Debug info. + self:I(string.format("Player %s joint unit %s of group %s", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName))) + + -- Add client. self:AddClient( Event.IniDCSUnitName ) + + -- Add player. if not self.PLAYERS[PlayerName] then self:AddPlayer( Event.IniUnitName, PlayerName ) end + + -- Player settings. local Settings = SETTINGS:Set( PlayerName ) - Settings:SetPlayerMenu( Event.IniUnit ) + Settings:SetPlayerMenu(Event.IniUnit) + end - _DATABASE:CreateEventBirth(-EventTime,Initiator,IniUnitName,place,subplace) - + if PlayerName or self.CLIENTS[Event.IniDCSUnitName] then + self:CreateEventPlayerEnterAircraft(Event.IniUnit) + end + end end @@ -1348,19 +1395,13 @@ function DATABASE:_RegisterTemplates() for group_num, Template in pairs(obj_type_data.group) do if obj_type_name ~= "static" and Template and Template.units and type(Template.units) == 'table' then --making sure again- this is a valid group - self:_RegisterGroupTemplate( - Template, - CoalitionSide, - _DATABASECategory[string.lower(CategoryName)], - CountryID - ) + + self:_RegisterGroupTemplate(Template, CoalitionSide, _DATABASECategory[string.lower(CategoryName)], CountryID) + else - self:_RegisterStaticTemplate( - Template, - CoalitionSide, - _DATABASECategory[string.lower(CategoryName)], - CountryID - ) + + self:_RegisterStaticTemplate(Template, CoalitionSide, _DATABASECategory[string.lower(CategoryName)], CountryID) + 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/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index a4a15ce44..6a7960748 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -646,7 +646,7 @@ end -- @param #function EventFunction The function to be called when the event occurs for the unit. -- @param EventClass The instance of the class for which the event is. -- @param #function OnEventFunction --- @return #EVENT +-- @return #EVENT self function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EventID ) self:F2( EventTemplate.name ) @@ -693,8 +693,9 @@ end -- @param #string GroupName The name of the GROUP. -- @param #function EventFunction The function to be called when the event occurs for the GROUP. -- @param Core.Base#BASE EventClass The self instance of the class for which the event is. --- @param EventID --- @return #EVENT +-- @param #number EventID Event ID. +-- @param ... Optional arguments passed to the event function. +-- @return #EVENT self function EVENT:OnEventForGroup( GroupName, EventFunction, EventClass, EventID, ... ) local Event = self:Init( EventID, EventClass ) @@ -711,7 +712,7 @@ do -- OnBirth -- @param Wrapper.Group#GROUP EventGroup -- @param #function EventFunction The function to be called when the event occurs for the unit. -- @param EventClass The self instance of the class for which the event is. - -- @return #EVENT + -- @return #EVENT self function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventClass ) self:F2( EventTemplate.name ) diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 64e42950d..2100d698b 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -66,8 +66,7 @@ CLIENT = { ClientBriefingShown = false, _Menus = {}, _Tasks = {}, - Messages = { - } + Messages = {}, } @@ -137,7 +136,7 @@ end --- Transport defines that the Client is a Transport. Transports show cargo. -- @param #CLIENT self -- @param #string ClientName Name of the client unit. --- @return #CLIENT +-- @return #CLIENT self function CLIENT:Register( ClientName ) local self = BASE:Inherit( self, UNIT:Register( ClientName ) ) -- #CLIENT @@ -158,7 +157,7 @@ end --- Transport defines that the Client is a Transport. Transports show cargo. -- @param #CLIENT self --- @return #CLIENT +-- @return #CLIENT self function CLIENT:Transport() self:F() @@ -245,6 +244,7 @@ end --- Checks for a client alive event and calls a function on a continuous basis. -- @param #CLIENT self -- @param #function CallBackFunction Create a function that will be called when a player joins the slot. +-- @param ... (Optional) Arguments for callback function as comma separated list. -- @return #CLIENT function CLIENT:Alive( CallBackFunction, ... ) self:F() From 787151597c7fe36f08c23426fc9a42ca5045994a Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 31 Dec 2020 17:17:15 +0100 Subject: [PATCH 03/11] Client --- Moose Development/Moose/Core/Database.lua | 29 ++++++--- Moose Development/Moose/Wrapper/Client.lua | 68 +++++++++++++++++----- 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 9a9f0c738..47389e7a6 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -468,6 +468,8 @@ end --- Adds a CLIENT based on the ClientName in the DATABASE. -- @param #DATABASE self +-- @param #string ClientName Name of the Client unit. +-- @return Wrapper.Client#CLIENT The client object. function DATABASE:AddClient( ClientName ) if not self.CLIENTS[ClientName] then @@ -863,7 +865,7 @@ end function DATABASE:_RegisterClients() for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do - self:I(string.format("Register Client %s", tostring(ClientName))) + self:I(string.format("Register Client: %s", tostring(ClientName))) self:AddClient( ClientName ) end @@ -967,6 +969,13 @@ function DATABASE:_EventOnBirth( Event ) Event.IniUnit = self:FindUnit( Event.IniDCSUnitName ) Event.IniGroup = self:FindGroup( Event.IniDCSGroupName ) + + -- TODO: create event ClientAlive + local client=self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT + + if client then + + end -- Get player name. local PlayerName = Event.IniUnit:GetPlayerName() @@ -974,10 +983,15 @@ function DATABASE:_EventOnBirth( Event ) if PlayerName then -- Debug info. - self:I(string.format("Player %s joint unit %s of group %s", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName))) + self:I(string.format("Player '%s' joint unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName))) - -- Add client. - self:AddClient( Event.IniDCSUnitName ) + -- Add client in case it does not exist already. + if not client then + client=self:AddClient(Event.IniDCSUnitName) + end + + -- Add player. + client:AddPlayer(PlayerName) -- Add player. if not self.PLAYERS[PlayerName] then @@ -988,12 +1002,11 @@ function DATABASE:_EventOnBirth( Event ) local Settings = SETTINGS:Set( PlayerName ) Settings:SetPlayerMenu(Event.IniUnit) + -- Create an event. + self:CreateEventPlayerEnterAircraft(Event.IniUnit) + end - if PlayerName or self.CLIENTS[Event.IniDCSUnitName] then - self:CreateEventPlayerEnterAircraft(Event.IniUnit) - end - end end diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 2100d698b..8caea77d5 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -67,6 +67,7 @@ CLIENT = { _Menus = {}, _Tasks = {}, Messages = {}, + Players = {}, } @@ -145,12 +146,7 @@ function CLIENT:Register( ClientName ) self.ClientName = ClientName self.MessageSwitch = true self.ClientAlive2 = false - - --self.AliveCheckScheduler = routines.scheduleFunction( self._AliveCheckScheduler, { self }, timer.getTime() + 1, 5 ) - self.AliveCheckScheduler = SCHEDULER:New( self, self._AliveCheckScheduler, { "Client Alive " .. ClientName }, 1, 5, 0.5 ) - self.AliveCheckScheduler:NoTrace() - self:F( self ) return self end @@ -159,29 +155,68 @@ end -- @param #CLIENT self -- @return #CLIENT self function CLIENT:Transport() - self:F() - self.ClientTransport = true return self end ---- AddBriefing adds a briefing to a CLIENT when a player joins a mission. +--- Adds a briefing to a CLIENT when a player joins a mission. -- @param #CLIENT self -- @param #string ClientBriefing is the text defining the Mission briefing. -- @return #CLIENT self function CLIENT:AddBriefing( ClientBriefing ) - self:F( ClientBriefing ) + self.ClientBriefing = ClientBriefing self.ClientBriefingShown = false return self end +--- Add player name. +-- @param #CLIENT self +-- @param #string PlayerName Name of the player. +-- @return #CLIENT self +function CLIENT:AddPlayer(PlayerName) + + table.insert(self.Players, PlayerName) + + return self +end + +--- Get player name(s). +-- @param #CLIENT self +-- @return #table List of player names. +function CLIENT:GetPlayers() + return self.Players +end + +--- Get name of player. +-- @param #CLIENT self +-- @return # +function CLIENT:GetPlayer() + return self.Players[1] +end + +--- Remove player. +-- @param #CLIENT self +-- @param #string PlayerName Name of the player. +-- @return #CLIENT self +function CLIENT:RemovePlayer(PlayerName) + + for i,playername in pairs(self.Players) do + if PlayerName==playername then + table.remove(self.Players, i) + break + end + end + + return self +end + + --- Show the briefing of a CLIENT. -- @param #CLIENT self -- @return #CLIENT self function CLIENT:ShowBriefing() - self:F( { self.ClientName, self.ClientBriefingShown } ) if not self.ClientBriefingShown then self.ClientBriefingShown = true @@ -252,6 +287,9 @@ function CLIENT:Alive( CallBackFunction, ... ) self.ClientCallBack = CallBackFunction self.ClientParameters = arg + self.AliveCheckScheduler = SCHEDULER:New( self, self._AliveCheckScheduler, { "Client Alive " .. self.ClientName }, 0.1, 5, 0.5 ) + self.AliveCheckScheduler:NoTrace() + return self end @@ -259,6 +297,8 @@ end function CLIENT:_AliveCheckScheduler( SchedulerName ) self:F3( { SchedulerName, self.ClientName, self.ClientAlive2, self.ClientBriefingShown, self.ClientCallBack } ) + env.info("FF client alive scheduler") + if self:IsAlive() then if self.ClientAlive2 == false then self:ShowBriefing() @@ -388,11 +428,13 @@ function CLIENT:GetClientGroupUnit() local ClientDCSUnit = Unit.getByName( self.ClientName ) self:T( self.ClientDCSUnit ) - if ClientDCSUnit and ClientDCSUnit:isExist() then - local ClientUnit = _DATABASE:FindUnit( self.ClientName ) - self:T2( ClientUnit ) + + if ClientDCSUnit then -- and ClientDCSUnit:isExist() then + local ClientUnit=_DATABASE:FindUnit( self.ClientName ) return ClientUnit end + + return nil end --- Returns the DCSUnit of the CLIENT. From c0fc649f8b73d6ea1e93ae491cd05af1098d98f6 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 1 Jan 2021 01:46:14 +0100 Subject: [PATCH 04/11] Client --- Moose Development/Moose/Cargo/CargoGroup.lua | 3 ++ Moose Development/Moose/Core/Database.lua | 50 +++++++++++++++----- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/Moose Development/Moose/Cargo/CargoGroup.lua b/Moose Development/Moose/Cargo/CargoGroup.lua index 2d356f270..4a55946e3 100644 --- a/Moose Development/Moose/Cargo/CargoGroup.lua +++ b/Moose Development/Moose/Cargo/CargoGroup.lua @@ -78,6 +78,9 @@ do -- CARGO_GROUP local GroupName = CargoGroup:GetName() self.CargoName = Name self.CargoTemplate = UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ) ) + + -- Deactivate late activation. + self.CargoTemplate.lateActivation=false self.GroupTemplate = UTILS.DeepCopy( self.CargoTemplate ) self.GroupTemplate.name = self.CargoName .. "#CARGO" diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 47389e7a6..91259c8b7 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -692,6 +692,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category UnitNames[#UnitNames+1] = self.Templates.Units[UnitTemplate.name].UnitName end + -- Debug info. self:T( { Group = self.Templates.Groups[GroupTemplateName].GroupName, Coalition = self.Templates.Groups[GroupTemplateName].CoalitionID, Category = self.Templates.Groups[GroupTemplateName].CategoryID, @@ -739,7 +740,8 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category self.Templates.Statics[StaticTemplateName].CoalitionID = CoalitionID self.Templates.Statics[StaticTemplateName].CountryID = CountryID - self:I( { Static = self.Templates.Statics[StaticTemplateName].StaticName, + -- Debug info. + self:T( { Static = self.Templates.Statics[StaticTemplateName].StaticName, Coalition = self.Templates.Statics[StaticTemplateName].CoalitionID, Category = self.Templates.Statics[StaticTemplateName].CategoryID, Country = self.Templates.Statics[StaticTemplateName].CountryID @@ -829,33 +831,38 @@ end function DATABASE:_RegisterGroupsAndUnits() local CoalitionsData = { GroupsRed = coalition.getGroups( coalition.side.RED ), GroupsBlue = coalition.getGroups( coalition.side.BLUE ), GroupsNeutral = coalition.getGroups( coalition.side.NEUTRAL ) } + for CoalitionId, CoalitionData in pairs( CoalitionsData ) do + for DCSGroupId, DCSGroup in pairs( CoalitionData ) do if DCSGroup:isExist() then + + -- Group name. local DCSGroupName = DCSGroup:getName() - self:I( { "Register Group:", DCSGroupName } ) + -- Add group. + self:I(string.format("Register Group: %s", tostring(DCSGroupName))) self:AddGroup( DCSGroupName ) + -- Loop over units in group. for DCSUnitId, DCSUnit in pairs( DCSGroup:getUnits() ) do + -- Get unit name. local DCSUnitName = DCSUnit:getName() - self:I( { "Register Unit:", DCSUnitName } ) + + -- Add unit. + self:I(string.format("Register Unit: %s", tostring(DCSUnitName))) self:AddUnit( DCSUnitName ) + end else - self:E( { "Group does not exist: ", DCSGroup } ) + self:E({"Group does not exist: ", DCSGroup}) end end end - self:T("Groups:") - for GroupName, Group in pairs( self.GROUPS ) do - self:T( { "Group:", GroupName } ) - end - return self end @@ -1069,13 +1076,30 @@ function DATABASE:_EventOnPlayerLeaveUnit( Event ) self:F2( { Event } ) if Event.IniUnit then + if Event.IniObjectCategory == 1 then + + -- Try to get the player name. This can be buggy for multicrew aircraft! local PlayerName = Event.IniUnit:GetPlayerName() - if PlayerName and self.PLAYERS[PlayerName] then - self:I( { "Player Left:", PlayerName } ) + + if PlayerName then --and self.PLAYERS[PlayerName] then + + -- Debug info. + self:I(string.format("Player '%s' left unit %s", tostring(PlayerName), tostring(Event.IniUnitName))) + + -- Remove player menu. local Settings = SETTINGS:Set( PlayerName ) - Settings:RemovePlayerMenu( Event.IniUnit ) - self:DeletePlayer( Event.IniUnit, PlayerName ) + Settings:RemovePlayerMenu(Event.IniUnit) + + -- Delete player. + self:DeletePlayer(Event.IniUnit, PlayerName) + + -- Client stuff. + local client=self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT + if client then + client:RemovePlayer(PlayerName) + end + end end end From 721d027fb36400333d93ee8a52ca744fa13561bd Mon Sep 17 00:00:00 2001 From: Applevangelist <72444570+Applevangelist@users.noreply.github.com> Date: Fri, 1 Jan 2021 16:37:55 +0100 Subject: [PATCH 05/11] Update AI_Cargo_Helicopter.lua MI-26 is slightly over 5m blocking boarding of Cargo --- Moose Development/Moose/AI/AI_Cargo_Helicopter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua index 4b838fde5..8851cc6c9 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua @@ -243,7 +243,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To ) self:F( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } ) if self.RoutePickup == true then - if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then + if Helicopter:GetHeight( true ) <= 5.5 and Helicopter:GetVelocityKMH() < 10 then --self:Load( Helicopter:GetPointVec2() ) self:Load( self.PickupZone ) self.RoutePickup = false From 774c8971c8badf02c70280d1b8c3e6899639134a Mon Sep 17 00:00:00 2001 From: Applevangelist <72444570+Applevangelist@users.noreply.github.com> Date: Fri, 1 Jan 2021 17:24:00 +0100 Subject: [PATCH 06/11] Update AI_Cargo_Helicopter.lua Fixed FSM dead ends --- Moose Development/Moose/AI/AI_Cargo_Helicopter.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua index 8851cc6c9..fe8998093 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua @@ -62,7 +62,6 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet ) local self = BASE:Inherit( self, AI_CARGO:New( Helicopter, CargoSet ) ) -- #AI_CARGO_HELICOPTER self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 ) - self:SetStartState( "Unloaded" ) self:AddTransition( "Unloaded", "Pickup", "*" ) @@ -72,11 +71,13 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet ) self:AddTransition( "Boarding", "Board", "Boarding" ) self:AddTransition( "Boarding", "Loaded", "Boarding" ) self:AddTransition( "Boarding", "PickedUp", "Loaded" ) + self:AddTransition( "Boarding", "Deploy", "Loaded" ) self:AddTransition( "Loaded", "Unload", "Unboarding" ) self:AddTransition( "Unboarding", "Unboard", "Unboarding" ) self:AddTransition( "Unboarding", "Unloaded", "Unboarding" ) self:AddTransition( "Unboarding", "Deployed", "Unloaded" ) - + self:AddTransition( "Unboarding", "Pickup", "Unloaded" ) + self:AddTransition( "*", "Landed", "*" ) self:AddTransition( "*", "Queue", "*" ) self:AddTransition( "*", "Orbit" , "*" ) @@ -251,7 +252,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To ) end if self.RouteDeploy == true then - if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then + if Helicopter:GetHeight( true ) <= 5.5 and Helicopter:GetVelocityKMH() < 10 then self:Unload( self.DeployZone ) self.RouteDeploy = false end @@ -622,4 +623,3 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat end end - From 7b7605e50131cadc6cbfe0a4ed39a9dcb925f018 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 2 Jan 2021 01:21:45 +0100 Subject: [PATCH 07/11] Client --- Moose Development/Moose/Wrapper/Client.lua | 102 ++++++++++++--------- Moose Development/Moose/Wrapper/Unit.lua | 8 +- 2 files changed, 65 insertions(+), 45 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 8caea77d5..39f6af974 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -3,8 +3,7 @@ -- === -- -- ### Author: **FlightControl** --- --- ### Contributions: +-- ### Contributions: **funkyfranky** -- -- === -- @@ -52,13 +51,6 @@ -- -- @field #CLIENT CLIENT = { - ONBOARDSIDE = { - NONE = 0, - LEFT = 1, - RIGHT = 2, - BACK = 3, - FRONT = 4 - }, ClassName = "CLIENT", ClientName = nil, ClientAlive = false, @@ -73,20 +65,13 @@ CLIENT = { --- Finds a CLIENT from the _DATABASE using the relevant DCS Unit. -- @param #CLIENT self --- @param #string ClientName Name of the DCS **Unit** as defined within the Mission Editor. --- @param #string ClientBriefing Text that describes the briefing of the mission when a Player logs into the Client. --- @return #CLIENT --- @usage --- -- Create new Clients. --- local Mission = MISSIONSCHEDULER.AddMission( 'Russia Transport Troops SA-6', 'Operational', 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.', 'Russia' ) --- Mission:AddGoal( DeploySA6TroopsGoal ) --- --- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*HOT-Deploy Troops 1' ):Transport() ) --- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 3' ):Transport() ) --- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*HOT-Deploy Troops 2' ):Transport() ) --- Mission:AddClient( CLIENT:FindByName( 'RU MI-8MTV2*RAMP-Deploy Troops 4' ):Transport() ) -function CLIENT:Find( DCSUnit, Error ) +-- @param DCS#Unit DCSUnit The DCS unit of the client. +-- @param #boolean Error Throw an error message. +-- @return #CLIENT The CLIENT found in the _DATABASE. +function CLIENT:Find(DCSUnit, Error) + local ClientName = DCSUnit:getName() + local ClientFound = _DATABASE:FindClient( ClientName ) if ClientFound then @@ -123,7 +108,9 @@ function CLIENT:FindByName( ClientName, ClientBriefing, Error ) if ClientFound then ClientFound:F( { ClientName, ClientBriefing } ) - ClientFound:AddBriefing( ClientBriefing ) + + ClientFound:AddBriefing(ClientBriefing) + ClientFound.MessageSwitch = true return ClientFound @@ -138,13 +125,18 @@ end -- @param #CLIENT self -- @param #string ClientName Name of the client unit. -- @return #CLIENT self -function CLIENT:Register( ClientName ) +function CLIENT:Register(ClientName) - local self = BASE:Inherit( self, UNIT:Register( ClientName ) ) -- #CLIENT - - self:F( ClientName ) + -- Inherit unit. + local self = BASE:Inherit( self, UNIT:Register(ClientName )) -- #CLIENT + + -- Set client name. self.ClientName = ClientName + + -- Message switch. self.MessageSwitch = true + + -- Alive2. self.ClientAlive2 = false return self @@ -184,16 +176,19 @@ end --- Get player name(s). -- @param #CLIENT self --- @return #table List of player names. +-- @return #table List of player names or an empty table `{}`. function CLIENT:GetPlayers() return self.Players end --- Get name of player. -- @param #CLIENT self --- @return # +-- @return #string Player name or `nil`. function CLIENT:GetPlayer() - return self.Players[1] + if #self.Players>0 then + return self.Players[1] + end + return nil end --- Remove player. @@ -297,21 +292,29 @@ end function CLIENT:_AliveCheckScheduler( SchedulerName ) self:F3( { SchedulerName, self.ClientName, self.ClientAlive2, self.ClientBriefingShown, self.ClientCallBack } ) - env.info("FF client alive scheduler") - - if self:IsAlive() then + if self:IsAlive() then + if self.ClientAlive2 == false then + + -- Show briefing. self:ShowBriefing() + + -- Callback function. if self.ClientCallBack then self:T("Calling Callback function") self.ClientCallBack( self, unpack( self.ClientParameters ) ) end + + -- Alive. self.ClientAlive2 = true end + else + if self.ClientAlive2 == true then self.ClientAlive2 = false end + end return true @@ -344,10 +347,14 @@ function CLIENT:GetDCSGroup() --self:F(self.ClientName) if ClientUnit then + local ClientGroup = ClientUnit:getGroup() + if ClientGroup then self:T3( "ClientGroup = " .. self.ClientName ) - if ClientGroup:isExist() and UnitData:getGroup():isExist() then + + if ClientGroup:isExist() and UnitData:getGroup():isExist() then + if ClientGroup:getID() == UnitData:getGroup():getID() then self:T3( "Normal logic" ) self:T3( self.ClientName .. " : group found!" ) @@ -355,15 +362,22 @@ function CLIENT:GetDCSGroup() self.ClientGroupName = ClientGroup:getName() return ClientGroup end + else + -- Now we need to resolve the bugs in DCS 1.5 ... -- Consult the database for the units of the Client Group. (ClientGroup:getUnits() returns nil) self:T3( "Bug 1.5 logic" ) + local ClientGroupTemplate = _DATABASE.Templates.Units[self.ClientName].GroupTemplate + self.ClientGroupID = ClientGroupTemplate.groupId + self.ClientGroupName = _DATABASE.Templates.Units[self.ClientName].GroupName + self:T3( self.ClientName .. " : group found in bug 1.5 resolvement logic!" ) return ClientGroup + end -- else -- error( "Client " .. self.ClientName .. " not found!" ) @@ -388,22 +402,22 @@ function CLIENT:GetDCSGroup() end end + -- Nothing could be found :( self.ClientGroupID = nil - self.ClientGroupUnit = nil + self.ClientGroupName = nil return nil end --- TODO: Check DCS#Group.ID --- Get the group ID of the client. -- @param #CLIENT self --- @return DCS#Group.ID +-- @return #number DCS#Group ID. function CLIENT:GetClientGroupID() - local ClientGroup = self:GetDCSGroup() + -- This updates the ID. + self:GetDCSGroup() - --self:F( self.ClientGroupID ) -- Determined in GetDCSGroup() return self.ClientGroupID end @@ -413,15 +427,15 @@ end -- @return #string function CLIENT:GetClientGroupName() - local ClientGroup = self:GetDCSGroup() - - self:T( self.ClientGroupName ) -- Determined in GetDCSGroup() + -- This updates the group name. + self:GetDCSGroup() + return self.ClientGroupName end --- Returns the UNIT of the CLIENT. -- @param #CLIENT self --- @return Wrapper.Unit#UNIT +-- @return Wrapper.Unit#UNIT The client UNIT or `nil`. function CLIENT:GetClientGroupUnit() self:F2() @@ -429,7 +443,7 @@ function CLIENT:GetClientGroupUnit() self:T( self.ClientDCSUnit ) - if ClientDCSUnit then -- and ClientDCSUnit:isExist() then + if ClientDCSUnit and ClientDCSUnit:isExist() then local ClientUnit=_DATABASE:FindUnit( self.ClientName ) return ClientUnit end diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index cbbc924d4..739c42649 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -103,12 +103,18 @@ UNIT = { --- Create a new UNIT from DCSUnit. -- @param #UNIT self -- @param #string UnitName The name of the DCS unit. --- @return #UNIT +-- @return #UNIT self function UNIT:Register( UnitName ) + + -- Inherit CONTROLLABLE. local self = BASE:Inherit( self, CONTROLLABLE:New( UnitName ) ) + + -- Set unit name. self.UnitName = UnitName + -- Set event prio. self:SetEventPriority( 3 ) + return self end From 5b2e67df194a047fc6e9fc9a932e53dd33de02e1 Mon Sep 17 00:00:00 2001 From: Applevangelist <72444570+Applevangelist@users.noreply.github.com> Date: Sat, 2 Jan 2021 18:53:58 +0100 Subject: [PATCH 08/11] Update AI_Cargo.lua Some small additions from learnings from AI CARGO HELI --- Moose Development/Moose/AI/AI_Cargo.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua index 586c0ab51..a5a08b2e7 100644 --- a/Moose Development/Moose/AI/AI_Cargo.lua +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -393,7 +393,7 @@ end function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, PickupZone ) self:F( { Carrier, From, Event, To, Cargo, CarrierUnit:GetName() } ) - if Carrier and Carrier:IsAlive() then + if Carrier and Carrier:IsAlive() and From == "Boarding" then self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } ) if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then self:__Board( -10, Cargo, CarrierUnit, PickupZone ) @@ -509,7 +509,7 @@ end function AI_CARGO:onafterUnboard( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone, Defend ) self:F( { Carrier, From, Event, To, Cargo:GetName(), DeployZone = DeployZone, Defend = Defend } ) - if Carrier and Carrier:IsAlive() then + if Carrier and Carrier:IsAlive() and From == "Unboarding" then if not Cargo:IsUnLoaded() then self:__Unboard( 10, Cargo, CarrierUnit, DeployZone, Defend ) return From c51a65f0587b7f2ceb9b099d37bc404c99a88984 Mon Sep 17 00:00:00 2001 From: Applevangelist <72444570+Applevangelist@users.noreply.github.com> Date: Sat, 2 Jan 2021 18:56:27 +0100 Subject: [PATCH 09/11] Update AI_Cargo_Helicopter.lua Removed unnecessary FSM transitions, added height to Waypoints to avoid (blue) Helis to creep over the ground --- .../Moose/AI/AI_Cargo_Helicopter.lua | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua index fe8998093..0307266c7 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Helicopter.lua @@ -62,14 +62,15 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet ) local self = BASE:Inherit( self, AI_CARGO:New( Helicopter, CargoSet ) ) -- #AI_CARGO_HELICOPTER self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 ) + self:SetStartState( "Unloaded" ) self:AddTransition( "Unloaded", "Pickup", "*" ) self:AddTransition( "Loaded", "Deploy", "*" ) - + --[[ self:AddTransition( { "Unloaded", "Loading" }, "Load", "Boarding" ) self:AddTransition( "Boarding", "Board", "Boarding" ) - self:AddTransition( "Boarding", "Loaded", "Boarding" ) + self:AddTransition( "Boarding", "Loaded", "Loaded" ) self:AddTransition( "Boarding", "PickedUp", "Loaded" ) self:AddTransition( "Boarding", "Deploy", "Loaded" ) self:AddTransition( "Loaded", "Unload", "Unboarding" ) @@ -77,7 +78,11 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet ) self:AddTransition( "Unboarding", "Unloaded", "Unboarding" ) self:AddTransition( "Unboarding", "Deployed", "Unloaded" ) self:AddTransition( "Unboarding", "Pickup", "Unloaded" ) - + --]] + self:AddTransition( "Boarding", "Loaded", "Loaded" ) + self:AddTransition( "Unboarding", "Pickup", "Unloaded" ) + self:AddTransition( "Unloaded", "Unboard", "Unloaded" ) + self:AddTransition( "Unloaded", "Unloaded", "Unloaded" ) self:AddTransition( "*", "Landed", "*" ) self:AddTransition( "*", "Queue", "*" ) self:AddTransition( "*", "Orbit" , "*" ) @@ -309,7 +314,11 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina -- true -- ) -- Route[#Route+1] = WaypointFrom - local CoordinateTo = Coordinate + local CoordinateTo = Coordinate + + local landheight = CoordinateTo:GetLandHeight() -- get target height + CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground + local WaypointTo = CoordinateTo:WaypointAir( "RADIO", POINT_VEC3.RoutePointType.TurningPoint, @@ -363,7 +372,10 @@ function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordina -- true -- ) -- Route[#Route+1] = WaypointFrom - local CoordinateTo = Coordinate + local CoordinateTo = Coordinate + local landheight = CoordinateTo:GetLandHeight() -- get target height + CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground + local WaypointTo = CoordinateTo:WaypointAir( "RADIO", POINT_VEC3.RoutePointType.TurningPoint, @@ -423,7 +435,8 @@ end -- @param #number Height Height in meters to move to the pickup coordinate. This parameter is ignored for APCs. -- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided. function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordinate, Speed, Height, PickupZone ) - + self:F({Coordinate, Speed, Height, PickupZone }) + if Helicopter and Helicopter:IsAlive() ~= nil then Helicopter:Activate() @@ -437,7 +450,6 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin --- Calculate the target route point. local CoordinateFrom = Helicopter:GetCoordinate() - local CoordinateTo = Coordinate --- Create a route point of type air. local WaypointFrom = CoordinateFrom:WaypointAir( @@ -449,6 +461,10 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin ) --- Create a route point of type air. + local CoordinateTo = Coordinate + local landheight = CoordinateTo:GetLandHeight() -- get target height + CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground + local WaypointTo = CoordinateTo:WaypointAir( "RADIO", POINT_VEC3.RoutePointType.TurningPoint, @@ -526,7 +542,11 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin Route[#Route+1] = WaypointFrom --- Create a route point of type air. - local CoordinateTo = Coordinate + + local CoordinateTo = Coordinate + local landheight = CoordinateTo:GetLandHeight() -- get target height + CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground + local WaypointTo = CoordinateTo:WaypointAir( "RADIO", POINT_VEC3.RoutePointType.TurningPoint, @@ -596,7 +616,10 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat Route[#Route+1] = WaypointFrom --- Create a route point of type air. - local CoordinateTo = Coordinate + local CoordinateTo = Coordinate + local landheight = CoordinateTo:GetLandHeight() -- get target height + CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground + local WaypointTo = CoordinateTo:WaypointAir( "RADIO", POINT_VEC3.RoutePointType.TurningPoint, @@ -623,3 +646,4 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat end end + From 417af6a93c748b1f9a17a281137a77e1c3662322 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 2 Jan 2021 21:45:19 +0100 Subject: [PATCH 10/11] Client --- Moose Development/Moose/AI/AI_Cargo_APC.lua | 19 ++++++--- Moose Development/Moose/Core/Database.lua | 46 +++++++++++++++++---- Moose Development/Moose/Wrapper/Client.lua | 8 ++++ Moose Development/Moose/Wrapper/Unit.lua | 31 +++++++++++++- 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index c20475711..ac63297d0 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -428,18 +428,27 @@ function AI_CARGO_APC:onafterDeploy( APC, From, Event, To, Coordinate, Speed, He self.RouteDeploy = true - local _speed=Speed or APC:GetSpeedMax()*0.5 - - local Waypoints = APC:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true ) + -- Set speed in km/h. + local speedmax=APC:GetSpeedMax() + local _speed=Speed or speedmax*0.5 + _speed=math.min(_speed, speedmax) + -- Route on road. + local Waypoints = APC:TaskGroundOnRoad(Coordinate, _speed, "Line abreast", true) + + -- Task function local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Deploy", self, Coordinate, DeployZone ) - self:F({Waypoints = Waypoints}) + -- Last waypoint local Waypoint = Waypoints[#Waypoints] - APC:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. + + -- Set task function + APC:SetTaskWaypoint(Waypoint, TaskFunction) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. + -- Route group APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details. + -- Call parent function. self:GetParent( self, AI_CARGO_APC ).onafterDeploy( self, APC, From, Event, To, Coordinate, Speed, Height, DeployZone ) end diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 91259c8b7..63df70d01 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -977,11 +977,11 @@ function DATABASE:_EventOnBirth( Event ) Event.IniUnit = self:FindUnit( Event.IniDCSUnitName ) Event.IniGroup = self:FindGroup( Event.IniDCSGroupName ) - -- TODO: create event ClientAlive + -- Client local client=self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT if client then - + -- TODO: create event ClientAlive end -- Get player name. @@ -1018,8 +1018,6 @@ function DATABASE:_EventOnBirth( Event ) end - - end @@ -1030,17 +1028,31 @@ function DATABASE:_EventOnDeadOrCrash( Event ) self:F2( { Event } ) if Event.IniDCSUnit then + + local name=Event.IniDCSUnitName + if Event.IniObjectCategory == 3 then if self.STATICS[Event.IniDCSUnitName] then self:DeleteStatic( Event.IniDCSUnitName ) end else if Event.IniObjectCategory == 1 then + + -- Delete unit. if self.UNITS[Event.IniDCSUnitName] then - self:DeleteUnit( Event.IniDCSUnitName ) + self:DeleteUnit(Event.IniDCSUnitName) end + + -- Remove client players. + local client=self.CLIENTS[name] --Wrapper.Client#CLIENT + + if client then + client:RemovePlayers() + end + end end + end self:AccountDestroys( Event ) @@ -1055,15 +1067,31 @@ function DATABASE:_EventOnPlayerEnterUnit( Event ) if Event.IniDCSUnit then if Event.IniObjectCategory == 1 then + + -- Add unit. self:AddUnit( Event.IniDCSUnitName ) + + -- Ini unit. Event.IniUnit = self:FindUnit( Event.IniDCSUnitName ) + + -- Add group. self:AddGroup( Event.IniDCSGroupName ) + + -- Get player unit. local PlayerName = Event.IniDCSUnit:getPlayerName() - if not self.PLAYERS[PlayerName] then - self:AddPlayer( Event.IniDCSUnitName, PlayerName ) + + if PlayerName then + + if not self.PLAYERS[PlayerName] then + self:AddPlayer( Event.IniDCSUnitName, PlayerName ) + end + + local Settings = SETTINGS:Set( PlayerName ) + Settings:SetPlayerMenu( Event.IniUnit ) + + else + self:E("ERROR: getPlayerName() returned nil for event PlayerEnterUnit") end - local Settings = SETTINGS:Set( PlayerName ) - Settings:SetPlayerMenu( Event.IniUnit ) end end end diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 39f6af974..445c655ee 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -207,6 +207,14 @@ function CLIENT:RemovePlayer(PlayerName) return self end +--- Remove all players. +-- @param #CLIENT self +-- @return #CLIENT self +function CLIENT:RemovePlayers() + self.Players={} + return self +end + --- Show the briefing of a CLIENT. -- @param #CLIENT self diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 739c42649..1321cba5d 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -13,7 +13,7 @@ -- -- ### Author: **FlightControl** -- --- ### Contributions: +-- ### Contributions: **funkyfranky** -- -- === -- @@ -22,6 +22,8 @@ --- @type UNIT +-- @field #string ClassName Name of the class. +-- @field #string UnitName Name of the unit. -- @extends Wrapper.Controllable#CONTROLLABLE --- For each DCS Unit object alive within a running mission, a UNIT wrapper object (instance) will be created within the _@{DATABASE} object. @@ -87,6 +89,7 @@ -- @field #UNIT UNIT UNIT = { ClassName="UNIT", + UnitName=nil, } @@ -379,6 +382,32 @@ function UNIT:GetPlayerName() end +--- Checks is the unit is a *Player* or *Client* slot. +-- @param #UNIT self +-- @return #boolean If true, unit is a player or client aircraft +function UNIT:IsClient() + + if _DATABASE.CLIENTS[self.UnitName] then + return true + end + + return false +end + +--- Get the CLIENT of the unit +-- @param #UNIT self +-- @return Wrapper.Client#CLIENT +function UNIT:GetClient() + + local client=_DATABASE.CLIENTS[self.UnitName] + + if client then + return client + end + + return nil +end + --- Returns the unit's number in the group. -- The number is the same number the unit has in ME. -- It may not be changed during the mission. From 3358f98bc40ff77ab72b9a143a381eace867cf60 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 2 Jan 2021 23:53:36 +0100 Subject: [PATCH 11/11] Some stuff --- Moose Development/Moose/Cargo/Cargo.lua | 14 ++- Moose Development/Moose/Cargo/CargoUnit.lua | 13 +-- Moose Development/Moose/Core/Database.lua | 96 +++++++++++++++++---- Moose Development/Moose/Core/Event.lua | 2 +- Moose Development/Moose/Core/Set.lua | 34 +++++--- 5 files changed, 119 insertions(+), 40 deletions(-) diff --git a/Moose Development/Moose/Cargo/Cargo.lua b/Moose Development/Moose/Cargo/Cargo.lua index 6051c25e4..3e43b3ef7 100644 --- a/Moose Development/Moose/Cargo/Cargo.lua +++ b/Moose Development/Moose/Cargo/Cargo.lua @@ -1078,11 +1078,14 @@ do -- CARGO_REPRESENTABLE local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE self:F( { Type, Name, LoadRadius, NearRadius } ) - local Desc = CargoObject:GetDesc() - self:I( { Desc = Desc } ) + -- Descriptors. + local Desc=CargoObject:GetDesc() + self:T({Desc=Desc}) + -- Weight. local Weight = math.random( 80, 120 ) + -- Adjust weight.. if Desc then if Desc.typeName == "2B11 mortar" then Weight = 210 @@ -1091,13 +1094,8 @@ do -- CARGO_REPRESENTABLE end end + -- Set weight. self:SetWeight( Weight ) - --- local Box = CargoUnit:GetBoundingBox() --- local VolumeUnit = ( Box.max.x - Box.min.x ) * ( Box.max.y - Box.min.y ) * ( Box.max.z - Box.min.z ) --- self:I( { VolumeUnit = VolumeUnit, WeightUnit = WeightUnit } ) - --self:SetVolume( VolumeUnit ) - return self end diff --git a/Moose Development/Moose/Cargo/CargoUnit.lua b/Moose Development/Moose/Cargo/CargoUnit.lua index 88ba8c725..4d0093b47 100644 --- a/Moose Development/Moose/Cargo/CargoUnit.lua +++ b/Moose Development/Moose/Cargo/CargoUnit.lua @@ -46,14 +46,17 @@ do -- CARGO_UNIT -- @param #number NearRadius (optional) -- @return #CARGO_UNIT function CARGO_UNIT:New( CargoUnit, Type, Name, LoadRadius, NearRadius ) - local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoUnit, Type, Name, LoadRadius, NearRadius ) ) -- #CARGO_UNIT - self:I( { Type, Name, LoadRadius, NearRadius } ) - self:T( CargoUnit ) + -- Inherit CARGO_REPRESENTABLE. + local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoUnit, Type, Name, LoadRadius, NearRadius ) ) -- #CARGO_UNIT + + -- Debug info. + self:T({Type=Type, Name=Name, LoadRadius=LoadRadius, NearRadius=NearRadius}) + + -- Set cargo object. self.CargoObject = CargoUnit - self:T( self.ClassName ) - + -- Set event prio. self:SetEventPriority( 5 ) return self diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 63df70d01..eafe78140 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -411,7 +411,6 @@ do -- cargo local Groups = UTILS.DeepCopy( self.GROUPS ) -- This is a very important statement. CARGO_GROUP:New creates a new _DATABASE.GROUP entry, which will confuse the loop. I searched 4 hours on this to find the bug! for CargoGroupName, CargoGroup in pairs( Groups ) do - self:I( { Cargo = CargoGroupName } ) if self:IsCargo( CargoGroupName ) then local CargoInfo = CargoGroupName:match("#CARGO(.*)") local CargoParam = CargoInfo and CargoInfo:match( "%((.*)%)") @@ -755,46 +754,96 @@ end --- Get static group template. -- @param #DATABASE self --- @param #string StaticName Name of the static +-- @param #string StaticName Name of the static. -- @return #table Static template table. function DATABASE:GetStaticGroupTemplate( StaticName ) - local StaticTemplate = self.Templates.Statics[StaticName].GroupTemplate - return StaticTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID + if self.Templates.Statics[StaticName] then + local StaticTemplate = self.Templates.Statics[StaticName].GroupTemplate + return StaticTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID + else + self:E("ERROR: Static group template does NOT exist for static "..tostring(StaticName)) + return nil + end end ---- @param #DATABASE self +--- Get static unit template. +-- @param #DATABASE self +-- @param #string StaticName Name of the static. +-- @return #table Static template table. function DATABASE:GetStaticUnitTemplate( StaticName ) - local UnitTemplate = self.Templates.Statics[StaticName].UnitTemplate - return UnitTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID + if self.Templates.Statics[StaticName] then + local UnitTemplate = self.Templates.Statics[StaticName].UnitTemplate + return UnitTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID + else + self:E("ERROR: Static unit template does NOT exist for static "..tostring(StaticName)) + return nil + end end - +--- Get group name from unit name. +-- @param #DATABASE self +-- @param #string UnitName Name of the unit. +-- @return #string Group name. function DATABASE:GetGroupNameFromUnitName( UnitName ) - return self.Templates.Units[UnitName].GroupName + if self.Templates.Units[UnitName] then + return self.Templates.Units[UnitName].GroupName + else + self:E("ERROR: Unit template does not exist for unit "..tostring(UnitName)) + return nil + end end +--- Get group template from unit name. +-- @param #DATABASE self +-- @param #string UnitName Name of the unit. +-- @return #table Group template. function DATABASE:GetGroupTemplateFromUnitName( UnitName ) - return self.Templates.Units[UnitName].GroupTemplate + if self.Templates.Units[UnitName] then + return self.Templates.Units[UnitName].GroupTemplate + else + self:E("ERROR: Unit template does not exist for unit "..tostring(UnitName)) + return nil + end end +--- Get coalition ID from client name. +-- @param #DATABASE self +-- @param #string ClientName Name of the Client. +-- @return #number Coalition ID. function DATABASE:GetCoalitionFromClientTemplate( ClientName ) return self.Templates.ClientsByName[ClientName].CoalitionID end +--- Get category ID from client name. +-- @param #DATABASE self +-- @param #string ClientName Name of the Client. +-- @return #number Category ID. function DATABASE:GetCategoryFromClientTemplate( ClientName ) return self.Templates.ClientsByName[ClientName].CategoryID end +--- Get country ID from client name. +-- @param #DATABASE self +-- @param #string ClientName Name of the Client. +-- @return #number Country ID. function DATABASE:GetCountryFromClientTemplate( ClientName ) return self.Templates.ClientsByName[ClientName].CountryID end --- Airbase +--- Get coalition ID from airbase name. +-- @param #DATABASE self +-- @param #string AirbaseName Name of the airbase. +-- @return #number Coalition ID. function DATABASE:GetCoalitionFromAirbase( AirbaseName ) return self.AIRBASES[AirbaseName]:GetCoalition() end +--- Get category from airbase name. +-- @param #DATABASE self +-- @param #string AirbaseName Name of the airbase. +-- @return #number Category. function DATABASE:GetCategoryFromAirbase( AirbaseName ) return self.AIRBASES[AirbaseName]:GetCategory() end @@ -890,7 +939,7 @@ function DATABASE:_RegisterStatics() if DCSStatic:isExist() then local DCSStaticName = DCSStatic:getName() - self:I( { "Register Static:", DCSStaticName } ) + self:I(string.format("Register Static: %s", tostring(DCSStaticName))) self:AddStatic( DCSStaticName ) else self:E( { "Static does not exist: ", DCSStatic } ) @@ -921,7 +970,7 @@ function DATABASE:_RegisterAirbases() local airbaseUID=airbase:GetID(true) -- Debug output. - local text=string.format("Register Airbase: %s (ID=%d UID=%d), category=%s, parking=%d [", tostring(DCSAirbaseName), airbaseID, airbaseUID, AIRBASE.CategoryName[airbase.category], airbase.NparkingTotal) + local text=string.format("Register %s: %s (ID=%d UID=%d), parking=%d [", AIRBASE.CategoryName[airbase.category], tostring(DCSAirbaseName), airbaseID, airbaseUID, airbase.NparkingTotal) for _,terminalType in pairs(AIRBASE.TerminalType) do if airbase.NparkingTerminal and airbase.NparkingTerminal[terminalType] then text=text..string.format("%d=%d ", terminalType, airbase.NparkingTerminal[terminalType]) @@ -1025,19 +1074,29 @@ end -- @param #DATABASE self -- @param Core.Event#EVENTDATA Event function DATABASE:_EventOnDeadOrCrash( Event ) - self:F2( { Event } ) if Event.IniDCSUnit then local name=Event.IniDCSUnitName if Event.IniObjectCategory == 3 then + + --- + -- STATICS + --- + if self.STATICS[Event.IniDCSUnitName] then self:DeleteStatic( Event.IniDCSUnitName ) end + else + if Event.IniObjectCategory == 1 then + --- + -- UNITS + --- + -- Delete unit. if self.UNITS[Event.IniDCSUnitName] then self:DeleteUnit(Event.IniDCSUnitName) @@ -1048,13 +1107,20 @@ function DATABASE:_EventOnDeadOrCrash( Event ) if client then client:RemovePlayers() - end - + end + end end + -- Add airbase if it was spawned later in the mission. + local airbase=self.AIRBASES[Event.IniDCSUnitName] --Wrapper.Airbase#AIRBASE + if airbase and (airbase:IsHelipad() or airbase:IsShip()) then + self:DeleteAirbase(Event.IniDCSUnitName) + end + end + -- Account destroys. self:AccountDestroys( Event ) end diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index 6a7960748..4588c6ba7 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -820,7 +820,7 @@ do -- Event Creation -- @param #EVENT self -- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created. function EVENT:CreateEventNewCargo( Cargo ) - self:I( { Cargo } ) + self:F( { Cargo } ) local Event = { id = EVENTS.NewCargo, diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index df5c431df..b34ceb757 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -4705,7 +4705,8 @@ do -- SET_AIRBASE if _DATABASE then -- We use the BaseCaptured event, which is generated by DCS when a base got captured. - self:HandleEvent( EVENTS.BaseCaptured ) + self:HandleEvent(EVENTS.BaseCaptured) + self:HandleEvent(EVENTS.Dead) -- We initialize the first set. for ObjectName, Object in pairs( self.Database ) do @@ -4720,10 +4721,9 @@ do -- SET_AIRBASE return self end - --- Starts the filtering. + --- Base capturing event. -- @param #SET_AIRBASE self -- @param Core.Event#EVENT EventData - -- @return #SET_AIRBASE self function SET_AIRBASE:OnEventBaseCaptured(EventData) -- When a base got captured, we reevaluate the set. @@ -4739,24 +4739,36 @@ do -- SET_AIRBASE end + --- Dead event. + -- @param #SET_AIRBASE self + -- @param Core.Event#EVENT EventData + function SET_AIRBASE:OnEventDead(EventData) + + local airbaseName, airbase=self:FindInDatabase(EventData) + + if airbase and airbase:IsShip() or airbase:IsHelipad() then + self:RemoveAirbasesByName(airbaseName) + end + + end + + --- Handles the Database to check on an event (birth) that the Object was added in the Database. -- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event! -- @param #SET_AIRBASE self - -- @param Core.Event#EVENTDATA Event - -- @return #string The name of the AIRBASE - -- @return #table The AIRBASE + -- @param Core.Event#EVENTDATA Event Event data. + -- @return #string The name of the AIRBASE. + -- @return Wrapper.Airbase#AIRBASE The AIRBASE object. function SET_AIRBASE:AddInDatabase( Event ) - self:F3( { Event } ) - return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName] end --- Handles the Database to check on any event that Object exists in the Database. -- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa! -- @param #SET_AIRBASE self - -- @param Core.Event#EVENTDATA Event - -- @return #string The name of the AIRBASE - -- @return #table The AIRBASE + -- @param Core.Event#EVENTDATA Event Event data. + -- @return #string The name of the AIRBASE. + -- @return Wrapper.Airbase#AIRBASE The AIRBASE object. function SET_AIRBASE:FindInDatabase( Event ) self:F3( { Event } )