From 76770c4a2f7a3314ac39286deb51c50dd5b9897c Mon Sep 17 00:00:00 2001 From: quaK Date: Fri, 12 Jul 2024 18:57:22 +0300 Subject: [PATCH] dedi fixes and other changes --- src/client/component/dedicated.cpp | 15 +++ src/client/component/fov.cpp | 1 - src/client/component/logprint.cpp | 144 ++++++++++++++++++++++++ src/client/component/network.cpp | 9 ++ src/client/component/party.cpp | 9 ++ src/client/component/ranked.cpp | 11 +- src/client/component/weapon.cpp | 5 - src/client/game/scripting/array.cpp | 14 +-- src/client/game/scripting/execution.cpp | 4 +- src/client/game/structs.hpp | 1 + src/client/game/symbols.hpp | 16 ++- 11 files changed, 203 insertions(+), 26 deletions(-) diff --git a/src/client/component/dedicated.cpp b/src/client/component/dedicated.cpp index f8409d63..3f5ea34f 100644 --- a/src/client/component/dedicated.cpp +++ b/src/client/component/dedicated.cpp @@ -27,6 +27,16 @@ namespace dedicated const game::dvar_t* sv_lanOnly; + const char* sv_get_game_type_stub() + { + return game::Dvar_FindVar("g_gametype")->current.string; + } + + bool sv_is_hardcore_mode_stub() + { + return game::Dvar_FindVar("g_hardcore")->current.enabled; + } + void kill_server() { game::SV_MainMP_KillLocalServer(); @@ -257,6 +267,11 @@ namespace dedicated // delay startup commands until the initialization is done utils::hook::call(0x140B8D20F, execute_startup_command); + utils::hook::set(0x140B21107 + 2, 0x482); // g_gametype flags + utils::hook::set(0x140B21137 + 2, 0x480); // g_hardcore flags + utils::hook::jump(0x140C12400, sv_get_game_type_stub); + utils::hook::jump(0x140C12660, sv_is_hardcore_mode_stub); + utils::hook::nop(0x140CDD5D3, 5); // don't load config file utils::hook::nop(0x140B7CE46, 5); // ^ utils::hook::set(0x140BB0930, 0xC3); // don't save config file diff --git a/src/client/component/fov.cpp b/src/client/component/fov.cpp index a6bba9e2..9256c7d0 100644 --- a/src/client/component/fov.cpp +++ b/src/client/component/fov.cpp @@ -4,7 +4,6 @@ #include "game/game.hpp" #include "game/dvars.hpp" -#include "scheduler.hpp" #include "dvars.hpp" #include diff --git a/src/client/component/logprint.cpp b/src/client/component/logprint.cpp index ffa78403..4a2721b1 100644 --- a/src/client/component/logprint.cpp +++ b/src/client/component/logprint.cpp @@ -5,6 +5,7 @@ #include "game/dvars.hpp" #include "scheduler.hpp" +#include "console/console.hpp" #include "gsc/script_extension.hpp" @@ -15,6 +16,9 @@ namespace logprint namespace { utils::hook::detour g_say_hook; + utils::hook::detour scr_player_killed_hook; + utils::hook::detour scr_player_damage_hook; + void g_say_stub(game::gentity_s* ent, game::gentity_s* target, int mode, const char* chat_text) { const char* cmd = mode == game::SAY_TEAM ? "say_team" : "say"; @@ -38,6 +42,142 @@ namespace logprint game::G_LogPrintf(buffer, guid, ent_number, name, weapon_name); game::LUI_Interface_DebugPrint(buffer, guid, ent_number, name, weapon_name); } + + std::string get_weapon_name(unsigned short* weapon, bool isAlternate) + { + char output[1024] = { 0 }; + game::BG_GetWeaponNameComplete(weapon, isAlternate, output, 1024); + return output; + } + + std::string convert_mod(const int meansOfDeath) + { + const auto value = reinterpret_cast(0x14196AA40)[meansOfDeath]; + const auto string = game::SL_ConvertToString(*value); + return string; + } + + void scr_player_damage_stub(game::gentity_s* self, game::gentity_s* inflictor, game::gentity_s* attacker, int damage, int damageFlags, + unsigned int meansOfDeath, unsigned short* weapon, bool isAlternate, const float* vPoint, const float* vDir, + game::hitLocation_t hitLoc, int timeOffset, int modelIndex, game::scr_string_t partName) + { + auto hit_location = game::g_HitLocNames[hitLoc]; + const auto mod = convert_mod(meansOfDeath); + const auto weapon_name = get_weapon_name(weapon, isAlternate); + + scheduler::once([=]() + { + try + { + const scripting::entity self_{ game::Scr_GetEntityId(self->s.number, 0) }; + assert(self, "self must be defined in Scr_PlayerDamage"); + + int lpselfnum = self_.call("getentitynumber").as(); + std::string lpselfname = self_.get("name").as(); + std::string lpselfteam = self_.get("team").as(); + std::string lpselfGuid = self_.call("getxuid").as(); + + int lpattacknum = -1; + std::string lpattackname = ""; + std::string lpattackGuid = ""; + std::string lpattackerteam = "world"; + + if (attacker) + { + const scripting::entity attacker_{ game::Scr_GetEntityId(attacker->s.number, 0) }; + if (scripting::call("isplayer", { attacker_ }).as()) + { + lpattacknum = attacker_.call("getentitynumber").as(); + lpattackname = attacker_.get("name").as(); + lpattackerteam = attacker_.get("team").as(); + lpattackGuid = attacker_.call("getxuid").as(); + } + } + + game::G_LogPrintf("D;%s;%d;%s;%s;%s;%d;%s;%s;%s;%d;%s;%s\n", + lpselfGuid.data(), + lpselfnum, + lpselfteam.data(), + lpselfname.data(), + lpattackGuid.data(), + lpattacknum, + lpattackerteam.data(), + lpattackname.data(), + weapon_name.data(), + damage, + mod.data(), + hit_location); + } + catch (std::exception err) + { + console::error("%s\n", err.what()); + } + }, scheduler::pipeline::server); + + return scr_player_damage_hook.invoke(self, inflictor, attacker, damage, damageFlags, + meansOfDeath, weapon, isAlternate, vPoint, vDir, hitLoc, timeOffset, modelIndex, partName); + } + + void scr_player_killed_stub(game::gentity_s* self, game::gentity_s* inflictor, game::gentity_s* attacker, int damage, int damageFlags, + unsigned int meansOfDeath, unsigned short* weapon, bool isAlternate, const float* vDir, + game::hitLocation_t hitLoc, int timeOffset, int deathAnimDuration) + { + auto hit_location = game::g_HitLocNames[hitLoc]; + const auto mod = convert_mod(meansOfDeath); + const auto weapon_name = get_weapon_name(weapon, isAlternate); + + scheduler::once([=]() + { + try + { + const scripting::entity self_{ game::Scr_GetEntityId(self->s.number, 0) }; + assert(self, "self must be defined in Scr_PlayerKilled"); + + int lpselfnum = self_.call("getentitynumber").as(); + std::string lpselfname = self_.get("name").as(); + std::string lpselfteam = self_.get("team").as(); + std::string lpselfGuid = self_.call("getxuid").as(); + + int lpattacknum = -1; + std::string lpattackname = ""; + std::string lpattackGuid = ""; + std::string lpattackerteam = "world"; + + if (attacker) + { + const scripting::entity attacker_{ game::Scr_GetEntityId(attacker->s.number, 0) }; + if (scripting::call("isplayer", { attacker_ }).as()) + { + lpattacknum = attacker_.call("getentitynumber").as(); + lpattackname = attacker_.get("name").as(); + lpattackerteam = attacker_.get("team").as(); + lpattackGuid = attacker_.call("getxuid").as(); + } + } + + game::G_LogPrintf("K;%s;%d;%s;%s;%s;%d;%s;%s;%s;%d;%s;%s\n", + lpselfGuid.data(), + lpselfnum, + lpselfteam.data(), + lpselfname.data(), + lpattackGuid.data(), + lpattacknum, + lpattackerteam.data(), + lpattackname.data(), + weapon_name.data(), + damage, + mod.data(), + hit_location); + } + catch (std::exception err) + { + console::error("%s\n", err.what()); + } + }, scheduler::pipeline::server); + + return scr_player_killed_hook.invoke(self, inflictor, attacker, damage, damageFlags, + meansOfDeath, weapon, isAlternate, vDir, hitLoc, timeOffset, deathAnimDuration); + } } class component final : public component_interface @@ -72,6 +212,10 @@ namespace logprint // Hook LUI_Interface_DebugPrint call in GItemsMP::TouchLogPickup utils::hook::call(0x140448F1D, touch_log_pickup_stub); + + // Hook player damage and player death so we can logprint them + scr_player_damage_hook.create(0x140B5E7D0, scr_player_damage_stub); + scr_player_killed_hook.create(0x140B5E9E0, scr_player_killed_stub); } }; } diff --git a/src/client/component/network.cpp b/src/client/component/network.cpp index 041ff246..294cf34f 100644 --- a/src/client/component/network.cpp +++ b/src/client/component/network.cpp @@ -363,6 +363,15 @@ namespace network utils::hook::set(0x140BB4E22, max_packet_size); utils::hook::set(0x140BB4F31, max_packet_size); + // increase cl_maxpackets + dvars::override::register_int("cl_maxpackets", 1000, 1, 1000, game::DVAR_FLAG_NONE); + + // increase snaps + dvars::override::register_int("sv_remote_client_snapshot_msec", 33, -1, 100, game::DVAR_FLAG_NONE); + + // disable snapshot default values overriding the actual values every time the server starts + utils::hook::set(0x140C56780, 0xC3); // SV_SnapshotMP_InitRuntime + // ignore built in "print" oob command and add in our own utils::hook::set(0x1409B0326, 0xEB); diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp index 1a55ff2f..449f7239 100644 --- a/src/client/component/party.cpp +++ b/src/client/component/party.cpp @@ -278,6 +278,12 @@ namespace party command::execute(utils::string::va("ui_gametype %s", gametype->current.string), true); } + auto* hardcore = game::Dvar_FindVar("g_hardcore"); + if (hardcore) + { + command::execute(utils::string::va("ui_hardcore %s", hardcore->current.enabled), true); + } + perform_game_initialization(); console::info("Starting map: %s\n", mapname.data()); @@ -415,6 +421,9 @@ namespace party // enable custom kick reason in GScr_KickPlayer utils::hook::set(0x140B5377E, 0xEB); + // disable this, maybe causes no issues, but fixes Session unregister on map change/restart + utils::hook::set(0x140851B50, 0xC3); // CG_ServerCmdMP_ParsePlayerInfos + command::add("map", [](const command::params& args) { if (args.size() != 2) diff --git a/src/client/component/ranked.cpp b/src/client/component/ranked.cpp index 14f80d68..5c6f5957 100644 --- a/src/client/component/ranked.cpp +++ b/src/client/component/ranked.cpp @@ -15,18 +15,19 @@ namespace ranked public: void post_unpack() override { - // This must be registered as 'true' to avoid crash when starting a private match - dvars::override::register_bool("xblive_privatematch", true, game::DVAR_FLAG_REPLICATED); - - if (game::environment::is_dedi() && !utils::flags::has_flag("unranked")) + if (game::environment::is_dedi()) { - dvars::override::register_bool("xblive_privatematch", false, game::DVAR_FLAG_REPLICATED | game::DVAR_FLAG_WRITE); // DVAR_FLAG_REPLICATED needed? + dvars::override::register_bool("xblive_privatematch", false, game::DVAR_FLAG_REPLICATED | game::DVAR_FLAG_WRITE); game::Dvar_RegisterBool("onlinegame", true, game::DVAR_FLAG_READ, "Current game is an online game with stats, custom classes, unlocks"); // Fix sessionteam always returning none (SV_ClientMP_HasAssignedTeam_Internal) utils::hook::set(0x140C50BC0, 0xC300B0); } + else + { + dvars::override::register_bool("xblive_privatematch", true, game::DVAR_FLAG_REPLICATED); + } } component_priority priority() override diff --git a/src/client/component/weapon.cpp b/src/client/component/weapon.cpp index 1bc16024..47bd2348 100644 --- a/src/client/component/weapon.cpp +++ b/src/client/component/weapon.cpp @@ -238,11 +238,6 @@ namespace weapon public: void post_unpack() override { - if (game::environment::is_dedi()) - { - return; - } - #ifdef DEBUG command::add("setWeaponFieldFloat", [](const command::params& params) { diff --git a/src/client/game/scripting/array.cpp b/src/client/game/scripting/array.cpp index c2255f08..9137df3b 100644 --- a/src/client/game/scripting/array.cpp +++ b/src/client/game/scripting/array.cpp @@ -14,7 +14,7 @@ namespace scripting return; } - const auto value = game::scr_VarGlob->childVariableValue[this->id_ + 0xFA00 * (this->parent_id_ & 3)]; + const auto value = game::scr_VarGlob->childVariableValue[this->id_ + 0xA000 * (this->parent_id_ & 3)]; game::VariableValue variable; variable.u = value.u.u; variable.type = value.type; @@ -31,7 +31,7 @@ namespace scripting const auto value = _value.get_raw(); - const auto variable = &game::scr_VarGlob->childVariableValue[this->id_ + 0xFA00 * (this->parent_id_ & 3)]; + const auto variable = &game::scr_VarGlob->childVariableValue[this->id_ + 0xA000 * (this->parent_id_ & 3)]; game::AddRefToValue(value.type, value.u); game::RemoveRefToValue(variable->type, variable->u.u); @@ -131,7 +131,7 @@ namespace scripting { std::vector result; - const auto offset = 0xFA00 * (this->id_ & 3); + const auto offset = 0xA000 * (this->id_ & 3); auto current = game::scr_VarGlob->objectVariableChildren[this->id_].firstChild; for (auto i = offset + current; current; i = offset + current) @@ -224,7 +224,7 @@ namespace scripting return {}; } - const auto value = game::scr_VarGlob->childVariableValue[variable_id + 0xFA00 * (this->id_ & 3)]; + const auto value = game::scr_VarGlob->childVariableValue[variable_id + 0xA000 * (this->id_ & 3)]; game::VariableValue variable; variable.u = value.u.u; variable.type = value.type; @@ -241,7 +241,7 @@ namespace scripting return {}; } - const auto value = game::scr_VarGlob->childVariableValue[variable_id + 0xFA00 * (this->id_ & 3)]; + const auto value = game::scr_VarGlob->childVariableValue[variable_id + 0xA000 * (this->id_ & 3)]; game::VariableValue variable; variable.u = value.u.u; variable.type = value.type; @@ -271,7 +271,7 @@ namespace scripting return; } - const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + 0xFA00 * (this->id_ & 3)]; + const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + 0xA000 * (this->id_ & 3)]; game::AddRefToValue(value.type, value.u); game::RemoveRefToValue(variable->type, variable->u.u); @@ -290,7 +290,7 @@ namespace scripting return; } - const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + 0xFA00 * (this->id_ & 3)]; + const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + 0xA000 * (this->id_ & 3)]; game::AddRefToValue(value.type, value.u); game::RemoveRefToValue(variable->type, variable->u.u); diff --git a/src/client/game/scripting/execution.cpp b/src/client/game/scripting/execution.cpp index d72fc358..f5a9ed52 100644 --- a/src/client/game/scripting/execution.cpp +++ b/src/client/game/scripting/execution.cpp @@ -208,7 +208,7 @@ namespace scripting void set_object_variable(const unsigned int parent_id, const unsigned int id, const script_value& value) { - const auto offset = 0xFA00 * (parent_id & 3); + const auto offset = 0xA000 * (parent_id & 3); const auto variable_id = game::GetVariable(parent_id, id); const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + offset]; const auto& raw_value = value.get_raw(); @@ -228,7 +228,7 @@ namespace scripting script_value get_object_variable(const unsigned int parent_id, const unsigned int id) { - const auto offset = 0xFA00 * (parent_id & 3); + const auto offset = 0xA000 * (parent_id & 3); const auto variable_id = game::FindVariable(parent_id, id); if (!variable_id) { diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 823f94b7..6fc01b81 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -929,6 +929,7 @@ namespace game static_assert(offsetof(cg_s, cubemapSize) == 19164); static_assert(offsetof(cg_s, viewModelAxis) == 324368); static_assert(offsetof(cg_s, renderScreen) == 492892); + static_assert(offsetof(cg_s, spectatingThirdPerson) == 492908); static_assert(offsetof(cg_s, renderingThirdPerson) == 492912); static_assert(offsetof(cg_s, m_deathCameraFailsafeLock) == 553708); diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 2d5be05d..e2e59f69 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -19,8 +19,9 @@ namespace game WEAK symbol Scr_ExecThread{ 0x140C0ACD0 }; WEAK symbol BG_GetGravity{ 0x140068DD0 }; - WEAK game::symbol BG_PlayerLastWeaponHandForViewWeapon{ 0x14074B410 }; - WEAK game::symbol BG_ViewModelAnimExists{ 0x140751200 }; + WEAK symbol BG_PlayerLastWeaponHandForViewWeapon{ 0x14074B410 }; + WEAK symbol BG_ViewModelAnimExists{ 0x140751200 }; + WEAK symbol BG_GetWeaponNameComplete{ 0x140733D50 }; WEAK symbol Com_Error{ 0x140B8D830 }; @@ -141,6 +142,7 @@ namespace game WEAK symbol G_GetWeaponForName { 0x140B4FCB0 }; WEAK symbol G_GivePlayerWeapon{ 0x140B69400 }; WEAK symbol G_InitializeAmmo{ 0x140B1B0E0 }; + WEAK symbol G_GetHitLocationString{ 0x1403F5D70 }; WEAK symbol I_CleanStr{ 0x140CFACC0 }; @@ -216,9 +218,9 @@ namespace game WEAK symbol PMem_AllocFromSource_NoDebug{ 0x140CF0A90 }; WEAK symbol PMem_Free{ 0x140CF10D0 }; - WEAK game::symbol PM_Weapon_IsInInterruptibleState{ 0x140728210 }; - WEAK game::symbol PM_BuildWeaponAnimArrays{ 0x14071AC50 }; - WEAK game::symbol PM_Weapon_Idle{ 0x140727910 }; + WEAK symbol PM_Weapon_IsInInterruptibleState{ 0x140728210 }; + WEAK symbol PM_BuildWeaponAnimArrays{ 0x14071AC50 }; + WEAK symbol PM_Weapon_Idle{ 0x140727910 }; WEAK symbol VM_Execute{ 0x140C0CDB0 }; @@ -277,7 +279,7 @@ namespace game WEAK symbol UI_RunMenuScript{ 0x140CC9710 }; WEAK symbol UI_SafeTranslateString{ 0x140CC9790 }; - WEAK game::symbol XAnimGetLengthMsec{ 0x140D761C0 }; + WEAK symbol XAnimGetLengthMsec{ 0x140D761C0 }; WEAK symbol longjmp{ 0x1412C0758 }; WEAK symbol _setjmp{ 0x141423110 }; @@ -354,6 +356,8 @@ namespace game WEAK symbol bg_weaponDefs{ 0x145210120 }; + WEAK symbol g_HitLocNames{ 0x14196AAF0 }; + namespace hks { WEAK symbol lua_state{ 0x144FC35F0 };