game patches
This commit is contained in:
parent
d6ce8bcfc5
commit
29a3b864fa
@ -77,41 +77,283 @@ namespace dvars
|
|||||||
|
|
||||||
namespace disable
|
namespace disable
|
||||||
{
|
{
|
||||||
|
static std::unordered_set<std::string> re_register_disables;
|
||||||
|
static std::unordered_set<std::string> de_register_disables;
|
||||||
|
|
||||||
|
void re_register(const std::string& name)
|
||||||
|
{
|
||||||
|
re_register_disables.emplace(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void de_register(const std::string& name)
|
||||||
|
{
|
||||||
|
de_register_disables.emplace(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace override
|
namespace override
|
||||||
{
|
{
|
||||||
|
static std::unordered_map<std::string, dvar_bool> register_bool_overrides;
|
||||||
|
static std::unordered_map<std::string, dvar_float> register_float_overrides;
|
||||||
|
static std::unordered_map<std::string, dvar_int> register_int_overrides;
|
||||||
|
static std::unordered_map<std::string, dvar_string> register_string_overrides;
|
||||||
|
static std::unordered_map<std::string, dvar_vector2> register_vector2_overrides;
|
||||||
|
static std::unordered_map<std::string, dvar_vector3> register_vector3_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, std::function<void()>> dvar_on_register_function_map;
|
namespace callback
|
||||||
void on_register(const std::string& name, const std::function<void()>& callback)
|
|
||||||
{
|
{
|
||||||
dvar_on_register_function_map[name] = callback;
|
std::unordered_map<std::string, std::function<void()>> dvar_on_register_function_map;
|
||||||
|
std::unordered_map<std::string, std::function<void()>> dvar_on_re_register_function_map;
|
||||||
|
std::unordered_map<std::string, std::function<void()>> dvar_on_de_register_function_map;
|
||||||
|
|
||||||
|
void on_register(const std::string& name, const std::function<void()>& callback)
|
||||||
|
{
|
||||||
|
dvar_on_register_function_map[name] = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_re_register(const std::string& name, const std::function<void()>& callback)
|
||||||
|
{
|
||||||
|
dvar_on_re_register_function_map[name] = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_de_register(const std::string& name, const std::function<void()>& callback)
|
||||||
|
{
|
||||||
|
dvar_on_de_register_function_map[name] = callback;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
game::dvar_t* dvar_register_bool(const char* name, bool value, unsigned int flags, const char* description)
|
||||||
|
{
|
||||||
|
auto* var = find_dvar(override::register_bool_overrides, name);
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
value = var->value;
|
||||||
|
flags = var->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dvar_register_bool_hook.invoke<game::dvar_t*>(name, value, flags, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::dvar_t* dvar_register_float(const char* name, float value, float min, float max, unsigned int flags, const char* description)
|
||||||
|
{
|
||||||
|
auto* var = find_dvar(override::register_float_overrides, name);
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
value = var->value;
|
||||||
|
min = var->min;
|
||||||
|
max = var->max;
|
||||||
|
flags = var->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dvar_register_float_hook.invoke<game::dvar_t*>(name, value, min, max, flags, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::dvar_t* dvar_register_int(const char* name, int value, int min, int max, unsigned int flags, const char* description)
|
||||||
|
{
|
||||||
|
auto* var = find_dvar(override::register_int_overrides, name);
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
value = var->value;
|
||||||
|
min = var->min;
|
||||||
|
max = var->max;
|
||||||
|
flags = var->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dvar_register_int_hook.invoke<game::dvar_t*>(name, value, min, max, flags, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::dvar_t* dvar_register_string(const char* name, const char* value, unsigned int flags, const char* description)
|
||||||
|
{
|
||||||
|
auto* var = find_dvar(override::register_string_overrides, name);
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
value = var->value.data();
|
||||||
|
flags = var->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dvar_register_string_hook.invoke<game::dvar_t*>(name, value, flags, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::dvar_t* dvar_register_vector2(const char* name, float x, float y, float min, float max,
|
||||||
|
unsigned int flags, const char* description)
|
||||||
|
{
|
||||||
|
auto* var = find_dvar(override::register_vector2_overrides, name);
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
x = var->x;
|
||||||
|
y = var->y;
|
||||||
|
min = var->min;
|
||||||
|
max = var->max;
|
||||||
|
flags = var->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dvar_register_vector2_hook.invoke<game::dvar_t*>(name, x, y, min, max, flags, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::dvar_t* dvar_register_vector3(const char* name, float x, float y, float z, float min,
|
||||||
|
float max, unsigned int flags, const char* description)
|
||||||
|
{
|
||||||
|
auto* var = find_dvar(override::register_vector3_overrides, name);
|
||||||
|
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<game::dvar_t*>(name, x, y, z, min, max, flags, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::recursive_mutex _mutex;
|
||||||
|
|
||||||
utils::hook::detour dvar_register_new_hook;
|
utils::hook::detour dvar_register_new_hook;
|
||||||
|
utils::hook::detour dvar_re_register_hook;
|
||||||
|
utils::hook::detour dvar_de_register_hook;
|
||||||
|
utils::hook::detour dvar_register_variant_hook;
|
||||||
|
|
||||||
game::dvar_t* dvar_register_new(const char* name, unsigned int checksum, game::DvarType type, unsigned int flags,
|
game::dvar_t* dvar_register_new(const char* name, unsigned int checksum, game::DvarType type, unsigned int flags,
|
||||||
game::DvarValue* value, game::DvarLimits* domain, char level, const char* description)
|
game::DvarValue* value, game::DvarLimits* domain, char level, const char* description)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> $(_mutex);
|
||||||
auto* dvar = dvar_register_new_hook.invoke<game::dvar_t*>(name, checksum, type, flags, value, domain, level, description);
|
auto* dvar = dvar_register_new_hook.invoke<game::dvar_t*>(name, checksum, type, flags, value, domain, level, description);
|
||||||
|
|
||||||
if (dvar && name && dvar_on_register_function_map.find(name) != dvar_on_register_function_map.end())
|
if (dvar && name)
|
||||||
{
|
{
|
||||||
dvar_on_register_function_map[name]();
|
auto* callback = find_dvar(callback::dvar_on_register_function_map, name);
|
||||||
dvar_on_register_function_map.erase(name);
|
if (callback)
|
||||||
|
{
|
||||||
|
(*callback)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dvar;
|
return dvar;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::recursive_mutex register_var_lock;
|
void dvar_re_register(game::dvar_t* dvar, const char* name, game::DvarType type, unsigned int flags,
|
||||||
utils::hook::detour dvar_register_variant_hook;
|
game::DvarValue* resetValue, game::DvarLimits* domain, char level, const char* description)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> $(_mutex);
|
||||||
|
|
||||||
|
if (dvar && name)
|
||||||
|
{
|
||||||
|
const auto disabled = find_dvar(disable::re_register_disables, name);
|
||||||
|
if (disabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* callback = find_dvar(callback::dvar_on_re_register_function_map, name);
|
||||||
|
if (callback)
|
||||||
|
{
|
||||||
|
(*callback)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dvar_re_register_hook.invoke<void>(dvar, name, type, flags, resetValue, domain, level, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::dvar_t* dvar_de_register(game::dvar_t* dvar)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::recursive_mutex> $(_mutex);
|
||||||
|
|
||||||
|
auto name = dvars::dvar_get_name(dvar);
|
||||||
|
if (dvar && !name.empty())
|
||||||
|
{
|
||||||
|
const auto disabled = find_dvar(disable::de_register_disables, name);
|
||||||
|
if (disabled)
|
||||||
|
{
|
||||||
|
return dvar;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* callback = find_dvar(callback::dvar_on_de_register_function_map, name);
|
||||||
|
if (callback)
|
||||||
|
{
|
||||||
|
(*callback)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dvar_de_register_hook.invoke<game::dvar_t*>(dvar);
|
||||||
|
}
|
||||||
|
|
||||||
game::dvar_t* dvar_register_variant(const char* name, unsigned int checksum, game::DvarType type, unsigned int flags,
|
game::dvar_t* dvar_register_variant(const char* name, unsigned int checksum, game::DvarType type, unsigned int flags,
|
||||||
game::DvarValue* value, game::DvarLimits* domain, const char* description)
|
game::DvarValue* value, game::DvarLimits* domain, const char* description)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> $(register_var_lock);
|
std::lock_guard<std::recursive_mutex> $(_mutex);
|
||||||
auto* dvar = dvar_register_variant_hook.invoke<game::dvar_t*>(name, checksum, type, flags, value, domain, description);
|
auto* dvar = dvar_register_variant_hook.invoke<game::dvar_t*>(name, checksum, type, flags, value, domain, description);
|
||||||
|
|
||||||
if (dvar)
|
if (dvar)
|
||||||
@ -134,7 +376,16 @@ namespace dvars
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
|
dvar_register_bool_hook.create(0xCEB380_b, &dvar_register_bool);
|
||||||
|
dvar_register_float_hook.create(0xCEB890_b, &dvar_register_float);
|
||||||
|
dvar_register_int_hook.create(0xCEB920_b, &dvar_register_int);
|
||||||
|
dvar_register_string_hook.create(0xCEBD50_b, &dvar_register_string);
|
||||||
|
dvar_register_vector2_hook.create(0xCEBF50_b, &dvar_register_vector2);
|
||||||
|
dvar_register_vector3_hook.create(0xCEBFE0_b, &dvar_register_vector3);
|
||||||
|
|
||||||
dvar_register_new_hook.create(0xCEBA60_b, dvar_register_new);
|
dvar_register_new_hook.create(0xCEBA60_b, dvar_register_new);
|
||||||
|
dvar_re_register_hook.create(0xCEC210_b, dvar_re_register);
|
||||||
|
dvar_de_register_hook.create(0xCE9F30_b, dvar_de_register);
|
||||||
dvar_register_variant_hook.create(0xCEBDD0_b, dvar_register_variant);
|
dvar_register_variant_hook.create(0xCEBDD0_b, dvar_register_variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,8 @@ namespace dvars
|
|||||||
{
|
{
|
||||||
namespace disable
|
namespace disable
|
||||||
{
|
{
|
||||||
void set_bool(const std::string& name);
|
void re_register(const std::string& name);
|
||||||
void set_float(const std::string& name);
|
void de_register(const std::string& name);
|
||||||
void set_int(const std::string& name);
|
|
||||||
void set_string(const std::string& name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace override
|
namespace override
|
||||||
@ -18,13 +16,12 @@ namespace dvars
|
|||||||
void register_string(const std::string& name, const std::string& value, 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_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 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_register(const std::string& name, const std::function<void()>& callback);
|
namespace callback
|
||||||
|
{
|
||||||
|
void on_register(const std::string& name, const std::function<void()>& callback);
|
||||||
|
void on_re_register(const std::string& name, const std::function<void()>& callback);
|
||||||
|
void on_de_register(const std::string& name, const std::function<void()>& callback);
|
||||||
|
}
|
||||||
}
|
}
|
@ -69,6 +69,21 @@ namespace fastfiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool exists(const std::string& zone)
|
||||||
|
{
|
||||||
|
const auto is_localized = game::DB_IsLocalized(zone.data());
|
||||||
|
const auto handle = game::Sys_CreateFile((is_localized ? game::SF_ZONE_LOC : game::SF_ZONE),
|
||||||
|
utils::string::va("%s.ff", zone.data()));
|
||||||
|
|
||||||
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
CloseHandle(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
namespace fastfiles
|
namespace fastfiles
|
||||||
{
|
{
|
||||||
std::string get_current_fastfile();
|
std::string get_current_fastfile();
|
||||||
|
bool exists(const std::string& zone);
|
||||||
}
|
}
|
@ -4,6 +4,9 @@
|
|||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
#include "game/dvars.hpp"
|
#include "game/dvars.hpp"
|
||||||
|
|
||||||
|
#include "fastfiles.hpp"
|
||||||
|
#include "dvars.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
@ -11,6 +14,56 @@ namespace patches
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
utils::hook::detour com_register_common_dvars_hook;
|
||||||
|
utils::hook::detour cg_set_client_dvar_from_server_hook;
|
||||||
|
utils::hook::detour live_get_map_index_hook;
|
||||||
|
utils::hook::detour content_do_we_have_content_pack_hook;
|
||||||
|
|
||||||
|
std::string get_login_username()
|
||||||
|
{
|
||||||
|
char username[UNLEN + 1];
|
||||||
|
DWORD username_len = UNLEN + 1;
|
||||||
|
if (!GetUserNameA(username, &username_len))
|
||||||
|
{
|
||||||
|
return "Unknown Soldier";
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string{ username, username_len - 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
game::dvar_t* name_dvar;
|
||||||
|
game::dvar_t* com_maxfps;
|
||||||
|
game::dvar_t* cg_fov;
|
||||||
|
game::dvar_t* cg_fovScale;
|
||||||
|
void com_register_common_dvars_stub()
|
||||||
|
{
|
||||||
|
name_dvar = game::Dvar_RegisterString("name", get_login_username().data(), game::DVAR_FLAG_SAVED, "Player name.");
|
||||||
|
com_maxfps = game::Dvar_RegisterInt("com_maxfps", 0, 0, 1000, game::DVAR_FLAG_SAVED, "Cap frames per second");
|
||||||
|
cg_fov = game::Dvar_RegisterFloat("cg_fov", 65.0f, 1.0f, 160.f, game::DVAR_FLAG_SAVED,
|
||||||
|
"The field of view angle in degrees");
|
||||||
|
cg_fovScale = game::Dvar_RegisterFloat("cg_fovScale", 1.0f, 0.1f, 2.0f, game::DVAR_FLAG_SAVED,
|
||||||
|
"Scale applied to the field of view");
|
||||||
|
|
||||||
|
*reinterpret_cast<game::dvar_t**>(0x6005758_b) = com_maxfps;
|
||||||
|
dvars::disable::re_register("com_maxfps");
|
||||||
|
dvars::disable::de_register("com_maxfps");
|
||||||
|
|
||||||
|
*reinterpret_cast<game::dvar_t**>(0x1FA6DA0_b) = cg_fov;
|
||||||
|
dvars::disable::re_register("cg_fov");
|
||||||
|
dvars::disable::de_register("cg_fov");
|
||||||
|
|
||||||
|
*reinterpret_cast<game::dvar_t**>(0x1FA6DB0_b) = cg_fovScale;
|
||||||
|
dvars::disable::re_register("cg_fovScale");
|
||||||
|
dvars::disable::de_register("cg_fovScale");
|
||||||
|
|
||||||
|
return com_register_common_dvars_hook.invoke<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* live_get_local_client_name()
|
||||||
|
{
|
||||||
|
return game::Dvar_FindVar("name")->current.string;
|
||||||
|
}
|
||||||
|
|
||||||
void dvar_write_single_variable_stub(const game::dvar_t* dvar, int* user_data)
|
void dvar_write_single_variable_stub(const game::dvar_t* dvar, int* user_data)
|
||||||
{
|
{
|
||||||
if ((dvar->flags & game::DVAR_FLAG_SAVED) != 0)
|
if ((dvar->flags & game::DVAR_FLAG_SAVED) != 0)
|
||||||
@ -28,6 +81,83 @@ namespace patches
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void missing_content_error_stub(int, const char*)
|
||||||
|
{
|
||||||
|
game::Com_Error(game::ERR_DROP, utils::string::va("MISSING FILE\n%s.ff",
|
||||||
|
fastfiles::get_current_fastfile().data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* stored_mapname;
|
||||||
|
int live_get_map_index_stub(const char* map)
|
||||||
|
{
|
||||||
|
stored_mapname = map;
|
||||||
|
return live_get_map_index_hook.invoke<int>(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool content_do_we_have_content_pack_stub(int index)
|
||||||
|
{
|
||||||
|
if (stored_mapname != nullptr && !fastfiles::exists(stored_mapname))
|
||||||
|
{
|
||||||
|
stored_mapname = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return content_do_we_have_content_pack_hook.invoke<bool>(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cg_set_client_dvar_from_server_stub(void* client_num, void* cgame_glob, const char* dvar_checksum, const char* value)
|
||||||
|
{
|
||||||
|
unsigned int checksum = static_cast<unsigned int>(atoi(dvar_checksum));
|
||||||
|
auto* dvar = game::Dvar_FindMalleableVar(checksum);
|
||||||
|
|
||||||
|
static unsigned int cg_fov_checksum = game::Dvar_GenerateChecksum("cg_fov");
|
||||||
|
static unsigned int cg_fovScale_checksum = game::Dvar_GenerateChecksum("cg_fovScale");
|
||||||
|
|
||||||
|
if (checksum == cg_fov_checksum ||
|
||||||
|
checksum == cg_fovScale_checksum)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// register new dvar
|
||||||
|
if (!dvar)
|
||||||
|
{
|
||||||
|
game::Dvar_SetFromStringByChecksum(checksum, value, game::DvarSetSource::DVAR_SOURCE_EXTERNAL);
|
||||||
|
}
|
||||||
|
// only set if dvar has no flags or has external flag
|
||||||
|
else if (dvar->flags == game::DVAR_FLAG_NONE ||
|
||||||
|
(dvar->flags & game::DVAR_FLAG_EXTERNAL) != 0)
|
||||||
|
{
|
||||||
|
game::Dvar_SetFromStringFromSource(dvar, value, game::DvarSetSource::DVAR_SOURCE_EXTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// original code
|
||||||
|
unsigned int index = 0;
|
||||||
|
auto result = utils::hook::invoke<__int64>(0xB7AC60_b, dvar, &index); // NetConstStrings_SV_GetNetworkDvarIndex
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
std::string index_str = std::to_string(index);
|
||||||
|
return cg_set_client_dvar_from_server_hook.invoke<void>(client_num, cgame_glob, index_str.data(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
game::dvar_t* get_client_dvar(const char* name)
|
||||||
|
{
|
||||||
|
game::dvar_t* dvar = game::Dvar_FindVar(name);
|
||||||
|
if (!dvar)
|
||||||
|
{
|
||||||
|
static game::dvar_t dummy{ 0 };
|
||||||
|
dummy.checksum = game::Dvar_GenerateChecksum(name);
|
||||||
|
return &dummy;
|
||||||
|
}
|
||||||
|
return dvar;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_client_dvar_checksum(game::dvar_t* dvar, unsigned int* checksum)
|
||||||
|
{
|
||||||
|
*checksum = dvar->checksum;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
@ -35,8 +165,34 @@ namespace patches
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
|
// register custom dvars
|
||||||
|
com_register_common_dvars_hook.create(0xBADF30_b, com_register_common_dvars_stub);
|
||||||
|
|
||||||
|
// get client name from dvar
|
||||||
|
utils::hook::jump(0xD32770_b, live_get_local_client_name);
|
||||||
|
|
||||||
// write better config
|
// write better config
|
||||||
utils::hook::jump(0xBB2A50_b, dvar_write_single_variable_stub);
|
utils::hook::jump(0xBB2A50_b, dvar_write_single_variable_stub);
|
||||||
|
|
||||||
|
// show missing fastfiles
|
||||||
|
utils::hook::call(0x3BBD4B_b, missing_content_error_stub);
|
||||||
|
|
||||||
|
// show missing map
|
||||||
|
stored_mapname = nullptr;
|
||||||
|
live_get_map_index_hook.create(0xCE72C0_b, live_get_map_index_stub);
|
||||||
|
content_do_we_have_content_pack_hook.create(0xCE8550_b, content_do_we_have_content_pack_stub);
|
||||||
|
|
||||||
|
// make setclientdvar behave like older games
|
||||||
|
cg_set_client_dvar_from_server_hook.create(0x856D70_b, cg_set_client_dvar_from_server_stub);
|
||||||
|
utils::hook::call(0xB0A9BB_b, get_client_dvar_checksum); // setclientdvar
|
||||||
|
utils::hook::call(0xB0ACD7_b, get_client_dvar_checksum); // setclientdvars
|
||||||
|
utils::hook::call(0xB0A984_b, get_client_dvar); // setclientdvar
|
||||||
|
utils::hook::call(0xB0AC9F_b, get_client_dvar); // setclientdvars
|
||||||
|
utils::hook::set<uint8_t>(0xB0A9AC_b, 0xEB); // setclientdvar
|
||||||
|
utils::hook::set<uint8_t>(0xB0ACC8_b, 0xEB); // setclientdvars
|
||||||
|
|
||||||
|
// don't reset our fov
|
||||||
|
utils::hook::set<uint8_t>(0x8A6160_b, 0xC3);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,23 @@ namespace game
|
|||||||
GAME_TYPE_CP = 0x3,
|
GAME_TYPE_CP = 0x3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum errorParm
|
||||||
|
{
|
||||||
|
ERR_FATAL = 0,
|
||||||
|
ERR_DROP = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Sys_Folder
|
||||||
|
{
|
||||||
|
SF_ZONE = 0x0,
|
||||||
|
SF_ZONE_LOC = 0x1,
|
||||||
|
SF_VIDEO = 0x2,
|
||||||
|
SF_VIDEO_LOC = 0x3,
|
||||||
|
SF_PAKFILE = 0x4,
|
||||||
|
SF_PAKFILE_LOC = 0x5,
|
||||||
|
SF_COUNT = 0x6,
|
||||||
|
};
|
||||||
|
|
||||||
struct CmdArgs
|
struct CmdArgs
|
||||||
{
|
{
|
||||||
int nesting;
|
int nesting;
|
||||||
@ -55,6 +72,8 @@ namespace game
|
|||||||
DVAR_FLAG_LATCHED = 0x2,
|
DVAR_FLAG_LATCHED = 0x2,
|
||||||
DVAR_FLAG_CHEAT = 0x4,
|
DVAR_FLAG_CHEAT = 0x4,
|
||||||
DVAR_FLAG_REPLICATED = 0x8,
|
DVAR_FLAG_REPLICATED = 0x8,
|
||||||
|
DVAR_FLAG_NETWORK = 0x10,
|
||||||
|
DVAR_FLAG_EXTERNAL = 0x100,
|
||||||
DVAR_FLAG_WRITE = 0x800,
|
DVAR_FLAG_WRITE = 0x800,
|
||||||
DVAR_FLAG_READ = 0x2000,
|
DVAR_FLAG_READ = 0x2000,
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,8 @@ namespace game
|
|||||||
* Functions
|
* Functions
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
|
|
||||||
|
WEAK symbol<void(errorParm code, const char* message, ...)> Com_Error{ 0xB8D830 };
|
||||||
|
|
||||||
WEAK symbol<void()> Com_Quit_f{ 0xBADC90 };
|
WEAK symbol<void()> Com_Quit_f{ 0xBADC90 };
|
||||||
|
|
||||||
WEAK symbol<bool()> Com_FrontEndScene_IsActive{ 0x5AEBA0 };
|
WEAK symbol<bool()> Com_FrontEndScene_IsActive{ 0x5AEBA0 };
|
||||||
@ -30,6 +32,8 @@ namespace game
|
|||||||
WEAK symbol<bool(XAssetType type, const char* name)> DB_IsXAssetDefault{ 0xA780D0 };
|
WEAK symbol<bool(XAssetType type, const char* name)> DB_IsXAssetDefault{ 0xA780D0 };
|
||||||
WEAK symbol<XAssetHeader(XAssetType type, const char* name, int allowCreateDefault)> DB_FindXAssetHeader{ 0xA76E00 };
|
WEAK symbol<XAssetHeader(XAssetType type, const char* name, int allowCreateDefault)> DB_FindXAssetHeader{ 0xA76E00 };
|
||||||
|
|
||||||
|
WEAK symbol<bool(const char* zoneName)> DB_IsLocalized{ 0x3BC500 };
|
||||||
|
|
||||||
WEAK symbol<dvar_t* (const char* name, bool value,
|
WEAK symbol<dvar_t* (const char* name, bool value,
|
||||||
unsigned int flags, const char* description)> Dvar_RegisterBool{ 0xCEB380 };
|
unsigned int flags, const char* description)> Dvar_RegisterBool{ 0xCEB380 };
|
||||||
WEAK symbol<dvar_t* (const char* name, int value, int min, int max,
|
WEAK symbol<dvar_t* (const char* name, int value, int min, int max,
|
||||||
@ -45,6 +49,10 @@ namespace game
|
|||||||
WEAK symbol<dvar_t* (const char* name, float x, float y, float z,
|
WEAK symbol<dvar_t* (const char* name, float x, float y, float z,
|
||||||
float w, float min, float max, unsigned int flags, const char* description)> Dvar_RegisterVec4{ 0xCEC110 };
|
float w, float min, float max, unsigned int flags, const char* description)> Dvar_RegisterVec4{ 0xCEC110 };
|
||||||
|
|
||||||
|
WEAK symbol<dvar_t*(unsigned int checksum, const char* string, DvarSetSource source)> Dvar_SetFromStringByChecksum{ 0xCECDB0 };
|
||||||
|
WEAK symbol<dvar_t* (const char* name, const char* string, DvarSetSource source)> Dvar_SetFromStringByName{ 0xCECF30 };
|
||||||
|
WEAK symbol<void(dvar_t* dvar, const char* string, DvarSetSource source)> Dvar_SetFromStringFromSource{ 0xCECFF0 };
|
||||||
|
|
||||||
WEAK symbol<void(const char* name, const char* string)> Dvar_SetCommand{ 0xCECB30 };
|
WEAK symbol<void(const char* name, const char* string)> Dvar_SetCommand{ 0xCECB30 };
|
||||||
WEAK symbol<dvar_t* (const char* name)> Dvar_FindVar{ 0xCEA460 };
|
WEAK symbol<dvar_t* (const char* name)> Dvar_FindVar{ 0xCEA460 };
|
||||||
WEAK symbol<dvar_t* (unsigned int checksum)> Dvar_FindMalleableVar{ 0xCEA3C0 };
|
WEAK symbol<dvar_t* (unsigned int checksum)> Dvar_FindMalleableVar{ 0xCEA3C0 };
|
||||||
@ -52,9 +60,7 @@ namespace game
|
|||||||
WEAK symbol<const char* (const dvar_t* dvar)> Dvar_DisplayableLatchedValue{ 0xCEA1D0 };
|
WEAK symbol<const char* (const dvar_t* dvar)> Dvar_DisplayableLatchedValue{ 0xCEA1D0 };
|
||||||
WEAK symbol<void(char* buffer, int index)> Dvar_GetCombinedString{ 0xBB1F30 };
|
WEAK symbol<void(char* buffer, int index)> Dvar_GetCombinedString{ 0xBB1F30 };
|
||||||
WEAK symbol<const char* (dvar_t* dvar, DvarValue value)> Dvar_ValueToString{ 0xCEED00 };
|
WEAK symbol<const char* (dvar_t* dvar, DvarValue value)> Dvar_ValueToString{ 0xCEED00 };
|
||||||
WEAK symbol<int(const char* name)> Dvar_GenerateChecksum{ 0xCEA520 };
|
WEAK symbol<unsigned int(const char* name)> Dvar_GenerateChecksum{ 0xCEA520 };
|
||||||
#define Dvar_GenerateHash(name) \
|
|
||||||
Dvar_GenerateChecksum(name);
|
|
||||||
|
|
||||||
WEAK symbol<void(int h, const char* fmt, ...)> FS_Printf{ 0xCDD1C0 };
|
WEAK symbol<void(int h, const char* fmt, ...)> FS_Printf{ 0xCDD1C0 };
|
||||||
|
|
||||||
@ -83,6 +89,8 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<int()> Sys_Milliseconds{ 0xD58110 };
|
WEAK symbol<int()> Sys_Milliseconds{ 0xD58110 };
|
||||||
|
|
||||||
|
WEAK symbol<HANDLE(Sys_Folder folder, const char* baseFilename)> Sys_CreateFile{ 0xCFDF50 };
|
||||||
|
|
||||||
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{ 0x9E4090 };
|
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{ 0x9E4090 };
|
||||||
|
|
||||||
WEAK symbol<void(const char* string)> SV_Cmd_TokenizeString{ 0xB7DD00 };
|
WEAK symbol<void(const char* string)> SV_Cmd_TokenizeString{ 0xB7DD00 };
|
||||||
|
Loading…
Reference in New Issue
Block a user