From a02f4386e45e6f2c8f5325f73028fee07baaae55 Mon Sep 17 00:00:00 2001 From: nooperation Date: Sun, 11 Sep 2022 04:10:07 -0400 Subject: [PATCH] Added EnumPlayers functionality from newer d2hackit Updated follow to utilize EnumPlayers --- D2Hackit/Core/Server20.cpp | 18 ++++++++++++ D2Hackit/Includes/ClientCore.cpp | 1 + D2Hackit/Includes/CommonStructs.h | 5 ++++ D2Hackit/Includes/D2HackIt.h | 2 ++ D2Hackit/Modules/follow/follow.cpp | 46 ++++++++++++++++++++---------- D2Hackit/Modules/follow/follow.h | 1 - D2Hackit/Modules/follow/main.cpp | 26 ----------------- 7 files changed, 57 insertions(+), 42 deletions(-) diff --git a/D2Hackit/Core/Server20.cpp b/D2Hackit/Core/Server20.cpp index 3dbd64e..4c1fc28 100644 --- a/D2Hackit/Core/Server20.cpp +++ b/D2Hackit/Core/Server20.cpp @@ -1057,6 +1057,24 @@ BOOL EXPORT IsInteractedWithWP() return !(*p_D2CLIENT_IsNotInteractedWithWP); } +BOOL EXPORT EnumPlayers(fnEnumPlayerProc lpfn, LPARAM lParam) +{ + if (lpfn == NULL || p_D2CLIENT_FirstRosterUnit == NULL) + return FALSE; + + for (Roster* p = *p_D2CLIENT_FirstRosterUnit; p; p = p->ptNext) + { + if (p->PlayerId == GetSafePlayerID()) + continue; + + DWORD dwPvpFlags = 0; + BYTE iMapID =(BYTE)p->LevelId; + if (!lpfn(p->PlayerId, p->Name, p->ClassId, dwPvpFlags, iMapID, lParam)) + return FALSE; + } + + return TRUE; +} // -- B DWORD EXPORT GetSpellName(WORD wSpell, LPSTR lpszBuffer, DWORD dwMaxChars) diff --git a/D2Hackit/Includes/ClientCore.cpp b/D2Hackit/Includes/ClientCore.cpp index 4cef2f5..16545ec 100644 --- a/D2Hackit/Includes/ClientCore.cpp +++ b/D2Hackit/Includes/ClientCore.cpp @@ -275,6 +275,7 @@ BOOL PRIVATE SetupClient(HMODULE hModule, LPCSTR szModule) BIND_AND_CHECK(IsInteractedWithWP); BIND_TO_PLAYER(GetSpellChargesReal); + BIND_AND_CHECK(EnumPlayers); // Was missing, thanks to LordTerror and Tiamat for the bug report // -- B // Bind player functions diff --git a/D2Hackit/Includes/CommonStructs.h b/D2Hackit/Includes/CommonStructs.h index 07366e5..527552b 100644 --- a/D2Hackit/Includes/CommonStructs.h +++ b/D2Hackit/Includes/CommonStructs.h @@ -250,6 +250,9 @@ typedef const tagGameUnit* LPCGAMEUNIT; // Unit enumeration callback definition typedef BOOL (CALLBACK *fnEnumUnitProc)(LPCGAMEUNIT lpUnit, LPARAM lParam); +// Player enumeration callback definition +typedef BOOL (CALLBACK *fnEnumPlayerProc)(DWORD dwPlayerID, LPCSTR lpszPlayerName, DWORD dwPlayerClass, DWORD dwPvpFlags, BYTE iMapID, LPARAM lParam); + ////////////////////////////////////////////////////////////////////// // PresetUnit(Caves, Stairs, Dens, Towers, Entrances, Izual, Hephasto, Countess Chest, etc...) ////////////////////////////////////////////////////////////////////// @@ -458,6 +461,7 @@ typedef BOOL(__cdecl *fnIsInteractedWithNPC)(); typedef DWORD(__cdecl *fnGetInteractedNPCClassID)(); typedef DWORD(__cdecl *fnGetInteractedWPUniqueID)(); typedef BOOL(__cdecl *fnIsInteractedWithWP)(); +typedef BOOL (__cdecl *fnEnumPlayers)(fnEnumPlayerProc lpfn, LPARAM lParam); // -- B typedef struct functionentrypoints_t { @@ -572,6 +576,7 @@ typedef struct functionentrypoints_t fnGetInteractedNPCClassID GetInteractedNPCClassID; fnGetInteractedWPUniqueID GetInteractedWPUniqueID; fnIsInteractedWithWP IsInteractedWithWP; + fnEnumPlayers EnumPlayers; // 2.00 (Abin) // -- B } FUNCTIONENTRYPOINTS, *PFUNCTIONENTRYPOINTS; diff --git a/D2Hackit/Includes/D2HackIt.h b/D2Hackit/Includes/D2HackIt.h index b24d826..324ddb8 100644 --- a/D2Hackit/Includes/D2HackIt.h +++ b/D2Hackit/Includes/D2HackIt.h @@ -311,6 +311,8 @@ DWORD EXPORT GetInteractedNPCClassID(); DWORD EXPORT GetInteractedWPUniqueID(); BOOL EXPORT IsInteractedWithWP(); DWORD EXPORT GetSpellChargesReal(WORD wSpellID); + +BOOL EXPORT EnumPlayers(fnEnumPlayerProc lpfn, LPARAM lParam); // -- B BOOL EXPORT LeftClick(long x, long y); diff --git a/D2Hackit/Modules/follow/follow.cpp b/D2Hackit/Modules/follow/follow.cpp index 630bbe3..c55e60f 100644 --- a/D2Hackit/Modules/follow/follow.cpp +++ b/D2Hackit/Modules/follow/follow.cpp @@ -2,6 +2,7 @@ #include "Follow.h" BOOL CALLBACK enumObjectsForPortal(LPCGAMEUNIT lpUnit, LPARAM lParam); +BOOL CALLBACK FindMaster(DWORD dwPlayerID, LPCSTR lpszPlayerName, DWORD dwPlayerClass, DWORD dwPvpFlags, BYTE iMapID, LPARAM lParam); Follow::Follow() @@ -9,7 +10,6 @@ Follow::Follow() this->currentState = State::Uninitialized; this->fleeLoaded = false; this->master = ""; - this->playerIdToNameMap.clear(); this->portalOwnershipMap.clear(); } @@ -39,24 +39,34 @@ void Follow::Abort() server->GameStringf("˙c5Follow˙c0: Aborted"); } +struct FindMasterPayload +{ + std::string masterName; + uint32_t masterId; + bool isSuccess; +}; void Follow::OnChatMessage(const std::string_view& from, const std::string_view& message) { if (message == "follow") { - this->master = from; - this->masterId = 0; + FindMasterPayload payload; + payload.isSuccess = false; + payload.masterId = 0; + payload.masterName = from; + + server->EnumPlayers(FindMaster, (LPARAM)&payload); - for (const auto& item : this->playerIdToNameMap) + if (!payload.isSuccess) { - if (item.second == this->master) - { - this->masterId = item.first; - break; - } + server->GameStringf("˙c5Follow˙c0: Failed to find master '%s'", from.data()); + me->Say("I cannot find you. Please rejoin or something"); + return; } - server->GameStringf("˙c5Follow˙c0: Now following %s (id = %d)", this->master.c_str(), this->masterId); + this->master = payload.masterName; + this->masterId = payload.masterId; + server->GameStringf("˙c5Follow˙c0: Now following %s (id = %d)", this->master.c_str(), this->masterId); char buff[128] = {}; sprintf_s(buff, "Ok, now following %s", this->master.c_str()); me->Say(&buff[0]); @@ -104,6 +114,7 @@ struct Packet_CS_InteractWithEntity DWORD ID; }; + bool Follow::FindAndUsePortal() { std::vector foundPortals; @@ -115,6 +126,9 @@ bool Follow::FindAndUsePortal() return false; } + + server->EnumPlayers(FindMaster, 0); + for (auto const& portalId : foundPortals) { auto const& portalInfo = this->portalOwnershipMap.find(portalId); @@ -161,17 +175,19 @@ void Follow::OnTick() } -void Follow::UpdatePlayerInfo(DWORD playerId, const std::string_view& playerName) +BOOL CALLBACK FindMaster(DWORD dwPlayerID, LPCSTR lpszPlayerName, DWORD dwPlayerClass, DWORD dwPvpFlags, BYTE iMapID, LPARAM lParam) { - if (playerName == this->master && playerId != this->masterId) + auto payload = (FindMasterPayload *)lParam; + if (lpszPlayerName == payload->masterName) { - this->masterId = playerId; + payload->masterId = dwPlayerID; + payload->isSuccess = true; + return FALSE; } - this->playerIdToNameMap[playerId] = playerName; + return TRUE; } - BOOL CALLBACK enumObjectsForPortal(LPCGAMEUNIT lpUnit, LPARAM lParam) { auto foundPortals = (std::vector*)lParam; diff --git a/D2Hackit/Modules/follow/follow.h b/D2Hackit/Modules/follow/follow.h index 8ec9367..da83a33 100644 --- a/D2Hackit/Modules/follow/follow.h +++ b/D2Hackit/Modules/follow/follow.h @@ -44,7 +44,6 @@ class Follow std::string master; DWORD masterId; - std::map playerIdToNameMap; std::map portalOwnershipMap; }; diff --git a/D2Hackit/Modules/follow/main.cpp b/D2Hackit/Modules/follow/main.cpp index 64ca2c1..12a92ad 100644 --- a/D2Hackit/Modules/follow/main.cpp +++ b/D2Hackit/Modules/follow/main.cpp @@ -48,9 +48,6 @@ DWORD EXPORT OnGamePacketBeforeReceived(BYTE* aPacket, DWORD aLen) { if (aPacket[0] == 0x26) { - const auto unknownA = ((DWORD *)&aPacket[4]); - server->GameStringf("Unknown = %d", unknownA); - const auto source = std::string_view((char*)(&aPacket[10])); const auto message = std::string_view((char*)(&aPacket[10] + source.length() + 1)); @@ -80,29 +77,6 @@ DWORD EXPORT OnGamePacketBeforeReceived(BYTE* aPacket, DWORD aLen) follow.OnPortalOwnershipUpdate(ownershipPacket->OwnerID, ownershipPacket->OwnerName, ownershipPacket->LocalID); } - // player joined - if(aPacket[0] == 0x5b) - { - // Player info packet - //5B 24 00 XX XX XX XX 01 (Char Name) 00 01 00 FF FF 00 00 00 00 00 00 00 00 - //(WORD) Packet Lengh - //(DWORD) Player's ID - //(BYTE) Player's Class - //(BYTE[16]) Character's Name - //(WORD) Character's Level - //(WORD) Party Number (0xFFFF = none) - //(VOID) Null-Padding - - const unsigned short length = *((unsigned short*)(aPacket+1)); - const unsigned int playerId = *((unsigned int*)(aPacket+3)); - const unsigned char playerClass = *((unsigned char*)(aPacket+7)); - const char *playerName = (char *)(aPacket+8); - const unsigned short playerLevel = *((unsigned short*)(aPacket + 24)); - const unsigned short playerPartyId = *((unsigned short*)(aPacket + 26)); - - follow.UpdatePlayerInfo(playerId, playerName); - } - return aLen; }