[MapRotation]: Rename dvar (#737)

This commit is contained in:
Edo 2023-01-27 23:05:26 +00:00 committed by GitHub
parent b1f022b34f
commit b599a9c700
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 175 additions and 134 deletions

View File

@ -197,10 +197,10 @@ namespace Components
CardTitles::CardTitles() CardTitles::CardTitles()
{ {
Scheduler::Once([] Events::OnDvarInit([]
{ {
CustomTitle = Dvar::Register<const char*>("customTitle", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE, "Custom card title"); CustomTitle = Dvar::Register<const char*>("customTitle", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE, "Custom card title");
}, Scheduler::Pipeline::MAIN); });
std::memset(&CustomTitles, 0, sizeof(char[Game::MAX_CLIENTS][18])); std::memset(&CustomTitles, 0, sizeof(char[Game::MAX_CLIENTS][18]));

View File

@ -342,10 +342,8 @@ namespace Components
nullptr, nullptr,
}; };
DebugOverlay = Game::Dvar_RegisterEnum("debugOverlay", debugOverlayNames_0, 0, DebugOverlay = Game::Dvar_RegisterEnum("debugOverlay", debugOverlayNames_0, 0, Game::DVAR_NONE, "Toggles the display of various debug info.");
Game::DVAR_NONE, "Toggles the display of various debug info."); BugName = Game::Dvar_RegisterString("bug_name", "bug0", Game::DVAR_NONE, "Name appended to the copied console log");
BugName = Game::Dvar_RegisterString("bug_name", "bug0",
Game::DVAR_CHEAT | Game::DVAR_CODINFO, "Name appended to the copied console log");
} }
const Game::dvar_t* Debug::Dvar_Register_PlayerDebugHealth(const char* name, bool value, [[maybe_unused]] std::uint16_t flags, const char* description) const Game::dvar_t* Debug::Dvar_Register_PlayerDebugHealth(const char* name, bool value, [[maybe_unused]] std::uint16_t flags, const char* description)
@ -356,7 +354,7 @@ namespace Components
Debug::Debug() Debug::Debug()
{ {
Scheduler::Once(CL_InitDebugDvars, Scheduler::Pipeline::MAIN); Events::OnDvarInit(CL_InitDebugDvars);
// Hook end of CG_DrawDebugOverlays (This is to ensure some checks are done before our hook is executed). // Hook end of CG_DrawDebugOverlays (This is to ensure some checks are done before our hook is executed).
Utils::Hook(0x49CB0A, CG_DrawDebugOverlays_Hk, HOOK_JUMP).install()->quick(); Utils::Hook(0x49CB0A, CG_DrawDebugOverlays_Hk, HOOK_JUMP).install()->quick();

View File

@ -3,6 +3,7 @@
#include "CardTitles.hpp" #include "CardTitles.hpp"
#include "ClanTags.hpp" #include "ClanTags.hpp"
#include "Party.hpp"
#include "ServerCommands.hpp" #include "ServerCommands.hpp"
namespace Components namespace Components
@ -114,10 +115,9 @@ namespace Components
{ {
Scheduler::Once([] Scheduler::Once([]
{ {
const auto partyEnable = Dvar::Var("party_enable").get<bool>();
std::string mapname = (*Game::sv_mapname)->current.string; std::string mapname = (*Game::sv_mapname)->current.string;
if (!partyEnable) // Time wrapping should not occur in party servers, but yeah... if (!Party::IsEnabled()) // Time wrapping should not occur in party servers, but yeah...
{ {
if (mapname.empty()) mapname = "mp_rust"; if (mapname.empty()) mapname = "mp_rust";
Command::Execute(std::format("map {}", mapname), true); Command::Execute(std::format("map {}", mapname), true);
@ -216,10 +216,10 @@ namespace Components
if (!ZoneBuilder::IsEnabled()) if (!ZoneBuilder::IsEnabled())
{ {
Scheduler::Once([] Events::OnDvarInit([]
{ {
SVMOTD = Dvar::Register<const char*>("sv_motd", "", Game::DVAR_NONE, "A custom message of the day for servers"); SVMOTD = Dvar::Register<const char*>("sv_motd", "", Game::DVAR_NONE, "A custom message of the day for servers");
}, Scheduler::Pipeline::MAIN); });
// Post initialization point // Post initialization point
Utils::Hook(0x60BFBF, PostInitializationStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x60BFBF, PostInitializationStub, HOOK_JUMP).install()->quick();

View File

@ -372,7 +372,7 @@ namespace Components
Scheduler::Once([] Scheduler::Once([]
{ {
framePushed = false; framePushed = false;
Dvar::Var("ui_dl_progress").set(Utils::String::VA("(%d/%d) %d%%", dlIndex, dlSize, dlProgress)); Dvar::Var("ui_dl_progress").set(std::format("({}/{}) {}%%", dlIndex, dlSize, dlProgress));
}, Scheduler::Pipeline::CLIENT); }, Scheduler::Pipeline::CLIENT);
} }
@ -683,12 +683,12 @@ namespace Components
} }
else else
{ {
Scheduler::Once([] Events::OnDvarInit([]
{ {
Dvar::Register<const char*>("ui_dl_timeLeft", "", Game::DVAR_NONE, ""); Dvar::Register<const char*>("ui_dl_timeLeft", "", Game::DVAR_NONE, "");
Dvar::Register<const char*>("ui_dl_progress", "", Game::DVAR_NONE, ""); Dvar::Register<const char*>("ui_dl_progress", "", Game::DVAR_NONE, "");
Dvar::Register<const char*>("ui_dl_transRate", "", Game::DVAR_NONE, ""); Dvar::Register<const char*>("ui_dl_transRate", "", Game::DVAR_NONE, "");
}, Scheduler::Pipeline::MAIN); });
UIScript::Add("mod_download_cancel", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) UIScript::Add("mod_download_cancel", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
{ {
@ -696,11 +696,11 @@ namespace Components
}); });
} }
Scheduler::Once([] Events::OnDvarInit([]
{ {
SV_wwwDownload = Dvar::Register<bool>("sv_wwwDownload", false, Game::DVAR_NONE, "Set to true to enable downloading maps/mods from an external server."); SV_wwwDownload = Dvar::Register<bool>("sv_wwwDownload", false, Game::DVAR_NONE, "Set to true to enable downloading maps/mods from an external server.");
SV_wwwBaseUrl = Dvar::Register<const char*>("sv_wwwBaseUrl", "", Game::DVAR_NONE, "Set to the base url for the external map download."); SV_wwwBaseUrl = Dvar::Register<const char*>("sv_wwwBaseUrl", "", Game::DVAR_NONE, "Set to the base url for the external map download.");
}, Scheduler::Pipeline::MAIN); });
} }
Download::~Download() Download::~Download()

View File

@ -8,7 +8,7 @@ namespace Components
: dvar_(Game::Dvar_FindVar(dvarName.data())) : dvar_(Game::Dvar_FindVar(dvarName.data()))
{ {
// If the dvar can't be found it will be registered as an empty string dvar // If the dvar can't be found it will be registered as an empty string dvar
if (this->dvar_ == nullptr) if (!this->dvar_)
{ {
this->dvar_ = const_cast<Game::dvar_t*>(Game::Dvar_SetFromStringByNameFromSource(dvarName.data(), "", Game::DVAR_SOURCE_INTERNAL)); this->dvar_ = const_cast<Game::dvar_t*>(Game::Dvar_SetFromStringByNameFromSource(dvarName.data(), "", Game::DVAR_SOURCE_INTERNAL));
} }
@ -21,22 +21,28 @@ namespace Components
template <> const char* Dvar::Var::get() template <> const char* Dvar::Var::get()
{ {
if (this->dvar_ == nullptr) if (!this->dvar_)
{
return ""; return "";
}
if (this->dvar_->type == Game::DVAR_TYPE_STRING || this->dvar_->type == Game::DVAR_TYPE_ENUM) if (this->dvar_->type == Game::DVAR_TYPE_STRING || this->dvar_->type == Game::DVAR_TYPE_ENUM)
{ {
if (this->dvar_->current.string != nullptr) if (this->dvar_->current.string)
{
return this->dvar_->current.string; return this->dvar_->current.string;
} }
}
return ""; return "";
} }
template <> int Dvar::Var::get() template <> int Dvar::Var::get()
{ {
if (this->dvar_ == nullptr) if (!this->dvar_)
{
return 0; return 0;
}
if (this->dvar_->type == Game::DVAR_TYPE_INT || this->dvar_->type == Game::DVAR_TYPE_ENUM) if (this->dvar_->type == Game::DVAR_TYPE_INT || this->dvar_->type == Game::DVAR_TYPE_ENUM)
{ {
@ -48,8 +54,10 @@ namespace Components
template <> unsigned int Dvar::Var::get() template <> unsigned int Dvar::Var::get()
{ {
if (this->dvar_ == nullptr) if (!this->dvar_)
{
return 0; return 0;
}
if (this->dvar_->type == Game::DVAR_TYPE_INT) if (this->dvar_->type == Game::DVAR_TYPE_INT)
{ {
@ -61,8 +69,10 @@ namespace Components
template <> float Dvar::Var::get() template <> float Dvar::Var::get()
{ {
if (this->dvar_ == nullptr) if (!this->dvar_)
{
return 0.f; return 0.f;
}
if (this->dvar_->type == Game::DVAR_TYPE_FLOAT) if (this->dvar_->type == Game::DVAR_TYPE_FLOAT)
{ {
@ -72,26 +82,12 @@ namespace Components
return 0.f; return 0.f;
} }
template <> float* Dvar::Var::get()
{
static Game::vec4_t vector{0.f, 0.f, 0.f, 0.f};
if (this->dvar_ == nullptr)
return vector;
if (this->dvar_->type == Game::DVAR_TYPE_FLOAT_2 || this->dvar_->type == Game::DVAR_TYPE_FLOAT_3 ||
this->dvar_->type == Game::DVAR_TYPE_FLOAT_4)
{
return this->dvar_->current.vector;
}
return vector;
}
template <> bool Dvar::Var::get() template <> bool Dvar::Var::get()
{ {
if (this->dvar_ == nullptr) if (!this->dvar_)
{
return false; return false;
}
if (this->dvar_->type == Game::DVAR_TYPE_BOOL) if (this->dvar_->type == Game::DVAR_TYPE_BOOL)
{ {
@ -108,7 +104,9 @@ namespace Components
void Dvar::Var::set(const char* string) void Dvar::Var::set(const char* string)
{ {
assert(string);
assert(this->dvar_->type == Game::DVAR_TYPE_STRING); assert(this->dvar_->type == Game::DVAR_TYPE_STRING);
if (this->dvar_) if (this->dvar_)
{ {
Game::Dvar_SetString(this->dvar_, string); Game::Dvar_SetString(this->dvar_, string);
@ -299,7 +297,7 @@ namespace Components
{ {
// Save the dvar original value if it has the archive flag // Save the dvar original value if it has the archive flag
const auto* dvar = Game::Dvar_FindVar(dvarName); const auto* dvar = Game::Dvar_FindVar(dvarName);
if (dvar != nullptr && dvar->flags & Game::DVAR_ARCHIVE) if (dvar && dvar->flags & Game::DVAR_ARCHIVE)
{ {
if (!AreArchiveDvarsUnprotected()) if (!AreArchiveDvarsUnprotected())
{ {
@ -310,7 +308,7 @@ namespace Components
Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Server is overriding saved dvar '{}'\n", dvarName); Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Server is overriding saved dvar '{}'\n", dvarName);
} }
if (dvar != nullptr && std::strcmp(dvar->name, "com_errorResolveCommand") == 0) if (dvar && std::strcmp(dvar->name, "com_errorResolveCommand") == 0)
{ {
Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Not allowing server to set '{}'\n", dvar->name); Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Not allowing server to set '{}'\n", dvar->name);
return; return;

View File

@ -14,7 +14,7 @@ namespace Components
auto* ps = pm->ps; auto* ps = pm->ps;
auto i = 0; auto i = 0;
const auto elevatorSetting = Elevators::BG_Elevators.get<int>(); const auto elevatorSetting = BG_Elevators.get<int>();
while (true) while (true)
{ {
point[0] = ps->origin[0] + (*Game::CorrectSolidDeltas)[i][0]; point[0] = ps->origin[0] + (*Game::CorrectSolidDeltas)[i][0];
@ -24,7 +24,7 @@ namespace Components
Game::PM_playerTrace(pm, trace, point, point, &pm->bounds, ps->clientNum, pm->tracemask); Game::PM_playerTrace(pm, trace, point, point, &pm->bounds, ps->clientNum, pm->tracemask);
// If the player wishes to glitch without effort they can do so // If the player wishes to glitch without effort they can do so
if (!trace->startsolid || elevatorSetting == Elevators::EASY) if (!trace->startsolid || elevatorSetting == EASY)
{ {
ps->origin[0] = point[0]; ps->origin[0] = point[0];
ps->origin[1] = point[1]; ps->origin[1] = point[1];
@ -35,7 +35,7 @@ namespace Components
// If elevators are disabled we need to check that startsolid is false before proceeding // If elevators are disabled we need to check that startsolid is false before proceeding
// like later versions of the game do // like later versions of the game do
if (!trace->startsolid || elevatorSetting >= Elevators::ENABLED) if (!trace->startsolid || elevatorSetting >= ENABLED)
{ {
break; break;
} }
@ -69,7 +69,7 @@ namespace Components
Game::PM_Trace(pm, results, start, end, bounds, passEntityNum, contentMask); Game::PM_Trace(pm, results, start, end, bounds, passEntityNum, contentMask);
// Allow the player to stand even when there is no headroom // Allow the player to stand even when there is no headroom
if (Elevators::BG_Elevators.get<int>() == Elevators::EASY) if (BG_Elevators.get<int>() == EASY)
{ {
results->allsolid = false; results->allsolid = false;
} }
@ -85,7 +85,7 @@ namespace Components
push [esp + 0x8 + 0x24] push [esp + 0x8 + 0x24]
push [esp + 0x8 + 0x24] push [esp + 0x8 + 0x24]
push eax push eax
call Elevators::PM_CorrectAllSolid call PM_CorrectAllSolid
add esp, 0xC add esp, 0xC
mov [esp + 0x20], eax mov [esp + 0x20], eax
@ -98,7 +98,7 @@ namespace Components
Elevators::Elevators() Elevators::Elevators()
{ {
Scheduler::Once([] Events::OnDvarInit([]
{ {
static const char* values[] = static const char* values[] =
{ {
@ -108,16 +108,15 @@ namespace Components
nullptr nullptr
}; };
Elevators::BG_Elevators = Game::Dvar_RegisterEnum("bg_elevators", values, BG_Elevators = Game::Dvar_RegisterEnum("bg_elevators", values, ENABLED, Game::DVAR_CODINFO, "Elevators glitch settings");
Elevators::ENABLED, Game::DVAR_CODINFO, "Elevators glitch settings"); });
}, Scheduler::Pipeline::MAIN);
Utils::Hook(0x57369E, Elevators::PM_CorrectAllSolidStub, HOOK_CALL).install()->quick(); // PM_GroundTrace Utils::Hook(0x57369E, PM_CorrectAllSolidStub, HOOK_CALL).install()->quick(); // PM_GroundTrace
// Place hooks in PM_CheckDuck. If the elevators dvar is set to easy the // Place hooks in PM_CheckDuck. If the elevators dvar is set to easy the
// flags for duck/prone will always be removed from the player state // flags for duck/prone will always be removed from the player state
Utils::Hook(0x570EC5, Elevators::PM_Trace_Hk, HOOK_CALL).install()->quick(); Utils::Hook(0x570EC5, PM_Trace_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x570E0B, Elevators::PM_Trace_Hk, HOOK_CALL).install()->quick(); Utils::Hook(0x570E0B, PM_Trace_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x570D70, Elevators::PM_Trace_Hk, HOOK_CALL).install()->quick(); Utils::Hook(0x570D70, PM_Trace_Hk, HOOK_CALL).install()->quick();
} }
} }

View File

@ -8,6 +8,7 @@ namespace Components
Utils::Signal<Events::Callback> Events::ShutdownSystemSignal; Utils::Signal<Events::Callback> Events::ShutdownSystemSignal;
Utils::Signal<Events::Callback> Events::ClientInitSignal; Utils::Signal<Events::Callback> Events::ClientInitSignal;
Utils::Signal<Events::Callback> Events::ServerInitSignal; Utils::Signal<Events::Callback> Events::ServerInitSignal;
Utils::Signal<Events::Callback> Events::DvarInitSignal;
void Events::OnClientDisconnect(const Utils::Slot<ClientCallback>& callback) void Events::OnClientDisconnect(const Utils::Slot<ClientCallback>& callback)
{ {
@ -39,6 +40,11 @@ namespace Components
ServerInitSignal.connect(callback); ServerInitSignal.connect(callback);
} }
void Events::OnDvarInit(const Utils::Slot<Callback>& callback)
{
DvarInitSignal.connect(callback);
}
/* /*
* Should be called when a client drops from the server * Should be called when a client drops from the server
* but not "between levels" (Quake-III-Arena) * but not "between levels" (Quake-III-Arena)
@ -87,6 +93,14 @@ namespace Components
Utils::Hook::Call<void()>(0x474320)(); // SV_InitGameMode Utils::Hook::Call<void()>(0x474320)(); // SV_InitGameMode
} }
void Events::Com_InitDvars_Hk()
{
DvarInitSignal();
DvarInitSignal.clear();
Utils::Hook::Call<void()>(0x60AD10)(); // Com_InitDvars
}
Events::Events() Events::Events()
{ {
Utils::Hook(0x625235, ClientDisconnect_Hk, HOOK_CALL).install()->quick(); // SV_FreeClient Utils::Hook(0x625235, ClientDisconnect_Hk, HOOK_CALL).install()->quick(); // SV_FreeClient
@ -100,6 +114,8 @@ namespace Components
Utils::Hook(0x60BE5B, CL_InitOnceForAllClients_HK, HOOK_CALL).install()->quick(); // Com_Init_Try_Block_Function Utils::Hook(0x60BE5B, CL_InitOnceForAllClients_HK, HOOK_CALL).install()->quick(); // Com_Init_Try_Block_Function
Utils::Hook(0x60BB3A, Com_InitDvars_Hk, HOOK_CALL).install()->quick(); // Com_Init_Try_Block_Function
Utils::Hook(0x4D3665, SV_Init_Hk, HOOK_CALL).install()->quick(); // SV_Init Utils::Hook(0x4D3665, SV_Init_Hk, HOOK_CALL).install()->quick(); // SV_Init
} }
} }

View File

@ -27,6 +27,9 @@ namespace Components
// Client & Server (triggered once) // Client & Server (triggered once)
static void OnSVInit(const Utils::Slot<Callback>& callback); static void OnSVInit(const Utils::Slot<Callback>& callback);
// Client & Server (triggered once)
static void OnDvarInit(const Utils::Slot<Callback>& callback);
private: private:
static Utils::Signal<ClientCallback> ClientDisconnectSignal; static Utils::Signal<ClientCallback> ClientDisconnectSignal;
static Utils::Signal<ClientConnectCallback> ClientConnectSignal; static Utils::Signal<ClientConnectCallback> ClientConnectSignal;
@ -34,6 +37,7 @@ namespace Components
static Utils::Signal<Callback> ShutdownSystemSignal; static Utils::Signal<Callback> ShutdownSystemSignal;
static Utils::Signal<Callback> ClientInitSignal; static Utils::Signal<Callback> ClientInitSignal;
static Utils::Signal<Callback> ServerInitSignal; static Utils::Signal<Callback> ServerInitSignal;
static Utils::Signal<Callback> DvarInitSignal;
static void ClientDisconnect_Hk(int clientNum); static void ClientDisconnect_Hk(int clientNum);
static void SV_UserinfoChanged_Hk(Game::client_t* cl); static void SV_UserinfoChanged_Hk(Game::client_t* cl);
@ -41,5 +45,6 @@ namespace Components
static void Scr_ShutdownSystem_Hk(unsigned char sys); static void Scr_ShutdownSystem_Hk(unsigned char sys);
static void CL_InitOnceForAllClients_HK(); static void CL_InitOnceForAllClients_HK();
static void SV_Init_Hk(); static void SV_Init_Hk();
static void Com_InitDvars_Hk();
}; };
} }

View File

@ -5,6 +5,7 @@ namespace Components
{ {
Dvar::Var MapRotation::SVRandomMapRotation; Dvar::Var MapRotation::SVRandomMapRotation;
Dvar::Var MapRotation::SVDontRotate; Dvar::Var MapRotation::SVDontRotate;
Dvar::Var MapRotation::SVNextMap;
MapRotation::RotationData MapRotation::DedicatedRotation; MapRotation::RotationData MapRotation::DedicatedRotation;
@ -263,19 +264,23 @@ namespace Components
const auto& entry = rotation.peekNextEntry(); const auto& entry = rotation.peekNextEntry();
if (entry.first == "map"s) if (entry.first == "map"s)
{ {
Game::Dvar_SetString(*Game::nextmap, entry.second.data()); SVNextMap.set(entry.second);
}
else
{
ClearNextMap();
} }
} }
void MapRotation::SetNextMap(const char* value) void MapRotation::SetNextMap(const char* value)
{ {
assert(value); assert(value);
Game::Dvar_SetString(*Game::nextmap, value); SVNextMap.set(value);
} }
void MapRotation::ClearNextMap() void MapRotation::ClearNextMap()
{ {
Game::Dvar_SetString(*Game::nextmap, ""); SVNextMap.set("");
} }
void MapRotation::RandomizeMapRotation() void MapRotation::RandomizeMapRotation()
@ -325,15 +330,19 @@ namespace Components
SetNextMap(DedicatedRotation); SetNextMap(DedicatedRotation);
} }
void MapRotation::RegisterMapRotationDvars()
{
SVRandomMapRotation = Dvar::Register<bool>("sv_randomMapRotation", false, Game::DVAR_ARCHIVE, "Randomize map rotation when true");
SVDontRotate = Dvar::Register<bool>("sv_dontRotate", false, Game::DVAR_NONE, "Do not perform map rotation");
SVNextMap = Dvar::Register<const char*>("sv_nextMap", "", Game::DVAR_SERVERINFO, "");
}
MapRotation::MapRotation() MapRotation::MapRotation()
{ {
AddMapRotationCommands(); AddMapRotationCommands();
Utils::Hook::Set<void(*)()>(0x4152E8, SV_MapRotate_f); Utils::Hook::Set<void(*)()>(0x4152E8, SV_MapRotate_f);
SVRandomMapRotation = Dvar::Register<bool>("sv_randomMapRotation", false, Events::OnDvarInit(RegisterMapRotationDvars);
Game::DVAR_ARCHIVE, "Randomize map rotation when true");
SVDontRotate = Dvar::Register<bool>("sv_dontRotate", false,
Game::DVAR_NONE, "Do not perform map rotation");
} }
bool MapRotation::unitTest() bool MapRotation::unitTest()

View File

@ -48,6 +48,7 @@ namespace Components
// Rotation Dvars // Rotation Dvars
static Dvar::Var SVRandomMapRotation; static Dvar::Var SVRandomMapRotation;
static Dvar::Var SVDontRotate; static Dvar::Var SVDontRotate;
static Dvar::Var SVNextMap;
// Holds the parsed data from sv_mapRotation // Holds the parsed data from sv_mapRotation
static RotationData DedicatedRotation; static RotationData DedicatedRotation;
@ -57,6 +58,7 @@ namespace Components
// Use these commands before SV_MapRotate_f is called // Use these commands before SV_MapRotate_f is called
static void AddMapRotationCommands(); static void AddMapRotationCommands();
static void RegisterMapRotationDvars();
static bool ShouldRotate(); static bool ShouldRotate();
static void ApplyMap(const std::string& map); static void ApplyMap(const std::string& map);

View File

@ -265,7 +265,7 @@ namespace Components
AssertOffset(Game::playerState_s, eFlags, 0xB0); AssertOffset(Game::playerState_s, eFlags, 0xB0);
AssertOffset(Game::playerState_s, pm_flags, 0xC); AssertOffset(Game::playerState_s, pm_flags, 0xC);
Scheduler::Once([] Events::OnDvarInit([]
{ {
static const char* bg_bouncesValues[] = static const char* bg_bouncesValues[] =
{ {
@ -275,9 +275,8 @@ namespace Components
nullptr nullptr
}; };
BGBounces = Game::Dvar_RegisterEnum("bg_bounces", BGBounces = Game::Dvar_RegisterEnum("bg_bounces", bg_bouncesValues, DISABLED, Game::DVAR_CODINFO, "Bounce glitch settings");
bg_bouncesValues, DISABLED, Game::DVAR_CODINFO, "Bounce glitch settings"); });
}, Scheduler::Pipeline::MAIN);
// Hook Dvar_RegisterFloat. Only thing that's changed is that the 0x80 flag is not used. // Hook Dvar_RegisterFloat. Only thing that's changed is that the 0x80 flag is not used.
Utils::Hook(0x448990, Dvar_RegisterSpectateSpeedScale, HOOK_CALL).install()->quick(); Utils::Hook(0x448990, Dvar_RegisterSpectateSpeedScale, HOOK_CALL).install()->quick();

View File

@ -161,11 +161,11 @@ namespace Components
RconContainer.timestamp = 0; RconContainer.timestamp = 0;
Scheduler::Once([] Events::OnDvarInit([]
{ {
RconPassword = Dvar::Register<const char*>("rcon_password", "", Game::DVAR_NONE, "The password for rcon"); RconPassword = Dvar::Register<const char*>("rcon_password", "", Game::DVAR_NONE, "The password for rcon");
RconLogRequests = Dvar::Register<bool>("rcon_log_requests", false, Game::DVAR_NONE, "Print remote commands in the output log"); RconLogRequests = Dvar::Register<bool>("rcon_log_requests", false, Game::DVAR_NONE, "Print remote commands in the output log");
}, Scheduler::Pipeline::MAIN); });
Network::OnClientPacket("rcon", [](const Network::Address& address, [[maybe_unused]] const std::string& data) Network::OnClientPacket("rcon", [](const Network::Address& address, [[maybe_unused]] const std::string& data)
{ {

View File

@ -550,7 +550,7 @@ namespace Components
// End vid_restart // End vid_restart
Utils::Hook(0x4CA3A7, Renderer::PostVidRestartStub, HOOK_CALL).install()->quick(); Utils::Hook(0x4CA3A7, Renderer::PostVidRestartStub, HOOK_CALL).install()->quick();
Scheduler::Once([] Events::OnDvarInit([]
{ {
static const char* values[] = static const char* values[] =
{ {
@ -566,9 +566,9 @@ namespace Components
Renderer::r_drawTriggers = Game::Dvar_RegisterBool("r_drawTriggers", false, Game::DVAR_CHEAT, "Draw triggers"); Renderer::r_drawTriggers = Game::Dvar_RegisterBool("r_drawTriggers", false, Game::DVAR_CHEAT, "Draw triggers");
Renderer::r_drawModelNames = Game::Dvar_RegisterEnum("r_drawModelNames", values, 0, Game::DVAR_CHEAT, "Draw all model names"); Renderer::r_drawModelNames = Game::Dvar_RegisterEnum("r_drawModelNames", values, 0, Game::DVAR_CHEAT, "Draw all model names");
Renderer::r_drawAABBTrees = Game::Dvar_RegisterBool("r_drawAabbTrees", false, Game::DVAR_CHEAT, "Draw aabb trees"); Renderer::r_drawAABBTrees = Game::Dvar_RegisterBool("r_drawAabbTrees", false, Game::DVAR_CHEAT, "Draw aabb trees");
Renderer::r_playerDrawDebugDistance = Game::Dvar_RegisterInt("r_drawDebugDistance", 1000, 0, 50000, Game::DVAR_ARCHIVE, "r_draw debug functions draw distance, relative to the player"); Renderer::r_playerDrawDebugDistance = Game::Dvar_RegisterInt("r_drawDebugDistance", 1000, 0, 50000, Game::DVAR_ARCHIVE, "r_draw debug functions draw distance relative to the player");
Renderer::r_forceTechnique = Game::Dvar_RegisterInt("r_forceTechnique", 0, 0, 14, Game::DVAR_NONE, "Force a base technique on the renderer"); Renderer::r_forceTechnique = Game::Dvar_RegisterInt("r_forceTechnique", 0, 0, 14, Game::DVAR_NONE, "Force a base technique on the renderer");
}, Scheduler::Pipeline::MAIN); });
} }
Renderer::~Renderer() Renderer::~Renderer()

View File

@ -161,7 +161,7 @@ namespace Components
// Ensure mapname is set // Ensure mapname is set
if (info.get("mapname").empty()) if (info.get("mapname").empty())
{ {
info.set("mapname", Dvar::Var("ui_mapname").get<const char*>()); info.set("mapname", (*Game::ui_mapname)->current.string);
} }
// Set matchtype // Set matchtype

View File

@ -834,7 +834,7 @@ namespace Components
FavouriteList.clear(); FavouriteList.clear();
VisibleList.clear(); VisibleList.clear();
Scheduler::Once([] Events::OnDvarInit([]
{ {
UIServerSelected = Dvar::Register<bool>("ui_serverSelected", false, UIServerSelected = Dvar::Register<bool>("ui_serverSelected", false,
Game::DVAR_NONE, "Whether a server has been selected in the serverlist"); Game::DVAR_NONE, "Whether a server has been selected in the serverlist");
@ -845,7 +845,7 @@ namespace Components
1, 10, Dedicated::IsEnabled() ? Game::DVAR_NONE : Game::DVAR_ARCHIVE, "Amount of server queries per frame"); 1, 10, Dedicated::IsEnabled() ? Game::DVAR_NONE : Game::DVAR_ARCHIVE, "Amount of server queries per frame");
NETServerFrames = Dvar::Register<int>("net_serverFrames", 30, NETServerFrames = Dvar::Register<int>("net_serverFrames", 30,
1, 60, Dedicated::IsEnabled() ? Game::DVAR_NONE : Game::DVAR_ARCHIVE, "Amount of server query frames per second"); 1, 60, Dedicated::IsEnabled() ? Game::DVAR_NONE : Game::DVAR_ARCHIVE, "Amount of server query frames per second");
}, Scheduler::Pipeline::MAIN); });
// Fix ui_netsource dvar // Fix ui_netsource dvar
Utils::Hook::Nop(0x4CDEEC, 5); // Don't reset the netsource when gametypes aren't loaded Utils::Hook::Nop(0x4CDEEC, 5); // Don't reset the netsource when gametypes aren't loaded

View File

@ -6,37 +6,41 @@ namespace Components
int StartupMessages::TotalMessages = -1; int StartupMessages::TotalMessages = -1;
std::list<std::string> StartupMessages::MessageList; std::list<std::string> StartupMessages::MessageList;
Dvar::Var StartupMessages::UIStartupMessage;
Dvar::Var StartupMessages::UIStartupMessageTitle;
Dvar::Var StartupMessages::UIStartupNextButtonText;
StartupMessages::StartupMessages() StartupMessages::StartupMessages()
{ {
Scheduler::Once([] Events::OnDvarInit([]
{ {
Dvar::Register<const char*>("ui_startupMessage", "", Game::DVAR_EXTERNAL | Game::DVAR_INIT, ""); UIStartupMessage = Dvar::Register<const char*>("ui_startupMessage", "", Game::DVAR_NONE, "");
Dvar::Register<const char*>("ui_startupMessageTitle", "", Game::DVAR_EXTERNAL | Game::DVAR_INIT, ""); UIStartupMessageTitle = Dvar::Register<const char*>("ui_startupMessageTitle", "", Game::DVAR_NONE, "");
Dvar::Register<const char*>("ui_startupNextButtonText", "", Game::DVAR_EXTERNAL | Game::DVAR_INIT, ""); UIStartupNextButtonText = Dvar::Register<const char*>("ui_startupNextButtonText", "", Game::DVAR_NONE, "");
}, Scheduler::Pipeline::MAIN); });
UIScript::Add("nextStartupMessage", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) UIScript::Add("nextStartupMessage", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
{ {
if (!StartupMessages::MessageList.size()) return; if (MessageList.empty()) return;
if (StartupMessages::TotalMessages < 1) if (TotalMessages < 1)
{ {
StartupMessages::TotalMessages = StartupMessages::MessageList.size(); TotalMessages = static_cast<int>(MessageList.size());
} }
const auto& message = StartupMessages::MessageList.front(); const auto& message = MessageList.front();
Game::Dvar_SetStringByName("ui_startupMessage", message.data()); UIStartupMessage.set(message);
Game::Dvar_SetStringByName("ui_startupMessageTitle", Utils::String::VA("Messages (%d/%d)", StartupMessages::TotalMessages - StartupMessages::MessageList.size(), StartupMessages::TotalMessages)); UIStartupMessageTitle.set(std::format("Messages ({}/{})", TotalMessages - MessageList.size(), TotalMessages));
Game::Dvar_SetStringByName("ui_startupNextButtonText", StartupMessages::MessageList.size() ? "Next" : "Close"); UIStartupNextButtonText.set(MessageList.empty() ? "Close" : "Next");
Game::Cbuf_AddText(0, "openmenu startup_messages\n"); Game::Cbuf_AddText(0, "openmenu startup_messages\n");
StartupMessages::MessageList.pop_front(); MessageList.pop_front();
}); });
} }
void StartupMessages::AddMessage(const std::string& message) void StartupMessages::AddMessage(const std::string& message)
{ {
StartupMessages::MessageList.push_back(message); MessageList.push_back(message);
} }
} }

View File

@ -12,5 +12,9 @@ namespace Components
private: private:
static int TotalMessages; static int TotalMessages;
static std::list<std::string> MessageList; static std::list<std::string> MessageList;
static Dvar::Var UIStartupMessage;
static Dvar::Var UIStartupMessageTitle;
static Dvar::Var UIStartupNextButtonText;
}; };
} }

View File

@ -6,16 +6,20 @@ namespace Components
UIFeeder::Container UIFeeder::Current; UIFeeder::Container UIFeeder::Current;
std::unordered_map<float, UIFeeder::Callbacks> UIFeeder::Feeders; std::unordered_map<float, UIFeeder::Callbacks> UIFeeder::Feeders;
void UIFeeder::Add(float feeder, UIFeeder::GetItemCount_t itemCountCb, UIFeeder::GetItemText_t itemTextCb, UIFeeder::Select_t selectCb) Dvar::Var UIFeeder::UIMapLong;
Dvar::Var UIFeeder::UIMapName;
Dvar::Var UIFeeder::UIMapDesc;
void UIFeeder::Add(float feeder, GetItemCount_t itemCountCb, GetItemText_t itemTextCb, Select_t selectCb)
{ {
UIFeeder::Feeders[feeder] = { itemCountCb, itemTextCb, selectCb }; Feeders[feeder] = { itemCountCb, itemTextCb, selectCb };
} }
const char* UIFeeder::GetItemText() const char* UIFeeder::GetItemText()
{ {
if (UIFeeder::Feeders.contains(UIFeeder::Current.feeder)) if (Feeders.contains(Current.feeder))
{ {
return UIFeeder::Feeders[UIFeeder::Current.feeder].getItemText(UIFeeder::Current.index, UIFeeder::Current.column); return Feeders[Current.feeder].getItemText(Current.index, Current.column);
} }
return nullptr; return nullptr;
@ -23,9 +27,9 @@ namespace Components
unsigned int UIFeeder::GetItemCount() unsigned int UIFeeder::GetItemCount()
{ {
if (UIFeeder::Feeders.contains(UIFeeder::Current.feeder)) if (Feeders.contains(Current.feeder))
{ {
return UIFeeder::Feeders[UIFeeder::Current.feeder].getItemCount(); return Feeders[Current.feeder].getItemCount();
} }
return 0; return 0;
@ -33,9 +37,9 @@ namespace Components
bool UIFeeder::SetItemSelection() bool UIFeeder::SetItemSelection()
{ {
if (UIFeeder::Feeders.find(UIFeeder::Current.feeder) != UIFeeder::Feeders.end()) if (Feeders.contains(Current.feeder))
{ {
UIFeeder::Feeders[UIFeeder::Current.feeder].select(UIFeeder::Current.index); Feeders[Current.feeder].select(Current.index);
return true; return true;
} }
@ -44,8 +48,8 @@ namespace Components
bool UIFeeder::CheckFeeder() bool UIFeeder::CheckFeeder()
{ {
if (UIFeeder::Current.feeder == 15.0f) return false; if (Current.feeder == 15.0f) return false;
return (UIFeeder::Feeders.find(UIFeeder::Current.feeder) != UIFeeder::Feeders.end()); return Feeders.contains(Current.feeder);
} }
__declspec(naked) void UIFeeder::SetItemSelectionStub() __declspec(naked) void UIFeeder::SetItemSelectionStub()
@ -53,12 +57,12 @@ namespace Components
__asm __asm
{ {
mov eax, [esp + 08h] mov eax, [esp + 08h]
mov UIFeeder::Current.feeder, eax mov Current.feeder, eax
mov eax, [esp + 0Ch] mov eax, [esp + 0Ch]
mov UIFeeder::Current.index, eax mov Current.index, eax
call UIFeeder::SetItemSelection call SetItemSelection
test al, al test al, al
jz continue jz continue
@ -78,15 +82,15 @@ namespace Components
__asm __asm
{ {
mov eax, [esp + 0Ch] mov eax, [esp + 0Ch]
mov UIFeeder::Current.feeder, eax mov Current.feeder, eax
mov eax, [esp + 10h] mov eax, [esp + 10h]
mov UIFeeder::Current.index, eax mov Current.index, eax
mov eax, [esp + 14h] mov eax, [esp + 14h]
mov UIFeeder::Current.column, eax mov Current.column, eax
call UIFeeder::GetItemText call GetItemText
test eax, eax test eax, eax
jz continue jz continue
@ -111,9 +115,9 @@ namespace Components
__asm __asm
{ {
mov eax, [esp + 8h] mov eax, [esp + 8h]
mov UIFeeder::Current.feeder, eax mov Current.feeder, eax
call UIFeeder::GetItemCount call GetItemCount
test eax, eax test eax, eax
jz continue jz continue
@ -131,17 +135,16 @@ namespace Components
__declspec(naked) void UIFeeder::HandleKeyStub() __declspec(naked) void UIFeeder::HandleKeyStub()
{ {
// ReSharper disable once CppEntityNeverUsed
static int nextClickTime = 0; static int nextClickTime = 0;
__asm __asm
{ {
mov ebx, ebp mov ebx, ebp
mov eax, [ebp + 12Ch] mov eax, [ebp + 12Ch]
mov UIFeeder::Current.feeder, eax mov Current.feeder, eax
push ebx push ebx
call UIFeeder::CheckFeeder call CheckFeeder
pop ebx pop ebx
test al, al test al, al
@ -180,9 +183,9 @@ namespace Components
// Update indices if not // Update indices if not
mov [ecx], edx mov [ecx], edx
mov UIFeeder::Current.index, edx mov Current.index, edx
call UIFeeder::SetItemSelection call SetItemSelection
returnSafe: returnSafe:
retn retn
@ -198,9 +201,9 @@ namespace Components
__asm __asm
{ {
mov eax, [edi + 12Ch] mov eax, [edi + 12Ch]
mov UIFeeder::Current.feeder, eax mov Current.feeder, eax
call UIFeeder::CheckFeeder call CheckFeeder
test al, al test al, al
jnz continue jnz continue
@ -218,9 +221,9 @@ namespace Components
__asm __asm
{ {
mov eax, [esp + 08h] mov eax, [esp + 08h]
mov UIFeeder::Current.feeder, eax mov Current.feeder, eax
call UIFeeder::CheckFeeder call CheckFeeder
test al, al test al, al
jnz continue jnz continue
@ -238,9 +241,9 @@ namespace Components
__asm __asm
{ {
mov eax, [edi + 12Ch] mov eax, [edi + 12Ch]
mov UIFeeder::Current.feeder, eax mov Current.feeder, eax
call UIFeeder::CheckFeeder call CheckFeeder
test al, al test al, al
jnz continue jnz continue
@ -257,13 +260,13 @@ namespace Components
{ {
if (Game::uiContext->openMenuCount > 0) if (Game::uiContext->openMenuCount > 0)
{ {
Game::menuDef_t* menu = Game::uiContext->menuStack[Game::uiContext->openMenuCount - 1]; auto* menu = Game::uiContext->menuStack[Game::uiContext->openMenuCount - 1];
if (menu && menu->items) if (menu && menu->items)
{ {
for (int i = 0; i < menu->itemCount; ++i) for (int i = 0; i < menu->itemCount; ++i)
{ {
Game::itemDef_s* item = menu->items[i]; auto* item = menu->items[i];
if (item && item->type == 6 && item->special == feeder) if (item && item->type == 6 && item->special == feeder)
{ {
item->cursorPos[0] = static_cast<int>(index); item->cursorPos[0] = static_cast<int>(index);
@ -302,13 +305,13 @@ namespace Components
if (index < static_cast<unsigned int>(*Game::arenaCount)) if (index < static_cast<unsigned int>(*Game::arenaCount))
{ {
index = reinterpret_cast<int*>(0x633E934)[index]; index = reinterpret_cast<int*>(0x633E934)[index];
const char* mapname = ArenaLength::NewArenas[index].mapName; const char* map_name = ArenaLength::NewArenas[index].mapName;
const char* longname = ArenaLength::NewArenas[index].uiName; const char* long_name = ArenaLength::NewArenas[index].uiName;
const char* description = ArenaLength::NewArenas[index].description; const char* description = ArenaLength::NewArenas[index].description;
Dvar::Var("ui_map_name").set(mapname); UIMapName.set(map_name);
Dvar::Var("ui_map_long").set(Game::SEH_StringEd_GetString(longname)); UIMapLong.set(Game::SEH_StringEd_GetString(long_name));
Dvar::Var("ui_map_desc").set(Game::SEH_StringEd_GetString(description)); UIMapDesc.set(Game::SEH_StringEd_GetString(description));
} }
} }
@ -322,21 +325,21 @@ namespace Components
void UIFeeder::ApplyInitialMap([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) void UIFeeder::ApplyInitialMap([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
{ {
const auto mapname = Dvar::Var("ui_mapname").get<std::string>(); const auto* mapname = (*Game::ui_mapname)->current.string;
Game::UI_UpdateArenas(); Game::UI_UpdateArenas();
Game::UI_SortArenas(); Game::UI_SortArenas();
for (unsigned int i = 0; i < static_cast<unsigned int>(*Game::arenaCount); ++i) for (unsigned int i = 0; i < static_cast<unsigned int>(*Game::arenaCount); ++i)
{ {
if (ArenaLength::NewArenas[i].mapName == mapname) if (!std::strcmp(ArenaLength::NewArenas[i].mapName, mapname))
{ {
for (unsigned int j = 0; j < static_cast<unsigned int>(*Game::arenaCount); ++j) for (unsigned int j = 0; j < static_cast<unsigned int>(*Game::arenaCount); ++j)
{ {
if (reinterpret_cast<unsigned int*>(0x633E934)[j] == i) if (reinterpret_cast<unsigned int*>(0x633E934)[j] == i)
{ {
UIFeeder::SelectMap(j); SelectMap(j);
UIFeeder::Select(60.0f, j); Select(60.0f, j);
break; break;
} }
} }
@ -361,7 +364,7 @@ namespace Components
call ecx // __ftol2_sse call ecx // __ftol2_sse
push eax push eax
call UIFeeder::CheckSelection call CheckSelection
test al, al test al, al
jz returnSafe jz returnSafe
@ -382,12 +385,12 @@ namespace Components
{ {
if (Dedicated::IsEnabled()) return; if (Dedicated::IsEnabled()) return;
Scheduler::Once([] Events::OnDvarInit([]
{ {
Dvar::Register<const char*>("ui_map_long", "Afghan", Game::DVAR_NONE, ""); UIMapLong = Dvar::Register<const char*>("ui_map_long", "Afghan", Game::DVAR_NONE, "");
Dvar::Register<const char*>("ui_map_name", "mp_afghan", Game::DVAR_NONE, ""); UIMapName = Dvar::Register<const char*>("ui_map_name", "mp_afghan", Game::DVAR_NONE, "");
Dvar::Register<const char*>("ui_map_desc", "", Game::DVAR_NONE, ""); UIMapDesc = Dvar::Register<const char*>("ui_map_desc", "", Game::DVAR_NONE, "");
}, Scheduler::Pipeline::MAIN); });
// Get feeder item count // Get feeder item count
Utils::Hook(0x41A0D0, UIFeeder::GetItemCountStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x41A0D0, UIFeeder::GetItemCountStub, HOOK_JUMP).install()->quick();

View File

@ -31,6 +31,10 @@ namespace Components
static Container Current; static Container Current;
static Dvar::Var UIMapLong;
static Dvar::Var UIMapName;
static Dvar::Var UIMapDesc;
static void GetItemCountStub(); static void GetItemCountStub();
static unsigned int GetItemCount(); static unsigned int GetItemCount();