somethings
cg_drawfps/ping
This commit is contained in:
parent
de124220f5
commit
71866e7f7f
177
src/client/component/fps.cpp
Normal file
177
src/client/component/fps.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <component/scheduler.hpp>
|
||||
|
||||
namespace fps
|
||||
{
|
||||
namespace
|
||||
{
|
||||
float fps_color_good[4] = { 0.6f, 1.0f, 0.0f, 1.0f };
|
||||
float fps_color_ok[4] = { 1.0f, 0.7f, 0.3f, 1.0f };
|
||||
float fps_color_bad[4] = { 1.0f, 0.3f, 0.3f, 1.0f };
|
||||
|
||||
//float origin_color[4] = { 1.0f, 0.67f, 0.13f, 1.0f };
|
||||
float ping_color[4] = { 1.0f, 1.0f, 1.0f, 0.65f };
|
||||
|
||||
struct cg_perf_data
|
||||
{
|
||||
std::chrono::time_point<std::chrono::steady_clock> perf_start;
|
||||
std::int32_t current_ms{};
|
||||
std::int32_t previous_ms{};
|
||||
std::int32_t frame_ms{};
|
||||
std::int32_t history[32]{};
|
||||
std::int32_t count{};
|
||||
std::int32_t index{};
|
||||
std::int32_t instant{};
|
||||
std::int32_t total{};
|
||||
float average{};
|
||||
float variance{};
|
||||
std::int32_t min{};
|
||||
std::int32_t max{};
|
||||
};
|
||||
|
||||
cg_perf_data cg_perf = cg_perf_data();
|
||||
|
||||
void perf_calc_fps(cg_perf_data* data, const std::int32_t value)
|
||||
{
|
||||
data->history[data->index % 32] = value;
|
||||
data->instant = value;
|
||||
data->min = 0x7FFFFFFF;
|
||||
data->max = 0;
|
||||
data->average = 0.0f;
|
||||
data->variance = 0.0f;
|
||||
data->total = 0;
|
||||
|
||||
for (auto i = 0; i < data->count; ++i)
|
||||
{
|
||||
const std::int32_t idx = (data->index - i) % 32;
|
||||
|
||||
if (idx < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
data->total += data->history[idx];
|
||||
|
||||
if (data->min > data->history[idx])
|
||||
{
|
||||
data->min = data->history[idx];
|
||||
}
|
||||
|
||||
if (data->max < data->history[idx])
|
||||
{
|
||||
data->max = data->history[idx];
|
||||
}
|
||||
}
|
||||
|
||||
data->average = static_cast<float>(data->total) / static_cast<float>(data->count);
|
||||
++data->index;
|
||||
}
|
||||
|
||||
void perf_update()
|
||||
{
|
||||
cg_perf.count = 32;
|
||||
|
||||
cg_perf.current_ms = static_cast<std::int32_t>(std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::high_resolution_clock::now() - cg_perf.perf_start).count());
|
||||
cg_perf.frame_ms = cg_perf.current_ms - cg_perf.previous_ms;
|
||||
cg_perf.previous_ms = cg_perf.current_ms;
|
||||
|
||||
perf_calc_fps(&cg_perf, cg_perf.frame_ms);
|
||||
|
||||
utils::hook::invoke<void>(SELECT_VALUE(0x1405487A0, 0x1406575A0)); // H1(1.4)
|
||||
}
|
||||
|
||||
void cg_draw_fps()
|
||||
{
|
||||
const auto* draw_fps = game::Dvar_FindVar("cg_drawFPS");
|
||||
if (draw_fps && draw_fps->current.integer > 0 /*&& game::CL_IsCgameInitialized()*/)
|
||||
{
|
||||
const auto fps = static_cast<std::int32_t>(static_cast<float>(1000.0f / static_cast<float>(cg_perf.
|
||||
average))
|
||||
+ 9.313225746154785e-10);
|
||||
|
||||
auto* font = game::R_RegisterFont("fonts/fira_mono_regular.ttf", 19);
|
||||
if (!font) return;
|
||||
|
||||
const auto* const fps_string = utils::string::va("%i", fps);
|
||||
|
||||
const auto scale = 1.0f;
|
||||
|
||||
const auto x = (game::ScrPlace_GetViewPlacement()->realViewportSize[0] - 10.0f) - game::R_TextWidth(
|
||||
fps_string, 0x7FFFFFFF, font) * scale;
|
||||
|
||||
const auto y = font->pixelHeight * 1.2f;
|
||||
|
||||
const auto fps_color = fps >= 60 ? fps_color_good : (fps >= 30 ? fps_color_ok : fps_color_bad);
|
||||
game::R_AddCmdDrawText(fps_string, 0x7FFFFFFF, font, x, y, scale, scale, 0.0f, fps_color, 6);
|
||||
}
|
||||
}
|
||||
|
||||
void cg_draw_ping()
|
||||
{
|
||||
const auto* draw_ping = game::Dvar_FindVar("cg_drawPing");
|
||||
if (draw_ping && draw_ping->current.integer > 0 && game::CL_IsCgameInitialized())
|
||||
{
|
||||
const auto ping = *reinterpret_cast<int*>(0x142D106F0); // H1MP(1.4)
|
||||
|
||||
auto* font = game::R_RegisterFont("fonts/consolefont", 20);
|
||||
if (!font) return;
|
||||
|
||||
auto* const ping_string = utils::string::va("Ping: %i", ping);
|
||||
|
||||
const auto scale = 1.0f;
|
||||
|
||||
const auto x = (game::ScrPlace_GetViewPlacement()->realViewportSize[0] - 375.0f) - game::R_TextWidth(
|
||||
ping_string, 0x7FFFFFFF, font) * scale;
|
||||
|
||||
const auto y = font->pixelHeight * 1.2f;
|
||||
|
||||
game::R_AddCmdDrawText(ping_string, 0x7FFFFFFF, font, x, y, scale, scale, 0.0f, ping_color, 6);
|
||||
}
|
||||
}
|
||||
|
||||
void cg_draw_fps_register_stub(const char* name, const char** _enum, const int value, unsigned int /*flags*/,
|
||||
const char* desc)
|
||||
{
|
||||
game::Dvar_RegisterEnum(name, _enum, value, game::DVAR_FLAG_SAVED);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// fps setup
|
||||
cg_perf.perf_start = std::chrono::high_resolution_clock::now();
|
||||
utils::hook::call(SELECT_VALUE(0x14018D261, 0x140213B27), &perf_update); //h1sp
|
||||
|
||||
// change cg_drawfps flags to saved
|
||||
utils::hook::call(SELECT_VALUE(0x140139F48, 0x1401A4B8E), &cg_draw_fps_register_stub); //h1sp
|
||||
|
||||
// fix ping value
|
||||
utils::hook::nop(0x14025AC41, 2); // H1MP(1.4)
|
||||
|
||||
scheduler::loop(cg_draw_fps, scheduler::pipeline::renderer);
|
||||
if (game::environment::is_mp())
|
||||
{
|
||||
dvars::register_int("cg_drawPing", 0, 0, 1, game::DVAR_FLAG_SAVED, true);
|
||||
scheduler::loop(cg_draw_ping, scheduler::pipeline::renderer);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(fps::component)
|
@ -299,10 +299,10 @@ namespace game_console
|
||||
{
|
||||
const auto offset = (con.screen_max[0] - con.globals.x) / 2.5f;
|
||||
|
||||
draw_hint_text(0, game::Dvar_ValueToString(dvar, dvar->current, 0),
|
||||
draw_hint_text(0, game::Dvar_ValueToString(dvar, dvar->current),
|
||||
dvars::con_inputDvarValueColor->current.vector, offset);
|
||||
draw_hint_text(1, " default", dvars::con_inputDvarInactiveValueColor->current.vector);
|
||||
draw_hint_text(1, game::Dvar_ValueToString(dvar, dvar->reset, 0),
|
||||
draw_hint_text(1, game::Dvar_ValueToString(dvar, dvar->reset),
|
||||
dvars::con_inputDvarInactiveValueColor->current.vector, offset);
|
||||
}
|
||||
|
||||
@ -326,7 +326,7 @@ namespace game_console
|
||||
|
||||
if (dvar)
|
||||
{
|
||||
draw_hint_text(static_cast<int>(i), game::Dvar_ValueToString(dvar, dvar->current, 0),
|
||||
draw_hint_text(static_cast<int>(i), game::Dvar_ValueToString(dvar, dvar->current),
|
||||
dvars::con_inputDvarValueColor->current.vector, offset);
|
||||
}
|
||||
}
|
||||
|
@ -46,26 +46,6 @@ namespace dvars
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
T* find_dvar(std::unordered_map<std::string, T>& map, const std::string& name)
|
||||
{
|
||||
auto i = map.find(name);
|
||||
if (i != map.end())
|
||||
{
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool find_dvar(std::unordered_set<std::string>& set, const std::string& name)
|
||||
{
|
||||
return set.find(name) != set.end();
|
||||
}
|
||||
}
|
||||
|
||||
std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain)
|
||||
{
|
||||
std::string str;
|
||||
@ -82,16 +62,19 @@ namespace dvars
|
||||
{
|
||||
return "Domain is any number"s;
|
||||
}
|
||||
|
||||
return utils::string::va("Domain is any number %g or smaller", domain.value.max);
|
||||
else
|
||||
{
|
||||
return utils::string::va("Domain is any number %g or smaller", domain.value.max);
|
||||
}
|
||||
}
|
||||
|
||||
if (domain.value.max == FLT_MAX)
|
||||
else if (domain.value.max == FLT_MAX)
|
||||
{
|
||||
return utils::string::va("Domain is any number %g or bigger", domain.value.min);
|
||||
}
|
||||
|
||||
return utils::string::va("Domain is any number from %g to %g", domain.value.min, domain.value.max);
|
||||
else
|
||||
{
|
||||
return utils::string::va("Domain is any number from %g to %g", domain.value.min, domain.value.max);
|
||||
}
|
||||
|
||||
case game::dvar_type::vec2:
|
||||
return dvar_get_vector_domain(2, domain);
|
||||
@ -110,16 +93,19 @@ namespace dvars
|
||||
{
|
||||
return "Domain is any integer"s;
|
||||
}
|
||||
|
||||
return utils::string::va("Domain is any integer %i or smaller", domain.integer.max);
|
||||
else
|
||||
{
|
||||
return utils::string::va("Domain is any integer %i or smaller", domain.integer.max);
|
||||
}
|
||||
}
|
||||
|
||||
if (domain.integer.max == INT_MAX)
|
||||
else if (domain.integer.max == INT_MAX)
|
||||
{
|
||||
return utils::string::va("Domain is any integer %i or bigger", domain.integer.min);
|
||||
}
|
||||
|
||||
return utils::string::va("Domain is any integer from %i to %i", domain.integer.min, domain.integer.max);
|
||||
else
|
||||
{
|
||||
return utils::string::va("Domain is any integer from %i to %i", domain.integer.min, domain.integer.max);
|
||||
}
|
||||
|
||||
case game::dvar_type::color:
|
||||
return "Domain is any 4-component color, in RGBA format"s;
|
||||
@ -142,6 +128,28 @@ namespace dvars
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
T* find_dvar(std::unordered_map<std::string, T>& map, const std::string& name)
|
||||
{
|
||||
auto i = map.find(name);
|
||||
if (i != map.end())
|
||||
{
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool find_dvar(std::unordered_set<std::string>& set, const std::string& name)
|
||||
{
|
||||
return set.find(name) != set.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::string> dvar_list =
|
||||
{
|
||||
"accessToSubscriberContent",
|
||||
@ -167,6 +175,7 @@ namespace dvars
|
||||
"aim_assist_min_target_distance",
|
||||
"aim_assist_script_disable",
|
||||
"cg_draw2D",
|
||||
"cg_drawPing",
|
||||
"cg_drawBigFPS",
|
||||
"cg_drawBreathHint",
|
||||
"cg_drawBuildName",
|
||||
@ -582,5 +591,31 @@ namespace dvars
|
||||
{
|
||||
set_string_overrides[name] = value;
|
||||
}
|
||||
|
||||
game::dvar_t* register_float(const std::string& name, float value, float min,
|
||||
float max, game::DvarFlags flags, bool add_to_list)
|
||||
{
|
||||
const auto hash = game::generateHashValue(name.data());
|
||||
|
||||
if (add_to_list && can_add_dvar_to_list(name))
|
||||
{
|
||||
dvar_list.push_back(name);
|
||||
}
|
||||
|
||||
return game::Dvar_RegisterFloat(hash, "", value, min, max, flags);
|
||||
}
|
||||
|
||||
game::dvar_t* register_string(const std::string& name, const char* value,
|
||||
game::DvarFlags flags, bool add_to_list)
|
||||
{
|
||||
const auto hash = game::generateHashValue(name.data());
|
||||
|
||||
if (add_to_list && can_add_dvar_to_list(name))
|
||||
{
|
||||
dvar_list.push_back(name);
|
||||
}
|
||||
|
||||
return game::Dvar_RegisterString(hash, "", value, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,5 +35,7 @@ namespace dvars
|
||||
namespace override {
|
||||
game::dvar_t* register_int(const std::string& name, int value, int min, int max, const unsigned int flags, bool add_to_list = true);
|
||||
void Dvar_SetString(const std::string& name, const std::string& string);
|
||||
game::dvar_t* register_float(const std::string& name, float value, float min, float max, game::DvarFlags flags, bool add_to_list = true);
|
||||
game::dvar_t* register_string(const std::string& name, const char* value, game::DvarFlags flags, bool add_to_list = true);
|
||||
}
|
||||
}
|
||||
|
@ -932,7 +932,7 @@ namespace game
|
||||
|
||||
struct dvar_t
|
||||
{
|
||||
const char* hash;
|
||||
int hash;
|
||||
unsigned int flags;
|
||||
dvar_type type;
|
||||
bool modified;
|
||||
|
@ -32,7 +32,9 @@ namespace game
|
||||
WEAK symbol<void()> Cmd_EndTokenizeString{ 0x140343630, 0x140403C20 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<dvar_t* (const char* name)> Dvar_FindVar{ 0x1403C5D50, 0x1404FBB00 }; // H1(1.4)
|
||||
WEAK symbol<const char* (const dvar_t* dvar, dvar_value value, __int64 a3)> Dvar_ValueToString{ 0x1403C8560,0x1404FE660 }; // H1(1.4); different typedef from previous titles
|
||||
WEAK symbol<void(char* buffer, int index)> Dvar_GetCombinedString{ 0x140354DF0, 0x14041D830 }; // H1(1.4)
|
||||
//WEAK symbol<const char* (const dvar_t* dvar, dvar_value value, __int64 a3)> Dvar_ValueToString{ 0x1403C8560,0x1404FE660 }; // H1(1.4); different typedef from previous titles
|
||||
WEAK symbol<const char* (dvar_t* dvar, dvar_value value)> Dvar_ValueToString{ 0x1403C8560, 0x1404FE660 }; // H1(1.4)
|
||||
//WEAK symbol<void(int hash, const char* name, const char* buffer)> Dvar_SetCommand{ 0, 0x1404FD0A0 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<dvar_t* (int hash, const char* name, bool value, unsigned int flags)> Dvar_RegisterBool{ 0x1403C47E0,0x1404FA540 }; // H1
|
||||
@ -40,6 +42,17 @@ namespace game
|
||||
WEAK symbol<dvar_t* (int hash, const char* dvarName, float value, float min, float max, unsigned int flags)> Dvar_RegisterFloat{ 0x1403C4BB0,0x1404FA910 }; // H1(1.4)
|
||||
WEAK symbol<dvar_t* (int hash, const char* dvarName, const char* value, unsigned int flags)> Dvar_RegisterString{ 0x1403C4DA0,0x1404FAB00 }; // H1(1.4)
|
||||
WEAK symbol<dvar_t* (int dvarName, const char* a2, float x, float y, float z, float w, float min, float max, unsigned int flags)> Dvar_RegisterVec4{ 0x1403C5220, 0x1404FAF40 }; // H1(1.4)
|
||||
WEAK symbol<dvar_t* (const char* dvarName, const char** valueList, int defaultIndex, unsigned int flags)> Dvar_RegisterEnum{ 0x1403C4AC0, 0x1404C0EC0 }; // H1(1.4)
|
||||
|
||||
|
||||
|
||||
WEAK symbol<long long(const char* qpath, char** buffer)> FS_ReadFile{ 0x1403B9020, 0x1404EE720 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<void(void* buffer)> FS_FreeFile{ 0x1403B9010, 0x1404EE710 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<void(const char* gameName)> FS_Startup{ 0x1403B85D0, 0x1404EDD30 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<void(const char* path, const char* dir)> FS_AddLocalizedGameDirectory{ 0x1403B6030, 0x1404EBE20 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<int(const char* fname)> generateHashValue{ 0x1400FE8A0, 0x1401B1010 }; // H1(1.4)
|
||||
|
||||
@ -115,6 +128,7 @@ namespace game
|
||||
WEAK symbol<XAssetHeader(XAssetType type, const char* name, int allowCreateDefault)> DB_FindXAssetHeader{ 0, 0x140412F60 };
|
||||
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{ 0,0x140413D80 };
|
||||
WEAK symbol<int(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{ 0,0x140413C40 };
|
||||
WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{ 0x14019A3B0, 0x14028BE70 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<unsigned int(unsigned int parentId, unsigned int name)> FindVariable{ 0,0x1405C1D50 };
|
||||
WEAK symbol<unsigned int(int entnum, unsigned int classnum)> FindEntityId{ 0, 0x1405C1C50 };
|
||||
@ -155,6 +169,7 @@ namespace game
|
||||
|
||||
WEAK symbol<const char* (const char*)> UI_GetGameTypeDisplayName{ 0, 0x1404086A0 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<void(const char* error, ...)> Sys_Error{ 0x1403E0C40, 0x140511520 }; // H1(1.4)
|
||||
|
||||
WEAK symbol<const char* (const char* string)> UI_SafeTranslateString{ 0x140350430, 0x1405A2930 }; // H1(1.4)
|
||||
|
||||
@ -183,6 +198,7 @@ namespace game
|
||||
WEAK symbol<scrVarGlob_t> scr_VarGlob{ 0, 0x14B617C00 };
|
||||
WEAK symbol<scrVmPub_t> scr_VmPub{ 0,0x14BA9EE40 };
|
||||
WEAK symbol<function_stack_t> scr_function_stack{ 0,0x14BAA93C0 };
|
||||
WEAK symbol<void*> DB_XAssetPool{ 0x140DE8C80, 0x140FEB5D0 }; // H1(1.4)
|
||||
|
||||
namespace mp
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user