iw4x-sp/src/client/component/branding.cpp

153 lines
4.8 KiB
C++

#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/dvars.hpp"
#include "branding.hpp"
#include "scheduler.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
#include <version.hpp>
namespace branding {
namespace {
#ifdef _DEBUG
constexpr auto* BUILD_TYPE = "IW4x_DEV SP";
#else
constexpr auto* BUILD_TYPE = "IW4x SP";
#endif
const char* get_version_string() {
const auto* result = utils::string::va(
"{0} {1} build {2} {3}", BUILD_TYPE, "(Alpha)", get_build_number(),
reinterpret_cast<const char*>(0x6A1574));
return result;
}
void dvar_set_version_string(const game::dvar_t* dvar, const char* /*value*/) {
const auto* result = get_version_string();
utils::hook::invoke<void>(0x480E70, dvar, result);
}
void cg_draw_version() {
assert(game::ScrPlace_IsFullScreenActive());
// Default values
constexpr auto font_scale = 0.25f;
constexpr auto max_chars = std::numeric_limits<int>::max();
// Default colours
constexpr float shadow_color[] = {0.0f, 0.0f, 0.0f, 0.69f};
constexpr float 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((*dvars::version)->current.string, 0,
font, font_scale);
const auto height = game::UI_TextHeight(font, font_scale);
game::UI_DrawText(
placement, (*dvars::version)->current.string, max_chars, font,
1.0f -
(dvars::cg_drawVersionX->current.value + static_cast<float>(width)),
1.0f -
(dvars::cg_drawVersionY->current.value + static_cast<float>(height)),
3, 3, font_scale, shadow_color, 0);
game::UI_DrawText(placement, (*dvars::version)->current.string, max_chars,
font,
(0.0f - static_cast<float>(width)) -
dvars::cg_drawVersionX->current.value,
(0.0f - static_cast<float>(height)) -
dvars::cg_drawVersionY->current.value,
3, 3, font_scale, color, 0);
}
void cg_draw_full_screen_debug_overlays_stub(int local_client_num) {
assert(game::ScrPlace_IsFullScreenActive());
if (dvars::cg_drawVersion->current.enabled) {
cg_draw_version();
}
utils::hook::invoke<void>(0x44BD00, local_client_num);
}
volatile bool left_side = true;
game::Font_s** small_font;
void branding_loop() {
float color[4] = {1.0f, 1.0f, 1.0f, 0.25f};
const auto* text = "AlterWare IW4x-SP";
if (!*small_font) {
return;
}
auto* const scr_place =
game::ScrPlace_GetActivePlacement(game::LOCAL_CLIENT_0);
const auto x =
left_side
? 10.0f
: scr_place->realViewportSize[0] -
static_cast<float>(game::R_TextWidth(text, 0, *small_font)) -
10.0f;
game::R_AddCmdDrawText(text, std::numeric_limits<int>::max(), *small_font, x,
30.0f, 1.0f, 1.0f, 0.0f, color, 3);
}
} // namespace
const char* get_build_number() {
return SHORTVERSION " latest " __DATE__ " " __TIME__;
}
class component final : public component_interface {
public:
void post_load() override {
utils::hook(0x46F570, get_build_number, HOOK_JUMP).install()->quick();
utils::hook(0x60429A, dvar_set_version_string, HOOK_CALL)
.install() // hook*
->quick();
utils::hook::set<const char*>(0x446A48, "iw4x-sp: Console");
utils::hook::set<const char*>(0x50C110, "iw4x-sp: Game");
utils::hook::set<const char*>(0x579364, "iw4x-sp: " SHORTVERSION "> ");
// Com_Init_Try_Block_Function
utils::hook::set<const char*>(0x604004, BUILD_TYPE);
utils::hook::set<const char*>(0x603FFF, SHORTVERSION);
utils::hook::set<const char*>(0x603FF5, __DATE__);
register_branding_dvars();
utils::hook(0x57DAFF, cg_draw_full_screen_debug_overlays_stub, HOOK_CALL)
.install() // hook*
->quick();
small_font = reinterpret_cast<game::Font_s**>(0x192A0DC);
scheduler::loop(branding_loop, scheduler::pipeline::renderer);
scheduler::loop([] { left_side = !left_side; },
scheduler::pipeline::renderer, 60s);
}
static void register_branding_dvars() {
#ifdef _DEBUG
constexpr auto value = true;
#else
constexpr auto value = false;
#endif
dvars::cg_drawVersion = game::Dvar_RegisterBool(
"cg_drawVersion", value, game::DVAR_NONE, "Draw the game version");
dvars::cg_drawVersionX = game::Dvar_RegisterFloat(
"cg_drawVersionX", 50.0f, 0.0f, 512.0f, game::DVAR_NONE,
"X offset for the version string");
dvars::cg_drawVersionY = game::Dvar_RegisterFloat(
"cg_drawVersionY", 18.0f, 0.0f, 512.0f, game::DVAR_NONE,
"Y offset for the version string");
}
};
} // namespace branding
REGISTER_COMPONENT(branding::component)