From 6306283272493bf621f613c4ee6c9293187a982e Mon Sep 17 00:00:00 2001 From: Federico Cecchetto Date: Sat, 5 Mar 2022 16:38:34 +0100 Subject: [PATCH] Add better hud ping & fps counter --- data/ui_scripts/hud_info/__init__.lua | 6 + data/ui_scripts/hud_info/hud.lua | 152 ++++++++++++++++ data/ui_scripts/hud_info/settings.lua | 173 +++++++++++++++++++ src/client/component/fps.cpp | 20 ++- src/client/component/fps.hpp | 6 + src/client/component/patches.cpp | 2 +- src/client/game/symbols.hpp | 2 + src/client/game/ui_scripting/lua/context.cpp | 21 +++ 8 files changed, 375 insertions(+), 7 deletions(-) create mode 100644 data/ui_scripts/hud_info/__init__.lua create mode 100644 data/ui_scripts/hud_info/hud.lua create mode 100644 data/ui_scripts/hud_info/settings.lua create mode 100644 src/client/component/fps.hpp diff --git a/data/ui_scripts/hud_info/__init__.lua b/data/ui_scripts/hud_info/__init__.lua new file mode 100644 index 00000000..f1c9049c --- /dev/null +++ b/data/ui_scripts/hud_info/__init__.lua @@ -0,0 +1,6 @@ +if (game:issingleplyer()) then + return +end + +require("settings") +require("hud") \ No newline at end of file diff --git a/data/ui_scripts/hud_info/hud.lua b/data/ui_scripts/hud_info/hud.lua new file mode 100644 index 00000000..fc44dab6 --- /dev/null +++ b/data/ui_scripts/hud_info/hud.lua @@ -0,0 +1,152 @@ +local mphud = luiglobals.require("LUI.mp_hud.MPHud") + +function createinfobar() + local infobar = LUI.UIElement.new({ + left = luiglobals.GameX.IsHardcoreMode() and 160 or 228, + top = luiglobals.GameX.IsHardcoreMode() and 5 or 9, + height = 15, + width = 70, + leftAnchor = true, + topAnchor = true + }) + + infobar:registerAnimationState("hud_on", { + alpha = 1 + }) + + infobar:registerAnimationState("hud_off", { + alpha = 0 + }) + + return infobar +end + +function populateinfobar(infobar) + elementoffset = 0 + + if (Engine.GetDvarBool("cg_infobar_fps")) then + infobar:addElement(infoelement({ + label = "FPS: ", + getvalue = function() + return game:getfps() + end, + width = 70, + interval = 100 + })) + end + + if (Engine.GetDvarBool("cg_infobar_ping")) then + infobar:addElement(infoelement({ + label = "Latency: ", + getvalue = function() + return game:getping() .. " ms" + end, + width = 115, + interval = 100 + })) + end +end + +function infoelement(data) + local container = LUI.UIElement.new({ + bottomAnchor = true, + leftAnchor = true, + topAnchor = true, + width = data.width, + left = elementoffset + }) + + elementoffset = elementoffset + data.width + 10 + + local background = LUI.UIImage.new({ + bottomAnchor = true, + leftAnchor = true, + topAnchor = true, + rightAnchor = true, + material = luiglobals.RegisterMaterial("white"), + color = luiglobals.Colors.black, + alpha = 0.5 + }) + + local labelfont = CoD.TextSettings.FontBold110 + local textheight = 13 + + local label = LUI.UIText.new({ + left = 5, + top = 1, + font = labelfont.Font, + height = textheight, + leftAnchor = true, + topAnchor = true, + color = { + r = 0.8, + g = 0.8, + b = 0.8, + } + }) + + label:setText(data.label) + + local _, _, left = luiglobals.GetTextDimensions(data.label, labelfont.Font, textheight) + local value = LUI.UIText.new({ + left = left + 5, + top = 1, + height = textheight, + leftAnchor = true, + topAnchor = true, + color = { + r = 0.6, + g = 0.6, + b = 0.6, + } + }) + + value:addElement(LUI.UITimer.new(data.interval, "update")) + value:setText(data.getvalue()) + value:addEventHandler("update", function() + value:setText(data.getvalue()) + end) + + container:addElement(background) + container:addElement(label) + container:addElement(value) + + return container +end + +local updatehudvisibility = mphud.updateHudVisibility +mphud.updateHudVisibility = function(a1, a2) + updatehudvisibility(a1, a2) + + local root = Engine.GetLuiRoot() + local menus = root:AnyActiveMenusInStack() + local infobar = root.infobar + + if (menus) then + infobar:animateToState("hud_off") + else + infobar:animateToState("hud_on") + end +end + +LUI.onmenuopen("mp_hud", function(hud) + if (Engine.InFrontend()) then + return + end + + local infobar = createinfobar() + local root = Engine.GetLuiRoot() + root.infobar = infobar + populateinfobar(infobar) + + root:registerEventHandler("update_hud_infobar_settings", function() + infobar:removeAllChildren() + populateinfobar(infobar) + end) + + root:processEvent({ + name = "update_hud_infobar_settings" + }) + + hud.static:addElement(infobar) +end) \ No newline at end of file diff --git a/data/ui_scripts/hud_info/settings.lua b/data/ui_scripts/hud_info/settings.lua new file mode 100644 index 00000000..9646ce5d --- /dev/null +++ b/data/ui_scripts/hud_info/settings.lua @@ -0,0 +1,173 @@ +local pcdisplay = luiglobals.require("LUI.PCDisplay") + +function createdivider(menu, text) + local element = LUI.UIElement.new( { + leftAnchor = true, + rightAnchor = true, + left = 0, + right = 0, + topAnchor = true, + bottomAnchor = false, + top = 0, + bottom = 33.33 + }) + + element.scrollingToNext = true + element:addElement(LUI.MenuBuilder.BuildRegisteredType("h1_option_menu_titlebar", { + title_bar_text = text + })) + + menu.list:addElement(element) +end + +pcdisplay.CreateOptions = function( menu ) + LUI.Options.AddButtonOptionVariant( + menu, + luiglobals.GenericButtonSettings.Variants.Select, + "@LUA_MENU_COLORBLIND_FILTER", + "@LUA_MENU_COLOR_BLIND_DESC", + LUI.Options.GetRenderColorBlindText, + LUI.Options.RenderColorBlindToggle, + LUI.Options.RenderColorBlindToggle + ) + + if Engine.IsMultiplayer() and Engine.GetDvarType( "cg_paintballFx" ) == luiglobals.DvarTypeTable.DvarBool then + LUI.Options.AddButtonOptionVariant( + menu, + luiglobals.GenericButtonSettings.Variants.Select, + "@LUA_MENU_PAINTBALL", "@LUA_MENU_PAINTBALL_DESC", + LUI.Options.GetDvarEnableTextFunc("cg_paintballFx", false), + LUI.Options.ToggleDvarFunc("cg_paintballFx"), + LUI.Options.ToggleDvarFunc("cg_paintballFx") + ) + end + + LUI.Options.AddButtonOptionVariant( + menu, + luiglobals.GenericButtonSettings.Variants.Select, + "@LUA_MENU_BLOOD", + "@LUA_MENU_BLOOD_DESC", + LUI.Options.GetDvarEnableTextFunc("cg_blood", false), + LUI.Options.ToggleProfiledataFunc("showblood", Engine.GetControllerForLocalClient(0)), + LUI.Options.ToggleProfiledataFunc("showblood", Engine.GetControllerForLocalClient(0)) + ) + + if not Engine.IsMultiplayer() then + LUI.Options.AddButtonOptionVariant( + menu, + luiglobals.GenericButtonSettings.Variants.Select, + "@LUA_MENU_CROSSHAIR", + "@LUA_MENU_CROSSHAIR_DESC", + LUI.Options.GetDvarEnableTextFunc("cg_drawCrosshairOption", false), + LUI.Options.ToggleDvarFunc("cg_drawCrosshairOption"), + LUI.Options.ToggleDvarFunc("cg_drawCrosshairOption") + ) + + LUI.Options.CreateOptionButton( + menu, + "cg_drawDamageFeedbackOption", + "@LUA_MENU_HIT_MARKER", + "@LUA_MENU_HIT_MARKER_DESC", + { + { + text = "@LUA_MENU_ENABLED", + value = true + }, + { + text = "@LUA_MENU_DISABLED", + value = false + } + } + ) + end + + if Engine.IsMultiplayer() then + LUI.Options.AddButtonOptionVariant( + menu, + luiglobals.GenericButtonSettings.Variants.Select, + "@MENU_DISPLAY_KILLSTREAK_COUNTER", + "@MENU_DISPLAY_KILLSTREAK_COUNTER_DESC", + pcdisplay.GetDisplayKillstreakCounterText, + pcdisplay.DisplayKillstreakCounterToggle, + pcdisplay.DisplayKillstreakCounterToggle + ) + + LUI.Options.AddButtonOptionVariant( + menu, + luiglobals.GenericButtonSettings.Variants.Select, + "@MENU_DISPLAY_MEDAL_SPLASHES", + "@MENU_DISPLAY_MEDAL_SPLASHES_DESC", + pcdisplay.GetDisplayMedalSplashesText, + pcdisplay.DisplayMedalSplashesToggle, + pcdisplay.DisplayMedalSplashesToggle + ) + + LUI.Options.AddButtonOptionVariant( + menu, + luiglobals.GenericButtonSettings.Variants.Select, + "@MENU_DISPLAY_WEAPON_EMBLEMS", + "@MENU_DISPLAY_WEAPON_EMBLEMS_DESC", + pcdisplay.GetDisplayWeaponEmblemsText, + pcdisplay.DisplayWeaponEmblemsToggle, + pcdisplay.DisplayWeaponEmblemsToggle + ) + end + + LUI.Options.AddButtonOptionVariant( + menu, + luiglobals.GenericButtonSettings.Variants.Common, + "@MENU_BRIGHTNESS", + "@MENU_BRIGHTNESS_DESC1", + nil, nil, nil, + pcdisplay.OpenBrightnessMenu, + nil, nil, nil + ) + + createdivider(menu, "TELEMETRY") + + LUI.Options.CreateOptionButton( + menu, + "cg_infobar_ping", + "Server Latency", + "Show server latency", + { + { + text = "@LUA_MENU_ENABLED", + value = true + }, + { + text = "@LUA_MENU_DISABLED", + value = false + } + }, nil, nil, function(value) + Engine.SetDvarBool("cg_infobar_ping", value) + Engine.GetLuiRoot():processEvent({ + name = "update_hud_infobar_settings" + }) + end + ) + + LUI.Options.CreateOptionButton( + menu, + "cg_infobar_fps", + "FPS counter", + "Show FPS counter", + { + { + text = "@LUA_MENU_ENABLED", + value = true + }, + { + text = "@LUA_MENU_DISABLED", + value = false + } + }, nil, nil, function(value) + Engine.SetDvarBool("cg_infobar_fps", value) + Engine.GetLuiRoot():processEvent({ + name = "update_hud_infobar_settings" + }) + end + ) + + LUI.Options.InitScrollingList(menu.list, nil) +end diff --git a/src/client/component/fps.cpp b/src/client/component/fps.cpp index db471119..a0ea9299 100644 --- a/src/client/component/fps.cpp +++ b/src/client/component/fps.cpp @@ -1,6 +1,8 @@ #include #include "loader/component_loader.hpp" +#include "fps.hpp" + #include "game/game.hpp" #include "game/dvars.hpp" @@ -93,9 +95,7 @@ namespace fps { if (cg_drawfps->current.integer > 0) { - const auto fps = static_cast(static_cast(1000.0f / static_cast(cg_perf. - average)) - + 9.313225746154785e-10); + const auto fps = fps::get_fps(); const auto font = game::R_RegisterFont("fonts/fira_mono_regular.ttf", 25); const auto fps_string = utils::string::va("%i", fps); @@ -113,10 +113,8 @@ namespace fps { if (cg_drawping->current.integer > 0 && game::CL_IsCgameInitialized() && !game::VirtualLobby_Loaded()) { - const auto ping = *reinterpret_cast(0x142D106F0); - const auto font = game::R_RegisterFont("fonts/consolefont", 20); - const auto ping_string = utils::string::va("Ping: %i", ping); + const auto ping_string = utils::string::va("Ping: %i", *game::mp::ping); const auto x = (game::ScrPlace_GetViewPlacement()->realViewportSize[0] - 375.0f) - game::R_TextWidth( ping_string, 0x7FFFFFFF, font); @@ -134,6 +132,13 @@ namespace fps } } + int get_fps() + { + return static_cast(static_cast(1000.0f / static_cast(cg_perf. + average)) + + 9.313225746154785e-10); + } + class component final : public component_interface { public: @@ -167,6 +172,9 @@ namespace fps scheduler::loop(cg_draw_ping, scheduler::pipeline::renderer); } + + dvars::register_bool("cg_infobar_fps", false, game::DVAR_FLAG_SAVED, true); + dvars::register_bool("cg_infobar_ping", false, game::DVAR_FLAG_SAVED, true); } }; } diff --git a/src/client/component/fps.hpp b/src/client/component/fps.hpp new file mode 100644 index 00000000..a4326a1f --- /dev/null +++ b/src/client/component/fps.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace fps +{ + int get_fps(); +} diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index e9aaf21a..f90f0375 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -266,7 +266,7 @@ namespace patches dvars::register_int("scr_game_spectatetype", 1, 0, 99, game::DVAR_FLAG_REPLICATED); - dvars::override::register_int("com_maxfps", 0, 10, 1000, game::DVAR_FLAG_SAVED); + dvars::override::register_int("com_maxfps", 0, 0, 1000, game::DVAR_FLAG_SAVED); // Prevent clients from ending the game as non host by sending 'end_game' lui notification // cmd_lui_notify_server_hook.create(0x140335A70, cmd_lui_notify_server_stub); // H1(1.4) diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 72a3d2bd..0e0c02e4 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -220,6 +220,8 @@ namespace game WEAK symbol svs_numclients{0, 0x14B204A0C}; WEAK symbol gameTime{0, 0x14621BDBC}; + WEAK symbol ping{0, 0x142D106F0}; + WEAK symbol sv_serverId_value{0, 0x14A3E99B8}; WEAK symbol virtualLobby_loaded{0, 0x142D077FD}; diff --git a/src/client/game/ui_scripting/lua/context.cpp b/src/client/game/ui_scripting/lua/context.cpp index afa00d5d..42ca7977 100644 --- a/src/client/game/ui_scripting/lua/context.cpp +++ b/src/client/game/ui_scripting/lua/context.cpp @@ -8,6 +8,7 @@ #include "../../../component/ui_scripting.hpp" #include "../../../component/command.hpp" #include "../../../component/updater.hpp" +#include "../../../component/fps.hpp" #include "component/game_console.hpp" #include "component/scheduler.hpp" @@ -40,6 +41,26 @@ namespace ui_scripting::lua return scheduler.add(callback, milliseconds, false); }; + game_type["getfps"] = [](const game&) + { + return fps::get_fps(); + }; + + game_type["getping"] = [](const game&) + { + return *::game::mp::ping; + }; + + game_type["issingleplayer"] = [](const game&) + { + return ::game::environment::is_sp(); + }; + + game_type["ismultiplayer"] = [](const game&) + { + return ::game::environment::is_mp(); + }; + auto userdata_type = state.new_usertype("userdata_"); userdata_type["new"] = sol::property(