diff --git a/Framework/Database/Databases/WorldDatabase.cs b/Framework/Database/Databases/WorldDatabase.cs index 272f8214c..6a75fbbf7 100644 --- a/Framework/Database/Databases/WorldDatabase.cs +++ b/Framework/Database/Databases/WorldDatabase.cs @@ -35,7 +35,7 @@ namespace Framework.Database PrepareStatement(WorldStatements.DEL_GAME_TELE, "DELETE FROM game_tele WHERE name = ?"); PrepareStatement(WorldStatements.INS_NPC_VENDOR, "INSERT INTO npc_vendor (entry, item, maxcount, incrtime, extendedcost, type) VALUES(?, ?, ?, ?, ?, ?)"); PrepareStatement(WorldStatements.DEL_NPC_VENDOR, "DELETE FROM npc_vendor WHERE entry = ? AND item = ? AND type = ?"); - PrepareStatement(WorldStatements.SEL_NPC_VENDOR_REF, "SELECT item, maxcount, incrtime, ExtendedCost, type FROM npc_vendor WHERE entry = ? AND type = ? ORDER BY slot ASC"); + PrepareStatement(WorldStatements.SEL_NPC_VENDOR_REF, "SELECT item, maxcount, incrtime, ExtendedCost, type, BonusListIDs, PlayerConditionID, IgnoreFiltering FROM npc_vendor WHERE entry = ? ORDER BY slot ASC"); PrepareStatement(WorldStatements.UPD_CREATURE_MOVEMENT_TYPE, "UPDATE creature SET MovementType = ? WHERE guid = ?"); PrepareStatement(WorldStatements.UPD_CREATURE_FACTION, "UPDATE creature_template SET faction = ? WHERE entry = ?"); PrepareStatement(WorldStatements.UPD_CREATURE_NPCFLAG, "UPDATE creature_template SET npcflag = ? WHERE entry = ?"); diff --git a/Game/Chat/Commands/NPCCommands.cs b/Game/Chat/Commands/NPCCommands.cs index 31c1eb98d..0880cf2e8 100644 --- a/Game/Chat/Commands/NPCCommands.cs +++ b/Game/Chat/Commands/NPCCommands.cs @@ -25,6 +25,7 @@ using Game.Movement; using System; using System.Collections.Generic; using System.Linq; +using Framework.Collections; namespace Game.Chat { @@ -1166,6 +1167,7 @@ namespace Game.Chat uint maxcount = args.NextUInt32(); uint incrtime = args.NextUInt32(); uint extendedcost = args.NextUInt32(); + string fbonuslist = args.NextString(); Creature vendor = handler.getSelectedCreature(); if (!vendor) @@ -1176,10 +1178,24 @@ namespace Game.Chat uint vendor_entry = vendor.GetEntry(); - if (!Global.ObjectMgr.IsVendorItemValid(vendor_entry, itemId, (int)maxcount, incrtime, extendedcost, (ItemVendorType)type, handler.GetSession().GetPlayer())) + VendorItem vItem = new VendorItem(); + vItem.item = itemId; + vItem.maxcount = maxcount; + vItem.incrtime = incrtime; + vItem.ExtendedCost = extendedcost; + vItem.Type = (ItemVendorType)type; + + if (fbonuslist.IsEmpty()) + { + var bonusListIDsTok = new StringArray(fbonuslist, ';'); + foreach (string token in bonusListIDsTok) + vItem.BonusListIDs.Add(uint.Parse(token)); + } + + if (!Global.ObjectMgr.IsVendorItemValid(vendor_entry, vItem, handler.GetSession().GetPlayer())) return false; - Global.ObjectMgr.AddVendorItem(vendor_entry, itemId, (int)maxcount, incrtime, extendedcost, (ItemVendorType)type); + Global.ObjectMgr.AddVendorItem(vendor_entry, vItem); ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(itemId); diff --git a/Game/Entities/Creature/CreatureData.cs b/Game/Entities/Creature/CreatureData.cs index 32f7fa91a..7111669cc 100644 --- a/Game/Entities/Creature/CreatureData.cs +++ b/Game/Entities/Creature/CreatureData.cs @@ -327,6 +327,7 @@ namespace Game.Entities public class VendorItem { + public VendorItem() { } public VendorItem(uint _item, int _maxcount, uint _incrtime, uint _ExtendedCost, ItemVendorType _Type) { item = _item; @@ -341,6 +342,9 @@ namespace Game.Entities public uint incrtime; // time for restore items amount if maxcount != 0 public uint ExtendedCost; public ItemVendorType Type; + public List BonusListIDs = new List(); + public uint PlayerConditionId; + public bool IgnoreFiltering; //helpers public bool IsGoldRequired(ItemTemplate pProto) { return Convert.ToBoolean(pProto.GetFlags2() & ItemFlags2.DontIgnoreBuyPrice) || ExtendedCost == 0; } @@ -365,9 +369,9 @@ namespace Game.Entities { return m_items.Count; } - public void AddItem(uint item, int maxcount, uint ptime, uint ExtendedCost, ItemVendorType type) + public void AddItem(VendorItem vItem) { - m_items.Add(new VendorItem(item, maxcount, ptime, ExtendedCost, type)); + m_items.Add(vItem); } public bool RemoveItem(uint item_id, ItemVendorType type) { diff --git a/Game/Entities/Object/WorldObject.cs b/Game/Entities/Object/WorldObject.cs index 5baa8a721..450d5ce69 100644 --- a/Game/Entities/Object/WorldObject.cs +++ b/Game/Entities/Object/WorldObject.cs @@ -2790,7 +2790,7 @@ namespace Game.Entities return distsq < maxdist * maxdist; } - bool IsInBetween(WorldObject obj1, WorldObject obj2, float size = 0) { return obj1 && obj2 && IsInBetween(obj1.GetPosition(), obj2.GetPosition(), size); } + public bool IsInBetween(WorldObject obj1, WorldObject obj2, float size = 0) { return obj1 && obj2 && IsInBetween(obj1.GetPosition(), obj2.GetPosition(), size); } bool IsInBetween(Position pos1, Position pos2, float size) { float dist = GetExactDist2d(pos1); diff --git a/Game/Entities/Player/Player.Items.cs b/Game/Entities/Player/Player.Items.cs index 1fa604824..56d102ee7 100644 --- a/Game/Entities/Player/Player.Items.cs +++ b/Game/Entities/Player/Player.Items.cs @@ -2517,7 +2517,7 @@ namespace Game.Entities } } - Item it = bStore ? StoreNewItem(vDest, item, true, ItemEnchantment.GenerateItemRandomPropertyId(item), null, 0, null, false) : EquipNewItem(uiDest, item, true); + Item it = bStore ? StoreNewItem(vDest, item, true, ItemEnchantment.GenerateItemRandomPropertyId(item), null, 0, crItem.BonusListIDs, false) : EquipNewItem(uiDest, item, true); if (it != null) { uint new_count = pVendor.UpdateVendorItemCurrentCount(crItem, count); @@ -3630,6 +3630,16 @@ namespace Game.Entities return false; } + PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(crItem.PlayerConditionId); + if (playerCondition != null) + { + if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) + { + SendEquipError(InventoryResult.ItemLocked); + return false; + } + } + // check current item amount if it limited if (crItem.maxcount != 0) { diff --git a/Game/Entities/Unit/Unit.cs b/Game/Entities/Unit/Unit.cs index e984c0465..f69776468 100644 --- a/Game/Entities/Unit/Unit.cs +++ b/Game/Entities/Unit/Unit.cs @@ -661,7 +661,7 @@ namespace Game.Entities } } - void RemoveAllGameObjects() + public void RemoveAllGameObjects() { // remove references to unit while (!m_gameObj.Empty()) diff --git a/Game/Events/GameEventManager.cs b/Game/Events/GameEventManager.cs index 826f26596..ff63b0a63 100644 --- a/Game/Events/GameEventManager.cs +++ b/Game/Events/GameEventManager.cs @@ -23,6 +23,7 @@ using Game.Maps; using Game.Network.Packets; using System; using System.Collections.Generic; +using Framework.Collections; namespace Game { @@ -752,8 +753,8 @@ namespace Game { uint oldMSTime = Time.GetMSTime(); - // 0 1 2 3 4 5 6 - SQLResult result = DB.World.Query("SELECT eventEntry, guid, item, maxcount, incrtime, ExtendedCost, type FROM game_event_npc_vendor ORDER BY guid, slot ASC"); + // 0 1 2 3 4 5 6 7 8 9 + SQLResult result = DB.World.Query("SELECT eventEntry, guid, item, maxcount, incrtime, ExtendedCost, type, BonusListIDs, PlayerConditionId, IgnoreFiltering FROM game_event_npc_vendor ORDER BY guid, slot ASC"); if (result.IsEmpty()) Log.outInfo(LogFilter.ServerLoading, "Loaded 0 vendor additions in game events. DB table `game_event_npc_vendor` is empty."); @@ -763,6 +764,7 @@ namespace Game do { byte event_id = result.Read(0); + ulong guid = result.Read(1); if (event_id >= mGameEventVendors.Length) { @@ -770,13 +772,6 @@ namespace Game continue; } - NPCVendorEntry newEntry = new NPCVendorEntry(); - ulong guid = result.Read(1); - newEntry.item = result.Read(2); - newEntry.maxcount = result.Read(3); - newEntry.incrtime = result.Read(4); - newEntry.ExtendedCost = result.Read(5); - newEntry.Type = result.Read(6); // get the event npc flag for checking if the npc will be vendor during the event or not ulong event_npc_flag = 0; var flist = mGameEventNPCFlags[event_id]; @@ -789,16 +784,29 @@ namespace Game } } // get creature entry - newEntry.entry = 0; + uint entry = 0; CreatureData data = Global.ObjectMgr.GetCreatureData(guid); if (data != null) - newEntry.entry = data.id; + entry = data.id; + + VendorItem vItem = new VendorItem(); + vItem.item = result.Read(2); + vItem.maxcount = result.Read(3); + vItem.incrtime = result.Read(4); + vItem.ExtendedCost = result.Read(5); + vItem.Type = (ItemVendorType)result.Read(6); + vItem.PlayerConditionId = result.Read(8); + vItem.IgnoreFiltering = result.Read(9); + + var bonusListIDsTok = new StringArray(result.Read(7), ' '); + foreach (uint token in bonusListIDsTok) + vItem.BonusListIDs.Add(token); // check validity with event's npcflag - if (!Global.ObjectMgr.IsVendorItemValid(newEntry.entry, newEntry.item, newEntry.maxcount, newEntry.incrtime, newEntry.ExtendedCost, (ItemVendorType)newEntry.Type, null, null, event_npc_flag)) + if (!Global.ObjectMgr.IsVendorItemValid(entry, vItem, null, null, event_npc_flag)) continue; - mGameEventVendors[event_id].Add(newEntry); + mGameEventVendors[event_id].Add(entry, vItem); ++count; } @@ -922,7 +930,7 @@ namespace Game mGameEventCreatureQuests = new List>[maxEventId]; mGameEventGameObjectQuests = new List>[maxEventId]; - mGameEventVendors = new List[maxEventId]; + mGameEventVendors = new Dictionary[maxEventId]; mGameEventBattlegroundHolidays = new uint[maxEventId]; mGameEventNPCFlags = new List>[maxEventId]; mGameEventModelEquip = new List>[maxEventId]; @@ -931,7 +939,7 @@ namespace Game mGameEvent[i] = new GameEventData(); mGameEventCreatureQuests[i] = new List>(); mGameEventGameObjectQuests[i] = new List>(); - mGameEventVendors[i] = new List(); + mGameEventVendors[i] = new Dictionary(); mGameEventNPCFlags[i] = new List>(); mGameEventModelEquip[i] = new List>(); } @@ -1152,9 +1160,9 @@ namespace Game foreach (var npcEventVendor in mGameEventVendors[eventId]) { if (activate) - Global.ObjectMgr.AddVendorItem(npcEventVendor.entry, npcEventVendor.item, npcEventVendor.maxcount, npcEventVendor.incrtime, npcEventVendor.ExtendedCost, (ItemVendorType)npcEventVendor.Type, false); + Global.ObjectMgr.AddVendorItem(npcEventVendor.Key, npcEventVendor.Value, false); else - Global.ObjectMgr.RemoveVendorItem(npcEventVendor.entry, npcEventVendor.item, (ItemVendorType)npcEventVendor.Type, false); + Global.ObjectMgr.RemoveVendorItem(npcEventVendor.Key, npcEventVendor.Value.item, npcEventVendor.Value.Type, false); } } @@ -1615,7 +1623,7 @@ namespace Game List>[] mGameEventCreatureQuests; List>[] mGameEventGameObjectQuests; - List[] mGameEventVendors; + Dictionary[] mGameEventVendors; List>[] mGameEventModelEquip; List[] mGameEventPoolIds; GameEventData[] mGameEvent; @@ -1675,16 +1683,6 @@ namespace Game public byte equipement_id_prev; } - public struct NPCVendorEntry - { - public uint entry; // creature entry - public uint item; // item id - public int maxcount; // 0 for infinite - public uint incrtime; // time for restore items amount if maxcount != 0 - public uint ExtendedCost; - public byte Type; // 1 item, 2 currency - } - class GameEventAIHookWorker : Notifier { public GameEventAIHookWorker(ushort eventId, bool activate) diff --git a/Game/Globals/ObjectManager.cs b/Game/Globals/ObjectManager.cs index 91cd9029f..2c306fd38 100644 --- a/Game/Globals/ObjectManager.cs +++ b/Game/Globals/ObjectManager.cs @@ -3093,7 +3093,7 @@ namespace Game List skipvendors = new List(); - SQLResult result = DB.World.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost, type FROM npc_vendor ORDER BY entry, slot ASC"); + SQLResult result = DB.World.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost, type, BonusListIDs, PlayerConditionID, IgnoreFiltering FROM npc_vendor ORDER BY entry, slot ASC"); if (result.IsEmpty()) { Log.outError(LogFilter.ServerLoading, "Loaded 0 Vendors. DB table `npc_vendor` is empty!"); @@ -3109,33 +3109,40 @@ namespace Game // if item is a negative, its a reference if (itemid < 0) - count += LoadReferenceVendor((int)entry, -itemid, 0, skipvendors); + count += LoadReferenceVendor((int)entry, -itemid, skipvendors); else { - int maxcount = result.Read(2); - uint incrtime = result.Read(3); - uint ExtendedCost = result.Read(4); - ItemVendorType type = (ItemVendorType)result.Read(5); + VendorItem vItem = new VendorItem(); + vItem.item = (uint)itemid; + vItem.maxcount = result.Read(2); + vItem.incrtime = result.Read(3); + vItem.ExtendedCost = result.Read(4); + vItem.Type = (ItemVendorType)result.Read(5); + vItem.PlayerConditionId = result.Read(7); + vItem.IgnoreFiltering = result.Read(8); - if (!IsVendorItemValid(entry, (uint)itemid, maxcount, incrtime, ExtendedCost, type, null, skipvendors)) + var bonusListIDsTok = new StringArray(result.Read(6), ' '); + foreach (string token in bonusListIDsTok) + vItem.BonusListIDs.Add(uint.Parse(token)); + + if (!IsVendorItemValid(entry, vItem, null, skipvendors)) continue; if (cacheVendorItemStorage.LookupByKey(entry) == null) cacheVendorItemStorage.Add(entry, new VendorItemData()); - cacheVendorItemStorage[entry].AddItem((uint)itemid, maxcount, incrtime, ExtendedCost, type); + cacheVendorItemStorage[entry].AddItem(vItem); ++count; } } while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} Vendors in {1} ms", count, Time.GetMSTimeDiffToNow(time)); } - uint LoadReferenceVendor(int vendor, int item, byte type, List skip_vendors) + uint LoadReferenceVendor(int vendor, int item, List skip_vendors) { // find all items from the reference vendor PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.SEL_NPC_VENDOR_REF); stmt.AddValue(0, item); - stmt.AddValue(1, type); SQLResult result = DB.World.Query(stmt); if (result.IsEmpty()) @@ -3148,20 +3155,28 @@ namespace Game // if item is a negative, its a reference if (item_id < 0) - count += LoadReferenceVendor(vendor, -item_id, type, skip_vendors); + count += LoadReferenceVendor(vendor, -item_id, skip_vendors); else { - int maxcount = result.Read(1); - uint incrtime = result.Read(2); - uint ExtendedCost = result.Read(3); - ItemVendorType _type = (ItemVendorType)result.Read(4); + VendorItem vItem = new VendorItem(); + vItem.item = (uint)item_id; + vItem.maxcount = result.Read(1); + vItem.incrtime = result.Read(2); + vItem.ExtendedCost = result.Read(3); + vItem.Type = (ItemVendorType)result.Read(4); + vItem.PlayerConditionId = result.Read(6); + vItem.IgnoreFiltering = result.Read(7); - if (!IsVendorItemValid((uint)vendor, (uint)item_id, maxcount, incrtime, ExtendedCost, _type, null, skip_vendors)) + var bonusListIDsTok = new StringArray(result.Read(5), ' '); + foreach (string token in bonusListIDsTok) + vItem.BonusListIDs.Add(uint.Parse(token)); + + if (!IsVendorItemValid((uint)vendor, vItem, null, skip_vendors)) continue; VendorItemData vList = cacheVendorItemStorage[(uint)vendor]; - vList.AddItem((uint)item_id, maxcount, incrtime, ExtendedCost, _type); + vList.AddItem(vItem); ++count; } } while (result.NextRow()); @@ -4663,21 +4678,21 @@ namespace Game { return _trainers.LookupByKey(trainerId); } - public void AddVendorItem(uint entry, uint item, int maxcount, uint incrtime, uint extendedCost, ItemVendorType type, bool persist = true) + public void AddVendorItem(uint entry, VendorItem vItem, bool persist = true) { VendorItemData vList = cacheVendorItemStorage[entry]; - vList.AddItem(item, maxcount, incrtime, extendedCost, type); + vList.AddItem(vItem); if (persist) { PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.INS_NPC_VENDOR); stmt.AddValue(0, entry); - stmt.AddValue(1, item); - stmt.AddValue(2, maxcount); - stmt.AddValue(3, incrtime); - stmt.AddValue(4, extendedCost); - stmt.AddValue(5, (byte)type); + stmt.AddValue(1, vItem.item); + stmt.AddValue(2, vItem.maxcount); + stmt.AddValue(3, vItem.incrtime); + stmt.AddValue(4, vItem.ExtendedCost); + stmt.AddValue(5, vItem.Type); DB.World.Execute(stmt); } @@ -4704,7 +4719,7 @@ namespace Game return true; } - public bool IsVendorItemValid(uint vendorentry, uint id, int maxcount, uint incrtime, uint ExtendedCost, ItemVendorType type, Player player = null, List skipvendors = null, ulong ORnpcflag = 0) + public bool IsVendorItemValid(uint vendorentry, VendorItem vItem, Player player = null, List skipvendors = null, ulong ORnpcflag = 0) { CreatureTemplate cInfo = GetCreatureTemplate(vendorentry); if (cInfo == null) @@ -4731,55 +4746,76 @@ namespace Game return false; } - if ((type == ItemVendorType.Item && GetItemTemplate(id) == null) || - (type == ItemVendorType.Currency && CliDB.CurrencyTypesStorage.LookupByKey(id) == null)) + if ((vItem.Type == ItemVendorType.Item && GetItemTemplate(vItem.item) == null) || + (vItem.Type == ItemVendorType.Currency && CliDB.CurrencyTypesStorage.LookupByKey(vItem.item) == null)) { if (player != null) - player.SendSysMessage(CypherStrings.ItemNotFound, id, type); + player.SendSysMessage(CypherStrings.ItemNotFound, vItem.item, vItem.Type); else - Log.outError(LogFilter.Sql, "Table `(gameevent)npcvendor` for Vendor (Entry: {0}) have in item list non-existed item ({1}, type {2}), ignore", vendorentry, id, type); + Log.outError(LogFilter.Sql, "Table `(gameevent)npcvendor` for Vendor (Entry: {0}) have in item list non-existed item ({1}, type {2}), ignore", vendorentry, vItem.item, vItem.Type); return false; } - if (ExtendedCost != 0 && !CliDB.ItemExtendedCostStorage.ContainsKey(ExtendedCost)) + if (vItem.PlayerConditionId != 0 && !CliDB.PlayerConditionStorage.ContainsKey(vItem.PlayerConditionId)) { - if (player != null) - player.SendSysMessage(CypherStrings.ExtendedCostNotExist, ExtendedCost); - else - Log.outError(LogFilter.Sql, "Table `(gameevent)npcvendor` have Item (Entry: {0}) with wrong ExtendedCost ({1}) for vendor ({2}), ignore", id, ExtendedCost, vendorentry); + Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` has Item (Entry: {0}) with invalid PlayerConditionId ({1}) for vendor ({2}), ignore", vItem.item, vItem.PlayerConditionId, vendorentry); return false; } - if (type == ItemVendorType.Item) // not applicable to currencies + if (vItem.ExtendedCost != 0 && !CliDB.ItemExtendedCostStorage.ContainsKey(vItem.ExtendedCost)) { - if (maxcount > 0 && incrtime == 0) + if (player != null) + player.SendSysMessage(CypherStrings.ExtendedCostNotExist, vItem.ExtendedCost); + else + Log.outError(LogFilter.Sql, "Table `(gameevent)npcvendor` have Item (Entry: {0}) with wrong ExtendedCost ({1}) for vendor ({2}), ignore", vItem.item, vItem.ExtendedCost, vendorentry); + return false; + } + + if (vItem.Type == ItemVendorType.Item) // not applicable to currencies + { + if (vItem.maxcount > 0 && vItem.incrtime == 0) { if (player != null) - player.SendSysMessage("MaxCount != 0 ({0}) but IncrTime == 0", maxcount); + player.SendSysMessage("MaxCount != 0 ({0}) but IncrTime == 0", vItem.maxcount); else - Log.outError(LogFilter.Sql, "Table `(gameevent)npcvendor` has `maxcount` ({0}) for item {1} of vendor (Entry: {2}) but `incrtime`=0, ignore", maxcount, id, vendorentry); + Log.outError(LogFilter.Sql, "Table `(gameevent)npcvendor` has `maxcount` ({0}) for item {1} of vendor (Entry: {2}) but `incrtime`=0, ignore", vItem.maxcount, vItem.item, vendorentry); return false; } - else if (maxcount == 0 && incrtime > 0) + else if (vItem.maxcount == 0 && vItem.incrtime > 0) { if (player != null) player.SendSysMessage("MaxCount == 0 but IncrTime<>= 0"); else - Log.outError(LogFilter.Sql, "Table `(gameevent)npcvendor` has `maxcount`=0 for item {0} of vendor (Entry: {0}) but `incrtime`<>0, ignore", id, vendorentry); + Log.outError(LogFilter.Sql, "Table `(gameevent)npcvendor` has `maxcount`=0 for item {0} of vendor (Entry: {0}) but `incrtime`<>0, ignore", vItem.item, vendorentry); return false; } + + foreach (uint bonusList in vItem.BonusListIDs) + { + if (Global.DB2Mgr.GetItemBonusList(bonusList) == null) + { + Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` have Item (Entry: {0}) with invalid bonus {1} for vendor ({2}), ignore", vItem.item, bonusList, vendorentry); + return false; + } + } } VendorItemData vItems = GetNpcVendorItemList(vendorentry); if (vItems == null) return true; // later checks for non-empty lists - if (vItems.FindItemCostPair(id, ExtendedCost, type) != null) + if (vItems.FindItemCostPair(vItem.item, vItem.ExtendedCost, vItem.Type) != null) { if (player != null) - player.SendSysMessage(CypherStrings.ItemAlreadyInList, id, ExtendedCost, type); + player.SendSysMessage(CypherStrings.ItemAlreadyInList, vItem.item, vItem.ExtendedCost, vItem.Type); else - Log.outError(LogFilter.Sql, "Table `npcvendor` has duplicate items {0} (with extended cost {1}, type {2}) for vendor (Entry: {3}), ignoring", id, ExtendedCost, type, vendorentry); + Log.outError(LogFilter.Sql, "Table `npcvendor` has duplicate items {0} (with extended cost {1}, type {2}) for vendor (Entry: {3}), ignoring", vItem.item, vItem.ExtendedCost, vItem.Type, vendorentry); + return false; + } + + if (vItem.Type == ItemVendorType.Currency && vItem.maxcount == 0) + { + Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` have Item (Entry: {0}, type: {1}) with missing maxcount for vendor ({2}), ignore", vItem.item, vItem.Type, vendorentry); return false; } @@ -8541,6 +8577,10 @@ namespace Game stmt.AddValue(0, itemInfo.item_guid); DB.Characters.Execute(stmt); } + + stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_MAIL_ITEM_BY_ID); + stmt.AddValue(0, m.messageID); + DB.Characters.Execute(stmt); } else { diff --git a/Game/Handlers/NPCHandler.cs b/Game/Handlers/NPCHandler.cs index 8ac3de6ff..6530b1a92 100644 --- a/Game/Handlers/NPCHandler.cs +++ b/Game/Handlers/NPCHandler.cs @@ -491,6 +491,11 @@ namespace Game VendorItemPkt item = new VendorItemPkt(); + PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(vendorItem.PlayerConditionId); + if (playerCondition != null) + if (!ConditionManager.IsPlayerMeetingCondition(_player, playerCondition)) + item.PlayerConditionFailed = (int)playerCondition.Id; + if (vendorItem.Type == ItemVendorType.Item) { ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(vendorItem.item); @@ -530,8 +535,14 @@ namespace Game item.Quantity = leftInStock; item.StackCount = (int)itemTemplate.GetBuyCount(); item.Price = (ulong)price; + item.DoNotFilterOnVendor = vendorItem.IgnoreFiltering; item.Item.ItemID = vendorItem.item; + if (!vendorItem.BonusListIDs.Empty()) + { + item.Item.ItemBonus.HasValue = true; + item.Item.ItemBonus.Value.BonusListIDs = vendorItem.BonusListIDs; + } packet.Items.Add(item); } @@ -549,6 +560,7 @@ namespace Game item.Item.ItemID = vendorItem.item; item.Type = (int)vendorItem.Type; item.StackCount = (int)vendorItem.maxcount; + item.DoNotFilterOnVendor = vendorItem.IgnoreFiltering; packet.Items.Add(item); } diff --git a/Game/Scripting/SpellScript.cs b/Game/Scripting/SpellScript.cs index ca1ee4aac..eacf699e9 100644 --- a/Game/Scripting/SpellScript.cs +++ b/Game/Scripting/SpellScript.cs @@ -626,7 +626,7 @@ namespace Game.Scripting } m_spell.m_damage = damage; } - void PreventHitDamage() { SetHitDamage(0); } + public void PreventHitDamage() { SetHitDamage(0); } // setter/getter for for heal done by spell to target of spell hit // returns healing calculated before hit, and real dmg done after hit public int GetHitHeal() @@ -664,7 +664,7 @@ namespace Game.Scripting return m_spell.m_spellAura; } // prevents applying aura on current spell hit target - void PreventHitAura() + public void PreventHitAura() { if (!IsInTargetHook()) { diff --git a/Scripts/Northrend/IcecrownCitadel/IcecrownCitadel.cs b/Scripts/Northrend/IcecrownCitadel/IcecrownCitadel.cs index 02f150fe0..6ccc5ebd4 100644 --- a/Scripts/Northrend/IcecrownCitadel/IcecrownCitadel.cs +++ b/Scripts/Northrend/IcecrownCitadel/IcecrownCitadel.cs @@ -939,8 +939,7 @@ namespace Scripts.Northrend.IcecrownCitadel class npc_argent_captainAI : ScriptedAI { - public npc_argent_captainAI(Creature creature) - : base(creature) + public npc_argent_captainAI(Creature creature) : base(creature) { instance = creature.GetInstanceScript(); _firstDeath = true;