add loadscreen support

This commit is contained in:
quaK 2024-07-15 17:20:10 +03:00
parent fbe50b8ca0
commit f35b102d44
5 changed files with 266 additions and 8 deletions

View File

@ -53,14 +53,13 @@ namespace branding
if (dvars::branding && dvars::branding->current.enabled)
{
#if GIT_DIRTY == 1
const auto font = game::R_RegisterFont("fonts/blender_pro_medium.ttf", 32);
const auto* placement = game::ScrPlace_GetViewPlacement();
const auto font = game::UI_GetFontHandle(placement, game::FONT_TYPE_HUD_BIG_FONT, 1.0f);
if (!font) return;
static const auto offset_from_corner = 75.0f;
static float text_color[4] = { 0.4f, 0.69f, 1.0f, 0.69f };
const auto* placement = game::ScrPlace_GetViewPlacement();
const auto x = (placement->realViewportSize[0] - offset_from_corner) - (game::R_TextWidth(version_buffer, std::numeric_limits<int>::max(), font));
const auto height = (placement->realViewportSize[1] - offset_from_corner) + 5.0f; // remove some off the offset

View File

@ -0,0 +1,208 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "dvars.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
namespace loadscreen
{
namespace
{
bool CG_IsShowingProgress_FastFile()
{
return game::LoadBar_GetLoadedFraction() > 0.0;
}
void UI_DrawLoadScreenInfo()
{
auto* mapname = game::Dvar_FindVar("ui_mapname")->current.string;
auto* gametype = game::Dvar_FindVar("ui_gametype")->current.string;
auto* mapname_ui = game::UI_GetMapDisplayName(mapname);
auto* gametype_ui = game::UI_GetGameTypeDisplayName(gametype);
const auto* placement = game::ScrPlace_GetActivePlacement();
{
const auto scale_mapname = 0.4f;
const auto scale_gametype = 0.3f;
auto* font_mapname = game::UI_GetFontHandle(placement, game::FONT_TYPE_OBJECTIVE_FONT, scale_mapname);
auto* font_gametype = game::UI_GetFontHandle(placement, game::FONT_TYPE_OBJECTIVE_FONT, scale_gametype);
auto text_width_mapname = game::UI_TextWidth(mapname_ui, 0, font_mapname, scale_mapname);
auto text_width_gametype = game::UI_TextWidth(gametype_ui, 0, font_gametype, scale_gametype);
game::UI_DrawText(placement, mapname_ui, std::numeric_limits<int>::max(), font_mapname, (640.0f - (float)text_width_mapname) * 0.5f, 89.0f,
0, 0, scale_mapname, game::colorWhite, game::FONT_STYLE_SHADOW);
game::UI_DrawText(placement, gametype_ui, std::numeric_limits<int>::max(), font_gametype, (640.0f - (float)text_width_gametype) * 0.5f, 89.0f + 8.0f + font_mapname->pixelHeight * scale_mapname,
0, 0, scale_gametype, game::colorWhite, game::FONT_STYLE_SHADOW);
}
game::uiClientState_t cstate{};
game::CL_GetClientState(0, &cstate);
bool displayConnectionInfo = true;
if (!_stricmp(cstate.servername, "localhost"))
{
displayConnectionInfo = false;
}
if (game::LoadBar_GetLoadedFraction() >= 1.0f)
{
displayConnectionInfo = true;
}
if (displayConnectionInfo)
{
const char* s = nullptr;
switch (cstate.connState)
{
case game::CA_CONNECTING:
s = game::UI_SafeTranslateString("EXE_AWAITINGCONNECTION");
s = game::UI_ReplaceConversionInt(s, cstate.connectPacketCount);
break;
case game::CA_CHALLENGING:
s = game::UI_SafeTranslateString("EXE_AWAITINGCHALLENGE");
s = game::UI_ReplaceConversionInt(s, cstate.connectPacketCount);
break;
case game::CA_CONNECTED:
s = game::UI_SafeTranslateString("EXE_AWAITINGGAMESTATE");
break;
case game::CA_SENDINGSTATS:
s = game::UI_SafeTranslateString("EXE_UPLOADINGSTATS");
break;
case game::CA_LOADING:
case game::CA_PRIMED:
s = game::UI_SafeTranslateString("EXE_AWAITINGHOST");
break;
default:
break;
}
auto scale = 0.25f;
auto* font = game::UI_GetFontHandle(placement, game::FONT_TYPE_TEXT_FONT, scale);
auto width = game::UI_TextWidth(s, 0, font, scale);
game::UI_DrawText(
placement,
s,
std::numeric_limits<int>::max(),
font,
(640.0f - (float)width) * 0.5f,
420.0f,
0,
0,
scale,
game::colorWhite,
game::FONT_STYLE_SHADOW);
}
if (!CG_IsShowingProgress_FastFile() && *game::cl_serverLoadingMap && *game::g_waitingForServer)
{
const char* s = nullptr;
const char* dots = "";
const auto val = (game::Sys_Milliseconds() / 500) & 3;
switch (val)
{
case 1:
dots = ".";
break;
case 2:
dots = "..";
break;
case 3:
dots = "...";
break;
default:
dots = "";
break;
}
s = game::UI_SafeTranslateString("CGAME_WAITINGFORSERVERLOAD");
const char* sa = utils::string::va("%s%s", s, dots);
auto scale = 0.25f;
auto* font = game::UI_GetFontHandle(placement, game::FONT_TYPE_TEXT_FONT, scale);
auto width = game::UI_TextWidth(sa, 0, font, scale);
game::UI_DrawText(
placement,
sa,
std::numeric_limits<int>::max(),
font,
(640.0f - (float)width) * 0.5f,
400.0f,
0,
0,
scale,
game::colorWhite,
game::FONT_STYLE_SHADOW);
}
}
void UI_DrawLoadScreenMaterial()
{
auto* mapname = game::Dvar_FindVar("ui_mapname")->current.string;
auto* loadscreen_name = utils::string::va("loadscreen_%s", mapname);
auto* material = game::Material_RegisterHandle(loadscreen_name);
if (!material || game::DB_IsXAssetDefault(game::ASSET_TYPE_MATERIAL, loadscreen_name))
{
return;
}
const auto* placement = game::ScrPlace_GetActivePlacement();
game::R_AddCmdDrawStretchPic(0.0f, 0.0f, placement->realViewportSize[0], placement->realViewportSize[1], 0.0f, 0.0f, 1.0f, 1.0f, (float*)game::colorWhite.get(), material, 0);
auto* vignette_name = "load_vignette";
auto* vignette = game::Material_RegisterHandle(vignette_name);
if (vignette && !game::DB_IsXAssetDefault(game::ASSET_TYPE_MATERIAL, vignette_name))
{
static const game::vec4_t colorBlack{ 0.0f, 0.0f, 0.0f, 1.0f };
game::R_AddCmdDrawStretchPic(0.0f, 0.0f, placement->realViewportSize[0], placement->realViewportSize[1], 0.0f, 0.0f, 1.0f, 1.0f, (float*)&colorBlack, vignette, 0);
}
}
void UI_DrawLoadBarState()
{
const auto* placement = game::ScrPlace_GetActivePlacement();
static const game::vec4_t color{ 0.2f, 0.2f, 0.2f, 1.0f };
game::UI_FillRect(placement, 192.0f, 430.0f, 256.0f, 2.0f, 0, 0, &color);
game::UI_DrawLoadBar(placement, 192.0f, 430.0f, 256.0f, 2.0f, 0, 0, game::colorWhite, *game::whiteMaterial);
}
void UI_DrawTempConnectScreen([[maybe_unused]] int localClientNum)
{
UI_DrawLoadScreenMaterial();
UI_DrawLoadScreenInfo();
UI_DrawLoadBarState();
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
if (game::environment::is_dedi())
{
return;
}
//utils::hook::jump(0x1409BC7D7, UI_DrawTempConnectScreen);
utils::hook::call(0x1409BC84C, UI_DrawTempConnectScreen);
// Allows loading of _load fastfiles
dvars::override::register_bool("frontEndUseLoadFastfiles", true, game::DVAR_FLAG_NONE);
}
};
}
REGISTER_COMPONENT(loadscreen::component)

View File

@ -369,16 +369,18 @@ namespace party
return;
}
command::execute(utils::string::va("seta ui_mapname %s", mapname.data()), true);
auto* gametype = game::Dvar_FindVar("g_gametype");
if (gametype && gametype->current.string)
{
command::execute(utils::string::va("ui_gametype %s", gametype->current.string), true);
command::execute(utils::string::va("seta ui_gametype %s", gametype->current.string), true);
}
auto* hardcore = game::Dvar_FindVar("g_hardcore");
if (hardcore)
{
command::execute(utils::string::va("ui_hardcore %s", hardcore->current.enabled), true);
command::execute(utils::string::va("seta ui_hardcore %s", hardcore->current.enabled), true);
}
perform_game_initialization();

