-- private variables local topMenu local rightButtonsPanel local leftButtonsPanel local rightGameButtonsPanel local topLeftTogglesPanel local topLeftButtonsPanel local topLeftOnlinePlayersLabel local topLeftDiscordStreamersLabel local topLeftYoutubeViewersLabel local topLeftYoutubeStreamersLabel local fpsLabel local pingLabel local topLeftYoutubeLink local topLeftDiscordLink local url_discord = "" local url_youtube = "" local lastSyncValue = -1 local fpsEvent = nil local fpsMin = -1; local fpsMax = -1; local pingPanel local MainPingPanel local mainFpsPanel local fpsPanel2 local PingWidget local pingImg local zoomInButton = nil local zoomOutButton = nil local zoomLevel = 2 local managerAccountsButton = nil -- private functions local function addButton(id, description, icon, callback, panel, toggle, front) local class if toggle then class = 'MainToggleButton' else class = 'Button' end local button = panel:getChildById(id) if not button then button = g_ui.createWidget(class) if front then panel:insertChild(1, button) else panel:addChild(button) end end button:setId(id) button:setTooltip(description) if toggle then button:setIcon(resolvepath(icon, 3)) else button:setText(description) end button.onMouseRelease = function(widget, mousePos, mouseButton) if widget:containsPoint(mousePos) and mouseButton ~= MouseMidButton then callback() return true end end return button end local function updateZoomButtons() if zoomInButton then zoomInButton:setEnabled(zoomLevel < 6) end if zoomOutButton then zoomOutButton:setEnabled(zoomLevel > 1.5) end end local function setZoom(value) local oldValue = zoomLevel zoomLevel = math.max(1.5, math.min(6, value)) modules.client_options.setOption('hudScale', zoomLevel) updateZoomButtons() return oldValue ~= zoomLevel end -- public functions function init() connect(g_game, { onGameStart = online, onGameEnd = offline, onPingBack = updatePing }) connect(g_app, { onFps = updateFps }) topMenu = g_ui.displayUI('topmenu') topLeftButtonsPanel = topMenu:getChildById('topLeftButtonsPanel') topLeftTogglesPanel = topMenu:getChildById('topLeftTogglesPanel') rightButtonsPanel = topMenu:getChildById('rightButtonsPanel') leftButtonsPanel = topMenu:getChildById('leftButtonsPanel') rightGameButtonsPanel = topMenu:getChildById('rightGameButtonsPanel') pingLabel = topMenu:getChildById('pingLabel') fpsLabel = topMenu:getChildById('fpsLabel') topLeftOnlinePlayersLabel = topMenu:recursiveGetChildById('topLeftOnlinePlayersLabel') topLeftDiscordStreamersLabel = topMenu:recursiveGetChildById('topLeftDiscordStreamersLabel') topLeftYoutubeViewersLabel = topMenu:recursiveGetChildById('topLeftYoutubeViewersLabel') topLeftYoutubeStreamersLabel = topMenu:recursiveGetChildById('topLeftYoutubeStreamersLabel') topLeftYoutubeLink = topMenu:recursiveGetChildById('youtubeIcon') topLeftDiscordLink = topMenu:recursiveGetChildById('discordIcon') Keybind.new("UI", "Toggle Top Menu", "Ctrl+Shift+T", "") Keybind.bind("UI", "Toggle Top Menu", { { type = KEY_DOWN, callback = toggle, } }) if Services.websites and not managerAccountsButton then managerAccountsButton = modules.client_topmenu.addTopRightRegularButton('hotkeysButton', tr('Manage Account'), nil, openManagerAccounts) end if g_platform.isMobile() then zoomInButton = modules.client_topmenu.addLeftToggleButton('zoomInButton', 'Zoom In', '/images/topbuttons/zoomin', function() setZoom(zoomLevel + 0.5) end) zoomOutButton = modules.client_topmenu.addLeftToggleButton('zoomOutButton', 'Zoom Out', '/images/topbuttons/zoomout', function() setZoom(zoomLevel - 0.5) end) updateZoomButtons() end if g_game.isOnline() then online() end end function terminate() disconnect(g_game, { onGameStart = online, onGameEnd = offline, onPingBack = updatePing }) disconnect(g_app, { onFps = updateFps }) topMenu:destroy() if PingWidget and not PingWidget:isDestroyed() then PingWidget:destroy() PingWidget = nil end if managerAccountsButton and not managerAccountsButton:isDestroyed() then managerAccountsButton:destroy() managerAccountsButton = nil end if g_platform.isMobile() then if zoomInButton and not zoomOutButton:isDestroyed() then zoomInButton:destroy() zoomInButton= nil end if zoomOutButton and not zoomOutButton:isDestroyed() then zoomOutButton:destroy() zoomOutButton= nil end end Keybind.delete("UI", "Toggle Top Menu") end function hide() topMenu:hide() modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'parent', AnchorTop) end function show() topMenu:show() topMenu:raise() topMenu:focus() if modules.game_interface.currentViewMode == 2 then modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'topMenu', AnchorBottom) end end function online() showGameButtons() addEvent(function() if modules.game_interface.currentViewMode ~= 2 and g_game.isOnline() then hide() end local showPing = modules.client_options.getOption('showPing') local pingFeatureAvailable = g_game.getFeature(GameClientPing) or g_game.getFeature(GameExtendedClientPing) if not PingWidget then PingWidget = g_ui.loadUI("pingFps", modules.game_interface.getMapPanel()) MainPingPanel = g_ui.createWidget("testPingPanel", PingWidget:getChildByIndex(1)) MainPingPanel:setId("ping") pingImg = MainPingPanel:getChildByIndex(1) pingPanel = MainPingPanel:getChildByIndex(2) mainFpsPanel = g_ui.createWidget("testPingPanel", PingWidget:getChildByIndex(2)) mainFpsPanel:setId("fps") fpsPanel2 = mainFpsPanel:getChildByIndex(2) end if showPing and pingFeatureAvailable then pingLabel:show() if pingPanel then pingPanel:show() pingImg:show() end else pingLabel:hide() if pingPanel then pingPanel:hide() pingImg:hide() end end pingImg:setVisible(showPing) pingPanel:setVisible(showPing) local showFps = modules.client_options.getOption('showFps') fpsPanel2:setVisible(showFps) end) end function offline() hideGameButtons() pingLabel:hide() if pingPanel then pingPanel:hide() pingImg:hide() end fpsMin = -1 end function updateFps(fps) if fpsLabel:isVisible() then -- for the time being retained for the extended view local text = 'FPS ' .. fps if g_game.isOnline() then local vsync = modules.client_options.getOption('vsync') if fpsEvent == nil and lastSyncValue ~= vsync then fpsEvent = scheduleEvent(function() fpsMin = -1 lastSyncValue = vsync fpsEvent = nil end, 2000) end if fpsMin == -1 then fpsMin = fps fpsMax = fps end if fps > fpsMax then fpsMax = fps end if fps < fpsMin then fpsMin = fps end local midFps = math.floor((fpsMin + fpsMax) / 2) fpsLabel:setTooltip('Min: ' .. fpsMin .. '\nMid: ' .. midFps .. '\nMax: ' .. fpsMax) else fpsLabel:removeTooltip() end fpsLabel:setText(text) end local text = fps .. ' fps' if fpsPanel2 and fpsPanel2:isVisible() then if g_game.isOnline() then fpsPanel2:setText(text) end end end function updatePing(ping) if pingLabel:isVisible() then -- for the time being retained for the extended view local text = 'Ping: ' local color if ping < 0 then text = text .. '??' color = 'yellow' else text = text .. ping .. ' ms' if ping >= 500 then color = 'red' elseif ping >= 250 then color = 'yellow' else color = 'green' end end pingLabel:setColor(color) pingLabel:setText(text) end if pingPanel and pingPanel:isVisible() then local text local imagen if ping < 0 then text = 'High lag (??)' imagen = nil elseif ping >= 500 then text = 'High lag (' .. ping .. ' ms)' imagen = '/images/ui/high_ping' elseif ping >= 250 then text = 'Medium lag (' .. ping .. ' ms)' imagen = '/images/ui/medium_ping' else text = 'Low lag (' .. ping .. ' ms)' imagen = '/images/ui/low_ping' end pingImg:setImageSource(imagen) pingPanel:setText(text) end end function setPingVisible(enable) pingLabel:setVisible(enable) if pingPanel then pingPanel:setVisible(enable) pingImg:setVisible(enable) end end function setFpsVisible(enable) fpsLabel:setVisible(enable) if fpsPanel2 then fpsPanel2:setVisible(enable) end end function setPlayersOnline(value) topLeftOnlinePlayersLabel:setText(value .. " " .. tr('players online')) end function setDiscordStreams(value) topLeftDiscordStreamersLabel:setText(value) end function setYoutubeStreams(value) topLeftYoutubeStreamersLabel:setText(value) end function setYoutubeViewers(value) topLeftYoutubeViewersLabel:setText(value) end function setLinkYoutube(value) url_youtube = value topLeftYoutubeLink.onClick = function() if url_youtube then g_platform.openUrl(url_youtube) end end end function setLinkDiscord(value) url_discord = value topLeftDiscordLink.onClick = function() if url_discord then g_platform.openUrl(url_discord) end end end function addLeftButton(id, description, icon, callback, front) return addButton(id, description, icon, callback, leftButtonsPanel, false, front) end function addLeftToggleButton(id, description, icon, callback, front) return addButton(id, description, icon, callback, leftButtonsPanel, true, front) end function addRightButton(id, description, icon, callback, front) return addButton(id, description, icon, callback, topLeftTogglesPanel, false, front) end function addRightToggleButton(id, description, icon, callback, front) return addButton(id, description, icon, callback, rightButtonsPanel, true, front) end function addLeftGameButton(id, description, icon, callback, front, index) if not g_modules.getModule("game_mainpanel"):isLoaded() then -- Temp fix. game_mainpanel is not loaded if called from a client_XXX. scheduleEvent(function() return modules.game_mainpanel.addSpecialToggleButton(id, description, icon, callback, front, index) end, 100) else return modules.game_mainpanel.addSpecialToggleButton(id, description, icon, callback, front, index) end end function addLeftGameToggleButton(id, description, icon, callback, front, index) if not g_modules.getModule("game_mainpanel"):isLoaded() then -- Temp fix. game_mainpanel is not loaded if called from a client_XXX. scheduleEvent(function() return modules.game_mainpanel.addSpecialToggleButton(id, description, icon, callback, front, index) end, 100) else return modules.game_mainpanel.addSpecialToggleButton(id, description, icon, callback, front, index) end end function addRightGameButton(id, description, icon, callback, front, index) if not g_modules.getModule("game_mainpanel"):isLoaded() then -- Temp fix. game_mainpanel is not loaded if called from a client_XXX. scheduleEvent(function() return modules.game_mainpanel.addToggleButton(id, description, icon, callback, front, index) end, 100) else return modules.game_mainpanel.addToggleButton(id, description, icon, callback, front, index) end end function addRightGameToggleButton(id, description, icon, callback, front, index) if not g_modules.getModule("game_mainpanel"):isLoaded() then -- Temp fix. game_mainpanel is not loaded if called from a client_XXX. scheduleEvent(function() return modules.game_mainpanel.addToggleButton(id, description, icon, callback, front, index) end, 100) else return modules.game_mainpanel.addToggleButton(id, description, icon, callback, front, index) end end function addTopRightRegularButton(id, description, icon, callback, front) return addButton(id, description, icon, callback, topLeftButtonsPanel, false, front) end function addTopRightToggleButton(id, description, icon, callback, front) return addButton(id, description, icon, callback, topLeftTogglesPanel, true, front) end function showGameButtons() rightGameButtonsPanel:show() end function hideGameButtons() rightGameButtonsPanel:hide() end function getButton(id) return topMenu:recursiveGetChildById(id) end function getTopMenu() return topMenu end function getRightGameButtonsPanel() return topLeftTogglesPanel end function toggle() if not topMenu then return end if topMenu:isVisible() then hide() else show() end end function openManagerAccounts() if Services.websites then g_platform.openUrl(Services.websites) end end function extendedView(extendedView) if not topMenu then return end topMenu:breakAnchors() if extendedView then topMenu:show() topMenu:addAnchor(AnchorLeft, 'parent', AnchorLeft) topMenu:addAnchor(AnchorRight, 'parent', AnchorRight) modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'topMenu', AnchorBottom) pingLabel:setVisible(false) fpsLabel:setVisible(false) topMenu.topLeftOnlinePlayers:hide() topMenu.topLeftDiscord:setWidth(0) topMenu.topLeftYoutube:setWidth(0) topMenu.topLeftDiscord:hide() topMenu.topLeftYoutube:hide() else if g_game.isOnline() then topMenu:hide() end topMenu:addAnchor(AnchorHorizontalCenter, 'parent', AnchorHorizontalCenter) modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'parent', AnchorTop) topMenu:setWidth(1020) topMenu.topLeftDiscord:setWidth(110) topMenu.topLeftYoutube:setWidth(100) topMenu.topLeftOnlinePlayers:show() topMenu.topLeftDiscord:show() topMenu.topLeftYoutube:show() end end