diff --git a/data/menu/nullifiedcat/misc/autoparty.xml b/data/menu/nullifiedcat/misc/autoparty.xml index 43bffe63..f1c406de 100755 --- a/data/menu/nullifiedcat/misc/autoparty.xml +++ b/data/menu/nullifiedcat/misc/autoparty.xml @@ -13,7 +13,9 @@ + + diff --git a/include/hacks/AutoParty.hpp b/include/hacks/AutoParty.hpp new file mode 100644 index 00000000..3381ac47 --- /dev/null +++ b/include/hacks/AutoParty.hpp @@ -0,0 +1,4 @@ +namespace hacks::tf2::autoparty +{ +void joinMatch(); +} diff --git a/src/hacks/AutoJoin.cpp b/src/hacks/AutoJoin.cpp index fccb8a92..d1d5b525 100644 --- a/src/hacks/AutoJoin.cpp +++ b/src/hacks/AutoJoin.cpp @@ -105,7 +105,7 @@ void updateSearch() #if not ENABLE_VISUALS if (queue_time.test_and_set(1200000)) { - g_IEngine->ClientCmd_Unrestricted("quit"); //lol + g_IEngine->ClientCmd_Unrestricted("quit"); // lol } #endif } diff --git a/src/hacks/AutoParty.cpp b/src/hacks/AutoParty.cpp index 3ae7d2a2..92b87e6e 100644 --- a/src/hacks/AutoParty.cpp +++ b/src/hacks/AutoParty.cpp @@ -82,11 +82,15 @@ static settings::Boolean ipc_mode{ "autoparty.ipc-mode", "false" }; static settings::Int ipc_count{ "autoparty.ipc-count", "0" }; // How often to run the autoparty routine, in seconds static settings::Int timeout{ "autoparty.run-frequency", "60" }; +// Should we have bots bypass kicks? +static settings::Boolean kickbypass{ "autoparty.kick-bypass", "false" }; // Only run the autoparty routine once every N seconds static Timer routine_timer{}; // Populated by the routine when empty and by configuration changes static std::vector party_hosts = {}; +static settings::Boolean no_autojoin("misc.remove_invite_timer", "false"); + // ha ha macros go brr #define log(...) \ if (*autoparty_log) \ @@ -225,6 +229,10 @@ void party_routine() re::CTFPartyClient *client = re::CTFPartyClient::GTFPartyClient(); if (client) { + // Toggle anti-kick as needed + if (kickbypass) + no_autojoin = !is_host(); + int members = client->GetNumMembers(); // Are we in a party? if (members == 1) @@ -255,16 +263,9 @@ void party_routine() // Get a list of party members, then check each one to determine the leader std::vector members = client->GetPartySteamIDs(); uint32 leader_id = 0; - for (int i = 0; i < members.size(); i++) - { - CSteamID id = CSteamID(members[i], EUniverse::k_EUniversePublic, EAccountType::k_EAccountTypeIndividual); - // Are you my mummy? - if (client->GetCurrentPartyLeader(id)) - { - leader_id = members[i]; - break; - } - } + CSteamID id; + client->GetCurrentPartyLeader(id); + leader_id = id.GetAccountID(); if (leader_id == g_ISteamUser->GetSteamID().GetAccountID()) { // Great, let's manage it @@ -286,7 +287,7 @@ void party_routine() if (pl.state == playerlist::k_EState::RAGE) { std::string message = "Kicking Steam32 ID " + std::to_string(members[i]) + " from the party because they are set to RAGE"; - logging::Info("AutoParty: %s", message); + logging::Info("AutoParty: %s", message.c_str()); if (*message_kicks) client->SendPartyChat(message.c_str()); CSteamID id = CSteamID(members[i], EUniverse::k_EUniversePublic, EAccountType::k_EAccountTypeIndividual); @@ -310,7 +311,7 @@ void party_routine() { int num_to_kick = members.size() - *max_size; std::string message = "Kicking " + std::to_string(num_to_kick) + " party members because there are " + std::to_string(members.size()) + " out of " + std::to_string(*max_size) + " allowed members"; - logging::Info("AutoParty: %s", message); + logging::Info("AutoParty: %s", message.c_str()); if (*message_kicks) client->SendPartyChat(message.c_str()); for (int i = 0; i < num_to_kick; i++) @@ -352,9 +353,109 @@ void party_routine() } } -static InitRoutine init([]() { - host_list.installChangeCallback([](settings::VariableBase &var, std::string after) { repopulate(after); }); - ipc_mode.installChangeCallback([](settings::VariableBase &var, bool after) { party_hosts.clear(); }); - EC::Register(EC::Paint, party_routine, "paint_autoparty", EC::average); -}); +#define IP_STARTSTR "PB_IP" + +// Received party message +void partyChatMessage(IGameEvent *event) +{ + if (!event->GetString("text")) + return; + + // Only parse actual chat messages + if (event->GetInt("type") != 1) + return; + + re::CTFPartyClient *client = re::CTFPartyClient::GTFPartyClient(); + + if (!client) + return; + // And are we actually the leader? + // Get a list of party members, then check each one to determine the leader + uint32 leader_id = 0; + CSteamID id; + client->GetCurrentPartyLeader(id); + leader_id = id.GetAccountID(); + + // Party leader doesn't care, they just join + if (leader_id == g_ISteamUser->GetSteamID().GetAccountID() || client->GetNumMembers() == 1) + return; + + std::string chat_message = event->GetString("text"); + // Found Message about server IP + if (chat_message.find(IP_STARTSTR) == 0) + { + auto ip_string = "connect " + chat_message.substr(sizeof(IP_STARTSTR) - 1); + g_IEngine->ClientCmd_Unrestricted(ip_string.c_str()); + } +} + +class PartyEventListener : public IGameEventListener2 +{ + virtual void FireGameEvent(IGameEvent *event) + { + if (enabled && kickbypass) + partyChatMessage(event); + } +}; + +static PartyEventListener party_listener; + +void joinMatch() +{ + if (!enabled || !kickbypass) + return; + + re::CTFPartyClient *client = re::CTFPartyClient::GTFPartyClient(); + + if (!client) + return; + + CSteamID id; + client->GetCurrentPartyLeader(id); + if (id.GetAccountID() != g_ISteamUser->GetSteamID().GetAccountID()) + return; + + INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo(); + std::string party_string = IP_STARTSTR; + party_string.append(ch->GetAddress()); + + client->SendPartyChat(party_string.c_str()); +} + +static InitRoutine init( + []() + { + static BytePatch removeInviteTime(gSignatures.GetClientSignature, "55 89 e5 57 56 53 83 ec ? 8b ? ? 89 1c ? e8 ? ? ? ? f7 ? ? ? ? ? fd", 0x00, { 0xC3 }); + if (*no_autojoin) + removeInviteTime.Patch(); + no_autojoin.installChangeCallback( + [](settings::VariableBase &, bool new_val) + { + if (new_val) + removeInviteTime.Patch(); + else + removeInviteTime.Shutdown(); + }); + + host_list.installChangeCallback([](settings::VariableBase &var, std::string after) { repopulate(after); }); + ipc_mode.installChangeCallback([](settings::VariableBase &var, bool after) { party_hosts.clear(); }); + kickbypass.installChangeCallback( + [](settings::VariableBase &var, bool after) + { + if (*var && !after) + no_autojoin = false; + }); + EC::Register(EC::Paint, party_routine, "paint_autoparty", EC::average); + + g_IEventManager2->AddListener(&party_listener, "party_chat", false); + + EC::Register( + EC::Shutdown, + []() + { + removeInviteTime.Shutdown(); + g_IEventManager2->RemoveListener(&party_listener); + }, + "shutdown_autoparty"); + }); } // namespace hacks::tf2::autoparty diff --git a/src/hooks/Paint.cpp b/src/hooks/Paint.cpp index b55d4a50..3e4fe515 100644 --- a/src/hooks/Paint.cpp +++ b/src/hooks/Paint.cpp @@ -7,6 +7,7 @@ #include #include +#include "AutoParty.hpp" #include "common.hpp" #include "hitrate.hpp" #include "hack.hpp" @@ -41,6 +42,7 @@ DEFINE_HOOKED_METHOD(Paint, void, IEngineVGui *this_, PaintMode_t mode) #if ENABLE_IPC ipc::UpdateServerAddress(); #endif + hacks::tf2::autoparty::joinMatch(); } if (mode & PaintMode_t::PAINT_UIPANELS) diff --git a/src/reclasses/CTFPartyClient.cpp b/src/reclasses/CTFPartyClient.cpp index 180c7c60..efc2b485 100644 --- a/src/reclasses/CTFPartyClient.cpp +++ b/src/reclasses/CTFPartyClient.cpp @@ -50,7 +50,7 @@ bool re::CTFPartyClient::BCanQueueForStandby(re::CTFPartyClient *this_) { typedef bool (*BCanQueueForStandby_t)(re::CTFPartyClient *); static uintptr_t addr = gSignatures.GetClientSignature("55 89 E5 53 83 EC 24 8B 5D 08 80 7B 46 00 75 40 8B 4B 38 85 C9 74 39 " - "E8 ? ? ? ? 89 04 24 E8 ? ? ? ? 84 C0 75 28"); + "E8 ? ? ? ? 89 04 24 E8 ? ? ? ? 84 C0 75 28"); static BCanQueueForStandby_t BCanQueueForStandby_fn = BCanQueueForStandby_t(addr); return BCanQueueForStandby_fn(this_); @@ -115,7 +115,7 @@ int re::CTFPartyClient::BInvitePlayerToParty(CSteamID steamid) { typedef int (*BInvitePlayerToParty_t)(re::CTFPartyClient *, CSteamID, bool); static uintptr_t addr = gSignatures.GetClientSignature("55 89 E5 57 56 53 81 EC ? ? ? ? 8B 45 ? 8B 5D ? 8B 55 ? 89 85" - "65 A1 ? ? ? ? 89 45 ? 31 C0 8B 45"); + "65 A1 ? ? ? ? 89 45 ? 31 C0 8B 45"); static BInvitePlayerToParty_t BInvitePlayerToParty_fn = BInvitePlayerToParty_t(addr); return BInvitePlayerToParty_fn(this, steamid, false); } @@ -160,7 +160,7 @@ int re::CTFPartyClient::KickPlayer(CSteamID steamid) } bool re::CTFPartyClient::GetCurrentPartyLeader(CSteamID &id) { - uintptr_t party = *reinterpret_cast(reinterpret_cast(this) + 0x30); + uintptr_t party = *reinterpret_cast(reinterpret_cast(this) + 0x18); if (!party) return false;