2017-01-19 16:23:59 -05:00
|
|
|
#include "STDInclude.hpp"
|
|
|
|
|
|
|
|
namespace Components
|
|
|
|
{
|
2017-05-31 09:45:12 -04:00
|
|
|
Utils::Signal<Scheduler::Callback> Dvar::RegistrationSignal;
|
2021-10-03 16:23:26 -04:00
|
|
|
std::vector<std::string> Dvar::ChangedDvars;
|
2017-01-19 16:23:59 -05:00
|
|
|
|
2018-12-17 08:29:18 -05:00
|
|
|
Dvar::Var::Var(const std::string& dvarName) : Var()
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
this->dvar = Game::Dvar_FindVar(dvarName.data());
|
|
|
|
|
|
|
|
if (!this->dvar)
|
|
|
|
{
|
|
|
|
// Quick-register the dvar
|
|
|
|
Game::Dvar_SetStringByName(dvarName.data(), "");
|
|
|
|
this->dvar = Game::Dvar_FindVar(dvarName.data());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <> Game::dvar_t* Dvar::Var::get()
|
|
|
|
{
|
|
|
|
return this->dvar;
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <> char* Dvar::Var::get()
|
|
|
|
{
|
|
|
|
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_STRING && this->dvar->current.string)
|
|
|
|
{
|
2018-05-09 06:04:20 -04:00
|
|
|
return const_cast<char*>(this->dvar->current.string);
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
|
2020-12-09 14:13:34 -05:00
|
|
|
return const_cast<char*>("");
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <> const char* Dvar::Var::get()
|
|
|
|
{
|
|
|
|
return this->get<char*>();
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <> int Dvar::Var::get()
|
|
|
|
{
|
|
|
|
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_INT)
|
|
|
|
{
|
|
|
|
return this->dvar->current.integer;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <> unsigned int Dvar::Var::get()
|
|
|
|
{
|
|
|
|
return static_cast<unsigned int>(this->get<int>());
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <> float Dvar::Var::get()
|
|
|
|
{
|
|
|
|
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT)
|
|
|
|
{
|
|
|
|
return this->dvar->current.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <> float* Dvar::Var::get()
|
|
|
|
{
|
|
|
|
static float val[4] = { 0 };
|
|
|
|
|
|
|
|
if (this->dvar && (this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_2 || this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_3 || this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_4))
|
|
|
|
{
|
2018-05-09 06:04:20 -04:00
|
|
|
return this->dvar->current.vector;
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <> bool Dvar::Var::get()
|
|
|
|
{
|
|
|
|
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_BOOL)
|
|
|
|
{
|
2018-05-09 06:04:20 -04:00
|
|
|
return this->dvar->current.enabled;
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <> std::string Dvar::Var::get()
|
|
|
|
{
|
|
|
|
return this->get<const char*>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dvar::Var::set(char* string)
|
|
|
|
{
|
|
|
|
this->set(const_cast<const char*>(string));
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
void Dvar::Var::set(const char* string)
|
|
|
|
{
|
2021-09-01 17:19:44 -04:00
|
|
|
assert(this->dvar->type == Game::DVAR_TYPE_STRING);
|
|
|
|
if (this->dvar)
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
2021-08-31 12:12:25 -04:00
|
|
|
Game::Dvar_SetString(this->dvar, string);
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2018-12-17 08:29:18 -05:00
|
|
|
void Dvar::Var::set(const std::string& string)
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
this->set(string.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dvar::Var::set(int integer)
|
|
|
|
{
|
2021-09-01 17:19:44 -04:00
|
|
|
assert(this->dvar->type == Game::DVAR_TYPE_INT);
|
2017-01-19 16:23:59 -05:00
|
|
|
if (this->dvar)
|
|
|
|
{
|
2021-09-01 17:19:44 -04:00
|
|
|
Game::Dvar_SetInt(this->dvar, integer);
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
}
|
2021-09-09 04:50:49 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
void Dvar::Var::set(float value)
|
|
|
|
{
|
2021-09-01 17:19:44 -04:00
|
|
|
assert(this->dvar->type == Game::DVAR_TYPE_FLOAT);
|
2017-07-08 19:54:02 -04:00
|
|
|
if (this->dvar)
|
|
|
|
{
|
2021-09-01 17:19:44 -04:00
|
|
|
Game::Dvar_SetFloat(this->dvar, value);
|
2017-07-08 19:54:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-29 11:41:21 -04:00
|
|
|
void Dvar::Var::set(bool enabled)
|
2021-08-21 18:04:30 -04:00
|
|
|
{
|
2021-09-01 17:19:44 -04:00
|
|
|
assert(this->dvar->type == Game::DVAR_TYPE_BOOL);
|
2021-08-21 18:04:30 -04:00
|
|
|
if (this->dvar)
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
2021-09-09 04:44:04 -04:00
|
|
|
Game::Dvar_SetBool(this->dvar, enabled);
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dvar::Var::setRaw(int integer)
|
|
|
|
{
|
2021-09-10 05:40:30 -04:00
|
|
|
assert(this->dvar->type == Game::DVAR_TYPE_INT);
|
2017-01-19 16:23:59 -05:00
|
|
|
if (this->dvar)
|
|
|
|
{
|
|
|
|
this->dvar->current.integer = integer;
|
2021-09-10 05:40:30 -04:00
|
|
|
this->dvar->latched.integer = integer;
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-08 19:54:02 -04:00
|
|
|
void Dvar::Var::setRaw(float value)
|
|
|
|
{
|
2021-09-10 05:40:30 -04:00
|
|
|
assert(this->dvar->type == Game::DVAR_TYPE_FLOAT);
|
2017-07-08 19:54:02 -04:00
|
|
|
if (this->dvar)
|
|
|
|
{
|
|
|
|
this->dvar->current.value = value;
|
2021-09-10 05:40:30 -04:00
|
|
|
this->dvar->latched.value = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dvar::Var::setRaw(bool enabled)
|
|
|
|
{
|
|
|
|
assert(this->dvar->type == Game::DVAR_TYPE_BOOL);
|
|
|
|
if (this->dvar)
|
|
|
|
{
|
|
|
|
this->dvar->current.enabled = enabled;
|
|
|
|
this->dvar->latched.enabled = enabled;
|
2017-07-08 19:54:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template<> static Dvar::Var Dvar::Register(const char* name, bool value, Dvar::Flag flag, const char* description)
|
|
|
|
{
|
|
|
|
return Game::Dvar_RegisterBool(name, value, flag.val, description);
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template<> static Dvar::Var Dvar::Register(const char* name, const char* value, Dvar::Flag flag, const char* description)
|
|
|
|
{
|
|
|
|
return Game::Dvar_RegisterString(name, value, flag.val, description);
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template<> static Dvar::Var Dvar::Register(const char* name, int value, int min, int max, Dvar::Flag flag, const char* description)
|
|
|
|
{
|
|
|
|
return Game::Dvar_RegisterInt(name, value, min, max, flag.val, description);
|
|
|
|
}
|
2021-09-08 16:54:43 -04:00
|
|
|
|
2020-07-22 23:35:42 -04:00
|
|
|
template<> static Dvar::Var Dvar::Register(const char* name, float value, float min, float max, Dvar::Flag flag, const char* description)
|
|
|
|
{
|
|
|
|
return Game::Dvar_RegisterFloat(name, value, min, max, flag.val, description);
|
|
|
|
}
|
2017-01-19 16:23:59 -05:00
|
|
|
|
2017-05-31 09:45:12 -04:00
|
|
|
void Dvar::OnInit(Utils::Slot<Scheduler::Callback> callback)
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
Dvar::RegistrationSignal.connect(callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
Game::dvar_t* Dvar::RegisterName(const char* name, const char* /*default*/, Game::dvar_flag flag, const char* description)
|
|
|
|
{
|
|
|
|
// Run callbacks
|
|
|
|
Dvar::RegistrationSignal();
|
|
|
|
|
|
|
|
// Name watcher
|
2017-06-14 06:06:04 -04:00
|
|
|
Scheduler::OnFrame([]()
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
static std::string lastValidName = "Unknown Soldier";
|
|
|
|
std::string name = Dvar::Var("name").get<char*>();
|
|
|
|
|
|
|
|
// Don't perform any checks if name didn't change
|
|
|
|
if (name == lastValidName) return;
|
|
|
|
|
2021-09-07 08:33:36 -04:00
|
|
|
std::string saneName = TextRenderer::StripAllTextIcons(TextRenderer::StripColors(Utils::String::Trim(name)));
|
2017-01-19 16:23:59 -05:00
|
|
|
if (saneName.size() < 3 || (saneName[0] == '[' && saneName[1] == '{'))
|
|
|
|
{
|
|
|
|
Logger::Print("Username '%s' is invalid. It must at least be 3 characters long and not appear empty!\n", name.data());
|
|
|
|
Dvar::Var("name").set(lastValidName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lastValidName = name;
|
2017-01-31 11:04:54 -05:00
|
|
|
Friends::UpdateName();
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
2017-06-01 04:25:13 -04:00
|
|
|
}, true);
|
2017-01-19 16:23:59 -05:00
|
|
|
|
2017-02-10 04:19:36 -05:00
|
|
|
std::string username = "Unknown Soldier";
|
|
|
|
|
|
|
|
if (Steam::Proxy::SteamFriends)
|
|
|
|
{
|
|
|
|
const char* steamName = Steam::Proxy::SteamFriends->GetPersonaName();
|
|
|
|
|
|
|
|
if (steamName && !std::string(steamName).empty())
|
|
|
|
{
|
|
|
|
username = steamName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Dvar::Register<const char*>(name, username.data(), Dvar::Flag(flag | Game::dvar_flag::DVAR_FLAG_SAVED).val, description).get<Game::dvar_t*>();
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
|
2017-07-09 07:36:13 -04:00
|
|
|
Game::dvar_t* Dvar::SetFromStringByNameSafeExternal(const char* dvar, const char* value)
|
|
|
|
{
|
|
|
|
static const char* exceptions[] =
|
|
|
|
{
|
|
|
|
"ui_showEndOfGame",
|
|
|
|
"systemlink",
|
|
|
|
"splitscreen",
|
|
|
|
"onlinegame",
|
|
|
|
"party_maxplayers",
|
|
|
|
"xblive_privateserver",
|
|
|
|
"xblive_rankedmatch",
|
|
|
|
"ui_mptype",
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 0; i < ARRAYSIZE(exceptions); ++i)
|
|
|
|
{
|
|
|
|
if (Utils::String::ToLower(dvar) == Utils::String::ToLower(exceptions[i]))
|
|
|
|
{
|
|
|
|
return Game::Dvar_SetFromStringByName(dvar, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Dvar::SetFromStringByNameExternal(dvar, value);
|
|
|
|
}
|
|
|
|
|
2017-02-18 05:39:01 -05:00
|
|
|
Game::dvar_t* Dvar::SetFromStringByNameExternal(const char* dvar, const char* value)
|
|
|
|
{
|
2021-10-03 16:23:26 -04:00
|
|
|
Dvar::ChangedDvars.push_back(dvar);
|
2017-02-18 05:39:01 -05:00
|
|
|
return Game::Dvar_SetFromStringByNameFromSource(dvar, value, Game::DvarSetSource::DVAR_SOURCE_EXTERNAL);
|
|
|
|
}
|
|
|
|
|
2021-10-04 14:11:37 -04:00
|
|
|
void Dvar::Dvar_Reset(Game::dvar_t* var, Game::DvarSetSource source)
|
|
|
|
{
|
|
|
|
assert(var != nullptr);
|
|
|
|
OutputDebugStringA(Utils::String::VA("Dvar pointer: %p\n"));
|
|
|
|
Game::Dvar_SetVariant(var, var->reset, source);
|
|
|
|
}
|
|
|
|
|
2021-10-03 16:23:26 -04:00
|
|
|
void Dvar::ResetDvarsValue()
|
|
|
|
{
|
2021-10-04 14:11:37 -04:00
|
|
|
auto it = Dvar::ChangedDvars.begin();
|
|
|
|
while (it != Dvar::ChangedDvars.end())
|
2021-10-03 16:23:26 -04:00
|
|
|
{
|
|
|
|
auto var = Dvar::Var(*it).get<Game::dvar_t*>();
|
2021-10-04 14:11:37 -04:00
|
|
|
Dvar::Dvar_Reset(var, Game::DVAR_SOURCE_INTERNAL);
|
2021-10-03 16:23:26 -04:00
|
|
|
it = Dvar::ChangedDvars.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
Dvar::Dvar()
|
|
|
|
{
|
|
|
|
// set flags of cg_drawFPS to archive
|
|
|
|
Utils::Hook::Or<BYTE>(0x4F8F69, Game::dvar_flag::DVAR_FLAG_SAVED);
|
|
|
|
|
2021-03-18 20:02:48 -04:00
|
|
|
// un-cheat camera_thirdPersonCrosshairOffset and add archive flags
|
|
|
|
Utils::Hook::Xor<BYTE>(0x447B41, Game::dvar_flag::DVAR_FLAG_CHEAT | Game::dvar_flag::DVAR_FLAG_SAVED);
|
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
// un-cheat cg_fov and add archive flags
|
|
|
|
Utils::Hook::Xor<BYTE>(0x4F8E35, Game::dvar_flag::DVAR_FLAG_CHEAT | Game::dvar_flag::DVAR_FLAG_SAVED);
|
2020-12-04 16:04:50 -05:00
|
|
|
|
|
|
|
// un-cheat cg_fovscale and add archive flags
|
|
|
|
Utils::Hook::Xor<BYTE>(0x4F8E68, Game::dvar_flag::DVAR_FLAG_CHEAT | Game::dvar_flag::DVAR_FLAG_SAVED);
|
2017-01-19 16:23:59 -05:00
|
|
|
|
|
|
|
// un-cheat cg_debugInfoCornerOffset and add archive flags
|
|
|
|
Utils::Hook::Xor<BYTE>(0x4F8FC2, Game::dvar_flag::DVAR_FLAG_CHEAT | Game::dvar_flag::DVAR_FLAG_SAVED);
|
|
|
|
|
|
|
|
// remove archive flags for cg_hudchatposition
|
|
|
|
Utils::Hook::Xor<BYTE>(0x4F9992, Game::dvar_flag::DVAR_FLAG_SAVED);
|
|
|
|
|
|
|
|
// remove write protection from fs_game
|
|
|
|
Utils::Hook::Xor<DWORD>(0x6431EA, Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED);
|
|
|
|
|
|
|
|
// set cg_fov max to 90.0
|
2017-05-27 08:40:12 -04:00
|
|
|
// ...120 because of V2
|
|
|
|
static float cgFov90 = 120.0f;
|
2017-01-19 16:23:59 -05:00
|
|
|
Utils::Hook::Set<float*>(0x4F8E28, &cgFov90);
|
|
|
|
|
|
|
|
// set max volume to 1
|
|
|
|
static float volume = 1.0f;
|
|
|
|
Utils::Hook::Set<float*>(0x408078, &volume);
|
|
|
|
|
|
|
|
// Uncheat ui_showList
|
|
|
|
Utils::Hook::Xor<BYTE>(0x6310DC, Game::dvar_flag::DVAR_FLAG_CHEAT);
|
|
|
|
|
|
|
|
// Uncheat ui_debugMode
|
|
|
|
Utils::Hook::Xor<BYTE>(0x6312DE, Game::dvar_flag::DVAR_FLAG_CHEAT);
|
|
|
|
|
|
|
|
// Hook dvar 'name' registration
|
|
|
|
Utils::Hook(0x40531C, Dvar::RegisterName, HOOK_CALL).install()->quick();
|
2017-02-18 05:39:01 -05:00
|
|
|
|
2020-10-30 19:08:21 -04:00
|
|
|
// un-cheat safeArea_* and add archive flags
|
2020-10-31 13:55:32 -04:00
|
|
|
Utils::Hook::Xor<INT>(0x42E3F5, Game::dvar_flag::DVAR_FLAG_READONLY | Game::dvar_flag::DVAR_FLAG_SAVED); //safeArea_adjusted_horizontal
|
|
|
|
Utils::Hook::Xor<INT>(0x42E423, Game::dvar_flag::DVAR_FLAG_READONLY | Game::dvar_flag::DVAR_FLAG_SAVED); //safeArea_adjusted_vertical
|
2020-10-30 19:08:21 -04:00
|
|
|
Utils::Hook::Xor<BYTE>(0x42E398, Game::dvar_flag::DVAR_FLAG_CHEAT | Game::dvar_flag::DVAR_FLAG_SAVED); //safeArea_horizontal
|
|
|
|
Utils::Hook::Xor<BYTE>(0x42E3C4, Game::dvar_flag::DVAR_FLAG_CHEAT | Game::dvar_flag::DVAR_FLAG_SAVED); //safeArea_vertical
|
|
|
|
|
2017-02-18 05:39:01 -05:00
|
|
|
// Don't allow setting cheat protected dvars via menus
|
|
|
|
Utils::Hook(0x63C897, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
|
|
|
Utils::Hook(0x63CA96, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
|
|
|
Utils::Hook(0x63CDB5, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
|
|
|
Utils::Hook(0x635E47, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
2017-07-09 07:36:13 -04:00
|
|
|
|
|
|
|
// SetDvar
|
|
|
|
Utils::Hook(0x63444C, Dvar::SetFromStringByNameSafeExternal, HOOK_CALL).install()->quick();
|
|
|
|
|
|
|
|
// Slider
|
2017-07-05 17:17:59 -04:00
|
|
|
Utils::Hook(0x636159, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
|
|
|
Utils::Hook(0x636189, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
|
|
|
Utils::Hook(0x6364EA, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
2017-07-09 07:36:13 -04:00
|
|
|
|
|
|
|
Utils::Hook(0x636207, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
2017-07-05 17:17:59 -04:00
|
|
|
Utils::Hook(0x636608, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
|
|
|
Utils::Hook(0x636695, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
2017-02-18 05:39:01 -05:00
|
|
|
|
|
|
|
// Entirely block setting cheat dvars internally without sv_cheats
|
|
|
|
//Utils::Hook(0x4F52EC, Dvar::SetFromStringByNameExternal, HOOK_CALL).install()->quick();
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Dvar::~Dvar()
|
|
|
|
{
|
|
|
|
Dvar::RegistrationSignal.clear();
|
2021-10-03 16:23:26 -04:00
|
|
|
Dvar::ChangedDvars.clear();
|
2017-01-19 16:23:59 -05:00
|
|
|
}
|
|
|
|
}
|