local f0_local0 = module local f0_local1, f0_local2 = ... f0_local0( f0_local1, package.seeall ) CoD.PrintModuleLoad( _NAME ) INTERVAL_MS = 25 MAX_COUNTER = 200 MAX_COUNTER_GOBACK = 20 MAX_DURATION_COUNTER = 400 DISABLE_NAVIGATING_OVERLAY = 0 STATE = { IDLE = 0, WORKING_DROPBACK = 1, WORKING_MOVEFORWARD = 2 } LUI.MenuAutoNav.m_menuAutoNav = 0 s_navTableSP = { { destScreen = "resume_campaign", route = { { topScreen = "main_menu", action = "sp_button" }, { topScreen = "main_campaign", action = "btn_resume_id" }, { topScreen = "resume_game_menu", action = "" } } }, { destScreen = "mission_select", route = { { topScreen = "main_menu", action = "sp_button" }, { topScreen = "main_campaign", action = "btn_mission_select_id" }, { topScreen = "level_select_iw6", action = "" } } }, { destScreen = "mp", route = { { topScreen = "main_menu", action = "mp_button" } }, routeOverlayDelay = 5000 }, { destScreen = "aliens", route = { { topScreen = "main_menu", action = "extinction_button" } }, routeOverlayDelay = 5000 }, { destScreen = "squads", route = { { topScreen = "main_menu", action = "squadvssquad_button" } }, routeOverlayDelay = 5000 } } s_navTableMP = { { destScreen = "sp", route = { { topScreen = "mp_main_menu", action = "button_secondary" }, { topScreen = "main_choose_exe_popup_menu", action = "main_choose_sp_button" } }, routeOverlayDelay = 5000 }, { destScreen = "mp", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_7" } } }, { destScreen = "aliens", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_9" } } }, { destScreen = "squads", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_8" } } }, { destScreen = "xboxlive", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive", action = "" } } }, { destScreen = "splitscreen", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_1" }, { topScreen = "menu_splitscreensignin", action = "" } } }, { destScreen = "systemlink", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_2" }, { topScreen = "menu_systemlink", action = "" } } }, { destScreen = "options", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_6" } } }, { destScreen = "xboxlive_findmatch", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive", action = "find_match_button_id" }, { topScreen = "playlist_main", action = "" } } }, { destScreen = "xboxlive_privatematch", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive", action = "private_match_button_id" }, { topScreen = "menu_xboxlive_privatelobby", action = "" } } }, { destScreen = "xboxlive_privatematch_gamesetup", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive", action = "private_match_button_id" }, { topScreen = "menu_xboxlive_privatelobby", action = "setup_match_button_id" }, { topScreen = "menu_systemlink_gamesetup_root", action = "" } } }, { destScreen = "xboxlive_create_squad", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive", action = "create_squad_button_id" }, { topScreen = "cac_edit_main", action = "" } } }, { destScreen = "xboxlive_barracks_leaderboards", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive", action = "barracks_button_id" }, { topScreen = "menu_barracks", action = "leaderboard_button_id" }, { topScreen = "leaderboards", action = "" } } }, { destScreen = "xboxlive_aliens_loadout", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive", action = "aliens_loadout_btn_id" }, { topScreen = "aliens_cac_menu", action = "" } } }, { destScreen = "xboxlive_aliens_leaderboards", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive", action = "leaderboards_button_id" }, { topScreen = "mp_leaderboard_main", action = "" } } }, { destScreen = "squadvssquad_squad_assault", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive*", action = "squads_mode_button_squad_assault" } } }, { destScreen = "squadvssquad_squad_vs_squad", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive*", action = "squads_mode_button_squad_vs_squad" } } }, { destScreen = "squadvssquad_safeguard", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive*", action = "squads_mode_button_safeguard" } } }, { destScreen = "squadvssquad_wargame", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive*", action = "squads_mode_button_wargame" } } }, { destScreen = "squadvssquad_squad_reports", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_0" }, { topScreen = "menu_xboxlive*", action = "squads_mode_button_squad_reports" }, { topScreen = "squads_hq_menu*", action = "squads_mode_button_squad_reports" } } }, { destScreen = "squadvssquad_local_play", route = { { topScreen = "mp_main_menu", action = "btn_MPMain_1" }, { topScreen = "menu_splitscreensignin", action = "" } } } } function new() local f1_local0 = {} setmetatable( f1_local0, { __index = _M } ) f1_local0.m_state = STATE.IDLE f1_local0.m_controller = -1 f1_local0.m_counter = 0 f1_local0.m_durationCounter = 0 f1_local0.m_currentRoute = {} f1_local0.m_root = 0 f1_local0.m_timerElement = 0 return f1_local0 end function Reset() if LUI.MenuAutoNav.ShouldCloseOverlay() then LUI.MenuAutoNav.CloseOverlay() end local f2_local0 = LUI.MenuAutoNav.GetInstance() if f2_local0.m_timerElement and f2_local0.m_timerElement ~= 0 and f2_local0.m_root and f2_local0.m_root ~= 0 then f2_local0.m_root:removeElement( f2_local0.m_timerElement ) f2_local0.m_timerElement:close() end f2_local0.m_state = STATE.IDLE f2_local0.m_controller = -1 f2_local0.m_counter = 0 f2_local0.m_durationCounter = 0 f2_local0.m_currentRoute = {} f2_local0.m_root = 0 f2_local0.m_timerElement = 0 end function GetInstance() if LUI.MenuAutoNav.m_menuAutoNav == 0 then LUI.MenuAutoNav.m_menuAutoNav = LUI.MenuAutoNav.new() end return LUI.MenuAutoNav.m_menuAutoNav end function IsRunning() local f4_local0 = LUI.MenuAutoNav.GetInstance() if f4_local0.m_state ~= STATE.IDLE then return true else return false end end function Stop() if IsRunning() then Reset() end end function SendButtonPress( f6_arg0, f6_arg1, f6_arg2 ) local f6_local0 = { name = "gamepad_button", immediate = true, down = true, button = f6_arg0, qualifier = f6_arg1, controller = f6_arg2 } local f6_local1 = Engine.GetLuiRoot() if not f6_local1 then return false else f6_local1:dispatchEventToRoot( f6_local0 ) return true end end function FindRouteEntry( f7_arg0 ) local f7_local0 = LUI.MenuAutoNav.GetInstance() assert( f7_arg0 ) local f7_local1 = nil if Engine.IsMultiplayer() then f7_local1 = s_navTableMP else f7_local1 = s_navTableSP end if f7_local1 then for f7_local5, f7_local6 in ipairs( f7_local1 ) do if f7_local6.route and string.lower( f7_arg0 ) == string.lower( f7_local6.destScreen ) then return f7_local6 end end end return nil end function Yield() local f8_local0 = LUI.MenuAutoNav.GetInstance() f8_local0.m_counter = f8_local0.m_counter + 1 if f8_local0.m_counter > MAX_COUNTER then DebugPrint( "MenuAutoNav: Timeout!" ) LUI.MenuAutoNav.Stop() return else end end function IsMenuInCurrentRoute( f9_arg0 ) local f9_local0 = LUI.MenuAutoNav.GetInstance() assert( f9_arg0 ) local f9_local1 = LUI.MenuAutoNav.GetInstance() if f9_local1.m_currentRoute then for f9_local5, f9_local6 in ipairs( f9_local1.m_currentRoute ) do if string.lower( f9_local6.topScreen ) == string.lower( f9_arg0 ) then return true, f9_local5 end end end return false, -1 end function HandleMenuAutoNavOverlayRefresh( f10_arg0, f10_arg1 ) if LUI.MenuAutoNav.ShouldCloseOverlay() then LUI.MenuAutoNav.CloseOverlay() end end function menu_auto_nav_overlay() return { type = "UIElement", id = "menu_auto_nav_overlay_id", states = { default = { topAnchor = true, bottomAnchor = true, leftAnchor = true, rightAnchor = true, left = 0, right = 0, top = 0, bottom = 0 } }, handlers = { menu_auto_nav_overlay_refresh = HandleMenuAutoNavOverlayRefresh }, children = { { type = "UIImage", id = "menu_auto_nav_background_id", states = { default = CoD.ColorizeState( Swatches.Overlay.Color, { topAnchor = true, bottomAnchor = true, leftAnchor = true, rightAnchor = true, left = 0, right = 0, top = 0, bottom = 0, material = RegisterMaterial( "white" ), alpha = 1 } ) }, children = { { type = "generic_loading_widget", properties = { message = Engine.Localize( "@SPEECH_NAVIGATING" ) } } } }, { type = "UITimer", id = "menu_auto_nav_overlay_timer", properties = { event = "menu_auto_nav_overlay_refresh", interval = 25, disposable = false, broadcastToRoot = false } } } } end function OpenOverlay( f12_arg0 ) if DISABLE_NAVIGATING_OVERLAY ~= 0 then return end local f12_local0 = Engine.GetLuiRoot() if not f12_local0 then DebugPrint( "MenuAutoNavOverlay: Error, no root found. Cannot open overlay." ) return elseif f12_local0.m_menuAutoNavOverlay then DebugPrint( "MenuAutoNavOverlay: Ignoring open request because we are already open." ) return end local m_menuAutoNavOverlay = LUI.MenuBuilder.buildItems( menu_auto_nav_overlay(), {}, f12_local0 ) m_menuAutoNavOverlay:animateToState( "default" ) m_menuAutoNavOverlay:setPriority( 400 ) f12_local0:addElement( m_menuAutoNavOverlay ) f12_local0.m_menuAutoNavOverlay = m_menuAutoNavOverlay if f12_arg0 and f12_arg0 > 0 then f12_local0.m_menuAutoNavOverlayDelay = f12_arg0 f12_local0.m_menuAutoNavOverlayTimeStamp = 0 else f12_local0.m_menuAutoNavOverlayDelay = 0 f12_local0.m_menuAutoNavOverlayTimeStamp = 0 end end function CloseOverlay() local f13_local0 = Engine.GetLuiRoot() if not f13_local0 then DebugPrint( "MenuAutoNavOverlay: Error, no root found, therefore we cannot close overlay." ) return elseif not f13_local0.m_menuAutoNavOverlay then DebugPrint( "MenuAutoNavOverlay: Warning, ignoring attempt to close overlay because it is already closed." ) return else f13_local0:removeElement( f13_local0.m_menuAutoNavOverlay ) f13_local0.m_menuAutoNavOverlay = nil f13_local0.m_menuAutoNavOverlayDelay = nil f13_local0.m_menuAutoNavOverlayTimeStamp = nil end end function ShouldCloseOverlay() if LUI.MenuAutoNav.IsRunning() then return false end local f14_local0 = Engine.GetLuiRoot() if not f14_local0 then return false elseif not f14_local0.m_menuAutoNavOverlay then return false elseif f14_local0.m_menuAutoNavOverlayDelay and f14_local0.m_menuAutoNavOverlayTimeStamp and f14_local0.m_menuAutoNavOverlayDelay > 0 then local f14_local1 = Engine.GetMilliseconds() if f14_local0.m_menuAutoNavOverlayTimeStamp == 0 then f14_local0.m_menuAutoNavOverlayTimeStamp = f14_local1 + f14_local0.m_menuAutoNavOverlayDelay return false elseif f14_local1 < f14_local0.m_menuAutoNavOverlayTimeStamp then return false end end return true end function HandleTimerEvent( f15_arg0, f15_arg1 ) local f15_local0 = LUI.MenuAutoNav.GetInstance() if not f15_local0.m_currentRoute then DebugPrint( "MenuAutoNav: Current route is empty. Bailing" ) Stop() return elseif #f15_local0.m_currentRoute < 1 then DebugPrint( "MenuAutoNav: Current route is empty. Bailing" ) Stop() return end f15_local0.m_durationCounter = f15_local0.m_durationCounter + 1 if f15_local0.m_durationCounter > MAX_DURATION_COUNTER then DebugPrint( "MenuAutoNav: Max duration counter exceeded. Bailing" ) Stop() return elseif f15_local0.m_state == STATE.WORKING_DROPBACK then if LUI.FlowManager.IsTopMenuModal() then DebugPrint( "MenuAutoNav: A modal menu popped up while attempting to find a starting point. We are stopping here." ) LUI.MenuAutoNav.Stop() return end local f15_local1 = LUI.FlowManager.GetTopOpenAndVisibleMenuName() if not f15_local1 then Yield() return end local f15_local2, f15_local3 = nil f15_local2, f15_local3 = IsMenuInCurrentRoute( f15_local1 ) if not f15_local2 or f15_local2 ~= true then f15_local0.m_counter = f15_local0.m_counter + 1 if f15_local0.m_counter <= MAX_COUNTER_GOBACK then return elseif string.lower( f15_local1 ) == string.lower( "main_menu" ) or string.lower( f15_local1 ) == string.lower( "mp_main_menu" ) then DebugPrint( "MenuAutoNav: Menu we are looking for not found, and we cannot move back any more. Stopping!" ) LUI.MenuAutoNav.Stop() return elseif string.lower( f15_local1 ) == string.lower( "menu_splitscreensignin" ) then LUI.FlowManager.RequestLeaveMenuByName( "menu_splitscreensignin" ) f15_local0.m_counter = 0 elseif LUI.MenuAutoNav.SendButtonPress( "secondary", nil, f15_local0.m_controller ) == true then f15_local0.m_counter = 0 end return elseif f15_local3 > 1 then else f15_local0.m_state = STATE.WORKING_MOVEFORWARD f15_local0.m_counter = 0 end while f15_local3 > 1 do table.remove( f15_local0.m_currentRoute, 1 ) f15_local3 = f15_local3 - 1 end f15_local0.m_state = STATE.WORKING_MOVEFORWARD f15_local0.m_counter = 0 end if f15_local0.m_state == STATE.WORKING_MOVEFORWARD then local f15_local1 = Engine.GetLuiRoot() if f15_local1 == nil then DebugPrint( "MenuAutoNav: Error, we have no root! Stopping" ) Stop() return end local f15_local2 = f15_local0.m_currentRoute[1] if string.lower( f15_local2.action ) == string.lower( "" ) then DebugPrint( "MenuAutoNav: Our current route action is empty, therefore we should be at our destination. Done." ) Stop() return elseif string.lower( f15_local2.action ) == string.lower( "button_secondary" ) then if LUI.MenuAutoNav.SendButtonPress( "secondary", nil, f15_local0.m_controller ) ~= true then Yield() return end else local f15_local3 = f15_local1:getFirstDescendentById( f15_local2.action ) if not f15_local3 then Yield() return elseif f15_local3.disabled and not f15_local3.locked then Yield() return end f15_local3:processEvent( { name = "button_action", controller = f15_local0.m_controller } ) f15_local3:processEvent( { name = "button_down", controller = f15_local0.m_controller } ) end table.remove( f15_local0.m_currentRoute, 1 ) if #f15_local0.m_currentRoute >= 1 then f15_local0.m_counter = 0 return end DebugPrint( "MenuAutoNav: Done!" ) end Stop() end function DebugDumpRoute( f16_arg0 ) local f16_local0 = LUI.MenuAutoNav.GetInstance() DebugPrint( "----------------------------------------------------------------" ) DebugPrint( "MenuAutoNav: Route:" ) for f16_local4, f16_local5 in ipairs( f16_arg0 ) do DebugPrint( " #" .. tostring( f16_local4 ) .. " : topScreen=\"" .. tostring( f16_local5.topScreen ) .. "\", action=\"" .. tostring( f16_local5.action ) .. "\"" ) end DebugPrint( "----------------------------------------------------------------" ) end function Goto( f17_arg0, f17_arg1 ) assert( f17_arg0 ) local f17_local0 = LUI.MenuAutoNav.GetInstance() if IsRunning() then DebugPrint( "MenuAutoNav: Error, an outstanding auto navigation is still working. Unable to navigate to \"" .. f17_arg0 .. "\"!" ) return false end local f17_local1 = FindRouteEntry( f17_arg0 ) if not f17_local1 then DebugPrint( "MenuAutoNav: Error, unable to find a route to \"" .. f17_arg0 .. "\"!" ) return false end local f17_local2 = f17_local1.route local f17_local3 = f17_local1.routeOverlayDelay or 0 local f17_local4 = Engine.GetLuiRoot() if f17_local4 == nil then DebugPrint( "MenuAutoNav: Error, we do not appear to have a root! Unable to create timer for autonav process!" ) return false end f17_local0.m_controller = f17_arg1 f17_local0.m_counter = 0 f17_local0.m_currentRoute = {} for f17_local8, f17_local9 in ipairs( f17_local2 ) do table.insert( f17_local0.m_currentRoute, f17_local9 ) end f17_local0.m_state = STATE.WORKING_DROPBACK self = LUI.UITimer.new( INTERVAL_MS, { name = "menu_auto_nav_timer" } ) self.id = "MenuAutoNavTimer" f17_local4:addElement( self ) f17_local0.m_root = f17_local4 f17_local0.m_timerElement = self DebugPrint( "MenuAutoNav: Goto( \"" .. f17_arg0 .. "\") started" ) LUI.MenuAutoNav.OpenOverlay( f17_local3 ) return true end LockTable( _M )