Add client dev commands & more

This commit is contained in:
Diavolo 2022-04-12 14:34:51 +02:00
parent 51278faab0
commit f9c40233d1
No known key found for this signature in database
GPG Key ID: FA77F074E98D98A5
19 changed files with 300 additions and 161 deletions

View File

@ -174,7 +174,7 @@ namespace Components
return; return;
} }
if (*Game::svs_numclients <= num) if (*Game::svs_clientCount <= num)
{ {
Logger::Print("Player %d is not on the server\n", num); Logger::Print("Player %d is not on the server\n", num);
return; return;
@ -185,9 +185,9 @@ namespace Components
SteamID guid; SteamID guid;
guid.bits = client->steamID; guid.bits = client->steamID;
Bans::InsertBan({ guid, client->netchan.remoteAddress.ip }); Bans::InsertBan({guid, client->netchan.remoteAddress.ip});
Game::SV_KickClientError(client, reason); Game::SV_GameDropClient(num, reason.data());
} }
void Bans::UnbanClient(SteamID id) void Bans::UnbanClient(SteamID id)

View File

@ -341,15 +341,15 @@ namespace Components
{ {
if (params->get(1) == "all"s) if (params->get(1) == "all"s)
{ {
count = *Game::svs_numclients; count = *Game::svs_clientCount;
} }
else else
{ {
char* endptr; char* end;
const auto* input = params->get(1); const auto* input = params->get(1);
count = std::strtoul(input, &endptr, 10); count = std::strtoul(input, &end, 10);
if (input == endptr) if (input == end)
{ {
Logger::Print("Warning: %s is not a valid input\n" Logger::Print("Warning: %s is not a valid input\n"
"Usage: %s optional <number of bots> or optional <\"all\">\n", "Usage: %s optional <number of bots> or optional <\"all\">\n",
@ -359,7 +359,7 @@ namespace Components
} }
} }
count = std::min(static_cast<unsigned int>(*Game::svs_numclients), count); count = std::min(static_cast<unsigned int>(*Game::svs_clientCount), count);
// Check if ingame and host // Check if ingame and host
if (!Game::SV_Loaded()) if (!Game::SV_Loaded())

View File

@ -2,7 +2,7 @@
namespace Components namespace Components
{ {
std::unordered_map<std::string, Utils::Slot<ClientCommand::Callback>> ClientCommand::FunctionMap; std::unordered_map<std::string, std::function<void(Game::gentity_s*, Command::ServerParams*)>> ClientCommand::HandlersSV;
bool ClientCommand::CheatsOk(const Game::gentity_s* ent) bool ClientCommand::CheatsOk(const Game::gentity_s* ent)
{ {
@ -25,50 +25,38 @@ namespace Components
return true; return true;
} }
bool ClientCommand::CallbackHandler(Game::gentity_s* ent, const char* cmd) void ClientCommand::Add(const char* name, std::function<void(Game::gentity_s*, Command::ServerParams*)> callback)
{
const auto command = Utils::String::ToLower(cmd);
const auto got = ClientCommand::FunctionMap.find(command);
if (got != ClientCommand::FunctionMap.end())
{
got->second(ent);
return true;
}
return false;
}
void ClientCommand::Add(const char* name, Utils::Slot<Callback> callback)
{ {
const auto command = Utils::String::ToLower(name); const auto command = Utils::String::ToLower(name);
ClientCommand::FunctionMap[command] = std::move(callback); ClientCommand::HandlersSV[command] = std::move(callback);
} }
void ClientCommand::ClientCommandStub(const int clientNum) void ClientCommand::ClientCommandStub(const int clientNum)
{ {
char cmd[1024]{}; const auto ent = &Game::g_entities[clientNum];
const auto entity = &Game::g_entities[clientNum];
if (entity->client == nullptr) if (ent->client == nullptr)
{ {
Logger::Print("ClientCommand: client %d is not fully in game yet\n", clientNum); Logger::Print("ClientCommand: client %d is not fully in game yet\n", clientNum);
return; return;
} }
Game::SV_Cmd_ArgvBuffer(0, cmd, sizeof(cmd)); Command::ServerParams params;
const auto command = Utils::String::ToLower(params.get(0));
if (!ClientCommand::CallbackHandler(entity, cmd)) if (const auto got = HandlersSV.find(command); got != HandlersSV.end())
{ {
// If no callback was found call original game function got->second(ent, &params);
Utils::Hook::Call<void(const int)>(0x416790)(clientNum); return;
} }
Utils::Hook::Call<void(const int)>(0x416790)(clientNum);
} }
void ClientCommand::AddCheatCommands() void ClientCommand::AddCheatCommands()
{ {
ClientCommand::Add("noclip", [](Game::gentity_s* ent) ClientCommand::Add("noclip", [](Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{ {
if (!ClientCommand::CheatsOk(ent)) if (!ClientCommand::CheatsOk(ent))
return; return;
@ -82,7 +70,7 @@ namespace Components
(ent->client->flags & Game::PLAYER_FLAG_NOCLIP) ? "GAME_NOCLIPON" : "GAME_NOCLIPOFF")); (ent->client->flags & Game::PLAYER_FLAG_NOCLIP) ? "GAME_NOCLIPON" : "GAME_NOCLIPOFF"));
}); });
ClientCommand::Add("ufo", [](Game::gentity_s* ent) ClientCommand::Add("ufo", [](Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{ {
if (!ClientCommand::CheatsOk(ent)) if (!ClientCommand::CheatsOk(ent))
return; return;
@ -96,7 +84,7 @@ namespace Components
(ent->client->flags & Game::PLAYER_FLAG_UFO) ? "GAME_UFOON" : "GAME_UFOOFF")); (ent->client->flags & Game::PLAYER_FLAG_UFO) ? "GAME_UFOON" : "GAME_UFOOFF"));
}); });
ClientCommand::Add("god", [](Game::gentity_s* ent) ClientCommand::Add("god", [](Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{ {
if (!ClientCommand::CheatsOk(ent)) if (!ClientCommand::CheatsOk(ent))
return; return;
@ -110,7 +98,7 @@ namespace Components
(ent->flags & Game::FL_GODMODE) ? "GAME_GODMODE_ON" : "GAME_GODMODE_OFF")); (ent->flags & Game::FL_GODMODE) ? "GAME_GODMODE_ON" : "GAME_GODMODE_OFF"));
}); });
ClientCommand::Add("demigod", [](Game::gentity_s* ent) ClientCommand::Add("demigod", [](Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{ {
if (!ClientCommand::CheatsOk(ent)) if (!ClientCommand::CheatsOk(ent))
return; return;
@ -124,7 +112,7 @@ namespace Components
(ent->flags & Game::FL_DEMI_GODMODE) ? "GAME_DEMI_GODMODE_ON" : "GAME_DEMI_GODMODE_OFF")); (ent->flags & Game::FL_DEMI_GODMODE) ? "GAME_DEMI_GODMODE_ON" : "GAME_DEMI_GODMODE_OFF"));
}); });
ClientCommand::Add("notarget", [](Game::gentity_s* ent) ClientCommand::Add("notarget", [](Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{ {
if (!ClientCommand::CheatsOk(ent)) if (!ClientCommand::CheatsOk(ent))
return; return;
@ -138,17 +126,16 @@ namespace Components
(ent->flags & Game::FL_NOTARGET) ? "GAME_NOTARGETON" : "GAME_NOTARGETOFF")); (ent->flags & Game::FL_NOTARGET) ? "GAME_NOTARGETON" : "GAME_NOTARGETOFF"));
}); });
ClientCommand::Add("setviewpos", [](Game::gentity_s* ent) ClientCommand::Add("setviewpos", [](Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{ {
assert(ent != nullptr); assert(ent != nullptr);
if (!ClientCommand::CheatsOk(ent)) if (!ClientCommand::CheatsOk(ent))
return; return;
Command::ServerParams params = {};
Game::vec3_t origin, angles{0.f, 0.f, 0.f}; Game::vec3_t origin, angles{0.f, 0.f, 0.f};
if (params.size() < 4 || params.size() > 6) if (params->size() < 4 || params->size() > 6)
{ {
Game::SV_GameSendServerCommand(ent->s.number, 0, Game::SV_GameSendServerCommand(ent->s.number, 0,
Utils::String::VA("%c \"GAME_USAGE\x15: setviewpos x y z [yaw] [pitch]\n\"", 0x65)); Utils::String::VA("%c \"GAME_USAGE\x15: setviewpos x y z [yaw] [pitch]\n\"", 0x65));
@ -157,23 +144,109 @@ namespace Components
for (auto i = 0; i < 3; i++) for (auto i = 0; i < 3; i++)
{ {
origin[i] = std::strtof(params.get(i + 1), nullptr); origin[i] = std::strtof(params->get(i + 1), nullptr);
} }
if (params.size() >= 5) if (params->size() >= 5)
{ {
angles[1] = std::strtof(params.get(4), nullptr); // Yaw angles[1] = std::strtof(params->get(4), nullptr); // Yaw
} }
if (params.size() == 6) if (params->size() == 6)
{ {
angles[0] = std::strtof(params.get(5), nullptr); // Pitch angles[0] = std::strtof(params->get(5), nullptr); // Pitch
} }
Game::TeleportPlayer(ent, origin, angles); Game::TeleportPlayer(ent, origin, angles);
}); });
} }
void ClientCommand::AddDevelopmentCommands()
{
ClientCommand::Add("dropallbots", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{
Game::SV_DropAllBots();
});
ClientCommand::Add("entitylist", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{
Game::Svcmd_EntityList_f();
});
ClientCommand::Add("printentities", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{
Game::G_PrintEntities();
});
ClientCommand::Add("entitycount", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{
Logger::Print("Entity count = %i\n", *Game::level_num_entities);
});
// Also known as: "vis"
ClientCommand::Add("visionsetnaked", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{
if (params->size() < 2)
{
Logger::Print("USAGE: visionSetNaked <name> <duration>\n");
return;
}
auto duration = 1000;
if (params->size() > 2)
{
const auto input = std::strtof(params->get(2), nullptr);
duration = static_cast<int>(std::floorf(input * 1000.0f + 0.5f));
}
assert(ent->client != nullptr);
constexpr auto visMode = Game::visionSetMode_t::VISIONSET_NORMAL;
const auto* name = params->get(1);
ent->client->visionDuration[visMode] = duration;
strncpy_s(ent->client->visionName[visMode],
sizeof(Game::gclient_t::visionName[0]) / sizeof(char), name, _TRUNCATE);
Game::SV_GameSendServerCommand(ent->s.number, 1,
Utils::String::VA("%c \"%s\" %i", Game::MY_CMDS[visMode], name, duration));
});
ClientCommand::Add("visionsetnight", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{
if (params->size() < 2)
{
Logger::Print("USAGE: visionSetNight <name> <duration>\n");
return;
}
auto duration = 1000;
if (params->size() > 2)
{
const auto input = std::strtof(params->get(2), nullptr);
duration = static_cast<int>(std::floorf(input * 1000.0f + 0.5f));
}
assert(ent->client != nullptr);
constexpr auto visMode = Game::visionSetMode_t::VISIONSET_NIGHT;
const auto* name = params->get(1);
ent->client->visionDuration[visMode] = duration;
strncpy_s(ent->client->visionName[visMode],
sizeof(Game::gclient_t::visionName[0]) / sizeof(char), name, _TRUNCATE);
Game::SV_GameSendServerCommand(ent->s.number, 1,
Utils::String::VA("%c \"%s\" %i", Game::MY_CMDS[visMode], name, duration));
});
ClientCommand::Add("g_testCmd", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
{
assert(ent != nullptr);
ent->client->ps.stunTime = 1000 + *Game::level_time; // 1000 is the default test stun time
});
}
void ClientCommand::AddScriptFunctions() void ClientCommand::AddScriptFunctions()
{ {
Script::AddMethod("Noclip", [](Game::scr_entref_t entref) // gsc: Noclip(<optional int toggle>); Script::AddMethod("Noclip", [](Game::scr_entref_t entref) // gsc: Noclip(<optional int toggle>);
@ -280,6 +353,11 @@ namespace Components
ent->flags ^= Game::FL_NOTARGET; ent->flags ^= Game::FL_NOTARGET;
} }
}); });
Script::AddFunction("DropAllBots", []() // gsc: DropAllBots();
{
Game::SV_DropAllBots();
});
} }
ClientCommand::ClientCommand() ClientCommand::ClientCommand()
@ -289,5 +367,8 @@ namespace Components
ClientCommand::AddCheatCommands(); ClientCommand::AddCheatCommands();
ClientCommand::AddScriptFunctions(); ClientCommand::AddScriptFunctions();
#ifdef _DEBUG
ClientCommand::AddDevelopmentCommands();
#endif
} }
} }

