diff --git a/playerbot/RandomItemMgr.cpp b/playerbot/RandomItemMgr.cpp index bb39f2c57..64255aaa8 100644 --- a/playerbot/RandomItemMgr.cpp +++ b/playerbot/RandomItemMgr.cpp @@ -2015,96 +2015,198 @@ uint32 RandomItemMgr::CalculateStatWeight(uint8 playerclass, uint8 spec, ItemPro return statWeight; } -uint32 RandomItemMgr::CalculateRandomPropertyWeight(uint8 playerclass, uint8 spec, uint32 randomPropertyId) +uint32 RandomItemMgr::CalculateEnchantWeight(uint8 playerclass, uint8 spec, uint32 enchantId) { + if (!enchantId) + return 0; + + SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchantId); + + if (!pEnchant) + return 0; + uint32 weight = 0; - if (randomPropertyId > 0) + + for (int s = 0; s < 3; ++s) { - ItemRandomPropertiesEntry const* item_rand = sItemRandomPropertiesStore.LookupEntry(randomPropertyId); - if (item_rand) + switch (pEnchant->type[s]) { - for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i < PROP_ENCHANTMENT_SLOT_0 + 3; ++i) - { - if (SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_0])) - { - for (int s = 0; s < 3; ++s) - { - switch (pEnchant->type[s]) - { - case 1: //Proc //TODO add proc values? - break; - case 2: //Damage - if (!pEnchant->amount[s]) - continue; - weight += CalculateSingleStatWeight(playerclass, spec, "mledps", pEnchant->amount[s]); - break; - case 3: - { - if (!pEnchant->spellid[s]) - continue; + case 1: //Proc //TODO add proc values? + break; + case 2: //Damage + if (!pEnchant->amount[s]) + continue; + weight += CalculateSingleStatWeight(playerclass, spec, "mledps", pEnchant->amount[s]); + break; + case 3: + { + if (!pEnchant->spellid[s]) + continue; - SpellEntry const* spellInfo = sSpellTemplate.LookupEntry(pEnchant->spellid[s]); + SpellEntry const* spellInfo = sSpellTemplate.LookupEntry(pEnchant->spellid[s]); - if (!spellInfo) - continue; + if (!spellInfo) + continue; - for (uint32 j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if (spellInfo->Effect[j] != SPELL_EFFECT_APPLY_AURA) - continue; - if (spellInfo->EffectApplyAuraName[j] != SPELL_AURA_MOD_STAT) - continue; + for (uint32 j = 0; j < MAX_EFFECT_INDEX; ++j) + { + if (spellInfo->Effect[j] != SPELL_EFFECT_APPLY_AURA) + continue; + if (spellInfo->EffectApplyAuraName[j] != SPELL_AURA_MOD_STAT) + continue; - uint32 stat = spellInfo->EffectMiscValue[j]; - uint32 value = spellInfo->EffectBasePoints[j] + 1; + uint32 stat = spellInfo->EffectMiscValue[j]; + uint32 value = spellInfo->EffectBasePoints[j] + 1; - if (!value) - continue; + if (!value) + continue; - if (ItemStatLink.find(stat) == ItemStatLink.end()) - continue; + if (ItemStatLink.find(stat) == ItemStatLink.end()) + continue; - weight += CalculateSingleStatWeight(playerclass, spec, ItemStatLink[stat], value); - } - break; - } - case 4: //Armor - if (!pEnchant->amount[s]) - continue; - weight += CalculateSingleStatWeight(playerclass, spec, "armor", pEnchant->amount[s]); - break; - } + weight += CalculateSingleStatWeight(playerclass, spec, ItemStatLink[stat], value); + } + break; + } + case 4: //Armor + if (!pEnchant->amount[s]) + continue; + weight += CalculateSingleStatWeight(playerclass, spec, "armor", pEnchant->amount[s]); + break; + case 5: //Stat + { + for (auto& statLink : weightStatLink) + { + if (statLink.second != pEnchant->spellid[s]) + continue; - } - } + weight += CalculateSingleStatWeight(playerclass, spec, statLink.first, pEnchant->amount[s]); } + break; + } + case 6: //Totem + break; + case 7: //Use Spell + break; + case 8: //Prismatic socket + break; } } + return weight; } -uint32 RandomItemMgr::ItemStatWeight(Player* player, ItemPrototype const* proto, uint32 randomPropertyId, uint32 gem1, uint32 gem2, uint32 gem3, uint32 gem4) +uint32 RandomItemMgr::CalculateRandomPropertyWeight(uint8 playerclass, uint8 spec, int32 randomPropertyId) { - ItemSpecType itSpec; - uint32 weight = CalculateStatWeight(player->getClass(), GetPlayerSpecId(player), proto, itSpec); + uint32 weight = 0; if (randomPropertyId) - weight += CalculateRandomPropertyWeight(player->getClass(), GetPlayerSpecId(player), randomPropertyId); - - //Todo gems. + { + ItemRandomPropertiesEntry const* item_rand = sItemRandomPropertiesStore.LookupEntry(abs(randomPropertyId)); + if (item_rand) + { + for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i < PROP_ENCHANTMENT_SLOT_0 + 3; ++i) + { + uint32 enchantId = item_rand->enchant_id[i - PROP_ENCHANTMENT_SLOT_0]; + weight += CalculateEnchantWeight(playerclass, spec, enchantId); + } + } + } return weight; } -uint32 RandomItemMgr::ItemStatWeight(Player* player, uint32 itemId, uint32 randomPropertyId, uint32 gem1, uint32 gem2, uint32 gem3, uint32 gem4) +uint32 RandomItemMgr::CalculateGemWeight(uint8 playerclass, uint8 spec, uint32 gemId) { - const ItemPrototype* proto = sObjectMgr.GetItemPrototype(itemId); - return ItemStatWeight(player, proto, randomPropertyId, gem1, gem2, gem3, gem4); +#ifdef MANGOSBOT_ZERO + return 0; +#else + if (!gemId) + return 0; + + return CalculateEnchantWeight(playerclass, spec, gemId); +#endif } +uint32 RandomItemMgr::CalculateSocketWeight(uint8 playerclass, ItemQualifier& qualifier, uint8 spec) +{ +#ifdef MANGOSBOT_ZERO + return 0; +#else + + vector gems = { qualifier.GetGem1() , qualifier.GetGem2(), qualifier.GetGem3(), qualifier.GetGem4() }; + + ItemPrototype const* proto = qualifier.GetProto(); + + bool hasGem = false; + for (auto gem : gems) + if(gem) + hasGem = true; + + if (!hasGem) + return 0; + + for (int i = 0; i < MAX_GEM_SOCKETS; ++i) + { + uint8 SocketColor = proto->Socket[i].Color; + + if (!SocketColor) + continue; + + uint8 GemColor = 0; + + if (!gems[i]) + return 0; + + SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(gems[i]); + + if (!pEnchant) + return 0; + + uint32 gemid = pEnchant->GemID; + if (!gemid) + return 0; + + ItemPrototype const* gemProto = sItemStorage.LookupEntry(gemid); + if (!gemProto) + return 0; + + GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GemProperties); + + if (!gemProperty) + return 0; + + GemColor = gemProperty->color; + + if (!(GemColor & SocketColor)) + return 0; + } + + return CalculateEnchantWeight(playerclass, spec, proto->socketBonus); +#endif; +} + + uint32 RandomItemMgr::ItemStatWeight(Player* player, ItemQualifier& qualifier) { - return ItemStatWeight(player, qualifier.GetId(), qualifier.GetRandomPropertyId(), qualifier.GetGem1(), qualifier.GetGem2(), qualifier.GetGem3(), qualifier.GetGem4()); + ItemSpecType itSpec; + uint32 weight = CalculateStatWeight(player->getClass(), GetPlayerSpecId(player), qualifier.GetProto(), itSpec); + if(qualifier.GetEnchantId()) + weight += CalculateEnchantWeight(player->getClass(), GetPlayerSpecId(player), qualifier.GetEnchantId()); + if (qualifier.GetRandomPropertyId()) + weight += CalculateRandomPropertyWeight(player->getClass(), GetPlayerSpecId(player), qualifier.GetRandomPropertyId()); + if(qualifier.GetGem1()) + weight += CalculateGemWeight(player->getClass(), GetPlayerSpecId(player), qualifier.GetGem1()); + if (qualifier.GetGem2()) + weight += CalculateGemWeight(player->getClass(), GetPlayerSpecId(player), qualifier.GetGem2()); + if (qualifier.GetGem3()) + weight += CalculateGemWeight(player->getClass(), GetPlayerSpecId(player), qualifier.GetGem3()); + if (qualifier.GetGem4()) + weight += CalculateGemWeight(player->getClass(), GetPlayerSpecId(player), qualifier.GetGem4()); + + weight += CalculateSocketWeight(player->getClass(), qualifier, GetPlayerSpecId(player)); + + return weight; } uint32 RandomItemMgr::ItemStatWeight(Player* player, Item* item) diff --git a/playerbot/RandomItemMgr.h b/playerbot/RandomItemMgr.h index c299e8b9d..125061a32 100644 --- a/playerbot/RandomItemMgr.h +++ b/playerbot/RandomItemMgr.h @@ -166,10 +166,12 @@ class RandomItemMgr uint32 GetRandomTrade(uint32 level); vector GetGemsList(); - uint32 CalculateRandomPropertyWeight(uint8 playerclass, uint8 spec, uint32 randomPropertyId); + uint32 CalculateEnchantWeight(uint8 playerclass, uint8 spec, uint32 enchantId); + uint32 CalculateRandomPropertyWeight(uint8 playerclass, uint8 spec, int32 randomPropertyId); + uint32 CalculateGemWeight(uint8 playerclass, uint8 spec, uint32 gemId); + uint32 CalculateSocketWeight(uint8 playerclass, ItemQualifier& qualifier, uint8 spec); + uint32 CalculateStatWeight(uint8 playerclass, uint8 spec, ItemPrototype const* proto, ItemSpecType &itSpec); - uint32 ItemStatWeight(Player* player, ItemPrototype const* proto, uint32 randomPropertyId = 0, uint32 gem1 = 0, uint32 gem2 = 0, uint32 gem3 = 0, uint32 gem4 = 0); - uint32 ItemStatWeight(Player* player, uint32 itemId, uint32 randomPropertyId = 0, uint32 gem1 = 0, uint32 gem2 = 0, uint32 gem3 = 0, uint32 gem4 = 0); uint32 ItemStatWeight(Player* player, ItemQualifier& qualifier); uint32 ItemStatWeight(Player* player, Item* item); diff --git a/playerbot/strategy/values/ItemUsageValue.cpp b/playerbot/strategy/values/ItemUsageValue.cpp index 12e63dd8c..7a1716d6a 100644 --- a/playerbot/strategy/values/ItemUsageValue.cpp +++ b/playerbot/strategy/values/ItemUsageValue.cpp @@ -11,35 +11,61 @@ using namespace ai; -ItemQualifier::ItemQualifier(string qualifier) +ItemQualifier::ItemQualifier(string qualifier, bool linkQualifier) { vector numbers = Qualified::getMultiQualifiers(qualifier, ":"); itemId = stoi(numbers[0]); - if (numbers.size() > 2) - randomPropertyId = stoi(numbers[2]); - else - randomPropertyId = 0; + enchantId = 0; + randomPropertyId = 0; + gem1 = 0; + gem2 = 0; + gem3 = 0; + gem4 = 0; + proto = nullptr; + +#ifdef MANGOSBOT_ZERO + uint32 propertyPosition = linkQualifier ? 2 : 5; +#else + uint32 propertyPosition = linkQualifier ? 6 : 5; +#endif - if (numbers.size() > 7) - { - gem1 = stoi(numbers[4]); - gem2 = stoi(numbers[5]); - gem3 = stoi(numbers[6]); - gem4 = stoi(numbers[7]); - } - else + if (numbers.size() > 1) + enchantId = stoi(numbers[1]); + + if (numbers.size() > propertyPosition) + randomPropertyId = stoi(numbers[propertyPosition]); + +#ifndef MANGOSBOT_ZERO + uint8 gemPosition = linkQualifier ? 2 : 1; + + if (numbers.size() > gemPosition + 3) { - gem1 = 0; - gem2 = 0; - gem3 = 0; - gem4 = 0; + gem1 = stoi(numbers[gemPosition]); + gem2 = stoi(numbers[gemPosition+1]); + gem3 = stoi(numbers[gemPosition+2]); + gem4 = stoi(numbers[gemPosition+3]); } +#endif; +} + +uint32 ItemQualifier::GemId(Item* item, uint8 gemSlot) +{ +#ifdef MANGOSBOT_ZERO + return 0; +#else + uint32 enchantId = item->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + gemSlot)); + + if (!enchantId) + return 0; + + return enchantId; +#endif } ItemUsage ItemUsageValue::Calculate() { - ItemQualifier itemQualifier(qualifier); + ItemQualifier itemQualifier(qualifier,false); uint32 itemId = itemQualifier.GetId(); if (!itemId) return ITEM_USAGE_NONE; @@ -226,7 +252,7 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemQualifier& itemQualifier) uint16 dest; - list items = AI_VALUE2(list, "inventory items", chat->formatItem(itemProto)); + list items = AI_VALUE2(list, "inventory items", chat->formatItem(itemQualifier)); InventoryResult result; if (!items.empty()) { diff --git a/playerbot/strategy/values/ItemUsageValue.h b/playerbot/strategy/values/ItemUsageValue.h index cf6bf1d98..e520c00ee 100644 --- a/playerbot/strategy/values/ItemUsageValue.h +++ b/playerbot/strategy/values/ItemUsageValue.h @@ -7,28 +7,39 @@ namespace ai class ItemQualifier { public: - ItemQualifier() { itemId = 0; randomPropertyId = 0; gem1 = 0; gem2 = 0; gem3 = 0; gem4 = 0; }; - ItemQualifier(uint32 itemId, int32 randomPropertyId = 0, uint32 gem1 = 0, uint32 gem2 = 0, uint32 gem3 = 0, uint32 gem4 = 0) : itemId(itemId), randomPropertyId(randomPropertyId), gem1(gem1), gem2(gem2), gem3(gem3), gem4(gem4) {}; - ItemQualifier(Item* item) { itemId = item->GetProto()->ItemId; randomPropertyId = item->GetItemRandomPropertyId(); gem1 = 0; gem2 = 0; gem3 = 0; gem4 = 0; }; //todo Gems. - ItemQualifier(LootItem item) { itemId = item.itemId; randomPropertyId = item.randomPropertyId; gem1 = 0; gem2 = 0; gem3 = 0; gem4 = 0; }; //todo Gems. - - ItemQualifier(string qualifier); + ItemQualifier() { itemId = 0; enchantId = 0; randomPropertyId = 0; gem1 = 0; gem2 = 0; gem3 = 0; gem4 = 0; proto = nullptr; }; + ItemQualifier(uint32 itemId, int32 randomPropertyId = 0, uint32 enchantId = 0, uint32 gem1 = 0, uint32 gem2 = 0, uint32 gem3 = 0, uint32 gem4 = 0) : itemId(itemId), randomPropertyId(randomPropertyId), enchantId(enchantId), gem1(gem1), gem2(gem2), gem3(gem3), gem4(gem4) { proto = nullptr; }; + ItemQualifier(Item* item) { itemId = item->GetProto()->ItemId; enchantId = item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT); randomPropertyId = item->GetItemRandomPropertyId(); gem1 = GemId(item, 0); gem2 = GemId(item, 1); gem3 = GemId(item, 2); gem4 = GemId(item, 3); proto = item->GetProto();}; + ItemQualifier(LootItem item) { itemId = item.itemId; enchantId = 0; randomPropertyId = item.randomPropertyId; gem1 = 0; gem2 = 0; gem3 = 0; gem4 = 0; proto = nullptr; }; + ItemQualifier(AuctionEntry* auction) { itemId = auction->itemTemplate; enchantId = 0; randomPropertyId = auction->itemRandomPropertyId; gem1 = 0; gem2 = 0; gem3 = 0; gem4 = 0; proto = nullptr;}; + ItemQualifier(string qualifier, bool linkQualifier = true); + uint32 GetId() { return itemId; } - uint32 GetRandomPropertyId() { return randomPropertyId; } + uint32 GetEnchantId() { return enchantId; } + int32 GetRandomPropertyId() { return randomPropertyId; } uint32 GetGem1() { return gem1; } uint32 GetGem2() { return gem2; } uint32 GetGem3() { return gem3; } - uint32 GetGem4() { return gem4; } - string GetQualifier() { return to_string(itemId) + ":0:" + to_string(randomPropertyId) + ":0:" + to_string(gem1) + ":" + to_string(gem2) + ":" + to_string(gem3) + ":" + to_string(gem4); } + uint32 GetGem4() { return gem4; } + +#ifdef MANGOSBOT_ZERO + string GetLinkQualifier() { return to_string(itemId) + ":" + to_string(enchantID) + ":" + to_string(randomPropertyId) + ":0"; } +#else + string GetLinkQualifier() { return to_string(itemId) + ":" + to_string(enchantId) + ":" + to_string(gem1) + ":" + to_string(gem2) + ":" + to_string(gem3) + ":" + to_string(gem4) + ":" + to_string(randomPropertyId) + ":0"; } +#endif + string GetQualifier() { return to_string(itemId) + ((enchantId || gem1 || gem2 || gem3 || gem4 || randomPropertyId) ? ":" + to_string(enchantId) + ":" + to_string(gem1) + ":" + to_string(gem2) + ":" + to_string(gem3) + ":" + to_string(gem4) + ":" + to_string(randomPropertyId) : ""); } - ItemPrototype const* GetProto() { ItemPrototype const* proto = sItemStorage.LookupEntry(itemId); return proto; }; + ItemPrototype const* GetProto() { if (!proto) proto = sItemStorage.LookupEntry(itemId); return proto; }; + static uint32 GemId(Item* item, uint8 gemSlot = 0); private: uint32 itemId; + uint32 enchantId; int32 randomPropertyId; uint32 gem1; uint32 gem2; uint32 gem3; uint32 gem4; + ItemPrototype const* proto; }; enum ItemUsage