diff --git a/src/component/client_utils.cpp b/src/component/client_utils.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/component/command.cpp b/src/component/command.cpp index 753e9e0..1c450b3 100644 --- a/src/component/command.cpp +++ b/src/component/command.cpp @@ -98,11 +98,11 @@ namespace command if (sync) { - game::Cmd_ExecuteSingleCommand(0, 0, command.data()); + game::Cmd_ExecuteSingleCommand(game::LocalClientNum_t::LOCAL_CLIENT_0, 0, command.data()); } else { - game::Cbuf_AddText(0, command.data()); + game::Cbuf_AddText(game::LocalClientNum_t::LOCAL_CLIENT_0, command.data()); } } diff --git a/src/component/dvar_patches.cpp b/src/component/dvar_patches.cpp index e69de29..9a92435 100644 --- a/src/component/dvar_patches.cpp +++ b/src/component/dvar_patches.cpp @@ -0,0 +1,23 @@ +#include + +#include +#include + +namespace dvar_patches +{ + void dvar_set_from_string_by_name_stub(const char*, const char*) + { + return; + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + utils::hook::call(0x59C0EF, dvar_set_from_string_by_name_stub); + } + }; +} + +REGISTER_COMPONENT(dvar_patches::component) \ No newline at end of file diff --git a/src/component/exploit.cpp b/src/component/exploit.cpp index 7d8fed3..db7f15b 100644 --- a/src/component/exploit.cpp +++ b/src/component/exploit.cpp @@ -4,12 +4,13 @@ #include #include "command.hpp" +#include "key_catcher.hpp" namespace exploit { bool exploit = false; - void cl_netchan_transmit(int a1, unsigned char* data, int size) + void cl_netchan_transmit_stub(int a1, unsigned char* data, int size) { if (exploit) { @@ -26,11 +27,30 @@ namespace exploit void post_unpack() override { add_exploit_commands(); + add_key_hooks(); - utils::hook::call(0x420E40, cl_netchan_transmit); + utils::hook::call(0x420E40, cl_netchan_transmit_stub); } private: + static void add_key_hooks() + { + key_catcher::on_key_press("O", [](const game::LocalClientNum_t&) + { + command::execute("exploit"); + }); + + key_catcher::on_key_press("L", [](const game::LocalClientNum_t&) + { + command::execute("undo_exploit"); + }); + + key_catcher::on_key_press("K", [](const game::LocalClientNum_t&) + { + command::execute("disconnect"); + }); + } + static void add_exploit_commands() { command::add("exploit", [](const command::params&) diff --git a/src/component/key_catcher.cpp b/src/component/key_catcher.cpp new file mode 100644 index 0000000..a37c074 --- /dev/null +++ b/src/component/key_catcher.cpp @@ -0,0 +1,60 @@ +#include + +#include +#include + +#include "key_catcher.hpp" + +namespace key_catcher +{ + utils::hook::detour cl_key_event_hook; + + namespace + { + std::unordered_map& get_key_callbacks() + { + static std::unordered_map key_callbacks{}; + return key_callbacks; + } + + void handle_key_event(game::LocalClientNum_t localClient, int keyID) + { + auto result = VkKeyScanA(static_cast(keyID)); + auto VkKey = LOBYTE(result); + auto& callbacks = get_key_callbacks(); + + for (auto const& i : callbacks) + { + auto gameVkKey = game::Key_StringToKeynum(i.first.data()); + if (static_cast(gameVkKey) == VkKey) + { + i.second(localClient); + return; + } + } + } + } + + void on_key_press(const std::string& command, const callback& callback) + { + get_key_callbacks()[command] = callback; + } + + void cl_key_event_stub(game::LocalClientNum_t localClient, int keyID, int a3) + { + handle_key_event(localClient, keyID); + + cl_key_event_hook.invoke(localClient, keyID, a3); + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + cl_key_event_hook.create(0x4CD840, &cl_key_event_stub); + } + }; +} + +REGISTER_COMPONENT(key_catcher::component) diff --git a/src/component/key_catcher.hpp b/src/component/key_catcher.hpp new file mode 100644 index 0000000..0e96e1c --- /dev/null +++ b/src/component/key_catcher.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace key_catcher +{ + using callback = std::function; + + void on_key_press(const std::string& command, const callback& callback); +} diff --git a/src/component/network.cpp b/src/component/network.cpp new file mode 100644 index 0000000..720bec6 --- /dev/null +++ b/src/component/network.cpp @@ -0,0 +1,75 @@ +#include + +#include +#include +#include + +#include "network.hpp" +#include "command.hpp" + +namespace network +{ + namespace + { + std::unordered_map& get_callbacks() + { + static std::unordered_map network_callbacks{}; + return network_callbacks; + } + + bool handle_command(game::netadr_s* address, const char* command, game::msg_t* message) + { + const auto cmd_string = utils::string::to_lower(command); + auto& callbacks = get_callbacks(); + const auto handler = callbacks.find(cmd_string); + + if (handler == callbacks.end()) + { + return false; + } + + const auto offset = cmd_string.size() + 5; + const std::string_view data(message->data + offset, message->cursize - offset); + + handler->second(*address, data); + return true; + } + } + + int packet_interception_handler(game::netadr_s* from, const char* command, game::msg_t* message) + { + if (!handle_command(from, command, message)) + { + return reinterpret_cast(0x525730)(from, command, message); + } + + return TRUE; + } + + void on_packet(const std::string& command, const callback& callback) + { + get_callbacks()[utils::string::to_lower(command)] = callback; + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + add_network_commands(); + + utils::hook::call(0x5B27E1, packet_interception_handler); + } + + private: + static void add_network_commands() + { + on_packet("naughty_reply", [](const game::netadr_s&, const std::string_view&) + { + command::execute("dia_quit"); + }); + } + }; +} + +REGISTER_COMPONENT(network::component) diff --git a/src/component/network.hpp b/src/component/network.hpp new file mode 100644 index 0000000..f8c7a7e --- /dev/null +++ b/src/component/network.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace network +{ + using callback = std::function; + + void on_packet(const std::string& command, const callback& callback); +} diff --git a/src/component/remove_hooks.cpp b/src/component/remove_hooks.cpp new file mode 100644 index 0000000..44285db --- /dev/null +++ b/src/component/remove_hooks.cpp @@ -0,0 +1,28 @@ +#include + +#include +#include + +namespace remove_hooks +{ + class component final : public component_interface + { + public: + void post_unpack() override + { + remove_tekno_hooks(); + } + + private: + static void remove_tekno_hooks() + { + utils::hook::set(0x4E3D42, 0xE8); + utils::hook::set(0x4E3D43, 0xA9); + utils::hook::set(0x4E3D44, 0x25); + utils::hook::set(0x4E3D45, 0xFE); + utils::hook::set(0x4E3D46, 0xFF); + } + }; +} + +REGISTER_COMPONENT(remove_hooks::component) diff --git a/src/game/structs.hpp b/src/game/structs.hpp index 07f110f..43d9ca1 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -26,6 +26,16 @@ namespace game const char** argv[8]; }; + enum class LocalClientNum_t + { + LOCAL_CLIENT_0 = 0, + LOCAL_CLIENT_1 = 1, + LOCAL_CLIENT_2 = 2, + LOCAL_CLIENT_3 = 3, + LOCAL_CLIENT_LAST = 3, + LOCAL_CLIENT_COUNT = 4 + }; + typedef enum { NS_CLIENT1 = 0, @@ -368,6 +378,46 @@ namespace game int remoteControlMove; }; + enum LocSelInputState + { + LOC_SEL_INPUT_NONE = 0, + LOC_SEL_INPUT_CONFIRM = 1, + LOC_SEL_INPUT_CANCEL = 2 + }; + + struct field_t + { + int cursor; + int scroll; + int drawWidth; + int widthInPixels; + float charHeight; + int fixedSize; + char buffer[256]; + }; + + struct KeyState + { + int down; + int repeats; + int binding; + const char* bindingCheat; + }; + + static_assert(sizeof(field_t) == 280); + + struct PlayerKeyState + { + field_t chatField; + int chat_team; + int overstrikeMode; + int anyKeyDown; + KeyState keys[256]; + LocSelInputState locSelInputState; + }; + + static_assert(sizeof(PlayerKeyState) == 4392); + enum EffectiveStance { PM_EFF_STANCE_DEFAULT = 0, diff --git a/src/game/symbols.hpp b/src/game/symbols.hpp index a23c4f9..7865ff3 100644 --- a/src/game/symbols.hpp +++ b/src/game/symbols.hpp @@ -6,10 +6,10 @@ namespace game { // Functions WEAK symbol ConcatArgs{0x539060}; - WEAK symbol Cbuf_AddText{0x4C1030}; - WEAK symbol Cbuf_InsertText{0x429920}; + WEAK symbol Cbuf_AddText{0x4C1030}; + WEAK symbol Cbuf_InsertText{0x429920}; WEAK symbol Cmd_AddCommandInternal{0x537E70}; - WEAK symbol Cmd_ExecuteSingleCommand{0x4EB8F0}; + WEAK symbol Cmd_ExecuteSingleCommand{0x4EB8F0}; WEAK symbol Cmd_RemoveCommand{0x4EAF30}; WEAK symbol Cmd_Argv{0x5580E0}; @@ -24,6 +24,8 @@ namespace game Dvar_RegisterFloat{0x4A5CF0}; WEAK symbol Key_GetBindingForCmd{0x47D300}; + WEAK symbol Key_StringToKeynum{0x50A710}; // Virtual-Key Code + WEAK symbol Key_SetBinding{0x50B770}; WEAK symbol SV_Cmd_ArgvBuffer{0x4F6B00}; @@ -32,4 +34,5 @@ namespace game // Variables WEAK symbol cmd_args{0x1C96850}; + WEAK symbol playerKeys{0xB3A38C}; } diff --git a/src/utils/hook.cpp b/src/utils/hook.cpp index 4c736bf..81e7f78 100644 --- a/src/utils/hook.cpp +++ b/src/utils/hook.cpp @@ -1,3 +1,5 @@ +#include + #include "hook.hpp" #include "string.hpp" diff --git a/src/utils/memory.cpp b/src/utils/memory.cpp index 52d4677..af843e0 100644 --- a/src/utils/memory.cpp +++ b/src/utils/memory.cpp @@ -1,3 +1,5 @@ +#include + #include "memory.hpp" #include "nt.hpp" diff --git a/src/utils/nt.cpp b/src/utils/nt.cpp index 3d12c9e..5d95ea6 100644 --- a/src/utils/nt.cpp +++ b/src/utils/nt.cpp @@ -1,3 +1,5 @@ +#include + #include "nt.hpp" namespace utils::nt diff --git a/src/utils/signature.cpp b/src/utils/signature.cpp index 9bb8c62..85f3b49 100644 --- a/src/utils/signature.cpp +++ b/src/utils/signature.cpp @@ -1,6 +1,7 @@ +#include + #include "signature.hpp" #include -#include #include diff --git a/src/utils/string.cpp b/src/utils/string.cpp index f212955..f60d109 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -1,3 +1,5 @@ +#include + #include "string.hpp" #include #include