diff --git a/BH/BH.cpp b/BH/BH.cpp index 984d385b..e0422fa8 100644 --- a/BH/BH.cpp +++ b/BH/BH.cpp @@ -268,6 +268,9 @@ void BH::CheckForPD2() { FARPROC proc = GetProcAddress(pd2Handle, "_D2Client_PlaySoundWithCustomVolumeOrPriority@20"); App.pd2.pd2PlaySoundImpl = proc ? (pd2PlaySoundImpl_t)proc : NULL; + + proc = GetProcAddress(pd2Handle, "_D2Client_GetItemDiscoveryState@12"); + App.pd2.pd2GetItemDiscoveryStateImpl = proc ? (pd2GetItemDiscoveryStateImpl_t)proc : NULL; } } diff --git a/BH/BH.h b/BH/BH.h index ecf3cb63..3cff17bc 100644 --- a/BH/BH.h +++ b/BH/BH.h @@ -45,6 +45,7 @@ namespace BH }; typedef BOOL(__stdcall* pd2PlaySoundImpl_t)(UnitAny* pUnit, int nSound, int nVolume, int nPriority, BOOL bDropSound); +typedef DWORD(__stdcall* pd2GetItemDiscoveryStateImpl_t)(DWORD dwFileIndex, DWORD dwQuality, DWORD dwBaseId); struct BHApp { @@ -187,6 +188,7 @@ struct BHApp struct { pd2PlaySoundImpl_t pd2PlaySoundImpl = NULL; + pd2GetItemDiscoveryStateImpl_t pd2GetItemDiscoveryStateImpl = NULL; } pd2; std::vector hotkeyToggles; diff --git a/BH/Modules/Item/ItemDisplay.cpp b/BH/Modules/Item/ItemDisplay.cpp index e0c12198..ec79cc71 100644 --- a/BH/Modules/Item/ItemDisplay.cpp +++ b/BH/Modules/Item/ItemDisplay.cpp @@ -562,6 +562,10 @@ enum FilterCondition COND_UPSTAT, COND_MAXSOCKETS, COND_FORMULA, + COND_ANYDISCOVERED, + COND_ALLDISCOVERED, + COND_ANYOWNED, + COND_ALLOWNED, COND_NULL }; @@ -751,6 +755,10 @@ std::map condition_map = {L"WIDTH", COND_WIDTH}, {L"HEIGHT", COND_HEIGHT}, {L"AREA", COND_AREA}, + {L"ANYDISCOVERED", COND_ANYDISCOVERED}, + {L"ALLDISCOVERED", COND_ALLDISCOVERED}, + {L"ANYOWNED", COND_ANYOWNED}, + {L"ALLOWNED", COND_ALLOWNED}, // These have a number as part of the key, handled separately //{"SK", COND_SK}, //{"OS", COND_OS}, @@ -3997,6 +4005,18 @@ void Condition::BuildConditions(vector& conditions, case COND_ID: Condition::AddOperand(conditions, new FlagsCondition(ITEM_IDENTIFIED)); break; + case COND_ANYDISCOVERED: + Condition::AddOperand(conditions, new DiscoveryStateCondition(DISCOVERYSTATE_ANYDISCOVERED)); + break; + case COND_ALLDISCOVERED: + Condition::AddOperand(conditions, new DiscoveryStateCondition(DISCOVERYSTATE_ALLDISCOVERED)); + break; + case COND_ANYOWNED: + Condition::AddOperand(conditions, new DiscoveryStateCondition(DISCOVERYSTATE_ANYOWNED)); + break; + case COND_ALLOWNED: + Condition::AddOperand(conditions, new DiscoveryStateCondition(DISCOVERYSTATE_ALLOWNED)); + break; case COND_ILVL: Condition::AddOperand(conditions, new ItemLevelCondition(operation, value, value2)); break; @@ -4535,6 +4555,26 @@ bool QualityCondition::EvaluateInternal(UnitItemInfo* uInfo, return (uInfo->item->pItemData->dwQuality == quality); } +bool DiscoveryStateCondition::EvaluateInternal(UnitItemInfo* uInfo, + Condition* arg1, + Condition* arg2) { + if (!uInfo->item || !uInfo->item->pItemData) + { + return false; + } + // Backed by the ProjectDiablo.dll discovery export (resolved in + // BH::CheckForPD2); the conditions evaluate to false when + // ProjectDiablo.dll is absent. + if (!App.pd2.pd2GetItemDiscoveryStateImpl) { return false; } + ItemData* pItemData = uInfo->item->pItemData; + // Unidentified unique/set drops have no file index client-side; pass the + // unset sentinel so the dll covers "all the variants it could be" via + // the base item's code. + DWORD dwFileIndex = (pItemData->dwFlags & ITEM_IDENTIFIED) ? pItemData->dwFileIndex : 0xFFFFFFFF; + DWORD dwState = App.pd2.pd2GetItemDiscoveryStateImpl(dwFileIndex, pItemData->dwQuality, uInfo->item->dwTxtFileNo); + return (dwState & discoveryFlag) > 0; +} + bool NonMagicalCondition::EvaluateInternal(UnitItemInfo* uInfo, Condition* arg1, Condition* arg2) diff --git a/BH/Modules/Item/ItemDisplay.h b/BH/Modules/Item/ItemDisplay.h index 5fedfba4..d992214f 100644 --- a/BH/Modules/Item/ItemDisplay.h +++ b/BH/Modules/Item/ItemDisplay.h @@ -191,6 +191,23 @@ class QualityCondition : public Condition Condition* arg2); }; +enum DiscoveryStateFlag +{ + DISCOVERYSTATE_ANYDISCOVERED = 0x1, // any candidate variant group discovered (grail bit set) + DISCOVERYSTATE_ALLDISCOVERED = 0x2, // every candidate variant group discovered + DISCOVERYSTATE_ANYOWNED = 0x4, // any candidate variant group owned (stored in compendium) + DISCOVERYSTATE_ALLOWNED = 0x8, // every candidate variant group owned +};class DiscoveryStateCondition : public Condition +{ +public: + DiscoveryStateCondition(unsigned int flag) : discoveryFlag(flag) { conditionType = CT_Operand; }; +private: + unsigned int discoveryFlag; + bool EvaluateInternal(UnitItemInfo* uInfo, + Condition* arg1, + Condition* arg2); +}; + class NonMagicalCondition : public Condition { public: