Core/Loot: implement Loot Item Storage
Port From (https://github.com/TrinityCore/TrinityCore/commit/090fd8304a7a6e2f7c233ac39c94ccc67cc816f8)
This commit is contained in:
@@ -682,11 +682,11 @@ namespace Framework.Database
|
|||||||
PrepareStatement(CharStatements.DEL_GUILD_FINDER_GUILD_SETTINGS, "DELETE FROM guild_finder_guild_settings WHERE guildId = ?");
|
PrepareStatement(CharStatements.DEL_GUILD_FINDER_GUILD_SETTINGS, "DELETE FROM guild_finder_guild_settings WHERE guildId = ?");
|
||||||
|
|
||||||
// Items that hold loot or money
|
// Items that hold loot or money
|
||||||
PrepareStatement(CharStatements.SEL_ITEMCONTAINER_ITEMS, "SELECT item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_bonus, context, bonus_list_ids FROM item_loot_items WHERE container_id = ?");
|
PrepareStatement(CharStatements.SEL_ITEMCONTAINER_ITEMS, "SELECT container_id, item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_bonus, context, bonus_list_ids FROM item_loot_items");
|
||||||
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_ITEMS, "DELETE FROM item_loot_items WHERE container_id = ?");
|
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_ITEMS, "DELETE FROM item_loot_items WHERE container_id = ?");
|
||||||
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_ITEM, "DELETE FROM item_loot_items WHERE container_id = ? AND item_id = ?");
|
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_ITEM, "DELETE FROM item_loot_items WHERE container_id = ? AND item_id = ? AND item_count = ?");
|
||||||
PrepareStatement(CharStatements.INS_ITEMCONTAINER_ITEMS, "INSERT INTO item_loot_items (container_id, item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_bonus, context, bonus_list_ids) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
PrepareStatement(CharStatements.INS_ITEMCONTAINER_ITEMS, "INSERT INTO item_loot_items (container_id, item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_bonus, context, bonus_list_ids) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
PrepareStatement(CharStatements.SEL_ITEMCONTAINER_MONEY, "SELECT money FROM item_loot_money WHERE container_id = ?");
|
PrepareStatement(CharStatements.SEL_ITEMCONTAINER_MONEY, "SELECT container_id, money FROM item_loot_money");
|
||||||
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_MONEY, "DELETE FROM item_loot_money WHERE container_id = ?");
|
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_MONEY, "DELETE FROM item_loot_money WHERE container_id = ?");
|
||||||
PrepareStatement(CharStatements.INS_ITEMCONTAINER_MONEY, "INSERT INTO item_loot_money (container_id, money) VALUES (?, ?)");
|
PrepareStatement(CharStatements.INS_ITEMCONTAINER_MONEY, "INSERT INTO item_loot_money (container_id, money) VALUES (?, ?)");
|
||||||
|
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
// Delete the items if this is a container
|
// Delete the items if this is a container
|
||||||
if (!loot.IsLooted())
|
if (!loot.IsLooted())
|
||||||
ItemContainerDeleteLootMoneyAndLootItemsFromDB();
|
Global.LootItemStorage.RemoveStoredLootForContainer(GetGUID().GetCounter());
|
||||||
|
|
||||||
Dispose();
|
Dispose();
|
||||||
return;
|
return;
|
||||||
@@ -662,7 +662,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
// Delete the items if this is a container
|
// Delete the items if this is a container
|
||||||
if (!loot.IsLooted())
|
if (!loot.IsLooted())
|
||||||
ItemContainerDeleteLootMoneyAndLootItemsFromDB();
|
Global.LootItemStorage.RemoveStoredLootForContainer(GetGUID().GetCounter());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DeleteFromInventoryDB(SQLTransaction trans, ulong itemGuid)
|
public static void DeleteFromInventoryDB(SQLTransaction trans, ulong itemGuid)
|
||||||
@@ -1744,188 +1744,6 @@ namespace Game.Entities
|
|||||||
return proto.GetSellPrice();
|
return proto.GetSellPrice();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ItemContainerSaveLootToDB()
|
|
||||||
{
|
|
||||||
// Saves the money and item loot associated with an openable item to the DB
|
|
||||||
if (loot.IsLooted()) // no money and no loot
|
|
||||||
return;
|
|
||||||
|
|
||||||
SQLTransaction trans = new SQLTransaction();
|
|
||||||
|
|
||||||
loot.containerID = GetGUID(); // Save this for when a LootItem is removed
|
|
||||||
|
|
||||||
// Save money
|
|
||||||
if (loot.gold > 0)
|
|
||||||
{
|
|
||||||
PreparedStatement stmt_money = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_MONEY);
|
|
||||||
stmt_money.AddValue(0, loot.containerID.GetCounter());
|
|
||||||
trans.Append(stmt_money);
|
|
||||||
|
|
||||||
stmt_money = DB.Characters.GetPreparedStatement(CharStatements.INS_ITEMCONTAINER_MONEY);
|
|
||||||
stmt_money.AddValue(0, loot.containerID.GetCounter());
|
|
||||||
stmt_money.AddValue(1, loot.gold);
|
|
||||||
trans.Append(stmt_money);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save items
|
|
||||||
if (!loot.IsLooted())
|
|
||||||
{
|
|
||||||
PreparedStatement stmt_items = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_ITEMS);
|
|
||||||
stmt_items.AddValue(0, loot.containerID.GetCounter());
|
|
||||||
trans.Append(stmt_items);
|
|
||||||
|
|
||||||
// Now insert the items
|
|
||||||
foreach (var _li in loot.items)
|
|
||||||
{
|
|
||||||
// When an item is looted, it doesn't get removed from the items collection
|
|
||||||
// but we don't want to resave it.
|
|
||||||
if (!_li.canSave)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Player guid = GetOwner();
|
|
||||||
if (!_li.AllowedForPlayer(guid))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
stmt_items = DB.Characters.GetPreparedStatement(CharStatements.INS_ITEMCONTAINER_ITEMS);
|
|
||||||
|
|
||||||
// container_id, item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_prop, context, bonus_list_ids
|
|
||||||
stmt_items.AddValue(0, loot.containerID.GetCounter());
|
|
||||||
stmt_items.AddValue(1, _li.itemid);
|
|
||||||
stmt_items.AddValue(2, _li.count);
|
|
||||||
stmt_items.AddValue(3, _li.follow_loot_rules);
|
|
||||||
stmt_items.AddValue(4, _li.freeforall);
|
|
||||||
stmt_items.AddValue(5, _li.is_blocked);
|
|
||||||
stmt_items.AddValue(6, _li.is_counted);
|
|
||||||
stmt_items.AddValue(7, _li.is_underthreshold);
|
|
||||||
stmt_items.AddValue(8, _li.needs_quest);
|
|
||||||
stmt_items.AddValue(9, _li.randomBonusListId);
|
|
||||||
stmt_items.AddValue(10, _li.context);
|
|
||||||
|
|
||||||
string bonusListIDs = "";
|
|
||||||
foreach (int bonusListID in _li.BonusListIDs)
|
|
||||||
bonusListIDs += bonusListID + ' ';
|
|
||||||
|
|
||||||
stmt_items.AddValue(11, bonusListIDs);
|
|
||||||
trans.Append(stmt_items);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DB.Characters.CommitTransaction(trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ItemContainerLoadLootFromDB()
|
|
||||||
{
|
|
||||||
// Loads the money and item loot associated with an openable item from the DB
|
|
||||||
// Default. If there are no records for this item then it will be rolled for in Player.SendLoot()
|
|
||||||
m_lootGenerated = false;
|
|
||||||
|
|
||||||
// Save this for later use
|
|
||||||
loot.containerID = GetGUID();
|
|
||||||
|
|
||||||
// First, see if there was any money loot. This gets added directly to the container.
|
|
||||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_ITEMCONTAINER_MONEY);
|
|
||||||
stmt.AddValue(0, loot.containerID.GetCounter());
|
|
||||||
SQLResult money_result = DB.Characters.Query(stmt);
|
|
||||||
|
|
||||||
if (!money_result.IsEmpty())
|
|
||||||
{
|
|
||||||
loot.gold = money_result.Read<uint>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, load any items that were saved
|
|
||||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_ITEMCONTAINER_ITEMS);
|
|
||||||
stmt.AddValue(0, loot.containerID.GetCounter());
|
|
||||||
SQLResult item_result = DB.Characters.Query(stmt);
|
|
||||||
|
|
||||||
if (!item_result.IsEmpty())
|
|
||||||
{
|
|
||||||
// Get a LootTemplate for the container item. This is where
|
|
||||||
// the saved loot was originally rolled from, we will copy conditions from it
|
|
||||||
LootTemplate lt = LootStorage.Items.GetLootFor(GetEntry());
|
|
||||||
if (lt != null)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// Create an empty LootItem
|
|
||||||
LootItem loot_item = new LootItem();
|
|
||||||
|
|
||||||
// item_id, itm_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_prop, context, bonus_list_ids
|
|
||||||
loot_item.itemid = item_result.Read<uint>(0);
|
|
||||||
loot_item.count = item_result.Read<byte>(1);
|
|
||||||
loot_item.follow_loot_rules = item_result.Read<bool>(2);
|
|
||||||
loot_item.freeforall = item_result.Read<bool>(3);
|
|
||||||
loot_item.is_blocked = item_result.Read<bool>(4);
|
|
||||||
loot_item.is_counted = item_result.Read<bool>(5);
|
|
||||||
loot_item.canSave = true;
|
|
||||||
loot_item.is_underthreshold = item_result.Read<bool>(6);
|
|
||||||
loot_item.needs_quest = item_result.Read<bool>(7);
|
|
||||||
loot_item.randomBonusListId = item_result.Read<uint>(8);
|
|
||||||
loot_item.context = (ItemContext)item_result.Read<byte>(9);
|
|
||||||
|
|
||||||
StringArray bonusLists = new StringArray(item_result.Read<string>(10), ' ');
|
|
||||||
if (!bonusLists.IsEmpty())
|
|
||||||
{
|
|
||||||
foreach (string line in bonusLists)
|
|
||||||
{
|
|
||||||
if (uint.TryParse(line, out uint id))
|
|
||||||
loot_item.BonusListIDs.Add(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the extra loot conditions from the item in the loot template
|
|
||||||
lt.CopyConditions(loot_item);
|
|
||||||
|
|
||||||
// If container item is in a bag, add that player as an allowed looter
|
|
||||||
if (GetBagSlot() != 0)
|
|
||||||
loot_item.AddAllowedLooter(GetOwner());
|
|
||||||
|
|
||||||
// Finally add the LootItem to the container
|
|
||||||
loot.items.Add(loot_item);
|
|
||||||
|
|
||||||
// Increment unlooted count
|
|
||||||
loot.unlootedCount++;
|
|
||||||
}
|
|
||||||
while (item_result.NextRow());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the item if it has loot so it won't be generated again on open
|
|
||||||
m_lootGenerated = !loot.IsLooted();
|
|
||||||
|
|
||||||
return m_lootGenerated;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemContainerDeleteLootItemsFromDB()
|
|
||||||
{
|
|
||||||
// Deletes items associated with an openable item from the DB
|
|
||||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_ITEMS);
|
|
||||||
stmt.AddValue(0, GetGUID().GetCounter());
|
|
||||||
DB.Characters.Execute(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemContainerDeleteLootItemFromDB(uint itemID)
|
|
||||||
{
|
|
||||||
// Deletes a single item associated with an openable item from the DB
|
|
||||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_ITEM);
|
|
||||||
stmt.AddValue(0, GetGUID().GetCounter());
|
|
||||||
stmt.AddValue(1, itemID);
|
|
||||||
DB.Characters.Execute(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemContainerDeleteLootMoneyFromDB()
|
|
||||||
{
|
|
||||||
// Deletes the money loot associated with an openable item from the DB
|
|
||||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_MONEY);
|
|
||||||
stmt.AddValue(0, GetGUID().GetCounter());
|
|
||||||
DB.Characters.Execute(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ItemContainerDeleteLootMoneyAndLootItemsFromDB()
|
|
||||||
{
|
|
||||||
// Deletes money and items associated with an openable item from the DB
|
|
||||||
ItemContainerDeleteLootMoneyFromDB();
|
|
||||||
ItemContainerDeleteLootItemsFromDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetItemLevel(Player owner)
|
public uint GetItemLevel(Player owner)
|
||||||
{
|
{
|
||||||
ItemTemplate itemTemplate = GetTemplate();
|
ItemTemplate itemTemplate = GetTemplate();
|
||||||
|
|||||||
@@ -1507,12 +1507,27 @@ namespace Game.Entities
|
|||||||
for (var i = InventorySlots.BuyBackStart; i < InventorySlots.BuyBackEnd; ++i)
|
for (var i = InventorySlots.BuyBackStart; i < InventorySlots.BuyBackEnd; ++i)
|
||||||
{
|
{
|
||||||
Item item = m_items[i];
|
Item item = m_items[i];
|
||||||
if (item == null || item.GetState() == ItemUpdateState.New)
|
if (item == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
ItemTemplate itemTemplate = item.GetTemplate();
|
||||||
|
|
||||||
|
if (item.GetState() == ItemUpdateState.New)
|
||||||
|
{
|
||||||
|
if (itemTemplate != null)
|
||||||
|
if (itemTemplate.GetFlags().HasAnyFlag(ItemFlags.HasLoot))
|
||||||
|
Global.LootItemStorage.RemoveStoredLootForContainer(item.GetGUID().GetCounter());
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
item.DeleteFromInventoryDB(trans);
|
item.DeleteFromInventoryDB(trans);
|
||||||
item.DeleteFromDB(trans);
|
item.DeleteFromDB(trans);
|
||||||
m_items[i].FSetState(ItemUpdateState.New);
|
m_items[i].FSetState(ItemUpdateState.New);
|
||||||
|
|
||||||
|
if (itemTemplate != null)
|
||||||
|
if (itemTemplate.GetFlags().HasAnyFlag(ItemFlags.HasLoot))
|
||||||
|
Global.LootItemStorage.RemoveStoredLootForContainer(item.GetGUID().GetCounter());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updated played time for refundable items. We don't do this in Player.Update because there's simply no need for it,
|
// Updated played time for refundable items. We don't do this in Player.Update because there's simply no need for it,
|
||||||
|
|||||||
@@ -2449,7 +2449,7 @@ namespace Game.Entities
|
|||||||
Item bagItem = bag.GetItemByPos(i);
|
Item bagItem = bag.GetItemByPos(i);
|
||||||
if (bagItem != null)
|
if (bagItem != null)
|
||||||
{
|
{
|
||||||
if (bagItem.m_lootGenerated)
|
if (bagItem.GetGUID() == GetLootGUID())
|
||||||
{
|
{
|
||||||
GetSession().DoLootRelease(GetLootGUID());
|
GetSession().DoLootRelease(GetLootGUID());
|
||||||
released = true; // so we don't need to look at dstBag
|
released = true; // so we don't need to look at dstBag
|
||||||
@@ -2467,7 +2467,7 @@ namespace Game.Entities
|
|||||||
Item bagItem = bag.GetItemByPos(i);
|
Item bagItem = bag.GetItemByPos(i);
|
||||||
if (bagItem != null)
|
if (bagItem != null)
|
||||||
{
|
{
|
||||||
if (bagItem.m_lootGenerated)
|
if (bagItem.GetGUID() == GetLootGUID())
|
||||||
{
|
{
|
||||||
GetSession().DoLootRelease(GetLootGUID());
|
GetSession().DoLootRelease(GetLootGUID());
|
||||||
break;
|
break;
|
||||||
@@ -3911,7 +3911,13 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
pItem.RemoveFromWorld();
|
pItem.RemoveFromWorld();
|
||||||
if (del)
|
if (del)
|
||||||
|
{
|
||||||
pItem.SetState(ItemUpdateState.Removed, this);
|
pItem.SetState(ItemUpdateState.Removed, this);
|
||||||
|
ItemTemplate itemTemplate = pItem.GetTemplate();
|
||||||
|
if (itemTemplate != null)
|
||||||
|
if (itemTemplate.GetFlags().HasAnyFlag(ItemFlags.HasLoot))
|
||||||
|
Global.LootItemStorage.RemoveStoredLootForContainer(pItem.GetGUID().GetCounter());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_items[slot] = null;
|
m_items[slot] = null;
|
||||||
@@ -5811,7 +5817,10 @@ namespace Game.Entities
|
|||||||
ApplyItemObtainSpells(pItem, false);
|
ApplyItemObtainSpells(pItem, false);
|
||||||
|
|
||||||
ItemRemovedQuestCheck(pItem.GetEntry(), pItem.GetCount());
|
ItemRemovedQuestCheck(pItem.GetEntry(), pItem.GetCount());
|
||||||
|
Global.ScriptMgr.OnItemRemove(this, pItem);
|
||||||
|
|
||||||
Bag pBag;
|
Bag pBag;
|
||||||
|
ItemTemplate pProto = pItem.GetTemplate();
|
||||||
if (bag == InventorySlots.Bag0)
|
if (bag == InventorySlots.Bag0)
|
||||||
{
|
{
|
||||||
SetInvSlot(slot, ObjectGuid.Empty);
|
SetInvSlot(slot, ObjectGuid.Empty);
|
||||||
@@ -5819,8 +5828,6 @@ namespace Game.Entities
|
|||||||
// equipment and equipped bags can have applied bonuses
|
// equipment and equipped bags can have applied bonuses
|
||||||
if (slot < InventorySlots.BagEnd)
|
if (slot < InventorySlots.BagEnd)
|
||||||
{
|
{
|
||||||
ItemTemplate pProto = pItem.GetTemplate();
|
|
||||||
|
|
||||||
// item set bonuses applied only at equip and removed at unequip, and still active for broken items
|
// item set bonuses applied only at equip and removed at unequip, and still active for broken items
|
||||||
if (pProto != null && pProto.GetItemSet() != 0)
|
if (pProto != null && pProto.GetItemSet() != 0)
|
||||||
Item.RemoveItemsSetItem(this, pProto);
|
Item.RemoveItemsSetItem(this, pProto);
|
||||||
@@ -5856,10 +5863,8 @@ namespace Game.Entities
|
|||||||
|
|
||||||
// Delete rolled money / loot from db.
|
// Delete rolled money / loot from db.
|
||||||
// MUST be done before RemoveFromWorld() or GetTemplate() fails
|
// MUST be done before RemoveFromWorld() or GetTemplate() fails
|
||||||
ItemTemplate pTmp = pItem.GetTemplate();
|
if (pProto.GetFlags().HasAnyFlag(ItemFlags.HasLoot))
|
||||||
if (pTmp != null)
|
Global.LootItemStorage.RemoveStoredLootForContainer(pItem.GetGUID().GetCounter());
|
||||||
if (Convert.ToBoolean(pTmp.GetFlags() & ItemFlags.HasLoot))
|
|
||||||
pItem.ItemContainerDeleteLootMoneyAndLootItemsFromDB();
|
|
||||||
|
|
||||||
if (IsInWorld && update)
|
if (IsInWorld && update)
|
||||||
{
|
{
|
||||||
@@ -6325,7 +6330,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
// LootItem is being removed (looted) from the container, delete it from the DB.
|
// LootItem is being removed (looted) from the container, delete it from the DB.
|
||||||
if (!loot.containerID.IsEmpty())
|
if (!loot.containerID.IsEmpty())
|
||||||
loot.DeleteLootItemFromContainerItemDB(item.itemid);
|
Global.LootItemStorage.RemoveStoredLootItemForContainer(loot.containerID.GetCounter(), item.itemid, item.count);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -6517,9 +6522,12 @@ namespace Game.Entities
|
|||||||
|
|
||||||
loot = item.loot;
|
loot = item.loot;
|
||||||
|
|
||||||
|
// Store container id
|
||||||
|
loot.containerID = item.GetGUID();
|
||||||
|
|
||||||
// If item doesn't already have loot, attempt to load it. If that
|
// If item doesn't already have loot, attempt to load it. If that
|
||||||
// fails then this is first time opening, generate loot
|
// fails then this is first time opening, generate loot
|
||||||
if (!item.m_lootGenerated && !item.ItemContainerLoadLootFromDB())
|
if (!item.m_lootGenerated && !Global.LootItemStorage.LoadStoredLoot(item, this))
|
||||||
{
|
{
|
||||||
item.m_lootGenerated = true;
|
item.m_lootGenerated = true;
|
||||||
loot.Clear();
|
loot.Clear();
|
||||||
@@ -6542,7 +6550,7 @@ namespace Game.Entities
|
|||||||
// Force save the loot and money items that were just rolled
|
// Force save the loot and money items that were just rolled
|
||||||
// Also saves the container item ID in Loot struct (not to DB)
|
// Also saves the container item ID in Loot struct (not to DB)
|
||||||
if (loot.gold > 0 || loot.unlootedCount > 0)
|
if (loot.gold > 0 || loot.unlootedCount > 0)
|
||||||
item.ItemContainerSaveLootToDB();
|
Global.LootItemStorage.AddNewStoredLoot(loot, this);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ using Game.Scripting;
|
|||||||
using Game.SupportSystem;
|
using Game.SupportSystem;
|
||||||
using Game.Services;
|
using Game.Services;
|
||||||
using Game.Cache;
|
using Game.Cache;
|
||||||
|
using Game.Loots;
|
||||||
|
|
||||||
public static class Global
|
public static class Global
|
||||||
{
|
{
|
||||||
@@ -95,6 +96,7 @@ public static class Global
|
|||||||
public static CharacterTemplateDataStorage CharacterTemplateDataStorage { get { return CharacterTemplateDataStorage.Instance; } }
|
public static CharacterTemplateDataStorage CharacterTemplateDataStorage { get { return CharacterTemplateDataStorage.Instance; } }
|
||||||
public static ConversationDataStorage ConversationDataStorage { get { return ConversationDataStorage.Instance; } }
|
public static ConversationDataStorage ConversationDataStorage { get { return ConversationDataStorage.Instance; } }
|
||||||
public static CharacterCache CharacterCacheStorage { get { return CharacterCache.Instance; } }
|
public static CharacterCache CharacterCacheStorage { get { return CharacterCache.Instance; } }
|
||||||
|
public static LootItemStorage LootItemStorage { get { return LootItemStorage.Instance; } }
|
||||||
|
|
||||||
//Misc
|
//Misc
|
||||||
public static ConditionManager ConditionMgr { get { return ConditionManager.Instance; } }
|
public static ConditionManager ConditionMgr { get { return ConditionManager.Instance; } }
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ namespace Game
|
|||||||
|
|
||||||
// Delete the money loot record from the DB
|
// Delete the money loot record from the DB
|
||||||
if (!loot.containerID.IsEmpty())
|
if (!loot.containerID.IsEmpty())
|
||||||
loot.DeleteLootMoneyFromContainerItemDB();
|
Global.LootItemStorage.RemoveStoredMoneyForContainer(loot.containerID.GetCounter());
|
||||||
|
|
||||||
// Delete container if empty
|
// Delete container if empty
|
||||||
if (loot.IsLooted() && guid.IsItem())
|
if (loot.IsLooted() && guid.IsItem())
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace Game.Loots
|
|||||||
{
|
{
|
||||||
public class LootItem
|
public class LootItem
|
||||||
{
|
{
|
||||||
|
public LootItem() { }
|
||||||
public LootItem(LootStoreItem li)
|
public LootItem(LootStoreItem li)
|
||||||
{
|
{
|
||||||
itemid = li.itemid;
|
itemid = li.itemid;
|
||||||
@@ -41,12 +42,6 @@ namespace Game.Loots
|
|||||||
needs_quest = li.needs_quest;
|
needs_quest = li.needs_quest;
|
||||||
|
|
||||||
randomBonusListId = ItemEnchantmentManager.GenerateItemRandomBonusListId(itemid);
|
randomBonusListId = ItemEnchantmentManager.GenerateItemRandomBonusListId(itemid);
|
||||||
canSave = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LootItem()
|
|
||||||
{
|
|
||||||
canSave = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AllowedForPlayer(Player player)
|
public bool AllowedForPlayer(Player player)
|
||||||
@@ -100,7 +95,6 @@ namespace Game.Loots
|
|||||||
public bool is_counted;
|
public bool is_counted;
|
||||||
public bool needs_quest; // quest drop
|
public bool needs_quest; // quest drop
|
||||||
public bool follow_loot_rules;
|
public bool follow_loot_rules;
|
||||||
public bool canSave;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NotNormalLootItem
|
public class NotNormalLootItem
|
||||||
@@ -440,33 +434,6 @@ namespace Game.Loots
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteLootItemFromContainerItemDB(uint itemID)
|
|
||||||
{
|
|
||||||
// Deletes a single item associated with an openable item from the DB
|
|
||||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_ITEM);
|
|
||||||
stmt.AddValue(0, containerID.GetCounter());
|
|
||||||
stmt.AddValue(1, itemID);
|
|
||||||
DB.Characters.Execute(stmt);
|
|
||||||
|
|
||||||
// Mark the item looted to prevent resaving
|
|
||||||
foreach (var lootItem in items)
|
|
||||||
{
|
|
||||||
if (lootItem.itemid != itemID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
lootItem.canSave = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteLootMoneyFromContainerItemDB()
|
|
||||||
{
|
|
||||||
// Deletes money loot associated with an openable item from the DB
|
|
||||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_MONEY);
|
|
||||||
stmt.AddValue(0, containerID.GetCounter());
|
|
||||||
DB.Characters.Execute(stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LootItem LootItemInSlot(uint lootSlot, Player player)
|
public LootItem LootItemInSlot(uint lootSlot, Player player)
|
||||||
{
|
{
|
||||||
return LootItemInSlot(lootSlot, player, out _, out _, out _);
|
return LootItemInSlot(lootSlot, player, out _, out _, out _);
|
||||||
|
|||||||
@@ -0,0 +1,337 @@
|
|||||||
|
using Framework.Constants;
|
||||||
|
using Framework.Database;
|
||||||
|
using Game.Entities;
|
||||||
|
using Game.Loots;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Game.Loots;
|
||||||
|
using Framework.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace Game.Loots
|
||||||
|
{
|
||||||
|
public class LootItemStorage : Singleton<LootItemStorage>
|
||||||
|
{
|
||||||
|
LootItemStorage() { }
|
||||||
|
|
||||||
|
public void LoadStorageFromDB()
|
||||||
|
{
|
||||||
|
uint oldMSTime = Time.GetMSTime();
|
||||||
|
_lootItemStorage.Clear();
|
||||||
|
uint count = 0;
|
||||||
|
|
||||||
|
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_ITEMCONTAINER_ITEMS);
|
||||||
|
SQLResult result = DB.Characters.Query(stmt);
|
||||||
|
if (!result.IsEmpty())
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ulong key = result.Read<ulong>(0);
|
||||||
|
var itr = _lootItemStorage.LookupByKey(key);
|
||||||
|
if (!_lootItemStorage.ContainsKey(key))
|
||||||
|
_lootItemStorage[key] = new StoredLootContainer(key);
|
||||||
|
|
||||||
|
StoredLootContainer storedContainer = _lootItemStorage[key];
|
||||||
|
|
||||||
|
LootItem lootItem = new LootItem();
|
||||||
|
lootItem.itemid = result.Read<uint>(1);
|
||||||
|
lootItem.count = result.Read<byte>(2);
|
||||||
|
lootItem.follow_loot_rules = result.Read<bool>(3);
|
||||||
|
lootItem.freeforall = result.Read<bool>(4);
|
||||||
|
lootItem.is_blocked = result.Read<bool>(5);
|
||||||
|
lootItem.is_counted = result.Read<bool>(6);
|
||||||
|
lootItem.is_underthreshold = result.Read<bool>(7);
|
||||||
|
lootItem.needs_quest = result.Read<bool>(8);
|
||||||
|
lootItem.randomBonusListId = result.Read<uint>(9);
|
||||||
|
lootItem.context = (ItemContext)result.Read<byte>(10);
|
||||||
|
StringArray bonusLists = new StringArray(result.Read<string>(11), ' ');
|
||||||
|
|
||||||
|
foreach (string str in bonusLists)
|
||||||
|
lootItem.BonusListIDs.Add(uint.Parse(str));
|
||||||
|
|
||||||
|
storedContainer.AddLootItem(lootItem, null);
|
||||||
|
|
||||||
|
++count;
|
||||||
|
} while (result.NextRow());
|
||||||
|
|
||||||
|
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} stored item loots in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 stored item loots");
|
||||||
|
|
||||||
|
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_ITEMCONTAINER_MONEY);
|
||||||
|
result = DB.Characters.Query(stmt);
|
||||||
|
if (!result.IsEmpty())
|
||||||
|
{
|
||||||
|
count = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ulong key = result.Read<ulong>(0);
|
||||||
|
if (!_lootItemStorage.ContainsKey(key))
|
||||||
|
_lootItemStorage.TryAdd(key, new StoredLootContainer(key));
|
||||||
|
|
||||||
|
StoredLootContainer storedContainer = _lootItemStorage[key];
|
||||||
|
storedContainer.AddMoney(result.Read<uint>(1), null);
|
||||||
|
|
||||||
|
++count;
|
||||||
|
} while (result.NextRow());
|
||||||
|
|
||||||
|
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} stored item money in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 stored item money");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool LoadStoredLoot(Item item, Player player)
|
||||||
|
{
|
||||||
|
Loot loot = item.loot;
|
||||||
|
if (!_lootItemStorage.ContainsKey(loot.containerID.GetCounter()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var container = _lootItemStorage[loot.containerID.GetCounter()];
|
||||||
|
loot.gold = container.GetMoney();
|
||||||
|
|
||||||
|
LootTemplate lt = LootStorage.Items.GetLootFor(item.GetEntry());
|
||||||
|
if (lt != null)
|
||||||
|
{
|
||||||
|
foreach (var storedItemPair in container.GetLootItems())
|
||||||
|
{
|
||||||
|
LootItem li = new LootItem();
|
||||||
|
li.itemid = storedItemPair.Key;
|
||||||
|
li.count = (byte)storedItemPair.Value.Count;
|
||||||
|
li.follow_loot_rules = storedItemPair.Value.FollowRules;
|
||||||
|
li.freeforall = storedItemPair.Value.FFA;
|
||||||
|
li.is_blocked = storedItemPair.Value.Blocked;
|
||||||
|
li.is_counted = storedItemPair.Value.Counted;
|
||||||
|
li.is_underthreshold = storedItemPair.Value.UnderThreshold;
|
||||||
|
li.needs_quest = storedItemPair.Value.NeedsQuest;
|
||||||
|
li.randomBonusListId = storedItemPair.Value.RandomBonusListId;
|
||||||
|
li.context = storedItemPair.Value.Context;
|
||||||
|
li.BonusListIDs = storedItemPair.Value.BonusListIDs;
|
||||||
|
|
||||||
|
// Copy the extra loot conditions from the item in the loot template
|
||||||
|
lt.CopyConditions(li);
|
||||||
|
|
||||||
|
// If container item is in a bag, add that player as an allowed looter
|
||||||
|
if (item.GetBagSlot() != 0)
|
||||||
|
li.AddAllowedLooter(player);
|
||||||
|
|
||||||
|
// Finally add the LootItem to the container
|
||||||
|
loot.items.Add(li);
|
||||||
|
|
||||||
|
// Increment unlooted count
|
||||||
|
++loot.unlootedCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the item if it has loot so it won't be generated again on open
|
||||||
|
item.m_lootGenerated = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveStoredMoneyForContainer(ulong containerId)
|
||||||
|
{
|
||||||
|
if (!_lootItemStorage.ContainsKey(containerId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lootItemStorage[containerId].RemoveMoney();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveStoredLootForContainer(ulong containerId)
|
||||||
|
{
|
||||||
|
_lootItemStorage.TryRemove(containerId, out _);
|
||||||
|
|
||||||
|
SQLTransaction trans = new SQLTransaction();
|
||||||
|
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_ITEMS);
|
||||||
|
stmt.AddValue(0, containerId);
|
||||||
|
trans.Append(stmt);
|
||||||
|
|
||||||
|
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_MONEY);
|
||||||
|
stmt.AddValue(0, containerId);
|
||||||
|
trans.Append(stmt);
|
||||||
|
|
||||||
|
DB.Characters.CommitTransaction(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveStoredLootItemForContainer(ulong containerId, uint itemId, uint count)
|
||||||
|
{
|
||||||
|
if (!_lootItemStorage.ContainsKey(containerId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lootItemStorage[containerId].RemoveItem(itemId, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddNewStoredLoot(Loot loot, Player player)
|
||||||
|
{
|
||||||
|
// Saves the money and item loot associated with an openable item to the DB
|
||||||
|
if (loot.IsLooted()) // no money and no loot
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_lootItemStorage.ContainsKey(loot.containerID.GetCounter()))
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Misc, $"Trying to store item loot by player: {player.GetGUID()} for container id: {loot.containerID.GetCounter()} that is already in storage!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StoredLootContainer container = new StoredLootContainer(loot.containerID.GetCounter());
|
||||||
|
|
||||||
|
SQLTransaction trans = new SQLTransaction();
|
||||||
|
if (loot.gold != 0)
|
||||||
|
container.AddMoney(loot.gold, trans);
|
||||||
|
|
||||||
|
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_ITEMS);
|
||||||
|
stmt.AddValue(0, loot.containerID.GetCounter());
|
||||||
|
trans.Append(stmt);
|
||||||
|
|
||||||
|
foreach (LootItem li in loot.items)
|
||||||
|
{
|
||||||
|
// Conditions are not checked when loot is generated, it is checked when loot is sent to a player.
|
||||||
|
// For items that are lootable, loot is saved to the DB immediately, that means that loot can be
|
||||||
|
// saved to the DB that the player never should have gotten. This check prevents that, so that only
|
||||||
|
// items that the player should get in loot are in the DB.
|
||||||
|
// IE: Horde items are not saved to the DB for Ally players.
|
||||||
|
if (!li.AllowedForPlayer(player))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Don't save currency tokens
|
||||||
|
ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(li.itemid);
|
||||||
|
if (itemTemplate == null || itemTemplate.IsCurrencyToken())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
container.AddLootItem(li, trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.Characters.CommitTransaction(trans);
|
||||||
|
|
||||||
|
_lootItemStorage.TryAdd(loot.containerID.GetCounter(), container);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConcurrentDictionary<ulong, StoredLootContainer> _lootItemStorage = new ConcurrentDictionary<ulong, StoredLootContainer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class StoredLootContainer
|
||||||
|
{
|
||||||
|
public StoredLootContainer(ulong containerId)
|
||||||
|
{
|
||||||
|
_containerId = containerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddLootItem(LootItem lootItem, SQLTransaction trans)
|
||||||
|
{
|
||||||
|
_lootItems.Add(lootItem.itemid, new StoredLootItem(lootItem));
|
||||||
|
if (trans == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_ITEMCONTAINER_ITEMS);
|
||||||
|
|
||||||
|
// container_id, item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_prop, rnd_suffix
|
||||||
|
stmt.AddValue(0, _containerId);
|
||||||
|
stmt.AddValue(1, lootItem.itemid);
|
||||||
|
stmt.AddValue(2, lootItem.count);
|
||||||
|
stmt.AddValue(3, lootItem.follow_loot_rules);
|
||||||
|
stmt.AddValue(4, lootItem.freeforall);
|
||||||
|
stmt.AddValue(5, lootItem.is_blocked);
|
||||||
|
stmt.AddValue(6, lootItem.is_counted);
|
||||||
|
stmt.AddValue(7, lootItem.is_underthreshold);
|
||||||
|
stmt.AddValue(8, lootItem.needs_quest);
|
||||||
|
stmt.AddValue(9, lootItem.randomBonusListId);
|
||||||
|
stmt.AddValue(10, (uint)lootItem.context);
|
||||||
|
|
||||||
|
foreach (uint token in lootItem.BonusListIDs)
|
||||||
|
{
|
||||||
|
StringBuilder bonusListIDs = new StringBuilder();
|
||||||
|
foreach (int bonusListID in lootItem.BonusListIDs)
|
||||||
|
bonusListIDs.Append(bonusListID + ' ');
|
||||||
|
|
||||||
|
stmt.AddValue(11, bonusListIDs.ToString());
|
||||||
|
trans.Append(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMoney(uint money, SQLTransaction trans)
|
||||||
|
{
|
||||||
|
_money = money;
|
||||||
|
if (trans == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_MONEY);
|
||||||
|
stmt.AddValue(0, _containerId);
|
||||||
|
trans.Append(stmt);
|
||||||
|
|
||||||
|
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_ITEMCONTAINER_MONEY);
|
||||||
|
stmt.AddValue(0, _containerId);
|
||||||
|
stmt.AddValue(1, _money);
|
||||||
|
trans.Append(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveMoney()
|
||||||
|
{
|
||||||
|
_money = 0;
|
||||||
|
|
||||||
|
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_MONEY);
|
||||||
|
stmt.AddValue(0, _containerId);
|
||||||
|
DB.Characters.Execute(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveItem(uint itemId, uint count)
|
||||||
|
{
|
||||||
|
var bounds = _lootItems.LookupByKey(itemId);
|
||||||
|
foreach (var itr in bounds)
|
||||||
|
{
|
||||||
|
if (itr.Count == count)
|
||||||
|
{
|
||||||
|
_lootItems.Remove(itr.ItemId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deletes a single item associated with an openable item from the DB
|
||||||
|
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_ITEM);
|
||||||
|
stmt.AddValue(0, _containerId);
|
||||||
|
stmt.AddValue(1, itemId);
|
||||||
|
stmt.AddValue(2, count);
|
||||||
|
DB.Characters.Execute(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong GetContainer() { return _containerId; }
|
||||||
|
|
||||||
|
public uint GetMoney() { return _money; }
|
||||||
|
|
||||||
|
public MultiMap<uint, StoredLootItem> GetLootItems() { return _lootItems; }
|
||||||
|
|
||||||
|
MultiMap<uint, StoredLootItem> _lootItems = new MultiMap<uint, StoredLootItem>();
|
||||||
|
ulong _containerId;
|
||||||
|
uint _money;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StoredLootItem
|
||||||
|
{
|
||||||
|
public StoredLootItem(LootItem lootItem)
|
||||||
|
{
|
||||||
|
ItemId = lootItem.itemid;
|
||||||
|
Count = lootItem.count;
|
||||||
|
FollowRules = lootItem.follow_loot_rules;
|
||||||
|
FFA = lootItem.freeforall;
|
||||||
|
Blocked = lootItem.is_blocked;
|
||||||
|
Counted = lootItem.is_counted;
|
||||||
|
UnderThreshold = lootItem.is_underthreshold;
|
||||||
|
NeedsQuest = lootItem.needs_quest;
|
||||||
|
RandomBonusListId = lootItem.randomBonusListId;
|
||||||
|
Context = lootItem.context;
|
||||||
|
BonusListIDs = lootItem.BonusListIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint ItemId;
|
||||||
|
public uint Count;
|
||||||
|
public bool FollowRules;
|
||||||
|
public bool FFA;
|
||||||
|
public bool Blocked;
|
||||||
|
public bool Counted;
|
||||||
|
public bool UnderThreshold;
|
||||||
|
public bool NeedsQuest;
|
||||||
|
public uint RandomBonusListId;
|
||||||
|
public ItemContext Context;
|
||||||
|
public List<uint> BonusListIDs = new List<uint>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -836,6 +836,9 @@ namespace Game
|
|||||||
Log.outInfo(LogFilter.ServerLoading, "Loading Calendar data...");
|
Log.outInfo(LogFilter.ServerLoading, "Loading Calendar data...");
|
||||||
Global.CalendarMgr.LoadFromDB();
|
Global.CalendarMgr.LoadFromDB();
|
||||||
|
|
||||||
|
Log.outInfo(LogFilter.ServerLoading, "Loading Item loot...");
|
||||||
|
Global.LootItemStorage.LoadStorageFromDB();
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Initialize query data...");
|
Log.outInfo(LogFilter.ServerLoading, "Initialize query data...");
|
||||||
Global.ObjectMgr.InitializeQueriesData(QueryDataGroup.All);
|
Global.ObjectMgr.InitializeQueriesData(QueryDataGroup.All);
|
||||||
|
|
||||||
|
|||||||
@@ -481,9 +481,9 @@ DROP TABLE IF EXISTS `character_arena_stats`;
|
|||||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
/*!40101 SET character_set_client = utf8 */;
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
CREATE TABLE `character_arena_stats` (
|
CREATE TABLE `character_arena_stats` (
|
||||||
`guid` bigint(20) NOT NULL,
|
`guid` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||||
`slot` tinyint(3) NOT NULL,
|
`slot` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
`matchMakerRating` smallint(5) NOT NULL,
|
`matchMakerRating` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||||
PRIMARY KEY (`guid`,`slot`)
|
PRIMARY KEY (`guid`,`slot`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
@@ -738,8 +738,8 @@ DROP TABLE IF EXISTS `character_equipmentsets`;
|
|||||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
/*!40101 SET character_set_client = utf8 */;
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
CREATE TABLE `character_equipmentsets` (
|
CREATE TABLE `character_equipmentsets` (
|
||||||
`guid` bigint(20) NOT NULL DEFAULT '0',
|
`guid` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||||
`setguid` bigint(20) NOT NULL AUTO_INCREMENT,
|
`setguid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
`setindex` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
`setindex` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
`name` varchar(31) NOT NULL,
|
`name` varchar(31) NOT NULL,
|
||||||
`iconname` varchar(100) NOT NULL,
|
`iconname` varchar(100) NOT NULL,
|
||||||
@@ -1895,7 +1895,7 @@ DROP TABLE IF EXISTS `creature_respawn`;
|
|||||||
/*!40101 SET character_set_client = utf8 */;
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
CREATE TABLE `creature_respawn` (
|
CREATE TABLE `creature_respawn` (
|
||||||
`guid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
|
`guid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
|
||||||
`respawnTime` int(10) unsigned NOT NULL DEFAULT '0',
|
`respawnTime` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||||
`mapId` smallint(10) unsigned NOT NULL DEFAULT '0',
|
`mapId` smallint(10) unsigned NOT NULL DEFAULT '0',
|
||||||
`instanceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Instance Identifier',
|
`instanceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Instance Identifier',
|
||||||
PRIMARY KEY (`guid`,`instanceId`),
|
PRIMARY KEY (`guid`,`instanceId`),
|
||||||
@@ -1969,7 +1969,7 @@ DROP TABLE IF EXISTS `gameobject_respawn`;
|
|||||||
/*!40101 SET character_set_client = utf8 */;
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
CREATE TABLE `gameobject_respawn` (
|
CREATE TABLE `gameobject_respawn` (
|
||||||
`guid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
|
`guid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier',
|
||||||
`respawnTime` int(10) unsigned NOT NULL DEFAULT '0',
|
`respawnTime` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||||
`mapId` smallint(10) unsigned NOT NULL DEFAULT '0',
|
`mapId` smallint(10) unsigned NOT NULL DEFAULT '0',
|
||||||
`instanceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Instance Identifier',
|
`instanceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Instance Identifier',
|
||||||
PRIMARY KEY (`guid`,`instanceId`),
|
PRIMARY KEY (`guid`,`instanceId`),
|
||||||
@@ -2616,7 +2616,7 @@ DROP TABLE IF EXISTS `instance`;
|
|||||||
CREATE TABLE `instance` (
|
CREATE TABLE `instance` (
|
||||||
`id` int(10) unsigned NOT NULL DEFAULT '0',
|
`id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||||
`map` smallint(5) unsigned NOT NULL DEFAULT '0',
|
`map` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||||
`resettime` int(10) unsigned NOT NULL DEFAULT '0',
|
`resettime` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||||
`difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
`difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
`completedEncounters` int(10) unsigned NOT NULL DEFAULT '0',
|
`completedEncounters` int(10) unsigned NOT NULL DEFAULT '0',
|
||||||
`data` tinytext NOT NULL,
|
`data` tinytext NOT NULL,
|
||||||
@@ -2647,7 +2647,7 @@ DROP TABLE IF EXISTS `instance_reset`;
|
|||||||
CREATE TABLE `instance_reset` (
|
CREATE TABLE `instance_reset` (
|
||||||
`mapid` smallint(5) unsigned NOT NULL DEFAULT '0',
|
`mapid` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||||
`difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
`difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
`resettime` int(10) unsigned NOT NULL DEFAULT '0',
|
`resettime` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||||||
PRIMARY KEY (`mapid`,`difficulty`),
|
PRIMARY KEY (`mapid`,`difficulty`),
|
||||||
KEY `difficulty` (`difficulty`)
|
KEY `difficulty` (`difficulty`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
@@ -3180,8 +3180,8 @@ DROP TABLE IF EXISTS `item_loot_money`;
|
|||||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
/*!40101 SET character_set_client = utf8 */;
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
CREATE TABLE `item_loot_money` (
|
CREATE TABLE `item_loot_money` (
|
||||||
`container_id` bigint(20) NOT NULL DEFAULT '0' COMMENT 'guid of container (item_instance.guid)',
|
`container_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'guid of container (item_instance.guid)',
|
||||||
`money` int(10) NOT NULL DEFAULT '0' COMMENT 'money loot (in copper)',
|
`money` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'money loot (in copper)',
|
||||||
PRIMARY KEY (`container_id`)
|
PRIMARY KEY (`container_id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
@@ -3771,7 +3771,11 @@ INSERT INTO `updates` VALUES
|
|||||||
('2019_12_05_00_characters.sql','EA381C9634A5646A3168F15DF4E06A708A622762','RELEASED','2019-12-05 20:56:58',0),
|
('2019_12_05_00_characters.sql','EA381C9634A5646A3168F15DF4E06A708A622762','RELEASED','2019-12-05 20:56:58',0),
|
||||||
('2020_02_17_00_characters.sql','E1519A81D35F19B48B3C75A83A270CB4BA0B84F2','RELEASED','2020-02-17 21:55:17',0),
|
('2020_02_17_00_characters.sql','E1519A81D35F19B48B3C75A83A270CB4BA0B84F2','RELEASED','2020-02-17 21:55:17',0),
|
||||||
('2020_04_20_00_characters.sql','977B5E0C894E0A7E80B2A9626F17CA636A69BD22','RELEASED','2020-04-20 19:08:18',0),
|
('2020_04_20_00_characters.sql','977B5E0C894E0A7E80B2A9626F17CA636A69BD22','RELEASED','2020-04-20 19:08:18',0),
|
||||||
('2020_04_24_00_characters.sql','85E2E0395A9457A53D73A9E0A7BB39B7E4C429BF','RELEASED','2020-04-24 22:04:59',0);
|
('2020_04_24_00_characters.sql','85E2E0395A9457A53D73A9E0A7BB39B7E4C429BF','RELEASED','2020-04-24 22:04:59',0),
|
||||||
|
('2020_04_25_00_characters_2017_04_03_00_characters.sql','00FA3EFADAF807AC96619A3FE47216E21C3FCB19','RELEASED','2020-04-25 00:00:00',0),
|
||||||
|
('2020_04_26_00_characters_2017_04_12_00_characters.sql','86AA94DA9B1EA283101100886C10F648C0CE6494','RELEASED','2020-04-26 00:00:00',0),
|
||||||
|
('2020_04_26_01_characters_2017_04_12_01_characters.sql','5A8A1215E3A2356722F52CD7A64BBE03D21FBEA3','RELEASED','2020-04-26 00:00:00',0);
|
||||||
|
|
||||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `item_loot_money`
|
||||||
|
CHANGE `money` `money` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'money loot (in copper)';
|
||||||
Reference in New Issue
Block a user