iw4x-sp/src/client/component/patches.cpp
2024-12-23 12:14:50 +01:00

156 lines
4.2 KiB
C++

#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include <utils/hook.hpp>
#include <utils/nt.hpp>
#include "command.hpp"
#include "filesystem.hpp"
namespace patches {
namespace {
void sys_init_stub() {
game::Cmd_SetAutoComplete("exec", "", "cfg");
utils::hook::invoke<void>(0x4EEB20);
}
void cl_play_unskippable_cinematic_f() {
// CL_PlayCinematic_f
utils::hook::invoke<void>(0x4CC950);
*game::cin_skippable = true;
}
void cl_start_multiplayer_f() {
utils::nt::update_dll_search_path(filesystem::get_binary_directory());
utils::nt::launch_process("iw4mp.exe", "-multiplayer");
command::execute("quit", false);
}
const char* live_get_local_client_name_stub() {
return game::Dvar_FindVar("name")->current.string;
}
bool g_exit_after_tool_complete_stub() { return false; }
void ui_replace_directive_stub(const int local_client_num,
const char* src_string, char* dst_string,
const int dst_buffer_size) {
if (!src_string) {
return;
}
if (!dst_string) {
return;
}
if (dst_buffer_size <= 0) {
return;
}
constexpr std::size_t MAX_HUDELEM_TEXT_LEN = 0x100;
if (std::strlen(src_string) > MAX_HUDELEM_TEXT_LEN) {
return;
}
game::UI_ReplaceDirective(local_client_num, src_string, dst_string,
dst_buffer_size);
}
} // namespace
class component final : public component_interface {
public:
void post_load() override {
utils::hook(0x6042A2, sys_init_stub, HOOK_CALL).install()->quick();
utils::hook(0x6216CC, g_exit_after_tool_complete_stub, HOOK_CALL)
.install() // hook*
->quick(); // UI_LoadMenuLists
utils::hook(0x4E638C, g_exit_after_tool_complete_stub, HOOK_CALL)
.install() // hook*
->quick(); // Vehicle_Create
utils::hook(0x65F54A, g_exit_after_tool_complete_stub, HOOK_CALL)
.install() // hook*
->quick(); // ??
utils::hook(0x425F6F, g_exit_after_tool_complete_stub, HOOK_CALL)
.install() // hook*
->quick(); // ??
utils::hook(0x663845, g_exit_after_tool_complete_stub, HOOK_CALL)
.install() // hook*
->quick(); // ??
utils::hook(0x492EF0, live_get_local_client_name_stub, HOOK_JUMP)
.install() // hook*
->quick();
utils::hook(0x563C0C, ui_replace_directive_stub, HOOK_CALL)
.install() // hook*
->quick();
utils::hook(0x56454F, ui_replace_directive_stub, HOOK_CALL)
.install() // hook*
->quick();
utils::hook(0x568A7E, ui_replace_directive_stub, HOOK_CALL)
.install() // hook*
->quick();
utils::hook(0x6283AE, ui_replace_directive_stub, HOOK_CALL)
.install() // hook*
->quick();
patch_sp();
}
private:
static void patch_sp() {
// Force external console
utils::hook::nop(0x604071, 21);
// Remove limit on IWD file loading
utils::hook::set<std::uint8_t>(0x630FF3, 0xEB);
// Ignore XUID match
utils::hook::set<std::uint8_t>(0x65D1AF, 0xEB);
// Remove this particular string from the log file
utils::hook::nop(0x6030A6, 5);
// Config related
utils::hook::set<std::uint8_t>(0x4D3FD3, 0xEB);
// Improper quit popup
utils::hook::nop(0x4F5B3A, 2);
// Remove fs_game check
utils::hook::nop(0x612932, 2);
// Build os path stuff
utils::hook::set<std::uint8_t>(0x6300BF, 0xEB);
// raw -> main
utils::hook::set<std::uint32_t>(0x50A0B2, 0x723390);
// Disable 'replay' output
utils::hook::nop(0x65F14A, 5);
// Disable heartbeat output
utils::hook::nop(0x57EF87, 5);
// Allow intro to be skipped
utils::hook::set<void (*)()>(0x47529F, cl_play_unskippable_cinematic_f);
// Start IW4 MP
utils::hook::set<void (*)()>(0x475327, cl_start_multiplayer_f);
// Enable commandline arguments
utils::hook::set<std::uint8_t>(0x453B24, 0xEB);
// Rename config
utils::hook::set<const char*>(0x6040F2, CLIENT_CONFIG);
utils::hook::set<const char*>(0x602D38, CLIENT_CONFIG);
utils::hook::set<const char*>(0x6037C9, CLIENT_CONFIG);
utils::hook::set<const char*>(0x4D3FDB, CLIENT_CONFIG);
utils::hook::set<const char*>(0x469DB6, CLIENT_CONFIG);
}
};
} // namespace patches
REGISTER_COMPONENT(patches::component)