diff --git a/D2Hackit/Modules/autoSell/Resources/AutoSell_items.txt b/D2Hackit/Modules/autoSell/Resources/AutoSell_items.txt index a76f9d1..614f46f 100644 --- a/D2Hackit/Modules/autoSell/Resources/AutoSell_items.txt +++ b/D2Hackit/Modules/autoSell/Resources/AutoSell_items.txt @@ -1,3 +1 @@ fkn Fake Note -po3 Mountain Dew -po4 Nirvana Grass \ No newline at end of file diff --git a/D2Hackit/Modules/autoStocker/AutoStocker.cpp b/D2Hackit/Modules/autoStocker/AutoStocker.cpp index a76ae64..e2bd29a 100644 --- a/D2Hackit/Modules/autoStocker/AutoStocker.cpp +++ b/D2Hackit/Modules/autoStocker/AutoStocker.cpp @@ -54,6 +54,9 @@ bool AutoStocker::Init(bool useChat) IsTransmutingUnidentifiedSmallCharms = (GetPrivateProfileInt("Autostocker", "NonIDSmallCharms", 0, CONFIG_FILE) == 1); IsTransmutingUnidentifiedLargeCharms = (GetPrivateProfileInt("Autostocker", "NonIDLargeCharms", 0, CONFIG_FILE) == 1); IsTransmutingUnidentifiedGrandCharms = (GetPrivateProfileInt("Autostocker", "NonIDGrandCharms", 0, CONFIG_FILE) == 1); + IgnoreIdentifiedSetRingsAndAmulets = (GetPrivateProfileInt("Autostocker", "IgnoreIdentifiedSetRingsAndAmulets", 0, CONFIG_FILE) == 1); + MinPrefixCount = GetPrivateProfileInt("Autostocker", "PrefixCount", 0, CONFIG_FILE); + MinSuffixCount = GetPrivateProfileInt("Autostocker", "SuffixCount", 0, CONFIG_FILE); return true; } @@ -800,6 +803,9 @@ bool AutoStocker::ReadAffixConfig(const std::string &configPath, std::unordered_ return true; } +#include "../../Includes/itemPrefix.h" +#include "../../Includes/ItemSuffix.h" + /// /// Determines if this item has a good affix and should be kept /// @@ -817,19 +823,60 @@ bool AutoStocker::CheckItemAffix(const ITEM &item) if(goodPrefix.count(item.wPrefix[i]) > 0) { goodPrefixCount++; - //server->GameStringf("�c;Prefix�c0 %s: %s", Prefix[item.wPrefix[i]], PrefixDetails[item.wPrefix[i]]); + //server->GameStringf("�c;AS Prefix�c0 %s: %s", Prefix[item.wPrefix[i]], PrefixDetails[item.wPrefix[i]]); } if(goodSuffix.count(item.wSuffix[i]) > 0) { goodSuffixCount++; - //server->GameStringf("�c:Suffix�c0 %s: %s", Suffix[item.wSuffix[i]], SuffixDetails[item.wSuffix[i]]); + //server->GameStringf("�c:AS Suffix�c0 %s: %s", Suffix[item.wSuffix[i]], SuffixDetails[item.wSuffix[i]]); } } } + if (IsRingAmulet(item.szItemCode)) + { + if (item.iSocketed) + { + return true; + } + if (item.iPersonalized) + { + return true; + } + + //server->GameStringf("Suffix=%d Prefix=%d Result=(%d)", goodPrefixCount, goodSuffixCount, (goodPrefixCount + goodSuffixCount) >= 2); + return (goodPrefixCount + goodSuffixCount) >= 2; + } + return goodPrefixCount >= 1 || goodSuffixCount >= 1; } +bool AutoStocker::IsRingAmulet(LPCSTR itemCode) +{ + if(strcmp(itemCode, "amu") == 0 || + strcmp(itemCode, "rin") == 0 || + strcmp(itemCode, "zrn") == 0 || + strcmp(itemCode, "srn") == 0 || + strcmp(itemCode, "nrn") == 0 || + strcmp(itemCode, "prn") == 0 || + strcmp(itemCode, "brg") == 0 || + strcmp(itemCode, "drn") == 0 || + strcmp(itemCode, "arn") == 0 || + strcmp(itemCode, "zam") == 0 || + strcmp(itemCode, "sam") == 0 || + strcmp(itemCode, "nam") == 0 || + strcmp(itemCode, "pam") == 0 || + strcmp(itemCode, "bam") == 0 || + strcmp(itemCode, "dam") == 0 || + strcmp(itemCode, "aam") == 0) + + { + return true; + } + + return false; +} + /// /// Determines if specified item should be stored in the gem can /// @@ -915,7 +962,7 @@ bool AutoStocker::IsCrystalItem(LPCSTR itemCode) /// Determines if specified item should be stored in the rerolling orb /// /// Item being checked. -/// true if item should be cubed a stocker. +/// true if item should be destroyed bool AutoStocker::IsRerollItem(const ITEM &item) { if(!item.iIdentified) @@ -953,6 +1000,14 @@ bool AutoStocker::IsRerollItem(const ITEM &item) } } + if (item.iIdentified) + { + if (item.iQuality == ITEM_LEVEL_SET && IgnoreIdentifiedSetRingsAndAmulets && IsRingAmulet(item.szItemCode)) + { + return false; + } + } + if(item.iQuality == ITEM_LEVEL_MAGIC || (item.iQuality == ITEM_LEVEL_SET && transmuteSet) || (item.iQuality == ITEM_LEVEL_RARE && transmuteRare) || diff --git a/D2Hackit/Modules/autoStocker/AutoStocker.h b/D2Hackit/Modules/autoStocker/AutoStocker.h index d75d2c7..de9a9a3 100644 --- a/D2Hackit/Modules/autoStocker/AutoStocker.h +++ b/D2Hackit/Modules/autoStocker/AutoStocker.h @@ -77,6 +77,7 @@ class AutoStocker bool IsCrystalItem(LPCSTR itemCode); bool IsGemCanItem(LPCSTR itemCode); bool IsRerollItem(const ITEM &item); + bool AutoStocker::IsRingAmulet(LPCSTR itemCode); std::vector> itemsToTransmute; std::vector restockers; @@ -93,9 +94,12 @@ class AutoStocker bool IsTransmutingUnidentifiedSmallCharms; bool IsTransmutingUnidentifiedLargeCharms; bool IsTransmutingUnidentifiedGrandCharms; + bool IgnoreIdentifiedSetRingsAndAmulets; int MaxUnidentifiedSCharmLevel; int MaxUnidentifiedLCharmLevel; int MaxUnidentifiedGCharmLevel; + int MinPrefixCount; + int MinSuffixCount; unsigned int currentItem; unsigned int currentStocker; diff --git a/D2Hackit/Modules/autoStocker/Resources/autostockerMisc.ini b/D2Hackit/Modules/autoStocker/Resources/autostockerMisc.ini index c090878..e51f8cd 100644 --- a/D2Hackit/Modules/autoStocker/Resources/autostockerMisc.ini +++ b/D2Hackit/Modules/autoStocker/Resources/autostockerMisc.ini @@ -8,4 +8,5 @@ MaxUnidentifiedLCharmLvl=44 MaxUnidentifiedGCharmLvl=44 NonIDSmallCharms = 0 NonIDLargeCharms = 0 -NonIDGrandCharms = 0 \ No newline at end of file +NonIDGrandCharms = 0 +IgnoreIdentifiedSetRingsAndAmulets = 1 diff --git a/D2Hackit/Modules/filter/ItemFilter.cpp b/D2Hackit/Modules/filter/ItemFilter.cpp index 3279a93..438cf66 100644 --- a/D2Hackit/Modules/filter/ItemFilter.cpp +++ b/D2Hackit/Modules/filter/ItemFilter.cpp @@ -191,6 +191,7 @@ bool ItemFilter::LoadItemMap(const std::string &fileName, std::unordered_mapGameErrorf("�c:Filter�c0: �c1failed to read the follow item table:�c0 %s", fileName.c_str()); return false; } diff --git a/D2Hackit/Modules/filter/main.cpp b/D2Hackit/Modules/filter/main.cpp index e2daae7..88f659b 100644 --- a/D2Hackit/Modules/filter/main.cpp +++ b/D2Hackit/Modules/filter/main.cpp @@ -78,8 +78,7 @@ BOOL EXPORT OnClientStart() { if(!ItemFilter.LoadItems()) { - server->GameErrorf("Failed to load item tables. Do you have filterTable.txt"); - server->GameErrorf(" in the plugin directory?"); + server->GameErrorf("Failed to load all item tables."); return FALSE; } diff --git a/D2Hackit/Modules/goto/Main.cpp b/D2Hackit/Modules/goto/Main.cpp index c71e192..4f78328 100644 --- a/D2Hackit/Modules/goto/Main.cpp +++ b/D2Hackit/Modules/goto/Main.cpp @@ -97,6 +97,24 @@ bool isLeftHandCasting = false; #include "../../Core/definitions.h" +void Abort() +{ + if (currentState == STATE_Idle) + { + return; + } + + + server->GameStringf("�c5Goto�c0: Complete"); + currentState = STATE_Idle; + + auto fleeModule = GetModuleHandle("Flee.d2h"); + if (fleeModule != NULL) + { + server->GameCommandf("flee SuppressAutoTp 0"); + } +} + void SetState(States newState) { /* @@ -471,14 +489,12 @@ void NextRoomTransition() { //server->GameStringf("NextRoomTransition()"); - SetState(STATE_Idle); - if(currentTravelData->CurrentStep + 1 < currentTravelData->NumSteps) { currentTravelData->CurrentStep++; } else { - server->GameStringf("Done"); + Abort(); return; } @@ -552,7 +568,7 @@ void CalculatePathToStairsRoom() } } - SetState(States::STATE_Idle); + Abort(); server->GameStringf("Failed to find path to stairs. Returning to town"); server->GameCommandf(".flee tp"); } @@ -612,6 +628,12 @@ BOOL PRIVATE Start(char** argv, int argc) return TRUE; } + auto fleeModule = GetModuleHandle("Flee.d2h"); + if (fleeModule != NULL) + { + server->GameCommandf("flee SuppressAutoTp 1"); + } + currentState = STATE_UsingWaypoint; server->GameCommandf("load wp"); server->GameCommandf("wp start %d", currentTravelData->WaypointDestination); @@ -628,17 +650,17 @@ BOOL PRIVATE Start(char** argv, int argc) VOID EXPORT OnGameJoin(THISGAMESTRUCT* thisgame) { - SetState(STATE_Idle); + Abort(); } VOID EXPORT OnClientStop(THISGAMESTRUCT *thisgame) { server->GameStringf("OnClientStop"); - SetState(STATE_Idle); + Abort(); } VOID EXPORT OnGameLeave(THISGAMESTRUCT* thisgame) { - SetState(STATE_Idle); + Abort(); } BOOL EXPORT OnClientStart() @@ -763,7 +785,8 @@ DWORD EXPORT OnGamePacketBeforeSent(BYTE* aPacket, DWORD aLen) { if(strcmp(chatMessage, "�c5Waypoint�c0: Complete") != 0) { - SetState(STATE_Idle); + Abort(); + return 0; } return 0; @@ -828,7 +851,7 @@ VOID EXPORT OnThisPlayerMessage(UINT nMessage, WPARAM wParam, LPARAM lParam) if (me->IsInTown()) { server->GameStringf("Unexpected map change. Aborting."); - SetState(STATE_Idle); + Abort(); return; } @@ -848,16 +871,17 @@ VOID EXPORT OnThisPlayerMessage(UINT nMessage, WPARAM wParam, LPARAM lParam) { GoBackToTown(); } - SetState(STATE_Idle); + Abort(); } } } + BYTE EXPORT OnGameKeyDown(BYTE iKeyCode) { if(iKeyCode == VK_SPACE) { - currentState = STATE_Idle; + Abort(); } return iKeyCode; } diff --git a/D2Hackit/Modules/pick/ItemWatcher.cpp b/D2Hackit/Modules/pick/ItemWatcher.cpp index e1dbfe6..214a6a4 100644 --- a/D2Hackit/Modules/pick/ItemWatcher.cpp +++ b/D2Hackit/Modules/pick/ItemWatcher.cpp @@ -59,6 +59,8 @@ BOOL CALLBACK searchForTomesItemProc(LPCITEM item, LPARAM lParam) void ItemWatcher::CheckWatchedItems() { + bool needToResortWatchedItems = false; + if(!destroyedItemsSinceLastCheck.empty()) { for (auto watchedItemIter = watchedItems.begin(); watchedItemIter != watchedItems.end();) @@ -66,8 +68,9 @@ void ItemWatcher::CheckWatchedItems() if (destroyedItemsSinceLastCheck.find(watchedItemIter->id) != destroyedItemsSinceLastCheck.end()) { watchedItemIter = watchedItems.erase(watchedItemIter); + needToResortWatchedItems = true; } - else + else { ++watchedItemIter; } @@ -78,30 +81,25 @@ void ItemWatcher::CheckWatchedItems() // same thread (Proc_OnGameTimerTick() server20.cpp) destroyedItemsSinceLastCheck.clear(); - if(me->GetOpenedUI() != 0) + if(std::chrono::system_clock::now() < nextPickAttemptTime) { return; } - if (watchedItems.empty()) + if(me->GetOpenedUI() != 0) { return; } - const auto myPosition = me->GetPosition(); - for(auto &item: watchedItems) + if(watchedItems.empty()) { - item.distanceToItem = sqrt( - (myPosition.x - item.x) *(myPosition.x - item.x) + - (myPosition.y - item.y) * (myPosition.y - item.y) - ); + return; } - std::sort(watchedItems.begin(), watchedItems.end(), [](const WatchedItemData &left, const WatchedItemData &right) { - return left.distanceToItem < right.distanceToItem; - }); + SortWatchedItems(); - for(auto itemIter = watchedItems.begin(); itemIter != watchedItems.end(); ) + int numPickAttemptsThisFrame = 0; + for (auto itemIter = watchedItems.begin(); itemIter != watchedItems.end(); ) { GAMEUNIT itemUnit; itemUnit.dwUnitType = UNIT_TYPE_ITEM; @@ -112,28 +110,17 @@ void ItemWatcher::CheckWatchedItems() continue; } - const auto myPos = me->GetPosition(); - if (server->GetDistance(myPos.x, myPos.y, itemIter->x, itemIter->y) > radius || me->GetMode() == MODE_CAST) + if(itemIter->distanceToItem > radius || numPickAttemptsThisFrame > 5) { - ++itemIter; - continue; + break; } - //server->GameStringf("Picking %X... [%d]", i->id, watchedItems.size()); if(itemIter->isGold) { + numPickAttemptsThisFrame++; me->PickGroundItem(itemIter->id, this->isWalkToGold); - - goldPicksThisFrame++; - if (goldPicksThisFrame > goldSpeed) { - return; - } - ++itemIter; - continue; } - - - if (itemIter->isIdScroll) + else if(itemIter->isIdScroll) { TomeInfo info{ 0, 0, 0 }; me->EnumStorageItems(STORAGE_INVENTORY, searchForTomesItemProc, (LPARAM)&info); @@ -141,17 +128,16 @@ void ItemWatcher::CheckWatchedItems() const auto numCharges = me->GetSpellCharges(D2S_TOMEOFIDENTIFY); const auto maxCharges = info.totalTomesOfIdentify * 40; - if (maxCharges - numCharges < 2) + if(maxCharges - numCharges < 2) { itemIter = watchedItems.erase(itemIter); continue; } + numPickAttemptsThisFrame++; me->PickGroundItem(itemIter->id, this->isWalkToItems); - return; } - - if (itemIter->isTpScroll) + else if(itemIter->isTpScroll) { TomeInfo info{ 0, 0, 0 }; me->EnumStorageItems(STORAGE_INVENTORY, searchForTomesItemProc, (LPARAM)&info); @@ -159,40 +145,51 @@ void ItemWatcher::CheckWatchedItems() const auto numCharges = me->GetSpellCharges(D2S_TOMEOFTOWNPORTAL); const auto maxCharges = info.totalTomesOfTownPortal * 40; - if (maxCharges - numCharges < 2) + if(maxCharges - numCharges < 2) { itemIter = watchedItems.erase(itemIter); continue; } + numPickAttemptsThisFrame++; me->PickGroundItem(itemIter->id, this->isWalkToItems); - return; } - - if (itemIter->keyCount > 0) + else if(itemIter->keyCount > 0) { - TomeInfo info{ 0, 0, 0}; + TomeInfo info{ 0, 0, 0 }; me->EnumStorageItems(STORAGE_INVENTORY, searchForTomesItemProc, (LPARAM)&info); - if ((info.totalKeys + itemIter->keyCount) > 20) + if((info.totalKeys + itemIter->keyCount) > 20) { itemIter = watchedItems.erase(itemIter); continue; } + numPickAttemptsThisFrame++; me->PickGroundItem(itemIter->id, this->isWalkToItems); - return; } - - if(me->FindFirstStorageSpace(STORAGE_INVENTORY, itemIter->itemSize, NULL)) + else if(me->FindFirstStorageSpace(STORAGE_INVENTORY, itemIter->itemSize, NULL)) { + numPickAttemptsThisFrame++; me->PickGroundItem(itemIter->id, this->isWalkToItems); + } + else + { + server->GameStringf("�c1Pick�c0: �c:Not enough room for item, skipping"); + itemIter = watchedItems.erase(itemIter); + continue; + } + + if(radius > 5 && itemIter->distanceToItem > 5) + { + // We're likely walking somewhere, give it 200ms unless something new drops + // nextPickAttemptTime = std::chrono::system_clock::now() + std::chrono::milliseconds(200); return; } - server->GameStringf("�c1Pick�c0: �c:Not enough room for item, skipping"); - itemIter = watchedItems.erase(itemIter); - return; + ++itemIter; } + + nextPickAttemptTime = std::chrono::system_clock::now() + std::chrono::milliseconds(10); } //////////////////////////////////////////// @@ -316,7 +313,7 @@ bool ItemWatcher::loadItemMap(const std::string &fileName, std::unordered_mapGetItemSize(itemCode.c_str()); - watchedItems.push_back(itemData); + SortWatchedItems(); } } } + watchedItems.push_back(itemData); AnnounceItem(item); } -void ItemWatcher::AnnounceItem(const ITEM &item) +float ItemWatcher::Distance(float x1, float x2, float y1, float y2) const { - if (isMute) + return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); +} + +void ItemWatcher::SortWatchedItems() +{ + auto myPosition = me->GetPosition(); + + for (auto& item : watchedItems) + { + item.distanceToItem = Distance(myPosition.x, item.x, myPosition.y, item.y); + } + + std::sort(watchedItems.begin(), watchedItems.end(), [](const WatchedItemData& left, const WatchedItemData& right) { + return left.distanceToItem < right.distanceToItem; + }); +} + +void ItemWatcher::AnnounceItem(const ITEM& item) +{ + if(isMute) { return; } std::string outputMessage; outputMessage.reserve(128); - + bool overrideAnnouncment = false; const auto itemCode = std::string(item.szItemCode); diff --git a/D2Hackit/Modules/pick/ItemWatcher.h b/D2Hackit/Modules/pick/ItemWatcher.h index 13a0cb4..0bfc162 100644 --- a/D2Hackit/Modules/pick/ItemWatcher.h +++ b/D2Hackit/Modules/pick/ItemWatcher.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "../../Includes/D2Client.h" //#include "_item.h" @@ -46,6 +47,8 @@ class ItemWatcher void CheckWatchedItems(); void Cleanup(); bool loadItemMap(const std::string &fileName, std::unordered_map &itemMap); + void SortWatchedItems(); + float Distance(float x1, float x2, float y1, float y2) const; const char *GetItemDesc(const ITEM &item); const char *GetDirectionFrom(WORD sourceX, WORD sourceY, WORD targetX, WORD targetY); @@ -60,6 +63,9 @@ class ItemWatcher std::unordered_map itemsToAnnounce; std::unordered_map itemsToPick; + std::chrono::system_clock::time_point nextPickAttemptTime; + + int itemWatcherTicksToSkip; unsigned int radius; unsigned int minGold; bool townPickup;