View File

@ -465,6 +465,19 @@ namespace game
char __pad0[131112];
netadr_s address;
};
enum FontType
{
FONT_TYPE_BIG_FONT = 2,
FONT_TYPE_SMALL_FONT = 3,
FONT_TYPE_BOLD_FONT = 4,
FONT_TYPE_CONSOLE_FONT = 5,
FONT_TYPE_OBJECTIVE_FONT = 6,
FONT_TYPE_TEXT_FONT = 7,
FONT_TYPE_EXTRA_BIG_FONT = 8,
FONT_TYPE_HUD_BIG_FONT = 9,
FONT_TYPE_HUD_SMALL_FONT = 10,
};
struct GfxFont
{
@ -585,6 +598,15 @@ namespace game
vec4_t outlineGlowColor;
};
struct ComGameStartupData
{
int state;
char mapname[64];
char gameType[64];
unsigned int loadTime;
bool isServer;
};
namespace entity
{
enum connstate_t : std::uint32_t
@ -602,6 +624,14 @@ namespace game
CA_MAP_RESTART = 0xA,
};
struct uiClientState_t
{
connstate_t connState;
int connectPacketCount;
char servername[1024];
char messageString[1024];
};
struct clientUIActive_t
{
bool active;

View File

@ -60,6 +60,7 @@ namespace game
WEAK symbol<void(int localClientNum, void* hostInfo, const netadr_s* addr, const char* mapname, const char* gametype)>
CL_MainMP_ConnectAndPreloadMap{ 0x1409AED80 };
WEAK symbol<void(int localClientNum, uiClientState_t* state)> CL_GetClientState{ 0x1409BFFF0 };
WEAK symbol<void(int localClientNum, int andMask)> CL_Keys_RemoveCatcher{ 0x1409A9B00 };
@ -165,6 +166,8 @@ namespace game
WEAK symbol<unsigned int(int controllerIndex)> Live_SyncOnlineDataFlags{ 0x140DC5CE0 };
WEAK symbol<std::uint64_t(int controllerIndex)> Live_GetXuid{ 0x140D32A20 };
WEAK symbol<float()> LoadBar_GetLoadedFraction{ 0x1405DE190 };
WEAK symbol<PartyData* ()> Lobby_GetPartyData{ 0x1409C3E20 };
WEAK symbol<Material* (const char* material)> Material_RegisterHandle{ 0x140E11CE0 };
@ -184,12 +187,12 @@ namespace game
WEAK symbol<GfxFont* (const char* font, int size)> R_RegisterFont{ 0x140DFC670 };
WEAK symbol<int(const char* text, int maxChars, GfxFont* font)> R_TextWidth{ 0x140DFC770 };
WEAK symbol<int(void* font)> R_GetFontHeight{ 0x1412727B0 };
WEAK symbol<int(GfxFont* font)> R_GetFontHeight{ 0x1412727B0 };
WEAK symbol<FontGlowStyle* (int style)> R_Font_GetLegacyFontStyle{ 0x140DFBD00 };
WEAK symbol<void()> R_SyncRenderThread{ 0x140E27EE0 };
WEAK symbol<void(float x, float y, float width, float height, float s0, float t0, float s1, float t1,
float* color, Material* material, int unk)> R_AddCmdDrawStretchPic{ 0x140E24DC0 };
WEAK symbol<void* (const char* text, int maxChars, void* font, int fontHeight, float x,
WEAK symbol<void* (const char* text, int maxChars, GfxFont* font, int fontHeight, float x,
float y, float xScale, float yScale, float rotation, float* color,
int cursorPos, char cursor, FontGlowStyle* glowStyle, int a14, int a15, int a16, int a17)> AddBaseDrawTextCmd{ 0x140E23D90 };
#define R_AddCmdDrawText(TXT, MC, F, X, Y, XS, YS, R, C, S) \
@ -243,6 +246,7 @@ namespace game
WEAK symbol<void(const char* str)> Scr_AllocGlobalString{ 0x140C03C70 };
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{ 0x1409E4090 };
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetActivePlacement{ 0x1409E4060 };
WEAK symbol<const char* (const StringTable* table, const int comparisonColumn, const char* value, const int valueColumn)> StringTable_Lookup{ 0x140CE7950 };
WEAK symbol<const char* (const StringTable* table, const int row, const int column)> StringTable_GetColumnValueForRow{ 0x140CE78E0 };
@ -283,6 +287,15 @@ namespace game
WEAK symbol<const char* (const char*)> UI_GetGameTypeDisplayName{ 0x140CC61C0 };
WEAK symbol<void(unsigned int localClientNum, const char** args)> UI_RunMenuScript{ 0x140CC9710 };
WEAK symbol<const char* (const char* string)> UI_SafeTranslateString{ 0x140CC9790 };
WEAK symbol<const char* (const char* sourceString, int replaceInt)> UI_ReplaceConversionInt{ 0x140CC91A0 };
WEAK symbol<GfxFont*(const ScreenPlacement* scrPlace, int fontEnum, float scale)> UI_GetFontHandle{ 0x140CD1240 };
WEAK symbol<void(const ScreenPlacement* scrPlace, float x, float y, float width, float height,
int horzAlign, int vertAlign, const vec4_t* color)> UI_FillRect{ 0x140CBDE30 };
WEAK symbol<void(const ScreenPlacement* scrPlace, float x, float y, float w, float h,
int horzAlign, int vertAlign, const vec4_t* color, Material* material)> UI_DrawLoadBar{ 0x140CBDC40 };
WEAK symbol<void(const ScreenPlacement* scrPlace, const char* text, int maxChars, GfxFont* font, float x, float y,
int horzAlign, int vertAlign, float scale, const vec4_t* color, int style)> UI_DrawText{ 0x140CC5C00 };
WEAK symbol<int(const char* text, int maxChars, GfxFont* font, float scale)> UI_TextWidth{ 0x140CC9FA0 };
WEAK symbol<float(XAnim_s* anims, unsigned int anim)> XAnimGetLengthMsec{ 0x140D761C0 };
@ -365,6 +378,12 @@ namespace game
WEAK symbol<const char*> g_HitLocNames{ 0x14196AAF0 };
WEAK symbol<bool> cl_serverLoadingMap{ 0x141FE5D74 };
WEAK symbol<bool> g_waitingForServer{ 0x14523ED91 };
WEAK symbol<Material*> whiteMaterial{ 0x141FE5ED0 };
WEAK symbol<vec4_t> colorWhite{ 0x141524800 };
namespace hks
{
WEAK symbol<lua_State*> lua_state{ 0x144FC35F0 };