From 7d559d5a3153a11c381238b2545c229e6038e586 Mon Sep 17 00:00:00 2001 From: Joelrau Date: Sat, 9 Jan 2021 21:22:28 +0200 Subject: [PATCH] Bunch of new stuff --- src/client/component/bots.cpp | 14 ++--- src/client/component/command.cpp | 80 +++++++++++++++++++++++++++++ src/client/component/filesystem.cpp | 52 +++++++++++++++++++ src/client/component/filesystem.hpp | 19 +++++++ src/client/component/party.cpp | 80 ++++++++++++++++++++--------- src/client/component/patches.cpp | 48 +++++++++++++++-- src/client/game/dvars.cpp | 2 + src/client/game/dvars.hpp | 2 + 8 files changed, 260 insertions(+), 37 deletions(-) create mode 100644 src/client/component/filesystem.cpp create mode 100644 src/client/component/filesystem.hpp diff --git a/src/client/component/bots.cpp b/src/client/component/bots.cpp index 37d6925..a3d182a 100644 --- a/src/client/component/bots.cpp +++ b/src/client/component/bots.cpp @@ -13,15 +13,11 @@ namespace bots { bool can_spawn() { - // disable spawning for now, causes a crash if more than svs_numclients. - - //const auto index = *game::mp::svs_numclients - 1; - //const auto cant = game::mp::svs_clients[index].header.state; - //if (cant) - //{ - return false; - //} - //return true; + if (party::get_client_count() < *game::mp::svs_numclients) + { + return true; + } + return false; } void add_bot() diff --git a/src/client/component/command.cpp b/src/client/component/command.cpp index b03e2e5..470ab3a 100644 --- a/src/client/component/command.cpp +++ b/src/client/component/command.cpp @@ -295,12 +295,92 @@ namespace command static void add_commands_sp() { + add("give", [](const params& params) + { + if (!game::SV_Loaded()) + { + return; + } + if (params.size() < 2) + { + game::CG_GameMessage(0, "You did not specify a weapon name"); + return; + } + + auto ps = game::SV_GetPlayerstateForClientNum(0); + auto wp = game::G_GetWeaponForName(params.get(1)); + if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0, 0, 0, 0)) + { + game::G_InitializeAmmo(ps, wp, 0); + game::G_SelectWeapon(0, wp); + } + }); + + add("take", [](const params& params) + { + if (!game::SV_Loaded()) + { + return; + } + + if (params.size() < 2) + { + game::CG_GameMessage(0, "You did not specify a weapon name"); + return; + } + + auto ps = game::SV_GetPlayerstateForClientNum(0); + auto wp = game::G_GetWeaponForName(params.get(1)); + game::G_TakePlayerWeapon(ps, wp); + }); } static void add_commands_mp() { client_command_hook.create(0x1402E98F0, &client_command); + + add_sv("give", [](const int client_num, const params_sv& params) + { + if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + { + game::SV_GameSendServerCommand(client_num, 1, "f \"Cheats are not enabled on this server\""); + return; + } + + if (params.size() < 2) + { + game::SV_GameSendServerCommand(client_num, 1, "f \"You did not specify a weapon name\""); + return; + } + + auto ps = game::SV_GetPlayerstateForClientNum(client_num); + auto wp = game::G_GetWeaponForName(params.get(1)); + if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0, 0, 0, 0)) + { + game::G_InitializeAmmo(ps, wp, 0); + game::G_SelectWeapon(client_num, wp); + } + }); + + add_sv("take", [](const int client_num, const params_sv& params) + { + if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + { + game::SV_GameSendServerCommand(client_num, 1, "f \"Cheats are not enabled on this server\""); + return; + } + + if (params.size() < 2) + { + game::SV_GameSendServerCommand(client_num, 1, "f \"You did not specify a weapon name\""); + return; + } + + auto ps = game::SV_GetPlayerstateForClientNum(client_num); + auto wp = game::G_GetWeaponForName(params.get(1)); + game::G_TakePlayerWeapon(ps, wp); + }); } }; } diff --git a/src/client/component/filesystem.cpp b/src/client/component/filesystem.cpp new file mode 100644 index 0000000..9334442 --- /dev/null +++ b/src/client/component/filesystem.cpp @@ -0,0 +1,52 @@ +#include +#include "loader/component_loader.hpp" +#include "filesystem.hpp" + +#include "game/game.hpp" +#include "dvars.hpp" + +#include + +namespace filesystem +{ + file::file(std::string name) + : name_(std::move(name)) + { + char* buffer{}; + const auto size = game::FS_ReadFile(this->name_.data(), &buffer); + + if (size >= 0 && buffer) + { + this->valid_ = true; + this->buffer_.append(buffer, size); + game::FS_FreeFile(buffer); + } + } + + bool file::exists() const + { + return this->valid_; + } + + const std::string& file::get_buffer() const + { + return this->buffer_; + } + + const std::string& file::get_name() const + { + return this->name_; + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + // Set fs_basegame + dvars::override::Dvar_RegisterString("fs_basegame", "s1-mod", 2048); + } + }; +} + +REGISTER_COMPONENT(filesystem::component) diff --git a/src/client/component/filesystem.hpp b/src/client/component/filesystem.hpp new file mode 100644 index 0000000..bf391fe --- /dev/null +++ b/src/client/component/filesystem.hpp @@ -0,0 +1,19 @@ +#pragma once + +namespace filesystem +{ + class file + { + public: + file(std::string name); + + bool exists() const; + const std::string& get_buffer() const; + const std::string& get_name() const; + + private: + bool valid_ = false; + std::string name_; + std::string buffer_; + }; +} diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp index 9ceb071..a42834a 100644 --- a/src/client/component/party.cpp +++ b/src/client/component/party.cpp @@ -2,6 +2,7 @@ #include "loader/component_loader.hpp" #include "party.hpp" +#include "dvars.hpp" #include "command.hpp" #include "network.hpp" #include "scheduler.hpp" @@ -70,6 +71,40 @@ namespace party return {}; } + + int get_dvar_int(const std::string& dvar) + { + auto* dvar_value = game::Dvar_FindVar(dvar.data()); + if (dvar_value && dvar_value->current.integer) + { + return dvar_value->current.integer; + } + + return -1; + } + + bool get_dvar_bool(const std::string& dvar) + { + auto* dvar_value = game::Dvar_FindVar(dvar.data()); + if (dvar_value && dvar_value->current.enabled) + { + return dvar_value->current.enabled; + } + + return false; + } + + void didyouknow_stub(const char* dvar_name, const char* string) + { + if (!party::sv_motd.empty()) + { + string = party::sv_motd.data(); + } + + // This function either does Dvar_SetString or Dvar_RegisterString for the given dvar + reinterpret_cast(0x1404C39B0)(dvar_name, string); + party::sv_motd.clear(); + } } int get_client_count() @@ -77,10 +112,10 @@ namespace party auto count = 0; for (auto i = 0; i < *game::mp::svs_numclients; ++i) { - //if (game::mp::svs_clients[i].header.state >= 3) - //{ - // ++count; - //} + if (game::mp::svs_clients[i].header.state >= 3) + { + ++count; + } } return count; @@ -91,11 +126,11 @@ namespace party auto count = 0; for (auto i = 0; i < *game::mp::svs_numclients; ++i) { - //if (game::mp::svs_clients[i].header.state >= 3 && - // game::mp::svs_clients[i].testClient != game::TC_NONE) - //{ - // ++count; - //} + if (game::mp::svs_clients[i].header.state >= 3 && + game::SV_BotIsBot(i)) + { + ++count; + } } return count; @@ -146,10 +181,9 @@ namespace party return; } - // starting map doesn't work, only private match -> start + // starting map like this crashes the game. printf("Starting map: %s\n", mapname.data()); game::SV_StartMapForParty(0, mapname.data(), true); - //game::SV_StartMap(0, mapname.data()); } } @@ -310,6 +344,8 @@ namespace party printf("%s\n", message.data()); }); + utils::hook::call(0x14048811C, didyouknow_stub); // allow custom didyouknow based on sv_motd + network::on("getInfo", [](const game::netadr_s& target, const std::string_view& data) { utils::info_string info{}; @@ -326,8 +362,6 @@ namespace party info.set("sv_maxclients", utils::string::va("%i", *game::mp::svs_numclients)); info.set("protocol", utils::string::va("%i", PROTOCOL)); info.set("playmode", utils::string::va("%i", game::Com_GetCurrentCoDPlayMode())); - //info.set("shortversion", SHORTVERSION); - //info.set("hc", (Dvar::Var("g_hardcore").get() ? "1" : "0")); network::send(target, "infoResponse", info.build(), '\n'); }); @@ -350,8 +384,17 @@ namespace party return; } + const auto gamename = info.get("gamename"); + if (gamename != "S1"s) + { + const auto str = "Invalid gamename."; + printf("%s\n", str); + game::Com_Error(game::ERR_DROP, str); + return; + } + const auto playmode = info.get("playmode"); - if (playmode.empty()) + if (game::CodPlayMode(std::atoi(playmode.data())) != game::Com_GetCurrentCoDPlayMode()) { const auto str = "Invalid playmode."; printf("%s\n", str); @@ -377,15 +420,6 @@ namespace party return; } - const auto gamename = info.get("gamename"); - if (gamename != "S1"s) - { - const auto str = "Invalid gamename."; - printf("%s\n", str); - game::Com_Error(game::ERR_DROP, str); - return; - } - party::sv_motd = info.get("sv_motd"); connect_to_party(target, mapname, gametype); diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index 15512ac..aa10962 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -5,8 +5,9 @@ #include "game/game.hpp" #include "game/dvars.hpp" #include "scheduler.hpp" -#include "dvars.hpp" +#include "filesystem.hpp" #include "fastfiles.hpp" +#include "dvars.hpp" #include #include @@ -41,7 +42,7 @@ namespace patches if (game::environment::is_mp()) { // Make name save - game::Dvar_RegisterString("name", "Unknown Soldier", 0x1, "Player name."); + game::Dvar_RegisterString("name", "Unknown Soldier", game::DVAR_FLAG_SAVED, "Player name."); // Disable data validation error popup game::Dvar_RegisterInt("data_validation_allow_drop", 0, 0, 0, 0, ""); @@ -54,14 +55,14 @@ namespace patches const unsigned int /*flags*/, const char* description) { - return game::Dvar_RegisterInt(name, 0, 0, 1000, 0x1, description); + return game::Dvar_RegisterInt(name, 0, 0, 1000, game::DVAR_FLAG_SAVED, description); } game::dvar_t* register_cg_fov_stub(const char* name, float value, float min, float /*max*/, const unsigned int flags, const char* description) { - return game::Dvar_RegisterFloat(name, value, min, 160, flags | 0x1, description); + return game::Dvar_RegisterFloat(name, value, min, 160, game::DVAR_FLAG_SAVED, description); } game::dvar_t* register_fovscale_stub(const char* name, float /*value*/, float /*min*/, float /*max*/, @@ -69,7 +70,7 @@ namespace patches const char* desc) { // changed max value from 2.0f -> 5.0f and min value from 0.5f -> 0.1f - return game::Dvar_RegisterFloat(name, 1.0f, 0.1f, 5.0f, 0x1, desc); + return game::Dvar_RegisterFloat(name, 1.0f, 0.1f, 5.0f, game::DVAR_FLAG_SAVED, desc); } int dvar_command_patch() // game makes this return an int and compares with eax instead of al -_- @@ -104,6 +105,34 @@ namespace patches return 0; } + const char* db_read_raw_file_stub(const char* filename, char* buf, int size) + { + std::string file_name = filename; + if (file_name.find(".cfg") == std::string::npos) + { + file_name.append(".cfg"); + } + + const auto file = filesystem::file(file_name); + if (file.exists()) + { + snprintf(buf, size, "%s\n", file.get_buffer().data()); + printf("%s\n", buf); + return buf; + } + + // DB_ReadRawFile + return reinterpret_cast(SELECT_VALUE(0x140180E30, 0x140273080))(filename, buf, size); + } + + void aim_assist_add_to_target_list(void* a1, void* a2) + { + if (!dvars::aimassist_enabled->current.enabled) + return; + + game::AimAssist_AddToTargetList(a1, a2); + } + void missing_content_error_stub(int /*mode*/, const char* /*message*/) { game::Com_Error(game::ERR_DROP, utils::string::va("MISSING FILE\n%s.ff", fastfiles::get_current_fastfile())); @@ -152,6 +181,9 @@ namespace patches // Show missing fastfiles utils::hook::call(SELECT_VALUE(0x1401817AF, 0x1402742A8), missing_content_error_stub); + // Allow executing custom cfg files with the "exec" command + utils::hook::call(SELECT_VALUE(0x1402EE225, 0x1403AF7CD), db_read_raw_file_stub); + // Fix mouse lag utils::hook::nop(SELECT_VALUE(0x14038FAFF, 0x1404DB1AF), 6); scheduler::loop([]() @@ -179,6 +211,12 @@ namespace patches // patch "Couldn't find the bsp for this map." error to not be fatal in mp utils::hook::call(0x14026E63B, bsp_sys_error_stub); + + //client side aim assist dvar + dvars::aimassist_enabled = game::Dvar_RegisterBool("aimassist_enabled", true, + game::DvarFlags::DVAR_FLAG_SAVED, + "Enables aim assist for controllers"); + utils::hook::call(0x140003609, aim_assist_add_to_target_list); } static void patch_sp() diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp index 03b9d3f..1cf292e 100644 --- a/src/client/game/dvars.cpp +++ b/src/client/game/dvars.cpp @@ -5,6 +5,8 @@ namespace dvars { + game::dvar_t* aimassist_enabled = nullptr; + game::dvar_t* con_inputBoxColor = nullptr; game::dvar_t* con_inputHintBoxColor = nullptr; game::dvar_t* con_outputBarColor = nullptr; diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp index 8dfbb58..37c5847 100644 --- a/src/client/game/dvars.hpp +++ b/src/client/game/dvars.hpp @@ -5,6 +5,8 @@ namespace dvars { + extern game::dvar_t* aimassist_enabled; + extern game::dvar_t* con_inputBoxColor; extern game::dvar_t* con_inputHintBoxColor; extern game::dvar_t* con_outputBarColor;