From 93975376631e742abcb9d14d789cff36fc34dc1e Mon Sep 17 00:00:00 2001 From: fed <58637860+fedddddd@users.noreply.github.com> Date: Wed, 21 Jun 2023 02:14:56 +0200 Subject: [PATCH] Make "name" saved --- src/client/component/dvars.cpp | 459 +++++++++++++++++++++++++++++++ src/client/component/dvars.hpp | 28 ++ src/client/component/patches.cpp | 55 ++-- src/client/game/structs.hpp | 6 +- 4 files changed, 512 insertions(+), 36 deletions(-) create mode 100644 src/client/component/dvars.cpp create mode 100644 src/client/component/dvars.hpp diff --git a/src/client/component/dvars.cpp b/src/client/component/dvars.cpp new file mode 100644 index 00000000..12422d53 --- /dev/null +++ b/src/client/component/dvars.cpp @@ -0,0 +1,459 @@ +#include +#include "loader/component_loader.hpp" + +#include "game/game.hpp" +#include "dvars.hpp" + +#include + +namespace dvars +{ + struct dvar_base + { + unsigned int flags{}; + }; + + struct dvar_bool : dvar_base + { + bool value{}; + }; + + struct dvar_float : dvar_base + { + float value{}; + float min{}; + float max{}; + }; + + struct dvar_vector2 : dvar_base + { + float x{}; + float y{}; + float min{}; + float max{}; + }; + + struct dvar_vector3 : dvar_base + { + + float x{}; + float y{}; + float z{}; + float min{}; + float max{}; + }; + + struct dvar_int : dvar_base + { + int value{}; + int min{}; + int max{}; + }; + + struct dvar_string : dvar_base + { + std::string value{}; + }; + + namespace + { + template + T* find_dvar(std::unordered_map& map, const std::string& name) + { + auto i = map.find(name); + if (i != map.end()) + { + return &i->second; + } + + return nullptr; + } + + template + T* find_dvar(std::unordered_map& map, const int hash) + { + for (auto i = map.begin(); i != map.end(); ++i) + { + if (game::generateHashValue(i->first.data()) == hash) + { + return &i->second; + } + } + + return nullptr; + } + + bool find_dvar(std::unordered_set& set, const std::string& name) + { + return set.find(name) != set.end(); + } + + + bool find_dvar(std::unordered_set& set, const int hash) + { + for (auto i = set.begin(); i != set.end(); ++i) + { + if (game::generateHashValue(i->data()) == hash) + { + return true; + } + } + + return false; + } + } + + namespace disable + { + static std::unordered_set set_bool_disables; + static std::unordered_set set_float_disables; + static std::unordered_set set_int_disables; + static std::unordered_set set_string_disables; + + void set_bool(const std::string& name) + { + set_bool_disables.emplace(name); + } + + void set_float(const std::string& name) + { + set_float_disables.emplace(name); + } + + void set_int(const std::string& name) + { + set_int_disables.emplace(name); + } + + void set_string(const std::string& name) + { + set_string_disables.emplace(name); + } + } + + namespace override + { + static std::unordered_map register_bool_overrides; + static std::unordered_map register_float_overrides; + static std::unordered_map register_int_overrides; + static std::unordered_map register_string_overrides; + static std::unordered_map register_vector2_overrides; + static std::unordered_map register_vector3_overrides; + + static std::unordered_map set_bool_overrides; + static std::unordered_map set_float_overrides; + static std::unordered_map set_int_overrides; + static std::unordered_map set_string_overrides; + static std::unordered_map set_from_string_overrides; + + void register_bool(const std::string& name, const bool value, const unsigned int flags) + { + dvar_bool values; + values.value = value; + values.flags = flags; + register_bool_overrides[name] = std::move(values); + } + + void register_float(const std::string& name, const float value, const float min, const float max, + const unsigned int flags) + { + dvar_float values; + values.value = value; + values.min = min; + values.max = max; + values.flags = flags; + register_float_overrides[name] = std::move(values); + } + + void register_int(const std::string& name, const int value, const int min, const int max, + const unsigned int flags) + { + dvar_int values; + values.value = value; + values.min = min; + values.max = max; + values.flags = flags; + register_int_overrides[name] = std::move(values); + } + + void register_string(const std::string& name, const std::string& value, + const unsigned int flags) + { + dvar_string values; + values.value = value; + values.flags = flags; + register_string_overrides[name] = std::move(values); + } + + void register_vec2(const std::string& name, float x, float y, float min, float max, + const unsigned int flags) + { + dvar_vector2 values; + values.x = x; + values.y = y; + values.min = min; + values.max = max; + values.flags = flags; + register_vector2_overrides[name] = std::move(values); + } + + void register_vec3(const std::string& name, float x, float y, float z, float min, + float max, const unsigned int flags) + { + dvar_vector3 values; + values.x = x; + values.y = y; + values.z = z; + values.min = min; + values.max = max; + values.flags = flags; + register_vector3_overrides[name] = std::move(values); + } + + void set_bool(const std::string& name, const bool value) + { + set_bool_overrides[name] = value; + } + + void set_float(const std::string& name, const float value) + { + set_float_overrides[name] = value; + } + + void set_int(const std::string& name, const int value) + { + set_int_overrides[name] = value; + } + + void set_string(const std::string& name, const std::string& value) + { + set_string_overrides[name] = value; + } + + void set_from_string(const std::string& name, const std::string& value) + { + set_from_string_overrides[name] = value; + } + } + + utils::hook::detour dvar_register_bool_hook; + utils::hook::detour dvar_register_float_hook; + utils::hook::detour dvar_register_int_hook; + utils::hook::detour dvar_register_string_hook; + utils::hook::detour dvar_register_vector2_hook; + utils::hook::detour dvar_register_vector3_hook; + + utils::hook::detour dvar_set_bool_hook; + utils::hook::detour dvar_set_float_hook; + utils::hook::detour dvar_set_int_hook; + utils::hook::detour dvar_set_string_hook; + utils::hook::detour dvar_set_from_string_hook; + + game::dvar_t* dvar_register_bool(const int hash, const char* name, bool value, unsigned int flags) + { + auto* var = find_dvar(override::register_bool_overrides, hash); + if (var) + { + value = var->value; + flags = var->flags; + } + + return dvar_register_bool_hook.invoke(hash, name, value, flags); + } + + game::dvar_t* dvar_register_float(const int hash, const char* name, float value, float min, float max, unsigned int flags) + { + auto* var = find_dvar(override::register_float_overrides, hash); + if (var) + { + value = var->value; + min = var->min; + max = var->max; + flags = var->flags; + } + + return dvar_register_float_hook.invoke(hash, name, value, min, max, flags); + } + + game::dvar_t* dvar_register_int(const int hash, const char* name, int value, int min, int max, unsigned int flags) + { + auto* var = find_dvar(override::register_int_overrides, hash); + if (var) + { + value = var->value; + min = var->min; + max = var->max; + flags = var->flags; + } + + return dvar_register_int_hook.invoke(hash, name, value, min, max, flags); + } + + game::dvar_t* dvar_register_string(const int hash, const char* name, const char* value, unsigned int flags) + { + auto* var = find_dvar(override::register_string_overrides, hash); + + if (hash == game::generateHashValue("name")) + { + printf("lol\n"); + } + + if (var) + { + value = var->value.data(); + flags = var->flags; + } + + return dvar_register_string_hook.invoke(hash, name, value, flags); + } + + game::dvar_t* dvar_register_vector2(const int hash, const char* name, float x, float y, float min, float max, + unsigned int flags) + { + auto* var = find_dvar(override::register_vector2_overrides, hash); + if (var) + { + x = var->x; + y = var->y; + min = var->min; + max = var->max; + flags = var->flags; + } + + return dvar_register_vector2_hook.invoke(hash, name, x, y, min, max, flags); + } + + game::dvar_t* dvar_register_vector3(const int hash, const char* name, float x, float y, float z, float min, + float max, unsigned int flags) + { + auto* var = find_dvar(override::register_vector3_overrides, hash); + if (var) + { + x = var->x; + y = var->y; + z = var->z; + min = var->min; + max = var->max; + flags = var->flags; + } + + return dvar_register_vector3_hook.invoke(hash, name, x, y, z, min, max, flags); + } + + void dvar_set_bool(game::dvar_t* dvar, bool boolean) + { + const auto disabled = find_dvar(disable::set_bool_disables, dvar->hash); + if (disabled) + { + return; + } + + auto* var = find_dvar(override::set_bool_overrides, dvar->hash); + if (var) + { + boolean = *var; + } + + return dvar_set_bool_hook.invoke(dvar, boolean); + } + + void dvar_set_float(game::dvar_t* dvar, float fl) + { + const auto disabled = find_dvar(disable::set_float_disables, dvar->hash); + if (disabled) + { + return; + } + + auto* var = find_dvar(override::set_float_overrides, dvar->hash); + if (var) + { + fl = *var; + } + + return dvar_set_float_hook.invoke(dvar, fl); + } + + void dvar_set_int(game::dvar_t* dvar, int integer) + { + const auto disabled = find_dvar(disable::set_int_disables, dvar->hash); + if (disabled) + { + return; + } + + auto* var = find_dvar(override::set_int_overrides, dvar->hash); + if (var) + { + integer = *var; + } + + return dvar_set_int_hook.invoke(dvar, integer); + } + + void dvar_set_string(game::dvar_t* dvar, const char* string) + { + if (dvar->hash == game::generateHashValue("name")) + { + printf("lol\n"); + } + + const auto disabled = find_dvar(disable::set_string_disables, dvar->hash); + if (disabled) + { + return; + } + + auto* var = find_dvar(override::set_string_overrides, dvar->hash); + if (var) + { + string = var->data(); + } + + return dvar_set_string_hook.invoke(dvar, string); + } + + void dvar_set_from_string(game::dvar_t* dvar, const char* string, game::DvarSetSource source) + { + if (dvar->hash == game::generateHashValue("name")) + { + printf("lol\n"); + } + + const auto disabled = find_dvar(disable::set_string_disables, dvar->hash); + if (disabled) + { + return; + } + + auto* var = find_dvar(override::set_from_string_overrides, dvar->hash); + if (var) + { + string = var->data(); + } + + return dvar_set_from_string_hook.invoke(dvar, string, source); + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + dvar_register_bool_hook.create(0x140617BB0, &dvar_register_bool); + dvar_register_float_hook.create(0x140617F80, &dvar_register_float); + dvar_register_int_hook.create(0x140618090, &dvar_register_int); + dvar_register_string_hook.create(0x140618170, &dvar_register_string); + dvar_register_vector2_hook.create(0x140618250, &dvar_register_vector2); + dvar_register_vector3_hook.create(0x140618390, &dvar_register_vector3); + + dvar_set_bool_hook.create(0x14061A310, &dvar_set_bool); + dvar_set_float_hook.create(0x14061A750, &dvar_set_float); + dvar_set_int_hook.create(0x14061A9D0, &dvar_set_int); + dvar_set_string_hook.create(0x14061ABF0, &dvar_set_string); + dvar_set_from_string_hook.create(0x14061A910, &dvar_set_from_string); + } + }; +} + +REGISTER_COMPONENT(dvars::component) \ No newline at end of file diff --git a/src/client/component/dvars.hpp b/src/client/component/dvars.hpp new file mode 100644 index 00000000..66d6912d --- /dev/null +++ b/src/client/component/dvars.hpp @@ -0,0 +1,28 @@ +#pragma once + +namespace dvars +{ + namespace disable + { + void set_bool(const std::string& name); + void set_float(const std::string& name); + void set_int(const std::string& name); + void set_string(const std::string& name); + } + + namespace override + { + void register_bool(const std::string& name, bool value, const unsigned int flags); + void register_float(const std::string& name, float value, float min, float max, const unsigned int flags); + void register_int(const std::string& name, int value, int min, int max, const unsigned int flags); + void register_string(const std::string& name, const std::string& value, const unsigned int flags); + void register_vec2(const std::string& name, float x, float y, float min, float max, const unsigned int flags); + void register_vec3(const std::string& name, float x, float y, float z, float min, float max, const unsigned int flags); + + void set_bool(const std::string& name, bool boolean); + void set_float(const std::string& name, float fl); + void set_int(const std::string& name, int integer); + void set_string(const std::string& name, const std::string& string); + void set_from_string(const std::string& name, const std::string& value); + } +} diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index be5f8526..cfae7b10 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -3,6 +3,7 @@ #include "game/game.hpp" #include "game/dvars.hpp" +#include "dvars.hpp" #include #include @@ -28,7 +29,13 @@ namespace patches void gscr_set_save_dvar_stub() { - const auto string = utils::string::to_lower(utils::hook::invoke(0x1405C7C20, 0)); + const auto dvar = game::Scr_GetString(0); + if (dvar == nullptr) + { + return; + } + + const auto string = utils::string::to_lower(dvar); if (string == "cg_fov" || string == "cg_fovscale") { return; @@ -37,27 +44,6 @@ namespace patches gscr_set_save_dvar_hook.invoke(); } - game::dvar_t* cg_fov = nullptr; - game::dvar_t* cg_fovScale = nullptr; - - game::dvar_t* dvar_register_float_stub(int hash, const char* dvarName, float value, float min, float max, unsigned int flags) - { - static const auto cg_fov_hash = game::generateHashValue("cg_fov"); - static const auto cg_fov_scale_hash = game::generateHashValue("cg_fovscale"); - - if (hash == cg_fov_hash) - { - return cg_fov; - } - - if (hash == cg_fov_scale_hash) - { - return cg_fovScale; - } - - return dvar_register_float_hook.invoke(hash, dvarName, value, min, max, flags); - } - void free_lui_memory() { utils::hook::invoke(0x14032A540); // properly free lui memory @@ -75,9 +61,10 @@ namespace patches utils::hook::invoke(0x1406B5290); } - game::dvar_t* register_snd_music_stub(int hash, const char* name, bool value, unsigned int /*flags*/) + void exec_config_stub(void* a1) { - return game::Dvar_RegisterBool(hash, name, value, game::DVAR_FLAG_SAVED); + dvars::register_string("name", "Unknown Soldier", game::DVAR_FLAG_SAVED, "Player name"); + utils::hook::invoke(0x1405A35E0, a1); } } @@ -106,23 +93,21 @@ namespace patches // Prevent game from overriding cg_fov and cg_fovscale values gscr_set_save_dvar_hook.create(0x140504C60, &gscr_set_save_dvar_stub); - // Make cg_fov and cg_fovscale saved dvars - cg_fov = dvars::register_float("cg_fov", 65.f, 40.f, 200.f, - game::DVAR_FLAG_SAVED, "The field of view angle in degrees for client 0"); - cg_fovScale = dvars::register_float("cg_fovScale", 1.f, 0.1f, 2.f, - game::DVAR_FLAG_SAVED, "Scale applied to the field of view"); - - dvar_register_float_hook.create(game::Dvar_RegisterFloat.get(), dvar_register_float_stub); - // fix vid_restart crashing utils::hook::call(0x1403D7413, vid_restart_stub_1); utils::hook::jump(0x1403D7402, vid_restart_stub_2); - // make snd_musicDisabledForCustomSoundtrack saved - utils::hook::call(0x1405D05FB, register_snd_music_stub); - // cinematicingameloopresident -> cinematicingameloop (fix ingame cinematics) utils::hook::jump(0x140502140, 0x1405020C0); + + // override dvar flags + dvars::override::register_float("cg_fovScale", 1.f, 0.1f, 2.f, game::DVAR_FLAG_SAVED); + dvars::override::register_float("cg_fov", 65.f, 40.f, 200.f, game::DVAR_FLAG_SAVED); + dvars::override::register_bool("snd_musicDisabledForCustomSoundtrack", false, game::DVAR_FLAG_SAVED); + + // make "name" saved + utils::hook::call(0x1405A4960, exec_config_stub); + dvars::override::register_string("name", "Unknown Soldier", game::DVAR_FLAG_SAVED); } }; } diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index e0c399c9..7131ad9e 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -687,7 +687,11 @@ namespace game struct dvar_t { - int name; //00 + union + { + int name; + int hash; + }; unsigned int flags; //08 dvar_type type; //0C bool modified; //0D