diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index ebb7d99e..ec1f5dea 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -106,7 +106,7 @@ namespace Components Loader::Register(new TextRenderer()); Loader::Register(new Movement()); Loader::Register(new Elevators()); - Loader::Register(new Cheats()); + Loader::Register(new ClientCommand()); Loader::Register(new Client()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 80b6fa6c..ba7eef63 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -134,7 +134,7 @@ namespace Components #include "Modules/TextRenderer.hpp" #include "Modules/Movement.hpp" #include "Modules/Elevators.hpp" -#include "Modules/Cheats.hpp" +#include "Modules/ClientCommand.hpp" #include "Modules/Gamepad.hpp" #include "Modules/Client.hpp" diff --git a/src/Components/Modules/Cheats.cpp b/src/Components/Modules/Cheats.cpp deleted file mode 100644 index 1e9bab62..00000000 --- a/src/Components/Modules/Cheats.cpp +++ /dev/null @@ -1,313 +0,0 @@ -#include "STDInclude.hpp" - -namespace Components -{ - void Cheats::AddCheatCommands() - { - static int toastDurationShort = 1000; - static int toastDurationMedium = 2500; - static int toastDurationLong = 5000; - - Command::Add("noclip", [](Command::Params*) - { - int clientNum = Game::CG_GetClientNum(); - if (!Game::CL_IsCgameInitialized() || clientNum >= 18 || clientNum < 0 || !Game::g_entities[clientNum].client) - { - Logger::Print("You are not hosting a match!\n"); - Toast::Show("cardicon_stop", "Error", "You are not hosting a match!", toastDurationMedium); - return; - } - - if (!Dvar::Var("sv_cheats").get()) - { - Logger::Print("Cheats disabled!\n"); - Toast::Show("cardicon_stop", "Error", "Cheats disabled!", toastDurationMedium); - return; - } - - Game::g_entities[clientNum].client->flags ^= Game::PLAYER_FLAG_NOCLIP; - - Logger::Print("Noclip toggled\n"); - Toast::Show("cardicon_abduction", "Success", "Noclip toggled", toastDurationShort); - }); - - Command::Add("ufo", [](Command::Params*) - { - int clientNum = Game::CG_GetClientNum(); - if (!Game::CL_IsCgameInitialized() || clientNum >= 18 || clientNum < 0 || !Game::g_entities[clientNum].client) - { - Logger::Print("You are not hosting a match!\n"); - Toast::Show("cardicon_stop", "Error", "You are not hosting a match!", toastDurationMedium); - return; - } - - if (!Dvar::Var("sv_cheats").get()) - { - Logger::Print("Cheats disabled!\n"); - Toast::Show("cardicon_stop", "Error", "Cheats disabled!", toastDurationMedium); - return; - } - - Game::g_entities[clientNum].client->flags ^= Game::PLAYER_FLAG_UFO; - - Logger::Print("UFO toggled\n"); - Toast::Show("cardicon_abduction", "Success", "UFO toggled", toastDurationShort); - }); - - Command::Add("god", [](Command::Params*) - { - int clientNum = Game::CG_GetClientNum(); - if (!Game::CL_IsCgameInitialized() || clientNum >= 18 || clientNum < 0) - { - Logger::Print("You are not hosting a match!\n"); - Toast::Show("cardicon_stop", "Error", "You are not hosting a match!", toastDurationMedium); - return; - } - - if (!Dvar::Var("sv_cheats").get()) - { - Logger::Print("Cheats disabled!\n"); - Toast::Show("cardicon_stop", "Error", "Cheats disabled!", toastDurationMedium); - return; - } - - Game::g_entities[clientNum].flags ^= Game::FL_GODMODE; - - Logger::Print("God toggled\n"); - Toast::Show("cardicon_abduction", "Success", "God toggled", toastDurationShort); - }); - - Command::Add("demigod", [](Command::Params*) - { - int clientNum = Game::CG_GetClientNum(); - if (!Game::CL_IsCgameInitialized() || clientNum >= 18 || clientNum < 0) - { - Logger::Print("You are not hosting a match!\n"); - Toast::Show("cardicon_stop", "Error", "You are not hosting a match!", toastDurationMedium); - return; - } - - if (!Dvar::Var("sv_cheats").get()) - { - Logger::Print("Cheats disabled!\n"); - Toast::Show("cardicon_stop", "Error", "Cheats disabled!", toastDurationMedium); - return; - } - - Game::g_entities[clientNum].flags ^= Game::FL_DEMI_GODMODE; - - Logger::Print("Demigod toggled\n"); - Toast::Show("cardicon_abduction", "Success", "Demigod toggled", toastDurationShort); - }); - - Command::Add("notarget", [](Command::Params*) - { - int clientNum = Game::CG_GetClientNum(); - if (!Game::CL_IsCgameInitialized() || clientNum >= 18 || clientNum < 0) - { - Logger::Print("You are not hosting a match!\n"); - Toast::Show("cardicon_stop", "Error", "You are not hosting a match!", toastDurationMedium); - return; - } - - if (!Dvar::Var("sv_cheats").get()) - { - Logger::Print("Cheats disabled!\n"); - Toast::Show("cardicon_stop", "Error", "Cheats disabled!", toastDurationMedium); - return; - } - - Game::g_entities[clientNum].flags ^= Game::FL_NOTARGET; - - Logger::Print("Notarget toggled\n"); - Toast::Show("cardicon_abduction", "Success", "Notarget toggled", toastDurationShort); - }); - - Command::Add("setviewpos", [](Command::Params* params) - { - int clientNum = Game::CG_GetClientNum(); - if (!Game::CL_IsCgameInitialized() || clientNum >= 18 || clientNum < 0 || !Game::g_entities[clientNum].client) - { - Logger::Print("You are not hosting a match!\n"); - Toast::Show("cardicon_stop", "Error", "You are not hosting a match!", toastDurationMedium); - return; - } - - if (!Dvar::Var("sv_cheats").get()) - { - Logger::Print("Cheats disabled!\n"); - Toast::Show("cardicon_stop", "Error", "Cheats disabled!", toastDurationMedium); - return; - } - - if (params->length() != 4 && params->length() != 6) - { - Logger::Print("Invalid coordinate specified!\n"); - Toast::Show("cardicon_stop", "Error", "Invalid coordinate specified!", toastDurationMedium); - return; - } - - float pos[3] = { 0.0f, 0.0f, 0.0f }; - float orientation[3] = { 0.0f, 0.0f, 0.0f }; - - pos[0] = strtof(params->get(1), nullptr); - pos[1] = strtof(params->get(2), nullptr); - pos[2] = strtof(params->get(3), nullptr); - - if (params->length() == 6) - { - orientation[0] = strtof(params->get(4), nullptr); - orientation[1] = strtof(params->get(5), nullptr); - } - - Game::TeleportPlayer(&Game::g_entities[clientNum], pos, orientation); - - // Logging will spam the console and screen if people use cinematics - }); - } - - void Cheats::AddScriptFunctions() - { - Script::AddFunction("Noclip", [](Game::scr_entref_t entref) // gsc: Noclip(); - { - if (entref >= Game::MAX_GENTITIES || Game::g_entities[entref].client == nullptr) - { - Game::Scr_Error(Utils::String::VA("^1NoClip: entity %u is not a client\n", entref)); - return; - } - - if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) - { - if (Game::Scr_GetInt(0)) - { - Game::g_entities[entref].client->flags |= Game::PLAYER_FLAG_NOCLIP; - } - else - { - Game::g_entities[entref].client->flags &= ~Game::PLAYER_FLAG_NOCLIP; - } - } - else - { - Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_NOCLIP; - } - }); - - Script::AddFunction("Ufo", [](Game::scr_entref_t entref) // gsc: Ufo(); - { - if (entref >= Game::MAX_GENTITIES || Game::g_entities[entref].client == nullptr) - { - Game::Scr_Error(Utils::String::VA("^1Ufo: entity %u is not a client\n", entref)); - return; - } - - if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) - { - if (Game::Scr_GetInt(0)) - { - Game::g_entities[entref].client->flags |= Game::PLAYER_FLAG_UFO; - } - else - { - Game::g_entities[entref].client->flags &= ~Game::PLAYER_FLAG_UFO; - } - } - else - { - Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_UFO; - } - }); - - Script::AddFunction("God", [](Game::scr_entref_t entref) // gsc: God(); - { - if (entref >= Game::MAX_GENTITIES) - { - Game::Scr_Error(Utils::String::VA("^1God: entity %u is out of bounds\n", entref)); - return; - } - - if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) - { - if (Game::Scr_GetInt(0)) - { - Game::g_entities[entref].flags |= Game::FL_GODMODE; - } - else - { - Game::g_entities[entref].flags &= ~Game::FL_GODMODE; - } - } - else - { - Game::g_entities[entref].flags ^= Game::FL_GODMODE; - } - }); - - Script::AddFunction("Demigod", [](Game::scr_entref_t entref) // gsc: Demigod(); - { - if (entref >= Game::MAX_GENTITIES) - { - Game::Scr_Error(Utils::String::VA("^1Demigod: entity %u is out of bounds\n", entref)); - return; - } - - if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) - { - if (Game::Scr_GetInt(0)) - { - Game::g_entities[entref].flags |= Game::FL_DEMI_GODMODE; - } - else - { - Game::g_entities[entref].flags &= ~Game::FL_DEMI_GODMODE; - } - } - else - { - Game::g_entities[entref].flags ^= Game::FL_DEMI_GODMODE; - } - }); - - Script::AddFunction("Notarget", [](Game::scr_entref_t entref) // gsc: Notarget(); - { - if (entref >= Game::MAX_GENTITIES) - { - Game::Scr_Error(Utils::String::VA("^1Notarget: entity %u is out of bounds\n", entref)); - return; - } - - if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) - { - if (Game::Scr_GetInt(0)) - { - Game::g_entities[entref].flags |= Game::FL_NOTARGET; - } - else - { - Game::g_entities[entref].flags &= ~Game::FL_NOTARGET; - } - } - else - { - Game::g_entities[entref].flags ^= Game::FL_NOTARGET; - } - }); - } - - Cheats::Cheats() - { - // Disable native cheat commands - Utils::Hook::Nop(0x474846, 5); // Cmd_Noclip_f - Utils::Hook::Nop(0x474859, 5); // Cmd_UFO_f - Utils::Hook::Nop(0x47480A, 5); // Cmd_God_f - Utils::Hook::Nop(0x47481D, 5); // Cmd_DemiGod_f - Utils::Hook::Nop(0x474833, 5); // Cmd_Notarget_f - - Cheats::AddCheatCommands(); - Cheats::AddScriptFunctions(); - } - - Cheats::~Cheats() - { - } -} diff --git a/src/Components/Modules/Cheats.hpp b/src/Components/Modules/Cheats.hpp deleted file mode 100644 index c86762e9..00000000 --- a/src/Components/Modules/Cheats.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -namespace Components -{ - class Cheats : public Component - { - public: - Cheats(); - ~Cheats(); - - private: - static void AddCheatCommands(); - static void AddScriptFunctions(); - }; -} diff --git a/src/Components/Modules/ClientCommand.cpp b/src/Components/Modules/ClientCommand.cpp new file mode 100644 index 00000000..39e14071 --- /dev/null +++ b/src/Components/Modules/ClientCommand.cpp @@ -0,0 +1,291 @@ +#include "STDInclude.hpp" + +namespace Components +{ + std::unordered_map> ClientCommand::FunctionMap; + + unsigned int ClientCommand::GetEntityNum(const Game::gentity_s* ent) + { + unsigned int num; + + num = ent - Game::g_entities; + + return num; + } + + bool ClientCommand::CheatsOk(const Game::gentity_s* ent) + { + const auto entNum = ClientCommand::GetEntityNum(ent); + + if (!Dvar::Var("sv_cheats").get()) + { + Logger::Print("Cheats disabled!\n"); + Game::SV_GameSendServerCommand(entNum, 0, Utils::String::VA("%c \"GAME_CHEATSNOTENABLED\"", 0x65)); + return false; + } + + if (ent->health < 1) + { + Logger::Print("Entity %u must be alive to use this command!\n", entNum); + Game::SV_GameSendServerCommand(entNum, 0, Utils::String::VA("%c \"GAME_MUSTBEALIVECOMMAND\"", 0x65)); + return false; + } + + return true; + } + + bool ClientCommand::CallbackHandler(Game::gentity_s* ent, const char* cmd) + { + const auto command = Utils::String::ToLower(cmd); + + if (ClientCommand::FunctionMap.find(command) != ClientCommand::FunctionMap.end()) + { + ClientCommand::FunctionMap[command](ent); + return true; + } + + return false; + } + + void ClientCommand::Add(const char* name, Utils::Slot callback) + { + const auto command = Utils::String::ToLower(name); + + ClientCommand::FunctionMap[command] = callback; + } + + void ClientCommand::ClientCommandStub(const int clientNum) + { + char cmd[1024]{}; + const auto entity = &Game::g_entities[clientNum]; + + if (entity->client == nullptr) + { + Logger::Print("Client %d is not fully in game yet\n", clientNum); + return; + } + + Game::SV_Cmd_ArgvBuffer(0, cmd, sizeof(cmd)); + + if (!ClientCommand::CallbackHandler(entity, cmd)) + { + // If no callback was found call original game function + Utils::Hook::Call(0x416790)(clientNum); + } + } + + void ClientCommand::AddCheatCommands() + { + ClientCommand::Add("noclip", [](Game::gentity_s* ent) + { + if (!ClientCommand::CheatsOk(ent)) + return; + + ent->client->flags ^= Game::PLAYER_FLAG_NOCLIP; + + const auto entNum = ClientCommand::GetEntityNum(ent); + Logger::Print("Noclip toggled for entity %u\n", entNum); + + Game::SV_GameSendServerCommand(entNum, 0, Utils::String::VA("%c \"%s\"", 0x65, + (ent->client->flags & Game::PLAYER_FLAG_NOCLIP) ? "GAME_NOCLIPON" : "GAME_NOCLIPOFF")); + }); + + ClientCommand::Add("ufo", [](Game::gentity_s* ent) + { + if (!ClientCommand::CheatsOk(ent)) + return; + + ent->client->flags ^= Game::PLAYER_FLAG_UFO; + + const auto entNum = ClientCommand::GetEntityNum(ent); + Logger::Print("UFO toggled for entity %u\n", entNum); + + Game::SV_GameSendServerCommand(entNum, 0, Utils::String::VA("%c \"%s\"", 0x65, + (ent->client->flags & Game::PLAYER_FLAG_UFO) ? "GAME_UFOON" : "GAME_UFOOFF")); + }); + + ClientCommand::Add("god", [](Game::gentity_s* ent) + { + if (!ClientCommand::CheatsOk(ent)) + return; + + ent->flags ^= Game::FL_GODMODE; + + const auto entNum = ClientCommand::GetEntityNum(ent); + Logger::Print("God toggled for entity %u\n", entNum); + + Game::SV_GameSendServerCommand(entNum, 0, Utils::String::VA("%c \"%s\"", 0x65, + (ent->flags & Game::FL_GODMODE) ? "GAME_GODMODE_ON" : "GAME_GODMODE_OFF")); + }); + + ClientCommand::Add("demigod", [](Game::gentity_s* ent) + { + if (!ClientCommand::CheatsOk(ent)) + return; + + ent->flags ^= Game::FL_DEMI_GODMODE; + + const auto entNum = ClientCommand::GetEntityNum(ent); + Logger::Print("Demigod toggled for entity %u\n", entNum); + + Game::SV_GameSendServerCommand(entNum, 0, Utils::String::VA("%c \"%s\"", 0x65, + (ent->flags & Game::FL_DEMI_GODMODE) ? "GAME_DEMI_GODMODE_ON" : "GAME_DEMI_GODMODE_OFF")); + }); + + ClientCommand::Add("notarget", [](Game::gentity_s* ent) + { + if (!ClientCommand::CheatsOk(ent)) + return; + + ent->flags ^= Game::FL_NOTARGET; + + const auto entNum = ClientCommand::GetEntityNum(ent); + Logger::Print("Notarget toggled for entity %u\n", entNum); + + Game::SV_GameSendServerCommand(entNum, 0, Utils::String::VA("%c \"%s\"", 0x65, + (ent->flags & Game::FL_NOTARGET) ? "GAME_NOTARGETON" : "GAME_NOTARGETOFF")); + }); + } + + void ClientCommand::AddScriptFunctions() + { + Script::AddFunction("Noclip", [](Game::scr_entref_t entref) // gsc: Noclip(); + { + if (entref >= Game::MAX_GENTITIES || Game::g_entities[entref].client == nullptr) + { + Game::Scr_Error(Utils::String::VA("^1NoClip: entity %u is not a client\n", entref)); + return; + } + + if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) + { + if (Game::Scr_GetInt(0)) + { + Game::g_entities[entref].client->flags |= Game::PLAYER_FLAG_NOCLIP; + } + else + { + Game::g_entities[entref].client->flags &= ~Game::PLAYER_FLAG_NOCLIP; + } + } + else + { + Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_NOCLIP; + } + }); + + Script::AddFunction("Ufo", [](Game::scr_entref_t entref) // gsc: Ufo(); + { + if (entref >= Game::MAX_GENTITIES || Game::g_entities[entref].client == nullptr) + { + Game::Scr_Error(Utils::String::VA("^1Ufo: entity %u is not a client\n", entref)); + return; + } + + if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) + { + if (Game::Scr_GetInt(0)) + { + Game::g_entities[entref].client->flags |= Game::PLAYER_FLAG_UFO; + } + else + { + Game::g_entities[entref].client->flags &= ~Game::PLAYER_FLAG_UFO; + } + } + else + { + Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_UFO; + } + }); + + Script::AddFunction("God", [](Game::scr_entref_t entref) // gsc: God(); + { + if (entref >= Game::MAX_GENTITIES) + { + Game::Scr_Error(Utils::String::VA("^1God: entity %u is out of bounds\n", entref)); + return; + } + + if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) + { + if (Game::Scr_GetInt(0)) + { + Game::g_entities[entref].flags |= Game::FL_GODMODE; + } + else + { + Game::g_entities[entref].flags &= ~Game::FL_GODMODE; + } + } + else + { + Game::g_entities[entref].flags ^= Game::FL_GODMODE; + } + }); + + Script::AddFunction("Demigod", [](Game::scr_entref_t entref) // gsc: Demigod(); + { + if (entref >= Game::MAX_GENTITIES) + { + Game::Scr_Error(Utils::String::VA("^1Demigod: entity %u is out of bounds\n", entref)); + return; + } + + if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) + { + if (Game::Scr_GetInt(0)) + { + Game::g_entities[entref].flags |= Game::FL_DEMI_GODMODE; + } + else + { + Game::g_entities[entref].flags &= ~Game::FL_DEMI_GODMODE; + } + } + else + { + Game::g_entities[entref].flags ^= Game::FL_DEMI_GODMODE; + } + }); + + Script::AddFunction("Notarget", [](Game::scr_entref_t entref) // gsc: Notarget(); + { + if (entref >= Game::MAX_GENTITIES) + { + Game::Scr_Error(Utils::String::VA("^1Notarget: entity %u is out of bounds\n", entref)); + return; + } + + if (Game::Scr_GetNumParam() == 1u && Game::Scr_GetType(0) == Game::VAR_INTEGER) + { + if (Game::Scr_GetInt(0)) + { + Game::g_entities[entref].flags |= Game::FL_NOTARGET; + } + else + { + Game::g_entities[entref].flags &= ~Game::FL_NOTARGET; + } + } + else + { + Game::g_entities[entref].flags ^= Game::FL_NOTARGET; + } + }); + } + + ClientCommand::ClientCommand() + { + //SV_ExecuteClientCommand + Utils::Hook(0x6259FA, ClientCommand::ClientCommandStub, HOOK_CALL).install()->quick(); + + ClientCommand::AddCheatCommands(); + ClientCommand::AddScriptFunctions(); + } + + ClientCommand::~ClientCommand() + { + ClientCommand::FunctionMap.clear(); + } +} diff --git a/src/Components/Modules/ClientCommand.hpp b/src/Components/Modules/ClientCommand.hpp new file mode 100644 index 00000000..643aa847 --- /dev/null +++ b/src/Components/Modules/ClientCommand.hpp @@ -0,0 +1,24 @@ +#pragma once + +namespace Components +{ + class ClientCommand : public Component + { + public: + typedef void(Callback)(Game::gentity_s* entity); + + ClientCommand(); + ~ClientCommand(); + static void Add(const char* name, Utils::Slot callback); + static unsigned int GetEntityNum(const Game::gentity_s* ent); + static bool CheatsOk(const Game::gentity_s* ent); + + private: + static std::unordered_map> FunctionMap; + + static bool CallbackHandler(Game::gentity_s* ent, const char* cmd); + static void ClientCommandStub(const int clientNum); + static void AddCheatCommands(); + static void AddScriptFunctions(); + }; +} diff --git a/src/Components/Modules/Command.cpp b/src/Components/Modules/Command.cpp index 49aa6745..52a1b3fc 100644 --- a/src/Components/Modules/Command.cpp +++ b/src/Components/Modules/Command.cpp @@ -160,6 +160,52 @@ namespace Components { AssertSize(Game::cmd_function_t, 24); + static int toastDurationShort = 1000; + static int toastDurationMedium = 2500; + static int toastDurationLong = 5000; + + Command::Add("setviewpos", [](Command::Params* params) + { + int clientNum = Game::CG_GetClientNum(); + if (!Game::CL_IsCgameInitialized() || clientNum >= 18 || clientNum < 0 || !Game::g_entities[clientNum].client) + { + Logger::Print("You are not hosting a match!\n"); + Toast::Show("cardicon_stop", "Error", "You are not hosting a match!", toastDurationMedium); + return; + } + + if (!Dvar::Var("sv_cheats").get()) + { + Logger::Print("Cheats disabled!\n"); + Toast::Show("cardicon_stop", "Error", "Cheats disabled!", toastDurationMedium); + return; + } + + if (params->length() != 4 && params->length() != 6) + { + Logger::Print("Invalid coordinate specified!\n"); + Toast::Show("cardicon_stop", "Error", "Invalid coordinate specified!", toastDurationMedium); + return; + } + + float pos[3] = { 0.0f, 0.0f, 0.0f }; + float orientation[3] = { 0.0f, 0.0f, 0.0f }; + + pos[0] = strtof(params->get(1), nullptr); + pos[1] = strtof(params->get(2), nullptr); + pos[2] = strtof(params->get(3), nullptr); + + if (params->length() == 6) + { + orientation[0] = strtof(params->get(4), nullptr); + orientation[1] = strtof(params->get(5), nullptr); + } + + Game::TeleportPlayer(&Game::g_entities[clientNum], pos, orientation); + + // Logging will spam the console and screen if people use cinematics + }); + Command::Add("openLink", [](Command::Params* params) { if (params->length() > 1) diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index d61e41fa..d66a4154 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -314,6 +314,7 @@ namespace Game SV_GameSendServerCommand_t SV_GameSendServerCommand = SV_GameSendServerCommand_t(0x4BC3A0); SV_Cmd_TokenizeString_t SV_Cmd_TokenizeString = SV_Cmd_TokenizeString_t(0x4B5780); SV_Cmd_EndTokenizedString_t SV_Cmd_EndTokenizedString = SV_Cmd_EndTokenizedString_t(0x464750); + SV_Cmd_ArgvBuffer_t SV_Cmd_ArgvBuffer = SV_Cmd_ArgvBuffer_t(0x40BB60); SV_DirectConnect_t SV_DirectConnect = SV_DirectConnect_t(0x460480); SV_SetConfigstring_t SV_SetConfigstring = SV_SetConfigstring_t(0x4982E0); SV_Loaded_t SV_Loaded = SV_Loaded_t(0x4EE3E0); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 2f2ef11b..71d05275 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -750,6 +750,9 @@ namespace Game typedef void(__cdecl * SV_Cmd_EndTokenizedString_t)(); extern SV_Cmd_EndTokenizedString_t SV_Cmd_EndTokenizedString; + typedef void(__cdecl* SV_Cmd_ArgvBuffer_t)(int arg, char* buf, int size); + extern SV_Cmd_ArgvBuffer_t SV_Cmd_ArgvBuffer; + typedef void(__cdecl * SV_SetConfigstring_t)(int index, const char* string); extern SV_SetConfigstring_t SV_SetConfigstring;