using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using Server; using Server.Items; using Server.Mobiles; using Server.ContextMenus; using Server.Commands; using Server.Targeting; using Server.Regions; using Server.Gumps; using Server.Engines.Auction; namespace Server.Engines.VendorSearching { public class VendorSearch { public static string FilePath = Path.Combine("Saves/Misc", "VendorSearch.bin"); public static Ultima.StringList StringList { get; private set; } public static List DoSearchAuction(Mobile m, SearchCriteria criteria) { if (criteria == null || Auction.Auction.Auctions == null || Auction.Auction.Auctions.Count == 0) { return null; } List list = new List(); bool excludefel = criteria.Details.FirstOrDefault(d => d.Attribute is Misc && (Misc)d.Attribute == Misc.ExcludeFel) != null; foreach (Auction.Auction pv in Auction.Auction.Auctions.Where(pv => pv.AuctionItem != null && pv.AuctionItem.Map != Map.Internal && pv.AuctionItem.Map != null && pv.OnGoing && (!excludefel || pv.AuctionItem.Map != Map.Felucca))) { list.Add(new SearchItem(pv.Safe, pv.AuctionItem, (int)pv.Buyout, false)); } switch (criteria.SortBy) { case SortBy.LowToHigh: list = list.OrderBy(vi => vi.Price).ToList(); break; case SortBy.HighToLow: list = list.OrderBy(vi => -vi.Price).ToList(); break; } return list; } public static List DoSearch(Mobile m, SearchCriteria criteria) { if (criteria == null || PlayerVendor.PlayerVendors == null || PlayerVendor.PlayerVendors.Count == 0) return null; List list = new List(); bool excludefel = criteria.Details.FirstOrDefault(d => d.Attribute is Misc && (Misc)d.Attribute == Misc.ExcludeFel) != null; foreach (PlayerVendor pv in PlayerVendor.PlayerVendors.Where(pv => pv.Map != Map.Internal && pv.Map != null && pv.Backpack != null && pv.VendorSearch && pv.Backpack.Items.Count > 0 && (!excludefel || pv.Map != Map.Felucca))) { List items = GetItems(pv); foreach (Item item in items) { VendorItem vendorItem = pv.GetVendorItem(item); int price = 0; bool isChild = false; if (vendorItem != null) { price = vendorItem.Price; } else if (item.Parent is Container) { vendorItem = GetParentVendorItem(pv, (Container)item.Parent); if (vendorItem != null) { isChild = true; price = vendorItem.Price; } } if (price > 0 && CheckMatch(item, price, criteria)) { list.Add(new SearchItem(pv, item, price, isChild)); } } ColUtility.Free(items); } switch (criteria.SortBy) { case SortBy.LowToHigh: list = list.OrderBy(vi => vi.Price).ToList(); break; case SortBy.HighToLow: list = list.OrderBy(vi => -vi.Price).ToList(); break; } return list; } private static VendorItem GetParentVendorItem(PlayerVendor pv, Container parent) { VendorItem vendorItem = pv.GetVendorItem(parent); if (vendorItem == null) { if (parent.Parent is Container) { return GetParentVendorItem(pv, (Container)parent.Parent); } } return vendorItem; } public static bool CheckMatch(Item item, int price, SearchCriteria searchCriteria) { if (item is CommodityDeed && ((CommodityDeed)item).Commodity != null) { item = ((CommodityDeed)item).Commodity; } if (searchCriteria.MinPrice > -1 && price < searchCriteria.MinPrice) return false; if (searchCriteria.MaxPrice > -1 && price > searchCriteria.MaxPrice) return false; if (!string.IsNullOrEmpty(searchCriteria.SearchName)) { string name; if (item is CommodityDeed && ((CommodityDeed)item).Commodity is ICommodity) { var commodity = (ICommodity)((CommodityDeed)item).Commodity; if (!string.IsNullOrEmpty(commodity.Description.String)) { name = commodity.Description.String; } else { name = StringList.GetString(commodity.Description.Number); } } else { name = GetItemName(item); } if(name == null) { return false; // TODO? REturn null names? } if (!CheckKeyword(searchCriteria.SearchName, item) && name.ToLower().IndexOf(searchCriteria.SearchName.ToLower()) < 0) { return false; } } if (searchCriteria.SearchType != Layer.Invalid && searchCriteria.SearchType != item.Layer) { return false; } if(searchCriteria.Details.Count == 0) return true; foreach(SearchDetail detail in searchCriteria.Details) { object o = detail.Attribute; int value = detail.Value; if (value == 0) value = 1; if (o is AosAttribute) { AosAttributes attrs = RunicReforging.GetAosAttributes(item); if (attrs == null || attrs[(AosAttribute)o] < value) return false; } else if (o is AosWeaponAttribute) { AosWeaponAttributes attrs = RunicReforging.GetAosWeaponAttributes(item); if ((AosWeaponAttribute)o == AosWeaponAttribute.MageWeapon) { if (attrs == null || attrs[(AosWeaponAttribute)o] == 0 || attrs[(AosWeaponAttribute)o] > Math.Max(0, 30 - value)) return false; } else if (attrs == null || attrs[(AosWeaponAttribute)o] < value) return false; } else if (o is SAAbsorptionAttribute) { SAAbsorptionAttributes attrs = RunicReforging.GetSAAbsorptionAttributes(item); if (attrs == null || attrs[(SAAbsorptionAttribute)o] < value) return false; } else if (o is AosArmorAttribute) { AosArmorAttributes attrs = RunicReforging.GetAosArmorAttributes(item); if (attrs == null || attrs[(AosArmorAttribute)o] < value) return false; } else if (o is SkillName) { if (detail.Category != Category.RequiredSkill) { AosSkillBonuses skillbonuses = RunicReforging.GetAosSkillBonuses(item); if (skillbonuses != null) { bool hasSkill = false; for (int i = 0; i < 5; i++) { SkillName check; double bonus; if (skillbonuses.GetValues(i, out check, out bonus) && check == (SkillName)o && bonus >= value) { hasSkill = true; break; } } if (!hasSkill) return false; } else if (item is SpecialScroll && value >= 105) { if (((SpecialScroll)item).Skill != (SkillName)o || ((SpecialScroll)item).Value < value) return false; } else { return false; } } else if (!(item is BaseWeapon) || ((BaseWeapon)item).DefSkill != (SkillName)o) { return false; } } else if (!CheckSlayer(item, o)) { return false; } else if (o is AosElementAttribute) { if (item is BaseWeapon) { BaseWeapon wep = item as BaseWeapon; if (detail.Category == Category.DamageType) { int phys, fire, cold, pois, nrgy, chaos, direct; wep.GetDamageTypes(null, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct); switch ((AosElementAttribute)o) { case AosElementAttribute.Physical: if (phys < value) return false; break; case AosElementAttribute.Fire: if (fire < value) return false; break; case AosElementAttribute.Cold: if (cold < value) return false; break; case AosElementAttribute.Poison: if (pois < value) return false; break; case AosElementAttribute.Energy: if (nrgy < value) return false; break; case AosElementAttribute.Chaos: if (chaos < value) return false; break; case AosElementAttribute.Direct: if (direct < value) return false; break; } } else { switch ((AosElementAttribute)o) { case AosElementAttribute.Physical: if (wep.WeaponAttributes.ResistPhysicalBonus < value) return false; break; case AosElementAttribute.Fire: if (wep.WeaponAttributes.ResistFireBonus < value) return false; break; case AosElementAttribute.Cold: if (wep.WeaponAttributes.ResistColdBonus < value) return false; break; case AosElementAttribute.Poison: if (wep.WeaponAttributes.ResistPoisonBonus < value) return false; break; case AosElementAttribute.Energy: if (wep.WeaponAttributes.ResistEnergyBonus < value) return false; break; } } } else if (item is BaseArmor && detail.Category == Category.Resists) { BaseArmor armor = item as BaseArmor; switch ((AosElementAttribute)o) { case AosElementAttribute.Physical: if (armor.PhysicalResistance < value) return false; break; case AosElementAttribute.Fire: if (armor.FireResistance < value) return false; break; case AosElementAttribute.Cold: if (armor.ColdResistance < value) return false; break; case AosElementAttribute.Poison: if (armor.PoisonResistance < value) return false; break; case AosElementAttribute.Energy: if (armor.EnergyResistance < value) return false; break; } } else if (detail.Category != Category.DamageType) { AosElementAttributes attrs = RunicReforging.GetElementalAttributes(item); if (attrs == null || attrs[(AosElementAttribute)o] < value) { return false; } } else { return false; } } else if (o is Misc) { switch ((Misc)o) { case Misc.ExcludeFel: break; case Misc.GargoyleOnly: if (!IsGargoyle(item)) return false; break; case Misc.NotGargoyleOnly: if (IsGargoyle(item)) return false; break; case Misc.ElvesOnly: if (!IsElf(item)) return false; break; case Misc.NotElvesOnly: if (IsElf(item)) return false; break; case Misc.FactionItem: if (!(item is Factions.IFactionItem)) return false; break; case Misc.PromotionalToken: if (!(item is PromotionalToken)) return false; break; case Misc.Cursed: if (item.LootType != LootType.Cursed) return false; break; case Misc.NotCursed: if (item.LootType == LootType.Cursed) return false; break; case Misc.CannotRepair: if (CheckCanRepair(item)) return false; break; case Misc.NotCannotBeRepaired: if (!CheckCanRepair(item)) return false; break; case Misc.Brittle: NegativeAttributes neg2 = RunicReforging.GetNegativeAttributes(item); if (neg2 == null || neg2.Brittle == 0) return false; break; case Misc.NotBrittle: NegativeAttributes neg3 = RunicReforging.GetNegativeAttributes(item); if (neg3 != null && neg3.Brittle > 0) return false; break; case Misc.Antique: NegativeAttributes neg4 = RunicReforging.GetNegativeAttributes(item); if (neg4 == null || neg4.Antique == 0) return false; break; case Misc.NotAntique: NegativeAttributes neg5 = RunicReforging.GetNegativeAttributes(item); if (neg5 != null && neg5.Antique > 0) return false; break; } } else if (o is string) { string str = o as string; if (str == "WeaponVelocity" && (!(item is BaseRanged) || ((BaseRanged)item).Velocity < value)) return false; if (str == "SearingWeapon" && (!(item is BaseWeapon) || !((BaseWeapon)item).SearingWeapon)) return false; if (str == "ArtifactRarity" && (!(item is IArtifact) || ((IArtifact)item).ArtifactRarity < value)) { return false; } } } return true; } private static bool CheckSlayer(Item item, object o) { if (o is TalismanSlayerName && (TalismanSlayerName)o == TalismanSlayerName.Undead) { if (!(item is ISlayer) || ((((ISlayer)item).Slayer != SlayerName.Silver && ((ISlayer)item).Slayer2 != SlayerName.Silver))) { if (!(item is BaseTalisman) || ((BaseTalisman)item).Slayer != TalismanSlayerName.Undead) { return false; } } } else { if (o is SlayerName && (!(item is ISlayer) || (((ISlayer)item).Slayer != (SlayerName)o && ((ISlayer)item).Slayer2 != (SlayerName)o))) { return false; } else if (o is TalismanSlayerName && (!(item is BaseTalisman) || ((BaseTalisman)item).Slayer != (TalismanSlayerName)o)) { return false; } } return true; } private static bool CheckCanRepair(Item item) { NegativeAttributes neg = RunicReforging.GetNegativeAttributes(item); return neg != null && neg.NoRepair != 0; } private static bool CheckKeyword(string searchstring, Item item) { if (item is CommodityDeed && ((CommodityDeed)item).Commodity != null) { item = ((CommodityDeed)item).Commodity; } if (item is IResource) { var resName = CraftResources.GetName(((IResource)item).Resource); if (resName.ToLower().IndexOf(searchstring.ToLower()) >= 0) { return true; } } if (item is ICommodity) { var commodity = (ICommodity)item; string name = commodity.Description.String; if (string.IsNullOrEmpty(name) && commodity.Description.Number > 0) { name = StringList.GetString(commodity.Description.Number); } if (!string.IsNullOrEmpty(name) && name.ToLower().IndexOf(searchstring.ToLower()) >= 0) { return true; } } return Keywords.ContainsKey(searchstring.ToLower()) && Keywords[searchstring.ToLower()] == item.GetType(); } public static bool IsGargoyle(Item item) { if (item is BaseArmor) { return ((BaseArmor)item).RequiredRace == Race.Gargoyle; } else if (item is BaseWeapon) { return ((BaseWeapon)item).RequiredRace == Race.Gargoyle; } else if (item is BaseClothing) { return ((BaseClothing)item).RequiredRace == Race.Gargoyle; } else if (item is BaseJewel) { return ((BaseJewel)item).RequiredRace == Race.Gargoyle; } return false; } public static bool IsElf(Item item) { if (item is BaseArmor) { return ((BaseArmor)item).RequiredRace == Race.Elf; } else if (item is BaseWeapon) { return ((BaseWeapon)item).RequiredRace == Race.Elf; } else if (item is BaseClothing) { return ((BaseClothing)item).RequiredRace == Race.Elf; } else if (item is BaseJewel) { return ((BaseJewel)item).RequiredRace == Race.Elf; } return false; } public static SearchCriteria AddNewContext(PlayerMobile pm) { SearchCriteria criteria = new SearchCriteria(); Contexts[pm] = criteria; return criteria; } public static SearchCriteria GetContext(PlayerMobile pm) { if (Contexts.ContainsKey(pm)) return Contexts[pm]; return null; } public static Dictionary Contexts { get; set; } public static List Categories { get; set; } public static Dictionary Keywords { get; set; } public static void Configure() { EventSink.WorldSave += OnSave; EventSink.WorldLoad += OnLoad; } public static void OnSave(WorldSaveEventArgs e) { Persistence.Serialize( FilePath, writer => { writer.Write(0); writer.Write(Contexts == null ? 0 : Contexts.Where(kvp => !kvp.Value.IsEmpty).Count()); if (Contexts != null) { foreach (var kvp in Contexts.Where(kvp => !kvp.Value.IsEmpty)) { writer.Write(kvp.Key); kvp.Value.Serialize(writer); } } }); } public static void OnLoad() { Persistence.Deserialize( FilePath, reader => { int version = reader.ReadInt(); int count = reader.ReadInt(); for (int i = 0; i < count; i++) { PlayerMobile pm = reader.ReadMobile() as PlayerMobile; var criteria = new SearchCriteria(reader); if (pm != null) { if (Contexts == null) Contexts = new Dictionary(); Contexts[pm] = criteria; } } }); } public static void Initialize() { try { StringList = new Ultima.StringList("enu"); } catch { } CommandSystem.Register("GetOPLString", AccessLevel.Administrator, e => { e.Mobile.BeginTarget(-1, false, TargetFlags.None, (m, targeted) => { if (targeted is Item) { Console.WriteLine(GetItemName((Item)targeted)); e.Mobile.SendMessage(GetItemName((Item)targeted)); } }); }); Categories = new List(); if (Contexts == null) { Contexts = new Dictionary(); } Timer.DelayCall(TimeSpan.FromSeconds(1), () => { SearchCategory price = new SearchCategory(Category.PriceRange); Categories.Add(price); SearchCriteriaCategory.AllCategories.ToList().ForEach(x => { SearchCategory cat = new SearchCategory(x.Category); x.Criteria.ToList().ForEach(y => { if (y.PropCliloc != 0) { cat.Register(y.Object, y.Cliloc, y.PropCliloc); } else { cat.Register(y.Object, y.Cliloc); } }); Categories.Add(cat); }); SearchCategory sort = new SearchCategory(Category.Sort); Categories.Add(sort); }); Keywords = new Dictionary(); Keywords["power scroll"] = typeof(PowerScroll); Keywords["stat scroll"] = typeof(StatCapScroll); } public static string GetItemName(Item item) { if (StringList == null || item.Name != null) return item.Name; ObjectPropertyList opl = new ObjectPropertyList(item); item.GetProperties(opl); if (opl == null) { //if there was a problem with this process, just return null return null; } //since the object property list is based on a packet object, the property info is packed away in a packet format byte[] data = opl.UnderlyingStream.UnderlyingStream.ToArray(); int index = 15; // First localization number index string basestring = null; //reset the number property uint number = 0; //if there's not enough room for another record, quit if (index + 4 >= data.Length) { return null; } //read number property from the packet data number = (uint)(data[index++] << 24 | data[index++] << 16 | data[index++] << 8 | data[index++]); //reset the length property ushort length = 0; //if there's not enough room for another record, quit if (index + 2 > data.Length) { return null; } //read length property from the packet data length = (ushort)(data[index++] << 8 | data[index++]); //determine the location of the end of the string int end = index + length; //truncate if necessary if (end >= data.Length) { end = data.Length - 1; } //read the string into a StringBuilder object StringBuilder s = new StringBuilder(); while (index + 2 <= end + 1) { short next = (short)(data[index++] | data[index++] << 8); if (next == 0) break; s.Append(Encoding.Unicode.GetString(BitConverter.GetBytes(next))); } basestring = StringList.GetString((int)number); string args = s.ToString(); if (args == null || args == string.Empty) { return basestring; } string[] parms = args.Split('\t'); try { if (parms.Length > 1) { for (int i = 0; i < parms.Length; i++) { parms[i] = parms[i].Trim(' '); if (parms[i].IndexOf("#") == 0) { parms[i] = StringList.GetString(Convert.ToInt32(parms[i].Substring(1, parms[i].Length - 1))); } } } else if (parms.Length == 1 && parms[0].IndexOf("#") == 0) { parms[0] = StringList.GetString(Convert.ToInt32(args.Substring(1, parms[0].Length - 1))); } } catch { return null; } Ultima.StringEntry entry = StringList.GetEntry((int)number); if (entry != null) { return entry.Format(parms); } return basestring; } private static List GetItems(PlayerVendor pv) { List list = new List(); foreach (Item item in pv.Items) if (item.Movable && item != pv.Backpack && item.Layer != Layer.Hair && item.Layer != Layer.FacialHair) list.Add(item); if (pv.Backpack != null) { GetItems(pv.Backpack, list); } return list; } public static void GetItems(Container c, List list) { if (c == null || c.Items.Count == 0) return; foreach (Item item in c.Items) { if (item is Container && !IsSearchableContainer(item.GetType())) GetItems((Container)item, list); else list.Add(item); } } public static bool CanSearch(Mobile m) { Region r = m.Region; if (r.GetLogoutDelay(m) == TimeSpan.Zero) return true; return r is GuardedRegion && !((GuardedRegion)r).Disabled || r is HouseRegion && ((HouseRegion)r).House.IsFriend(m); } private static bool IsSearchableContainer(Type type) { return _SearchableContainers.Any(t => t == type || type.IsSubclassOf(t)); } private static Type[] _SearchableContainers = { typeof(BaseQuiver), typeof(BaseResourceSatchel), typeof(FishBowl), typeof(FirstAidBelt), typeof(Plants.SeedBox), typeof(BaseSpecialScrollBook), typeof(GardenShedBarrel), typeof(JewelryBox), }; } public enum SortBy { LowToHigh, HighToLow } public enum Category { PriceRange, Misc, Equipment, Combat, Casting, DamageType, HitSpell, HitArea, Resists, Stats, Slayer1, Slayer2, Slayer3, RequiredSkill, Skill1, Skill2, Skill3, Skill4, Skill5, Skill6, Sort, Auction } public enum Misc { ExcludeFel, GargoyleOnly, NotGargoyleOnly, ElvesOnly, NotElvesOnly, FactionItem, PromotionalToken, Cursed, NotCursed, CannotRepair, NotCannotBeRepaired, Brittle, NotBrittle, Antique, NotAntique } public enum SpecialSearch { PowerScroll, StatScroll, Transcendence, Alacrity, UsesRemaining } public class SearchCategory { public Category Category { get; private set; } public int Label { get { return (int)Category; } } public List> Objects { get; private set; } public SearchCategory(Category category) { Category = category; Objects = new List>(); } public void Register(object o, int label) { if (Objects.FirstOrDefault(t => t.Item1 == o) == null) { Objects.Add(new Tuple(o, label, 0)); } } public void Register(object o, int label, int pcliloc) { if (Objects.FirstOrDefault(t => t.Item1 == o) == null) { Objects.Add(new Tuple(o, label, pcliloc)); } } } public class SearchCriteria { public Layer SearchType { get; set; } public string SearchName { get; set; } public SortBy SortBy { get; set; } public bool Auction { get; set; } public long MinPrice { get; set; } public long MaxPrice { get; set; } public bool EntryPrice { get; set; } public List Details { get; set; } public SearchCriteria() { Details = new List(); MinPrice = 0; MaxPrice = 175000000; SearchType = Layer.Invalid; } public void Reset() { Details.Clear(); Details.TrimExcess(); Details = new List(); MinPrice = 0; MaxPrice = 175000000; SortBy = SortBy.LowToHigh; Auction = false; SearchName = null; SearchType = Layer.Invalid; EntryPrice = false; } public int GetValueForDetails(object o) { SearchDetail detail = Details.FirstOrDefault(d => d.Attribute == o); return detail != null ? detail.Value : 0; } public void TryAddDetails(object o, int name, int propname, int value, Category cat) { SearchDetail d = Details.FirstOrDefault(det => det.Attribute == o); if (o is Layer) { SearchDetail layer = Details.FirstOrDefault(det => det.Attribute is Layer && (Layer)det.Attribute != (Layer)o); if (layer != null) { Details.Remove(layer); } Details.Add(new SearchDetail(o, name, propname, value, cat)); SearchType = (Layer)o; } else if (d == null) { d = new SearchDetail(o, name, propname, value, cat); Details.Add(d); } else if (d.Value != value) { d.Value = value; } /*if (d.Attribute is TalismanSlayerName && (TalismanSlayerName)d.Attribute == TalismanSlayerName.Undead) { TryAddDetails(SlayerName.Silver, name, value, cat); }*/ } public bool IsEmpty { get { return Details.Count == 0 && !EntryPrice && string.IsNullOrEmpty(SearchName) && SearchType == Layer.Invalid; } } public SearchCriteria(GenericReader reader) { int version = reader.ReadInt(); Details = new List(); if (version > 1) Auction = reader.ReadBool(); if (version != 0) EntryPrice = reader.ReadBool(); SearchType = (Layer)reader.ReadInt(); SearchName = reader.ReadString(); SortBy = (SortBy)reader.ReadInt(); MinPrice = reader.ReadLong(); MaxPrice = reader.ReadLong(); int count = reader.ReadInt(); for (int i = 0; i < count; i++) { Details.Add(new SearchDetail(reader)); } } public void Serialize(GenericWriter writer) { writer.Write(2); writer.Write((bool)Auction); writer.Write((bool)EntryPrice); writer.Write((int)SearchType); writer.Write(SearchName); writer.Write((int)SortBy); writer.Write(MinPrice); writer.Write(MaxPrice); writer.Write(Details.Count); for (int i = 0; i < Details.Count; i++) { Details[i].Serialize(writer); } } } public class SearchDetail { public enum AttributeID { None = 0, AosAttribute, AosArmorAttribute, AosWeaponAttribute, AosElementAttribute, SkillName, SAAbosorptionAttribute, ExtendedWeaponAttribute, NegativeAttribute, SlayerName, String, TalismanSlayerName, TalismanSkill, TalismanRemoval, Int, } public object Attribute { get; set; } public int Label { get; set; } public int PropLabel { get; set; } public int Value { get; set; } public Category Category { get; set; } public SearchDetail(object o, int label, int proplabel, int value, Category category) { Attribute = o; Label = label; PropLabel = proplabel; Value = value; Category = category; } public SearchDetail(GenericReader reader) { int version = reader.ReadInt(); // version if (version > 0) { PropLabel = reader.ReadInt(); } ReadAttribute(reader); Label = reader.ReadInt(); Value = reader.ReadInt(); Category = (Category)reader.ReadInt(); } public void Serialize(GenericWriter writer) { writer.Write(1); writer.Write(PropLabel); WriteAttribute(writer); writer.Write(Label); writer.Write(Value); writer.Write((int)Category); } private void WriteAttribute(GenericWriter writer) { int attrID = GetAttributeID(Attribute); writer.Write(attrID); switch (attrID) { case 0: break; case 1: writer.Write((int)(AosAttribute)Attribute); break; case 2: writer.Write((int)(AosArmorAttribute)Attribute); break; case 3: writer.Write((int)(AosWeaponAttribute)Attribute); break; case 4: writer.Write((int)(AosElementAttribute)Attribute); break; case 5: writer.Write((int)(SkillName)Attribute); break; case 6: writer.Write((int)(SAAbsorptionAttribute)Attribute); break; case 7: writer.Write((int)(ExtendedWeaponAttribute)Attribute); break; case 8: writer.Write((int)(NegativeAttribute)Attribute); break; case 9: writer.Write((int)(SlayerName)Attribute); break; case 10: writer.Write((string)Attribute); break; case 11: writer.Write((int)(TalismanSlayerName)Attribute); break; case 12: writer.Write((int)(TalismanSkill)Attribute); break; case 13: writer.Write((int)(TalismanRemoval)Attribute); break; case 14: writer.Write((int)Attribute); break; } } private void ReadAttribute(GenericReader reader) { switch (reader.ReadInt()) { case 0: break; case 1: Attribute = (AosAttribute)reader.ReadInt(); break; case 2: Attribute = (AosArmorAttribute)reader.ReadInt(); break; case 3: Attribute = (AosWeaponAttribute)reader.ReadInt(); break; case 4: Attribute = (AosElementAttribute)reader.ReadInt(); break; case 5: Attribute = (SkillName)reader.ReadInt(); break; case 6: Attribute = (SAAbsorptionAttribute)reader.ReadInt(); break; case 7: Attribute = (ExtendedWeaponAttribute)reader.ReadInt(); break; case 8: Attribute = (NegativeAttribute)reader.ReadInt(); break; case 9: Attribute = (SlayerName)reader.ReadInt(); break; case 10: Attribute = reader.ReadString(); break; case 11: Attribute = (TalismanSlayerName)reader.ReadInt(); break; case 12: Attribute = (TalismanSkill)reader.ReadInt(); break; case 13: Attribute = (TalismanRemoval)reader.ReadInt(); break; case 14: Attribute = reader.ReadInt(); break; } } public static int GetAttributeID(object o) { if (o is AosAttribute) return (int)AttributeID.AosAttribute; if (o is AosArmorAttribute) return (int)AttributeID.AosArmorAttribute; if (o is AosWeaponAttribute) return (int)AttributeID.AosWeaponAttribute; if (o is AosElementAttribute) return (int)AttributeID.AosElementAttribute; if (o is SkillName) return (int)AttributeID.SkillName; if (o is SAAbsorptionAttribute) return (int)AttributeID.SAAbosorptionAttribute; if (o is ExtendedWeaponAttribute) return (int)AttributeID.ExtendedWeaponAttribute; if (o is NegativeAttribute) return (int)AttributeID.NegativeAttribute; if (o is SlayerName) return (int)AttributeID.SlayerName; if (o is TalismanSlayerName) return (int)AttributeID.TalismanSlayerName; if (o is string) return (int)AttributeID.String; if (o is TalismanSkill) return (int)AttributeID.TalismanSkill; if (o is TalismanRemoval) return (int)AttributeID.TalismanRemoval; if (o is int) return (int)AttributeID.Int; return (int)AttributeID.None; } } public class SearchVendors : ContextMenuEntry { public PlayerMobile Player { get; set; } public SearchVendors(PlayerMobile pm) : base(1154679, -1) { Player = pm; Enabled = VendorSearch.CanSearch(pm); } public override void OnClick() { if (VendorSearch.CanSearch(Player)) { BaseGump.SendGump(new VendorSearchGump(Player)); } } } public class SearchItem { public PlayerVendor Vendor { get; set; } public AuctionSafe AuctionSafe { get; set; } public Item Item { get; set; } public int Price { get; set; } public bool IsChild { get; set; } public bool IsAuction { get; set; } public SearchItem(PlayerVendor vendor, Item item, int price, bool isChild) { Vendor = vendor; Item = item; Price = price; IsChild = isChild; IsAuction = false; } public SearchItem(AuctionSafe auctionsafe, Item item, int price, bool isChild) { AuctionSafe = auctionsafe; Item = item; Price = price; IsChild = isChild; IsAuction = true; } } }