#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.5f); 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() + width), 1.0f - (CGDrawVersionY.get() + height), 3, 3, fontScale, shadowColor, 0); Game::UI_DrawText(placement, (*Version)->current.string, maxChars, font, (0.0f - width) - CGDrawVersionX.get(), (0.0f - 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() { static char buf[128]; // Length the game uses const auto* data = "latest " __DATE__ " " __TIME__; sprintf_s(buf, "%s %s", SHORTVERSION, data); return buf; } 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, 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, const char* /*string*/) { const auto* result = Branding::GetVersionString(); Utils::Hook::Call(0x463820)(msg, result); } Game::dvar_t* Branding::Dvar_RegisterUIBuildLocation(const char* dvarName, float /*x*/, float /*y*/, float min, float max, int /*flags*/, const char* description) { #ifdef _DEBUG constexpr auto flag = Game::dvar_flag::DVAR_NONE; #else constexpr auto flag = Game::dvar_flag::DVAR_READONLY; #endif return Game::Dvar_RegisterVec2(dvarName, -60.0f, 474.0f, min, max, flag, 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", 50.0f, 0.0f, 512.0f, Game::dvar_flag::DVAR_NONE, "X offset for the version string"); Branding::CGDrawVersionY = Dvar::Register("cg_drawVersionY", 18.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(); } }