diff --git a/src/client/component/cheats.cpp b/src/client/component/cheats.cpp index 307c908..1033a55 100644 --- a/src/client/component/cheats.cpp +++ b/src/client/component/cheats.cpp @@ -6,11 +6,12 @@ #include "key_catcher.hpp" #include "command.hpp" +#include "console.hpp" namespace cheats { game::dvar_t* cl_EnableCheats; -__declspec(naked) void draw_red_box_stub() { +void __declspec(naked) draw_red_box_stub() { __asm { push eax mov eax, cl_EnableCheats @@ -30,7 +31,7 @@ __declspec(naked) void draw_red_box_stub() { } } -__declspec(naked) void blind_eye_check_stub() { +void __declspec(naked) blind_eye_check_stub() { __asm { push eax mov eax, cl_EnableCheats @@ -73,24 +74,29 @@ private: key_catcher::on_key_press( "Z", []([[maybe_unused]] const game::LocalClientNum_t& local_client) { game::Dvar_SetBool(cl_EnableCheats, true); + console::print("Enabled cl_EnableCheats"); }); key_catcher::on_key_press( "X", []([[maybe_unused]] const game::LocalClientNum_t& local_client) { game::Dvar_SetBool(cl_EnableCheats, false); + console::print("Disabled cl_EnableCheats"); }); key_catcher::on_key_press( "Y", []([[maybe_unused]] const game::LocalClientNum_t& local_client) { - command::execute( - utils::string::va("cmd mr %i 2 allies", *game::serverId), true); + const auto* cmd = + utils::string::va("cmd mr %i 2 allies", *game::serverId); + command::execute(cmd, true); + console::print("Executed: {}", cmd); }); key_catcher::on_key_press( "8", []([[maybe_unused]] const game::LocalClientNum_t& local_client) { - command::execute( - utils::string::va("cmd mr %i -1 endround", *game::serverId), - true); + const auto* cmd = + utils::string::va("cmd mr %i -1 endround", *game::serverId); + command::execute(cmd, true); + console::print("Executed: {}", cmd); }); } }; diff --git a/src/client/component/command.cpp b/src/client/component/command.cpp index 9cb2e54..8e2c823 100644 --- a/src/client/component/command.cpp +++ b/src/client/component/command.cpp @@ -5,6 +5,7 @@ #include #include "command.hpp" +#include "console.hpp" constexpr auto CMD_MAX_NESTING = 8; @@ -86,6 +87,27 @@ private: // Will cause blue screen add("quitMeme", utils::nt::raise_hard_exception); add("quit", game::Com_Quit_f); + add("vstr", [](const params& params) { + if (params.size() < 2) { + console::print("vstr : execute a variable command"); + return; + } + + const auto* dvar_name = params.get(1); + const auto* dvar = game::Dvar_FindVar(dvar_name); + + if (dvar == nullptr) { + console::print("{} doesn't exist", dvar_name); + return; + } + if (dvar->type != game::dvar_type::DVAR_TYPE_STRING && + dvar->type != game::dvar_type::DVAR_TYPE_ENUM) { + console::print("{} is not a string-based dvar\n", dvar->name); + return; + } + + execute(dvar->current.string); + }); } }; } // namespace command diff --git a/src/client/component/console.cpp b/src/client/component/console.cpp index 069bf85..f033d83 100644 --- a/src/client/component/console.cpp +++ b/src/client/component/console.cpp @@ -2,6 +2,9 @@ #include "../loader/component_loader.hpp" #include +#include + +#include "console.hpp" namespace console { namespace { @@ -27,6 +30,28 @@ void show_console() { } } // namespace +#ifdef _DEBUG +void console_print(const std::source_location& location, std::string_view fmt, + std::format_args&& args) { +#else +void console_print(std::string_view fmt, std::format_args&& args) { +#endif +#ifdef _DEBUG + const auto msg = std::vformat(fmt, args); + const auto line = + std::format("Debug:\n {}\nFile: {}\nFunction: {}\n\n", msg, + location.file_name(), location.function_name()); +#else + const auto line = std::vformat(fmt, args); +#endif + + if (IsDebuggerPresent()) { + OutputDebugStringA(line.data()); + } + + game::Conbuf_AppendText(line.data()); +} + class component final : public component_interface { public: void post_unpack() override { diff --git a/src/client/component/console.hpp b/src/client/component/console.hpp new file mode 100644 index 0000000..7f70a9b --- /dev/null +++ b/src/client/component/console.hpp @@ -0,0 +1,28 @@ +#pragma once + +namespace console { + +#ifdef _DEBUG +void console_print(const std::source_location& location, std::string_view fmt, + std::format_args&& args); +#else +void console_print(std::string_view fmt, std::format_args&& args); +#endif + +static inline void log(std::string_view fmt, std::format_args&& args) { +#ifdef _DEBUG + console_print(std::source_location::current(), fmt, std::move(args)); +#else + console_print(fmt, std::move(args)); +#endif +} + +static inline void print(std::string_view fmt) { + log(fmt, std::make_format_args(0)); +} + +template +static inline void print(std::string_view fmt, Args&&... args) { + log(fmt, std::make_format_args(args...)); +} +} // namespace console diff --git a/src/client/component/dvar_patches.cpp b/src/client/component/dvar_patches.cpp index dc77ebf..c838480 100644 --- a/src/client/component/dvar_patches.cpp +++ b/src/client/component/dvar_patches.cpp @@ -3,9 +3,13 @@ #include +#include "console.hpp" + namespace dvar_patches { -void dvar_set_from_string_by_name_stub(const char* /*dvarName*/, - const char* /*string*/) {} +void dvar_set_from_string_by_name_stub(const char* dvar_name, + const char* string) { + console::print("Server tried setting {} with value {}", dvar_name, string); +} class component final : public component_interface { public: diff --git a/src/client/component/exploit.cpp b/src/client/component/exploit.cpp index 303653a..8364832 100644 --- a/src/client/component/exploit.cpp +++ b/src/client/component/exploit.cpp @@ -5,6 +5,7 @@ #include "command.hpp" #include "key_catcher.hpp" +#include "console.hpp" namespace exploit { game::dvar_t* cl_exploit; @@ -81,11 +82,13 @@ private: static void add_exploit_commands() { command::add("exploit", []([[maybe_unused]] const command::params& params) { game::Dvar_SetBool(cl_exploit, true); + console::print("Enabled cl_exploit"); }); command::add("undo_exploit", []([[maybe_unused]] const command::params& params) { game::Dvar_SetBool(cl_exploit, false); + console::print("Disabled cl_exploit"); }); command::add( @@ -97,6 +100,7 @@ private: return; const auto cmd = std::format("queryserverinfo ;{}", params.join(1)); + console::print("Sending OOB packet {}", cmd); game::NET_OutOfBandPrint(game::NS_SERVER, game::localClientConnection->serverAddress, cmd.data()); diff --git a/src/client/component/scheduler.cpp b/src/client/component/scheduler.cpp index ea62ca8..eec544f 100644 --- a/src/client/component/scheduler.cpp +++ b/src/client/component/scheduler.cpp @@ -87,6 +87,11 @@ void cl_frame_stub(game::LocalClientNum_t localClientNum) { execute(pipeline::client); } +void r_end_frame_stub() { + utils::hook::invoke(0x4FF340); + execute(pipeline::renderer); +} + void main_frame_stub() { utils::hook::invoke(0x4E46A0); execute(pipeline::main); @@ -140,6 +145,7 @@ public: }); utils::hook::call(0x4E4A0D, cl_frame_stub); + utils::hook::call(0x5B54D2, r_end_frame_stub); utils::hook::call(0x543B0E, main_frame_stub); } diff --git a/src/client/component/scheduler.hpp b/src/client/component/scheduler.hpp index 0efaa12..0fbaf1d 100644 --- a/src/client/component/scheduler.hpp +++ b/src/client/component/scheduler.hpp @@ -3,6 +3,7 @@ namespace scheduler { enum pipeline { client, + renderer, async, main, count, diff --git a/src/client/game/game.cpp b/src/client/game/game.cpp index b9f981f..2984988 100644 --- a/src/client/game/game.cpp +++ b/src/client/game/game.cpp @@ -1,3 +1,7 @@ #include -namespace game {} +namespace game { +ScreenPlacement* ScrPlace_GetUnsafeFullPlacement() { + return scrPlaceFullUnsafe; +} +} // namespace game diff --git a/src/client/game/game.hpp b/src/client/game/game.hpp index edc0075..6130553 100644 --- a/src/client/game/game.hpp +++ b/src/client/game/game.hpp @@ -3,17 +3,19 @@ namespace game { template class symbol { public: - symbol(const size_t dedi) : dedi_(reinterpret_cast(dedi)) {} + symbol(const size_t mp) : mp_(reinterpret_cast(mp)) {} - T* get() const { return dedi_; } + [[nodiscard]] T* get() const { return mp_; } operator T*() const { return this->get(); } T* operator->() const { return this->get(); } private: - T* dedi_; + T* mp_; }; + +ScreenPlacement* ScrPlace_GetUnsafeFullPlacement(); } // namespace game #include "symbols.hpp" diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index eb1d522..598015c 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -159,14 +159,29 @@ struct netchan_t { static_assert(sizeof(netchan_t) == 0x630); enum dvar_flags : std::uint16_t { - DVAR_NONE = 0x0, - DVAR_ARCHIVE = 0x1, - DVAR_CHEAT = 0x4, - DVAR_CODINFO = 0x8, - DVAR_SCRIPTINFO = 0x10, - DVAR_SERVERINFO = 0x400, - DVAR_WRITEPROTECTED = 0x800, - DVAR_READONLY = 0x2000, + DVAR_NONE = 0, + DVAR_ARCHIVE = 1 << 0, + DVAR_LATCH = 1 << 1, + DVAR_CHEAT = 1 << 2, + DVAR_CODINFO = 1 << 3, + DVAR_SCRIPTINFO = 1 << 4, + DVAR_SERVERINFO = 1 << 10, + DVAR_WRITEPROTECTED = 1 << 11, + DVAR_READONLY = 1 << 13, + DVAR_AUTOEXEC = 1 << 15, +}; + +enum dvar_type : std::int8_t { + DVAR_TYPE_BOOL = 0x0, + DVAR_TYPE_FLOAT = 0x1, + DVAR_TYPE_FLOAT_2 = 0x2, + DVAR_TYPE_FLOAT_3 = 0x3, + DVAR_TYPE_FLOAT_4 = 0x4, + DVAR_TYPE_INT = 0x5, + DVAR_TYPE_ENUM = 0x6, + DVAR_TYPE_STRING = 0x7, + DVAR_TYPE_COLOR = 0x8, + DVAR_TYPE_FLOAT_3_COLOR = 0x9, }; union DvarValue { @@ -306,6 +321,39 @@ struct clientConnection_t { }; struct clientStatic_t {}; + +struct ScreenPlacement { + float scaleVirtualToReal[2]; + float scaleVirtualToFull[2]; + float scaleRealToVirtual[2]; + float realViewportPosition[2]; + float realViewportSize[2]; + float virtualViewableMin[2]; + float virtualViewableMax[2]; + float realViewableMin[2]; + float realViewableMax[2]; + float virtualAdjustableMin[2]; + float virtualAdjustableMax[2]; + float realAdjustableMin[2]; + float realAdjustableMax[2]; + float subScreenLeft; +}; + +static_assert(sizeof(ScreenPlacement) == 0x6C); + +struct Font_s { + const char* fontName; + int pixelHeight; + int glyphCount; + void* material; + void* glowMaterial; + void* glyphs; +}; + +union XAssetHeader { + Font_s* font; +}; + } // namespace game #pragma warning(pop) diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 1dfc7fb..c5bf46b 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -36,6 +36,8 @@ WEAK symbol Dvar_SetBool{0x46DD70}; WEAK symbol Dvar_SetBoolByName{ 0x48C7D0}; WEAK symbol Dvar_InfoString{0x4028C0}; +WEAK symbol Dvar_SetString{ + 0x465240}; WEAK symbol Key_GetBindingForCmd{0x47D300}; WEAK symbol Key_StringToKeynum{ @@ -69,6 +71,14 @@ WEAK symbol LiveSteam_GetUid{0x4A4050}; WEAK symbol LiveSteam_Client_ConnectToSteamServer{0x4D6980}; +WEAK symbol + DB_FindXAssetHeader{0x4B25C0}; + +WEAK symbol + R_AddCmdDrawText{0x42C970}; + // Variables WEAK symbol cmd_args{0x1C96850}; WEAK symbol playerKeys{0xB3A38C}; @@ -77,4 +87,5 @@ WEAK symbol g_wv_hWnd{0x5A86AF0}; WEAK symbol s_wcd_hWnd{0x5A86330}; WEAK symbol serverId{0xFF5058}; WEAK symbol connectionState{0x1060214}; +WEAK symbol scrPlaceFullUnsafe{0x1337FC0}; } // namespace game diff --git a/src/client/std_include.hpp b/src/client/std_include.hpp index 3a06720..68306ac 100644 --- a/src/client/std_include.hpp +++ b/src/client/std_include.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #pragma comment(lib, "ntdll.lib")