#include #include "loader/component_loader.hpp" #include "game/game.hpp" #include "game/dvars.hpp" #include #include namespace patches { namespace { utils::hook::detour gscr_set_save_dvar_hook; utils::hook::detour dvar_register_float_hook; void* sub_46148() { static uint64_t off_11C52460 = 0x140AD0C58; return &off_11C52460; } DECLSPEC_NORETURN void quit_stub() { component_loader::pre_destroy(); exit(0); } void gscr_set_save_dvar_stub() { const auto string = utils::string::to_lower(utils::hook::invoke(0x1405C7C20, 0)); if (string == "cg_fov" || string == "cg_fovscale") { return; } 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 } void vid_restart_stub_1() { free_lui_memory(); utils::hook::invoke(0x1405A6480); } void vid_restart_stub_2() { free_lui_memory(); utils::hook::invoke(0x1406B5290); } game::dvar_t* register_snd_music_stub(int hash, const char* name, bool value, unsigned int /*flags*/) { return game::Dvar_RegisterBool(hash, name, value, game::DVAR_FLAG_SAVED); } } class component final : public component_interface { public: void post_unpack() override { // Fix startup crashes utils::hook::set(0x140633080, 0xC301B0); utils::hook::set(0x140272F70, 0xC301B0); utils::hook::jump(0x140046148, sub_46148, true); utils::hook::jump(0x14064EF10, quit_stub, true); // Unlock fps in main menu utils::hook::set(0x1403D8E1B, 0xEB); // Disable battle net popup utils::hook::nop(0x1405F4496, 5); // Allow kbam input when gamepad is enabled utils::hook::nop(0x1403D2F8E, 2); utils::hook::nop(0x1403D0C9C, 6); // 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); } }; } REGISTER_COMPONENT(patches::component)