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;