diff --git a/premake5.lua b/premake5.lua index 47c2b42f..4a5fbe51 100644 --- a/premake5.lua +++ b/premake5.lua @@ -161,7 +161,7 @@ newaction { local versionHeader = assert(io.open(wks.location .. "/src/version.h", "w")) versionHeader:write("/*\n") versionHeader:write(" * Automatically generated by premake5.\n") - versionHeader:write(" * Do not touch, you fucking moron!\n") + versionHeader:write(" * Do not touch!\n") versionHeader:write(" */\n") versionHeader:write("\n") versionHeader:write("#define GIT_DESCRIBE " .. gitDescribeOutputQuoted .. "\n") @@ -181,7 +181,7 @@ newaction { local versionHeader = assert(io.open(wks.location .. "/src/version.hpp", "w")) versionHeader:write("/*\n") versionHeader:write(" * Automatically generated by premake5.\n") - versionHeader:write(" * Do not touch, you fucking moron!\n") + versionHeader:write(" * Do not touch!\n") versionHeader:write(" *\n") versionHeader:write(" * This file exists for reasons of complying with our coding standards.\n") versionHeader:write(" *\n") diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index 7c64416a..912f2487 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -105,6 +105,7 @@ namespace Components Loader::Register(new Elevators()); Loader::Register(new ClientCommand()); Loader::Register(new ScriptExtension()); + Loader::Register(new Branding()); Loader::Register(new RawMouse()); Loader::Register(new Bullet()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 12ffb1ff..9851066a 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -136,5 +136,6 @@ namespace Components #include "Modules/ClientCommand.hpp" #include "Modules/Gamepad.hpp" #include "Modules/ScriptExtension.hpp" +#include "Modules/Branding.hpp" #include "Modules/RawMouse.hpp" #include "Modules/Bullet.hpp" diff --git a/src/Components/Modules/Branding.cpp b/src/Components/Modules/Branding.cpp new file mode 100644 index 00000000..3a513af6 --- /dev/null +++ b/src/Components/Modules/Branding.cpp @@ -0,0 +1,122 @@ +#include + +namespace Components +{ + Dvar::Var Branding::CGDrawVersion; + Dvar::Var Branding::CGDrawVersionX; + Dvar::Var Branding::CGDrawVersionY; + Game::dvar_t** Branding::Version = reinterpret_cast(0x1AD7930); + + void Branding::CG_DrawVersion() + { + // Default values + constexpr auto fontScale = 0.25f; + constexpr auto maxChars = std::numeric_limits::max(); + // Default colours + constexpr Game::vec4_t shadowColor = {0.0f, 0.0f, 0.0f, 0.69f}; + constexpr Game::vec4_t color = {0.4f, 0.69f, 1.0f, 0.69f}; + + auto* const placement = Game::ScrPlace_GetUnsafeFullPlacement(); + auto* const font = Game::UI_GetFontHandle(placement, 0, 0.583f); + + const auto width = Game::UI_TextWidth((*Version)->current.string, 0, font, fontScale); + const auto height = Game::UI_TextHeight(font, fontScale); + + Game::UI_DrawText(placement, (*Version)->current.string, maxChars, font, 1.0f - (CGDrawVersionX.get() + static_cast(width)), + 1.0f - (CGDrawVersionY.get() + static_cast(height)), 3, 3, fontScale, shadowColor, 0); + Game::UI_DrawText(placement, (*Version)->current.string, maxChars, font, (0.0f - static_cast(width)) - CGDrawVersionX.get(), + (0.0f - static_cast(height)) - CGDrawVersionY.get(), 3, 3, fontScale, color, 0); + } + + void Branding::CG_DrawVersion_Hk(int localClientNum) + { + Utils::Hook::Call(0x4EFF80)(localClientNum); + + if (Branding::CGDrawVersion.get()) + { + Branding::CG_DrawVersion(); + } + } + + const char* Branding::GetBuildNumber() + { + return SHORTVERSION " latest " __DATE__ " " __TIME__; + } + + const char* Branding::GetVersionString() + { +#ifdef _DEBUG + const auto* buildType = "IW4x_DEV MP"; +#else + const auto* buildType = "IW4x MP"; +#endif + + // IW4x is technically a beta + const auto* result = Utils::String::VA("%s %s build %s %s", + buildType, "(Beta)", Branding::GetBuildNumber(), reinterpret_cast(0x7170A0)); + + return result; + } + + void Branding::Dvar_SetVersionString(const Game::dvar_t* dvar, [[maybe_unused]] const char* value) + { + const auto* result = Branding::GetVersionString(); + Utils::Hook::Call(0x4A9580)(dvar, result); + } + + // Branding this might be a good idea in case this LSP logging ever gets turned on for some reason + void Branding::MSG_WriteVersionStringHeader(Game::msg_t* msg, [[maybe_unused]] const char* string) + { + const auto* result = Branding::GetVersionString(); + Utils::Hook::Call(0x463820)(msg, result); + } + + Game::dvar_t* Branding::Dvar_RegisterUIBuildLocation(const char* dvarName, [[maybe_unused]] float x, + [[maybe_unused]] float y, float min, float max, [[maybe_unused]] int flags, const char* description) + { + return Game::Dvar_RegisterVec2(dvarName, -60.0f, + 474.0f, min, max, Game::dvar_flag::DVAR_READONLY, description); + } + + void Branding::RegisterBrandingDvars() + { +#ifdef _DEBUG + constexpr auto value = true; +#else + constexpr auto value = false; +#endif + Branding::CGDrawVersion = Dvar::Register("cg_drawVersion", value, + Game::dvar_flag::DVAR_NONE, "Draw the game version"); + Branding::CGDrawVersionX = Dvar::Register("cg_drawVersionX", 10.0f, + 0.0f, 512.0f, Game::dvar_flag::DVAR_NONE, "X offset for the version string"); + Branding::CGDrawVersionY = Dvar::Register("cg_drawVersionY", 455.0f, + 0.0f, 512.0f, Game::dvar_flag::DVAR_NONE, "Y offset for the version string"); + } + + Branding::Branding() + { + Dvar::OnInit(Branding::RegisterBrandingDvars); + + // UI version string + Utils::Hook::Set(0x43F73B, "IW4x: " VERSION); + + // Short version dvar + Utils::Hook::Set(0x60BD91, SHORTVERSION); + + Utils::Hook(0x4B12B0, Branding::GetBuildNumber, HOOK_JUMP).install()->quick(); + + // Version string color + static Game::vec4_t buildLocColor = {1.0f, 1.0f, 1.0f, 0.8f}; + Utils::Hook::Set(0x43F710, buildLocColor); + + // Place ui version string to bottom right corner (ui_buildlocation) + Utils::Hook(0x6310A0, Branding::Dvar_RegisterUIBuildLocation, HOOK_CALL).install()->quick(); // Dvar_RegisterVec2 + + Utils::Hook(0x60BD81, Branding::Dvar_SetVersionString, HOOK_CALL).install()->quick(); + + Utils::Hook(0x4DA842, Branding::MSG_WriteVersionStringHeader, HOOK_CALL).install()->quick(); + + // Hook CG_DrawFullScreenDebugOverlays so we may render the version when it's appropriate + Utils::Hook(0x5AC975, Branding::CG_DrawVersion_Hk, HOOK_CALL).install()->quick(); + } +} diff --git a/src/Components/Modules/Branding.hpp b/src/Components/Modules/Branding.hpp new file mode 100644 index 00000000..b8424ae4 --- /dev/null +++ b/src/Components/Modules/Branding.hpp @@ -0,0 +1,30 @@ +#pragma once + +namespace Components +{ + class Branding : public Component + { + public: + Branding(); + + static const char* GetBuildNumber(); + static const char* GetVersionString(); + + private: + static Dvar::Var CGDrawVersion; + static Dvar::Var CGDrawVersionX; + static Dvar::Var CGDrawVersionY; + static Game::dvar_t** Version; + + static void CG_DrawVersion(); + static void CG_DrawVersion_Hk(int localClientNum); + + // Use IW4x Branding + static void Dvar_SetVersionString(const Game::dvar_t* dvar, const char* value); + static void MSG_WriteVersionStringHeader(Game::msg_t* msg, const char* string); + + static Game::dvar_t* Dvar_RegisterUIBuildLocation(const char* dvarName, float x, float y, float min, float max, int flags, const char* description); + + static void RegisterBrandingDvars(); + }; +} diff --git a/src/Components/Modules/Exception.cpp b/src/Components/Modules/Exception.cpp index 572bfdfd..a58dfefa 100644 --- a/src/Components/Modules/Exception.cpp +++ b/src/Components/Modules/Exception.cpp @@ -193,24 +193,6 @@ namespace Components { Exception::SetMiniDumpType(Flags::HasFlag("bigminidumps"), Flags::HasFlag("reallybigminidumps")); -#ifdef DEBUG - // Display DEBUG branding, so we know we're on a debug build - Scheduler::OnFrame([]() - { - auto* font = Game::R_RegisterFont("fonts/normalFont", 0); - Game::vec4_t color = { 1.0f, 1.0f, 1.0f, 1.0f }; - - // Change the color when attaching a debugger - if (IsDebuggerPresent()) - { - color[0] = 0.6588f; - color[1] = 1.0000f; - color[2] = 0.0000f; - } - - Game::R_AddCmdDrawText("DEBUG-BUILD", 0x7FFFFFFF, font, 15.0f, 10.0f + Game::R_TextHeight(font), 1.0f, 1.0f, 0.0f, color, Game::ITEM_TEXTSTYLE_SHADOWED); - }, true); -#endif #if !defined(DEBUG) || defined(FORCE_EXCEPTION_HANDLER) Exception::SetFilterHook.initialize(SetUnhandledExceptionFilter, Exception::SetUnhandledExceptionFilterStub, HOOK_JUMP); Exception::SetFilterHook.install(); diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 92e09546..c05eac23 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -229,12 +229,6 @@ namespace Components } } - Game::dvar_t* QuickPatch::Dvar_RegisterUIBuildLocation(const char* dvarName, - float /*x*/, float /*y*/, float min, float max, int /*flags*/, const char* description) - { - return Game::Dvar_RegisterVec2(dvarName, -60.0f, 474.0f, min, max, Game::DVAR_READONLY, description); - } - QuickPatch::QuickPatch() { // quitHard @@ -304,22 +298,6 @@ namespace Components // fs_basegame Utils::Hook::Set(0x6431D1, BASEGAME); - // UI version string - Utils::Hook::Set(0x43F73B, "IW4x: " VERSION); - - // console version string - Utils::Hook::Set(0x4B12BB, "IW4x " VERSION " (built " __DATE__ " " __TIME__ ")"); - - // version string - Utils::Hook::Set(0x60BD56, "IW4x (" VERSION ")"); - - // version string color - static Game::vec4_t buildLocColor = { 1.0f, 1.0f, 1.0f, 0.8f }; - Utils::Hook::Set(0x43F710, buildLocColor); - - // Shift ui version string to the left (ui_buildlocation) - Utils::Hook(0x6310A0, QuickPatch::Dvar_RegisterUIBuildLocation, HOOK_CALL).install()->quick(); - // console title if (ZoneBuilder::IsEnabled()) { @@ -340,9 +318,6 @@ namespace Components // sv_hostname Utils::Hook::Set(0x4D378B, "IW4Host"); - // shortversion - Utils::Hook::Set(0x60BD91, SHORTVERSION); - // console logo Utils::Hook::Set(0x428A66, BASEGAME "/images/logo.bmp"); diff --git a/src/Components/Modules/QuickPatch.hpp b/src/Components/Modules/QuickPatch.hpp index 62377cfd..b9b03407 100644 --- a/src/Components/Modules/QuickPatch.hpp +++ b/src/Components/Modules/QuickPatch.hpp @@ -27,7 +27,5 @@ namespace Components static void CL_KeyEvent_OnEscape(); static void CL_KeyEvent_ConsoleEscape_Stub(); - - static Game::dvar_t* Dvar_RegisterUIBuildLocation(const char* dvarName, float x, float y, float min, float max, int flags, const char* description); }; } diff --git a/src/Components/Modules/Window.cpp b/src/Components/Modules/Window.cpp index 3661625b..04fa8f22 100644 --- a/src/Components/Modules/Window.cpp +++ b/src/Components/Modules/Window.cpp @@ -100,7 +100,7 @@ namespace Components } } - void Window::DrawCursorStub(void *scrPlace, float x, float y, float w, float h, int horzAlign, int vertAlign, const float *color, Game::Material *material) + void Window::DrawCursorStub(Game::ScreenPlacement* scrPlace, float x, float y, float w, float h, int horzAlign, int vertAlign, const float* color, Game::Material* material) { if (Window::NativeCursor.get()) { diff --git a/src/Components/Modules/Window.hpp b/src/Components/Modules/Window.hpp index 9b0f09c6..9728fd21 100644 --- a/src/Components/Modules/Window.hpp +++ b/src/Components/Modules/Window.hpp @@ -40,7 +40,7 @@ namespace Components static BOOL WINAPI MessageHandler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); static int WINAPI ShowCursorHook(BOOL show); - static void DrawCursorStub(void *scrPlace, float x, float y, float w, float h, int horzAlign, int vertAlign, const float *color, Game::Material *material); + static void DrawCursorStub(Game::ScreenPlacement* scrPlace, float x, float y, float w, float h, int horzAlign, int vertAlign, const float* color, Game::Material* material); static void StyleHookStub(); static HWND WINAPI CreateMainWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index da023505..d7d00756 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -387,6 +387,7 @@ namespace Game UI_DrawHandlePic_t UI_DrawHandlePic = UI_DrawHandlePic_t(0x4D0EA0); ScrPlace_GetActivePlacement_t ScrPlace_GetActivePlacement = ScrPlace_GetActivePlacement_t(0x4F8940); UI_TextWidth_t UI_TextWidth = UI_TextWidth_t(0x6315C0); + UI_TextHeight_t UI_TextHeight = UI_TextHeight_t(0x4C8630); UI_DrawText_t UI_DrawText = UI_DrawText_t(0x49C0D0); UI_GetFontHandle_t UI_GetFontHandle = UI_GetFontHandle_t(0x4AEA60); ScrPlace_ApplyRect_t ScrPlace_ApplyRect = ScrPlace_ApplyRect_t(0x454E20); @@ -548,6 +549,8 @@ namespace Game FastCriticalSection* db_hashCritSect = reinterpret_cast(0x16B8A54); + ScreenPlacement* scrPlaceFullUnsafe = reinterpret_cast(0x1084460); + float (*CorrectSolidDeltas)[26][3] = reinterpret_cast(0x739BB8); // Count 26 level_locals_t* level = reinterpret_cast(0x1A831A8); @@ -1125,6 +1128,11 @@ namespace Game return GraphGetValueFromFraction(graph->knotCount, graph->knots, fraction) * graph->scale; } + ScreenPlacement* ScrPlace_GetUnsafeFullPlacement() + { + return scrPlaceFullUnsafe; + } + #pragma optimize("", off) __declspec(naked) float UI_GetScoreboardLeft(void* /*a1*/) { diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 67b2364f..47658d08 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -891,7 +891,7 @@ namespace Game typedef bool(__cdecl * Sys_IsDatabaseThread_t)(); extern Sys_IsDatabaseThread_t Sys_IsDatabaseThread; - typedef char** (__cdecl * Sys_ListFiles_t)(const char *directory, const char *extension, const char *filter, int *numfiles, int wantsubs); + typedef char**(__cdecl * Sys_ListFiles_t)(const char* directory, const char* extension, const char* filter, int* numfiles, int wantsubs); extern Sys_ListFiles_t Sys_ListFiles; typedef int(__cdecl * Sys_Milliseconds_t)(); @@ -936,28 +936,31 @@ namespace Game typedef void(__cdecl * UI_SortArenas_t)(); extern UI_SortArenas_t UI_SortArenas; - typedef void(__cdecl * UI_DrawHandlePic_t)(/*ScreenPlacement*/void *scrPlace, float x, float y, float w, float h, int horzAlign, int vertAlign, const float *color, Material *material); + typedef void(__cdecl * UI_DrawHandlePic_t)(ScreenPlacement* scrPlace, float x, float y, float w, float h, int horzAlign, int vertAlign, const float* color, Material* material); extern UI_DrawHandlePic_t UI_DrawHandlePic; typedef ScreenPlacement*(__cdecl * ScrPlace_GetActivePlacement_t)(int localClientNum); extern ScrPlace_GetActivePlacement_t ScrPlace_GetActivePlacement; - typedef int(__cdecl * UI_TextWidth_t)(const char *text, int maxChars, Font_s *font, float scale); + typedef int(__cdecl * UI_TextWidth_t)(const char* text, int maxChars, Font_s* font, float scale); extern UI_TextWidth_t UI_TextWidth; + typedef int(__cdecl * UI_TextHeight_t)(Font_s* font, float scale); + extern UI_TextHeight_t UI_TextHeight; + typedef void(__cdecl * UI_DrawText_t)(const ScreenPlacement* scrPlace, const char* text, int maxChars, Font_s* font, float x, float y, int horzAlign, int vertAlign, float scale, const float* color, int style); extern UI_DrawText_t UI_DrawText; typedef Font_s* (__cdecl* UI_GetFontHandle_t)(ScreenPlacement* scrPlace, int fontEnum, float scale); extern UI_GetFontHandle_t UI_GetFontHandle; - typedef void(__cdecl* ScrPlace_ApplyRect_t)(ScreenPlacement* a1, float* x, float* y, float* w, float* h, int horzAlign, int vertAlign); + typedef void(__cdecl* ScrPlace_ApplyRect_t)(const ScreenPlacement* scrPlace, float* x, float* y, float* w, float* h, int horzAlign, int vertAlign); extern ScrPlace_ApplyRect_t ScrPlace_ApplyRect; - typedef const char * (__cdecl * Win_GetLanguage_t)(); + typedef const char*(__cdecl * Win_GetLanguage_t)(); extern Win_GetLanguage_t Win_GetLanguage; - typedef void (__cdecl * Vec3UnpackUnitVec_t)(PackedUnitVec, vec3_t *); + typedef void(__cdecl * Vec3UnpackUnitVec_t)(PackedUnitVec, vec3_t*); extern Vec3UnpackUnitVec_t Vec3UnpackUnitVec; typedef float(__cdecl * vectoyaw_t)(vec2_t* vec); @@ -1152,6 +1155,8 @@ namespace Game extern FastCriticalSection* db_hashCritSect; + extern ScreenPlacement* scrPlaceFullUnsafe; + extern level_locals_t* level; extern float (*penetrationDepthTable)[PENETRATE_TYPE_COUNT][SURF_TYPE_COUNT]; @@ -1168,6 +1173,8 @@ namespace Game XModel* G_GetModel(int index); + ScreenPlacement* ScrPlace_GetUnsafeFullPlacement(); + XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize); void Menu_FreeItemMemory(Game::itemDef_s* item); void Menu_SetNextCursorItem(Game::UiContext* ctx, Game::menuDef_t* currentMenu, int unk = 1);