aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-12-26 21:21:28 +0100
committerShauren <shauren.trinity@gmail.com>2016-12-26 21:21:28 +0100
commit87427321497aad5ba3c6dbc1b7f4838f255e052b (patch)
treea3bbb5512bb04d957448fa7686dd27a998b94568 /src/server/game
parent9f81cf445ff47507a9469d57808df231460793f1 (diff)
Core/Items: Implemented bonus list as a possible result of RandomSuffix
Ref #18423
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp3
-rw-r--r--src/server/game/Entities/Item/Item.cpp179
-rw-r--r--src/server/game/Entities/Item/Item.h7
-rw-r--r--src/server/game/Entities/Item/ItemEnchantmentMgr.cpp122
-rw-r--r--src/server/game/Entities/Item/ItemEnchantmentMgr.h20
-rw-r--r--src/server/game/Entities/Player/Player.cpp57
-rw-r--r--src/server/game/Entities/Player/Player.h8
-rw-r--r--src/server/game/Groups/Group.cpp10
-rw-r--r--src/server/game/Groups/Group.h2
-rw-r--r--src/server/game/Guilds/Guild.cpp4
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp22
-rw-r--r--src/server/game/Handlers/VoidStorageHandler.cpp2
-rw-r--r--src/server/game/Loot/LootMgr.h4
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp8
14 files changed, 254 insertions, 194 deletions
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
index 145b0709592..83d53144a7e 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
@@ -987,8 +987,7 @@ void AuctionBotSeller::AddNewAuctions(SellerConfiguration& config)
// Update the just created item so that if it needs random properties it has them.
// Ex: Notched Shortsword of Stamina will only generate as a Notched Shortsword without this.
- if (int32 randomPropertyId = Item::GenerateItemRandomPropertyId(itemId))
- item->SetItemRandomProperties(randomPropertyId);
+ item->SetItemRandomProperties(Item::GenerateItemRandomPropertyId(itemId));
uint32 buyoutPrice;
uint32 bidPrice = 0;
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index abc7e526f30..fc8ef4755f6 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -410,7 +410,8 @@ void Item::SaveToDB(SQLTransaction& trans)
}
stmt->setString(++index, ssEnchants.str());
- stmt->setInt16 (++index, GetItemRandomPropertyId());
+ stmt->setUInt8(++index, uint8(GetItemRandomEnchantmentId().Type));
+ stmt->setUInt32(++index, GetItemRandomEnchantmentId().Id);
stmt->setUInt16(++index, GetUInt32Value(ITEM_FIELD_DURABILITY));
stmt->setUInt32(++index, GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME));
stmt->setString(++index, m_text);
@@ -617,17 +618,17 @@ void Item::SaveToDB(SQLTransaction& trans)
bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fields, uint32 entry)
{
- // 0 1 2 3 4 5 6 7 8 9 10 11 12
- // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text,
- // 13 14 15 16 17 18
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyType, randomPropertyId, durability, playedTime, text,
+ // 14 15 16 17 18 19
// upgradeId, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, bonusListIDs,
- // 19 20 21 22 23
+ // 20 21 22 23 24
// itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4,
- // 24 25 26 27 28
+ // 25 26 27 28 29
// spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4,
- // 29 30 31 32 33 34 35 36 37 38 39 40
+ // 30 31 32 33 34 35 36 37 38 39 40 41
// gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3
- // 41 42
+ // 42 43
// fixedScalingLevel, artifactKnowledgeLevel FROM item_instance
// create item before any checks for store correct guid
@@ -684,12 +685,18 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
}
_LoadIntoDataField(fields[8].GetString(), ITEM_FIELD_ENCHANTMENT, MAX_ENCHANTMENT_SLOT * MAX_ENCHANTMENT_OFFSET);
- SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, fields[9].GetInt16());
- // recalculate suffix factor
- if (GetItemRandomPropertyId() < 0)
+ m_randomEnchantment.Type = ItemRandomEnchantmentType(fields[9].GetUInt8());
+ m_randomEnchantment.Id = fields[10].GetUInt32();
+ if (m_randomEnchantment.Type == ItemRandomEnchantmentType::Property)
+ SetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, m_randomEnchantment.Id);
+ else if (m_randomEnchantment.Type == ItemRandomEnchantmentType::Suffix)
+ {
+ SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, -int32(m_randomEnchantment.Id));
+ // recalculate suffix factor
UpdateItemSuffixFactor();
+ }
- uint32 durability = fields[10].GetUInt16();
+ uint32 durability = fields[11].GetUInt16();
SetUInt32Value(ITEM_FIELD_DURABILITY, durability);
// update max durability (and durability) if need
SetUInt32Value(ITEM_FIELD_MAXDURABILITY, proto->MaxDurability);
@@ -699,10 +706,10 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
need_save = true;
}
- SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, fields[11].GetUInt32());
- SetText(fields[12].GetString());
+ SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, fields[12].GetUInt32());
+ SetText(fields[13].GetString());
- uint32 upgradeId = fields[13].GetUInt32();
+ uint32 upgradeId = fields[14].GetUInt32();
ItemUpgradeEntry const* rulesetUpgrade = sItemUpgradeStore.LookupEntry(sDB2Manager.GetRulesetItemUpgrade(entry));
ItemUpgradeEntry const* upgrade = sItemUpgradeStore.LookupEntry(upgradeId);
if (!rulesetUpgrade || !upgrade || rulesetUpgrade->ItemUpgradePathID != upgrade->ItemUpgradePathID)
@@ -718,49 +725,49 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
}
SetModifier(ITEM_MODIFIER_UPGRADE_ID, upgradeId);
- SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, fields[14].GetUInt32());
- SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, fields[15].GetUInt32());
- SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, fields[16].GetUInt16());
- SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, fields[17].GetUInt32());
+ SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, fields[15].GetUInt32());
+ SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, fields[16].GetUInt32());
+ SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, fields[17].GetUInt16());
+ SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, fields[18].GetUInt32());
- Tokenizer bonusListIDs(fields[18].GetString(), ' ');
+ Tokenizer bonusListIDs(fields[19].GetString(), ' ');
for (char const* token : bonusListIDs)
{
uint32 bonusListID = atoul(token);
AddBonuses(bonusListID);
}
- SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS, fields[19].GetUInt32());
- SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1, fields[20].GetUInt32());
- SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_2, fields[21].GetUInt32());
- SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_3, fields[22].GetUInt32());
- SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4, fields[23].GetUInt32());
+ SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS, fields[20].GetUInt32());
+ SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1, fields[21].GetUInt32());
+ SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_2, fields[22].GetUInt32());
+ SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_3, fields[23].GetUInt32());
+ SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4, fields[24].GetUInt32());
- SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS, fields[24].GetUInt32());
- SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1, fields[25].GetUInt32());
- SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2, fields[26].GetUInt32());
- SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3, fields[27].GetUInt32());
- SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4, fields[28].GetUInt32());
+ SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS, fields[25].GetUInt32());
+ SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1, fields[26].GetUInt32());
+ SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2, fields[27].GetUInt32());
+ SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3, fields[28].GetUInt32());
+ SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4, fields[29].GetUInt32());
uint32 const gemFields = 4;
ItemDynamicFieldGems gemData[MAX_GEM_SOCKETS];
memset(gemData, 0, sizeof(gemData));
for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)
{
- gemData[i].ItemId = fields[29 + i * gemFields].GetUInt32();
- Tokenizer gemBonusListIDs(fields[30 + i * gemFields].GetString(), ' ');
+ gemData[i].ItemId = fields[30 + i * gemFields].GetUInt32();
+ Tokenizer gemBonusListIDs(fields[31 + i * gemFields].GetString(), ' ');
uint32 b = 0;
for (char const* token : gemBonusListIDs)
if (uint32 bonusListID = atoul(token))
gemData[i].BonusListIDs[b++] = bonusListID;
- gemData[i].Context = fields[31 + i * gemFields].GetUInt8();
+ gemData[i].Context = fields[32 + i * gemFields].GetUInt8();
if (gemData[i].ItemId)
- SetGem(i, &gemData[i], fields[32 + i * gemFields].GetUInt32());
+ SetGem(i, &gemData[i], fields[33 + i * gemFields].GetUInt32());
}
- SetModifier(ITEM_MODIFIER_SCALING_STAT_DISTRIBUTION_FIXED_LEVEL, fields[41].GetUInt32());
- SetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL, fields[42].GetUInt32());
+ SetModifier(ITEM_MODIFIER_SCALING_STAT_DISTRIBUTION_FIXED_LEVEL, fields[42].GetUInt32());
+ SetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL, fields[43].GetUInt32());
if (need_save) // normal item changed state set not work at loading
{
@@ -876,82 +883,69 @@ uint32 Item::GetSkill()
return proto->GetSkill();
}
-int32 Item::GenerateItemRandomPropertyId(uint32 item_id)
+ItemRandomEnchantmentId Item::GenerateItemRandomPropertyId(uint32 item_id)
{
ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id);
-
if (!itemProto)
- return 0;
+ return{};
// item must have one from this field values not null if it can have random enchantments
- if ((!itemProto->GetRandomProperty()) && (!itemProto->GetRandomSuffix()))
- return 0;
+ if (!itemProto->GetRandomProperty() && !itemProto->GetRandomSuffix())
+ return{};
// item can have not null only one from field values
- if ((itemProto->GetRandomProperty()) && (itemProto->GetRandomSuffix()))
+ if (itemProto->GetRandomProperty() && itemProto->GetRandomSuffix())
{
TC_LOG_ERROR("sql.sql", "Item template %u have RandomProperty == %u and RandomSuffix == %u, but must have one from field =0", itemProto->GetId(), itemProto->GetRandomProperty(), itemProto->GetRandomSuffix());
- return 0;
+ return{};
}
// RandomProperty case
if (itemProto->GetRandomProperty())
- {
- uint32 randomPropId = GetItemEnchantMod(itemProto->GetRandomProperty());
- if (!sItemRandomPropertiesStore.LookupEntry(randomPropId))
- {
- TC_LOG_ERROR("sql.sql", "Enchantment id #%u used but it doesn't have records in 'ItemRandomProperties.dbc'", randomPropId);
- return 0;
- }
-
- return randomPropId;
- }
+ return GetItemEnchantMod(itemProto->GetRandomProperty(), ItemRandomEnchantmentType::Property);
// RandomSuffix case
else
- {
- uint32 randomPropId = GetItemEnchantMod(itemProto->GetRandomSuffix());
- if (!sItemRandomSuffixStore.LookupEntry(randomPropId))
- {
- TC_LOG_ERROR("sql.sql", "Enchantment id #%u used but it doesn't have records in sItemRandomSuffixStore.", randomPropId);
- return 0;
- }
-
- return -int32(randomPropId);
- }
+ return GetItemEnchantMod(itemProto->GetRandomSuffix(), ItemRandomEnchantmentType::Suffix);
}
-void Item::SetItemRandomProperties(int32 randomPropId)
+void Item::SetItemRandomProperties(ItemRandomEnchantmentId const& randomPropId)
{
- if (!randomPropId)
+ if (!randomPropId.Id)
return;
- if (randomPropId > 0)
+ switch (randomPropId.Type)
{
- if (ItemRandomPropertiesEntry const* item_rand = sItemRandomPropertiesStore.LookupEntry(randomPropId))
- {
- if (GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID) != randomPropId)
+ case ItemRandomEnchantmentType::Property:
+ if (ItemRandomPropertiesEntry const* item_rand = sItemRandomPropertiesStore.LookupEntry(randomPropId.Id))
{
- SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, randomPropId);
- SetState(ITEM_CHANGED, GetOwner());
+ if (GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID) != randomPropId.Id)
+ {
+ SetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, randomPropId.Id);
+ SetState(ITEM_CHANGED, GetOwner());
+ }
+ for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i <= PROP_ENCHANTMENT_SLOT_4; ++i)
+ SetEnchantment(EnchantmentSlot(i), item_rand->Enchantment[i - PROP_ENCHANTMENT_SLOT_0], 0, 0);
}
- for (uint32 i = PROP_ENCHANTMENT_SLOT_1; i < PROP_ENCHANTMENT_SLOT_1 + 3; ++i)
- SetEnchantment(EnchantmentSlot(i), item_rand->Enchantment[i - PROP_ENCHANTMENT_SLOT_1], 0, 0);
- }
- }
- else
- {
- if (ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(-randomPropId))
- {
- if (GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID) != randomPropId || !GetItemSuffixFactor())
+ break;
+ case ItemRandomEnchantmentType::Suffix:
+ if (ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(randomPropId.Id))
{
- SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, randomPropId);
- UpdateItemSuffixFactor();
- SetState(ITEM_CHANGED, GetOwner());
- }
+ if (GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID) != -int32(randomPropId.Id) || !GetItemSuffixFactor())
+ {
+ SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, -int32(randomPropId.Id));
+ UpdateItemSuffixFactor();
+ SetState(ITEM_CHANGED, GetOwner());
+ }
- for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i <= PROP_ENCHANTMENT_SLOT_4; ++i)
- SetEnchantment(EnchantmentSlot(i), item_rand->Enchantment[i - PROP_ENCHANTMENT_SLOT_0], 0, 0);
- }
+ for (uint32 i = PROP_ENCHANTMENT_SLOT_0; i <= PROP_ENCHANTMENT_SLOT_4; ++i)
+ SetEnchantment(EnchantmentSlot(i), item_rand->Enchantment[i - PROP_ENCHANTMENT_SLOT_0], 0, 0);
+ }
+ break;
+ case ItemRandomEnchantmentType::BonusList:
+ AddBonuses(randomPropId.Id);
+ break;
+ default:
+ break;
}
}
@@ -1412,7 +1406,7 @@ Item* Item::CloneItem(uint32 count, Player const* player) const
newItem->SetUInt32Value(ITEM_FIELD_DURATION, GetUInt32Value(ITEM_FIELD_DURATION));
// player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
if (player)
- newItem->SetItemRandomProperties(GetItemRandomPropertyId());
+ newItem->SetItemRandomProperties(GetItemRandomEnchantmentId());
return newItem;
}
@@ -2048,8 +2042,9 @@ void Item::ItemContainerSaveLootToDB()
stmt_items->setBool(6, _li->is_counted);
stmt_items->setBool(7, _li->is_underthreshold);
stmt_items->setBool(8, _li->needs_quest);
- stmt_items->setInt32(9, _li->randomPropertyId);
- stmt_items->setUInt32(10, _li->randomSuffix);
+ stmt_items->setUInt8(9, uint8(_li->randomPropertyId.Type));
+ stmt_items->setUInt32(10, _li->randomPropertyId.Id);
+ stmt_items->setUInt32(11, _li->randomSuffix);
trans->Append(stmt_items);
}
}
@@ -2107,8 +2102,8 @@ bool Item::ItemContainerLoadLootFromDB()
loot_item.canSave = true;
loot_item.is_underthreshold = fields[6].GetBool();
loot_item.needs_quest = fields[7].GetBool();
- loot_item.randomPropertyId = fields[8].GetInt32();
- loot_item.randomSuffix = fields[9].GetUInt32();
+ loot_item.randomPropertyId = { ItemRandomEnchantmentType(fields[8].GetUInt8()), fields[9].GetUInt32() };
+ loot_item.randomSuffix = fields[10].GetUInt32();
// Copy the extra loot conditions from the item in the loot template
lt->CopyConditions(&loot_item);
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 6fdc8e212b4..bef82a76013 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -22,6 +22,7 @@
#include "Common.h"
#include "Object.h"
#include "LootMgr.h"
+#include "ItemEnchantmentMgr.h"
#include "ItemTemplate.h"
#include "DatabaseEnv.h"
@@ -395,9 +396,10 @@ class TC_GAME_API Item : public Object
// RandomPropertyId (signed but stored as unsigned)
int32 GetItemRandomPropertyId() const { return GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); }
uint32 GetItemSuffixFactor() const { return GetUInt32Value(ITEM_FIELD_PROPERTY_SEED); }
- void SetItemRandomProperties(int32 randomPropId);
+ void SetItemRandomProperties(ItemRandomEnchantmentId const& randomPropId);
void UpdateItemSuffixFactor();
- static int32 GenerateItemRandomPropertyId(uint32 item_id);
+ static ItemRandomEnchantmentId GenerateItemRandomPropertyId(uint32 item_id);
+ ItemRandomEnchantmentId GetItemRandomEnchantmentId() const { return m_randomEnchantment; }
void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster = ObjectGuid::Empty);
void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player* owner);
void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges);
@@ -528,6 +530,7 @@ class TC_GAME_API Item : public Object
uint32 m_paidMoney;
uint32 m_paidExtendedCost;
GuidSet allowedGUIDs;
+ ItemRandomEnchantmentId m_randomEnchantment; // store separately to easily find which bonus list is the one randomly given for stat rerolling
ObjectGuid m_childItem;
std::unordered_map<uint32, uint16> m_artifactPowerIdToIndex;
std::array<uint32, MAX_ITEM_PROTO_SOCKETS> m_gemScalingLevels;
diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
index ac9000ded5e..f2723a97981 100644
--- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
+++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
@@ -17,6 +17,7 @@
*/
#include "ItemEnchantmentMgr.h"
+#include "Containers.h"
#include "DatabaseEnv.h"
#include "Log.h"
#include "ObjectMgr.h"
@@ -28,29 +29,41 @@
struct EnchStoreItem
{
+ ItemRandomEnchantmentType type;
uint32 ench;
float chance;
EnchStoreItem()
- : ench(0), chance(0) { }
+ : type(ItemRandomEnchantmentType::Property), ench(0), chance(0) { }
- EnchStoreItem(uint32 _ench, float _chance)
- : ench(_ench), chance(_chance) { }
+ EnchStoreItem(ItemRandomEnchantmentType _type, uint32 _ench, float _chance)
+ : type(_type), ench(_ench), chance(_chance) { }
};
typedef std::vector<EnchStoreItem> EnchStoreList;
-typedef std::unordered_map<uint32, EnchStoreList> EnchantmentStore;
-static EnchantmentStore RandomItemEnch;
+class EnchantmentStore
+{
+ std::unordered_map<uint32, EnchStoreList> _data[2];
+
+public:
+ std::unordered_map<uint32, EnchStoreList>& operator[](ItemRandomEnchantmentType type)
+ {
+ ASSERT(type != ItemRandomEnchantmentType::BonusList, "Random bonus lists do not have their own storage, use Suffix for them");
+ return _data[uint8(type)];
+ }
+
+} static RandomItemEnch;
void LoadRandomEnchantmentsTable()
{
uint32 oldMSTime = getMSTime();
- RandomItemEnch.clear(); // for reload case
+ RandomItemEnch[ItemRandomEnchantmentType::Property].clear();
+ RandomItemEnch[ItemRandomEnchantmentType::Suffix].clear();
- // 0 1 2
- QueryResult result = WorldDatabase.Query("SELECT entry, ench, chance FROM item_enchantment_template");
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT entry, type, ench, chance FROM item_enchantment_template");
if (result)
{
@@ -61,11 +74,56 @@ void LoadRandomEnchantmentsTable()
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
- uint32 ench = fields[1].GetUInt32();
- float chance = fields[2].GetFloat();
-
- if (chance > 0.000001f && chance <= 100.0f)
- RandomItemEnch[entry].push_back(EnchStoreItem(ench, chance));
+ ItemRandomEnchantmentType type = ItemRandomEnchantmentType(fields[1].GetUInt8());
+ uint32 ench = fields[2].GetUInt32();
+ float chance = fields[3].GetFloat();
+
+ switch (type)
+ {
+ case ItemRandomEnchantmentType::Property:
+ if (!sItemRandomPropertiesStore.LookupEntry(ench))
+ {
+ TC_LOG_ERROR("sql.sql", "Property %u used in `item_enchantment_template` by entry %u doesn't have exist in ItemRandomProperties.db2", ench, entry);
+ continue;
+ }
+ break;
+ case ItemRandomEnchantmentType::Suffix:
+ if (!sItemRandomSuffixStore.LookupEntry(ench))
+ {
+ TC_LOG_ERROR("sql.sql", "Suffix %u used in `item_enchantment_template` by entry %u doesn't have exist in ItemRandomSuffix.db2", ench, entry);
+ continue;
+ }
+ break;
+ case ItemRandomEnchantmentType::BonusList:
+ if (!sDB2Manager.GetItemBonusList(ench))
+ {
+ TC_LOG_ERROR("sql.sql", "Bonus list %u used in `item_enchantment_template` by entry %u doesn't have exist in ItemBonus.db2", ench, entry);
+ continue;
+ }
+ break;
+ default:
+ TC_LOG_ERROR("sql.sql", "Invalid random enchantment type specified in `item_enchantment_template` table for `entry` %u `ench` %u", entry, ench);
+ break;
+ }
+
+ if (chance < 0.000001f || chance > 100.0f)
+ {
+ TC_LOG_ERROR("sql.sql", "Random item enchantment for entry %u type %u ench %u has invalid chance %f", entry, uint32(type), ench, chance);
+ continue;
+ }
+
+ switch (type)
+ {
+ case ItemRandomEnchantmentType::Property:
+ RandomItemEnch[ItemRandomEnchantmentType::Property][entry].emplace_back(type, ench, chance);
+ break;
+ case ItemRandomEnchantmentType::Suffix:
+ case ItemRandomEnchantmentType::BonusList: // random bonus lists use RandomSuffix field in Item-sparse.db2
+ RandomItemEnch[ItemRandomEnchantmentType::Suffix][entry].emplace_back(type, ench, chance);
+ break;
+ default:
+ break;
+ }
++count;
} while (result->NextRow());
@@ -76,45 +134,27 @@ void LoadRandomEnchantmentsTable()
TC_LOG_ERROR("server.loading", ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty.");
}
-uint32 GetItemEnchantMod(int32 entry)
+ItemRandomEnchantmentId GetItemEnchantMod(int32 entry, ItemRandomEnchantmentType type)
{
if (!entry)
- return 0;
+ return{};
if (entry == -1)
- return 0;
+ return{};
- EnchantmentStore::const_iterator tab = RandomItemEnch.find(entry);
- if (tab == RandomItemEnch.end())
+ auto tab = RandomItemEnch[type].find(entry);
+ if (tab == RandomItemEnch[type].end())
{
TC_LOG_ERROR("sql.sql", "Item RandomProperty / RandomSuffix id #%u used in `item_template` but it does not have records in `item_enchantment_template` table.", entry);
- return 0;
+ return{};
}
- double dRoll = rand_chance();
- float fCount = 0;
-
- for (EnchStoreList::const_iterator ench_iter = tab->second.begin(); ench_iter != tab->second.end(); ++ench_iter)
+ auto selectedItr = Trinity::Containers::SelectRandomWeightedContainerElement(tab->second, [](EnchStoreItem const& enchant)
{
- fCount += ench_iter->chance;
-
- if (fCount > dRoll)
- return ench_iter->ench;
- }
+ return enchant.chance;
+ });
- //we could get here only if sum of all enchantment chances is lower than 100%
- dRoll = (irand(0, (int)floor(fCount * 100) + 1)) / 100;
- fCount = 0;
-
- for (EnchStoreList::const_iterator ench_iter = tab->second.begin(); ench_iter != tab->second.end(); ++ench_iter)
- {
- fCount += ench_iter->chance;
-
- if (fCount > dRoll)
- return ench_iter->ench;
- }
-
- return 0;
+ return{ selectedItr->type, selectedItr->ench };
}
uint32 GenerateEnchSuffixFactor(uint32 item_id)
diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.h b/src/server/game/Entities/Item/ItemEnchantmentMgr.h
index ec84b13dec5..9ef98545505 100644
--- a/src/server/game/Entities/Item/ItemEnchantmentMgr.h
+++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.h
@@ -21,9 +21,25 @@
#include "Common.h"
+enum class ItemRandomEnchantmentType : uint8
+{
+ Property = 0,
+ Suffix = 1,
+ BonusList = 2
+};
+
+struct ItemRandomEnchantmentId
+{
+ ItemRandomEnchantmentId() = default;
+ ItemRandomEnchantmentId(ItemRandomEnchantmentType type, uint32 id) : Type(type), Id(id) { }
+
+ ItemRandomEnchantmentType Type = ItemRandomEnchantmentType::Property;
+ uint32 Id = 0;
+};
+
TC_GAME_API void LoadRandomEnchantmentsTable();
-TC_GAME_API uint32 GetItemEnchantMod(int32 entry);
+TC_GAME_API ItemRandomEnchantmentId GetItemEnchantMod(int32 entry, ItemRandomEnchantmentType type);
TC_GAME_API uint32 GenerateEnchSuffixFactor(uint32 item_id);
TC_GAME_API uint32 GetRandomPropertyPoints(uint32 itemLevel, uint32 quality, uint32 inventoryType, uint32 subclass);
-#endif
+#endif
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 5b8302dc794..77e2870a24e 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -11421,7 +11421,7 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
}
// Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
-Item* Player::StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool update, int32 randomPropertyId /*= 0*/, GuidSet const& allowedLooters /*= GuidSet()*/, std::vector<int32> const& bonusListIDs /*= std::vector<int32>()*/, bool addToCollection /*= true*/)
+Item* Player::StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool update, ItemRandomEnchantmentId const& randomPropertyId /*= {}*/, GuidSet const& allowedLooters /*= GuidSet()*/, std::vector<int32> const& bonusListIDs /*= std::vector<int32>()*/, bool addToCollection /*= true*/)
{
uint32 count = 0;
for (ItemPosCountVec::const_iterator itr = pos.begin(); itr != pos.end(); ++itr)
@@ -11434,8 +11434,7 @@ Item* Player::StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool updat
UpdateCriteria(CRITERIA_TYPE_RECEIVE_EPIC_ITEM, itemId, count);
UpdateCriteria(CRITERIA_TYPE_OWN_ITEM, itemId, 1);
- if (randomPropertyId)
- item->SetItemRandomProperties(randomPropertyId);
+ item->SetItemRandomProperties(randomPropertyId);
if (uint32 upgradeID = sDB2Manager.GetRulesetItemUpgrade(itemId))
item->SetModifier(ITEM_MODIFIER_UPGRADE_ID, upgradeID);
@@ -11473,7 +11472,7 @@ Item* Player::StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool updat
{
ItemPosCountVec childDest;
CanStoreItem_InInventorySlots(CHILD_EQUIPMENT_SLOT_START, CHILD_EQUIPMENT_SLOT_END, childDest, childTemplate, count, false, nullptr, NULL_BAG, NULL_SLOT);
- if (Item* childItem = StoreNewItem(childDest, childTemplate->GetId(), update, 0, {}, {}, addToCollection))
+ if (Item* childItem = StoreNewItem(childDest, childTemplate->GetId(), update, {}, {}, {}, addToCollection))
{
childItem->SetGuidValue(ITEM_FIELD_CREATOR, item->GetGUID());
childItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_CHILD);
@@ -18002,18 +18001,20 @@ void Player::LoadCorpse(PreparedQueryResult result)
void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult artifactsResult, uint32 timeDiff)
{
- // 0 1 2 3 4 5 6 7 8 9 10 11 12
- // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text,
- // 13 14 15 16 17 18
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyType, randomPropertyId, durability, playedTime, text,
+ // 14 15 16 17 18 19
// upgradeId, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, bonusListIDs,
- // 19 20 21 22 23
+ // 20 21 22 23 24
// itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4,
- // 24 25 26 27 28
+ // 25 26 27 28 29
// spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4,
- // 29 30 31 32 33 34 35 36 37 38 39 40
+ // 30 31 32 33 34 35 36 37 38 39 40 41
// gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3
- // 41 42 43 44
- // fixedScalingLevel, artifactKnowledgeLevel, bag, slot
+ // 42 43
+ // fixedScalingLevel, artifactKnowledgeLevel
+ // 44 45
+ // bag, slot
// FROM character_inventory ci
// JOIN item_instance ii ON ci.item = ii.guid
// LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid
@@ -18075,8 +18076,8 @@ void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult arti
if (item->GetTemplate()->GetArtifactID() && artifactDataItr != artifactData.end())
item->LoadArtifactData(std::get<0>(artifactDataItr->second), std::get<1>(artifactDataItr->second), std::get<2>(artifactDataItr->second));
- ObjectGuid bagGuid = fields[43].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[43].GetUInt64()) : ObjectGuid::Empty;
- uint8 slot = fields[44].GetUInt8();
+ ObjectGuid bagGuid = fields[44].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[44].GetUInt64()) : ObjectGuid::Empty;
+ uint8 slot = fields[45].GetUInt8();
GetSession()->GetCollectionMgr()->CheckHeirloomUpgrades(item);
GetSession()->GetCollectionMgr()->AddItemAppearance(item);
@@ -18210,13 +18211,13 @@ void Player::_LoadVoidStorage(PreparedQueryResult result)
uint32 itemEntry = fields[1].GetUInt32();
uint8 slot = fields[2].GetUInt8();
ObjectGuid creatorGuid = fields[3].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[3].GetUInt64()) : ObjectGuid::Empty;
- uint32 randomProperty = fields[4].GetUInt32();
- uint32 suffixFactor = fields[5].GetUInt32();
- uint32 upgradeId = fields[6].GetUInt32();
- uint32 fixedScalingLevel = fields[7].GetUInt32();
- uint32 artifactKnowledgeLevel = fields[8].GetUInt32();
+ ItemRandomEnchantmentId randomProperty(ItemRandomEnchantmentType(fields[4].GetUInt8()), fields[5].GetUInt32());
+ uint32 suffixFactor = fields[6].GetUInt32();
+ uint32 upgradeId = fields[7].GetUInt32();
+ uint32 fixedScalingLevel = fields[8].GetUInt32();
+ uint32 artifactKnowledgeLevel = fields[9].GetUInt32();
std::vector<uint32> bonusListIDs;
- Tokenizer bonusListIdTokens(fields[9].GetString(), ' ');
+ Tokenizer bonusListIdTokens(fields[10].GetString(), ' ');
for (char const* token : bonusListIdTokens)
bonusListIDs.push_back(atoul(token));
@@ -18417,7 +18418,7 @@ void Player::_LoadMailedItems(Mail* mail)
Item* item = NewItemOrBag(proto);
- ObjectGuid ownerGuid = fields[43].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[43].GetUInt64()) : ObjectGuid::Empty;
+ ObjectGuid ownerGuid = fields[44].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[44].GetUInt64()) : ObjectGuid::Empty;
if (!item->LoadFromDB(itemGuid, ownerGuid, fields, itemEntry))
{
TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems: Item (GUID: " UI64FMTD ") in mail (%u) doesn't exist, deleted from mail.", itemGuid, mail->messageID);
@@ -19955,22 +19956,22 @@ void Player::_SaveVoidStorage(SQLTransaction& trans)
stmt->setUInt32(2, _voidStorageItems[i]->ItemEntry);
stmt->setUInt8(3, i);
stmt->setUInt64(4, _voidStorageItems[i]->CreatorGuid.GetCounter());
- stmt->setUInt32(5, _voidStorageItems[i]->ItemRandomPropertyId);
- stmt->setUInt32(6, _voidStorageItems[i]->ItemSuffixFactor);
- stmt->setUInt32(7, _voidStorageItems[i]->ItemUpgradeId);
- stmt->setUInt32(8, _voidStorageItems[i]->FixedScalingLevel);
- stmt->setUInt32(9, _voidStorageItems[i]->ArtifactKnowledgeLevel);
+ stmt->setUInt8(5, uint8(_voidStorageItems[i]->ItemRandomPropertyId.Type));
+ stmt->setUInt32(6, _voidStorageItems[i]->ItemRandomPropertyId.Id);
+ stmt->setUInt32(7, _voidStorageItems[i]->ItemSuffixFactor);
+ stmt->setUInt32(8, _voidStorageItems[i]->ItemUpgradeId);
+ stmt->setUInt32(9, _voidStorageItems[i]->FixedScalingLevel);
+ stmt->setUInt32(10, _voidStorageItems[i]->ArtifactKnowledgeLevel);
std::ostringstream bonusListIDs;
for (int32 bonusListID : _voidStorageItems[i]->BonusListIDs)
bonusListIDs << bonusListID << ' ';
- stmt->setString(10, bonusListIDs.str());
+ stmt->setString(11, bonusListIDs.str());
}
trans->Append(stmt);
}
}
-
void Player::_SaveCUFProfiles(SQLTransaction& trans)
{
PreparedStatement* stmt;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index a9d12310683..ee23fb76cdc 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1132,8 +1132,8 @@ struct BGData
struct VoidStorageItem
{
- VoidStorageItem() : ItemId(0), ItemEntry(0), ItemRandomPropertyId(0), ItemSuffixFactor(0), ItemUpgradeId(0), FixedScalingLevel(0), ArtifactKnowledgeLevel(0) { }
- VoidStorageItem(uint64 id, uint32 entry, ObjectGuid const& creator, uint32 randomPropertyId, uint32 suffixFactor,
+ VoidStorageItem() : ItemId(0), ItemEntry(0), ItemRandomPropertyId(), ItemSuffixFactor(0), ItemUpgradeId(0), FixedScalingLevel(0), ArtifactKnowledgeLevel(0) { }
+ VoidStorageItem(uint64 id, uint32 entry, ObjectGuid const& creator, ItemRandomEnchantmentId randomPropertyId, uint32 suffixFactor,
uint32 upgradeId, uint32 fixedScalingLevel, uint32 artifactKnowledgeLevel, std::vector<uint32> const& bonuses)
: ItemId(id), ItemEntry(entry), CreatorGuid(creator), ItemRandomPropertyId(randomPropertyId),
ItemSuffixFactor(suffixFactor), ItemUpgradeId(upgradeId), FixedScalingLevel(fixedScalingLevel), ArtifactKnowledgeLevel(artifactKnowledgeLevel)
@@ -1147,7 +1147,7 @@ struct VoidStorageItem
uint64 ItemId;
uint32 ItemEntry;
ObjectGuid CreatorGuid;
- uint32 ItemRandomPropertyId;
+ ItemRandomEnchantmentId ItemRandomPropertyId;
uint32 ItemSuffixFactor;
uint32 ItemUpgradeId;
uint32 FixedScalingLevel;
@@ -1384,7 +1384,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool HasItemTotemCategory(uint32 TotemCategory) const;
InventoryResult CanUseItem(ItemTemplate const* pItem) const;
InventoryResult CanRollForItemInLFG(ItemTemplate const* item, WorldObject const* lootedObject) const;
- Item* StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool update, int32 randomPropertyId = 0, GuidSet const& allowedLooters = GuidSet(), std::vector<int32> const& bonusListIDs = std::vector<int32>(), bool addToCollection = true);
+ Item* StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool update, ItemRandomEnchantmentId const& randomPropertyId = {}, GuidSet const& allowedLooters = GuidSet(), std::vector<int32> const& bonusListIDs = std::vector<int32>(), bool addToCollection = true);
Item* StoreItem(ItemPosCountVec const& pos, Item* pItem, bool update);
Item* EquipNewItem(uint16 pos, uint32 item, bool update);
Item* EquipItem(uint16 pos, Item* pItem, bool update);
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 479bd6d2da9..d855776fa3a 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -853,7 +853,7 @@ void Group::SendLootStartRoll(uint32 countDown, uint32 mapid, const Roll &r)
data << uint32(r.itemSlot); // itemslot
data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for
data << uint32(r.itemRandomSuffix); // randomSuffix
- data << uint32(r.itemRandomPropId); // item random property ID
+ data << uint32(r.itemRandomPropId.Id); // item random property ID
data << uint32(r.itemCount); // items in stack
data << uint32(countDown); // the countdown time to choose "need" or "greed"
data << uint8(r.rollVoteMask); // roll type mask
@@ -881,7 +881,7 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p,
data << uint32(r.itemSlot); // itemslot
data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for
data << uint32(r.itemRandomSuffix); // randomSuffix
- data << uint32(r.itemRandomPropId); // item random property ID
+ data << uint32(r.itemRandomPropId.Id); // item random property ID
data << uint32(r.itemCount); // items in stack
data << uint32(countDown); // the countdown time to choose "need" or "greed"
uint8 voteMask = r.rollVoteMask;
@@ -901,7 +901,7 @@ void Group::SendLootRoll(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8 rol
data << targetGuid;
data << uint32(roll.itemid); // the itemEntryId for the item that shall be rolled for
data << uint32(roll.itemRandomSuffix); // randomSuffix
- data << uint32(roll.itemRandomPropId); // Item random property ID
+ data << uint32(roll.itemRandomPropId.Id); // Item random property ID
data << uint32(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number
data << uint8(rollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll
data << uint8(0); // 1: "You automatically passed on: %s because you cannot loot that item." - Possibly used in need befor greed
@@ -924,7 +924,7 @@ void Group::SendLootRollWon(ObjectGuid sourceGuid, ObjectGuid targetGuid, uint8
data << uint32(roll.itemSlot); // slot
data << uint32(roll.itemid); // the itemEntryId for the item that shall be rolled for
data << uint32(roll.itemRandomSuffix); // randomSuffix
- data << uint32(roll.itemRandomPropId); // Item random property
+ data << uint32(roll.itemRandomPropId.Id); // Item random property
data << targetGuid; // guid of the player who won.
data << uint32(rollNumber); // rollnumber realted to SMSG_LOOT_ROLL
data << uint8(rollType); // rollType related to SMSG_LOOT_ROLL
@@ -946,7 +946,7 @@ void Group::SendLootAllPassed(Roll const& roll)
data << roll.itemGUID; // Guid of the item rolled
data << uint32(roll.itemSlot); // Item loot slot
data << uint32(roll.itemid); // The itemEntryId for the item that shall be rolled for
- data << uint32(roll.itemRandomPropId); // Item random property ID
+ data << uint32(roll.itemRandomPropId.Id); // Item random property ID
data << uint32(roll.itemRandomSuffix); // Item random suffix ID
for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr)
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 093d0d3d215..bf29b8f8a50 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -162,7 +162,7 @@ class Roll : public LootValidatorRef
ObjectGuid itemGUID;
uint32 itemid;
- int32 itemRandomPropId;
+ ItemRandomEnchantmentId itemRandomPropId;
uint32 itemRandomSuffix;
uint8 itemCount;
typedef std::map<ObjectGuid, RollVote> PlayerVote;
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 60f6d6acc9f..4848f75b4bd 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -368,7 +368,7 @@ void Guild::BankTab::LoadFromDB(Field* fields)
bool Guild::BankTab::LoadItemFromDB(Field* fields)
{
- uint8 slotId = fields[45].GetUInt8();
+ uint8 slotId = fields[46].GetUInt8();
ObjectGuid::LowType itemGuid = fields[0].GetUInt64();
uint32 itemEntry = fields[1].GetUInt32();
if (slotId >= GUILD_BANK_MAX_SLOTS)
@@ -2399,7 +2399,7 @@ void Guild::LoadBankTabFromDB(Field* fields)
bool Guild::LoadBankItemFromDB(Field* fields)
{
- uint8 tabId = fields[44].GetUInt8();
+ uint8 tabId = fields[45].GetUInt8();
if (tabId >= _GetPurchasedTabsSize())
{
TC_LOG_ERROR("guild", "Invalid tab for item (GUID: %u, id: #%u) in guild bank, skipped.",
diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp
index 151429ebb9b..292ec374257 100644
--- a/src/server/game/Guilds/GuildMgr.cpp
+++ b/src/server/game/Guilds/GuildMgr.cpp
@@ -401,17 +401,19 @@ void GuildMgr::LoadGuilds()
// Delete orphan guild bank items
CharacterDatabase.DirectExecute("DELETE gbi FROM guild_bank_item gbi LEFT JOIN guild g ON gbi.guildId = g.guildId WHERE g.guildId IS NULL");
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
- // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, upgradeId,
- // 14 15 16 17 18
- // battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, bonusListIDs,
- // 19 20 21 22 23
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyType, randomPropertyId, durability, playedTime, text,
+ // 14 15 16 17 18 19
+ // upgradeId, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, bonusListIDs,
+ // 20 21 22 23 24
// itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4,
- // 24 25 26 27 28
+ // 25 26 27 28 29
// spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4,
- // 29 30 31 32 33 34 35 36 37 38 39
- // gemItemId1, gemBonuses1, gemContext1, gemItemId2, gemBonuses2, gemContext2, gemItemId3, gemBonuses3, gemContext3, fixedScalingLevel, artifactKnowledgeLevel,
- // 40 41 42
+ // 30 31 32 33 34 35 36 37 38 39 40 41
+ // gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3
+ // 42 43
+ // fixedScalingLevel, artifactKnowledgeLevel
+ // 44 45 46
// guildid, TabId, SlotId FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid
PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_ITEMS));
@@ -425,7 +427,7 @@ void GuildMgr::LoadGuilds()
do
{
Field* fields = result->Fetch();
- uint64 guildId = fields[43].GetUInt64();
+ uint64 guildId = fields[44].GetUInt64();
if (Guild* guild = GetGuildById(guildId))
guild->LoadBankItemFromDB(fields);
diff --git a/src/server/game/Handlers/VoidStorageHandler.cpp b/src/server/game/Handlers/VoidStorageHandler.cpp
index ee4d43dff08..cf3ef7abcbc 100644
--- a/src/server/game/Handlers/VoidStorageHandler.cpp
+++ b/src/server/game/Handlers/VoidStorageHandler.cpp
@@ -155,7 +155,7 @@ void WorldSession::HandleVoidStorageTransfer(WorldPackets::VoidStorage::VoidStor
}
VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetGuidValue(ITEM_FIELD_CREATOR),
- item->GetItemRandomPropertyId(), item->GetItemSuffixFactor(), item->GetModifier(ITEM_MODIFIER_UPGRADE_ID),
+ item->GetItemRandomEnchantmentId(), item->GetItemSuffixFactor(), item->GetModifier(ITEM_MODIFIER_UPGRADE_ID),
item->GetModifier(ITEM_MODIFIER_SCALING_STAT_DISTRIBUTION_FIXED_LEVEL), item->GetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL),
item->GetDynamicValues(ITEM_DYNAMIC_FIELD_BONUSLIST_IDS));
diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h
index 4fea6967ef4..b7d3ba2123b 100644
--- a/src/server/game/Loot/LootMgr.h
+++ b/src/server/game/Loot/LootMgr.h
@@ -155,7 +155,7 @@ struct TC_GAME_API LootItem
{
uint32 itemid;
uint32 randomSuffix;
- int32 randomPropertyId;
+ ItemRandomEnchantmentId randomPropertyId;
int32 upgradeId;
std::vector<int32> BonusListIDs;
ConditionContainer conditions; // additional loot condition
@@ -175,7 +175,7 @@ struct TC_GAME_API LootItem
explicit LootItem(LootStoreItem const& li);
// Empty constructor for creating an empty LootItem to be filled in with DB data
- LootItem() : itemid(0), randomSuffix(0), randomPropertyId(0), upgradeId(0), count(0), is_looted(false), is_blocked(false),
+ LootItem() : itemid(0), randomSuffix(0), randomPropertyId(), upgradeId(0), count(0), is_looted(false), is_blocked(false),
freeforall(false), is_underthreshold(false), is_counted(false), needs_quest(false), follow_loot_rules(false),
canSave(true){ };
diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp
index 1311a32a460..a689bf2f627 100644
--- a/src/server/game/Server/Packets/ItemPackets.cpp
+++ b/src/server/game/Server/Packets/ItemPackets.cpp
@@ -308,7 +308,9 @@ void WorldPackets::Item::ItemInstance::Initialize(::LootItem const& lootItem)
{
ItemID = lootItem.itemid;
RandomPropertiesSeed = lootItem.randomSuffix;
- RandomPropertiesID = lootItem.randomPropertyId;
+ if (lootItem.randomPropertyId.Type != ItemRandomEnchantmentType::BonusList)
+ RandomPropertiesID = lootItem.randomPropertyId.Id;
+
if (!lootItem.BonusListIDs.empty())
{
ItemBonus = boost::in_place();
@@ -326,8 +328,10 @@ void WorldPackets::Item::ItemInstance::Initialize(::LootItem const& lootItem)
void WorldPackets::Item::ItemInstance::Initialize(::VoidStorageItem const* voidItem)
{
ItemID = voidItem->ItemEntry;
- RandomPropertiesID = voidItem->ItemRandomPropertyId;
RandomPropertiesSeed = voidItem->ItemSuffixFactor;
+ if (voidItem->ItemRandomPropertyId.Type != ItemRandomEnchantmentType::BonusList)
+ RandomPropertiesID = voidItem->ItemRandomPropertyId.Id;
+
if (voidItem->ItemUpgradeId || voidItem->FixedScalingLevel || voidItem->ArtifactKnowledgeLevel)
{
Modifications = boost::in_place();