View File

@ -5,19 +5,17 @@ namespace Components
class ClientCommand : public Component class ClientCommand : public Component
{ {
public: public:
typedef void(Callback)(Game::gentity_s* entity);
ClientCommand(); ClientCommand();
static void Add(const char* name, Utils::Slot<Callback> callback); static void Add(const char* name, std::function<void(Game::gentity_s*, Command::ServerParams*)> callback);
static bool CheatsOk(const Game::gentity_s* ent); static bool CheatsOk(const Game::gentity_s* ent);
private: private:
static std::unordered_map<std::string, Utils::Slot<Callback>> FunctionMap; static std::unordered_map<std::string, std::function<void(Game::gentity_s*, Command::ServerParams*)>> HandlersSV;
static bool CallbackHandler(Game::gentity_s* ent, const char* cmd);
static void ClientCommandStub(const int clientNum); static void ClientCommandStub(const int clientNum);
static void AddCheatCommands(); static void AddCheatCommands();
static void AddDevelopmentCommands();
static void AddScriptFunctions(); static void AddScriptFunctions();
}; };
} }

View File

@ -2,8 +2,8 @@
namespace Components namespace Components
{ {
std::unordered_map<std::string, Utils::Slot<Command::Callback>> Command::FunctionMap; std::unordered_map<std::string, std::function<void(Command::Params*)>> Command::FunctionMap;
std::unordered_map<std::string, Utils::Slot<Command::Callback>> Command::FunctionMapSV; std::unordered_map<std::string, std::function<void(Command::Params*)>> Command::FunctionMapSV;
std::string Command::Params::join(const int index) std::string Command::Params::join(const int index)
{ {
@ -60,7 +60,7 @@ namespace Components
return Game::sv_cmd_args->argv[this->nesting_][index]; return Game::sv_cmd_args->argv[this->nesting_][index];
} }
void Command::Add(const char* name, Utils::Slot<Command::Callback> callback) void Command::Add(const char* name, std::function<void(Command::Params*)> callback)
{ {
const auto command = Utils::String::ToLower(name); const auto command = Utils::String::ToLower(name);
@ -69,10 +69,10 @@ namespace Components
Command::AddRaw(name, Command::MainCallback); Command::AddRaw(name, Command::MainCallback);
} }
Command::FunctionMap[command] = std::move(callback); Command::FunctionMap.insert_or_assign(command, std::move(callback));
} }
void Command::AddSV(const char* name, Utils::Slot<Command::Callback> callback) void Command::AddSV(const char* name, std::function<void(Command::Params*)> callback)
{ {
if (Loader::IsPregame()) if (Loader::IsPregame())
{ {
@ -95,7 +95,7 @@ namespace Components
Command::AddRaw(name, Game::Cbuf_AddServerText); Command::AddRaw(name, Game::Cbuf_AddServerText);
} }
FunctionMapSV[command] = std::move(callback); FunctionMapSV.insert_or_assign(command, std::move(callback));
} }
void Command::AddRaw(const char* name, void(*callback)(), bool key) void Command::AddRaw(const char* name, void(*callback)(), bool key)
@ -127,11 +127,11 @@ namespace Components
Game::cmd_function_t* Command::Find(const std::string& command) Game::cmd_function_t* Command::Find(const std::string& command)
{ {
Game::cmd_function_t* cmdFunction = *Game::cmd_functions; auto* cmdFunction = *Game::cmd_functions;
while (cmdFunction) while (cmdFunction != nullptr)
{ {
if (cmdFunction->name && cmdFunction->name == command) if (cmdFunction->name != nullptr && cmdFunction->name == command)
{ {
return cmdFunction; return cmdFunction;
} }
@ -149,12 +149,10 @@ namespace Components
void Command::MainCallback() void Command::MainCallback()
{ {
Command::ClientParams params; ClientParams params;
const auto command = Utils::String::ToLower(params[0]); const auto command = Utils::String::ToLower(params[0]);
const auto got = Command::FunctionMap.find(command);
if (got != Command::FunctionMap.end()) if (const auto got = FunctionMap.find(command); got != FunctionMap.end())
{ {
got->second(&params); got->second(&params);
} }
@ -162,12 +160,10 @@ namespace Components
void Command::MainCallbackSV() void Command::MainCallbackSV()
{ {
Command::ServerParams params; ServerParams params;
const auto command = Utils::String::ToLower(params[0]); const auto command = Utils::String::ToLower(params[0]);
const auto got = Command::FunctionMapSV.find(command);
if (got != Command::FunctionMapSV.end()) if (const auto got = FunctionMapSV.find(command); got != FunctionMapSV.end())
{ {
got->second(&params); got->second(&params);
} }

View File

@ -8,7 +8,8 @@ namespace Components
class Params class Params
{ {
public: public:
Params() {}; Params() = default;
virtual ~Params() = default;
virtual int size() = 0; virtual int size() = 0;
virtual const char* get(int index) = 0; virtual const char* get(int index) = 0;
@ -20,7 +21,7 @@ namespace Components
} }
}; };
class ClientParams : public Params class ClientParams final : public Params
{ {
public: public:
ClientParams(); ClientParams();
@ -32,7 +33,7 @@ namespace Components
int nesting_; int nesting_;
}; };
class ServerParams : public Params class ServerParams final : public Params
{ {
public: public:
ServerParams(); ServerParams();
@ -44,14 +45,12 @@ namespace Components
int nesting_; int nesting_;
}; };
typedef void(Callback)(Command::Params* params);
Command(); Command();
static Game::cmd_function_t* Allocate(); static Game::cmd_function_t* Allocate();
static void Add(const char* name, Utils::Slot<Callback> callback); static void Add(const char* name, std::function<void(Command::Params*)> callback);
static void AddSV(const char* name, Utils::Slot<Callback> callback); static void AddSV(const char* name, std::function<void(Command::Params*)> callback);
static void AddRaw(const char* name, void(*callback)(), bool key = false); static void AddRaw(const char* name, void(*callback)(), bool key = false);
static void AddRawSV(const char* name, void(*callback)()); static void AddRawSV(const char* name, void(*callback)());
static void Execute(std::string command, bool sync = true); static void Execute(std::string command, bool sync = true);
@ -59,8 +58,8 @@ namespace Components
static Game::cmd_function_t* Find(const std::string& command); static Game::cmd_function_t* Find(const std::string& command);
private: private:
static std::unordered_map<std::string, Utils::Slot<Callback>> FunctionMap; static std::unordered_map<std::string, std::function<void(Command::Params*)>> FunctionMap;
static std::unordered_map<std::string, Utils::Slot<Callback>> FunctionMapSV; static std::unordered_map<std::string, std::function<void(Command::Params*)>> FunctionMapSV;
static void MainCallback(); static void MainCallback();
static void MainCallbackSV(); static void MainCallbackSV();

View File

@ -51,8 +51,8 @@ namespace Components
{ {
SetConsoleTitleA(hostname.data()); SetConsoleTitleA(hostname.data());
int clientCount = 0; auto clientCount = 0;
int maxclientCount = *Game::svs_numclients; auto maxclientCount = *Game::svs_clientCount;
if (maxclientCount) if (maxclientCount)
{ {

View File

@ -381,7 +381,7 @@ namespace Components
{ {
Network::Address address(nc->sa.sa); Network::Address address(nc->sa.sa);
for (int i = 0; i < *Game::svs_numclients; ++i) for (int i = 0; i < *Game::svs_clientCount; ++i)
{ {
Game::client_t* client = &Game::svs_clients[i]; Game::client_t* client = &Game::svs_clients[i];

View File

@ -307,7 +307,7 @@ namespace Components
{ {
int botCount = 0; int botCount = 0;
int clientCount = 0; int clientCount = 0;
int maxclientCount = *Game::svs_numclients; int maxclientCount = *Game::svs_clientCount;
if (maxclientCount) if (maxclientCount)
{ {

View File

@ -18,16 +18,16 @@ namespace Components
void Script::FunctionError() void Script::FunctionError()
{ {
std::string funcName = Game::SL_ConvertToString(Script::FunctionName); const auto* funcName = Game::SL_ConvertToString(Script::FunctionName);
Game::Scr_ShutdownAllocNode(); Game::Scr_ShutdownAllocNode();
Logger::Print(23, "\n"); Logger::Print(23, "\n");
Logger::Print(23, "******* script compile error *******\n"); Logger::Print(23, "******* script compile error *******\n");
Logger::Print(23, "Error: unknown function %s in %s\n", funcName.data(), Script::ScriptName.data()); Logger::Print(23, "Error: unknown function %s in %s\n", funcName, Script::ScriptName.data());
Logger::Print(23, "************************************\n"); Logger::Print(23, "************************************\n");
Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\nunknown function %s\n%s\n\n", funcName.data(), Script::ScriptName.data()); Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\nunknown function %s\n%s\n\n", funcName, Script::ScriptName.data());
} }
__declspec(naked) void Script::StoreFunctionNameStub() __declspec(naked) void Script::StoreFunctionNameStub()
@ -270,27 +270,27 @@ namespace Components
Game::GScr_LoadGameTypeScript(); Game::GScr_LoadGameTypeScript();
} }
void Script::AddFunction(const char* name, Game::xfunction_t func, int type) void Script::AddFunction(const char* name, Game::BuiltinFunction func, int type)
{ {
Game::BuiltinFunctionDef toAdd; Game::BuiltinFunctionDef toAdd;
toAdd.actionString = name; toAdd.actionString = name;
toAdd.actionFunc = func; toAdd.actionFunc = func;
toAdd.type = type; toAdd.type = type;
CustomScrFunctions.insert_or_assign(Utils::String::ToLower(name), std::move(toAdd)); CustomScrFunctions.insert_or_assign(Utils::String::ToLower(name), toAdd);
} }
void Script::AddMethod(const char* name, Game::xmethod_t func, int type) void Script::AddMethod(const char* name, Game::BuiltinMethod func, int type)
{ {
Game::BuiltinMethodDef toAdd; Game::BuiltinMethodDef toAdd;
toAdd.actionString = name; toAdd.actionString = name;
toAdd.actionFunc = func; toAdd.actionFunc = func;
toAdd.type = type; toAdd.type = type;
CustomScrMethods.insert_or_assign(Utils::String::ToLower(name), std::move(toAdd)); CustomScrMethods.insert_or_assign(Utils::String::ToLower(name), toAdd);
} }
Game::xfunction_t Script::BuiltIn_GetFunctionStub(const char** pName, int* type) Game::BuiltinFunction Script::BuiltIn_GetFunctionStub(const char** pName, int* type)
{ {
if (pName != nullptr) if (pName != nullptr)
{ {
@ -311,10 +311,10 @@ namespace Components
} }
} }
return Utils::Hook::Call<Game::xfunction_t(const char**, int*)>(0x5FA2B0)(pName, type); // BuiltIn_GetFunction return Utils::Hook::Call<Game::BuiltinFunction(const char**, int*)>(0x5FA2B0)(pName, type); // BuiltIn_GetFunction
} }
Game::xmethod_t Script::BuiltIn_GetMethod(const char** pName, int* type) Game::BuiltinMethod Script::BuiltIn_GetMethod(const char** pName, int* type)
{ {
if (pName != nullptr) if (pName != nullptr)
{ {
@ -335,7 +335,7 @@ namespace Components
} }
} }
return Utils::Hook::Call<Game::xmethod_t(const char**, int*)>(0x5FA360)(pName, type); // Player_GetMethod return Utils::Hook::Call<Game::BuiltinMethod(const char**, int*)>(0x5FA360)(pName, type); // Player_GetMethod
} }
void Script::StoreScriptBaseProgramNum() void Script::StoreScriptBaseProgramNum()
@ -538,7 +538,7 @@ namespace Components
return nullptr; return nullptr;
} }
if (ent->s.number >= *Game::svs_numclients) if (ent->s.number >= *Game::svs_clientCount)
{ {
Game::Scr_ObjectError(Utils::String::VA("Entity %i is out of bounds", ent->s.number)); Game::Scr_ObjectError(Utils::String::VA("Entity %i is out of bounds", ent->s.number));
return nullptr; return nullptr;

View File

@ -11,8 +11,8 @@ namespace Components
static int LoadScriptAndLabel(const std::string& script, const std::string& label); static int LoadScriptAndLabel(const std::string& script, const std::string& label);
static void AddFunction(const char* name, Game::xfunction_t func, int type = 0); static void AddFunction(const char* name, Game::BuiltinFunction func, int type = 0);
static void AddMethod(const char* name, Game::xmethod_t func, int type = 0); static void AddMethod(const char* name, Game::BuiltinMethod func, int type = 0);
static void OnVMShutdown(Utils::Slot<Scheduler::Callback> callback); static void OnVMShutdown(Utils::Slot<Scheduler::Callback> callback);
@ -49,8 +49,8 @@ namespace Components
static void LoadGameType(); static void LoadGameType();
static void LoadGameTypeScript(); static void LoadGameTypeScript();
static Game::xfunction_t BuiltIn_GetFunctionStub(const char** pName, int* type); static Game::BuiltinFunction BuiltIn_GetFunctionStub(const char** pName, int* type);
static Game::xmethod_t BuiltIn_GetMethod(const char** pName, int* type); static Game::BuiltinMethod BuiltIn_GetMethod(const char** pName, int* type);
static void ScrShutdownSystemStub(unsigned char sys); static void ScrShutdownSystemStub(unsigned char sys);
static void StoreScriptBaseProgramNumStub(); static void StoreScriptBaseProgramNumStub();

View File

@ -2,24 +2,24 @@
namespace Components namespace Components
{ {
std::unordered_map<std::int32_t, Utils::Slot<bool(Command::Params*)>> ServerCommands::Commands; std::unordered_map<std::int32_t, std::function<bool(Command::Params*)>> ServerCommands::Commands;
void ServerCommands::OnCommand(std::int32_t cmd, Utils::Slot<bool(Command::Params*)> cb) void ServerCommands::OnCommand(std::int32_t cmd, std::function<bool(Command::Params*)> callback)
{ {
ServerCommands::Commands[cmd] = cb; ServerCommands::Commands.insert_or_assign(cmd, std::move(callback));
} }
bool ServerCommands::OnServerCommand() bool ServerCommands::OnServerCommand()
{ {
Command::ClientParams params; Command::ClientParams params;
for (const auto& serverCommandCB : ServerCommands::Commands) for (const auto& [id, callback] : ServerCommands::Commands)
{ {
if (params.size() >= 1) if (params.size() >= 1)
{ {
if (params.get(0)[0] == serverCommandCB.first) if (params.get(0)[0] == id) // Compare ID of server command
{ {
return serverCommandCB.second(&params); return callback(&params);
} }
} }
} }
@ -27,7 +27,7 @@ namespace Components
return false; return false;
} }
__declspec(naked) void ServerCommands::OnServerCommandStub() __declspec(naked) void ServerCommands::CG_DeployServerCommand_Stub()
{ {
__asm __asm
{ {
@ -44,7 +44,7 @@ namespace Components
test eax, eax test eax, eax
jle error jle error
mov eax, DWORD PTR[edx * 4 + 1AAC634h] mov eax, dword ptr [edx * 4 + 1AAC634h]
mov eax, [eax] mov eax, [eax]
push 5944B3h push 5944B3h
@ -63,6 +63,6 @@ namespace Components
ServerCommands::ServerCommands() ServerCommands::ServerCommands()
{ {
// Server command receive hook // Server command receive hook
Utils::Hook(0x59449F, ServerCommands::OnServerCommandStub).install()->quick(); Utils::Hook(0x59449F, ServerCommands::CG_DeployServerCommand_Stub).install()->quick();
} }
} }

View File

@ -7,12 +7,12 @@ namespace Components
public: public:
ServerCommands(); ServerCommands();
static void OnCommand(std::int32_t cmd, Utils::Slot<bool(Command::Params*)> cb); static void OnCommand(std::int32_t cmd, std::function<bool(Command::Params*)> callback);
private: private:
static std::unordered_map<std::int32_t, Utils::Slot<bool(Command::Params*)>> Commands; static std::unordered_map<std::int32_t, std::function<bool(Command::Params*)>> Commands;
static bool OnServerCommand(); static bool OnServerCommand();
static void OnServerCommandStub(); static void CG_DeployServerCommand_Stub();
}; };
} }

View File

@ -125,7 +125,7 @@ namespace Components
Utils::InfoString ServerInfo::GetInfo() Utils::InfoString ServerInfo::GetInfo()
{ {
int maxclientCount = *Game::svs_numclients; int maxclientCount = *Game::svs_clientCount;
if (!maxclientCount) if (!maxclientCount)
{ {

View File

@ -68,7 +68,7 @@ namespace Components
SlowMotion::Delay = delay; SlowMotion::Delay = delay;
// set snapshot num to 1 behind (T6 does this, why shouldn't we?) // set snapshot num to 1 behind (T6 does this, why shouldn't we?)
for (int i = 0; i < *Game::svs_numclients; ++i) for (int i = 0; i < *Game::svs_clientCount; ++i)
{ {
Game::svs_clients[i].snapNum = *reinterpret_cast<DWORD*>(0x31D9384) - 1; Game::svs_clients[i].snapNum = *reinterpret_cast<DWORD*>(0x31D9384) - 1;
} }

View File

@ -41,7 +41,17 @@ namespace Components
if (params.size() <= 1) if (params.size() <= 1)
return 0; return 0;
int index = atoi(params[1]); char* end;
const auto* input = params.get(1);
auto index = std::strtol(input, &end, 10);
if (input == end)
{
Logger::Print("Warning: %s is not a valid input\n"
"Usage: %s <weapon index>\n",
input, params.get(0));
return 0;
}
if (index >= 4139) if (index >= 4139)
{ {
@ -56,7 +66,7 @@ namespace Components
return 0; return 0;
} }
Utils::Hook::Call<void(int, int)>(0x4BD520)(0, index); Game::CG_SetupWeaponDef(0, index);
return 1; return 1;
} }

View File

@ -5,19 +5,19 @@ namespace Game
std::vector<std::string> Sys_ListFilesWrapper(const std::string& directory, const std::string& extension) std::vector<std::string> Sys_ListFilesWrapper(const std::string& directory, const std::string& extension)
{ {
auto fileCount = 0; auto fileCount = 0;
auto files = Game::Sys_ListFiles(directory.data(), extension.data(), 0, &fileCount, 0); auto** const files = Sys_ListFiles(directory.data(), extension.data(), nullptr, &fileCount, 0);
std::vector<std::string> result; std::vector<std::string> result;
for (auto i = 0; i < fileCount; i++) for (auto i = 0; i < fileCount; i++)
{ {
if (files[i]) if (files[i] != nullptr)
{ {
result.push_back(files[i]); result.emplace_back(files[i]);
} }
} }
Game::FS_FreeFileList(files); FS_FreeFileList(files);
return result; return result;
} }
@ -31,6 +31,7 @@ namespace Game
BG_GetWeaponName_t BG_GetWeaponName = BG_GetWeaponName_t(0x4E6EC0); BG_GetWeaponName_t BG_GetWeaponName = BG_GetWeaponName_t(0x4E6EC0);
BG_LoadWeaponDef_LoadObj_t BG_LoadWeaponDef_LoadObj = BG_LoadWeaponDef_LoadObj_t(0x57B5F0); BG_LoadWeaponDef_LoadObj_t BG_LoadWeaponDef_LoadObj = BG_LoadWeaponDef_LoadObj_t(0x57B5F0);
BG_GetWeaponDef_t BG_GetWeaponDef = BG_GetWeaponDef_t(0x440EB0); BG_GetWeaponDef_t BG_GetWeaponDef = BG_GetWeaponDef_t(0x440EB0);
BG_GetEntityTypeName_t BG_GetEntityTypeName = BG_GetEntityTypeName_t(0x43A0E0);
Cbuf_AddServerText_t Cbuf_AddServerText = Cbuf_AddServerText_t(0x4BB9B0); Cbuf_AddServerText_t Cbuf_AddServerText = Cbuf_AddServerText_t(0x4BB9B0);
Cbuf_AddText_t Cbuf_AddText = Cbuf_AddText_t(0x404B20); Cbuf_AddText_t Cbuf_AddText = Cbuf_AddText_t(0x404B20);
@ -44,6 +45,8 @@ namespace Game
CG_ScoresUp_f_t CG_ScoresUp_f = CG_ScoresUp_f_t(0x5802C0); CG_ScoresUp_f_t CG_ScoresUp_f = CG_ScoresUp_f_t(0x5802C0);
CG_ScrollScoreboardUp_t CG_ScrollScoreboardUp = CG_ScrollScoreboardUp_t(0x47A5C0); CG_ScrollScoreboardUp_t CG_ScrollScoreboardUp = CG_ScrollScoreboardUp_t(0x47A5C0);
CG_ScrollScoreboardDown_t CG_ScrollScoreboardDown = CG_ScrollScoreboardDown_t(0x493B50); CG_ScrollScoreboardDown_t CG_ScrollScoreboardDown = CG_ScrollScoreboardDown_t(0x493B50);
CG_GetTeamName_t CG_GetTeamName = CG_GetTeamName_t(0x4B6210);
CG_SetupWeaponDef_t CG_SetupWeaponDef = CG_SetupWeaponDef_t(0x4BD520);
CL_GetClientName_t CL_GetClientName = CL_GetClientName_t(0x4563D0); CL_GetClientName_t CL_GetClientName = CL_GetClientName_t(0x4563D0);
CL_IsCgameInitialized_t CL_IsCgameInitialized = CL_IsCgameInitialized_t(0x43EB20); CL_IsCgameInitialized_t CL_IsCgameInitialized = CL_IsCgameInitialized_t(0x43EB20);
@ -152,6 +155,10 @@ namespace Game
G_GetWeaponIndexForName_t G_GetWeaponIndexForName = G_GetWeaponIndexForName_t(0x49E540); G_GetWeaponIndexForName_t G_GetWeaponIndexForName = G_GetWeaponIndexForName_t(0x49E540);
G_SpawnEntitiesFromString_t G_SpawnEntitiesFromString = G_SpawnEntitiesFromString_t(0x4D8840); G_SpawnEntitiesFromString_t G_SpawnEntitiesFromString = G_SpawnEntitiesFromString_t(0x4D8840);
G_PrintEntities_t G_PrintEntities = G_PrintEntities_t(0x4E6A50);
G_GetEntityTypeName_t G_GetEntityTypeName = G_GetEntityTypeName_t(0x4EB810);
Svcmd_EntityList_f_t Svcmd_EntityList_f = Svcmd_EntityList_f_t(0x4B6A70);
GScr_LoadGameTypeScript_t GScr_LoadGameTypeScript = GScr_LoadGameTypeScript_t(0x4ED9A0); GScr_LoadGameTypeScript_t GScr_LoadGameTypeScript = GScr_LoadGameTypeScript_t(0x4ED9A0);
@ -339,6 +346,7 @@ namespace Game
SV_SetConfigstring_t SV_SetConfigstring = SV_SetConfigstring_t(0x4982E0); SV_SetConfigstring_t SV_SetConfigstring = SV_SetConfigstring_t(0x4982E0);
SV_Loaded_t SV_Loaded = SV_Loaded_t(0x4EE3E0); SV_Loaded_t SV_Loaded = SV_Loaded_t(0x4EE3E0);
SV_ClientThink_t SV_ClientThink = SV_ClientThink_t(0x44ADD0); SV_ClientThink_t SV_ClientThink = SV_ClientThink_t(0x44ADD0);
SV_DropClient_t SV_DropClient = SV_DropClient_t(0x4D1600);
SV_GetPlayerByName_t SV_GetPlayerByName = SV_GetPlayerByName_t(0x6242B0); SV_GetPlayerByName_t SV_GetPlayerByName = SV_GetPlayerByName_t(0x6242B0);
SV_GetPlayerByNum_t SV_GetPlayerByNum = SV_GetPlayerByNum_t(0x624390); SV_GetPlayerByNum_t SV_GetPlayerByNum = SV_GetPlayerByNum_t(0x624390);
@ -421,7 +429,7 @@ namespace Game
float* cgameFOVSensitivityScale = reinterpret_cast<float*>(0xB2F884); float* cgameFOVSensitivityScale = reinterpret_cast<float*>(0xB2F884);
int* svs_time = reinterpret_cast<int*>(0x31D9384); int* svs_time = reinterpret_cast<int*>(0x31D9384);
int* svs_numclients = reinterpret_cast<int*>(0x31D938C); int* svs_clientCount = reinterpret_cast<int*>(0x31D938C);
client_t* svs_clients = reinterpret_cast<client_t*>(0x31D9390); client_t* svs_clients = reinterpret_cast<client_t*>(0x31D9390);
UiContext *uiContext = reinterpret_cast<UiContext *>(0x62E2858); UiContext *uiContext = reinterpret_cast<UiContext *>(0x62E2858);
@ -452,6 +460,8 @@ namespace Game
gentity_t* g_entities = reinterpret_cast<gentity_t*>(0x18835D8); gentity_t* g_entities = reinterpret_cast<gentity_t*>(0x18835D8);
int* level_num_entities = reinterpret_cast<int*>(0x1A831B0);
int* level_time = reinterpret_cast<int*>(0x1A83554);
int* level_scriptPrintChannel = reinterpret_cast<int*>(0x1A860FC); int* level_scriptPrintChannel = reinterpret_cast<int*>(0x1A860FC);
netadr_t* connectedHost = reinterpret_cast<netadr_t*>(0xA1E888); netadr_t* connectedHost = reinterpret_cast<netadr_t*>(0xA1E888);
@ -520,6 +530,10 @@ namespace Game
GraphFloat* aaInputGraph = reinterpret_cast<GraphFloat*>(0x7A2FC0); GraphFloat* aaInputGraph = reinterpret_cast<GraphFloat*>(0x7A2FC0);
const char* MY_CMDS = reinterpret_cast<const char*>(0x73C9C4); // Count 5
XModel** cached_models = reinterpret_cast<XModel**>(0x1AA20C8);
FastCriticalSection* db_hashCritSect = reinterpret_cast<FastCriticalSection*>(0x16B8A54); FastCriticalSection* db_hashCritSect = reinterpret_cast<FastCriticalSection*>(0x16B8A54);
vec3_t* CorrectSolidDeltas = reinterpret_cast<vec3_t*>(0x739BB8); // Count 26 vec3_t* CorrectSolidDeltas = reinterpret_cast<vec3_t*>(0x739BB8); // Count 26
@ -536,6 +550,13 @@ namespace Game
InterlockedDecrement(&critSect->readCount); InterlockedDecrement(&critSect->readCount);
} }
XModel* G_GetModel(const int index)
{
assert(index > 0);
assert(index < MAX_MODELS);
return cached_models[index];
}
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize) XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize)
{ {
int elSize = DB_GetXAssetSizeHandlers[type](); int elSize = DB_GetXAssetSizeHandlers[type]();
@ -722,14 +743,27 @@ namespace Game
return hash; return hash;
} }
void SV_KickClientError(client_t* client, const std::string& reason) void SV_GameDropClient(int clientNum, const char* reason)
{ {
if (client->state < 5) const auto maxClients = Dvar_FindVar("sv_maxclients")->current.integer;
{ assert(maxClients >= 1 && maxClients <= 18);
Components::Network::SendCommand(client->netchan.remoteAddress, "error", reason);
}
SV_KickClient(client, reason.data()); if (clientNum >= 0 && clientNum < maxClients)
{
SV_DropClient(&svs_clients[clientNum], reason, true);
}
}
void SV_DropAllBots()
{
for (auto i = 0; i < *svs_clientCount; ++i)
{
if (svs_clients[i].state != clientstate_t::CS_FREE
&& svs_clients[i].netchan.remoteAddress.type == netadrtype_t::NA_BOT)
{
SV_GameDropClient(i, "GAME_GET_TO_COVER");
}
}
} }
void IncInParam() void IncInParam()
@ -1199,28 +1233,6 @@ namespace Game
} }
} }
__declspec(naked) void SV_KickClient(client_t* /*client*/, const char* /*reason*/)
{
__asm
{
pushad
mov edi, 0
mov esi, [esp + 24h]
push [esp + 28h]
push 0
push 0
mov eax, 6249A0h
call eax
add esp, 0Ch
popad
retn
}
}
__declspec(naked) void Scr_NotifyId(unsigned int /*id*/, unsigned __int16 /*stringValue*/, unsigned int /*paramcount*/) __declspec(naked) void Scr_NotifyId(unsigned int /*id*/, unsigned __int16 /*stringValue*/, unsigned int /*paramcount*/)
{ {
__asm __asm

View File

@ -43,6 +43,9 @@ namespace Game
typedef WeaponDef* (__cdecl * BG_GetWeaponDef_t)(int weaponIndex); typedef WeaponDef* (__cdecl * BG_GetWeaponDef_t)(int weaponIndex);
extern BG_GetWeaponDef_t BG_GetWeaponDef; extern BG_GetWeaponDef_t BG_GetWeaponDef;
typedef const char*(__cdecl * BG_GetEntityTypeName_t)(const int eType);
extern BG_GetEntityTypeName_t BG_GetEntityTypeName;
typedef void(__cdecl * Cbuf_AddServerText_t)(); typedef void(__cdecl * Cbuf_AddServerText_t)();
extern Cbuf_AddServerText_t Cbuf_AddServerText; extern Cbuf_AddServerText_t Cbuf_AddServerText;
@ -76,6 +79,12 @@ namespace Game
typedef void(__cdecl * CG_ScrollScoreboardDown_t)(cg_s* cgameGlob); typedef void(__cdecl * CG_ScrollScoreboardDown_t)(cg_s* cgameGlob);
extern CG_ScrollScoreboardDown_t CG_ScrollScoreboardDown; extern CG_ScrollScoreboardDown_t CG_ScrollScoreboardDown;
typedef const char*(__cdecl * CG_GetTeamName_t)(team_t team);
extern CG_GetTeamName_t CG_GetTeamName;
typedef void(__cdecl * CG_SetupWeaponDef_t)(int localClientNum, unsigned int weapIndex);
extern CG_SetupWeaponDef_t CG_SetupWeaponDef;
typedef char*(__cdecl * CL_GetClientName_t)(int localClientNum, int index, char *buf, size_t size); typedef char*(__cdecl * CL_GetClientName_t)(int localClientNum, int index, char *buf, size_t size);
extern CL_GetClientName_t CL_GetClientName; extern CL_GetClientName_t CL_GetClientName;
@ -374,9 +383,18 @@ namespace Game
typedef unsigned int(__cdecl * G_GetWeaponIndexForName_t)(const char*); typedef unsigned int(__cdecl * G_GetWeaponIndexForName_t)(const char*);
extern G_GetWeaponIndexForName_t G_GetWeaponIndexForName; extern G_GetWeaponIndexForName_t G_GetWeaponIndexForName;
typedef void(__cdecl* G_SpawnEntitiesFromString_t)(); typedef void(__cdecl * G_SpawnEntitiesFromString_t)();
extern G_SpawnEntitiesFromString_t G_SpawnEntitiesFromString; extern G_SpawnEntitiesFromString_t G_SpawnEntitiesFromString;
typedef void(__cdecl * G_PrintEntities_t)();
extern G_PrintEntities_t G_PrintEntities;
typedef const char*(__cdecl * G_GetEntityTypeName_t)(const gentity_s* ent);
extern G_GetEntityTypeName_t G_GetEntityTypeName;
typedef void(__cdecl * Svcmd_EntityList_f_t)();
extern Svcmd_EntityList_f_t Svcmd_EntityList_f;
typedef void(__cdecl * GScr_LoadGameTypeScript_t)(); typedef void(__cdecl * GScr_LoadGameTypeScript_t)();
extern GScr_LoadGameTypeScript_t GScr_LoadGameTypeScript; extern GScr_LoadGameTypeScript_t GScr_LoadGameTypeScript;
@ -750,7 +768,7 @@ namespace Game
typedef unsigned int(__cdecl* SEH_ReadCharFromString_t)(const char** text, int* isTrailingPunctuation); typedef unsigned int(__cdecl* SEH_ReadCharFromString_t)(const char** text, int* isTrailingPunctuation);
extern SEH_ReadCharFromString_t SEH_ReadCharFromString; extern SEH_ReadCharFromString_t SEH_ReadCharFromString;
typedef char*(__cdecl * SL_ConvertToString_t)(unsigned short stringValue); typedef const char*(__cdecl * SL_ConvertToString_t)(scr_string_t stringValue);
extern SL_ConvertToString_t SL_ConvertToString; extern SL_ConvertToString_t SL_ConvertToString;
typedef short(__cdecl * SL_GetString_t)(const char *str, unsigned int user); typedef short(__cdecl * SL_GetString_t)(const char *str, unsigned int user);
@ -816,6 +834,9 @@ namespace Game
typedef void(__cdecl * SV_ClientThink_t)(client_s*, usercmd_s*); typedef void(__cdecl * SV_ClientThink_t)(client_s*, usercmd_s*);
extern SV_ClientThink_t SV_ClientThink; extern SV_ClientThink_t SV_ClientThink;
typedef void(__cdecl * SV_DropClient_t)(client_t* drop, const char* reason, bool tellThem);
extern SV_DropClient_t SV_DropClient;
typedef client_t*(__cdecl * SV_GetPlayerByName_t)(); typedef client_t*(__cdecl * SV_GetPlayerByName_t)();
extern SV_GetPlayerByName_t SV_GetPlayerByName; extern SV_GetPlayerByName_t SV_GetPlayerByName;
@ -979,7 +1000,7 @@ namespace Game
extern float* cgameFOVSensitivityScale; extern float* cgameFOVSensitivityScale;
extern int* svs_time; extern int* svs_time;
extern int* svs_numclients; extern int* svs_clientCount;
extern client_t* svs_clients; extern client_t* svs_clients;
extern source_t **sourceFiles; extern source_t **sourceFiles;
@ -1015,6 +1036,8 @@ namespace Game
constexpr auto ENTITYNUM_NONE = MAX_GENTITIES - 1; constexpr auto ENTITYNUM_NONE = MAX_GENTITIES - 1;
extern gentity_t* g_entities; extern gentity_t* g_entities;
extern int* level_num_entities;
extern int* level_time;
extern int* level_scriptPrintChannel; extern int* level_scriptPrintChannel;
extern netadr_t* connectedHost; extern netadr_t* connectedHost;
@ -1085,6 +1108,11 @@ namespace Game
constexpr auto AIM_ASSIST_GRAPH_COUNT = 4u; constexpr auto AIM_ASSIST_GRAPH_COUNT = 4u;
extern GraphFloat* aaInputGraph; extern GraphFloat* aaInputGraph;
extern const char* MY_CMDS;
constexpr auto MAX_MODELS = 512;
extern XModel** cached_models;
extern vec3_t* CorrectSolidDeltas; extern vec3_t* CorrectSolidDeltas;
extern FastCriticalSection* db_hashCritSect; extern FastCriticalSection* db_hashCritSect;
@ -1092,6 +1120,8 @@ namespace Game
void Sys_LockRead(FastCriticalSection* critSect); void Sys_LockRead(FastCriticalSection* critSect);
void Sys_UnlockRead(FastCriticalSection* critSect); void Sys_UnlockRead(FastCriticalSection* critSect);
XModel* G_GetModel(int index);
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize); XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize);
void Menu_FreeItemMemory(Game::itemDef_s* item); void Menu_FreeItemMemory(Game::itemDef_s* item);
void Menu_SetNextCursorItem(Game::UiContext* ctx, Game::menuDef_t* currentMenu, int unk = 1); void Menu_SetNextCursorItem(Game::UiContext* ctx, Game::menuDef_t* currentMenu, int unk = 1);
@ -1120,8 +1150,8 @@ namespace Game
void R_LoadSunThroughDvars(const char* mapname, sunflare_t* sun); void R_LoadSunThroughDvars(const char* mapname, sunflare_t* sun);
void R_SetSunFromDvars(sunflare_t* sun); void R_SetSunFromDvars(sunflare_t* sun);
void SV_KickClient(client_t* client, const char* reason); void SV_GameDropClient(int clientNum, const char* reason);
void SV_KickClientError(client_t* client, const std::string& reason); void SV_DropAllBots();
void SV_BotUserMove(client_t* client); void SV_BotUserMove(client_t* client);
void RuntimeErrorInternal(int channel, const char* codePos, unsigned int index, const char* msg); void RuntimeErrorInternal(int channel, const char* codePos, unsigned int index, const char* msg);

View File

@ -28,20 +28,20 @@ namespace Game
unsigned __int16 classnum; unsigned __int16 classnum;
}; };
typedef void(__cdecl * xfunction_t)(); typedef void(__cdecl * BuiltinFunction)();
typedef void(__cdecl * xmethod_t)(scr_entref_t); typedef void(__cdecl * BuiltinMethod)(scr_entref_t);
struct BuiltinFunctionDef struct BuiltinFunctionDef
{ {
const char* actionString; const char* actionString;
xfunction_t actionFunc; BuiltinFunction actionFunc;
int type; int type;
}; };
struct BuiltinMethodDef struct BuiltinMethodDef
{ {
const char* actionString; const char* actionString;
xmethod_t actionFunc; BuiltinMethod actionFunc;
int type; int type;
}; };
@ -5576,15 +5576,25 @@ namespace Game
CON_CONNECTED = 0x2 CON_CONNECTED = 0x2
} clientConnected_t; } clientConnected_t;
typedef enum
{
VISIONSET_NORMAL,
VISIONSET_NIGHT,
VISIONSET_MISSILECAM,
VISIONSET_THERMAL,
VISIONSET_PAIN,
VISIONSETCOUNT
} visionSetMode_t;
typedef struct gclient_s typedef struct gclient_s
{ {
playerState_s ps; playerState_s ps;
sessionState_t sessionState; // 12572 sessionState_t sessionState; // 12572
char pad0[40]; unsigned char __pad0[40];
clientConnected_t connected; // 12616 clientConnected_t connected; // 12616
char pad1[144]; unsigned char __pad1[144];
unsigned int team; // 12764 team_t team; // 12764
char pad2[436]; unsigned char __pad2[436];
int flags; // 13204 int flags; // 13204
int spectatorClient; int spectatorClient;
int lastCmdTime; int lastCmdTime;
@ -5592,7 +5602,10 @@ namespace Game
int oldbuttons; // 13220 int oldbuttons; // 13220
int latched_buttons; // 13224 int latched_buttons; // 13224
int buttonsSinceLastFrame; // 13228 int buttonsSinceLastFrame; // 13228
char pad3[700]; // 13232 unsigned char __pad3[324]; // 13232
int visionDuration[5];
char visionName[5][64];
unsigned char __pad4[36];
} gclient_t; } gclient_t;
static_assert(sizeof(gclient_t) == 13932); static_assert(sizeof(gclient_t) == 13932);