diff --git a/Moose Development/Moose/AI/AI_Escort.lua b/Moose Development/Moose/AI/AI_Escort.lua index e18948790..c772940ab 100644 --- a/Moose Development/Moose/AI/AI_Escort.lua +++ b/Moose Development/Moose/AI/AI_Escort.lua @@ -147,8 +147,8 @@ -- @image Escorting.JPG - ---- @type AI_ESCORT +--- +-- @type AI_ESCORT -- @extends AI.AI_Formation#AI_FORMATION @@ -168,11 +168,14 @@ -- -- -- First find the GROUP object and the CLIENT object. -- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor. --- local EscortGroup = GROUP:FindByName( "Group Name" ) -- The Group Name is the name of the group that will escort the Escort Client. +-- local EscortGroup = SET_GROUP:New():FilterPrefixes("Escort"):FilterOnce() -- The the group name of the escorts contains "Escort". -- -- -- Now use these 2 objects to construct the new EscortPlanes object. -- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." ) --- +-- EscortPlanes:MenusAirplanes() -- create menus for airplanes +-- EscortPlanes:__Start(2) +-- +-- -- @field #AI_ESCORT AI_ESCORT = { ClassName = "AI_ESCORT", @@ -189,7 +192,7 @@ AI_ESCORT = { TaskPoints = {} } ---- @field Functional.Detection#DETECTION_AREAS +-- @field Functional.Detection#DETECTION_AREAS AI_ESCORT.Detection = nil --- MENUPARAM type @@ -211,10 +214,14 @@ AI_ESCORT.Detection = nil -- -- -- First find the GROUP object and the CLIENT object. -- local EscortUnit = CLIENT:FindByName( "Unit Name" ) -- The Unit Name is the name of the unit flagged with the skill Client in the mission editor. --- local EscortGroup = GROUP:FindByName( "Group Name" ) -- The Group Name is the name of the group that will escort the Escort Client. +-- local EscortGroup = SET_GROUP:New():FilterPrefixes("Escort"):FilterOnce() -- The the group name of the escorts contains "Escort". -- -- -- Now use these 2 objects to construct the new EscortPlanes object. -- EscortPlanes = AI_ESCORT:New( EscortUnit, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." ) +-- EscortPlanes:MenusAirplanes() -- create menus for airplanes +-- EscortPlanes:__Start(2) +-- +-- function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) local self = BASE:Inherit( self, AI_FORMATION:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) ) -- #AI_ESCORT @@ -227,10 +234,17 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) self.EscortGroupSet = EscortGroupSet self.EscortGroupSet:SetSomeIteratorLimit( 8 ) - + self.EscortBriefing = EscortBriefing self.Menu = {} + self.Menu.HoldAtEscortPosition = self.Menu.HoldAtEscortPosition or {} + self.Menu.HoldAtLeaderPosition = self.Menu.HoldAtLeaderPosition or {} + self.Menu.Flare = self.Menu.Flare or {} + self.Menu.Smoke = self.Menu.Smoke or {} + self.Menu.Targets = self.Menu.Targets or {} + self.Menu.ROE = self.Menu.ROE or {} + self.Menu.ROT = self.Menu.ROT or {} -- if not EscortBriefing then -- EscortGroup:MessageToClient( EscortGroup:GetCategoryName() .. " '" .. EscortName .. "' (" .. EscortGroup:GetCallsign() .. ") reporting! " .. @@ -250,7 +264,7 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) EscortGroupSet:ForEachGroup( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) -- Set EscortGroup known at EscortUnit. if not self.PlayerUnit._EscortGroups then @@ -325,14 +339,14 @@ function AI_ESCORT:_InitEscortRoute( EscortGroup ) end ---- @param #AI_ESCORT self +-- @param #AI_ESCORT self -- @param Core.Set#SET_GROUP EscortGroupSet function AI_ESCORT:onafterStart( EscortGroupSet ) self:F() EscortGroupSet:ForEachGroup( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) EscortGroup:WayPointInitialize() @@ -370,7 +384,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet ) self:_InitFlightMenus() self.EscortGroupSet:ForSomeGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) self:_InitEscortMenus( EscortGroup ) @@ -378,7 +392,7 @@ function AI_ESCORT:onafterStart( EscortGroupSet ) self:SetFlightModeFormation( EscortGroup ) - --- @param #AI_ESCORT self + -- @param #AI_ESCORT self -- @param Core.Event#EVENTDATA EventData function EscortGroup:OnEventDeadOrCrash( EventData ) self:F( { "EventDead", EventData } ) @@ -394,14 +408,14 @@ function AI_ESCORT:onafterStart( EscortGroupSet ) end ---- @param #AI_ESCORT self +-- @param #AI_ESCORT self -- @param Core.Set#SET_GROUP EscortGroupSet function AI_ESCORT:onafterStop( EscortGroupSet ) self:F() EscortGroupSet:ForEachGroup( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) EscortGroup:WayPointInitialize() @@ -550,7 +564,7 @@ function AI_ESCORT:SetFlightMenuFormation( Formation ) local MenuFlightFormationID = MENU_GROUP_COMMAND:New( self.PlayerGroup, Formation, FlightMenuFormation, function ( self, Formation, ... ) self.EscortGroupSet:ForSomeGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup, self, Formation, Arguments ) if EscortGroup:IsAir() then self:E({FormationID=FormationID}) @@ -764,7 +778,7 @@ end function AI_ESCORT:SetFlightMenuHoldAtEscortPosition() - for _, MenuHoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition ) do + for _, MenuHoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition or {} ) do local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu ) local FlightMenuHoldPosition = MENU_GROUP_COMMAND @@ -785,7 +799,7 @@ end function AI_ESCORT:SetEscortMenuHoldAtEscortPosition( EscortGroup ) - for _, HoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition ) do + for _, HoldAtEscortPosition in pairs( self.Menu.HoldAtEscortPosition or {}) do if EscortGroup:IsAir() then local EscortGroupName = EscortGroup:GetName() local EscortMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", EscortGroup.EscortMenu ) @@ -853,7 +867,7 @@ end function AI_ESCORT:SetFlightMenuHoldAtLeaderPosition() - for _, MenuHoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition ) do + for _, MenuHoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition or {}) do local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu ) local FlightMenuHoldAtLeaderPosition = MENU_GROUP_COMMAND @@ -874,7 +888,7 @@ end function AI_ESCORT:SetEscortMenuHoldAtLeaderPosition( EscortGroup ) - for _, HoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition ) do + for _, HoldAtLeaderPosition in pairs( self.Menu.HoldAtLeaderPosition or {}) do if EscortGroup:IsAir() then local EscortGroupName = EscortGroup:GetName() @@ -999,7 +1013,7 @@ end function AI_ESCORT:SetFlightMenuFlare() - for _, MenuFlare in pairs( self.Menu.Flare) do + for _, MenuFlare in pairs( self.Menu.Flare or {}) do local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu ) local FlightMenuFlare = MENU_GROUP:New( self.PlayerGroup, MenuFlare.MenuText, FlightMenuReportNavigation ) @@ -1014,7 +1028,7 @@ end function AI_ESCORT:SetEscortMenuFlare( EscortGroup ) - for _, MenuFlare in pairs( self.Menu.Flare) do + for _, MenuFlare in pairs( self.Menu.Flare or {}) do if EscortGroup:IsAir() then local EscortGroupName = EscortGroup:GetName() @@ -1059,7 +1073,7 @@ end function AI_ESCORT:SetFlightMenuSmoke() - for _, MenuSmoke in pairs( self.Menu.Smoke) do + for _, MenuSmoke in pairs( self.Menu.Smoke or {}) do local FlightMenuReportNavigation = MENU_GROUP:New( self.PlayerGroup, "Navigation", self.FlightMenu ) local FlightMenuSmoke = MENU_GROUP:New( self.PlayerGroup, MenuSmoke.MenuText, FlightMenuReportNavigation ) @@ -1076,7 +1090,7 @@ end function AI_ESCORT:SetEscortMenuSmoke( EscortGroup ) - for _, MenuSmoke in pairs( self.Menu.Smoke) do + for _, MenuSmoke in pairs( self.Menu.Smoke or {}) do if EscortGroup:IsAir() then local EscortGroupName = EscortGroup:GetName() @@ -1169,7 +1183,7 @@ function AI_ESCORT:SetFlightMenuTargets() local FlightMenuAttackNearbyAir = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest airborne targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Air ):SetTag( "Attack" ) local FlightMenuAttackNearbyGround = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest ground targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Ground ):SetTag( "Attack" ) - for _, MenuTargets in pairs( self.Menu.Targets) do + for _, MenuTargets in pairs( self.Menu.Targets or {}) do MenuTargets.FlightReportTargetsScheduler = SCHEDULER:New( self, self._FlightReportTargetsScheduler, {}, MenuTargets.Interval, MenuTargets.Interval ) end @@ -1179,7 +1193,7 @@ end function AI_ESCORT:SetEscortMenuTargets( EscortGroup ) - for _, MenuTargets in pairs( self.Menu.Targets) do + for _, MenuTargets in pairs( self.Menu.Targets or {} or {}) do if EscortGroup:IsAir() then local EscortGroupName = EscortGroup:GetName() --local EscortMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", EscortGroup.EscortMenu ) @@ -1231,7 +1245,7 @@ function AI_ESCORT:MenuAssistedAttack() self:F() self.EscortGroupSet:ForSomeGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) if not EscortGroup:IsAir() then -- Request assistance from other escorts. @@ -1246,7 +1260,7 @@ end function AI_ESCORT:SetFlightMenuROE() - for _, MenuROE in pairs( self.Menu.ROE) do + for _, MenuROE in pairs( self.Menu.ROE or {}) do local FlightMenuROE = MENU_GROUP:New( self.PlayerGroup, "Rule Of Engagement", self.FlightMenu ) local FlightMenuROEHoldFire = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Hold fire", FlightMenuROE, AI_ESCORT._FlightROEHoldFire, self, "Holding weapons!" ) @@ -1261,7 +1275,7 @@ end function AI_ESCORT:SetEscortMenuROE( EscortGroup ) - for _, MenuROE in pairs( self.Menu.ROE) do + for _, MenuROE in pairs( self.Menu.ROE or {}) do if EscortGroup:IsAir() then local EscortGroupName = EscortGroup:GetName() @@ -1302,7 +1316,7 @@ end function AI_ESCORT:SetFlightMenuROT() - for _, MenuROT in pairs( self.Menu.ROT) do + for _, MenuROT in pairs( self.Menu.ROT or {}) do local FlightMenuROT = MENU_GROUP:New( self.PlayerGroup, "Reaction On Threat", self.FlightMenu ) local FlightMenuROTNoReaction = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Fight until death", FlightMenuROT, AI_ESCORT._FlightROTNoReaction, self, "Fighting until death!" ) @@ -1317,7 +1331,7 @@ end function AI_ESCORT:SetEscortMenuROT( EscortGroup ) - for _, MenuROT in pairs( self.Menu.ROT) do + for _, MenuROT in pairs( self.Menu.ROT or {}) do if EscortGroup:IsAir() then local EscortGroupName = EscortGroup:GetName() @@ -1375,7 +1389,7 @@ function AI_ESCORT:SetEscortMenuResumeMission( EscortGroup ) end ---- @param #AI_ESCORT self +-- @param #AI_ESCORT self -- @param Wrapper.Group#GROUP OrbitGroup -- @param Wrapper.Group#GROUP EscortGroup -- @param #number OrbitHeight @@ -1419,7 +1433,7 @@ function AI_ESCORT:_HoldPosition( OrbitGroup, EscortGroup, OrbitHeight, OrbitSec end ---- @param #AI_ESCORT self +-- @param #AI_ESCORT self -- @param Wrapper.Group#GROUP OrbitGroup -- @param #number OrbitHeight -- @param #number OrbitSeconds @@ -1428,7 +1442,7 @@ function AI_ESCORT:_FlightHoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds ) local EscortUnit = self.PlayerUnit self.EscortGroupSet:ForEachGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup, OrbitGroup ) if EscortGroup:IsAir() then if OrbitGroup == nil then @@ -1456,7 +1470,7 @@ end function AI_ESCORT:_FlightJoinUp() self.EscortGroupSet:ForEachGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) if EscortGroup:IsAir() then self:_JoinUp( EscortGroup ) @@ -1483,7 +1497,7 @@ end function AI_ESCORT:_FlightFormationTrail( XStart, XSpace, YStart ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) if EscortGroup:IsAir() then self:_EscortFormationTrail( EscortGroup, XStart, XSpace, YStart ) @@ -1510,7 +1524,7 @@ end function AI_ESCORT:_FlightFormationStack( XStart, XSpace, YStart, YSpace ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) if EscortGroup:IsAir() then self:_EscortFormationStack( EscortGroup, XStart, XSpace, YStart, YSpace ) @@ -1533,7 +1547,7 @@ end function AI_ESCORT:_FlightFlare( Color, Message ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) if EscortGroup:IsAir() then self:_Flare( EscortGroup, Color, Message ) @@ -1556,7 +1570,7 @@ end function AI_ESCORT:_FlightSmoke( Color, Message ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) if EscortGroup:IsAir() then self:_Smoke( EscortGroup, Color, Message ) @@ -1587,7 +1601,7 @@ end function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup ) if EscortGroup:IsAir() then self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets ) @@ -1679,7 +1693,7 @@ function AI_ESCORT:_ScanTargets( ScanDuration ) end ---- @param Wrapper.Group#GROUP EscortGroup +-- @param Wrapper.Group#GROUP EscortGroup -- @param #AI_ESCORT self function AI_ESCORT.___Resume( EscortGroup, self ) @@ -1701,7 +1715,7 @@ function AI_ESCORT.___Resume( EscortGroup, self ) end ---- @param #AI_ESCORT self +-- @param #AI_ESCORT self -- @param Wrapper.Group#GROUP EscortGroup -- @param #number WayPoint function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint ) @@ -1723,7 +1737,7 @@ function AI_ESCORT:_ResumeMission( EscortGroup, WayPoint ) end ---- @param #AI_ESCORT self +-- @param #AI_ESCORT self -- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item. -- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem ) @@ -1743,7 +1757,7 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem ) local AttackUnitTasks = {} DetectedSet:ForEachUnit( - --- @param Wrapper.Unit#UNIT DetectedUnit + -- @param Wrapper.Unit#UNIT DetectedUnit function( DetectedUnit, Tasks ) if DetectedUnit:IsAlive() then AttackUnitTasks[#AttackUnitTasks+1] = EscortGroup:TaskAttackUnit( DetectedUnit ) @@ -1767,7 +1781,7 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem ) local Tasks = {} DetectedSet:ForEachUnit( - --- @param Wrapper.Unit#UNIT DetectedUnit + -- @param Wrapper.Unit#UNIT DetectedUnit function( DetectedUnit, Tasks ) if DetectedUnit:IsAlive() then Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 ) @@ -1795,7 +1809,7 @@ end function AI_ESCORT:_FlightAttackTarget( DetectedItem ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Core.Group#GROUP EscortGroup + -- @param Core.Group#GROUP EscortGroup function( EscortGroup, DetectedItem ) if EscortGroup:IsAir() then self:_AttackTarget( EscortGroup, DetectedItem ) @@ -1842,7 +1856,7 @@ end --- ---- @param #AI_ESCORT self +-- @param #AI_ESCORT self -- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item. -- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem ) @@ -1854,7 +1868,7 @@ function AI_ESCORT:_AssistTarget( EscortGroup, DetectedItem ) local Tasks = {} DetectedSet:ForEachUnit( - --- @param Wrapper.Unit#UNIT DetectedUnit + -- @param Wrapper.Unit#UNIT DetectedUnit function( DetectedUnit, Tasks ) if DetectedUnit:IsAlive() then Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 ) @@ -1881,7 +1895,7 @@ end function AI_ESCORT:_FlightROEHoldFire( EscortROEMessage ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Wrapper.Group#GROUP EscortGroup + -- @param Wrapper.Group#GROUP EscortGroup function( EscortGroup ) self:_ROE( EscortGroup, EscortGroup.OptionROEHoldFire, EscortROEMessage ) end @@ -1890,7 +1904,7 @@ end function AI_ESCORT:_FlightROEOpenFire( EscortROEMessage ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Wrapper.Group#GROUP EscortGroup + -- @param Wrapper.Group#GROUP EscortGroup function( EscortGroup ) self:_ROE( EscortGroup, EscortGroup.OptionROEOpenFire, EscortROEMessage ) end @@ -1899,7 +1913,7 @@ end function AI_ESCORT:_FlightROEReturnFire( EscortROEMessage ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Wrapper.Group#GROUP EscortGroup + -- @param Wrapper.Group#GROUP EscortGroup function( EscortGroup ) self:_ROE( EscortGroup, EscortGroup.OptionROEReturnFire, EscortROEMessage ) end @@ -1908,7 +1922,7 @@ end function AI_ESCORT:_FlightROEWeaponFree( EscortROEMessage ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Wrapper.Group#GROUP EscortGroup + -- @param Wrapper.Group#GROUP EscortGroup function( EscortGroup ) self:_ROE( EscortGroup, EscortGroup.OptionROEWeaponFree, EscortROEMessage ) end @@ -1924,7 +1938,7 @@ end function AI_ESCORT:_FlightROTNoReaction( EscortROTMessage ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Wrapper.Group#GROUP EscortGroup + -- @param Wrapper.Group#GROUP EscortGroup function( EscortGroup ) self:_ROT( EscortGroup, EscortGroup.OptionROTNoReaction, EscortROTMessage ) end @@ -1933,7 +1947,7 @@ end function AI_ESCORT:_FlightROTPassiveDefense( EscortROTMessage ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Wrapper.Group#GROUP EscortGroup + -- @param Wrapper.Group#GROUP EscortGroup function( EscortGroup ) self:_ROT( EscortGroup, EscortGroup.OptionROTPassiveDefense, EscortROTMessage ) end @@ -1942,7 +1956,7 @@ end function AI_ESCORT:_FlightROTEvadeFire( EscortROTMessage ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Wrapper.Group#GROUP EscortGroup + -- @param Wrapper.Group#GROUP EscortGroup function( EscortGroup ) self:_ROT( EscortGroup, EscortGroup.OptionROTEvadeFire, EscortROTMessage ) end @@ -1951,7 +1965,7 @@ end function AI_ESCORT:_FlightROTVertical( EscortROTMessage ) self.EscortGroupSet:ForEachGroupAlive( - --- @param Wrapper.Group#GROUP EscortGroup + -- @param Wrapper.Group#GROUP EscortGroup function( EscortGroup ) self:_ROT( EscortGroup, EscortGroup.OptionROTVertical, EscortROTMessage ) end @@ -2178,5 +2192,3 @@ function AI_ESCORT:_FlightReportTargetsScheduler() return false end - - diff --git a/Moose Development/Moose/Core/ClientMenu.lua b/Moose Development/Moose/Core/ClientMenu.lua index d58c62f4b..1f11eebaa 100644 --- a/Moose Development/Moose/Core/ClientMenu.lua +++ b/Moose Development/Moose/Core/ClientMenu.lua @@ -381,7 +381,7 @@ end CLIENTMENUMANAGER = { ClassName = "CLIENTMENUMANAGER", lid = "", - version = "0.1.0", + version = "0.1.1", name = nil, clientset = nil, menutree = {}, @@ -670,7 +670,7 @@ end --- Remove the entry and all entries below the given entry from the client's F10 menus. -- @param #CLIENTMENUMANAGER self -- @param #CLIENTMENU Entry The entry to remove --- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client. In this case the generic structure will not be touched. +-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client. -- @return #CLIENTMENUMANAGER self function CLIENTMENUMANAGER:DeleteF10Entry(Entry,Client) self:T(self.lid.."DeleteF10Entry") @@ -783,3 +783,4 @@ end -- End ClientMenu -- ---------------------------------------------------------------------------------------------------------------- + diff --git a/Moose Development/Moose/Ops/ATIS.lua b/Moose Development/Moose/Ops/ATIS.lua index 719ad8da7..a7222956b 100644 --- a/Moose Development/Moose/Ops/ATIS.lua +++ b/Moose Development/Moose/Ops/ATIS.lua @@ -419,6 +419,8 @@ ATIS.RunwayM2T = { TheChannel = -10, Syria = 5, MarianaIslands = 2, + Falklands = 12, + Sinai = 5, } --- Whether ICAO phraseology is used for ATIS broadcasts. @@ -430,6 +432,8 @@ ATIS.RunwayM2T = { -- @field #boolean TheChannel true. -- @field #boolean Syria true. -- @field #boolean MarianaIslands true. +-- @field #boolean Falklands true. +-- @field #boolean Sinai true. ATIS.ICAOPhraseology = { Caucasus = true, Nevada = false, @@ -437,7 +441,9 @@ ATIS.ICAOPhraseology = { PersianGulf = true, TheChannel = true, Syria = true, - MarianaIslands = true + MarianaIslands = true, + Falklands = true, + Sinai = true, } --- Nav point data. @@ -1272,7 +1278,8 @@ end -- @param #string Event Event. -- @param #string To To state. function ATIS:onafterStart( From, Event, To ) - + self:I("Airbase category is "..self.airbase:GetAirbaseCategory()) + -- Check that this is an airdrome. if self.airbase:GetAirbaseCategory() == Airbase.Category.SHIP then self:E( self.lid .. string.format( "ERROR: Cannot start ATIS for airbase %s! Only AIRDROMES are supported but NOT SHIPS.", self.airbasename ) ) @@ -1823,7 +1830,10 @@ function ATIS:onafterBroadcast( From, Event, To ) -- Airbase name subtitle = string.format( "%s", self.airbasename ) - if (not self.ATISforFARPs) and self.airbasename:find( "AFB" ) == nil and self.airbasename:find( "Airport" ) == nil and self.airbasename:find( "Airstrip" ) == nil and self.airbasename:find( "airfield" ) == nil and self.airbasename:find( "AB" ) == nil then + if (not self.ATISforFARPs) and self.airbasename:find( "AFB" ) == nil and self.airbasename:find( "Airport" ) == nil + and self.airbasename:find( "Airstrip" ) == nil and self.airbasename:find( "airfield" ) == nil and self.airbasename:find( "AB" ) == nil + and self.airbasename:find( "Field" ) == nil + then subtitle = subtitle .. " Airport" end if not self.useSRS then diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 7eaf70fa1..3c04848a3 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -17,7 +17,7 @@ -- === -- -- ### Author: **applevangelist** --- @date Last Update December 2022 +-- @date Last Update July 2023 -- @module Ops.AWACS -- @image OPS_AWACS.jpg @@ -63,6 +63,7 @@ do -- @field Utilities.FiFo#FIFO RadioQueue -- @field Utilities.FiFo#FIFO PrioRadioQueue -- @field Utilities.FiFo#FIFO CAPAirwings +-- @field Utilities.FiFo#FIFO TacticalQueue -- @field #number AwacsTimeOnStation -- @field #number AwacsTimeStamp -- @field #number EscortsTimeOnStation @@ -113,6 +114,13 @@ do -- @field Wrapper.Group#GROUP GCIGroup EWR group object for GCI ops -- @field #string locale Localization -- @field #boolean IncludeHelicopters +-- @field #boolean TacticalMenu +-- @field #table TacticalFrequencies +-- @field #table TacticalSubscribers +-- @field #number TacticalBaseFreq +-- @field #number TacticalIncrFreq +-- @field #number TacticalModulation +-- @field #number TacticalInterval -- @extends Core.Fsm#FSM @@ -499,7 +507,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "0.2.55", -- #string + version = "0.2.57", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -532,6 +540,7 @@ AWACS = { ContactsAO = {}, -- Utilities.FiFo#FIFO RadioQueue = {}, -- Utilities.FiFo#FIFO PrioRadioQueue = {}, -- Utilities.FiFo#FIFO + TacticalQueue = {}, -- Utilities.FiFo#FIFO AwacsTimeOnStation = 4, AwacsTimeStamp = 0, EscortsTimeOnStation = 4, @@ -587,6 +596,13 @@ AWACS = { GCIGroup = nil, locale = "en", IncludeHelicopters = false, + TacticalMenu = false, + TacticalFrequencies = {}, + TacticalSubscribers = {}, + TacticalBaseFreq = 130, + TacticalIncrFreq = 0.5, + TacticalModulation = radio.modulation.AM, + TacticalInterval = 120, } --- @@ -917,7 +933,7 @@ AWACS.TaskStatus = { --@field #boolean FromAI ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO-List 0.2.52 +-- TODO-List 0.2.53 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- -- DONE - WIP - Player tasking, VID @@ -1110,6 +1126,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self.Volume = 1.0 self.RadioQueue = FIFO:New() -- Utilities.FiFo#FIFO self.PrioRadioQueue = FIFO:New() -- Utilities.FiFo#FIFO + self.TacticalQueue = FIFO:New() -- Utilities.FiFo#FIFO self.maxspeakentries = 3 self.GoogleTTSPadding = 1 self.WindowsTTSPadding = 2.5 @@ -1180,6 +1197,15 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self.clientmenus = FIFO:New() -- Utilities.FiFo#FIFO + -- Tactical Menu + self.TacticalMenu = false + self.TacticalBaseFreq = 130 + self.TacticalIncrFreq = 0.5 + self.TacticalModulation = radio.modulation.AM + self.acticalFrequencies = {} + self.TacticalSubscribers = {} + self.TacticalInterval = 120 + -- SET for Intel Detection self.DetectionSet=SET_GROUP:New() @@ -1204,6 +1230,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station self:AddTransition("*", "LostCluster", "*") self:AddTransition("*", "LostContact", "*") self:AddTransition("*", "CheckRadioQueue", "*") + self:AddTransition("*", "CheckTacticalQueue", "*") self:AddTransition("*", "EscortShiftChange", "*") self:AddTransition("*", "AwacsShiftChange", "*") self:AddTransition("*", "FlightOnMission", "*") @@ -1354,6 +1381,142 @@ end -- Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +--- [User] Set the tactical information option, create 10 radio channels groups can subscribe and get Bogey Dope on a specific frequency automatically. +-- @param #AWACS self +-- @param #number BaseFreq Base Frequency to use, defaults to 130. +-- @param #number Increase Increase to use, defaults to 0.5, thus channels created are 130, 130.5, 131 .. etc. +-- @param #number Modulation Modulation to use, defaults to radio.modulation.AM. +-- @param #number Interval Seconds between each update call. +-- @param #number Number Number of Frequencies to create, can be 1..10. +-- @return #AWACS self +function AWACS:SetTacticalRadios(BaseFreq,Increase,Modulation,Interval,Number) + self:T(self.lid.."SetTacticalRadios") + self.TacticalMenu = true + self.TacticalBaseFreq = BaseFreq or 130 + self.TacticalIncrFreq = Increase or 0.5 + self.TacticalModulation = Modulation or radio.modulation.AM + self.TacticalInterval = Interval or 120 + local number = Number or 10 + if number < 1 then number = 1 end + if number > 10 then number = 10 end + for i=1,number do + local freq = self.TacticalBaseFreq + ((i-1)*self.TacticalIncrFreq) + self.TacticalFrequencies[freq] = freq + end + if self.AwacsSRS then + self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation,self.Volume) + self.TacticalSRS:SetCoalition(self.coalition) + self.TacticalSRS:SetGender(self.Gender) + self.TacticalSRS:SetCulture(self.Culture) + self.TacticalSRS:SetVoice(self.Voice) + self.TacticalSRS:SetPort(self.Port) + self.TacticalSRS:SetLabel("AWACS") + if self.PathToGoogleKey then + self.TacticalSRS:SetGoogle(self.PathToGoogleKey) + end + self.TacticalSRSQ = MSRSQUEUE:New("Tactical AWACS") + end + return self +end + +--- TODO +-- [Internal] _RefreshMenuNonSubscribed +-- @param #AWACS self +-- @return #AWACS self +function AWACS:_RefreshMenuNonSubscribed() + self:T(self.lid.."_RefreshMenuNonSubscribed") + local aliveset = self.clientset:GetAliveSet() + + for _,_group in pairs(aliveset) do + -- go through set and re-build the sub-menu + local grp = _group -- Wrapper.Client#CLIENT + local Group = grp:GetGroup() + local gname = nil + if Group and Group:IsAlive() then + gname = Group:GetName() + self:T(gname) + end + local menustr = self.clientmenus:ReadByID(gname) + local menu = menustr.tactical -- Core.Menu#MENU_GROUP + if not self.TacticalSubscribers[gname] and menu then + menu:RemoveSubMenus() + for _,_freq in UTILS.spairs(self.TacticalFrequencies) do + local modu = UTILS.GetModulationName(self.TacticalModulation) + local text = string.format("Subscribe to %.3f %s",_freq,modu) + local entry = MENU_GROUP_COMMAND:New(Group,text,menu,self._SubScribeTactRadio,self,Group,_freq) + end + end + end + return self +end + +--- [Internal] _UnsubScribeTactRadio +-- @param #AWACS self +-- @param Wrapper.Group#GROUP Group +-- @return #AWACS self +function AWACS:_UnsubScribeTactRadio(Group) + self:T(self.lid.."_UnsubScribeTactRadio") + local text = "" + local textScreen = "" + local GID, Outcome = self:_GetManagedGrpID(Group) + local gcallsign = self:_GetCallSign(Group,GID) or "Ghost 1" + local gname = Group:GetName() or "unknown" + + if Outcome and self.TacticalSubscribers[gname] then + -- Pilot is checked in + local Freq = self.TacticalSubscribers[gname] + self.TacticalFrequencies[Freq] = Freq + self.TacticalSubscribers[gname] = nil + local modu = self.TacticalModulation == 0 and "AM" or "FM" + text = string.format("%s, %s, switch back to AWACS main frequency!",gcallsign,self.callsigntxt) + self:_NewRadioEntry(text,text,GID,true,true,true,false,true) + self:_RefreshMenuNonSubscribed() + elseif self.AwacsFG then + -- no, unknown + local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale) + text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) + self:_NewRadioEntry(text,text,GID,Outcome,true,true,false) + end + return self +end + +--- [Internal] _SubScribeTactRadio +-- @param #AWACS self +-- @param Wrapper.Group#GROUP Group +-- @param #number Frequency +-- @return #AWACS self +function AWACS:_SubScribeTactRadio(Group,Frequency) + self:T(self.lid.."_SubScribeTactRadio") + local text = "" + local textScreen = "" + local GID, Outcome = self:_GetManagedGrpID(Group) + local gcallsign = self:_GetCallSign(Group,GID) or "Ghost 1" + local gname = Group:GetName() or "unknown" + + if Outcome then + -- Pilot is checked in + self.TacticalSubscribers[gname] = Frequency + self.TacticalFrequencies[Frequency] = nil + local modu = self.TacticalModulation == 0 and "AM" or "FM" + text = string.format("%s, %s, switch to %.3f %s for tactical information!",gcallsign,self.callsigntxt,Frequency,modu) + self:_NewRadioEntry(text,text,GID,true,true,true,false,true) + local menustr = self.clientmenus:ReadByID(gname) + local menu = menustr.tactical -- Core.Menu#MENU_GROUP + if menu then + menu:RemoveSubMenus() + local text = string.format("Unsubscribe %.3f %s",Frequency,modu) + local entry = MENU_GROUP_COMMAND:New(Group,text,menu,self._UnsubScribeTactRadio,self,Group) + end + elseif self.AwacsFG then + -- no, unknown + local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale) + text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) + self:_NewRadioEntry(text,text,GID,Outcome,true,true,false) + end + + return self +end + --- [Internal] Init localization -- @param #AWACS self -- @return #AWACS self @@ -1426,8 +1589,9 @@ end -- @param #boolean IsNew New -- @param #boolean FromAI From AI -- @param #boolean IsPrio Priority entry +-- @param #boolean Tactical Is for tactical info -- @return #AWACS self -function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,FromAI,IsPrio) +function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,FromAI,IsPrio,Tactical) self:T(self.lid.."_NewRadioEntry") local RadioEntry = {} -- #AWACS.RadioEntry RadioEntry.IsNew = IsNew @@ -1438,7 +1602,9 @@ function AWACS:_NewRadioEntry(TextTTS, TextScreen,GID,IsGroup,ToScreen,IsNew,Fro RadioEntry.Duration = STTS.getSpeechTime(TextTTS,0.95,false) or 8 RadioEntry.FromAI = FromAI RadioEntry.IsGroup = IsGroup - if IsPrio then + if Tactical then + self.TacticalQueue:Push(RadioEntry) + elseif IsPrio then self.PrioRadioQueue:Push(RadioEntry) else self.RadioQueue:Push(RadioEntry) @@ -1618,7 +1784,7 @@ function AWACS:_EventHandler(EventData) if WeaponDesc.category == 1 then Type = "Missile" -- AAM - local guidance = WeaponDesc.guidance -- IR=2, Radar Active=3, Radar Semi Active=4, Radar Passive = 5 + local guidance = WeaponDesc.guidance or 4 -- IR=2, Radar Active=3, Radar Semi Active=4, Radar Passive = 5 if guidance == 2 then warndist = 10 elseif guidance == 3 then @@ -2689,8 +2855,9 @@ end -- @param #AWACS self -- @param #string Callsign Callsign to address -- @param #number GID GroupID for comms +-- @param #boolean Tactical Is for tactical info -- @return #AWACS self -function AWACS:_CreateBogeyDope(Callsign,GID) +function AWACS:_CreateBogeyDope(Callsign,GID,Tactical) self:T(self.lid.."_CreateBogeyDope for "..Callsign.." GID "..GID) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup @@ -2716,7 +2883,7 @@ function AWACS:_CreateBogeyDope(Callsign,GID) local tag = contact.TargetGroupNaming local reportingname = contact.ReportingName -- DONE - add tag - self:_AnnounceContact(contact,false,group,true,tag,false,reportingname) + self:_AnnounceContact(contact,false,group,true,tag,false,reportingname,Tactical) end end @@ -2841,8 +3008,9 @@ end --- [Internal] AWACS Menu for Bogey Dope -- @param #AWACS self -- @param Wrapper.Group#GROUP Group Group to use +-- @param #boolean Tactical Check for tactical info -- @return #AWACS self -function AWACS:_BogeyDope(Group) +function AWACS:_BogeyDope(Group,Tactical) self:T(self.lid.."_BogeyDope") local text = "" local textScreen = "" @@ -2853,8 +3021,7 @@ function AWACS:_BogeyDope(Group) -- no intel yet! local clean = self.gettext:GetEntry("CLEAN",self.locale) text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) - self:_NewRadioEntry(text,text,0,false,true,true,false,true) - + self:_NewRadioEntry(text,text,0,false,true,true,false,true,Tactical) return self end @@ -2896,7 +3063,7 @@ function AWACS:_BogeyDope(Group) local clean = self.gettext:GetEntry("CLEAN",self.locale) text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) - self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true) + self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true,Tactical) else @@ -2915,9 +3082,9 @@ function AWACS:_BogeyDope(Group) textScreen = string.format("%s%d %s.\n",textScreen,contactsAO,groupstxt) end - self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false,true) + self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false,true,Tactical) - self:_CreateBogeyDope(self:_GetCallSign(Group,GID) or "Ghost 1",GID) + self:_CreateBogeyDope(self:_GetCallSign(Group,GID) or "Ghost 1",GID,Tactical) end end @@ -2925,7 +3092,7 @@ function AWACS:_BogeyDope(Group) -- no, unknown local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale) text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) - self:_NewRadioEntry(text,text,GID,Outcome,true,true,false) + self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,Tactical) end return self @@ -3528,11 +3695,17 @@ function AWACS:_CheckOut(Group,GID,dead) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup local Stack = managedgroup.AnchorStackNo local Angels = managedgroup.AnchorStackAngels + local GroupName = managedgroup.GroupName -- remove menus if managedgroup.IsPlayer then - if self.clientmenus:HasUniqueID(managedgroup.GroupName) then - local menus = self.clientmenus:PullByID(managedgroup.GroupName) --#AWACS.MenuStructure + if self.clientmenus:HasUniqueID(GroupName) then + local menus = self.clientmenus:PullByID(GroupName) --#AWACS.MenuStructure menus.basemenu:Remove() + if self.TacticalSubscribers[GroupName] then + local Freq = self.TacticalSubscribers[GroupName] + self.TacticalFrequencies[Freq] = Freq + self.TacticalSubscribers[GroupName] = nil + end end end -- delete open tasks @@ -3614,6 +3787,22 @@ function AWACS:_SetClientMenus() local friendly = MENU_GROUP_COMMAND:New(cgrp,"Friendly",vid,self._VID,self,cgrp,AWACS.IFF.FRIENDLY) end + local tactical + if self.TacticalMenu then + tactical = MENU_GROUP:New(cgrp,"Tactical Radio",basemenu) + if self.TacticalSubscribers[cgrpname] then + -- unsubscribe + local entry = MENU_GROUP_COMMAND:New(cgrp,"Unsubscribe",tactical,self._UnsubScribeTactRadio,self,cgrp) + else + -- subscribe + for _,_freq in UTILS.spairs(self.TacticalFrequencies) do + local modu = UTILS.GetModulationName(self.TacticalModulation) + local text = string.format("Subscribe to %.3f %s",_freq,modu) + local entry = MENU_GROUP_COMMAND:New(cgrp,text,tactical,self._SubScribeTactRadio,self,cgrp,_freq) + end + end + end + local ainfo = MENU_GROUP_COMMAND:New(cgrp,"Awacs Info",basemenu,self._ShowAwacsInfo,self,cgrp) local checkout = MENU_GROUP_COMMAND:New(cgrp,"Check Out",basemenu,self._CheckOut,self,cgrp) @@ -3631,6 +3820,7 @@ function AWACS:_SetClientMenus() unable = unable, abort = abort, commit=commit, + tactical=tactical, } self.clientmenus:PullByID(cgrpname) self.clientmenus:Push(menus,cgrpname) @@ -4812,8 +5002,9 @@ end -- @param #string Tag Tag name for this contact. Alpha, Brave, Charlie ... -- @param #boolean IsPopup This is a pop-up group -- @param #string ReportingName The NATO code reporting name for the contact, e.g. "Foxbat". "Bogey" if unknown. +-- @param #boolean Tactical -- @return #AWACS self -function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,ReportingName) +function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,ReportingName,Tactical) self:T(self.lid.."_AnnounceContact") -- do we have a group to talk to? local tag = "" @@ -4940,7 +5131,7 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo BRAText = string.gsub(BRAText,"BRA","brah") local prio = IsNew or IsBogeyDope - self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false,prio) + self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false,prio,Tactical) return self end @@ -5328,6 +5519,15 @@ function AWACS:_MergedCall(GID) local merge = self.gettext:GetEntry("MERGED",self.locale) local text = string.format("%s. %s. %s.",self.callsigntxt,pilotcallsign,merge) self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true) + if GID and GID ~= 0 then + local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + local name = managedgroup.GroupName + if self.TacticalSubscribers[name] then + self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true) + end + end + end return self end @@ -5703,6 +5903,10 @@ function AWACS:onafterStart(From, Event, To) self:__Started(-5) end + if self.TacticalMenu then + self:__CheckTacticalQueue(55) + end + self:__Status(-30) return self end @@ -6316,6 +6520,77 @@ function AWACS:onafterLostCluster(From,Event,To,Cluster,Mission) return self end +--- [Internal] onafterCheckTacticalQueue +-- @param #AWACS self +-- @param #string From +-- @param #string Event +-- @param #string To +-- @return #AWACS self +function AWACS:onafterCheckTacticalQueue(From,Event,To) + self:T({From, Event, To}) + -- do we have messages queued? + + if self.clientset:CountAlive() == 0 then + self:T(self.lid.."No player connected.") + self:__CheckTacticalQueue(-5) + return self + end + + for _name,_freq in pairs(self.TacticalSubscribers) do + local Group = nil + if _name then + Group = GROUP:FindByName(_name) + end + if Group and Group:IsAlive() then + self:_BogeyDope(Group,true) + end + end + + if (self.TacticalQueue:IsNotEmpty()) then + + while self.TacticalQueue:Count() > 0 do + + local RadioEntry = self.TacticalQueue:Pull() -- #AWACS.RadioEntry + self:T({RadioEntry}) + local frequency = self.TacticalBaseFreq + if RadioEntry.GroupID and RadioEntry.GroupID ~= 0 then + local managedgroup = self.ManagedGrps[RadioEntry.GroupID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + local name = managedgroup.GroupName + frequency = self.TacticalSubscribers[name] + end + end + -- AI AWACS Speaking + local gtext = RadioEntry.TextTTS + if self.PathToGoogleKey then + gtext = string.format("%s",gtext) + end + self.TacticalSRSQ:NewTransmission(gtext,nil,self.TacticalSRS,nil,0.5,nil,nil,nil,frequency,self.TacticalModulation,nil,nil,nil,nil,nil) + + self:T(RadioEntry.TextTTS) + + if RadioEntry.ToScreen and RadioEntry.TextScreen and (not self.SuppressScreenOutput) then + if RadioEntry.GroupID and RadioEntry.GroupID ~= 0 then + local managedgroup = self.ManagedGrps[RadioEntry.GroupID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + MESSAGE:New(RadioEntry.TextScreen,20,"AWACS"):ToGroup(managedgroup.Group) + self:T(RadioEntry.TextScreen) + end + else + MESSAGE:New(RadioEntry.TextScreen,20,"AWACS"):ToCoalition(self.coalition) + end + end + end + + end -- end while + + if self:Is("Running") then + self:__CheckTacticalQueue(-self.TacticalInterval) + end + return self +end + + --- [Internal] onafterCheckRadioQueue -- @param #AWACS self -- @param #string From diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 126705e2f..bde363415 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -4206,11 +4206,13 @@ function FLIGHTGROUP:GetClosestAirbase() local coord=group:GetCoordinate() local coalition=self:GetCoalition() - - local airbase=coord:GetClosestAirbase() --(nil, coalition) - - return airbase - + + if coord then + local airbase=coord:GetClosestAirbase() --(nil, coalition) + return airbase + else + return nil + end else return nil diff --git a/Moose Development/Moose/Ops/PlayerTask.lua b/Moose Development/Moose/Ops/PlayerTask.lua index 196e422d0..d44e9c644 100644 --- a/Moose Development/Moose/Ops/PlayerTask.lua +++ b/Moose Development/Moose/Ops/PlayerTask.lua @@ -98,7 +98,7 @@ PLAYERTASK = { --- PLAYERTASK class version. -- @field #string version -PLAYERTASK.version="0.1.17" +PLAYERTASK.version="0.1.18" --- Generic task condition. -- @type PLAYERTASK.Condition @@ -1008,6 +1008,7 @@ do -- @field Core.ClientMenu#CLIENTMENUMANAGER ActiveTaskMenuTemplate -- @field Core.ClientMenu#CLIENTMENU ActiveTopMenu -- @field Core.ClientMenu#CLIENTMENU ActiveInfoMenu +-- @field Core.ClientMenu#CLIENTMENU MenuNoTask -- @extends Core.Fsm#FSM --- @@ -1336,6 +1337,7 @@ PLAYERTASKCONTROLLER = { InfoHasCoordinate = false, UseTypeNames = false, Scoring = nil, + MenuNoTask = nil, } --- @@ -3469,6 +3471,19 @@ function PLAYERTASKCONTROLLER:_UpdateJoinMenuTemplate() local actinfomenu = self.ActiveInfoMenu --local entrynumbers = {} --local existingentries = {} + + if self.TaskQueue:Count() == 0 and self.MenuNoTask == nil then + local menunotasks = self.gettext:GetEntry("MENUNOTASKS",self.locale) + self.MenuNoTask = controller:NewEntry(menunotasks,self.JoinMenu) + controller:AddEntry(self.MenuNoTask) + end + + if self.TaskQueue:Count() > 0 and self.MenuNoTask ~= nil then + controller:DeleteGenericEntry(self.MenuNoTask) + controller:DeleteF10Entry(self.MenuNoTask) + self.MenuNoTask = nil + end + local maxn = self.menuitemlimit -- Generate task type menu items for _type,_ in pairs(taskpertype) do @@ -3641,8 +3656,13 @@ function PLAYERTASKCONTROLLER:_CreateJoinMenuTemplate() self.JoinInfoMenu = JoinTaskMenuTemplate:NewEntry(menutaskinfo,self.JoinTopMenu) end - if self.TaskQueue:Count() == 0 then - JoinTaskMenuTemplate:NewEntry(menunotasks,self.JoinMenu) + if self.TaskQueue:Count() == 0 and self.MenuNoTask == nil then + self.MenuNoTask = JoinTaskMenuTemplate:NewEntry(menunotasks,self.JoinMenu) + end + + if self.TaskQueue:Count() > 0 and self.MenuNoTask ~= nil then + JoinTaskMenuTemplate:DeleteGenericEntry(self.MenuNoTask) + self.MenuNoTask = nil end self.JoinTaskMenuTemplate = JoinTaskMenuTemplate diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 276ec5b8d..dd52825fa 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -11,7 +11,7 @@ -- @module Wrapper.Airbase -- @image Wrapper_Airbase.JPG - +--- -- @type AIRBASE -- @field #string ClassName Name of the class, i.e. "AIRBASE". -- @field #table CategoryName Names of airbase categories. @@ -548,6 +548,8 @@ AIRBASE.Syria={ -- * AIRBASE.MarianaIslands.Saipan_Intl -- * AIRBASE.MarianaIslands.Tinian_Intl -- * AIRBASE.MarianaIslands.Olf_Orote +-- * AIRBASE.MarianaIslands.Pagan_Airstrip +-- * AIRBASE.MarianaIslands.North_West_Field -- -- @field MarianaIslands AIRBASE.MarianaIslands = { @@ -557,6 +559,8 @@ AIRBASE.MarianaIslands = { ["Saipan_Intl"] = "Saipan Intl", ["Tinian_Intl"] = "Tinian Intl", ["Olf_Orote"] = "Olf Orote", + ["Pagan_Airstrip"] = "Pagan Airstrip", + ["North_West_Field"] = "North West Field", } --- Airbases of the South Atlantic map: @@ -787,7 +791,13 @@ function AIRBASE:Register(AirbaseName) -- Category. self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME - + + -- H2 is bugged + --if self.AirbaseName == "H4" and self.descriptors == nil then + --self:E("***** H4 on Syria map is currently bugged!") + --return nil + --end + -- Set category. if self.category==Airbase.Category.AIRDROME then self.isAirdrome=true