diff --git a/BH/Constants.h b/BH/Constants.h index 3543259..7fd24e9 100644 --- a/BH/Constants.h +++ b/BH/Constants.h @@ -762,6 +762,12 @@ enum PetType #define NODEPAGE_BELTSLOTS 2 #define NODEPAGE_EQUIP 3 +enum InventoryStoreType { + INVENTORY_STORE_TYPE_BODY = 0, + INVENTORY_STORE_TYPE_BELT, + INVENTORY_STORE_TYPE_INVENTORY, +}; + /////////////////////////////////////////////////// // Item Actions /////////////////////////////////////////////////// diff --git a/BH/D2Structs.h b/BH/D2Structs.h index ec85bf2..30dc470 100644 --- a/BH/D2Structs.h +++ b/BH/D2Structs.h @@ -292,11 +292,11 @@ struct PlayerData { DWORD _0x244; DWORD _0x248; DWORD _0x24C; - BOOL _0x250; // + BOOL _0x250; // DWORD _0x254; // DWORD _0x258; // DWORD _0x25C; // - BOOL _0x260; // + BOOL _0x260; // BYTE _0x264; // BOOL _0x265; DWORD _0x269; @@ -460,7 +460,7 @@ struct InventoryStore BYTE Width; //0x08 BYTE Height; //0x09 BYTE unk[2]; //0x0A - DWORD pArray; //0x0C UnitAny* [height][width] + UnitAny** pArray; //0x0C UnitAny* [height][width] }; struct Inventory { @@ -581,7 +581,7 @@ struct ItemText { BYTE _uncharted6[0x0d]; //0xDF BYTE fQuest; //0xEC BYTE _uncharted7[0x12]; //0xED - BYTE reqlvl; //0xFF + BYTE reqlvl; //0xFF BYTE magiclvl; //0x100 }; @@ -746,10 +746,10 @@ struct UnitAny { struct BnetData { DWORD dwId; //0x00 - DWORD dwId2; //0x04 + DWORD dwId2; //0x04 BYTE _12[13]; //0xC0 //DWORD dwId3; //0x14 - //WORD Unk3; //0x18 + //WORD Unk3; //0x18 BYTE _13[6]; //0xC0 char szGameName[22]; //0x1A char szGameIP[16]; //0x30 diff --git a/BH/Modules/Item/ItemDisplay.cpp b/BH/Modules/Item/ItemDisplay.cpp index 421e73f..32c99bf 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_BELT_1, + COND_BELT_2, + COND_BELT_3, + COND_BELT_4, COND_NULL }; @@ -751,6 +755,10 @@ std::map condition_map = {L"WIDTH", COND_WIDTH}, {L"HEIGHT", COND_HEIGHT}, {L"AREA", COND_AREA}, + {L"BELTCOLUMN1", COND_BELT_1}, + {L"BELTCOLUMN2", COND_BELT_2}, + {L"BELTCOLUMN3", COND_BELT_3}, + {L"BELTCOLUMN4", COND_BELT_4}, // These have a number as part of the key, handled separately //{"SK", COND_SK}, //{"OS", COND_OS}, @@ -4323,6 +4331,18 @@ void Condition::BuildConditions(vector& conditions, case COND_AREA: Condition::AddOperand(conditions, new ItemSizeCondition(operation, value, value2, ItemSizeCondition::Dimension::kArea)); break; + case COND_BELT_1: + Condition::AddOperand(conditions, new BeltCondition(operation, value, value2, 0)); + break; + case COND_BELT_2: + Condition::AddOperand(conditions, new BeltCondition(operation, value, value2, 1)); + break; + case COND_BELT_3: + Condition::AddOperand(conditions, new BeltCondition(operation, value, value2, 2)); + break; + case COND_BELT_4: + Condition::AddOperand(conditions, new BeltCondition(operation, value, value2, 3)); + break; case COND_ITEMCODE: Condition::AddOperand(conditions, new ItemCodeCondition(WideToAnsi(key.substr(0, 4)).c_str())); break; @@ -5152,6 +5172,39 @@ bool ItemSizeCondition::EvaluateInternal(UnitItemInfo* uInfo, Condition* arg1, C return IntegerCompare(value, op_, targetStat_, targetStat2_); } +bool BeltCondition::EvaluateInternal(UnitItemInfo* uInfo, Condition* arg1, Condition* arg2) +{ + const int kBeltWidth = 4; + const int kBeltHeight = 4; + + Inventory* inventory = D2CLIENT_GetPlayerUnit()->pInventory; + if (inventory == nullptr) { + return false; + } + if (column_ >= kBeltWidth) { + return false; + } + if (inventory->dwStoresCount <= InventoryStoreType::INVENTORY_STORE_TYPE_BELT) { + return false; + } + InventoryStore& store = inventory->pStores[InventoryStoreType::INVENTORY_STORE_TYPE_BELT]; + // Double check that this is indeed the correct `InventoryStore`. + // Internally belt is represented as a flat, 16 elements, array. + if (store.Width != kBeltWidth * kBeltHeight || store.Height != 1) { + return false; + } + + int itemsInColumnCount = 0; + for (int row = 0; row < kBeltHeight; ++row) { + auto slot = row * kBeltWidth + column_; + if (store.pArray[slot] != nullptr) { + itemsInColumnCount += 1; + } + } + + return IntegerCompare(itemsInColumnCount, op_, targetStat_, targetStat2_); +} + bool ResistAllCondition::EvaluateInternal(UnitItemInfo* uInfo, Condition* arg1, Condition* arg2) diff --git a/BH/Modules/Item/ItemDisplay.h b/BH/Modules/Item/ItemDisplay.h index 5fedfba..1bb5925 100644 --- a/BH/Modules/Item/ItemDisplay.h +++ b/BH/Modules/Item/ItemDisplay.h @@ -799,6 +799,27 @@ class ItemSizeCondition: public Condition bool EvaluateInternal(UnitItemInfo* uInfo, Condition* arg1, Condition* arg2); }; +class BeltCondition: public Condition +{ +public: + BeltCondition(BYTE op, + unsigned int targetStat, + unsigned int targetStat2, + unsigned int column) + : op_(op), + targetStat_(targetStat), + targetStat2_(targetStat2), + column_(column){ + conditionType = CT_Operand; + }; +private: + BYTE op_; + unsigned int targetStat_; + unsigned int targetStat2_; + unsigned int column_; + bool EvaluateInternal(UnitItemInfo* uInfo, Condition* arg1, Condition* arg2); +}; + class ResistAllCondition : public Condition { public: