From df9040c6af20fccb645417dfb87e6735677528c4 Mon Sep 17 00:00:00 2001 From: quaK Date: Mon, 12 Aug 2024 01:52:13 +0300 Subject: [PATCH 1/3] dedi fixes and more --- src/client/component/command.cpp | 8 +- src/client/component/dedicated.cpp | 35 ++--- src/client/component/party.cpp | 148 ++++++++++++++----- src/client/component/patches.cpp | 19 ++- src/client/component/profile_infos.cpp | 193 +------------------------ src/client/component/profile_infos.hpp | 8 - src/client/component/ranked.cpp | 14 ++ src/client/game/game.hpp | 2 +- src/client/game/symbols.hpp | 3 + 9 files changed, 166 insertions(+), 264 deletions(-) diff --git a/src/client/component/command.cpp b/src/client/component/command.cpp index 38a7154f..20f76d5a 100644 --- a/src/client/component/command.cpp +++ b/src/client/component/command.cpp @@ -79,8 +79,8 @@ namespace command static std::string comand_line_buffer = GetCommandLineA(); auto* command_line = comand_line_buffer.data(); - auto& com_num_console_lines = *reinterpret_cast(0x146006DB0); - auto* com_console_lines = reinterpret_cast(0x146006DC0); + auto& com_num_console_lines = *game::com_num_console_lines; + auto* com_console_lines = game::com_console_lines.get(); auto inq = false; com_console_lines[0] = command_line; @@ -111,8 +111,8 @@ namespace command void parse_startup_variables() { - auto& com_num_console_lines = *reinterpret_cast(0x146006DB0); - auto* com_console_lines = reinterpret_cast(0x146006DC0); + auto& com_num_console_lines = *game::com_num_console_lines; + auto* com_console_lines = game::com_console_lines.get(); for (int i = 0; i < com_num_console_lines; i++) { diff --git a/src/client/component/dedicated.cpp b/src/client/component/dedicated.cpp index ad437bbd..37efc00c 100644 --- a/src/client/component/dedicated.cpp +++ b/src/client/component/dedicated.cpp @@ -50,26 +50,22 @@ namespace dedicated return startup_command_queue; } - void execute_startup_command(int client, int /*controllerIndex*/, const char* command) + void execute_startup_commands() { - if (game::Live_SyncOnlineDataFlags(0) == 0) - { - game::Cbuf_ExecuteBufferInternal(0, 0, command, game::Cmd_ExecuteSingleCommand); - } - else - { - get_startup_command_queue().emplace_back(command); - } - } + auto& com_num_console_lines = *game::com_num_console_lines; + auto* com_console_lines = game::com_console_lines.get(); - void execute_startup_command_queue() - { - const auto queue = get_startup_command_queue(); - get_startup_command_queue().clear(); - - for (const auto& command : queue) + for (auto i = 0; i < com_num_console_lines; i++) { - game::Cbuf_ExecuteBufferInternal(0, 0, command.data(), game::Cmd_ExecuteSingleCommand); + auto cmd = com_console_lines[i]; + + // if command is map or map_rotate, its already been called + if (cmd == "map"s || cmd == "map_rotate"s) + { + continue; + } + + game::Cbuf_ExecuteBufferInternal(0, 0, cmd, game::Cmd_ExecuteSingleCommand); } } @@ -268,9 +264,6 @@ namespace dedicated utils::hook::jump(0x140341B60, init_dedicated_server, true); - // 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); @@ -397,7 +390,7 @@ namespace dedicated // remove disconnect command game::Cmd_RemoveCommand("disconnect"); - execute_startup_command_queue(); + execute_startup_commands(); // Send heartbeat to dpmaster scheduler::once(send_heartbeat, scheduler::pipeline::server); diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp index b6674f94..e0d22534 100644 --- a/src/client/component/party.cpp +++ b/src/client/component/party.cpp @@ -296,16 +296,52 @@ namespace party bool preloaded_map = false; - void perform_game_initialization() + void xstartlobby(const int max_clients, const bool private_match) { - command::execute("onlinegame 1", true); - command::execute("xblive_privatematch 1", true); - //command::execute("xstartprivateparty", true); - command::execute("xstartprivatematch", true); + // Retrieve game variables + const int privateMatch = private_match; //game::Dvar_FindVar("xblive_privatematch")->current.integer; + const int maxPlayers = max_clients; //game::Dvar_FindVar("party_maxplayers")->current.integer; + const int privateClients = 0; //game::Dvar_FindVar("ui_privateClients")->current.integer; + const int availableSpots = maxPlayers - privateClients; + + // Get party data + auto partyData = game::Lobby_GetPartyData(); + + // Stop current party and reset settings + utils::hook::invoke(0x1409D07B0, partyData); // Party_StopParty + utils::hook::invoke(0x1409CAB20, partyData, 0, 1); // Party_Awake + utils::hook::invoke(0x1409D0050); // Party_ResetTweakDvars + utils::hook::invoke(0x1409CB460, partyData); // Voice_DisableLocalMics + + // Set lobby presence + utils::hook::invoke(0x140D330B0, 0); // Live_SetLobbyPresence + + // Run playlist rule if not in a private match + if (!privateMatch/* && !game::environment::is_dedi()*/) + { + utils::hook::invoke(0x140CCD840, 0, 0); // Playlist_RunRule + } + + // Set up lobby flags + const int flags = utils::hook::invoke(0x140D9B200, 0); // PartyHost_GetCreateFlags + + // Initialize lobby + utils::hook::invoke(0x1409D9940, partyData, 0, 0, flags, privateClients, availableSpots); + } + + void perform_game_initialization(const int max_clients, const bool private_match) + { + xstartlobby(max_clients, private_match); + + const auto ui_maxclients = game::Dvar_FindVar("ui_maxclients"); + const auto party_maxplayers = game::Dvar_FindVar("party_maxplayers"); + game::Dvar_SetInt(ui_maxclients, max_clients); + game::Dvar_SetInt(party_maxplayers, max_clients); + command::execute("uploadstats", true); } - void connect_to_party(const game::netadr_s& target, const std::string& mapname, const std::string& gametype, int sv_maxclients) + void connect_to_party(const game::netadr_s& target, const std::string& mapname, const std::string& gametype, int sv_maxclients, const bool private_match) { const auto mode = game::Com_GameMode_GetActiveGameMode(); if (mode != game::GAME_MODE_MP && mode != game::GAME_MODE_CP) @@ -317,20 +353,15 @@ namespace party { scheduler::once([=]() { - connect_to_party(target, mapname, gametype, sv_maxclients); + connect_to_party(target, mapname, gametype, sv_maxclients, private_match); }, scheduler::pipeline::main, 1s); return; } - const auto ui_maxclients = game::Dvar_FindVar("ui_maxclients"); - const auto party_maxplayers = game::Dvar_FindVar("party_maxplayers"); - game::Dvar_SetInt(ui_maxclients, sv_maxclients); - game::Dvar_SetInt(party_maxplayers, sv_maxclients); + perform_game_initialization(sv_maxclients, private_match); - command::execute(utils::string::va("ui_mapname %s", mapname.data()), true); - command::execute(utils::string::va("ui_gametype %s", gametype.data()), true); - - perform_game_initialization(); + game::Dvar_SetFromStringByName("ui_mapname", mapname.data(), game::DVAR_SOURCE_INTERNAL); + game::Dvar_SetFromStringByName("ui_gametype", gametype.data(), game::DVAR_SOURCE_INTERNAL); // setup agent count utils::hook::invoke(0x140C19B00, gametype.data()); @@ -344,7 +375,7 @@ namespace party void start_map_for_party(std::string map_name) { - [[maybe_unused]]auto* mapname = game::Dvar_FindVar("ui_mapname"); + [[maybe_unused]] auto* mapname = game::Dvar_FindVar("ui_mapname"); auto* gametype = game::Dvar_FindVar("ui_gametype"); auto* clients = game::Dvar_FindVar("ui_maxclients"); auto* private_clients = game::Dvar_FindVar("ui_privateClients"); @@ -398,8 +429,6 @@ namespace party void sv_start_map_for_party_stub(const char* map, const char* game_type, int client_count, int agent_count, bool hardcore, bool map_is_preloaded, bool migrate) { - profile_infos::xuid::clear_xuids(); - hash_cache.clear(); if (game::environment::is_dedi()) @@ -426,6 +455,8 @@ namespace party memset(&*reinterpret_cast<__int64*>(0x144E3A490 + 8), 0, 0x78680ui64 - 8); } } + + utils::hook::invoke(0x140C55DF0); // SV_InitMP_SetXUIDConfigStrings } void reset_mem_stuff_stub(utils::hook::assembler& a) @@ -439,6 +470,30 @@ namespace party a.jmp(0x140C563E2); } + + void send_user_info() + { + auto userinfostring = utils::hook::invoke(0x1409B2850, 0); // CL_MainMP_GetUserInfoString + auto cmd = utils::string::va("userinfo \"%s\"", userinfostring); + utils::hook::invoke(0x140341430, 0, cmd); // CL_Main_AddReliableCommand + } + + utils::hook::detour cl_prepare_for_map_restart_hook; + void cl_prepare_for_map_restart_stub(const char* mapname, const char* gametype) + { + cl_prepare_for_map_restart_hook.invoke(mapname, gametype); + } + + utils::hook::detour cl_initialize_gamestate_hook; + void cl_initialize_gamestate_stub(int local_client_num) + { + if (!game::Com_IsAnyLocalServerRunning()) + { + send_user_info(); + } + + cl_initialize_gamestate_hook.invoke(local_client_num); + } } void start_map(const std::string& mapname, bool dev) @@ -506,7 +561,18 @@ namespace party command::execute(utils::string::va("seta ui_hardcore %d", hardcore->current.enabled), true); } - perform_game_initialization(); + if (!utils::hook::invoke(0x1409CDCF0) || game::Com_FrontEnd_IsInFrontEnd()) + { + if (game::environment::is_dedi()) + { + perform_game_initialization(game::Dvar_FindVar("party_maxplayers")->current.integer, false); + } + else + { + perform_game_initialization(game::Dvar_FindVar("party_maxplayers")->current.integer, + game::Dvar_FindVar("xblive_privatematch")->current.integer); + } + } console::info("Starting map: %s\n", mapname.data()); @@ -573,7 +639,6 @@ namespace party { command::execute("luiOpenPopup AcceptingInvite", true); - profile_infos::xuid::clear_xuids(); profile_infos::clear_profile_infos(); server_connection_state.host = target; @@ -648,8 +713,15 @@ 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 + cl_prepare_for_map_restart_hook.create(0x1409B3FE0, cl_prepare_for_map_restart_stub); + cl_initialize_gamestate_hook.create(0x1409B2FA0, cl_initialize_gamestate_stub); + + command::add("senduserinfo", []() + { + auto userinfostring = utils::hook::invoke(0x1409B2850, 0); // CL_MainMP_GetUserInfoString + auto cmd = utils::string::va("userinfo \"%s\"", userinfostring); + utils::hook::invoke(0x140341430, 0, cmd); // CL_Main_AddReliableCommand + }); command::add("map", [](const command::params& args) { @@ -667,21 +739,24 @@ namespace party start_map(args.get(1), false); }); - command::add("devmap", [](const command::params& args) + if (!game::environment::is_dedi()) { - if (args.size() != 2) + command::add("devmap", [](const command::params& args) { - return; - } + if (args.size() != 2) + { + return; + } - if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP) - { - command::execute(utils::string::va("spmap %s", args.get(1))); - return; - } + if (game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_SP) + { + command::execute(utils::string::va("spmap %s", args.get(1))); + return; + } - start_map(args.get(1), true); - }); + start_map(args.get(1), true); + }); + } command::add("map_restart", []() { @@ -855,6 +930,7 @@ namespace party info.set("playmode", utils::string::va("%i", game::Com_GameMode_GetActiveGameMode())); info.set("sv_running", utils::string::va("%i", get_dvar_bool("sv_running") && !game::Com_FrontEndScene_IsActive())); info.set("dedicated", utils::string::va("%i", get_dvar_bool("dedicated"))); + info.set("privatematch", utils::string::va("%i", get_dvar_bool("xblive_privatematch"))); info.set("sv_wwwBaseUrl", get_dvar_string("sv_wwwBaseUrl")); info.set("sv_discordImageUrl", get_dvar_string("sv_discordImageUrl")); info.set("sv_discordImageText", get_dvar_string("sv_discordImageText")); @@ -866,7 +942,7 @@ namespace party { for (const auto& file : mod_files) { - const auto hash = get_file_hash(utils::string::va("%s/mod%s", + const auto hash = get_file_hash(utils::string::va("%s/mod%s", fs_game.data(), file.extension.data())); info.set(file.name, hash); } @@ -973,7 +1049,9 @@ namespace party server_discord_info.emplace(discord_info); } - connect_to_party(target, mapname, gametype, sv_maxclients); + const auto privatematch = std::atoi(info.get("privatematch").data()); + + connect_to_party(target, mapname, gametype, sv_maxclients, privatematch); }); } }; diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index ef92888d..5fe1f72d 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -219,6 +219,11 @@ namespace patches { //init_network_dvars_hook.invoke(dvar); } + + void disconnect() + { + utils::hook::invoke(0x140C58E20); // SV_MainMP_MatchEnd + } } class component final : public component_interface @@ -268,8 +273,15 @@ namespace patches // killswitches dvars::override::register_bool("mission_team_contracts_enabled", true, game::DVAR_FLAG_READ); - //dvars::override::register_bool("killswitch_store", true, game::DVAR_FLAG_READ); + dvars::override::register_bool("killswitch_store", false, game::DVAR_FLAG_READ); + dvars::override::register_bool("killswitch_quartermaster", false, game::DVAR_FLAG_READ); + dvars::override::register_bool("killswitch_cod_points", false, game::DVAR_FLAG_READ); + dvars::override::register_bool("killswitch_custom_emblems", false, game::DVAR_FLAG_READ); dvars::override::register_bool("killswitch_matchID", true, game::DVAR_FLAG_READ); + dvars::override::register_bool("killswitch_mp_leaderboards", true, game::DVAR_FLAG_READ); + dvars::override::register_bool("killswitch_cp_leaderboards", true, game::DVAR_FLAG_READ); + dvars::override::register_bool("killswitch_streak_variants", false, game::DVAR_FLAG_READ); + dvars::override::register_bool("killswitch_blood_anvil", false, game::DVAR_FLAG_READ); // announcer packs if (!game::environment::is_dedi()) @@ -297,11 +309,8 @@ namespace patches dvars::override::register_float("gpad_stick_pressed", 0.4f, 0, 1, game::DVAR_FLAG_SAVED); dvars::override::register_float("gpad_stick_pressed_hysteresis", 0.1f, 0, 1, game::DVAR_FLAG_SAVED); - // block changing name in-game - utils::hook::set(0x140C4DF90, 0xC3); - // disable host migration - utils::hook::set(0x140C5A200, 0xC3); + utils::hook::jump(0x140C5A200, disconnect); // precache is always allowed utils::hook::set(0x1406D5280, 0xC301B0); // NetConstStrings_IsPrecacheAllowed diff --git a/src/client/component/profile_infos.cpp b/src/client/component/profile_infos.cpp index cdaafb03..2dd1cb7d 100644 --- a/src/client/component/profile_infos.cpp +++ b/src/client/component/profile_infos.cpp @@ -37,38 +37,12 @@ namespace profile_infos return info; } - std::unordered_set get_connected_client_xuids() - { - if (!game::Com_IsAnyLocalServerRunning()) // is_host() - { - return {}; - } - - std::unordered_set xuids{}; - - const auto* svs_clients = *game::svs_clients; - for (unsigned int i = 0; i < *game::svs_numclients; ++i) - { - if (svs_clients[i].header.state >= 1) - { - xuids.emplace(xuid::get_client_xuid(i)); - } - } - - return xuids; - } - void set_playercardcache_to_download(const std::uint64_t user_id) { game::XUID xuid{ user_id }; game::PlayercardCache_AddToDownload(0, xuid); *game::g_DWPlayercardCacheDownloadTaskStage = game::PLAYERCARD_CACHE_TASK_STAGE_WAITING; } - - void set_client_xuid_to_session(game::SessionData* session, const std::uint32_t client_index) - { - session->dyn.users[client_index].xuid = xuid::get_client_xuid(client_index); - } } profile_info::profile_info(utils::byte_buffer& buffer) @@ -107,16 +81,6 @@ namespace profile_infos }); } - void remove_profile_info_by_client_index(const std::uint32_t client_index) - { - const auto user_id = xuid::get_client_xuid(client_index); - if (!user_id) - { - return; - } - remove_profile_info(user_id); - } - void send_profile_info(const game::netadr_s& address, const std::string& data) { game::fragment_handler::fragment_data(data.data(), data.size(), [&address](const utils::byte_buffer& buffer) @@ -207,12 +171,10 @@ namespace profile_infos { if (svs_clients[i].header.state >= 1 && !game::SV_ClientIsBot(i) && game::Session_IsHost(game::SV_MainMP_GetServerLobby(), i)) { - assert(i == 0); - auto self = load_profile_info(); if (self.has_value()) { - send_profile_info(addr, xuid::get_client_xuid(i), self.value()); + send_profile_info(addr, steam::SteamUser()->GetSteamID().bits, self.value()); break; } } @@ -245,135 +207,12 @@ namespace profile_infos }); } - namespace xuid - { - client_xuid_array client_xuids{}; - - void add_client_xuid(const std::uint32_t& client_index, const std::uint64_t& xuid) - { - if (client_xuids[client_index] && client_xuids[client_index] != xuid) - { - remove_profile_info(client_xuids[client_index]); // remove profile if it exists - } - - client_xuids[client_index] = xuid; - - set_client_xuid_to_session(game::SV_MainMP_GetServerLobby(), client_index); - } - - std::uint64_t get_client_xuid(const std::uint32_t& client_index) - { - if (client_xuids[client_index]) - { - // returns xuid for player. this must be on both the client & server - // client recieves data for this via playerXuid packet - return client_xuids[client_index]; - } - - return static_cast(0); - } - - void remove_client_xuid(const std::uint32_t& client_index) - { - client_xuids[client_index] = 0; - } - - void clear_xuids() - { - for (auto& xuid : client_xuids) - { - xuid = 0; - } - } - - client_xuid_array get_xuids() - { - return client_xuids; - } - - void send_xuid(const game::netadr_s& addr, const std::uint64_t xuid, const std::uint32_t client_index) - { - utils::byte_buffer buffer{}; - buffer.write(client_index); - buffer.write(xuid); - - const std::string data = buffer.move_buffer(); - - game::fragment_handler::fragment_data(data.data(), data.size(), [&](const utils::byte_buffer& buffer) - { - network::send(addr, "playerXuid", buffer.get_buffer()); - }); - } - - void send_xuid_to_all_clients(const std::uint64_t xuid, const std::uint32_t& client_index) - { - const auto* svs_clients = *game::svs_clients; - for (unsigned int i = 0; i < *game::svs_numclients; ++i) - { - if (svs_clients[i].header.state >= 1 && !game::SV_ClientIsBot(i) && !game::Session_IsHost(game::SV_MainMP_GetServerLobby(), i)) - { - send_xuid(svs_clients[i].remoteAddress, xuid, client_index); - } - } - } - - void send_all_xuids(const game::netadr_s& addr) - { - int i = 0; - for (const auto xuid : xuid::get_xuids()) - { - if (xuid == 0) - { - i++; - continue; - } - send_xuid(addr, xuid, i++); - } - - if (!game::environment::is_dedi()) - { - // send self xuid here too - send_xuid(addr, steam::SteamUser()->GetSteamID().bits, 0); - } - } - } - namespace { - utils::hook::detour client_connect_hook; - const char* client_connect_stub(int client_num, unsigned __int16 script_pers_id) - { - auto result = client_connect_hook.invoke(client_num, script_pers_id); - - if (game::SV_ClientIsBot(client_num)) - { - return result; - } - - const auto client = game::svs_clients[client_num]; - std::uint64_t xuid{}; - game::StringToXUID(client->playerGuid, &xuid); - - xuid::add_client_xuid(client_num, xuid); // add to self - - // don't send if client is self - if (client_num == 0 && !game::environment::is_dedi() && game::Com_IsAnyLocalServerRunning()) - { - return result; - } - - xuid::send_xuid_to_all_clients(xuid, client_num); // add to all connected - xuid::send_all_xuids(client->remoteAddress); - - return result; - } - utils::hook::detour session_unregister_remote_player_hook; void session_unregister_remote_player_stub(game::SessionData* session, const int slot) { session_unregister_remote_player_hook.invoke(session, slot); - - set_client_xuid_to_session(session, slot); } } @@ -382,12 +221,9 @@ namespace profile_infos public: void post_unpack() override { - client_connect_hook.create(0x140AFFF10, client_connect_stub); + session_unregister_remote_player_hook.create(0x140C73970, session_unregister_remote_player_stub); - // comment out this, since i think i fixed this indirectly with a patch from party.cpp - //session_unregister_remote_player_hook.create(0x140C73970, session_unregister_remote_player_stub); - - dvars::override::register_int("playercard_cache_validity_life", 5000, 0, 3600000, 0x0); // 5sec + //dvars::override::register_int("playercard_cache_validity_life", 5000, 0, 3600000, 0x0); // 5sec network::on("profileInfo", [](const game::netadr_s& client_addr, const std::string_view& data) { @@ -410,29 +246,6 @@ namespace profile_infos set_playercardcache_to_download(user_id); } }); - - network::on("playerXuid", [](const game::netadr_s& server_addr, const std::string_view& data) - { - utils::byte_buffer buffer(data); - std::string final_packet{}; - if (!game::fragment_handler::handle(server_addr, buffer, final_packet)) - { - return; - } - - buffer = utils::byte_buffer(final_packet); - - const auto client_index = buffer.read(); - const auto xuid = buffer.read(); - - if (!game::Com_IsAnyLocalServerRunning() && server_addr.addr != party::get_server_connection_state().host.addr) - { - console::debug("playerXuid call from an unknown address\n"); - return; - } - - xuid::add_client_xuid(client_index, xuid); - }); } }; } diff --git a/src/client/component/profile_infos.hpp b/src/client/component/profile_infos.hpp index 3d60ba49..2a2899ad 100644 --- a/src/client/component/profile_infos.hpp +++ b/src/client/component/profile_infos.hpp @@ -5,14 +5,6 @@ namespace profile_infos { - namespace xuid - { - using client_xuid_array = std::array; - std::uint64_t get_client_xuid(const std::uint32_t& client_index); - void clear_xuids(); - client_xuid_array get_xuids(); - } - struct profile_info { std::string m_memberplayer_card{}; diff --git a/src/client/component/ranked.cpp b/src/client/component/ranked.cpp index da53d5a8..45d6e2c7 100644 --- a/src/client/component/ranked.cpp +++ b/src/client/component/ranked.cpp @@ -10,6 +10,14 @@ namespace ranked { + namespace + { + bool bots_enabled() + { + return !game::Com_FrontEndScene_IsActive() && game::Com_GameMode_GetActiveGameMode() == game::GAME_MODE_MP; + } + } + class component final : public component_interface { public: @@ -28,6 +36,12 @@ namespace ranked { dvars::override::register_bool("xblive_privatematch", true, game::DVAR_FLAG_REPLICATED); } + + // Always run bots, even if xblive_privatematch is 0 + utils::hook::jump(0x1406E6940, bots_enabled); // BG_BotSystemEnabled + utils::hook::jump(0x1406E6510, bots_enabled); // BG_AISystemEnabled + utils::hook::jump(0x1406E68F0, bots_enabled); // BG_BotFastFileEnabled + utils::hook::jump(0x140C546F0, bots_enabled); // BG_BotsUsingTeamDifficulty } }; } diff --git a/src/client/game/game.hpp b/src/client/game/game.hpp index b391cb6c..3c1c05aa 100644 --- a/src/client/game/game.hpp +++ b/src/client/game/game.hpp @@ -2,7 +2,7 @@ #include "structs.hpp" -#define PROTOCOL 1 +#define PROTOCOL 2 namespace game { diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 24f002ce..5620d41f 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -378,6 +378,9 @@ namespace game WEAK symbol com_frameTime{ 0x1460053C0 }; + WEAK symbol com_num_console_lines{ 0x146006DB0 }; + WEAK symbol com_console_lines{ 0x146006DC0 }; + WEAK symbol s_frontEndScene_state{ 0x144BFF608 }; WEAK symbol bg_weaponDefs{ 0x145210120 }; From 984e5478d23df3be977e609bd3785df81510c182 Mon Sep 17 00:00:00 2001 From: quaK Date: Mon, 12 Aug 2024 01:52:39 +0300 Subject: [PATCH 2/3] fix campaign menu --- .../MainMenu/CampaignMenuButtons.lua | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/data/cdata/ui_scripts/MainMenu/CampaignMenuButtons.lua b/data/cdata/ui_scripts/MainMenu/CampaignMenuButtons.lua index 6eec2c1a..95c9f765 100644 --- a/data/cdata/ui_scripts/MainMenu/CampaignMenuButtons.lua +++ b/data/cdata/ui_scripts/MainMenu/CampaignMenuButtons.lua @@ -1,3 +1,39 @@ +local f0_local0 = function ( f1_arg0 ) + if Engine.HasCompletedAnyLevel( f1_arg0 ) then + return true + end + local f1_local0 = {} + for f1_local1 = 0, Engine.TableGetRowCount( CSV.levels.file ) - 1, 1 do + local f1_local4 = CSV.ReadRow( CSV.levels, f1_local1 ) + local f1_local5 = f1_local4.name + if not Engine.GetDvarBool( "lui_checkIfLevelInFileSystem" ) or Engine.IsLevelInFileSystem and Engine.IsLevelInFileSystem( f1_local5 ) then + f1_local0[#f1_local0 + 1] = { + buttonLabel = f1_local4.string, + levelName = f1_local5, + objectiveText = f1_local4.desc, + levelNumber = f1_local4.ref, + completedLevelIndex = f1_local4.completedRef, + image = f1_local4.image + } + end + end + local f1_local1 = LUI.DataSourceFromPlayerData.new( CoD.ProgressionBlob.Gold, CoD.PlayMode.SP ) + local f1_local2 = f1_local1.spData + for f1_local3 = 1, #f1_local0, 1 do + local f1_local7 = f1_local0[f1_local3].levelName + if f1_local7 ~= "europa" then + local f1_local8 = "" + if f1_local2.missionStateData[f1_local7] ~= nil then + f1_local8 = f1_local2.missionStateData[f1_local7]:GetValue( f1_arg0 ) + end + if f1_local8 ~= nil and (f1_local8 == "complete" or f1_local8 == "incomplete") then + return true + end + end + end + return false +end + local f0_local1 = function(arg0) arg0.ResumeButton:SetButtonDisabled(not Engine.CanResumeGame(arg0._controllerIndex)) if not CONDITIONS.IsTrialLicense(arg0) then From 70b3d380d32b401e1c958caf9ceb5a16d4d16785 Mon Sep 17 00:00:00 2001 From: quaK Date: Tue, 13 Aug 2024 16:29:28 +0300 Subject: [PATCH 3/3] fix crash --- src/client/component/party.cpp | 19 +++++++++++-------- src/client/game/symbols.hpp | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp index e0d22534..89dca6ae 100644 --- a/src/client/component/party.cpp +++ b/src/client/component/party.cpp @@ -296,12 +296,12 @@ namespace party bool preloaded_map = false; - void xstartlobby(const int max_clients, const bool private_match) + void xstartlobby() { // Retrieve game variables - const int privateMatch = private_match; //game::Dvar_FindVar("xblive_privatematch")->current.integer; - const int maxPlayers = max_clients; //game::Dvar_FindVar("party_maxplayers")->current.integer; - const int privateClients = 0; //game::Dvar_FindVar("ui_privateClients")->current.integer; + const int privateMatch = game::Dvar_FindVar("xblive_privatematch")->current.integer; + const int maxPlayers = game::Dvar_FindVar("party_maxplayers")->current.integer; + const int privateClients = game::Dvar_FindVar("ui_privateClients")->current.integer; const int availableSpots = maxPlayers - privateClients; // Get party data @@ -331,13 +331,16 @@ namespace party void perform_game_initialization(const int max_clients, const bool private_match) { - xstartlobby(max_clients, private_match); - const auto ui_maxclients = game::Dvar_FindVar("ui_maxclients"); const auto party_maxplayers = game::Dvar_FindVar("party_maxplayers"); game::Dvar_SetInt(ui_maxclients, max_clients); game::Dvar_SetInt(party_maxplayers, max_clients); + const auto xblive_privatematch = game::Dvar_FindVar("xblive_privatematch"); + game::Dvar_SetBool(xblive_privatematch, private_match); + + xstartlobby(); + command::execute("uploadstats", true); } @@ -550,7 +553,7 @@ namespace party command::execute(utils::string::va("seta ui_mapname %s", mapname.data()), true); auto* gametype = game::Dvar_FindVar("g_gametype"); - if (gametype && gametype->current.string) + if (gametype && gametype->current.string && gametype->current.string != "frontend"s) { command::execute(utils::string::va("seta ui_gametype %s", gametype->current.string), true); } @@ -561,7 +564,7 @@ namespace party command::execute(utils::string::va("seta ui_hardcore %d", hardcore->current.enabled), true); } - if (!utils::hook::invoke(0x1409CDCF0) || game::Com_FrontEnd_IsInFrontEnd()) + if (!utils::hook::invoke(0x1409CDCF0, game::Lobby_GetPartyData()) || game::Com_FrontEnd_IsInFrontEnd()) { if (game::environment::is_dedi()) { diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 5620d41f..827d71a1 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -125,6 +125,7 @@ namespace game WEAK symbol Dvar_ValueToString{ 0x140CEED00 }; WEAK symbol Dvar_Reset{ 0x140CEC490 }; WEAK symbol Dvar_GenerateChecksum{ 0x140CEA520 }; + WEAK symbol Dvar_SetBool{ 0x140CEC7D0 }; WEAK symbol Dvar_SetInt{ 0x140CED3D0 }; WEAK symbol Dvar_SetFloat{ 0x140CECD90 }; WEAK symbol Dvar_OverrideCheatProtection{ 0x140CEB250 };